]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'rio.b19' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/bird
authorLinus Torvalds <torvalds@g5.osdl.org>
Tue, 20 Jun 2006 22:38:12 +0000 (15:38 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 20 Jun 2006 22:38:12 +0000 (15:38 -0700)
* 'rio.b19' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/bird:
  [PATCH] missing readb/readw in rio
  [PATCH] copy_to_user() from iomem is a bad thing
  [PATCH] forgotten swap of copyout() arguments
  [PATCH] handling rio MEMDUMP
  [PATCH] fix rio_copy_to_card() for OLDPCI case
  [PATCH] uses of ->Copy() in rioroute are bogus
  [PATCH] bogus order of copy_from_user() arguments
  [PATCH] rio ->Copy() expects the sourse as first argument
  [PATCH] trivial annotations in rio

2004 files changed:
Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen [new file with mode: 0644]
Documentation/arm/Sharp-LH/LCDPanels [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
Documentation/filesystems/inotify.txt
Documentation/infiniband/ipoib.txt
Documentation/kernel-parameters.txt
Documentation/memory-barriers.txt
Documentation/networking/README.ipw2200
Documentation/networking/bonding.txt
Documentation/networking/ip-sysctl.txt
Documentation/networking/netdevices.txt
Documentation/serial/driver
MAINTAINERS
Makefile
arch/alpha/Kconfig
arch/alpha/kernel/alpha_ksyms.c
arch/alpha/kernel/process.c
arch/alpha/kernel/smp.c
arch/alpha/kernel/sys_titan.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/compressed/head.S
arch/arm/configs/lpd7a400_defconfig
arch/arm/configs/lpd7a404_defconfig
arch/arm/configs/pnx4008_defconfig [new file with mode: 0644]
arch/arm/kernel/entry-common.S
arch/arm/kernel/irq.c
arch/arm/kernel/time.c
arch/arm/mach-ep93xx/ts72xx.c
arch/arm/mach-imx/irq.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-ixp23xx/core.c
arch/arm/mach-ixp4xx/Kconfig
arch/arm/mach-lh7a40x/Kconfig
arch/arm/mach-lh7a40x/Makefile
arch/arm/mach-lh7a40x/arch-lpd7a40x.c
arch/arm/mach-lh7a40x/clcd.c [new file with mode: 0644]
arch/arm/mach-lh7a40x/clocks.c [new file with mode: 0644]
arch/arm/mach-lh7a40x/common.h
arch/arm/mach-lh7a40x/irq-lh7a404.c
arch/arm/mach-lh7a40x/lcd-panel.h [new file with mode: 0644]
arch/arm/mach-lh7a40x/ssp-cpld.c [new file with mode: 0644]
arch/arm/mach-lh7a40x/time.c
arch/arm/mach-pnx4008/Makefile [new file with mode: 0644]
arch/arm/mach-pnx4008/Makefile.boot [new file with mode: 0644]
arch/arm/mach-pnx4008/clock.c [new file with mode: 0644]
arch/arm/mach-pnx4008/clock.h [new file with mode: 0644]
arch/arm/mach-pnx4008/core.c [new file with mode: 0644]
arch/arm/mach-pnx4008/dma.c [new file with mode: 0644]
arch/arm/mach-pnx4008/gpio.c [new file with mode: 0644]
arch/arm/mach-pnx4008/irq.c [new file with mode: 0644]
arch/arm/mach-pnx4008/pm.c [new file with mode: 0644]
arch/arm/mach-pnx4008/serial.c [new file with mode: 0644]
arch/arm/mach-pnx4008/sleep.S [new file with mode: 0644]
arch/arm/mach-pnx4008/time.c [new file with mode: 0644]
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-s3c2410/Kconfig
arch/arm/mach-s3c2410/Makefile
arch/arm/mach-s3c2410/clock.c
arch/arm/mach-s3c2410/common-smdk.c
arch/arm/mach-s3c2410/cpu.c
arch/arm/mach-s3c2410/cpu.h
arch/arm/mach-s3c2410/devs.c
arch/arm/mach-s3c2410/devs.h
arch/arm/mach-s3c2410/mach-anubis.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mach-s3c2410/mach-nexcoder.c
arch/arm/mach-s3c2410/mach-osiris.c
arch/arm/mach-s3c2410/mach-otom.c
arch/arm/mach-s3c2410/mach-smdk2410.c
arch/arm/mach-s3c2410/mach-smdk2440.c
arch/arm/mach-s3c2410/mach-vr1000.c
arch/arm/mach-s3c2410/pm.c
arch/arm/mach-s3c2410/s3c2410.c
arch/arm/mach-s3c2410/s3c2440-irq.c
arch/arm/mach-s3c2410/s3c2440.c
arch/arm/mach-s3c2410/s3c2442-clock.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2442.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c2442.h [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c244x-irq.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c244x.c [new file with mode: 0644]
arch/arm/mach-s3c2410/s3c244x.h [new file with mode: 0644]
arch/arm/mach-s3c2410/sleep.S
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-versatile/core.c
arch/arm/mm/Kconfig
arch/arm/mm/mm-armv.c
arch/arm/mm/proc-xsc3.S
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/acpi/earlyquirk.c
arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/longrun.c
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
arch/i386/kernel/setup.c
arch/i386/kernel/syscall_table.S
arch/i386/mach-generic/probe.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/au1000/common/au1xxx_irqmap.c
arch/mips/au1000/common/irq.c
arch/mips/au1000/common/pci.c
arch/mips/au1000/common/prom.c
arch/mips/au1000/common/setup.c
arch/mips/au1000/common/sleeper.S
arch/mips/au1000/common/time.c
arch/mips/au1000/csb250/irqmap.c
arch/mips/au1000/db1x00/irqmap.c
arch/mips/au1000/hydrogen3/irqmap.c
arch/mips/au1000/mtx-1/irqmap.c
arch/mips/au1000/pb1000/irqmap.c
arch/mips/au1000/pb1100/irqmap.c
arch/mips/au1000/pb1200/irqmap.c
arch/mips/au1000/pb1500/irqmap.c
arch/mips/au1000/pb1550/irqmap.c
arch/mips/au1000/xxs1500/irqmap.c
arch/mips/basler/excite/Makefile [new file with mode: 0644]
arch/mips/basler/excite/excite_dbg_io.c [new file with mode: 0644]
arch/mips/basler/excite/excite_device.c [new file with mode: 0644]
arch/mips/basler/excite/excite_flashtest.c [new file with mode: 0644]
arch/mips/basler/excite/excite_fpga.h [new file with mode: 0644]
arch/mips/basler/excite/excite_iodev.c [new file with mode: 0644]
arch/mips/basler/excite/excite_iodev.h [new file with mode: 0644]
arch/mips/basler/excite/excite_irq.c [new file with mode: 0644]
arch/mips/basler/excite/excite_procfs.c [new file with mode: 0644]
arch/mips/basler/excite/excite_prom.c [new file with mode: 0644]
arch/mips/basler/excite/excite_setup.c [new file with mode: 0644]
arch/mips/cobalt/console.c
arch/mips/cobalt/setup.c
arch/mips/configs/atlas_defconfig
arch/mips/configs/bigsur_defconfig
arch/mips/configs/capcella_defconfig
arch/mips/configs/cobalt_defconfig
arch/mips/configs/db1000_defconfig
arch/mips/configs/db1100_defconfig
arch/mips/configs/db1200_defconfig
arch/mips/configs/db1500_defconfig
arch/mips/configs/db1550_defconfig
arch/mips/configs/ddb5477_defconfig
arch/mips/configs/decstation_defconfig
arch/mips/configs/e55_defconfig
arch/mips/configs/emma2rh_defconfig [new file with mode: 0644]
arch/mips/configs/ev64120_defconfig
arch/mips/configs/ev96100_defconfig
arch/mips/configs/excite_defconfig [new file with mode: 0644]
arch/mips/configs/ip22_defconfig
arch/mips/configs/ip27_defconfig
arch/mips/configs/ip32_defconfig
arch/mips/configs/it8172_defconfig
arch/mips/configs/ivr_defconfig
arch/mips/configs/jaguar-atx_defconfig
arch/mips/configs/jmr3927_defconfig
arch/mips/configs/lasat200_defconfig
arch/mips/configs/malta_defconfig
arch/mips/configs/mipssim_defconfig
arch/mips/configs/mpc30x_defconfig
arch/mips/configs/ocelot_3_defconfig
arch/mips/configs/ocelot_c_defconfig
arch/mips/configs/ocelot_defconfig
arch/mips/configs/ocelot_g_defconfig
arch/mips/configs/pb1100_defconfig
arch/mips/configs/pb1500_defconfig
arch/mips/configs/pb1550_defconfig
arch/mips/configs/pnx8550-jbs_defconfig
arch/mips/configs/pnx8550-v2pci_defconfig
arch/mips/configs/qemu_defconfig
arch/mips/configs/rbhma4500_defconfig
arch/mips/configs/rm200_defconfig
arch/mips/configs/sb1250-swarm_defconfig
arch/mips/configs/sead_defconfig
arch/mips/configs/tb0226_defconfig
arch/mips/configs/tb0229_defconfig
arch/mips/configs/tb0287_defconfig
arch/mips/configs/workpad_defconfig
arch/mips/configs/wrppmc_defconfig [moved from arch/mips/configs/ddb5476_defconfig with 68% similarity]
arch/mips/configs/yosemite_defconfig
arch/mips/ddb5xxx/common/prom.c
arch/mips/ddb5xxx/ddb5074/Makefile [deleted file]
arch/mips/ddb5xxx/ddb5074/irq.c [deleted file]
arch/mips/ddb5xxx/ddb5074/nile4_pic.c [deleted file]
arch/mips/ddb5xxx/ddb5074/setup.c [deleted file]
arch/mips/ddb5xxx/ddb5476/Makefile [deleted file]
arch/mips/ddb5xxx/ddb5476/dbg_io.c [deleted file]
arch/mips/ddb5xxx/ddb5476/irq.c [deleted file]
arch/mips/ddb5xxx/ddb5476/nile4_pic.c [deleted file]
arch/mips/ddb5xxx/ddb5476/setup.c [deleted file]
arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c [deleted file]
arch/mips/ddb5xxx/ddb5477/kgdb_io.c
arch/mips/ddb5xxx/ddb5477/setup.c
arch/mips/dec/setup.c
arch/mips/dec/time.c
arch/mips/defconfig
arch/mips/emma2rh/common/Makefile [new file with mode: 0644]
arch/mips/emma2rh/common/irq.c [new file with mode: 0644]
arch/mips/emma2rh/common/irq_emma2rh.c [new file with mode: 0644]
arch/mips/emma2rh/common/prom.c [new file with mode: 0644]
arch/mips/emma2rh/markeins/Makefile [new file with mode: 0644]
arch/mips/emma2rh/markeins/irq.c [new file with mode: 0644]
arch/mips/emma2rh/markeins/irq_markeins.c [new file with mode: 0644]
arch/mips/emma2rh/markeins/led.c [new file with mode: 0644]
arch/mips/emma2rh/markeins/platform.c [new file with mode: 0644]
arch/mips/emma2rh/markeins/setup.c [new file with mode: 0644]
arch/mips/galileo-boards/ev96100/setup.c
arch/mips/gt64120/ev64120/serialGT.c
arch/mips/gt64120/ev64120/setup.c
arch/mips/gt64120/momenco_ocelot/dbg_io.c
arch/mips/gt64120/momenco_ocelot/setup.c
arch/mips/gt64120/wrppmc/Makefile [new file with mode: 0644]
arch/mips/gt64120/wrppmc/int-handler.S [new file with mode: 0644]
arch/mips/gt64120/wrppmc/irq.c [new file with mode: 0644]
arch/mips/gt64120/wrppmc/pci.c [new file with mode: 0644]
arch/mips/gt64120/wrppmc/reset.c [new file with mode: 0644]
arch/mips/gt64120/wrppmc/setup.c [new file with mode: 0644]
arch/mips/gt64120/wrppmc/time.c [new file with mode: 0644]
arch/mips/ite-boards/generic/dbg_io.c
arch/mips/ite-boards/generic/it8172_setup.c
arch/mips/jazz/setup.c
arch/mips/jmr3927/rbhma3100/setup.c
arch/mips/kernel/Makefile
arch/mips/kernel/apm.c [new file with mode: 0644]
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/branch.c
arch/mips/kernel/cpu-bugs64.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/entry.S
arch/mips/kernel/gdb-low.S
arch/mips/kernel/i8259.c
arch/mips/kernel/irixsig.c
arch/mips/kernel/module.c
arch/mips/kernel/proc.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/ptrace32.c
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/signal-common.h
arch/mips/kernel/smp.c
arch/mips/kernel/syscall.c
arch/mips/kernel/traps.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/lasat/setup.c
arch/mips/lib/Makefile
arch/mips/lib/ashldi3.c [new file with mode: 0644]
arch/mips/lib/ashrdi3.c [new file with mode: 0644]
arch/mips/lib/libgcc.h [new file with mode: 0644]
arch/mips/lib/lshrdi3.c [new file with mode: 0644]
arch/mips/math-emu/cp1emu.c
arch/mips/math-emu/dp_fint.c
arch/mips/math-emu/dp_flong.c
arch/mips/math-emu/ieee754.h
arch/mips/math-emu/kernel_linkage.c
arch/mips/math-emu/sp_fint.c
arch/mips/math-emu/sp_flong.c
arch/mips/mips-boards/atlas/atlas_setup.c
arch/mips/mips-boards/generic/memory.c
arch/mips/mips-boards/malta/malta_setup.c
arch/mips/mips-boards/malta/malta_smp.c
arch/mips/mips-boards/sead/sead_setup.c
arch/mips/mips-boards/sim/sim_setup.c
arch/mips/mips-boards/sim/sim_smp.c
arch/mips/mm/c-r4k.c
arch/mips/mm/init.c
arch/mips/mm/pg-r4k.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c
arch/mips/momentum/jaguar_atx/dbg_io.c
arch/mips/momentum/jaguar_atx/setup.c
arch/mips/momentum/ocelot_3/setup.c
arch/mips/momentum/ocelot_c/dbg_io.c
arch/mips/momentum/ocelot_c/setup.c
arch/mips/momentum/ocelot_g/dbg_io.c
arch/mips/momentum/ocelot_g/setup.c
arch/mips/oprofile/common.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/oprofile/op_model_rm9000.c
arch/mips/pci/Makefile
arch/mips/pci/fixup-ddb5074.c [deleted file]
arch/mips/pci/fixup-emma2rh.c [new file with mode: 0644]
arch/mips/pci/fixup-excite.c [new file with mode: 0644]
arch/mips/pci/fixup-wrppmc.c [new file with mode: 0644]
arch/mips/pci/ops-bridge.c [new file with mode: 0644]
arch/mips/pci/ops-ddb5074.c [deleted file]
arch/mips/pci/ops-ddb5476.c [deleted file]
arch/mips/pci/ops-emma2rh.c [new file with mode: 0644]
arch/mips/pci/ops-it8172.c
arch/mips/pci/ops-sni.c
arch/mips/pci/ops-titan.c
arch/mips/pci/pci-ddb5074.c [deleted file]
arch/mips/pci/pci-ddb5476.c [deleted file]
arch/mips/pci/pci-ddb5477.c
arch/mips/pci/pci-emma2rh.c [new file with mode: 0644]
arch/mips/pci/pci-excite.c [new file with mode: 0644]
arch/mips/pci/pci-ip27.c
arch/mips/pci/pci-jmr3927.c
arch/mips/pci/pci-ocelot.c
arch/mips/pci/pci-yosemite.c
arch/mips/pci/pci.c
arch/mips/philips/pnx8550/common/pci.c
arch/mips/philips/pnx8550/common/setup.c
arch/mips/pmc-sierra/yosemite/setup.c
arch/mips/qemu/Makefile
arch/mips/qemu/q-reset.c [new file with mode: 0644]
arch/mips/qemu/q-setup.c
arch/mips/sgi-ip22/ip22-setup.c
arch/mips/sgi-ip27/Kconfig
arch/mips/sgi-ip27/ip27-init.c
arch/mips/sgi-ip27/ip27-irq.c
arch/mips/sgi-ip27/ip27-timer.c
arch/mips/sgi-ip32/ip32-irq.c
arch/mips/sgi-ip32/ip32-setup.c
arch/mips/sibyte/bcm1480/time.c
arch/mips/sibyte/sb1250/irq.c
arch/mips/sibyte/swarm/setup.c
arch/mips/sni/Makefile
arch/mips/sni/setup.c
arch/mips/sni/sniprom.c [new file with mode: 0644]
arch/mips/tx4927/common/tx4927_setup.c
arch/mips/tx4938/common/setup.c
arch/mips/tx4938/toshiba_rbtx4938/setup.c
arch/mips/vr41xx/Kconfig
arch/mips/vr41xx/common/init.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/mm/hash_native_64.c
arch/powerpc/platforms/cell/setup.c
arch/powerpc/platforms/powermac/low_i2c.c
arch/powerpc/platforms/powermac/pfunc_core.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/pseries/setup.c
arch/ppc/kernel/asm-offsets.c
arch/ppc/platforms/mpc8272ads_setup.c
arch/ppc/syslib/pq2_devices.c
arch/ppc/syslib/pq2_sys.c
arch/s390/kernel/time.c
arch/sparc/kernel/smp.c
arch/sparc64/kernel/head.S
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/kernel/setup.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/kernel/traps.c
arch/sparc64/lib/checksum.S
arch/sparc64/lib/csum_copy.S
arch/um/Makefile-i386
arch/um/include/kern_util.h
arch/um/kernel/physmem.c
arch/um/kernel/time_kern.c
arch/um/os-Linux/main.c
arch/um/os-Linux/time.c
arch/um/sys-i386/syscalls.c
arch/um/sys-x86_64/signal.c
arch/um/sys-x86_64/syscalls.c
arch/x86_64/ia32/ia32_binfmt.c
arch/x86_64/kernel/e820.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/pci-dma.c
arch/x86_64/kernel/pci-gart.c
arch/x86_64/kernel/pmtimer.c
arch/x86_64/kernel/setup.c
arch/x86_64/mm/srat.c
block/as-iosched.c
block/cfq-iosched.c
block/deadline-iosched.c
block/elevator.c
block/noop-iosched.c
drivers/Kconfig
drivers/Makefile
drivers/acpi/pci_link.c
drivers/acpi/processor_perflib.c
drivers/base/power/suspend.c
drivers/block/aoe/aoenet.c
drivers/cdrom/cdrom.c
drivers/char/Makefile
drivers/char/agp/Kconfig
drivers/char/agp/alpha-agp.c
drivers/char/agp/amd64-agp.c
drivers/char/agp/generic.c
drivers/char/agp/intel-agp.c
drivers/char/agp/uninorth-agp.c
drivers/char/agp/via-agp.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/n_tty.c
drivers/char/pcmcia/cm4000_cs.c
drivers/char/tpm/tpm_bios.c
drivers/char/tpm/tpm_tis.c
drivers/char/vt.c
drivers/connector/cn_queue.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/freq_table.c
drivers/dma/Kconfig [new file with mode: 0644]
drivers/dma/Makefile [new file with mode: 0644]
drivers/dma/dmaengine.c [new file with mode: 0644]
drivers/dma/ioatdma.c [new file with mode: 0644]
drivers/dma/ioatdma.h [new file with mode: 0644]
drivers/dma/ioatdma_hw.h [new file with mode: 0644]
drivers/dma/ioatdma_io.h [new file with mode: 0644]
drivers/dma/ioatdma_registers.h [new file with mode: 0644]
drivers/dma/iovlock.c [new file with mode: 0644]
drivers/i2c/busses/scx200_acb.c
drivers/ide/pci/sgiioc4.c
drivers/ieee1394/sbp2.c
drivers/infiniband/Kconfig
drivers/infiniband/core/Makefile
drivers/infiniband/core/addr.c [new file with mode: 0644]
drivers/infiniband/core/cache.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c [new file with mode: 0644]
drivers/infiniband/core/fmr_pool.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/mad_priv.h
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/ucm.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/uverbs_marshall.c [new file with mode: 0644]
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/ipath/ipath_mad.c
drivers/infiniband/hw/mthca/mthca_cmd.c
drivers/infiniband/hw/mthca/mthca_cq.c
drivers/infiniband/hw/mthca/mthca_eq.c
drivers/infiniband/hw/mthca/mthca_mad.c
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/mthca/mthca_provider.h
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/hw/mthca/mthca_reset.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/ipoib/ipoib_verbs.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h
drivers/input/joystick/sidewinder.c
drivers/input/keyboard/corgikbd.c
drivers/input/keyboard/spitzkbd.c
drivers/input/misc/wistron_btns.c
drivers/input/mouse/alps.c
drivers/input/mouse/lifebook.c
drivers/input/mouse/logips2pp.c
drivers/input/touchscreen/ads7846.c
drivers/md/md.c
drivers/media/dvb/dvb-core/dvb_net.c
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptspi.c
drivers/message/i2o/exec-osm.c
drivers/message/i2o/iop.c
drivers/mmc/Kconfig
drivers/mmc/sdhci.c
drivers/mtd/Kconfig
drivers/mtd/chips/Kconfig
drivers/mtd/chips/Makefile
drivers/mtd/chips/amd_flash.c
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/cfi_cmdset_0020.c
drivers/mtd/chips/cfi_probe.c
drivers/mtd/chips/gen_probe.c
drivers/mtd/chips/map_ram.c
drivers/mtd/chips/map_rom.c
drivers/mtd/chips/sharp.c
drivers/mtd/devices/Kconfig
drivers/mtd/devices/Makefile
drivers/mtd/devices/block2mtd.c
drivers/mtd/devices/doc2000.c
drivers/mtd/devices/doc2001.c
drivers/mtd/devices/doc2001plus.c
drivers/mtd/devices/docprobe.c
drivers/mtd/devices/lart.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/ms02-nv.c
drivers/mtd/devices/mtdram.c
drivers/mtd/devices/phram.c
drivers/mtd/devices/slram.c
drivers/mtd/inftlcore.c
drivers/mtd/inftlmount.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/cfi_flagadm.c
drivers/mtd/maps/dbox2-flash.c
drivers/mtd/maps/mtx-1_flash.c
drivers/mtd/maps/nettel.c
drivers/mtd/maps/pcmciamtd.c
drivers/mtd/maps/physmap.c
drivers/mtd/mtdblock.c
drivers/mtd/mtdblock_ro.c
drivers/mtd/mtdchar.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/ams-delta.c [new file with mode: 0644]
drivers/mtd/nand/au1550nd.c
drivers/mtd/nand/autcpu12.c
drivers/mtd/nand/cs553x_nand.c [new file with mode: 0644]
drivers/mtd/nand/diskonchip.c
drivers/mtd/nand/edb7312.c
drivers/mtd/nand/h1910.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_bbt.c
drivers/mtd/nand/nand_ecc.c
drivers/mtd/nand/nand_ids.c
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/ndfc.c [new file with mode: 0644]
drivers/mtd/nand/ppchameleonevb.c
drivers/mtd/nand/rtc_from4.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sharpsl.c
drivers/mtd/nand/spia.c
drivers/mtd/nand/toto.c
drivers/mtd/nand/ts7250.c [new file with mode: 0644]
drivers/mtd/nftlcore.c
drivers/mtd/nftlmount.c
drivers/mtd/onenand/Kconfig
drivers/mtd/onenand/onenand_base.c
drivers/mtd/onenand/onenand_bbt.c
drivers/mtd/redboot.c
drivers/mtd/rfd_ftl.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/8139cp.c
drivers/net/8139too.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/au1000_eth.c
drivers/net/au1000_eth.h
drivers/net/bnx2.c
drivers/net/bnx2.h
drivers/net/bnx2_fw.h
drivers/net/bonding/bond_main.c
drivers/net/cassini.c
drivers/net/e100.c
drivers/net/e1000/Makefile
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000/e1000_hw.c
drivers/net/e1000/e1000_hw.h
drivers/net/e1000/e1000_main.c
drivers/net/e1000/e1000_osdep.h
drivers/net/e1000/e1000_param.c
drivers/net/epic100.c
drivers/net/forcedeth.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/mkiss.c
drivers/net/hp-plus.c
drivers/net/hp.c
drivers/net/ibmlana.c
drivers/net/ibmlana.h
drivers/net/ibmveth.c
drivers/net/ibmveth.h
drivers/net/ifb.c
drivers/net/irda/Kconfig
drivers/net/irda/Makefile
drivers/net/irda/ali-ircc.c
drivers/net/irda/irda-usb.c
drivers/net/irda/irda-usb.h
drivers/net/irda/mcs7780.c [new file with mode: 0644]
drivers/net/irda/mcs7780.h [new file with mode: 0644]
drivers/net/irda/stir4200.c
drivers/net/irda/vlsi_ir.c
drivers/net/ixgb/Makefile
drivers/net/ixgb/ixgb.h
drivers/net/ixgb/ixgb_ee.c
drivers/net/ixgb/ixgb_ee.h
drivers/net/ixgb/ixgb_ethtool.c
drivers/net/ixgb/ixgb_hw.c
drivers/net/ixgb/ixgb_hw.h
drivers/net/ixgb/ixgb_ids.h
drivers/net/ixgb/ixgb_main.c
drivers/net/ixgb/ixgb_osdep.h
drivers/net/ixgb/ixgb_param.c
drivers/net/mv643xx_eth.c
drivers/net/myri10ge/Makefile [new file with mode: 0644]
drivers/net/myri10ge/myri10ge.c [new file with mode: 0644]
drivers/net/myri10ge/myri10ge_mcp.h [new file with mode: 0644]
drivers/net/myri10ge/myri10ge_mcp_gen_header.h [new file with mode: 0644]
drivers/net/natsemi.c
drivers/net/ne.c
drivers/net/ne2.c
drivers/net/netconsole.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcnet32.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/smsc.c [new file with mode: 0644]
drivers/net/ppp_generic.c
drivers/net/pppoe.c
drivers/net/r8169.c
drivers/net/s2io-regs.h
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/sis900.c
drivers/net/sis900.h
drivers/net/skge.c
drivers/net/skge.h
drivers/net/sky2.c
drivers/net/smc-ultra.c
drivers/net/smc-ultra32.c
drivers/net/smc911x.c [new file with mode: 0644]
drivers/net/smc911x.h [new file with mode: 0644]
drivers/net/smc9194.c
drivers/net/smc91x.h
drivers/net/sungem_phy.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/tulip/de2104x.c
drivers/net/tulip/de4x5.c
drivers/net/tulip/de4x5.h
drivers/net/tulip/dmfe.c
drivers/net/tulip/eeprom.c
drivers/net/tulip/interrupt.c
drivers/net/tulip/media.c
drivers/net/tulip/tulip.h
drivers/net/tulip/tulip_core.c
drivers/net/tulip/uli526x.c
drivers/net/tulip/winbond-840.c
drivers/net/tulip/xircom_cb.c
drivers/net/via-velocity.c
drivers/net/via-velocity.h
drivers/net/wan/pci200syn.c
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/airo.c
drivers/net/wireless/arlan-main.c
drivers/net/wireless/bcm43xx/bcm43xx.h
drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
drivers/net/wireless/bcm43xx/bcm43xx_dma.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/hermes.c
drivers/net/wireless/hermes.h
drivers/net/wireless/hostap/hostap_80211_tx.c
drivers/net/wireless/hostap/hostap_ap.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_main.c
drivers/net/wireless/ipw2200.c
drivers/net/wireless/ipw2200.h
drivers/net/wireless/orinoco.c
drivers/net/wireless/orinoco.h
drivers/net/wireless/orinoco_cs.c
drivers/net/wireless/orinoco_nortel.c
drivers/net/wireless/orinoco_pci.c
drivers/net/wireless/orinoco_pci.h [new file with mode: 0644]
drivers/net/wireless/orinoco_plx.c
drivers/net/wireless/orinoco_tmd.c
drivers/net/wireless/spectrum_cs.c
drivers/net/wireless/wavelan.c
drivers/net/wireless/zd1201.c [moved from drivers/usb/net/zd1201.c with 97% similarity]
drivers/net/wireless/zd1201.h [moved from drivers/usb/net/zd1201.h with 100% similarity]
drivers/parport/Kconfig
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pcmcia/ds.c
drivers/rtc/rtc-m48t86.c
drivers/s390/cio/css.h
drivers/s390/cio/device_fsm.c
drivers/s390/crypto/z90crypt.h
drivers/s390/net/Makefile
drivers/s390/net/ctcmain.c
drivers/s390/net/ctcmain.h
drivers/s390/net/ctctty.c [deleted file]
drivers/s390/net/ctctty.h [deleted file]
drivers/s390/net/cu3088.c
drivers/s390/net/iucv.c
drivers/s390/net/iucv.h
drivers/s390/net/lcs.c
drivers/s390/net/lcs.h
drivers/s390/net/netiucv.c
drivers/s390/net/qeth.h
drivers/s390/net/qeth_eddp.c
drivers/s390/net/qeth_fs.h
drivers/s390/net/qeth_main.c
drivers/s390/net/qeth_mpc.h
drivers/s390/net/qeth_proc.c
drivers/s390/net/qeth_sys.c
drivers/s390/net/qeth_tso.h
drivers/scsi/libata-core.c
drivers/scsi/ppa.c
drivers/scsi/sata_mv.c
drivers/scsi/sata_sil24.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_sas.c
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/serial/cpm_uart/cpm_uart_cpm2.c
drivers/serial/s3c2410.c
drivers/serial/serial_lh7a40x.c
drivers/spi/spi_s3c24xx.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/net/Kconfig
drivers/usb/net/Makefile
drivers/video/Kconfig
drivers/video/au1100fb.c
drivers/video/console/fbcon.c
drivers/video/intelfb/intelfb.h
drivers/video/intelfb/intelfbdrv.c
drivers/video/intelfb/intelfbhw.c
drivers/video/intelfb/intelfbhw.h
drivers/video/maxinefb.c
fs/Kconfig
fs/Makefile
fs/affs/namei.c
fs/bio.c
fs/cifs/CHANGES
fs/cifs/cifsfs.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/file.c
fs/debugfs/inode.c
fs/eventpoll.c
fs/exec.c
fs/ext3/dir.c
fs/ext3/resize.c
fs/inotify.c
fs/inotify_user.c [new file with mode: 0644]
fs/jffs/intrep.c
fs/jffs2/Makefile
fs/jffs2/README.Locking
fs/jffs2/acl.c [new file with mode: 0644]
fs/jffs2/acl.h [new file with mode: 0644]
fs/jffs2/build.c
fs/jffs2/compr.c
fs/jffs2/compr.h
fs/jffs2/debug.c
fs/jffs2/debug.h
fs/jffs2/dir.c
fs/jffs2/erase.c
fs/jffs2/file.c
fs/jffs2/fs.c
fs/jffs2/gc.c
fs/jffs2/histo.h [deleted file]
fs/jffs2/jffs2_fs_i.h [moved from include/linux/jffs2_fs_i.h with 91% similarity]
fs/jffs2/jffs2_fs_sb.h [moved from include/linux/jffs2_fs_sb.h with 92% similarity]
fs/jffs2/malloc.c
fs/jffs2/nodelist.c
fs/jffs2/nodelist.h
fs/jffs2/nodemgmt.c
fs/jffs2/os-linux.h
fs/jffs2/readinode.c
fs/jffs2/scan.c
fs/jffs2/security.c [new file with mode: 0644]
fs/jffs2/summary.c
fs/jffs2/summary.h
fs/jffs2/super.c
fs/jffs2/symlink.c
fs/jffs2/wbuf.c
fs/jffs2/write.c
fs/jffs2/xattr.c [new file with mode: 0644]
fs/jffs2/xattr.h [new file with mode: 0644]
fs/jffs2/xattr_trusted.c [new file with mode: 0644]
fs/jffs2/xattr_user.c [new file with mode: 0644]
fs/locks.c
fs/namei.c
fs/open.c
fs/proc/base.c
fs/xattr.c
include/acpi/platform/aclinux.h
include/acpi/processor.h
include/asm-alpha/bitops.h
include/asm-alpha/cache.h
include/asm-alpha/cacheflush.h
include/asm-alpha/core_cia.h
include/asm-alpha/core_t2.h
include/asm-alpha/dma-mapping.h
include/asm-alpha/dma.h
include/asm-alpha/floppy.h
include/asm-alpha/hardirq.h
include/asm-alpha/hw_irq.h
include/asm-alpha/ide.h
include/asm-alpha/io.h
include/asm-alpha/irq.h
include/asm-alpha/kmap_types.h
include/asm-alpha/machvec.h
include/asm-alpha/mmu_context.h
include/asm-alpha/mmzone.h
include/asm-alpha/page.h
include/asm-alpha/param.h
include/asm-alpha/pgalloc.h
include/asm-alpha/pgtable.h
include/asm-alpha/serial.h
include/asm-alpha/smp.h
include/asm-alpha/spinlock.h
include/asm-alpha/system.h
include/asm-alpha/termbits.h
include/asm-alpha/tlbflush.h
include/asm-alpha/unistd.h
include/asm-arm/apm.h
include/asm-arm/arch-aaec2000/memory.h
include/asm-arm/arch-cl7500/acornfb.h
include/asm-arm/arch-clps711x/hardware.h
include/asm-arm/arch-clps711x/memory.h
include/asm-arm/arch-clps711x/uncompress.h
include/asm-arm/arch-ebsa285/hardware.h
include/asm-arm/arch-ebsa285/memory.h
include/asm-arm/arch-ebsa285/vmalloc.h
include/asm-arm/arch-integrator/smp.h
include/asm-arm/arch-iop3xx/memory.h
include/asm-arm/arch-iop3xx/timex.h
include/asm-arm/arch-iop3xx/uncompress.h
include/asm-arm/arch-ixp23xx/memory.h
include/asm-arm/arch-ixp4xx/dma.h
include/asm-arm/arch-l7200/serial_l7200.h
include/asm-arm/arch-l7200/uncompress.h
include/asm-arm/arch-lh7a40x/clocks.h [new file with mode: 0644]
include/asm-arm/arch-lh7a40x/constants.h
include/asm-arm/arch-lh7a40x/dma.h
include/asm-arm/arch-lh7a40x/entry-macro.S
include/asm-arm/arch-lh7a40x/hardware.h
include/asm-arm/arch-lh7a40x/irqs.h
include/asm-arm/arch-lh7a40x/registers.h
include/asm-arm/arch-lh7a40x/ssp.h [new file with mode: 0644]
include/asm-arm/arch-lh7a40x/uncompress.h
include/asm-arm/arch-omap/board.h
include/asm-arm/arch-omap/hardware.h
include/asm-arm/arch-omap/system.h
include/asm-arm/arch-omap/uncompress.h
include/asm-arm/arch-pnx4008/clock.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/debug-macro.S [new file with mode: 0644]
include/asm-arm/arch-pnx4008/dma.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/entry-macro.S [new file with mode: 0644]
include/asm-arm/arch-pnx4008/gpio.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/hardware.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/io.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/irq.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/irqs.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/memory.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/param.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/platform.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/pm.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/system.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/timex.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/uncompress.h [new file with mode: 0644]
include/asm-arm/arch-pnx4008/vmalloc.h [new file with mode: 0644]
include/asm-arm/arch-pxa/idp.h
include/asm-arm/arch-pxa/irqs.h
include/asm-arm/arch-pxa/ohci.h
include/asm-arm/arch-pxa/pxa-regs.h
include/asm-arm/arch-pxa/timex.h
include/asm-arm/arch-realview/smp.h
include/asm-arm/arch-s3c2410/dma.h
include/asm-arm/arch-s3c2410/map.h
include/asm-arm/arch-s3c2410/regs-clock.h
include/asm-arm/arch-s3c2410/regs-gpio.h
include/asm-arm/arch-s3c2410/uncompress.h
include/asm-arm/arch-sa1100/assabet.h
include/asm-arm/arch-sa1100/cerf.h
include/asm-arm/arch-sa1100/collie.h
include/asm-arm/arch-sa1100/dma.h
include/asm-arm/arch-sa1100/hardware.h
include/asm-arm/arch-sa1100/ide.h
include/asm-arm/arch-sa1100/irqs.h
include/asm-arm/arch-sa1100/memory.h
include/asm-arm/arch-sa1100/system.h
include/asm-arm/atomic.h
include/asm-arm/bug.h
include/asm-arm/cacheflush.h
include/asm-arm/cpu.h
include/asm-arm/dma-mapping.h
include/asm-arm/dma.h
include/asm-arm/elf.h
include/asm-arm/fpstate.h
include/asm-arm/glue.h
include/asm-arm/hardirq.h
include/asm-arm/hardware/dec21285.h
include/asm-arm/hardware/iomd.h
include/asm-arm/leds.h
include/asm-arm/mach/serial_at91rm9200.h
include/asm-arm/mach/serial_sa1100.h
include/asm-arm/mach/time.h
include/asm-arm/memory.h
include/asm-arm/page.h
include/asm-arm/pci.h
include/asm-arm/proc-fns.h
include/asm-arm/ptrace.h
include/asm-arm/smp.h
include/asm-arm/system.h
include/asm-arm/tlbflush.h
include/asm-arm/unistd.h
include/asm-arm26/atomic.h
include/asm-arm26/bug.h
include/asm-arm26/dma.h
include/asm-arm26/hardirq.h
include/asm-arm26/hardware.h
include/asm-arm26/io.h
include/asm-arm26/leds.h
include/asm-arm26/mach-types.h
include/asm-arm26/page.h
include/asm-arm26/pgtable.h
include/asm-arm26/serial.h
include/asm-arm26/smp.h
include/asm-arm26/sysirq.h
include/asm-arm26/system.h
include/asm-arm26/unistd.h
include/asm-cris/arch-v10/io.h
include/asm-cris/arch-v10/page.h
include/asm-cris/arch-v10/system.h
include/asm-cris/arch-v32/io.h
include/asm-cris/arch-v32/irq.h
include/asm-cris/arch-v32/page.h
include/asm-cris/arch-v32/processor.h
include/asm-cris/arch-v32/system.h
include/asm-cris/eshlibld.h
include/asm-cris/etraxgpio.h
include/asm-cris/fasttimer.h
include/asm-cris/page.h
include/asm-cris/pci.h
include/asm-cris/pgtable.h
include/asm-cris/processor.h
include/asm-cris/rtc.h
include/asm-cris/tlbflush.h
include/asm-cris/unistd.h
include/asm-frv/atomic.h
include/asm-frv/bitops.h
include/asm-frv/bug.h
include/asm-frv/cache.h
include/asm-frv/dma.h
include/asm-frv/elf.h
include/asm-frv/fpu.h
include/asm-frv/hardirq.h
include/asm-frv/highmem.h
include/asm-frv/ide.h
include/asm-frv/io.h
include/asm-frv/irq.h
include/asm-frv/mmu_context.h
include/asm-frv/page.h
include/asm-frv/pci.h
include/asm-frv/pgalloc.h
include/asm-frv/pgtable.h
include/asm-frv/processor.h
include/asm-frv/segment.h
include/asm-frv/serial.h
include/asm-frv/smp.h
include/asm-frv/system.h
include/asm-frv/tlbflush.h
include/asm-frv/types.h
include/asm-frv/unaligned.h
include/asm-frv/unistd.h
include/asm-frv/virtconvert.h
include/asm-generic/bug.h
include/asm-generic/dma-mapping.h
include/asm-generic/fcntl.h
include/asm-generic/local.h
include/asm-generic/pgtable.h
include/asm-generic/signal.h
include/asm-generic/tlb.h
include/asm-h8300/bitops.h
include/asm-h8300/dma.h
include/asm-h8300/elf.h
include/asm-h8300/hardirq.h
include/asm-h8300/io.h
include/asm-h8300/keyboard.h
include/asm-h8300/mmu_context.h
include/asm-h8300/page.h
include/asm-h8300/page_offset.h
include/asm-h8300/param.h
include/asm-h8300/pgtable.h
include/asm-h8300/processor.h
include/asm-h8300/semaphore-helper.h
include/asm-h8300/shm.h
include/asm-h8300/system.h
include/asm-h8300/unaligned.h
include/asm-h8300/unistd.h
include/asm-h8300/virtconvert.h
include/asm-i386/apic.h
include/asm-i386/atomic.h
include/asm-i386/bitops.h
include/asm-i386/bug.h
include/asm-i386/bugs.h
include/asm-i386/byteorder.h
include/asm-i386/cache.h
include/asm-i386/dma.h
include/asm-i386/fixmap.h
include/asm-i386/hardirq.h
include/asm-i386/highmem.h
include/asm-i386/hpet.h
include/asm-i386/hw_irq.h
include/asm-i386/ide.h
include/asm-i386/io.h
include/asm-i386/io_apic.h
include/asm-i386/irq.h
include/asm-i386/kmap_types.h
include/asm-i386/mach-summit/mach_apic.h
include/asm-i386/mmu_context.h
include/asm-i386/mtrr.h
include/asm-i386/page.h
include/asm-i386/param.h
include/asm-i386/pci.h
include/asm-i386/pgalloc.h
include/asm-i386/pgtable.h
include/asm-i386/processor.h
include/asm-i386/serial.h
include/asm-i386/smp.h
include/asm-i386/spinlock.h
include/asm-i386/string.h
include/asm-i386/system.h
include/asm-i386/thread_info.h
include/asm-i386/timex.h
include/asm-i386/tlbflush.h
include/asm-i386/types.h
include/asm-i386/uaccess.h
include/asm-i386/unistd.h
include/asm-ia64/asmmacro.h
include/asm-ia64/cache.h
include/asm-ia64/delay.h
include/asm-ia64/dma-mapping.h
include/asm-ia64/dma.h
include/asm-ia64/elf.h
include/asm-ia64/hardirq.h
include/asm-ia64/ia32.h
include/asm-ia64/ide.h
include/asm-ia64/intrinsics.h
include/asm-ia64/kmap_types.h
include/asm-ia64/machvec.h
include/asm-ia64/meminit.h
include/asm-ia64/nodedata.h
include/asm-ia64/numa.h
include/asm-ia64/page.h
include/asm-ia64/param.h
include/asm-ia64/percpu.h
include/asm-ia64/pgalloc.h
include/asm-ia64/pgtable.h
include/asm-ia64/processor.h
include/asm-ia64/ptrace.h
include/asm-ia64/smp.h
include/asm-ia64/sn/simulator.h
include/asm-ia64/sn/sn_cpuid.h
include/asm-ia64/sn/sn_sal.h
include/asm-ia64/sn/xpc.h
include/asm-ia64/string.h
include/asm-ia64/system.h
include/asm-ia64/tlb.h
include/asm-ia64/tlbflush.h
include/asm-ia64/unistd.h
include/asm-m32r/assembler.h
include/asm-m32r/atomic.h
include/asm-m32r/bitops.h
include/asm-m32r/cacheflush.h
include/asm-m32r/hardirq.h
include/asm-m32r/ide.h
include/asm-m32r/irq.h
include/asm-m32r/kmap_types.h
include/asm-m32r/m32104ut/m32104ut_pld.h
include/asm-m32r/m32700ut/m32700ut_lan.h
include/asm-m32r/m32700ut/m32700ut_lcd.h
include/asm-m32r/m32700ut/m32700ut_pld.h
include/asm-m32r/m32r.h
include/asm-m32r/mmu.h
include/asm-m32r/mmu_context.h
include/asm-m32r/opsput/opsput_lan.h
include/asm-m32r/opsput/opsput_lcd.h
include/asm-m32r/opsput/opsput_pld.h
include/asm-m32r/page.h
include/asm-m32r/pgalloc.h
include/asm-m32r/pgtable-2level.h
include/asm-m32r/pgtable.h
include/asm-m32r/processor.h
include/asm-m32r/ptrace.h
include/asm-m32r/rtc.h
include/asm-m32r/semaphore.h
include/asm-m32r/serial.h
include/asm-m32r/sigcontext.h
include/asm-m32r/smp.h
include/asm-m32r/spinlock.h
include/asm-m32r/system.h
include/asm-m32r/timex.h
include/asm-m32r/tlbflush.h
include/asm-m32r/uaccess.h
include/asm-m32r/unistd.h
include/asm-m68k/atomic.h
include/asm-m68k/bug.h
include/asm-m68k/dma-mapping.h
include/asm-m68k/dma.h
include/asm-m68k/dvma.h
include/asm-m68k/elf.h
include/asm-m68k/entry.h
include/asm-m68k/fpu.h
include/asm-m68k/hardirq.h
include/asm-m68k/ide.h
include/asm-m68k/io.h
include/asm-m68k/irq.h
include/asm-m68k/mc146818rtc.h
include/asm-m68k/mmu_context.h
include/asm-m68k/motorola_pgtable.h
include/asm-m68k/openprom.h
include/asm-m68k/page.h
include/asm-m68k/page_offset.h
include/asm-m68k/pgalloc.h
include/asm-m68k/pgtable.h
include/asm-m68k/processor.h
include/asm-m68k/semaphore-helper.h
include/asm-m68k/serial.h
include/asm-m68k/setup.h
include/asm-m68k/shm.h
include/asm-m68k/system.h
include/asm-m68k/tlbflush.h
include/asm-m68k/unistd.h
include/asm-m68k/virtconvert.h
include/asm-m68knommu/bitops.h
include/asm-m68knommu/coldfire.h
include/asm-m68knommu/commproc.h
include/asm-m68knommu/dma-mapping.h
include/asm-m68knommu/dma.h
include/asm-m68knommu/elf.h
include/asm-m68knommu/elia.h
include/asm-m68knommu/entry.h
include/asm-m68knommu/fpu.h
include/asm-m68knommu/hardirq.h
include/asm-m68knommu/io.h
include/asm-m68knommu/irq.h
include/asm-m68knommu/m5206sim.h
include/asm-m68knommu/m520xsim.h
include/asm-m68knommu/m523xsim.h
include/asm-m68knommu/m5272sim.h
include/asm-m68knommu/m527xsim.h
include/asm-m68knommu/m528xsim.h
include/asm-m68knommu/mcfcache.h
include/asm-m68knommu/mcfdma.h
include/asm-m68knommu/mcfmbus.h
include/asm-m68knommu/mcfne.h
include/asm-m68knommu/mcfpci.h
include/asm-m68knommu/mcfpit.h
include/asm-m68knommu/mcfsim.h
include/asm-m68knommu/mcfsmc.h
include/asm-m68knommu/mcftimer.h
include/asm-m68knommu/mcfuart.h
include/asm-m68knommu/mcfwdebug.h
include/asm-m68knommu/mmu_context.h
include/asm-m68knommu/nettel.h
include/asm-m68knommu/page.h
include/asm-m68knommu/page_offset.h
include/asm-m68knommu/param.h
include/asm-m68knommu/pgtable.h
include/asm-m68knommu/processor.h
include/asm-m68knommu/semaphore-helper.h
include/asm-m68knommu/system.h
include/asm-m68knommu/unaligned.h
include/asm-m68knommu/unistd.h
include/asm-mips/a.out.h
include/asm-mips/addrspace.h
include/asm-mips/apm.h [new file with mode: 0644]
include/asm-mips/arc/types.h
include/asm-mips/asm.h
include/asm-mips/asmmacro-32.h
include/asm-mips/asmmacro-64.h
include/asm-mips/asmmacro.h
include/asm-mips/atomic.h
include/asm-mips/bcache.h
include/asm-mips/bitops.h
include/asm-mips/bootinfo.h
include/asm-mips/bug.h
include/asm-mips/bugs.h
include/asm-mips/byteorder.h
include/asm-mips/cache.h
include/asm-mips/checksum.h
include/asm-mips/cpu-features.h
include/asm-mips/cpu-info.h
include/asm-mips/cpu.h
include/asm-mips/ddb5074.h [deleted file]
include/asm-mips/ddb5xxx/ddb5074.h [deleted file]
include/asm-mips/ddb5xxx/ddb5476.h [deleted file]
include/asm-mips/ddb5xxx/ddb5477.h
include/asm-mips/ddb5xxx/ddb5xxx.h
include/asm-mips/debug.h
include/asm-mips/dec/prom.h
include/asm-mips/delay.h
include/asm-mips/dma.h
include/asm-mips/elf.h
include/asm-mips/emma2rh/emma2rh.h [new file with mode: 0644]
include/asm-mips/emma2rh/markeins.h [new file with mode: 0644]
include/asm-mips/fcntl.h
include/asm-mips/fixmap.h
include/asm-mips/fpu.h
include/asm-mips/fpu_emulator.h
include/asm-mips/futex.h
include/asm-mips/hazards.h
include/asm-mips/highmem.h
include/asm-mips/inst.h
include/asm-mips/interrupt.h
include/asm-mips/io.h
include/asm-mips/ip32/machine.h
include/asm-mips/irq.h
include/asm-mips/isadep.h
include/asm-mips/jmr3927/irq.h
include/asm-mips/kmap_types.h
include/asm-mips/local.h
include/asm-mips/mach-au1x00/au1000.h
include/asm-mips/mach-au1x00/au1xxx.h
include/asm-mips/mach-au1x00/au1xxx_dbdma.h
include/asm-mips/mach-au1x00/au1xxx_ide.h
include/asm-mips/mach-au1x00/au1xxx_psc.h
include/asm-mips/mach-au1x00/ioremap.h
include/asm-mips/mach-cobalt/cpu-feature-overrides.h
include/asm-mips/mach-db1x00/db1x00.h
include/asm-mips/mach-ddb5074/mc146818rtc.h [deleted file]
include/asm-mips/mach-dec/param.h [deleted file]
include/asm-mips/mach-emma2rh/irq.h [moved from include/asm-mips/mach-mips/param.h with 58% similarity]
include/asm-mips/mach-excite/cpu-feature-overrides.h [new file with mode: 0644]
include/asm-mips/mach-excite/excite.h [new file with mode: 0644]
include/asm-mips/mach-excite/excite_nandflash.h [new file with mode: 0644]
include/asm-mips/mach-excite/rm9k_eth.h [new file with mode: 0644]
include/asm-mips/mach-excite/rm9k_wdt.h [new file with mode: 0644]
include/asm-mips/mach-excite/rm9k_xicap.h [new file with mode: 0644]
include/asm-mips/mach-generic/ide.h
include/asm-mips/mach-generic/kmalloc.h
include/asm-mips/mach-generic/param.h [deleted file]
include/asm-mips/mach-generic/spaces.h
include/asm-mips/mach-ip22/cpu-feature-overrides.h
include/asm-mips/mach-ip22/spaces.h
include/asm-mips/mach-ip27/cpu-feature-overrides.h
include/asm-mips/mach-ip32/cpu-feature-overrides.h
include/asm-mips/mach-ip32/kmalloc.h
include/asm-mips/mach-jazz/param.h [deleted file]
include/asm-mips/mach-mips/cpu-feature-overrides.h
include/asm-mips/mach-mips/irq.h
include/asm-mips/mach-pb1x00/pb1550.h
include/asm-mips/mach-qemu/param.h [deleted file]
include/asm-mips/mach-rm200/cpu-feature-overrides.h
include/asm-mips/mach-sim/cpu-feature-overrides.h
include/asm-mips/mach-wrppmc/mach-gt64120.h [new file with mode: 0644]
include/asm-mips/mips-boards/generic.h
include/asm-mips/mipsregs.h
include/asm-mips/mmu_context.h
include/asm-mips/mmzone.h
include/asm-mips/module.h
include/asm-mips/msgbuf.h
include/asm-mips/paccess.h
include/asm-mips/page.h
include/asm-mips/param.h
include/asm-mips/pci.h
include/asm-mips/pci/bridge.h
include/asm-mips/pgalloc.h
include/asm-mips/pgtable-32.h
include/asm-mips/pgtable-64.h
include/asm-mips/pgtable-bits.h
include/asm-mips/pgtable.h
include/asm-mips/prefetch.h
include/asm-mips/processor.h
include/asm-mips/ptrace.h
include/asm-mips/qemu.h
include/asm-mips/reg.h
include/asm-mips/resource.h
include/asm-mips/rm9k-ocd.h [new file with mode: 0644]
include/asm-mips/serial.h
include/asm-mips/sgiarcs.h
include/asm-mips/sibyte/board.h
include/asm-mips/sibyte/carmel.h
include/asm-mips/sibyte/sentosa.h
include/asm-mips/sibyte/swarm.h
include/asm-mips/sigcontext.h
include/asm-mips/siginfo.h
include/asm-mips/signal.h
include/asm-mips/sim.h
include/asm-mips/smp.h
include/asm-mips/sn/addrs.h
include/asm-mips/sn/agent.h
include/asm-mips/sn/arch.h
include/asm-mips/sn/fru.h [moved from include/asm-mips/sn/sn0/sn0_fru.h with 90% similarity]
include/asm-mips/sn/io.h
include/asm-mips/sn/klconfig.h
include/asm-mips/sn/kldir.h
include/asm-mips/sn/launch.h
include/asm-mips/sn/mapped_kernel.h
include/asm-mips/sn/sn0/addrs.h
include/asm-mips/sn/sn0/arch.h
include/asm-mips/sn/sn0/hub.h
include/asm-mips/sn/sn0/hubio.h
include/asm-mips/sn/sn0/hubmd.h
include/asm-mips/sn/sn0/hubpi.h
include/asm-mips/sn/sn0/ip27.h
include/asm-mips/sni.h
include/asm-mips/sparsemem.h [new file with mode: 0644]
include/asm-mips/stackframe.h
include/asm-mips/string.h
include/asm-mips/system.h
include/asm-mips/thread_info.h
include/asm-mips/tlbflush.h
include/asm-mips/tx4927/toshiba_rbtx4927.h
include/asm-mips/types.h
include/asm-mips/uaccess.h
include/asm-mips/unistd.h
include/asm-mips/vr41xx/vrc4173.h
include/asm-mips/war.h
include/asm-mips/wbflush.h
include/asm-parisc/atomic.h
include/asm-parisc/cache.h
include/asm-parisc/cacheflush.h
include/asm-parisc/dma-mapping.h
include/asm-parisc/dma.h
include/asm-parisc/io.h
include/asm-parisc/irq.h
include/asm-parisc/kmap_types.h
include/asm-parisc/page.h
include/asm-parisc/param.h
include/asm-parisc/pci.h
include/asm-parisc/pdc.h
include/asm-parisc/pgtable.h
include/asm-parisc/processor.h
include/asm-parisc/psw.h
include/asm-parisc/smp.h
include/asm-parisc/system.h
include/asm-parisc/tlbflush.h
include/asm-parisc/unistd.h
include/asm-powerpc/abs_addr.h
include/asm-powerpc/cache.h
include/asm-powerpc/cputable.h
include/asm-powerpc/dma-mapping.h
include/asm-powerpc/dma.h
include/asm-powerpc/eeh.h
include/asm-powerpc/elf.h
include/asm-powerpc/floppy.h
include/asm-powerpc/hw_irq.h
include/asm-powerpc/ide.h
include/asm-powerpc/iommu.h
include/asm-powerpc/irq.h
include/asm-powerpc/iseries/iseries_io.h
include/asm-powerpc/machdep.h
include/asm-powerpc/mmzone.h
include/asm-powerpc/paca.h
include/asm-powerpc/page.h
include/asm-powerpc/pgtable.h
include/asm-powerpc/ppc_asm.h
include/asm-powerpc/prom.h
include/asm-powerpc/smp.h
include/asm-powerpc/smu.h
include/asm-powerpc/spu.h
include/asm-powerpc/termbits.h
include/asm-powerpc/thread_info.h
include/asm-powerpc/time.h
include/asm-powerpc/timex.h
include/asm-powerpc/tlb.h
include/asm-powerpc/tlbflush.h
include/asm-powerpc/topology.h
include/asm-powerpc/types.h
include/asm-powerpc/unistd.h
include/asm-powerpc/vga.h
include/asm-powerpc/vio.h
include/asm-ppc/amigahw.h
include/asm-ppc/bootinfo.h
include/asm-ppc/commproc.h
include/asm-ppc/ibm403.h
include/asm-ppc/ibm44x.h
include/asm-ppc/ibm4xx.h
include/asm-ppc/io.h
include/asm-ppc/machdep.h
include/asm-ppc/mmu.h
include/asm-ppc/mmu_context.h
include/asm-ppc/mpc8260.h
include/asm-ppc/mpc83xx.h
include/asm-ppc/mpc85xx.h
include/asm-ppc/mpc8xx.h
include/asm-ppc/mv64x60.h
include/asm-ppc/ocp.h
include/asm-ppc/open_pic.h
include/asm-ppc/page.h
include/asm-ppc/pc_serial.h
include/asm-ppc/pgalloc.h
include/asm-ppc/pgtable.h
include/asm-ppc/ppc4xx_dma.h
include/asm-ppc/ppc4xx_pic.h
include/asm-ppc/serial.h
include/asm-ppc/smp.h
include/asm-ppc/time.h
include/asm-s390/bitops.h
include/asm-s390/cmb.h
include/asm-s390/debug.h
include/asm-s390/futex.h
include/asm-s390/hardirq.h
include/asm-s390/idals.h
include/asm-s390/local.h
include/asm-s390/lowcore.h
include/asm-s390/page.h
include/asm-s390/pgalloc.h
include/asm-s390/posix_types.h
include/asm-s390/ptrace.h
include/asm-s390/sfp-machine.h
include/asm-s390/smp.h
include/asm-s390/system.h
include/asm-s390/tlbflush.h
include/asm-s390/types.h
include/asm-s390/unistd.h
include/asm-s390/vtoc.h
include/asm-s390/z90crypt.h [new file with mode: 0644]
include/asm-sh/bug.h
include/asm-sh/checksum.h
include/asm-sh/dma-mapping.h
include/asm-sh/dma.h
include/asm-sh/fixmap.h
include/asm-sh/hardirq.h
include/asm-sh/hd64461/hd64461.h
include/asm-sh/hd64465/hd64465.h
include/asm-sh/ide.h
include/asm-sh/io.h
include/asm-sh/irq.h
include/asm-sh/keyboard.h
include/asm-sh/kmap_types.h
include/asm-sh/machvec.h
include/asm-sh/machvec_init.h
include/asm-sh/mpc1211/dma.h
include/asm-sh/overdrive/overdrive.h
include/asm-sh/page.h
include/asm-sh/pgtable.h
include/asm-sh/serial.h
include/asm-sh/smp.h
include/asm-sh/system.h
include/asm-sh/types.h
include/asm-sh/unistd.h
include/asm-sh/watchdog.h
include/asm-sh64/bug.h
include/asm-sh64/dma-mapping.h
include/asm-sh64/hardirq.h
include/asm-sh64/ide.h
include/asm-sh64/irq.h
include/asm-sh64/mmu_context.h
include/asm-sh64/page.h
include/asm-sh64/param.h
include/asm-sh64/pgtable.h
include/asm-sh64/system.h
include/asm-sh64/unistd.h
include/asm-sparc/asmmacro.h
include/asm-sparc/atomic.h
include/asm-sparc/bugs.h
include/asm-sparc/cacheflush.h
include/asm-sparc/delay.h
include/asm-sparc/dma-mapping.h
include/asm-sparc/dma.h
include/asm-sparc/elf.h
include/asm-sparc/fixmap.h
include/asm-sparc/hardirq.h
include/asm-sparc/ide.h
include/asm-sparc/irq.h
include/asm-sparc/mostek.h
include/asm-sparc/page.h
include/asm-sparc/pgalloc.h
include/asm-sparc/pgtable.h
include/asm-sparc/sfp-machine.h
include/asm-sparc/smp.h
include/asm-sparc/system.h
include/asm-sparc/timer.h
include/asm-sparc/tlbflush.h
include/asm-sparc/unistd.h
include/asm-sparc/vac-ops.h
include/asm-sparc/winmacro.h
include/asm-sparc64/atomic.h
include/asm-sparc64/bitops.h
include/asm-sparc64/bugs.h
include/asm-sparc64/cacheflush.h
include/asm-sparc64/delay.h
include/asm-sparc64/dma-mapping.h
include/asm-sparc64/dma.h
include/asm-sparc64/floppy.h
include/asm-sparc64/ide.h
include/asm-sparc64/irq.h
include/asm-sparc64/kprobes.h
include/asm-sparc64/mc146818rtc.h
include/asm-sparc64/mmu.h
include/asm-sparc64/oplib.h
include/asm-sparc64/page.h
include/asm-sparc64/param.h
include/asm-sparc64/pgalloc.h
include/asm-sparc64/pgtable.h
include/asm-sparc64/processor.h
include/asm-sparc64/siginfo.h
include/asm-sparc64/signal.h
include/asm-sparc64/smp.h
include/asm-sparc64/spinlock.h
include/asm-sparc64/system.h
include/asm-sparc64/timer.h
include/asm-sparc64/tlb.h
include/asm-sparc64/tlbflush.h
include/asm-sparc64/ttable.h
include/asm-sparc64/unistd.h
include/asm-um/a.out.h
include/asm-um/cache.h
include/asm-um/elf-ppc.h
include/asm-um/fixmap.h
include/asm-um/hardirq.h
include/asm-um/irqflags.h [new file with mode: 0644]
include/asm-um/linkage.h
include/asm-um/mmu_context.h
include/asm-um/page.h
include/asm-um/pgalloc.h
include/asm-um/processor-generic.h
include/asm-um/ptrace-generic.h
include/asm-um/smp.h
include/asm-um/thread_info.h
include/asm-um/uaccess.h
include/asm-v850/atomic.h
include/asm-v850/bitops.h
include/asm-v850/dma-mapping.h
include/asm-v850/hardirq.h
include/asm-v850/machdep.h
include/asm-v850/pgtable.h
include/asm-v850/processor.h
include/asm-v850/serial.h
include/asm-v850/unistd.h
include/asm-v850/v850e_uart.h
include/asm-x86_64/apic.h
include/asm-x86_64/atomic.h
include/asm-x86_64/bitops.h
include/asm-x86_64/bugs.h
include/asm-x86_64/cache.h
include/asm-x86_64/calling.h
include/asm-x86_64/dma-mapping.h
include/asm-x86_64/dma.h
include/asm-x86_64/dwarf2.h
include/asm-x86_64/elf.h
include/asm-x86_64/fixmap.h
include/asm-x86_64/hardirq.h
include/asm-x86_64/hw_irq.h
include/asm-x86_64/ia32.h
include/asm-x86_64/io.h
include/asm-x86_64/io_apic.h
include/asm-x86_64/mmu_context.h
include/asm-x86_64/mmzone.h
include/asm-x86_64/mtrr.h
include/asm-x86_64/page.h
include/asm-x86_64/param.h
include/asm-x86_64/pci.h
include/asm-x86_64/processor.h
include/asm-x86_64/serial.h
include/asm-x86_64/smp.h
include/asm-x86_64/spinlock.h
include/asm-x86_64/swiotlb.h
include/asm-x86_64/system.h
include/asm-x86_64/tlbflush.h
include/asm-x86_64/topology.h
include/asm-x86_64/uaccess.h
include/asm-x86_64/unistd.h
include/asm-xtensa/atomic.h
include/asm-xtensa/checksum.h
include/asm-xtensa/delay.h
include/asm-xtensa/dma.h
include/asm-xtensa/hardirq.h
include/asm-xtensa/ide.h
include/asm-xtensa/io.h
include/asm-xtensa/irq.h
include/asm-xtensa/mmu_context.h
include/asm-xtensa/page.h
include/asm-xtensa/pgalloc.h
include/asm-xtensa/platform.h
include/asm-xtensa/system.h
include/asm-xtensa/unistd.h
include/linux/acct.h
include/linux/acpi.h
include/linux/affs_hardblocks.h
include/linux/agpgart.h
include/linux/amba/clcd.h
include/linux/atmdev.h
include/linux/audit.h
include/linux/blkdev.h
include/linux/blkpg.h
include/linux/blktrace_api.h
include/linux/blockgroup_lock.h
include/linux/cache.h
include/linux/coda.h
include/linux/compat.h
include/linux/compiler.h
include/linux/console.h
include/linux/cpufreq.h
include/linux/cramfs_fs.h
include/linux/crypto.h
include/linux/cyclomx.h
include/linux/dcookies.h
include/linux/devfs_fs_kernel.h
include/linux/device.h
include/linux/divert.h
include/linux/dmaengine.h [new file with mode: 0644]
include/linux/dmi.h
include/linux/dnotify.h
include/linux/elevator.h
include/linux/elf-em.h [new file with mode: 0644]
include/linux/elf.h
include/linux/errqueue.h
include/linux/ethtool.h
include/linux/ext2_fs.h
include/linux/ext3_fs.h
include/linux/fs.h
include/linux/fsnotify.h
include/linux/ftape.h
include/linux/gameport.h
include/linux/generic_serial.h
include/linux/genhd.h
include/linux/gfp.h
include/linux/hardirq.h
include/linux/highmem.h
include/linux/highuid.h
include/linux/hrtimer.h
include/linux/i2c-algo-ite.h
include/linux/i2c.h
include/linux/i2o-dev.h
include/linux/i2o.h
include/linux/ide.h
include/linux/if_fddi.h
include/linux/if_frad.h
include/linux/if_tr.h
include/linux/igmp.h
include/linux/init.h
include/linux/inotify.h
include/linux/input.h
include/linux/interrupt.h
include/linux/ipmi.h
include/linux/ipv6.h
include/linux/irq.h
include/linux/irq_cpustat.h
include/linux/isapnp.h
include/linux/isdn.h
include/linux/isdn/tpam.h
include/linux/isdn_ppp.h
include/linux/isdnif.h
include/linux/jffs2.h
include/linux/joystick.h
include/linux/kallsyms.h
include/linux/kernel_stat.h
include/linux/kmod.h
include/linux/kprobes.h
include/linux/linkage.h
include/linux/lockd/lockd.h
include/linux/lockd/nlm.h
include/linux/m48t86.h
include/linux/mempolicy.h
include/linux/migrate.h
include/linux/mii.h
include/linux/mm.h
include/linux/mman.h
include/linux/mmzone.h
include/linux/module.h
include/linux/msg.h
include/linux/mtd/cfi.h
include/linux/mtd/inftl.h
include/linux/mtd/map.h
include/linux/mtd/mtd.h
include/linux/mtd/nand.h
include/linux/mtd/ndfc.h [new file with mode: 0644]
include/linux/mtd/nftl.h
include/linux/mtd/onenand.h
include/linux/mtd/onenand_regs.h
include/linux/mtd/partitions.h
include/linux/mtd/physmap.h
include/linux/mtd/xip.h
include/linux/nbd.h
include/linux/ncp_fs.h
include/linux/net.h
include/linux/netdevice.h
include/linux/netfilter.h
include/linux/netfilter/nf_conntrack_common.h
include/linux/netfilter/nfnetlink_conntrack.h
include/linux/netfilter/xt_CONNSECMARK.h [new file with mode: 0644]
include/linux/netfilter/xt_SECMARK.h [new file with mode: 0644]
include/linux/netfilter/xt_conntrack.h
include/linux/netfilter/xt_quota.h [new file with mode: 0644]
include/linux/netfilter/xt_statistic.h [new file with mode: 0644]
include/linux/netfilter_arp.h
include/linux/netfilter_bridge.h
include/linux/netfilter_ipv4.h
include/linux/netfilter_ipv4/ip_conntrack.h
include/linux/netfilter_ipv4/ip_conntrack_h323.h
include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
include/linux/netfilter_ipv4/ip_conntrack_sip.h [new file with mode: 0644]
include/linux/netfilter_ipv4/listhelp.h
include/linux/nfs.h
include/linux/nfs4.h
include/linux/nfs_fs.h
include/linux/nfsd/nfsd.h
include/linux/nfsd/nfsfh.h
include/linux/nfsd/syscall.h
include/linux/numa.h
include/linux/parport.h
include/linux/pci-acpi.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/percpu_counter.h
include/linux/pfkeyv2.h
include/linux/pm.h
include/linux/pm_legacy.h
include/linux/pmu.h
include/linux/ppp_defs.h
include/linux/preempt.h
include/linux/proc_fs.h
include/linux/profile.h
include/linux/quota.h
include/linux/quotaops.h
include/linux/rbtree.h
include/linux/reiserfs_xattr.h
include/linux/relay.h
include/linux/rio.h
include/linux/rio_drv.h
include/linux/rmap.h
include/linux/rtnetlink.h
include/linux/rwsem.h
include/linux/scc.h
include/linux/sched.h
include/linux/seccomp.h
include/linux/security.h
include/linux/selinux.h
include/linux/sem.h
include/linux/seqlock.h
include/linux/serialP.h
include/linux/serial_core.h
include/linux/signal.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/smb_fs.h
include/linux/smp.h
include/linux/smp_lock.h
include/linux/socket.h
include/linux/spinlock.h
include/linux/stop_machine.h
include/linux/sunrpc/auth.h
include/linux/sunrpc/debug.h
include/linux/sunrpc/stats.h
include/linux/suspend.h
include/linux/swap.h
include/linux/syscalls.h
include/linux/sysctl.h
include/linux/sysrq.h
include/linux/tcp.h
include/linux/threads.h
include/linux/timer.h
include/linux/timex.h
include/linux/tty.h
include/linux/types.h
include/linux/udp.h
include/linux/ufs_fs.h
include/linux/unistd.h
include/linux/usb.h
include/linux/usb_usual.h
include/linux/usbdevice_fs.h
include/linux/vt_buffer.h
include/linux/vt_kern.h
include/linux/wait.h
include/linux/wanrouter.h
include/linux/xfrm.h
include/mtd/mtd-abi.h
include/mtd/mtd-user.h
include/net/addrconf.h
include/net/af_unix.h
include/net/ax25.h
include/net/compat.h
include/net/dst.h
include/net/icmp.h
include/net/ieee80211.h
include/net/ieee80211softmac.h
include/net/ieee80211softmac_wx.h
include/net/inet6_hashtables.h
include/net/inet_hashtables.h
include/net/inet_sock.h
include/net/inet_timewait_sock.h
include/net/ip.h
include/net/ip_fib.h
include/net/ip_mp_alg.h
include/net/ip_vs.h
include/net/ipv6.h
include/net/irda/irda.h
include/net/irda/irda_device.h
include/net/irda/irlap.h
include/net/irda/irlmp.h
include/net/irda/irlmp_frame.h
include/net/irda/qos.h
include/net/llc_if.h
include/net/ndisc.h
include/net/netdma.h [new file with mode: 0644]
include/net/netfilter/nf_conntrack.h
include/net/netfilter/nf_conntrack_compat.h
include/net/pkt_act.h
include/net/protocol.h
include/net/raw.h
include/net/red.h
include/net/route.h
include/net/sch_generic.h
include/net/sctp/sctp.h
include/net/sctp/structs.h
include/net/sock.h
include/net/tcp.h
include/net/xfrm.h
include/pcmcia/ss.h
include/rdma/ib_addr.h [new file with mode: 0644]
include/rdma/ib_cache.h
include/rdma/ib_cm.h
include/rdma/ib_marshall.h [new file with mode: 0644]
include/rdma/ib_sa.h
include/rdma/ib_smi.h
include/rdma/ib_user_cm.h
include/rdma/ib_user_sa.h [new file with mode: 0644]
include/rdma/ib_user_verbs.h
include/rdma/ib_verbs.h
include/rdma/rdma_cm.h [new file with mode: 0644]
include/rdma/rdma_cm_ib.h [new file with mode: 0644]
include/scsi/scsi_transport_fc.h
include/scsi/scsi_transport_spi.h
include/scsi/srp.h
include/sound/driver.h
include/sound/hdsp.h
include/video/edid.h
include/video/vga.h
init/Kconfig
init/do_mounts.c
ipc/mqueue.c
ipc/msg.c
ipc/sem.c
ipc/shm.c
kernel/Makefile
kernel/audit.c
kernel/audit.h
kernel/auditfilter.c
kernel/auditsc.c
kernel/exit.c
kernel/hrtimer.c
kernel/intermodule.c [deleted file]
kernel/posix-cpu-timers.c
kernel/power/main.c
kernel/printk.c
kernel/signal.c
kernel/sysctl.c
kernel/user.c
lib/rbtree.c
mm/memory_hotplug.c
mm/shmem.c
mm/slab.c
mm/vmscan.c
net/Kconfig
net/atm/clip.c
net/bridge/Makefile
net/bridge/br.c
net/bridge/br_device.c
net/bridge/br_forward.c
net/bridge/br_if.c
net/bridge/br_netfilter.c
net/bridge/br_netlink.c [new file with mode: 0644]
net/bridge/br_notify.c
net/bridge/br_private.h
net/bridge/br_stp_if.c
net/core/Makefile
net/core/dev.c
net/core/dev_mcast.c
net/core/ethtool.c
net/core/netpoll.c
net/core/pktgen.c
net/core/skbuff.c
net/core/sock.c
net/core/user_dma.c [new file with mode: 0644]
net/dccp/ackvec.c
net/dccp/proto.c
net/decnet/dn_nsp_in.c
net/decnet/dn_route.c
net/ethernet/Makefile
net/ethernet/sysctl_net_ether.c [deleted file]
net/ieee80211/ieee80211_crypt_tkip.c
net/ieee80211/ieee80211_rx.c
net/ieee80211/ieee80211_tx.c
net/ieee80211/ieee80211_wx.c
net/ieee80211/softmac/Kconfig
net/ieee80211/softmac/ieee80211softmac_assoc.c
net/ieee80211/softmac/ieee80211softmac_auth.c
net/ieee80211/softmac/ieee80211softmac_event.c
net/ieee80211/softmac/ieee80211softmac_io.c
net/ieee80211/softmac/ieee80211softmac_module.c
net/ieee80211/softmac/ieee80211softmac_priv.h
net/ieee80211/softmac/ieee80211softmac_wx.c
net/ipv4/Kconfig
net/ipv4/Makefile
net/ipv4/ah4.c
net/ipv4/esp4.c
net/ipv4/fib_frontend.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip_forward.c
net/ipv4/ip_output.c
net/ipv4/ipcomp.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Makefile
net/ipv4/netfilter/ip_conntrack_amanda.c
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_conntrack_ftp.c
net/ipv4/netfilter/ip_conntrack_helper_h323.c
net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
net/ipv4/netfilter/ip_conntrack_helper_pptp.c
net/ipv4/netfilter/ip_conntrack_netlink.c
net/ipv4/netfilter/ip_conntrack_proto_gre.c
net/ipv4/netfilter/ip_conntrack_proto_icmp.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/ip_conntrack_proto_udp.c
net/ipv4/netfilter/ip_conntrack_sip.c [new file with mode: 0644]
net/ipv4/netfilter/ip_conntrack_standalone.c
net/ipv4/netfilter/ip_nat_helper_h323.c
net/ipv4/netfilter/ip_nat_sip.c [new file with mode: 0644]
net/ipv4/netfilter/ip_nat_snmp_basic.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/ipt_REJECT.c
net/ipv4/netfilter/ipt_hashlimit.c
net/ipv4/netfilter/ipt_recent.c
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
net/ipv4/netfilter/nf_conntrack_proto_icmp.c
net/ipv4/raw.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_bic.c
net/ipv4/tcp_compound.c [new file with mode: 0644]
net/ipv4/tcp_cong.c
net/ipv4/tcp_cubic.c
net/ipv4/tcp_highspeed.c
net/ipv4/tcp_htcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_lp.c [new file with mode: 0644]
net/ipv4/tcp_output.c
net/ipv4/tcp_probe.c [new file with mode: 0644]
net/ipv4/tcp_veno.c [new file with mode: 0644]
net/ipv4/tcp_westwood.c
net/ipv4/xfrm4_input.c
net/ipv4/xfrm4_mode_transport.c [new file with mode: 0644]
net/ipv4/xfrm4_mode_tunnel.c [new file with mode: 0644]
net/ipv4/xfrm4_output.c
net/ipv4/xfrm4_policy.c
net/ipv4/xfrm4_state.c
net/ipv6/Kconfig
net/ipv6/Makefile
net/ipv6/addrconf.c
net/ipv6/ah6.c
net/ipv6/esp6.c
net/ipv6/ip6_output.c
net/ipv6/ipcomp6.c
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/xfrm6_input.c
net/ipv6/xfrm6_mode_transport.c [new file with mode: 0644]
net/ipv6/xfrm6_mode_tunnel.c [new file with mode: 0644]
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_policy.c
net/ipv6/xfrm6_state.c
net/ipx/ipx_route.c
net/irda/irlap.c
net/irda/irlmp.c
net/key/af_key.c
net/llc/af_llc.c
net/llc/llc_if.c
net/llc/llc_input.c
net/llc/llc_sap.c
net/netfilter/Kconfig
net/netfilter/Makefile
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_ftp.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_proto_udp.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/xt_CONNSECMARK.c [new file with mode: 0644]
net/netfilter/xt_SECMARK.c [new file with mode: 0644]
net/netfilter/xt_connmark.c
net/netfilter/xt_dccp.c
net/netfilter/xt_mark.c
net/netfilter/xt_multiport.c
net/netfilter/xt_quota.c [new file with mode: 0644]
net/netfilter/xt_sctp.c
net/netfilter/xt_statistic.c [new file with mode: 0644]
net/netfilter/xt_string.c
net/sched/sch_generic.c
net/sched/sch_teql.c
net/sctp/input.c
net/sctp/ipv6.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/protocol.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/ulpevent.c
net/sysctl_net.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
security/dummy.c
security/keys/key.c
security/selinux/Kconfig
security/selinux/exports.c
security/selinux/hooks.c
security/selinux/include/av_inherit.h
security/selinux/include/av_perm_to_string.h
security/selinux/include/av_permissions.h
security/selinux/include/class_to_string.h
security/selinux/include/flask.h
security/selinux/include/xfrm.h
security/selinux/selinuxfs.c
security/selinux/ss/services.c
security/selinux/xfrm.c
sound/oss/Kconfig

diff --git a/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen b/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen
new file mode 100644 (file)
index 0000000..1e6a23f
--- /dev/null
@@ -0,0 +1,61 @@
+README on the ADC/Touchscreen Controller
+========================================
+
+The LH79524 and LH7A404 include a built-in Analog to Digital
+controller (ADC) that is used to process input from a touchscreen.
+The driver only implements a four-wire touch panel protocol.
+
+The touchscreen driver is maintenance free except for the pen-down or
+touch threshold.  Some resistive displays and board combinations may
+require tuning of this threshold.  The driver exposes some of it's
+internal state in the sys filesystem.  If the kernel is configured
+with it, CONFIG_SYSFS, and sysfs is mounted at /sys, there will be a
+directory
+
+  /sys/devices/platform/adc-lh7.0
+
+containing these files.
+
+  -r--r--r--    1 root     root         4096 Jan  1 00:00 samples
+  -rw-r--r--    1 root     root         4096 Jan  1 00:00 threshold
+  -r--r--r--    1 root     root         4096 Jan  1 00:00 threshold_range
+
+The threshold is the current touch threshold.  It defaults to 750 on
+most targets.
+
+  # cat threshold
+ 750
+
+The threshold_range contains the range of valid values for the
+threshold.  Values outside of this range will be silently ignored.
+
+  # cat threshold_range
+  0 1023
+
+To change the threshold, write a value to the threshold file.
+
+  # echo 500 > threshold
+  # cat threshold
+  500
+
+The samples file contains the most recently sampled values from the
+ADC.  There are 12.  Below are typical of the last sampled values when
+the pen has been released.  The first two and last two samples are for
+detecting whether or not the pen is down.  The third through sixth are
+X coordinate samples.  The seventh through tenth are Y coordinate
+samples.
+
+  # cat samples
+  1023 1023 0 0 0 0 530 529 530 529 1023 1023
+
+To determine a reasonable threshold, press on the touch panel with an
+appropriate stylus and read the values from samples.
+
+  # cat samples
+  1023 676 92 103 101 102 855 919 922 922 1023 679
+
+The first and eleventh samples are discarded.  Thus, the important
+values are the second and twelfth which are used to determine if the
+pen is down.  When both are below the threshold, the driver registers
+that the pen is down.  When either is above the threshold, it
+registers then pen is up.
diff --git a/Documentation/arm/Sharp-LH/LCDPanels b/Documentation/arm/Sharp-LH/LCDPanels
new file mode 100644 (file)
index 0000000..fb1b21c
--- /dev/null
@@ -0,0 +1,59 @@
+README on the LCD Panels
+========================
+
+Configuration options for several LCD panels, available from Logic PD,
+are included in the kernel source.  This README will help you
+understand the configuration data and give you some guidance for
+adding support for other panels if you wish.
+
+
+lcd-panels.h
+------------
+
+There is no way, at present, to detect which panel is attached to the
+system at runtime.  Thus the kernel configuration is static.  The file
+arch/arm/mach-ld7a40x/lcd-panels.h (or similar) defines all of the
+panel specific parameters.
+
+It should be possible for this data to be shared among several device
+families.  The current layout may be insufficiently general, but it is
+amenable to improvement.
+
+
+PIXEL_CLOCK
+-----------
+
+The panel data sheets will give a range of acceptable pixel clocks.
+The fundamental LCDCLK input frequency is divided down by a PCD
+constant in field '.tim2'.  It may happen that it is impossible to set
+the pixel clock within this range.  A clock which is too slow will
+tend to flicker.  For the highest quality image, set the clock as high
+as possible.
+
+
+MARGINS
+-------
+
+These values may be difficult to glean from the panel data sheet.  In
+the case of the Sharp panels, the upper margin is explicitly called
+out as a specific number of lines from the top of the frame.  The
+other values may not matter as much as the panels tend to
+automatically center the image.
+
+
+Sync Sense
+----------
+
+The sense of the hsync and vsync pulses may be called out in the data
+sheet.  On one panel, the sense of these pulses determine the height
+of the visible region on the panel.  Most of the Sharp panels use
+negative sense sync pulses set by the TIM2_IHS and TIM2_IVS bits in
+'.tim2'.
+
+
+Pel Layout
+----------
+
+The Sharp color TFT panels are all configured for 16 bit direct color
+modes.  The amba-lcd driver sets the pel mode to 565 for 5 bits of
+each red and blue and 6 bits of green.
index 43ab119963d5ef706f1f5c602526a4a9caf28ae9..f50cf8fac3f031d548ff68c3ab693761c87efadd 100644 (file)
@@ -212,15 +212,6 @@ Who:       Greg Kroah-Hartman <gregkh@suse.de>
 
 ---------------------------
 
-What:  Support for NEC DDB5074 and DDB5476 evaluation boards.
-When:  June 2006
-Why:   Board specific code doesn't build anymore since ~2.6.0 and no
-       users have complained indicating there is no more need for these
-       boards.  This should really be considered a last call.
-Who:   Ralf Baechle <ralf@linux-mips.org>
-
----------------------------
-
 What:  USB driver API moves to EXPORT_SYMBOL_GPL
 When:  Febuary 2008
 Files: include/linux/usb.h, drivers/usb/core/driver.c
index 6d501903f68ed823c12fc788c5f2be6e3d556338..59a919f16144df84dc6e3934dcdc22c26611a6ea 100644 (file)
@@ -69,17 +69,135 @@ Prototypes:
        int inotify_rm_watch (int fd, __u32 mask);
 
 
-(iii) Internal Kernel Implementation
+(iii) Kernel Interface
 
-Each inotify instance is associated with an inotify_device structure.
+Inotify's kernel API consists a set of functions for managing watches and an
+event callback.
+
+To use the kernel API, you must first initialize an inotify instance with a set
+of inotify_operations.  You are given an opaque inotify_handle, which you use
+for any further calls to inotify.
+
+    struct inotify_handle *ih = inotify_init(my_event_handler);
+
+You must provide a function for processing events and a function for destroying
+the inotify watch.
+
+    void handle_event(struct inotify_watch *watch, u32 wd, u32 mask,
+                     u32 cookie, const char *name, struct inode *inode)
+
+       watch - the pointer to the inotify_watch that triggered this call
+       wd - the watch descriptor
+       mask - describes the event that occurred
+       cookie - an identifier for synchronizing events
+       name - the dentry name for affected files in a directory-based event
+       inode - the affected inode in a directory-based event
+
+    void destroy_watch(struct inotify_watch *watch)
+
+You may add watches by providing a pre-allocated and initialized inotify_watch
+structure and specifying the inode to watch along with an inotify event mask.
+You must pin the inode during the call.  You will likely wish to embed the
+inotify_watch structure in a structure of your own which contains other
+information about the watch.  Once you add an inotify watch, it is immediately
+subject to removal depending on filesystem events.  You must grab a reference if
+you depend on the watch hanging around after the call.
+
+    inotify_init_watch(&my_watch->iwatch);
+    inotify_get_watch(&my_watch->iwatch);      // optional
+    s32 wd = inotify_add_watch(ih, &my_watch->iwatch, inode, mask);
+    inotify_put_watch(&my_watch->iwatch);      // optional
+
+You may use the watch descriptor (wd) or the address of the inotify_watch for
+other inotify operations.  You must not directly read or manipulate data in the
+inotify_watch.  Additionally, you must not call inotify_add_watch() more than
+once for a given inotify_watch structure, unless you have first called either
+inotify_rm_watch() or inotify_rm_wd().
+
+To determine if you have already registered a watch for a given inode, you may
+call inotify_find_watch(), which gives you both the wd and the watch pointer for
+the inotify_watch, or an error if the watch does not exist.
+
+    wd = inotify_find_watch(ih, inode, &watchp);
+
+You may use container_of() on the watch pointer to access your own data
+associated with a given watch.  When an existing watch is found,
+inotify_find_watch() bumps the refcount before releasing its locks.  You must
+put that reference with:
+
+    put_inotify_watch(watchp);
+
+Call inotify_find_update_watch() to update the event mask for an existing watch.
+inotify_find_update_watch() returns the wd of the updated watch, or an error if
+the watch does not exist.
+
+    wd = inotify_find_update_watch(ih, inode, mask);
+
+An existing watch may be removed by calling either inotify_rm_watch() or
+inotify_rm_wd().
+
+    int ret = inotify_rm_watch(ih, &my_watch->iwatch);
+    int ret = inotify_rm_wd(ih, wd);
+
+A watch may be removed while executing your event handler with the following:
+
+    inotify_remove_watch_locked(ih, iwatch);
+
+Call inotify_destroy() to remove all watches from your inotify instance and
+release it.  If there are no outstanding references, inotify_destroy() will call
+your destroy_watch op for each watch.
+
+    inotify_destroy(ih);
+
+When inotify removes a watch, it sends an IN_IGNORED event to your callback.
+You may use this event as an indication to free the watch memory.  Note that
+inotify may remove a watch due to filesystem events, as well as by your request.
+If you use IN_ONESHOT, inotify will remove the watch after the first event, at
+which point you may call the final inotify_put_watch.
+
+(iv) Kernel Interface Prototypes
+
+       struct inotify_handle *inotify_init(struct inotify_operations *ops);
+
+       inotify_init_watch(struct inotify_watch *watch);
+
+       s32 inotify_add_watch(struct inotify_handle *ih,
+                             struct inotify_watch *watch,
+                             struct inode *inode, u32 mask);
+
+       s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode,
+                              struct inotify_watch **watchp);
+
+       s32 inotify_find_update_watch(struct inotify_handle *ih,
+                                     struct inode *inode, u32 mask);
+
+       int inotify_rm_wd(struct inotify_handle *ih, u32 wd);
+
+       int inotify_rm_watch(struct inotify_handle *ih,
+                            struct inotify_watch *watch);
+
+       void inotify_remove_watch_locked(struct inotify_handle *ih,
+                                        struct inotify_watch *watch);
+
+       void inotify_destroy(struct inotify_handle *ih);
+
+       void get_inotify_watch(struct inotify_watch *watch);
+       void put_inotify_watch(struct inotify_watch *watch);
+
+
+(v) Internal Kernel Implementation
+
+Each inotify instance is represented by an inotify_handle structure.
+Inotify's userspace consumers also have an inotify_device which is
+associated with the inotify_handle, and on which events are queued.
 
 Each watch is associated with an inotify_watch structure.  Watches are chained
-off of each associated device and each associated inode.
+off of each associated inotify_handle and each associated inode.
 
-See fs/inotify.c for the locking and lifetime rules.
+See fs/inotify.c and fs/inotify_user.c for the locking and lifetime rules.
 
 
-(iv) Rationale
+(vi) Rationale
 
 Q: What is the design decision behind not tying the watch to the open fd of
    the watched object?
@@ -145,7 +263,7 @@ A: The poor user-space interface is the second biggest problem with dnotify.
    file descriptor-based one that allows basic file I/O and poll/select.
    Obtaining the fd and managing the watches could have been done either via a
    device file or a family of new system calls.  We decided to implement a
-   family of system calls because that is the preffered approach for new kernel
+   family of system calls because that is the preferred approach for new kernel
    interfaces.  The only real difference was whether we wanted to use open(2)
    and ioctl(2) or a couple of new system calls.  System calls beat ioctls.
 
index 5c5a4ccce76aaec20a921b395cf7028ffbed7a1c..187035560d7ff6a9817c90e824318e0dde69c5e6 100644 (file)
@@ -1,10 +1,10 @@
 IP OVER INFINIBAND
 
   The ib_ipoib driver is an implementation of the IP over InfiniBand
-  protocol as specified by the latest Internet-Drafts issued by the
-  IETF ipoib working group.  It is a "native" implementation in the
-  sense of setting the interface type to ARPHRD_INFINIBAND and the
-  hardware address length to 20 (earlier proprietary implementations
+  protocol as specified by RFC 4391 and 4392, issued by the IETF ipoib
+  working group.  It is a "native" implementation in the sense of
+  setting the interface type to ARPHRD_INFINIBAND and the hardware
+  address length to 20 (earlier proprietary implementations
   masqueraded to the kernel as ethernet interfaces).
 
 Partitions and P_Keys
@@ -53,3 +53,7 @@ References
 
   IETF IP over InfiniBand (ipoib) Working Group
     http://ietf.org/html.charters/ipoib-charter.html
+  Transmission of IP over InfiniBand (IPoIB) (RFC 4391)
+    http://ietf.org/rfc/rfc4391.txt 
+  IP over InfiniBand (IPoIB) Architecture (RFC 4392)
+    http://ietf.org/rfc/rfc4392.txt 
index b3a6187e53051866004696e4d5718cd85240e1c2..a9d3a1794b232da271d71178fbd05c3078e87723 100644 (file)
@@ -1402,6 +1402,15 @@ running once the system is up.
                        If enabled at boot time, /selinux/disable can be used
                        later to disable prior to initial policy load.
 
+       selinux_compat_net =
+                       [SELINUX] Set initial selinux_compat_net flag value.
+                        Format: { "0" | "1" }
+                        0 -- use new secmark-based packet controls
+                        1 -- use legacy packet controls
+                        Default value is 0 (preferred).
+                        Value can be changed at runtime via
+                        /selinux/compat_net.
+
        serialnumber    [BUGS=IA-32]
 
        sg_def_reserved_size=   [SCSI]
index c61d8b876fdbcba484a3ad149ac3d057dfb76bba..4710845dbac4fb663e35fcf0056499614a06e56b 100644 (file)
@@ -19,6 +19,7 @@ Contents:
      - Control dependencies.
      - SMP barrier pairing.
      - Examples of memory barrier sequences.
+     - Read memory barriers vs load speculation.
 
  (*) Explicit kernel barriers.
 
@@ -248,7 +249,7 @@ And there are a number of things that _must_ or _must_not_ be assumed:
      we may get either of:
 
        STORE *A = X; Y = LOAD *A;
-       STORE *A = Y;
+       STORE *A = Y = X;
 
 
 =========================
@@ -344,9 +345,12 @@ Memory barriers come in four basic varieties:
 
  (4) General memory barriers.
 
-     A general memory barrier is a combination of both a read memory barrier
-     and a write memory barrier.  It is a partial ordering over both loads and
-     stores.
+     A general memory barrier gives a guarantee that all the LOAD and STORE
+     operations specified before the barrier will appear to happen before all
+     the LOAD and STORE operations specified after the barrier with respect to
+     the other components of the system.
+
+     A general memory barrier is a partial ordering over both loads and stores.
 
      General memory barriers imply both read and write memory barriers, and so
      can substitute for either.
@@ -546,9 +550,9 @@ write barrier, though, again, a general barrier is viable:
        =============== ===============
        a = 1;
        <write barrier>
-       b = 2;          x = a;
+       b = 2;          x = b;
                        <read barrier>
-                       y = b;
+                       y = a;
 
 Or:
 
@@ -563,6 +567,18 @@ Or:
 Basically, the read barrier always has to be there, even though it can be of
 the "weaker" type.
 
+[!] Note that the stores before the write barrier would normally be expected to
+match the loads after the read barrier or data dependency barrier, and vice
+versa:
+
+       CPU 1                           CPU 2
+       ===============                 ===============
+       a = 1;           }----   --->{  v = c
+       b = 2;           }    \ /    {  w = d
+       <write barrier>        \        <read barrier>
+       c = 3;           }    / \    {  x = a;
+       d = 4;           }----   --->{  y = b;
+
 
 EXAMPLES OF MEMORY BARRIER SEQUENCES
 ------------------------------------
@@ -600,8 +616,8 @@ STORE B, STORE C } all occuring before the unordered set of { STORE D, STORE E
        |       |       +------+
        +-------+       :      :
                           |
-                          | Sequence in which stores committed to memory system
-                          | by CPU 1
+                          | Sequence in which stores are committed to the
+                          | memory system by CPU 1
                           V
 
 
@@ -683,14 +699,12 @@ then the following will occur:
                                       |        :       :       |       |
                                       |        :       :       | CPU 2 |
                                       |        +-------+       |       |
-                                       \       | X->9  |------>|       |
-                                        \      +-------+       |       |
-                                         ----->| B->2  |       |       |
-                                               +-------+       |       |
-            Makes sure all effects --->    ddddddddddddddddd   |       |
-            prior to the store of C            +-------+       |       |
-            are perceptible to                 | B->2  |------>|       |
-            successive loads                   +-------+       |       |
+                                      |        | X->9  |------>|       |
+                                      |        +-------+       |       |
+         Makes sure all effects --->   \   ddddddddddddddddd   |       |
+         prior to the store of C        \      +-------+       |       |
+         are perceptible to              ----->| B->2  |------>|       |
+         subsequent loads                      +-------+       |       |
                                                :       :       +-------+
 
 
@@ -699,73 +713,239 @@ following sequence of events:
 
        CPU 1                   CPU 2
        ======================= =======================
+               { A = 0, B = 9 }
        STORE A=1
-       STORE B=2
-       STORE C=3
        <write barrier>
-       STORE D=4
-       STORE E=5
-                               LOAD A
+       STORE B=2
                                LOAD B
-                               LOAD C
-                               LOAD D
-                               LOAD E
+                               LOAD A
 
 Without intervention, CPU 2 may then choose to perceive the events on CPU 1 in
 some effectively random order, despite the write barrier issued by CPU 1:
 
-       +-------+       :      :
-       |       |       +------+
-       |       |------>| C=3  | }
-       |       |  :    +------+ }
-       |       |  :    | A=1  | }
-       |       |  :    +------+ }
-       | CPU 1 |  :    | B=2  | }---
-       |       |       +------+ }   \
-       |       |   wwwwwwwwwwwww}    \
-       |       |       +------+ }     \          :       :       +-------+
-       |       |  :    | E=5  | }      \         +-------+       |       |
-       |       |  :    +------+ }       \      { | C->3  |------>|       |
-       |       |------>| D=4  | }        \     { +-------+    :  |       |
-       |       |       +------+           \    { | E->5  |    :  |       |
-       +-------+       :      :            \   { +-------+    :  |       |
-                                  Transfer  -->{ | A->1  |    :  | CPU 2 |
-                                 from CPU 1    { +-------+    :  |       |
-                                  to CPU 2     { | D->4  |    :  |       |
-                                               { +-------+    :  |       |
-                                               { | B->2  |------>|       |
-                                                 +-------+       |       |
-                                                 :       :       +-------+
-
-
-If, however, a read barrier were to be placed between the load of C and the
-load of D on CPU 2, then the partial ordering imposed by CPU 1 will be
-perceived correctly by CPU 2.
+       +-------+       :      :                :       :
+       |       |       +------+                +-------+
+       |       |------>| A=1  |------      --->| A->0  |
+       |       |       +------+      \         +-------+
+       | CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+       |       |       +------+        |       +-------+
+       |       |------>| B=2  |---     |       :       :
+       |       |       +------+   \    |       :       :       +-------+
+       +-------+       :      :    \   |       +-------+       |       |
+                                    ---------->| B->2  |------>|       |
+                                       |       +-------+       | CPU 2 |
+                                       |       | A->0  |------>|       |
+                                       |       +-------+       |       |
+                                       |       :       :       +-------+
+                                        \      :       :
+                                         \     +-------+
+                                          ---->| A->1  |
+                                               +-------+
+                                               :       :
 
-       +-------+       :      :
-       |       |       +------+
-       |       |------>| C=3  | }
-       |       |  :    +------+ }
-       |       |  :    | A=1  | }---
-       |       |  :    +------+ }   \
-       | CPU 1 |  :    | B=2  | }    \
-       |       |       +------+       \
-       |       |   wwwwwwwwwwwwwwww    \
-       |       |       +------+         \        :       :       +-------+
-       |       |  :    | E=5  | }        \       +-------+       |       |
-       |       |  :    +------+ }---      \    { | C->3  |------>|       |
-       |       |------>| D=4  | }   \      \   { +-------+    :  |       |
-       |       |       +------+      \      -->{ | B->2  |    :  |       |
-       +-------+       :      :       \        { +-------+    :  |       |
-                                       \       { | A->1  |    :  | CPU 2 |
-                                        \        +-------+       |       |
-          At this point the read ---->   \   rrrrrrrrrrrrrrrrr   |       |
-          barrier causes all effects      \      +-------+       |       |
-          prior to the storage of C        \   { | E->5  |    :  |       |
-          to be perceptible to CPU 2        -->{ +-------+    :  |       |
-                                               { | D->4  |------>|       |
-                                                 +-------+       |       |
-                                                 :       :       +-------+
+
+If, however, a read barrier were to be placed between the load of E and the
+load of A on CPU 2:
+
+       CPU 1                   CPU 2
+       ======================= =======================
+               { A = 0, B = 9 }
+       STORE A=1
+       <write barrier>
+       STORE B=2
+                               LOAD B
+                               <read barrier>
+                               LOAD A
+
+then the partial ordering imposed by CPU 1 will be perceived correctly by CPU
+2:
+
+       +-------+       :      :                :       :
+       |       |       +------+                +-------+
+       |       |------>| A=1  |------      --->| A->0  |
+       |       |       +------+      \         +-------+
+       | CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+       |       |       +------+        |       +-------+
+       |       |------>| B=2  |---     |       :       :
+       |       |       +------+   \    |       :       :       +-------+
+       +-------+       :      :    \   |       +-------+       |       |
+                                    ---------->| B->2  |------>|       |
+                                       |       +-------+       | CPU 2 |
+                                       |       :       :       |       |
+                                       |       :       :       |       |
+         At this point the read ---->   \  rrrrrrrrrrrrrrrrr   |       |
+         barrier causes all effects      \     +-------+       |       |
+         prior to the storage of B        ---->| A->1  |------>|       |
+         to be perceptible to CPU 2            +-------+       |       |
+                                               :       :       +-------+
+
+
+To illustrate this more completely, consider what could happen if the code
+contained a load of A either side of the read barrier:
+
+       CPU 1                   CPU 2
+       ======================= =======================
+               { A = 0, B = 9 }
+       STORE A=1
+       <write barrier>
+       STORE B=2
+                               LOAD B
+                               LOAD A [first load of A]
+                               <read barrier>
+                               LOAD A [second load of A]
+
+Even though the two loads of A both occur after the load of B, they may both
+come up with different values:
+
+       +-------+       :      :                :       :
+       |       |       +------+                +-------+
+       |       |------>| A=1  |------      --->| A->0  |
+       |       |       +------+      \         +-------+
+       | CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+       |       |       +------+        |       +-------+
+       |       |------>| B=2  |---     |       :       :
+       |       |       +------+   \    |       :       :       +-------+
+       +-------+       :      :    \   |       +-------+       |       |
+                                    ---------->| B->2  |------>|       |
+                                       |       +-------+       | CPU 2 |
+                                       |       :       :       |       |
+                                       |       :       :       |       |
+                                       |       +-------+       |       |
+                                       |       | A->0  |------>| 1st   |
+                                       |       +-------+       |       |
+         At this point the read ---->   \  rrrrrrrrrrrrrrrrr   |       |
+         barrier causes all effects      \     +-------+       |       |
+         prior to the storage of B        ---->| A->1  |------>| 2nd   |
+         to be perceptible to CPU 2            +-------+       |       |
+                                               :       :       +-------+
+
+
+But it may be that the update to A from CPU 1 becomes perceptible to CPU 2
+before the read barrier completes anyway:
+
+       +-------+       :      :                :       :
+       |       |       +------+                +-------+
+       |       |------>| A=1  |------      --->| A->0  |
+       |       |       +------+      \         +-------+
+       | CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+       |       |       +------+        |       +-------+
+       |       |------>| B=2  |---     |       :       :
+       |       |       +------+   \    |       :       :       +-------+
+       +-------+       :      :    \   |       +-------+       |       |
+                                    ---------->| B->2  |------>|       |
+                                       |       +-------+       | CPU 2 |
+                                       |       :       :       |       |
+                                        \      :       :       |       |
+                                         \     +-------+       |       |
+                                          ---->| A->1  |------>| 1st   |
+                                               +-------+       |       |
+                                           rrrrrrrrrrrrrrrrr   |       |
+                                               +-------+       |       |
+                                               | A->1  |------>| 2nd   |
+                                               +-------+       |       |
+                                               :       :       +-------+
+
+
+The guarantee is that the second load will always come up with A == 1 if the
+load of B came up with B == 2.  No such guarantee exists for the first load of
+A; that may come up with either A == 0 or A == 1.
+
+
+READ MEMORY BARRIERS VS LOAD SPECULATION
+----------------------------------------
+
+Many CPUs speculate with loads: that is they see that they will need to load an
+item from memory, and they find a time where they're not using the bus for any
+other loads, and so do the load in advance - even though they haven't actually
+got to that point in the instruction execution flow yet.  This permits the
+actual load instruction to potentially complete immediately because the CPU
+already has the value to hand.
+
+It may turn out that the CPU didn't actually need the value - perhaps because a
+branch circumvented the load - in which case it can discard the value or just
+cache it for later use.
+
+Consider:
+
+       CPU 1                   CPU 2
+       ======================= =======================
+                               LOAD B
+                               DIVIDE          } Divide instructions generally
+                               DIVIDE          } take a long time to perform
+                               LOAD A
+
+Which might appear as this:
+
+                                               :       :       +-------+
+                                               +-------+       |       |
+                                           --->| B->2  |------>|       |
+                                               +-------+       | CPU 2 |
+                                               :       :DIVIDE |       |
+                                               +-------+       |       |
+       The CPU being busy doing a --->     --->| A->0  |~~~~   |       |
+       division speculates on the              +-------+   ~   |       |
+       LOAD of A                               :       :   ~   |       |
+                                               :       :DIVIDE |       |
+                                               :       :   ~   |       |
+       Once the divisions are complete -->     :       :   ~-->|       |
+       the CPU can then perform the            :       :       |       |
+       LOAD with immediate effect              :       :       +-------+
+
+
+Placing a read barrier or a data dependency barrier just before the second
+load:
+
+       CPU 1                   CPU 2
+       ======================= =======================
+                               LOAD B
+                               DIVIDE
+                               DIVIDE
+                               <read barrier>
+                               LOAD A
+
+will force any value speculatively obtained to be reconsidered to an extent
+dependent on the type of barrier used.  If there was no change made to the
+speculated memory location, then the speculated value will just be used:
+
+                                               :       :       +-------+
+                                               +-------+       |       |
+                                           --->| B->2  |------>|       |
+                                               +-------+       | CPU 2 |
+                                               :       :DIVIDE |       |
+                                               +-------+       |       |
+       The CPU being busy doing a --->     --->| A->0  |~~~~   |       |
+       division speculates on the              +-------+   ~   |       |
+       LOAD of A                               :       :   ~   |       |
+                                               :       :DIVIDE |       |
+                                               :       :   ~   |       |
+                                               :       :   ~   |       |
+                                           rrrrrrrrrrrrrrrr~   |       |
+                                               :       :   ~   |       |
+                                               :       :   ~-->|       |
+                                               :       :       |       |
+                                               :       :       +-------+
+
+
+but if there was an update or an invalidation from another CPU pending, then
+the speculation will be cancelled and the value reloaded:
+
+                                               :       :       +-------+
+                                               +-------+       |       |
+                                           --->| B->2  |------>|       |
+                                               +-------+       | CPU 2 |
+                                               :       :DIVIDE |       |
+                                               +-------+       |       |
+       The CPU being busy doing a --->     --->| A->0  |~~~~   |       |
+       division speculates on the              +-------+   ~   |       |
+       LOAD of A                               :       :   ~   |       |
+                                               :       :DIVIDE |       |
+                                               :       :   ~   |       |
+                                               :       :   ~   |       |
+                                           rrrrrrrrrrrrrrrrr   |       |
+                                               +-------+       |       |
+       The speculation is discarded --->   --->| A->1  |------>|       |
+       and an updated value is                 +-------+       |       |
+       retrieved                               :       :       +-------+
 
 
 ========================
@@ -901,7 +1081,7 @@ IMPLICIT KERNEL MEMORY BARRIERS
 ===============================
 
 Some of the other functions in the linux kernel imply memory barriers, amongst
-which are locking, scheduling and memory allocation functions.
+which are locking and scheduling functions.
 
 This specification is a _minimum_ guarantee; any particular architecture may
 provide more substantial guarantees, but these may not be relied upon outside
@@ -966,6 +1146,20 @@ equivalent to a full barrier, but a LOCK followed by an UNLOCK is not.
     barriers is that the effects instructions outside of a critical section may
     seep into the inside of the critical section.
 
+A LOCK followed by an UNLOCK may not be assumed to be full memory barrier
+because it is possible for an access preceding the LOCK to happen after the
+LOCK, and an access following the UNLOCK to happen before the UNLOCK, and the
+two accesses can themselves then cross:
+
+       *A = a;
+       LOCK
+       UNLOCK
+       *B = b;
+
+may occur as:
+
+       LOCK, STORE *B, STORE *A, UNLOCK
+
 Locks and semaphores may not provide any guarantee of ordering on UP compiled
 systems, and so cannot be counted on in such a situation to actually achieve
 anything at all - especially with respect to I/O accesses - unless combined
@@ -1016,8 +1210,6 @@ Other functions that imply barriers:
 
  (*) schedule() and similar imply full memory barriers.
 
- (*) Memory allocation and release functions imply full memory barriers.
-
 
 =================================
 INTER-CPU LOCKING BARRIER EFFECTS
index acb30c5dcff333e11f9f9fd72957b71b3a9af02c..4f2a40f1dbc629837463a96695759e3848f41c68 100644 (file)
@@ -14,8 +14,8 @@ Copyright (C) 2004-2006, Intel Corporation
 
 README.ipw2200
 
-Version: 1.0.8
-Date   : October 20, 2005
+Version: 1.1.2
+Date   : March 30, 2006
 
 
 Index
@@ -103,7 +103,7 @@ file.
 
 1.1. Overview of Features
 -----------------------------------------------
-The current release (1.0.8) supports the following features:
+The current release (1.1.2) supports the following features:
 
 + BSS mode (Infrastructure, Managed)
 + IBSS mode (Ad-Hoc)
@@ -247,8 +247,8 @@ and can set the contents via echo.  For example:
 % cat /sys/bus/pci/drivers/ipw2200/debug_level
 
 Will report the current debug level of the driver's logging subsystem 
-(only available if CONFIG_IPW_DEBUG was configured when the driver was 
-built).
+(only available if CONFIG_IPW2200_DEBUG was configured when the driver
+was built).
 
 You can set the debug level via:
 
index 8d8b4e5ea184a26da6bfab62bed0f796ce16679a..afac780445cd19a9042a629fa32245d11806e610 100644 (file)
@@ -1,7 +1,7 @@
 
                Linux Ethernet Bonding Driver HOWTO
 
-               Latest update: 21 June 2005
+               Latest update: 24 April 2006
 
 Initial release : Thomas Davis <tadavis at lbl.gov>
 Corrections, HA extensions : 2000/10/03-15 :
@@ -12,6 +12,8 @@ Corrections, HA extensions : 2000/10/03-15 :
   - Jay Vosburgh <fubar at us dot ibm dot com>
 
 Reorganized and updated Feb 2005 by Jay Vosburgh
+Added Sysfs information: 2006/04/24
+  - Mitch Williams <mitch.a.williams at intel.com>
 
 Introduction
 ============
@@ -38,61 +40,62 @@ Table of Contents
 2. Bonding Driver Options
 
 3. Configuring Bonding Devices
-3.1    Configuration with sysconfig support
-3.1.1          Using DHCP with sysconfig
-3.1.2          Configuring Multiple Bonds with sysconfig
-3.2    Configuration with initscripts support
-3.2.1          Using DHCP with initscripts
-3.2.2          Configuring Multiple Bonds with initscripts
-3.3    Configuring Bonding Manually
+3.1    Configuration with Sysconfig Support
+3.1.1          Using DHCP with Sysconfig
+3.1.2          Configuring Multiple Bonds with Sysconfig
+3.2    Configuration with Initscripts Support
+3.2.1          Using DHCP with Initscripts
+3.2.2          Configuring Multiple Bonds with Initscripts
+3.3    Configuring Bonding Manually with Ifenslave
 3.3.1          Configuring Multiple Bonds Manually
+3.4    Configuring Bonding Manually via Sysfs
 
-5. Querying Bonding Configuration
-5.1    Bonding Configuration
-5.2    Network Configuration
+4. Querying Bonding Configuration
+4.1    Bonding Configuration
+4.2    Network Configuration
 
-6. Switch Configuration
+5. Switch Configuration
 
-7. 802.1q VLAN Support
+6. 802.1q VLAN Support
 
-8. Link Monitoring
-8.1    ARP Monitor Operation
-8.2    Configuring Multiple ARP Targets
-8.3    MII Monitor Operation
+7. Link Monitoring
+7.1    ARP Monitor Operation
+7.2    Configuring Multiple ARP Targets
+7.3    MII Monitor Operation
 
-9. Potential Trouble Sources
-9.1    Adventures in Routing
-9.2    Ethernet Device Renaming
-9.3    Painfully Slow Or No Failed Link Detection By Miimon
+8. Potential Trouble Sources
+8.1    Adventures in Routing
+8.2    Ethernet Device Renaming
+8.3    Painfully Slow Or No Failed Link Detection By Miimon
 
-10. SNMP agents
+9. SNMP agents
 
-11. Promiscuous mode
+10. Promiscuous mode
 
-12. Configuring Bonding for High Availability
-12.1   High Availability in a Single Switch Topology
-12.2   High Availability in a Multiple Switch Topology
-12.2.1         HA Bonding Mode Selection for Multiple Switch Topology
-12.2.2         HA Link Monitoring for Multiple Switch Topology
+11. Configuring Bonding for High Availability
+11.1   High Availability in a Single Switch Topology
+11.2   High Availability in a Multiple Switch Topology
+11.2.1         HA Bonding Mode Selection for Multiple Switch Topology
+11.2.2         HA Link Monitoring for Multiple Switch Topology
 
-13. Configuring Bonding for Maximum Throughput
-13.1   Maximum Throughput in a Single Switch Topology
-13.1.1         MT Bonding Mode Selection for Single Switch Topology
-13.1.2         MT Link Monitoring for Single Switch Topology
-13.2   Maximum Throughput in a Multiple Switch Topology
-13.2.1         MT Bonding Mode Selection for Multiple Switch Topology
-13.2.2         MT Link Monitoring for Multiple Switch Topology
+12. Configuring Bonding for Maximum Throughput
+12.1   Maximum Throughput in a Single Switch Topology
+12.1.1         MT Bonding Mode Selection for Single Switch Topology
+12.1.2         MT Link Monitoring for Single Switch Topology
+12.2   Maximum Throughput in a Multiple Switch Topology
+12.2.1         MT Bonding Mode Selection for Multiple Switch Topology
+12.2.2         MT Link Monitoring for Multiple Switch Topology
 
-14. Switch Behavior Issues
-14.1   Link Establishment and Failover Delays
-14.2   Duplicated Incoming Packets
+13. Switch Behavior Issues
+13.1   Link Establishment and Failover Delays
+13.2   Duplicated Incoming Packets
 
-15. Hardware Specific Considerations
-15.1   IBM BladeCenter
+14. Hardware Specific Considerations
+14.1   IBM BladeCenter
 
-16. Frequently Asked Questions
+15. Frequently Asked Questions
 
-17. Resources and Links
+16. Resources and Links
 
 
 1. Bonding Driver Installation
@@ -156,6 +159,9 @@ you're trying to build it for.  Some distros (e.g., Red Hat from 7.1
 onwards) do not have /usr/include/linux symbolically linked to the
 default kernel source include directory.
 
+SECOND IMPORTANT NOTE:
+       If you plan to configure bonding using sysfs, you do not need
+to use ifenslave.
 
 2. Bonding Driver Options
 =========================
@@ -270,7 +276,7 @@ mode
                In bonding version 2.6.2 or later, when a failover
                occurs in active-backup mode, bonding will issue one
                or more gratuitous ARPs on the newly active slave.
-               One gratutious ARP is issued for the bonding master
+               One gratuitous ARP is issued for the bonding master
                interface and each VLAN interfaces configured above
                it, provided that the interface has at least one IP
                address configured.  Gratuitous ARPs issued for VLAN
@@ -377,7 +383,7 @@ mode
                When a link is reconnected or a new slave joins the
                bond the receive traffic is redistributed among all
                active slaves in the bond by initiating ARP Replies
-               with the selected mac address to each of the
+               with the selected MAC address to each of the
                clients. The updelay parameter (detailed below) must
                be set to a value equal or greater than the switch's
                forwarding delay so that the ARP Replies sent to the
@@ -498,11 +504,12 @@ not exist, and the layer2 policy is the only policy.
 3. Configuring Bonding Devices
 ==============================
 
-       There are, essentially, two methods for configuring bonding:
-with support from the distro's network initialization scripts, and
-without.  Distros generally use one of two packages for the network
-initialization scripts: initscripts or sysconfig.  Recent versions of
-these packages have support for bonding, while older versions do not.
+       You can configure bonding using either your distro's network
+initialization scripts, or manually using either ifenslave or the
+sysfs interface.  Distros generally use one of two packages for the
+network initialization scripts: initscripts or sysconfig.  Recent
+versions of these packages have support for bonding, while older
+versions do not.
 
        We will first describe the options for configuring bonding for
 distros using versions of initscripts and sysconfig with full or
@@ -530,7 +537,7 @@ $ grep ifenslave /sbin/ifup
        If this returns any matches, then your initscripts or
 sysconfig has support for bonding.
 
-3.1 Configuration with sysconfig support
+3.1 Configuration with Sysconfig Support
 ----------------------------------------
 
        This section applies to distros using a version of sysconfig
@@ -538,7 +545,7 @@ with bonding support, for example, SuSE Linux Enterprise Server 9.
 
        SuSE SLES 9's networking configuration system does support
 bonding, however, at this writing, the YaST system configuration
-frontend does not provide any means to work with bonding devices.
+front end does not provide any means to work with bonding devices.
 Bonding devices can be managed by hand, however, as follows.
 
        First, if they have not already been configured, configure the
@@ -660,7 +667,7 @@ format can be found in an example ifcfg template file:
        Note that the template does not document the various BONDING_
 settings described above, but does describe many of the other options.
 
-3.1.1 Using DHCP with sysconfig
+3.1.1 Using DHCP with Sysconfig
 -------------------------------
 
        Under sysconfig, configuring a device with BOOTPROTO='dhcp'
@@ -670,7 +677,7 @@ attempt to obtain the device address from DHCP prior to adding any of
 the slave devices.  Without active slaves, the DHCP requests are not
 sent to the network.
 
-3.1.2 Configuring Multiple Bonds with sysconfig
+3.1.2 Configuring Multiple Bonds with Sysconfig
 -----------------------------------------------
 
        The sysconfig network initialization system is capable of
@@ -685,7 +692,7 @@ ifcfg-bondX files.
 options in the ifcfg-bondX file, it is not necessary to add them to
 the system /etc/modules.conf or /etc/modprobe.conf configuration file.
 
-3.2 Configuration with initscripts support
+3.2 Configuration with Initscripts Support
 ------------------------------------------
 
        This section applies to distros using a version of initscripts
@@ -756,7 +763,7 @@ options for your configuration.
 will restart the networking subsystem and your bond link should be now
 up and running.
 
-3.2.1 Using DHCP with initscripts
+3.2.1 Using DHCP with Initscripts
 ---------------------------------
 
        Recent versions of initscripts (the version supplied with
@@ -768,7 +775,7 @@ above, except replace the line "BOOTPROTO=none" with "BOOTPROTO=dhcp"
 and add a line consisting of "TYPE=Bonding".  Note that the TYPE value
 is case sensitive.
 
-3.2.2 Configuring Multiple Bonds with initscripts
+3.2.2 Configuring Multiple Bonds with Initscripts
 -------------------------------------------------
 
        At this writing, the initscripts package does not directly
@@ -784,8 +791,8 @@ Fedora Core kernels, and has been seen on RHEL 4 as well.  On kernels
 exhibiting this problem, it will be impossible to configure multiple
 bonds with differing parameters.
 
-3.3 Configuring Bonding Manually
---------------------------------
+3.3 Configuring Bonding Manually with Ifenslave
+-----------------------------------------------
 
        This section applies to distros whose network initialization
 scripts (the sysconfig or initscripts package) do not have specific
@@ -889,11 +896,139 @@ install bond1 /sbin/modprobe --ignore-install bonding -o bond1 \
        This may be repeated any number of times, specifying a new and
 unique name in place of bond1 for each subsequent instance.
 
+3.4 Configuring Bonding Manually via Sysfs
+------------------------------------------
+
+       Starting with version 3.0, Channel Bonding may be configured
+via the sysfs interface.  This interface allows dynamic configuration
+of all bonds in the system without unloading the module.  It also
+allows for adding and removing bonds at runtime.  Ifenslave is no
+longer required, though it is still supported.
+
+       Use of the sysfs interface allows you to use multiple bonds
+with different configurations without having to reload the module.
+It also allows you to use multiple, differently configured bonds when
+bonding is compiled into the kernel.
+
+       You must have the sysfs filesystem mounted to configure
+bonding this way.  The examples in this document assume that you
+are using the standard mount point for sysfs, e.g. /sys.  If your
+sysfs filesystem is mounted elsewhere, you will need to adjust the
+example paths accordingly.
+
+Creating and Destroying Bonds
+-----------------------------
+To add a new bond foo:
+# echo +foo > /sys/class/net/bonding_masters
+
+To remove an existing bond bar:
+# echo -bar > /sys/class/net/bonding_masters
+
+To show all existing bonds:
+# cat /sys/class/net/bonding_masters
+
+NOTE: due to 4K size limitation of sysfs files, this list may be
+truncated if you have more than a few hundred bonds.  This is unlikely
+to occur under normal operating conditions.
+
+Adding and Removing Slaves
+--------------------------
+       Interfaces may be enslaved to a bond using the file
+/sys/class/net/<bond>/bonding/slaves.  The semantics for this file
+are the same as for the bonding_masters file.
+
+To enslave interface eth0 to bond bond0:
+# ifconfig bond0 up
+# echo +eth0 > /sys/class/net/bond0/bonding/slaves
+
+To free slave eth0 from bond bond0:
+# echo -eth0 > /sys/class/net/bond0/bonding/slaves
+
+       NOTE: The bond must be up before slaves can be added.  All
+slaves are freed when the interface is brought down.
+
+       When an interface is enslaved to a bond, symlinks between the
+two are created in the sysfs filesystem.  In this case, you would get
+/sys/class/net/bond0/slave_eth0 pointing to /sys/class/net/eth0, and
+/sys/class/net/eth0/master pointing to /sys/class/net/bond0.
+
+       This means that you can tell quickly whether or not an
+interface is enslaved by looking for the master symlink.  Thus:
+# echo -eth0 > /sys/class/net/eth0/master/bonding/slaves
+will free eth0 from whatever bond it is enslaved to, regardless of
+the name of the bond interface.
+
+Changing a Bond's Configuration
+-------------------------------
+       Each bond may be configured individually by manipulating the
+files located in /sys/class/net/<bond name>/bonding
+
+       The names of these files correspond directly with the command-
+line parameters described elsewhere in in this file, and, with the
+exception of arp_ip_target, they accept the same values.  To see the
+current setting, simply cat the appropriate file.
+
+       A few examples will be given here; for specific usage
+guidelines for each parameter, see the appropriate section in this
+document.
+
+To configure bond0 for balance-alb mode:
+# ifconfig bond0 down
+# echo 6 > /sys/class/net/bond0/bonding/mode
+ - or -
+# echo balance-alb > /sys/class/net/bond0/bonding/mode
+       NOTE: The bond interface must be down before the mode can be
+changed.
+
+To enable MII monitoring on bond0 with a 1 second interval:
+# echo 1000 > /sys/class/net/bond0/bonding/miimon
+       NOTE: If ARP monitoring is enabled, it will disabled when MII
+monitoring is enabled, and vice-versa.
+
+To add ARP targets:
+# echo +192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
+# echo +192.168.0.101 > /sys/class/net/bond0/bonding/arp_ip_target
+       NOTE:  up to 10 target addresses may be specified.
+
+To remove an ARP target:
+# echo -192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
+
+Example Configuration
+---------------------
+       We begin with the same example that is shown in section 3.3,
+executed with sysfs, and without using ifenslave.
+
+       To make a simple bond of two e100 devices (presumed to be eth0
+and eth1), and have it persist across reboots, edit the appropriate
+file (/etc/init.d/boot.local or /etc/rc.d/rc.local), and add the
+following:
+
+modprobe bonding
+modprobe e100
+echo balance-alb > /sys/class/net/bond0/bonding/mode
+ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up
+echo 100 > /sys/class/net/bond0/bonding/miimon
+echo +eth0 > /sys/class/net/bond0/bonding/slaves
+echo +eth1 > /sys/class/net/bond0/bonding/slaves
+
+       To add a second bond, with two e1000 interfaces in
+active-backup mode, using ARP monitoring, add the following lines to
+your init script:
+
+modprobe e1000
+echo +bond1 > /sys/class/net/bonding_masters
+echo active-backup > /sys/class/net/bond1/bonding/mode
+ifconfig bond1 192.168.2.1 netmask 255.255.255.0 up
+echo +192.168.2.100 /sys/class/net/bond1/bonding/arp_ip_target
+echo 2000 > /sys/class/net/bond1/bonding/arp_interval
+echo +eth2 > /sys/class/net/bond1/bonding/slaves
+echo +eth3 > /sys/class/net/bond1/bonding/slaves
+
 
-5. Querying Bonding Configuration 
+4. Querying Bonding Configuration 
 =================================
 
-5.1 Bonding Configuration
+4.1 Bonding Configuration
 -------------------------
 
        Each bonding device has a read-only file residing in the
@@ -923,7 +1058,7 @@ generally as follows:
        The precise format and contents will change depending upon the
 bonding configuration, state, and version of the bonding driver.
 
-5.2 Network configuration
+4.2 Network configuration
 -------------------------
 
        The network configuration can be inspected using the ifconfig
@@ -958,7 +1093,7 @@ eth1      Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4
           collisions:0 txqueuelen:100
           Interrupt:9 Base address:0x1400
 
-6. Switch Configuration
+5. Switch Configuration
 =======================
 
        For this section, "switch" refers to whatever system the
@@ -991,7 +1126,7 @@ transmit policy for an EtherChannel group; all three will interoperate
 with another EtherChannel group.
 
 
-7. 802.1q VLAN Support
+6. 802.1q VLAN Support
 ======================
 
        It is possible to configure VLAN devices over a bond interface
@@ -1042,7 +1177,7 @@ underlying device -- i.e. the bonding interface -- to promiscuous
 mode, which might not be what you want.
 
 
-8. Link Monitoring
+7. Link Monitoring
 ==================
 
        The bonding driver at present supports two schemes for
@@ -1053,7 +1188,7 @@ monitor.
 bonding driver itself, it is not possible to enable both ARP and MII
 monitoring simultaneously.
 
-8.1 ARP Monitor Operation
+7.1 ARP Monitor Operation
 -------------------------
 
        The ARP monitor operates as its name suggests: it sends ARP
@@ -1071,7 +1206,7 @@ those slaves will stay down.  If networking monitoring (tcpdump, etc)
 shows the ARP requests and replies on the network, then it may be that
 your device driver is not updating last_rx and trans_start.
 
-8.2 Configuring Multiple ARP Targets
+7.2 Configuring Multiple ARP Targets
 ------------------------------------
 
        While ARP monitoring can be done with just one target, it can
@@ -1094,7 +1229,7 @@ alias bond0 bonding
 options bond0 arp_interval=60 arp_ip_target=192.168.0.100
 
 
-8.3 MII Monitor Operation
+7.3 MII Monitor Operation
 -------------------------
 
        The MII monitor monitors only the carrier state of the local
@@ -1120,14 +1255,14 @@ does not support or had some error in processing both the MII register
 and ethtool requests), then the MII monitor will assume the link is
 up.
 
-9. Potential Sources of Trouble
+8. Potential Sources of Trouble
 ===============================
 
-9.1 Adventures in Routing
+8.1 Adventures in Routing
 -------------------------
 
        When bonding is configured, it is important that the slave
-devices not have routes that supercede routes of the master (or,
+devices not have routes that supersede routes of the master (or,
 generally, not have routes at all).  For example, suppose the bonding
 device bond0 has two slaves, eth0 and eth1, and the routing table is
 as follows:
@@ -1154,11 +1289,11 @@ by the state of the routing table.
 
        The solution here is simply to insure that slaves do not have
 routes of their own, and if for some reason they must, those routes do
-not supercede routes of their master.  This should generally be the
+not supersede routes of their master.  This should generally be the
 case, but unusual configurations or errant manual or automatic static
 route additions may cause trouble.
 
-9.2 Ethernet Device Renaming
+8.2 Ethernet Device Renaming
 ----------------------------
 
        On systems with network configuration scripts that do not
@@ -1207,7 +1342,7 @@ modprobe with --ignore-install to cause the normal action to then take
 place.  Full documentation on this can be found in the modprobe.conf
 and modprobe manual pages.
 
-9.3. Painfully Slow Or No Failed Link Detection By Miimon
+8.3. Painfully Slow Or No Failed Link Detection By Miimon
 ---------------------------------------------------------
 
        By default, bonding enables the use_carrier option, which
@@ -1235,7 +1370,7 @@ carrier state.  It has no way to determine the state of devices on or
 beyond other ports of a switch, or if a switch is refusing to pass
 traffic while still maintaining carrier on.
 
-10. SNMP agents
+9. SNMP agents
 ===============
 
        If running SNMP agents, the bonding driver should be loaded
@@ -1281,7 +1416,7 @@ ifDescr, the association between the IP address and IfIndex remains
 and SNMP functions such as Interface_Scan_Next will report that
 association.
 
-11. Promiscuous mode
+10. Promiscuous mode
 ====================
 
        When running network monitoring tools, e.g., tcpdump, it is
@@ -1308,7 +1443,7 @@ sending to peers that are unassigned or if the load is unbalanced.
 the active slave changes (e.g., due to a link failure), the
 promiscuous setting will be propagated to the new active slave.
 
-12. Configuring Bonding for High Availability
+11. Configuring Bonding for High Availability
 =============================================
 
        High Availability refers to configurations that provide
@@ -1318,7 +1453,7 @@ goal is to provide the maximum availability of network connectivity
 (i.e., the network always works), even though other configurations
 could provide higher throughput.
 
-12.1 High Availability in a Single Switch Topology
+11.1 High Availability in a Single Switch Topology
 --------------------------------------------------
 
        If two hosts (or a host and a single switch) are directly
@@ -1332,7 +1467,7 @@ the load will be rebalanced across the remaining devices.
        See Section 13, "Configuring Bonding for Maximum Throughput"
 for information on configuring bonding with one peer device.
 
-12.2 High Availability in a Multiple Switch Topology
+11.2 High Availability in a Multiple Switch Topology
 ----------------------------------------------------
 
        With multiple switches, the configuration of bonding and the
@@ -1359,7 +1494,7 @@ switches (ISL, or inter switch link), and multiple ports connecting to
 the outside world ("port3" on each switch).  There is no technical
 reason that this could not be extended to a third switch.
 
-12.2.1 HA Bonding Mode Selection for Multiple Switch Topology
+11.2.1 HA Bonding Mode Selection for Multiple Switch Topology
 -------------------------------------------------------------
 
        In a topology such as the example above, the active-backup and
@@ -1381,7 +1516,7 @@ broadcast: This mode is really a special purpose mode, and is suitable
        necessary for some specific one-way traffic to reach both
        independent networks, then the broadcast mode may be suitable.
 
-12.2.2 HA Link Monitoring Selection for Multiple Switch Topology
+11.2.2 HA Link Monitoring Selection for Multiple Switch Topology
 ----------------------------------------------------------------
 
        The choice of link monitoring ultimately depends upon your
@@ -1402,10 +1537,10 @@ regardless of which switch is active, the ARP monitor has a suitable
 target to query.
 
 
-13. Configuring Bonding for Maximum Throughput
+12. Configuring Bonding for Maximum Throughput
 ==============================================
 
-13.1 Maximizing Throughput in a Single Switch Topology
+12.1 Maximizing Throughput in a Single Switch Topology
 ------------------------------------------------------
 
        In a single switch configuration, the best method to maximize
@@ -1476,7 +1611,7 @@ destination to make load balancing decisions.  The behavior of each
 mode is described below.
 
 
-13.1.1 MT Bonding Mode Selection for Single Switch Topology
+12.1.1 MT Bonding Mode Selection for Single Switch Topology
 -----------------------------------------------------------
 
        This configuration is the easiest to set up and to understand,
@@ -1607,7 +1742,7 @@ balance-alb: This mode is everything that balance-tlb is, and more.
        device driver must support changing the hardware address while
        the device is open.
 
-13.1.2 MT Link Monitoring for Single Switch Topology
+12.1.2 MT Link Monitoring for Single Switch Topology
 ----------------------------------------------------
 
        The choice of link monitoring may largely depend upon which
@@ -1616,7 +1751,7 @@ support the use of the ARP monitor, and are thus restricted to using
 the MII monitor (which does not provide as high a level of end to end
 assurance as the ARP monitor).
 
-13.2 Maximum Throughput in a Multiple Switch Topology
+12.2 Maximum Throughput in a Multiple Switch Topology
 -----------------------------------------------------
 
        Multiple switches may be utilized to optimize for throughput
@@ -1651,7 +1786,7 @@ a single 72 port switch.
 can be equipped with an additional network device connected to an
 external network; this host then additionally acts as a gateway.
 
-13.2.1 MT Bonding Mode Selection for Multiple Switch Topology
+12.2.1 MT Bonding Mode Selection for Multiple Switch Topology
 -------------------------------------------------------------
 
        In actual practice, the bonding mode typically employed in
@@ -1664,7 +1799,7 @@ packets has arrived).  When employed in this fashion, the balance-rr
 mode allows individual connections between two hosts to effectively
 utilize greater than one interface's bandwidth.
 
-13.2.2 MT Link Monitoring for Multiple Switch Topology
+12.2.2 MT Link Monitoring for Multiple Switch Topology
 ------------------------------------------------------
 
        Again, in actual practice, the MII monitor is most often used
@@ -1674,10 +1809,10 @@ advantages over the MII monitor are mitigated by the volume of probes
 needed as the number of systems involved grows (remember that each
 host in the network is configured with bonding).
 
-14. Switch Behavior Issues
+13. Switch Behavior Issues
 ==========================
 
-14.1 Link Establishment and Failover Delays
+13.1 Link Establishment and Failover Delays
 -------------------------------------------
 
        Some switches exhibit undesirable behavior with regard to the
@@ -1712,7 +1847,7 @@ switches take a long time to go into backup mode, it may be desirable
 to not activate a backup interface immediately after a link goes down.
 Failover may be delayed via the downdelay bonding module option.
 
-14.2 Duplicated Incoming Packets
+13.2 Duplicated Incoming Packets
 --------------------------------
 
        It is not uncommon to observe a short burst of duplicated
@@ -1751,14 +1886,14 @@ behavior, it can be induced by clearing the MAC forwarding table (on
 most Cisco switches, the privileged command "clear mac address-table
 dynamic" will accomplish this).
 
-15. Hardware Specific Considerations
+14. Hardware Specific Considerations
 ====================================
 
        This section contains additional information for configuring
 bonding on specific hardware platforms, or for interfacing bonding
 with particular switches or other devices.
 
-15.1 IBM BladeCenter
+14.1 IBM BladeCenter
 --------------------
 
        This applies to the JS20 and similar systems.
@@ -1861,7 +1996,7 @@ bonding driver.
 avoid fail-over delay issues when using bonding.
 
        
-16. Frequently Asked Questions
+15. Frequently Asked Questions
 ==============================
 
 1.  Is it SMP safe?
@@ -1925,7 +2060,7 @@ not have special switch requirements, but do need device drivers that
 support specific features (described in the appropriate section under
 module parameters, above).
 
-       In 802.3ad mode, it works with with systems that support IEEE
+       In 802.3ad mode, it works with systems that support IEEE
 802.3ad Dynamic Link Aggregation.  Most managed and many unmanaged
 switches currently available support 802.3ad.
 
index f12007b80a466e33fad7efb03dfe7e4f20913462..d46338af6002997b0593d4875a6aee825c77126f 100644 (file)
@@ -362,6 +362,13 @@ tcp_workaround_signed_windows - BOOLEAN
        not receive a window scaling option from them.
        Default: 0
 
+tcp_slow_start_after_idle - BOOLEAN
+       If set, provide RFC2861 behavior and time out the congestion
+       window after an idle period.  An idle period is defined at
+       the current RTO.  If unset, the congestion window will not
+       be timed out after an idle period.
+       Default: 1
+
 IP Variables:
 
 ip_local_port_range - 2 INTEGERS
index 3c0a5ba614d7c39146668f0b990e3fab03cceb06..847cedb238f6c0ed24ad6568b1d440bc3843fc6f 100644 (file)
@@ -42,9 +42,9 @@ dev->get_stats:
        Context: nominally process, but don't sleep inside an rwlock
 
 dev->hard_start_xmit:
-       Synchronization: dev->xmit_lock spinlock.
+       Synchronization: netif_tx_lock spinlock.
        When the driver sets NETIF_F_LLTX in dev->features this will be
-       called without holding xmit_lock. In this case the driver 
+       called without holding netif_tx_lock. In this case the driver
        has to lock by itself when needed. It is recommended to use a try lock
        for this and return -1 when the spin lock fails. 
        The locking there should also properly protect against 
@@ -62,12 +62,12 @@ dev->hard_start_xmit:
          Only valid when NETIF_F_LLTX is set.
 
 dev->tx_timeout:
-       Synchronization: dev->xmit_lock spinlock.
+       Synchronization: netif_tx_lock spinlock.
        Context: BHs disabled
        Notes: netif_queue_stopped() is guaranteed true
 
 dev->set_multicast_list:
-       Synchronization: dev->xmit_lock spinlock.
+       Synchronization: netif_tx_lock spinlock.
        Context: BHs disabled
 
 dev->poll:
index df82116a9f261c35998c3bb5a69eb1a38c8d83d1..88ad615dd338d75e2b282422c8f2d6f7f3af80b7 100644 (file)
@@ -214,12 +214,13 @@ hardware.
        The interaction of the iflag bits is as follows (parity error
        given as an example):
        Parity error    INPCK   IGNPAR
-       None            n/a     n/a     character received
-       Yes             n/a     0       character discarded
-       Yes             0       1       character received, marked as
+       n/a             0       n/a     character received, marked as
                                        TTY_NORMAL
-       Yes             1       1       character received, marked as
+       None            1       n/a     character received, marked as
+                                       TTY_NORMAL
+       Yes             1       0       character received, marked as
                                        TTY_PARITY
+       Yes             1       1       character discarded
 
        Other flags may be used (eg, xon/xoff characters) if your
        hardware supports hardware "soft" flow control.
index bd10b2af2223f081f58f58540b3fa939c201b526..ce37c4b1ef94110c28f1a8a92aacbc2cb1a3e937 100644 (file)
@@ -565,7 +565,19 @@ BROADBAND PROCESSOR ARCHITECTURE
 P:     Arnd Bergmann
 M:     arnd@arndb.de
 L:     linuxppc-dev@ozlabs.org
-W:     http://linuxppc64.org
+W:     http://www.penguinppc.org/ppc64/
+S:     Supported
+
+BROADCOM BNX2 GIGABIT ETHERNET DRIVER
+P:     Michael Chan
+M:     mchan@broadcom.com
+L:     netdev@vger.kernel.org
+S:     Supported
+
+BROADCOM TG3 GIGABIT ETHERNET DRIVER
+P:     Michael Chan
+M:     mchan@broadcom.com
+L:     netdev@vger.kernel.org
 S:     Supported
 
 BTTV VIDEO4LINUX DRIVER
@@ -1413,6 +1425,8 @@ P:        Jesse Brandeburg
 M:     jesse.brandeburg@intel.com
 P:     Jeff Kirsher
 M:     jeffrey.t.kirsher@intel.com
+P:     Auke Kok
+M:     auke-jan.h.kok@intel.com
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
@@ -1425,6 +1439,8 @@ P:        Jesse Brandeburg
 M:     jesse.brandeburg@intel.com
 P:     Jeff Kirsher
 M:     jeffrey.t.kirsher@intel.com
+P:     Auke Kok
+M:     auke-jan.h.kok@intel.com
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
@@ -1437,6 +1453,8 @@ P:        John Ronciak
 M:     john.ronciak@intel.com
 P:     Jesse Brandeburg
 M:     jesse.brandeburg@intel.com
+P:     Auke Kok
+M:     auke-jan.h.kok@intel.com
 W:     http://sourceforge.net/projects/e1000/
 S:     Supported
 
@@ -1716,7 +1734,7 @@ M:        paulus@au.ibm.com
 P:     Anton Blanchard
 M:     anton@samba.org
 M:     anton@au.ibm.com
-W:     http://linuxppc64.org
+W:     http://www.penguinppc.org/ppc64/
 L:     linuxppc-dev@ozlabs.org
 S:     Supported
 
@@ -1825,12 +1843,12 @@ S:     linux-scsi@vger.kernel.org
 W:     http://megaraid.lsilogic.com
 S:     Maintained
 
-MEMORY TECHNOLOGY DEVICES
+MEMORY TECHNOLOGY DEVICES (MTD)
 P:     David Woodhouse
 M:     dwmw2@infradead.org
 W:     http://www.linux-mtd.infradead.org/
 L:     linux-mtd@lists.infradead.org
-T:     git kernel.org:/pub/scm/linux/kernel/git/tglx/mtd-2.6.git
+T:     git git://git.infradead.org/mtd-2.6.git
 S:     Maintained
 
 MICROTEK X6 SCANNER
@@ -1877,6 +1895,11 @@ L:       linux-kernel@vger.kernel.org
 W:     http://www.atnf.csiro.au/~rgooch/linux/kernel-patches.html
 S:     Maintained
 
+MULTIMEDIA CARD (MMC) SUBSYSTEM
+P:     Russell King
+M:     rmk+mmc@arm.linux.org.uk
+S:     Maintained
+
 MULTISOUND SOUND DRIVER
 P:     Andrew Veliath
 M:     andrewtv@usa.net
@@ -1899,6 +1922,12 @@ M:       James.Bottomley@HansenPartnership.com
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 
+NETEM NETWORK EMULATOR
+P:     Stephen Hemminger
+M:     shemminger@osdl.org
+L:     netem@osdl.org
+S:     Maintained
+
 NETFILTER/IPTABLES/IPCHAINS
 P:     Rusty Russell
 P:     Marc Boucher
index 435d209f42d817381f6da6734c776a2066f276f7..1700d3f6ea22a6ac842efb5a41eb5b74ec19f412 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 17
-EXTRAVERSION =-rc5
-NAME=Lordi Rules
+EXTRAVERSION =
+NAME=Crazed Snow-Weasel
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index 8290b69da20214a7e19fedd0fc047d33d5d82ba7..213c7850d5fb9639a007616b7357fe93f5ae64e8 100644 (file)
@@ -453,7 +453,7 @@ config ALPHA_IRONGATE
 
 config GENERIC_HWEIGHT
        bool
-       default y if !ALPHA_EV6 && !ALPHA_EV67
+       default y if !ALPHA_EV67
 
 config ALPHA_AVANTI
        bool
index c645c5e14786fdd17efddf40bb3ae2b40524ffd8..2b245ad731ee8f85a4e02ce3de100713760a414c 100644 (file)
@@ -182,7 +182,6 @@ EXPORT_SYMBOL(smp_num_cpus);
 EXPORT_SYMBOL(smp_call_function);
 EXPORT_SYMBOL(smp_call_function_on_cpu);
 EXPORT_SYMBOL(_atomic_dec_and_lock);
-EXPORT_SYMBOL(cpu_present_mask);
 #endif /* CONFIG_SMP */
 
 /*
index 9924fd07743abfd5bb4cda9e78ac3e58ca72a9d7..c760a831fd1a250d45bdc2e6e70f6f5c243fd3c1 100644 (file)
@@ -94,7 +94,7 @@ common_shutdown_1(void *generic_ptr)
        if (cpuid != boot_cpuid) {
                flags |= 0x00040000UL; /* "remain halted" */
                *pflags = flags;
-               clear_bit(cpuid, &cpu_present_mask);
+               cpu_clear(cpuid, cpu_present_map);
                halt();
        }
 #endif
@@ -120,8 +120,8 @@ common_shutdown_1(void *generic_ptr)
 
 #ifdef CONFIG_SMP
        /* Wait for the secondaries to halt. */
-       cpu_clear(boot_cpuid, cpu_possible_map);
-       while (cpus_weight(cpu_possible_map))
+       cpu_clear(boot_cpuid, cpu_present_map);
+       while (cpus_weight(cpu_present_map))
                barrier();
 #endif
 
index 185255416e8538c22384ae89491720834aa6fcc1..4dc273e537fdd38830deb0ede8a3b560827a8ab0 100644 (file)
@@ -68,7 +68,6 @@ enum ipi_message_type {
 static int smp_secondary_alive __initdata = 0;
 
 /* Which cpus ids came online.  */
-cpumask_t cpu_present_mask;
 cpumask_t cpu_online_map;
 
 EXPORT_SYMBOL(cpu_online_map);
@@ -439,7 +438,7 @@ setup_smp(void)
                        if ((cpu->flags & 0x1cc) == 0x1cc) {
                                smp_num_probed++;
                                /* Assume here that "whami" == index */
-                               cpu_set(i, cpu_present_mask);
+                               cpu_set(i, cpu_present_map);
                                cpu->pal_revision = boot_cpu_palrev;
                        }
 
@@ -450,11 +449,10 @@ setup_smp(void)
                }
        } else {
                smp_num_probed = 1;
-               cpu_set(boot_cpuid, cpu_present_mask);
        }
 
-       printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
-              smp_num_probed, cpu_possible_map.bits[0]);
+       printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_map = %lx\n",
+              smp_num_probed, cpu_present_map.bits[0]);
 }
 
 /*
@@ -473,7 +471,7 @@ smp_prepare_cpus(unsigned int max_cpus)
 
        /* Nothing to do on a UP box, or when told not to.  */
        if (smp_num_probed == 1 || max_cpus == 0) {
-               cpu_present_mask = cpumask_of_cpu(boot_cpuid);
+               cpu_present_map = cpumask_of_cpu(boot_cpuid);
                printk(KERN_INFO "SMP mode deactivated.\n");
                return;
        }
@@ -486,10 +484,6 @@ smp_prepare_cpus(unsigned int max_cpus)
 void __devinit
 smp_prepare_boot_cpu(void)
 {
-       /*
-        * Mark the boot cpu (current cpu) as online
-        */ 
-       cpu_set(smp_processor_id(), cpu_online_map);
 }
 
 int __devinit
index 5f84417eeb7bee9502d0da72805bc895b864ca0f..2551fb49ae099150561407adc726e410b8e03c9f 100644 (file)
@@ -66,7 +66,7 @@ titan_update_irq_hw(unsigned long mask)
        register int bcpu = boot_cpuid;
 
 #ifdef CONFIG_SMP
-       cpumask_t cpm = cpu_present_mask;
+       cpumask_t cpm = cpu_present_map;
        volatile unsigned long *dim0, *dim1, *dim2, *dim3;
        unsigned long mask0, mask1, mask2, mask3, dummy;
 
index 08b7cc900cae5cd87c817b4c54d345c866d9182c..f47cf9af3bc8cd9061e8d2fe80958764ddcc5799 100644 (file)
@@ -270,6 +270,11 @@ config ARCH_AT91RM9200
          Say Y here if you intend to run this kernel on an Atmel
          AT91RM9200-based board.
 
+config ARCH_PNX4008
+       bool "Philips Nexperia PNX4008 Mobile"
+       help
+         This enables support for Philips PNX4008 mobile platform.
+
 endchoice
 
 source "arch/arm/mach-clps711x/Kconfig"
index 5d3acff8c596e0c0670d7d956379d860e9591ba7..d22f38b957db9c825e5cae7bec8bee90357efa06 100644 (file)
@@ -101,7 +101,7 @@ config DEBUG_S3C2410_UART
        help
          Choice for UART for kernel low-level using S3C2410 UARTS,
          should be between zero and two. The port must have been
-         initalised by the boot-loader before use.
+         initialised by the boot-loader before use.
 
          The uncompressor code port configuration is now handled
          by CONFIG_S3C2410_LOWLEVEL_UART_PORT.
index 6f8e84c1c1f2330d207951bdb8098cb99d11b15c..6c97aa70d3bc79696c6479ba358fc41d1d8208d2 100644 (file)
@@ -116,6 +116,7 @@ endif
  machine-$(CONFIG_ARCH_REALVIEW)   := realview
  machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200
  machine-$(CONFIG_ARCH_EP93XX)     := ep93xx
+ machine-$(CONFIG_ARCH_PNX4008)    := pnx4008
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
index b56f5e691d65062060db1f324737952517047c47..23016f6aa645f405dcb9108240f1fad80f4ac4b9 100644 (file)
@@ -605,8 +605,8 @@ proc_types:
                b       __armv4_mmu_cache_off
                b       __armv4_mmu_cache_flush
 
-               .word   0x00070000              @ ARMv6
-               .word   0x000f0000
+               .word   0x0007b000              @ ARMv6
+               .word   0x0007f000
                b       __armv4_mmu_cache_on
                b       __armv4_mmu_cache_off
                b       __armv6_mmu_cache_flush
index 67eaa26c2647ea83969238ddf26c941a813d0e72..bf9cf9c6d2dfb7770e0ac2b35fee5e3a87e1b8f2 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:06:33 2005
+# Linux kernel version: 2.6.12
+# Thu Nov  3 14:15:32 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -17,6 +17,7 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -36,6 +37,8 @@ CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 # CONFIG_EPOLL is not set
@@ -71,6 +74,7 @@ CONFIG_BASE_SMALL=0
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7952X is not set
 CONFIG_ARCH_LH7A40X=y
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_VERSATILE is not set
@@ -84,6 +88,7 @@ CONFIG_ARCH_LH7A40X=y
 CONFIG_MACH_LPD7A400=y
 # CONFIG_MACH_LPD7A404 is not set
 CONFIG_ARCH_LH7A400=y
+CONFIG_LPD7A40X_CPLD_SSP=y
 # CONFIG_LH7A40X_CONTIGMEM is not set
 # CONFIG_LH7A40X_ONE_BANK_PER_NODE is not set
 
@@ -110,6 +115,8 @@ CONFIG_ARM_THUMB=y
 #
 # Bus support
 #
+CONFIG_ARM_AMBA=y
+CONFIG_ISA_DMA_API=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -119,6 +126,7 @@ CONFIG_ARM_THUMB=y
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 CONFIG_PREEMPT=y
 CONFIG_DISCONTIGMEM=y
 CONFIG_ALIGNMENT_TRAP=y
@@ -175,7 +183,7 @@ CONFIG_MTD=y
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
 
 #
@@ -217,7 +225,10 @@ CONFIG_MTD_CFI_UTIL=y
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x00000000
+CONFIG_MTD_PHYSMAP_LEN=0x04000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_EDB7312 is not set
 
@@ -254,7 +265,6 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -288,13 +298,15 @@ CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_POLL=y
 
 #
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
-# CONFIG_IDE_ARM is not set
+CONFIG_IDE_ARM=y
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -302,7 +314,37 @@ CONFIG_IDE_GENERIC=y
 #
 # SCSI device support
 #
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -331,7 +373,6 @@ CONFIG_NET=y
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -438,13 +479,10 @@ CONFIG_INPUT=y
 #
 # Userland interfaces
 #
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
 
 #
@@ -453,7 +491,13 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # 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_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_ADS7843_LH7=y
+CONFIG_HAS_TOUCHSCREEN_ADS7843_LH7=y
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -461,7 +505,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -479,6 +522,8 @@ CONFIG_HW_CONSOLE=y
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_LH7A40X=y
@@ -510,7 +555,6 @@ CONFIG_RTC=y
 #
 # TPM devices
 #
-# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -534,18 +578,73 @@ CONFIG_RTC=y
 #
 # Graphics support
 #
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT=y
+# CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ64D343 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ10D368 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_RTCTIMER is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_AC97_CODEC=y
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_LH7A40X_AC97=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
 
 #
 # USB support
index 208d591ebfcec722567c0475da4bad8f2b6efea1..3a57be32e849d1ec89f29131c8e25d5f1c6d78be 100644 (file)
@@ -1,58 +1,81 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:14:08 2005
+# Linux kernel version: 2.6.16
+# Thu Mar 23 17:50:31 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
-CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 # CONFIG_EPOLL is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
 
 #
 # Loadable module support
 #
 # CONFIG_MODULES is not set
 
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
 #
 # System Type
 #
@@ -71,11 +94,15 @@ CONFIG_BASE_SMALL=0
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7952X is not set
 CONFIG_ARCH_LH7A40X=y
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
 
 #
 # LH7A40X Implementations
@@ -110,6 +137,7 @@ CONFIG_ARM_THUMB=y
 #
 # Bus support
 #
+CONFIG_ARM_AMBA=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -120,7 +148,18 @@ CONFIG_ARM_THUMB=y
 # Kernel Features
 #
 CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_AEABI is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -154,6 +193,84 @@ CONFIG_BINFMT_ELF=y
 # Power management options
 #
 # CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -167,6 +284,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
 #
 # Memory Technology Devices (MTD)
 #
@@ -175,7 +297,7 @@ CONFIG_MTD=y
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
 
 #
@@ -186,6 +308,7 @@ CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -211,15 +334,18 @@ 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_XIP is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x00000000
+CONFIG_MTD_PHYSMAP_LEN=0x04000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
 # CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -242,6 +368,11 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # CONFIG_MTD_NAND is not set
 
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
 #
 # Parallel port support
 #
@@ -254,7 +385,6 @@ CONFIG_MTD_CFI_UTIL=y
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -262,16 +392,7 @@ CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -291,12 +412,13 @@ CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_POLL=y
 
 #
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
-# CONFIG_IDE_ARM is not set
+CONFIG_IDE_ARM=y
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -304,6 +426,7 @@ CONFIG_IDE_GENERIC=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 
@@ -315,6 +438,7 @@ CONFIG_SCSI=y
 # 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
@@ -329,10 +453,12 @@ CONFIG_SCSI=y
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
 #
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_DEBUG is not set
 
@@ -344,6 +470,7 @@ CONFIG_SCSI=y
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -354,82 +481,26 @@ CONFIG_SCSI=y
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 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=y
+# CONFIG_DM9000 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -456,6 +527,8 @@ CONFIG_SMC91X=y
 # 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
@@ -470,10 +543,13 @@ CONFIG_INPUT=y
 #
 # Userland interfaces
 #
-# CONFIG_INPUT_MOUSEDEV is not set
+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_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
 
 #
@@ -482,7 +558,13 @@ CONFIG_INPUT=y
 # 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_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_ADC_LH7=y
+CONFIG_HAS_TOUCHSCREEN_ADC_LH7=y
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -490,7 +572,6 @@ CONFIG_INPUT=y
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -508,6 +589,8 @@ CONFIG_HW_CONSOLE=y
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_LH7A40X=y
@@ -533,23 +616,46 @@ CONFIG_RTC=y
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
 #
 # CONFIG_I2C is not set
 
+#
+# 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_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
 #
 # Misc devices
 #
 
+#
+# Multimedia Capabilities Port drivers
+#
+
 #
 # Multimedia devices
 #
@@ -563,18 +669,83 @@ CONFIG_RTC=y
 #
 # Graphics support
 #
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT=y
+# CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ64D343 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ10D368 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41 is not set
+# CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE is not set
+# CONFIG_FB_ARMCLCD_HITACHI is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_RTCTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_ARMAACI is not set
+CONFIG_SND_LH7A40X_AC97=y
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
 
 #
 # USB support
@@ -595,6 +766,7 @@ CONFIG_USB_DEVICEFS=y
 #
 # 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
@@ -603,16 +775,19 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# 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_RW_DETECT is not set
 CONFIG_USB_STORAGE_DATAFAB=y
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -621,22 +796,32 @@ CONFIG_USB_STORAGE_DATAFAB=y
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_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
@@ -686,16 +871,33 @@ CONFIG_USB_MON=y
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
 # USB Gadget Support
 #
-# CONFIG_USB_GADGET is not set
+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_LH7=y
+CONFIG_USB_LH7=y
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=y
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
 
 #
 # MMC/SD Card support
@@ -707,6 +909,7 @@ CONFIG_USB_MON=y
 #
 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
@@ -716,17 +919,17 @@ CONFIG_JBD=y
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=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
@@ -749,12 +952,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 #
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -769,8 +971,8 @@ CONFIG_RAMFS=y
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -787,12 +989,14 @@ CONFIG_CRAMFS=y
 #
 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 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -801,6 +1005,7 @@ CONFIG_SUNRPC=y
 # 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
@@ -820,6 +1025,7 @@ CONFIG_MSDOS_PARTITION=y
 # 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
 
 #
@@ -875,19 +1081,24 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
 CONFIG_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
@@ -912,6 +1123,7 @@ CONFIG_DEBUG_ERRORS=y
 # 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
diff --git a/arch/arm/configs/pnx4008_defconfig b/arch/arm/configs/pnx4008_defconfig
new file mode 100644 (file)
index 0000000..8a078d4
--- /dev/null
@@ -0,0 +1,2072 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc1
+# Thu Apr  6 17:05:58 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=m
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE 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"
+
+#
+# System Type
+#
+# 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_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX 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_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
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_PNX4008=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# 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=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# 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_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=m
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+# CONFIG_BRIDGE_EBT_ULOG is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+CONFIG_ATM=y
+CONFIG_ATM_CLIP=y
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=y
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+# CONFIG_NET_DIVERT is not set
+CONFIG_ECONET=m
+CONFIG_ECONET_AUNUDP=y
+CONFIG_ECONET_NATIVE=y
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+# CONFIG_AX25_DAMA_SLAVE is not set
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+CONFIG_BAYCOM_SER_FDX=m
+CONFIG_BAYCOM_SER_HDX=m
+CONFIG_BAYCOM_PAR=m
+CONFIG_BAYCOM_EPP=m
+CONFIG_YAM=m
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+# CONFIG_TOIM3232_DONGLE is not set
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+CONFIG_IRPORT_SIR=m
+
+#
+# Old Serial dongle support
+#
+# CONFIG_DONGLE_OLD is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+# CONFIG_BT_HCIBPA10X is not set
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+# CONFIG_IEEE80211_CRYPT_WEP is not set
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+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
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# 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=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x4000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLKMTD=m
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+# CONFIG_MTD_DOCPROBE_ADVANCED is not set
+CONFIG_MTD_DOCPROBE_ADDRESS=0
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+# CONFIG_PARIDE_EPATC8 is not set
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# 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_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_IDETAPE=m
+CONFIG_BLK_DEV_IDEFLOPPY=m
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_DEBUG=m
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH 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=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+CONFIG_STRIP=m
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+CONFIG_PCMCIA_RAYCS=m
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+CONFIG_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_PCMCIA_SPECTRUM is not set
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+CONFIG_SYNCLINK_SYNCPPP=m
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=y
+CONFIG_HDLC_RAW_ETH=y
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+CONFIG_HDLC_X25=y
+CONFIG_DLCI=m
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+CONFIG_WAN_ROUTER_DRIVERS=y
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_SHAPER=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+CONFIG_ISDN_PPP_BSDCOMP=m
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+CONFIG_ISDN_X25=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+# CONFIG_HISAX_NO_SENDCOMPLETE is not set
+# CONFIG_HISAX_NO_LLC is not set
+# CONFIG_HISAX_NO_KEYPAD is not set
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_SX=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+CONFIG_HISAX_HFCUSB=m
+# CONFIG_HISAX_HFC4S8S is not set
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+# CONFIG_ISDN_DRV_GIGASET is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_TSDEV=m
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_KEYBOARD_NEWTON=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+# CONFIG_JOYSTICK_TWIDJOY is not set
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_COMPUTONE=m
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+CONFIG_DIGIEPCA=m
+CONFIG_MOXA_INTELLIO=m
+CONFIG_MOXA_SMARTIO=m
+# CONFIG_ISI is not set
+CONFIG_SYNCLINKMP=m
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+CONFIG_SX=m
+CONFIG_RIO=m
+CONFIG_RIO_OLDPCI=y
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_NVRAM=m
+CONFIG_DTLK=m
+CONFIG_R3964=m
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ISA=m
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+# CONFIG_SENSORS_PCA9539 is not set
+CONFIG_SENSORS_PCF8591=m
+# 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=m
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS9490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+# CONFIG_SENSORS_ADM9240 is not set
+CONFIG_SENSORS_ASB100=m
+# CONFIG_SENSORS_ATXP1 is not set
+CONFIG_SENSORS_DS1621=m
+# CONFIG_SENSORS_F71805F is not set
+CONFIG_SENSORS_FSCHER=m
+# CONFIG_SENSORS_FSCPOS is not set
+CONFIG_SENSORS_GL518SM=m
+# CONFIG_SENSORS_GL520SM is not set
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+# CONFIG_SENSORS_LM92 is not set
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SMSC47M1=m
+# CONFIG_SENSORS_SMSC47B397 is not set
+CONFIG_SENSORS_W83781D=m
+# CONFIG_SENSORS_W83792D is not set
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported USB Adapters
+#
+# CONFIG_DVB_USB is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+# CONFIG_DVB_CX24123 is not set
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+# CONFIG_DVB_S5H1420 is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+# CONFIG_DVB_ZL10353 is not set
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terresterial DTV) frontends
+#
+# CONFIG_DVB_NXT200X is not set
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+# CONFIG_DVB_BCM3510 is not set
+# CONFIG_DVB_LGDT330X is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+
+#
+# ALSA ARM devices
+#
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OBSOLETE_OSS_DRIVER is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_TVMIXER=m
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_BANDWIDTH=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_SL811_HCD=m
+# CONFIG_USB_SL811_CS is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=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_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+# CONFIG_USB_ACECAD is not set
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_MTOUCH=m
+# CONFIG_USB_ITMTOUCH is not set
+CONFIG_USB_EGALAX=m
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+# 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=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+# CONFIG_USB_SERIAL_GARMIN is not set
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+# CONFIG_USB_SERIAL_TI is not set
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+# CONFIG_USB_CXACRU is not set
+# CONFIG_USB_UEAGLEATM is not set
+# CONFIG_USB_XUSBATM is not set
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# 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 is not set
+CONFIG_USB_GADGET_DUMMY_HCD=y
+CONFIG_USB_DUMMY_HCD=m
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS_FS=m
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+CONFIG_VXFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+# CONFIG_NCPFS_SMALLDOS is not set
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+CONFIG_AFS_FS=m
+CONFIG_RXRPC=m
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+# CONFIG_ACORN_PARTITION_CUMANA is not set
+# CONFIG_ACORN_PARTITION_EESOX is not set
+CONFIG_ACORN_PARTITION_ICS=y
+# CONFIG_ACORN_PARTITION_ADFS is not set
+# CONFIG_ACORN_PARTITION_POWERTEC is not set
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+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_PREEMPT=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+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=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=m
+CONFIG_SECURITY_ROOTPLUG=m
+CONFIG_SECURITY_SECLVL=m
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
index dbcb11a31f78167b5577c55cfe4660c922043a20..b5bcebca1cd65ed9abaecf520a97eea535752564 100644 (file)
@@ -271,7 +271,7 @@ ENTRY(sys_call_table)
 @ r8 = syscall table
                .type   sys_syscall, #function
 sys_syscall:
-               eor     scno, r0, #__NR_OABI_SYSCALL_BASE
+               bic     scno, r0, #__NR_OABI_SYSCALL_BASE
                cmp     scno, #__NR_syscall - __NR_SYSCALL_BASE
                cmpne   scno, #NR_syscalls      @ check range
                stmloia sp, {r5, r6}            @ shuffle args
index 2d5896b36181fa8ceb9636240b8abd13a2a0992e..bcc19fbb32df41ecca339fa49a76a28f25782582 100644 (file)
@@ -342,10 +342,10 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
 
 #ifdef CONFIG_NO_IDLE_HZ
        if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) {
-               write_seqlock(&xtime_lock);
+               spin_lock(&system_timer->dyn_tick->lock);
                if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)
                        system_timer->dyn_tick->handler(irq, 0, regs);
-               write_sequnlock(&xtime_lock);
+               spin_unlock(&system_timer->dyn_tick->lock);
        }
 #endif
 
index d6bd435a685722c1c59a249fa9d89d260e36e3c4..9c12d4fefbd30c9aa969f1c189cbf9a3f4f1f8bd 100644 (file)
@@ -379,7 +379,7 @@ static int timer_dyn_tick_enable(void)
        int ret = -ENODEV;
 
        if (dyn_tick) {
-               write_seqlock_irqsave(&xtime_lock, flags);
+               spin_lock_irqsave(&dyn_tick->lock, flags);
                ret = 0;
                if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
                        ret = dyn_tick->enable();
@@ -387,7 +387,7 @@ static int timer_dyn_tick_enable(void)
                        if (ret == 0)
                                dyn_tick->state |= DYN_TICK_ENABLED;
                }
-               write_sequnlock_irqrestore(&xtime_lock, flags);
+               spin_unlock_irqrestore(&dyn_tick->lock, flags);
        }
 
        return ret;
@@ -400,7 +400,7 @@ static int timer_dyn_tick_disable(void)
        int ret = -ENODEV;
 
        if (dyn_tick) {
-               write_seqlock_irqsave(&xtime_lock, flags);
+               spin_lock_irqsave(&dyn_tick->lock, flags);
                ret = 0;
                if (dyn_tick->state & DYN_TICK_ENABLED) {
                        ret = dyn_tick->disable();
@@ -408,7 +408,7 @@ static int timer_dyn_tick_disable(void)
                        if (ret == 0)
                                dyn_tick->state &= ~DYN_TICK_ENABLED;
                }
-               write_sequnlock_irqrestore(&xtime_lock, flags);
+               spin_unlock_irqrestore(&dyn_tick->lock, flags);
        }
 
        return ret;
@@ -422,15 +422,20 @@ static int timer_dyn_tick_disable(void)
 void timer_dyn_reprogram(void)
 {
        struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
-       unsigned long next, seq;
+       unsigned long next, seq, flags;
 
-       if (dyn_tick && (dyn_tick->state & DYN_TICK_ENABLED)) {
+       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_timer_interrupt() - jiffies);
+                       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)
@@ -499,5 +504,10 @@ void __init time_init(void)
        if (system_timer->offset == NULL)
                system_timer->offset = dummy_gettimeoffset;
        system_timer->init();
+
+#ifdef CONFIG_NO_IDLE_HZ
+       if (system_timer->dyn_tick)
+               system_timer->dyn_tick->lock = SPIN_LOCK_UNLOCKED;
+#endif
 }
 
index 9be01b0c3f4876f19a0a23c8b093321598658978..e24566b88a783744059639191d35af51db83aba4 100644 (file)
@@ -111,21 +111,21 @@ static void __init ts72xx_map_io(void)
        }
 }
 
-static unsigned char ts72xx_rtc_readb(unsigned long addr)
+static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
 {
        __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
        return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
 }
 
-static void ts72xx_rtc_writeb(unsigned char value, unsigned long addr)
+static void ts72xx_rtc_writebyte(unsigned char value, unsigned long addr)
 {
        __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
        __raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
 }
 
 static struct m48t86_ops ts72xx_rtc_ops = {
-       .readb                  = ts72xx_rtc_readb,
-       .writeb                 = ts72xx_rtc_writeb,
+       .readbyte               = ts72xx_rtc_readbyte,
+       .writebyte              = ts72xx_rtc_writebyte,
 };
 
 static struct platform_device ts72xx_rtc_device = {
index eeb8a6d4a3999c1f9f605588ab0852e0b4b88621..a5de5f1da9f2e65dd0c83e99556eeed7f40807aa 100644 (file)
@@ -127,7 +127,7 @@ static void
 imx_gpio_ack_irq(unsigned int irq)
 {
        DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, irq);
-       ISR(IRQ_TO_REG(irq)) |= 1 << ((irq - IRQ_GPIOA(0)) % 32);
+       ISR(IRQ_TO_REG(irq)) = 1 << ((irq - IRQ_GPIOA(0)) % 32);
 }
 
 static void
index a0724f2b24cec783a242887971b5fc0d2e5a6592..9f55f5ae1044ffcd4e4a3080e581525646e8d639 100644 (file)
@@ -232,8 +232,6 @@ static void __init intcp_init_irq(void)
        for (i = IRQ_PIC_START; i <= IRQ_PIC_END; i++) {
                if (i == 11)
                        i = 22;
-               if (i == IRQ_CP_CPPLDINT)
-                       i++;
                if (i == 29)
                        break;
                set_irq_chip(i, &pic_chip);
@@ -259,8 +257,7 @@ static void __init intcp_init_irq(void)
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 
-       set_irq_handler(IRQ_CP_CPPLDINT, sic_handle_irq);
-       pic_unmask_irq(IRQ_CP_CPPLDINT);
+       set_irq_chained_handler(IRQ_CP_CPPLDINT, sic_handle_irq);
 }
 
 /*
index 092ee12ced425dcfaaff125a4f8f4cc3324c85c3..affd1d5d744049c44c19d8214d74478317ccc672 100644 (file)
@@ -178,8 +178,12 @@ static int ixp23xx_irq_set_type(unsigned int irq, unsigned int type)
 
 static void ixp23xx_irq_mask(unsigned int irq)
 {
-       volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
+       volatile unsigned long *intr_reg;
 
+       if (irq >= 56)
+               irq += 8;
+
+       intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
        *intr_reg &= ~(1 << (irq % 32));
 }
 
@@ -199,17 +203,25 @@ static void ixp23xx_irq_ack(unsigned int irq)
  */
 static void ixp23xx_irq_level_unmask(unsigned int irq)
 {
-       volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
+       volatile unsigned long *intr_reg;
 
        ixp23xx_irq_ack(irq);
 
+       if (irq >= 56)
+               irq += 8;
+
+       intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
        *intr_reg |= (1 << (irq % 32));
 }
 
 static void ixp23xx_irq_edge_unmask(unsigned int irq)
 {
-       volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
+       volatile unsigned long *intr_reg;
+
+       if (irq >= 56)
+               irq += 8;
 
+       intr_reg = IXP23XX_INTR_EN1 + (irq / 32);
        *intr_reg |= (1 << (irq % 32));
 }
 
index 2a39f9e481ad2d455ae6f00b13f26042755f37d8..3b23f43cb1609f0ffaf38d07cb63f6c207532f56 100644 (file)
@@ -141,7 +141,7 @@ config IXP4XX_INDIRECT_PCI
           2) If > 64MB of memory space is required, the IXP4xx can be 
             configured to use indirect registers to access PCI This allows 
             for up to 128MB (0x48000000 to 0x4fffffff) of memory on the bus. 
-            The disadvantadge of this is that every PCI access requires 
+            The disadvantage of this is that every PCI access requires 
             three local register accesses plus a spinlock, but in some 
             cases the performance hit is acceptable. In addition, you cannot 
             mmap() PCI devices in this case due to the indirect nature
index 8a17867a6a24daae188c541dc979fe4915413798..558a34f53b1c7f8bcdbce50bcad11f9f8c14b48b 100644 (file)
@@ -14,6 +14,7 @@ config MACH_LPD7A400
        bool "LPD7A400 Card Engine"
        select ARCH_LH7A400
 #      select IDE_POLL
+       select HAS_TOUCHSCREEN_ADS7843_LH7
        help
          Say Y here if you are using Logic Product Development's
          LPD7A400 CardEngine.  For the time being, the LPD7A400 and
@@ -23,6 +24,7 @@ config MACH_LPD7A404
        bool "LPD7A404 Card Engine"
        select ARCH_LH7A404
 #      select IDE_POLL
+       select HAS_TOUCHSCREEN_ADC_LH7
        help
          Say Y here if you are using Logic Product Development's
          LPD7A404 CardEngine. For the time being, the LPD7A400 and
@@ -34,6 +36,9 @@ config ARCH_LH7A400
 config ARCH_LH7A404
        bool
 
+config LPD7A40X_CPLD_SSP
+       bool
+
 config LH7A40X_CONTIGMEM
        bool "Disable NUMA Support"
        depends on ARCH_LH7A40X
index e90512dbc2d6047d15f77758f25c0fb659c191e4..94b8615fb3c37bc33196bba0a2878acf8c039423 100644 (file)
@@ -4,11 +4,14 @@
 
 # Object file lists.
 
-obj-y                  := time.o
-obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o
-obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o irq-lh7a400.o
-obj-$(CONFIG_MACH_LPD7A404) += arch-lpd7a40x.o irq-lh7a404.o
-
-obj-m                  :=
-obj-n                  :=
-obj-                   :=
+obj-y                          := time.o clocks.o
+obj-m                          :=
+obj-n                          :=
+obj-                           :=
+
+obj-$(CONFIG_MACH_KEV7A400)    += arch-kev7a400.o irq-lh7a400.o
+obj-$(CONFIG_MACH_LPD7A400)    += arch-lpd7a40x.o irq-lh7a400.o
+obj-$(CONFIG_MACH_LPD7A404)    += arch-lpd7a40x.o irq-lh7a404.o
+obj-$(CONFIG_LPD7A40X_CPLD_SSP)        += ssp-cpld.o
+obj-$(CONFIG_FB_ARMCLCD)       += clcd.o
+
index 12e23277c5ea188bb2d8f76dad34cc504e3feab0..c0e6854289f14ae7554ebd3815a78386bfd9e1a6 100644 (file)
 
 #include "common.h"
 
+#define CPLD_INT_NETHERNET     (1<<0)
+#define CPLD_INTMASK_ETHERNET  (1<<2)
+#if defined (CONFIG_MACH_LPD7A400)
+# define CPLD_INT_NTOUCH               (1<<1)
+# define CPLD_INTMASK_TOUCH    (1<<3)
+# define CPLD_INT_PEN          (1<<4)
+# define CPLD_INTMASK_PEN      (1<<4)
+# define CPLD_INT_PIRQ         (1<<4)
+#endif
+#define CPLD_INTMASK_CPLD      (1<<7)
+#define CPLD_INT_CPLD          (1<<6)
+
+#define CPLD_CONTROL_SWINT             (1<<7) /* Disable all CPLD IRQs */
+#define CPLD_CONTROL_OCMSK             (1<<6) /* Mask USB1 connect IRQ */
+#define CPLD_CONTROL_PDRV              (1<<5) /* PCC_nDRV high */
+#define CPLD_CONTROL_USB1C             (1<<4) /* USB1 connect IRQ active */
+#define CPLD_CONTROL_USB1P             (1<<3) /* USB1 power disable */
+#define CPLD_CONTROL_AWKP              (1<<2) /* Auto-wakeup disabled  */
+#define CPLD_CONTROL_LCD_ENABLE                (1<<1) /* LCD Vee enable */
+#define CPLD_CONTROL_WRLAN_NENABLE     (1<<0) /* SMC91x power disable */
+
+
 static struct resource smc91x_resources[] = {
        [0] = {
                .start  = CPLD00_PHYS,
@@ -48,12 +70,12 @@ static struct platform_device smc91x_device = {
 static struct resource lh7a40x_usbclient_resources[] = {
        [0] = {
                .start  = USB_PHYS,
-               .end    = (USB_PHYS + 0xFF),
+               .end    = (USB_PHYS + PAGE_SIZE),
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = IRQ_USBINTR,
-               .end    = IRQ_USBINTR,
+               .start  = IRQ_USB,
+               .end    = IRQ_USB,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -61,7 +83,8 @@ static struct resource lh7a40x_usbclient_resources[] = {
 static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL;
 
 static struct platform_device lh7a40x_usbclient_device = {
-       .name           = "lh7a40x_udc",
+//     .name           = "lh7a40x_udc",
+       .name           = "lh7-udc",
        .id             = 0,
        .dev            = {
                .dma_mask = &lh7a40x_usbclient_dma_mask,
@@ -101,7 +124,7 @@ static struct platform_device lh7a404_usbhost_device = {
 
 #endif
 
-static struct platform_device *lpd7a40x_devs[] __initdata = {
+static struct platform_devicelpd7a40x_devs[] __initdata = {
        &smc91x_device,
        &lh7a40x_usbclient_device,
 #if defined (CONFIG_ARCH_LH7A404)
@@ -113,29 +136,52 @@ extern void lpd7a400_map_io (void);
 
 static void __init lpd7a40x_init (void)
 {
-       CPLD_CONTROL |=     (1<<6); /* Mask USB1 connection IRQ */
+#if defined (CONFIG_MACH_LPD7A400)
+       CPLD_CONTROL |= 0
+               | CPLD_CONTROL_SWINT /* Disable software interrupt */
+               | CPLD_CONTROL_OCMSK; /* Mask USB1 connection IRQ */
        CPLD_CONTROL &= ~(0
-                         | (1<<1) /* Disable LCD */
-                         | (1<<0) /* Enable WLAN */
+                         | CPLD_CONTROL_LCD_ENABLE     /* Disable LCD */
+                         | CPLD_CONTROL_WRLAN_NENABLE  /* Enable SMC91x */
                );
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+       CPLD_CONTROL &= ~(0
+                         | CPLD_CONTROL_WRLAN_NENABLE  /* Enable SMC91x */
+               );
+#endif
 
        platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs));
+#if defined (CONFIG_FB_ARMCLCD)
+        lh7a40x_clcd_init ();
+#endif
 }
 
 static void lh7a40x_ack_cpld_irq (u32 irq)
 {
-       /* CPLD doesn't have ack capability */
+       /* CPLD doesn't have ack capability, but some devices may */
+
+#if defined (CPLD_INTMASK_TOUCH)
+       /* The touch control *must* mask the the interrupt because the
+        * interrupt bit is read by the driver to determine if the pen
+        * is still down. */
+       if (irq == IRQ_TOUCH)
+               CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
+#endif
 }
 
 static void lh7a40x_mask_cpld_irq (u32 irq)
 {
        switch (irq) {
        case IRQ_LPD7A40X_ETH_INT:
-               CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
+               CPLD_INTERRUPTS |= CPLD_INTMASK_ETHERNET;
                break;
-       case IRQ_LPD7A400_TS:
-               CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8;
+#if defined (IRQ_TOUCH)
+       case IRQ_TOUCH:
+               CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
                break;
+#endif
        }
 }
 
@@ -143,11 +189,13 @@ static void lh7a40x_unmask_cpld_irq (u32 irq)
 {
        switch (irq) {
        case IRQ_LPD7A40X_ETH_INT:
-               CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
+               CPLD_INTERRUPTS &= ~CPLD_INTMASK_ETHERNET;
                break;
-       case IRQ_LPD7A400_TS:
-               CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
+#if defined (IRQ_TOUCH)
+       case IRQ_TOUCH:
+               CPLD_INTERRUPTS &= ~CPLD_INTMASK_TOUCH;
                break;
+#endif
        }
 }
 
@@ -164,11 +212,13 @@ static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
 
        desc->chip->ack (irq);
 
-       if ((mask & 0x1) == 0)  /* WLAN */
+       if ((mask & (1<<0)) == 0)       /* WLAN */
                IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT);
 
-       if ((mask & 0x2) == 0)  /* Touch */
-               IRQ_DISPATCH (IRQ_LPD7A400_TS);
+#if defined (IRQ_TOUCH)
+       if ((mask & (1<<1)) == 0)       /* Touch */
+               IRQ_DISPATCH (IRQ_TOUCH);
+#endif
 
        desc->chip->unmask (irq); /* Level-triggered need this */
 }
@@ -204,9 +254,21 @@ void __init lh7a40x_init_board_irq (void)
 
                /* Then, configure CPLD interrupt */
 
-       CPLD_INTERRUPTS =   0x9c; /* Disable all CPLD interrupts */
+                       /* Disable all CPLD interrupts */
+#if defined (CONFIG_MACH_LPD7A400)
+       CPLD_INTERRUPTS = CPLD_INTMASK_TOUCH | CPLD_INTMASK_PEN
+               | CPLD_INTMASK_ETHERNET;
+       /* *** FIXME: don't know why we need 7 and 4. 7 is way wrong
+               and 4 is uncefined. */
+       // (1<<7)|(1<<4)|(1<<3)|(1<<2);
+#endif
+#if defined (CONFIG_MACH_LPD7A404)
+       CPLD_INTERRUPTS = CPLD_INTMASK_ETHERNET;
+       /* *** FIXME: don't know why we need 6 and 5, neither is defined. */
+       // (1<<6)|(1<<5)|(1<<3);
+#endif
        GPIO_PFDD       &= ~(1 << pinCPLD); /* Make input */
-       GPIO_INTTYPE1   |=  (1 << pinCPLD); /* Edge triggered */
+       GPIO_INTTYPE1   &= ~(1 << pinCPLD); /* Level triggered */
        GPIO_INTTYPE2   &= ~(1 << pinCPLD); /* Active low */
        barrier ();
        GPIO_GPIOFINTEN |=  (1 << pinCPLD); /* Enable */
@@ -216,7 +278,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_edge_IRQ);
+               set_irq_handler (irq, do_level_IRQ);
                set_irq_flags (irq, IRQF_VALID);
        }
 
@@ -226,91 +288,109 @@ void __init lh7a40x_init_board_irq (void)
                                 lpd7a40x_cpld_handler);
 }
 
-static struct map_desc lpd7a400_io_desc[] __initdata = {
+static struct map_desc lpd7a40x_io_desc[] __initdata = {
        {
-               .virtual        =     IO_VIRT,
+               .virtual        = IO_VIRT,
                .pfn            = __phys_to_pfn(IO_PHYS),
-               .length         =           IO_SIZE,
+               .length         = IO_SIZE,
                .type           = MT_DEVICE
-       }, {    /* Mapping added to work around chip select problems */
+       },
+       {       /* Mapping added to work around chip select problems */
                .virtual        = IOBARRIER_VIRT,
                .pfn            = __phys_to_pfn(IOBARRIER_PHYS),
                .length         = IOBARRIER_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CF_VIRT,
                .pfn            = __phys_to_pfn(CF_PHYS),
-               .length         =       CF_SIZE,
+               .length         = CF_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CPLD02_VIRT,
                .pfn            = __phys_to_pfn(CPLD02_PHYS),
-               .length         =       CPLD02_SIZE,
+               .length         = CPLD02_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CPLD06_VIRT,
                .pfn            = __phys_to_pfn(CPLD06_PHYS),
-               .length         =       CPLD06_SIZE,
+               .length         = CPLD06_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
+               .virtual        = CPLD08_VIRT,
+               .pfn            = __phys_to_pfn(CPLD08_PHYS),
+               .length         = CPLD08_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CPLD08_VIRT,
                .pfn            = __phys_to_pfn(CPLD08_PHYS),
-               .length         =       CPLD08_SIZE,
+               .length         = CPLD08_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
+               .virtual        = CPLD0A_VIRT,
+               .pfn            = __phys_to_pfn(CPLD0A_PHYS),
+               .length         = CPLD0A_SIZE,
+               .type           = MT_DEVICE
+       },
+       {
                .virtual        = CPLD0C_VIRT,
                .pfn            = __phys_to_pfn(CPLD0C_PHYS),
-               .length         =       CPLD0C_SIZE,
+               .length         = CPLD0C_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CPLD0E_VIRT,
                .pfn            = __phys_to_pfn(CPLD0E_PHYS),
-               .length         =       CPLD0E_SIZE,
+               .length         = CPLD0E_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CPLD10_VIRT,
                .pfn            = __phys_to_pfn(CPLD10_PHYS),
-               .length         =       CPLD10_SIZE,
+               .length         = CPLD10_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CPLD12_VIRT,
                .pfn            = __phys_to_pfn(CPLD12_PHYS),
-               .length         =       CPLD12_SIZE,
+               .length         = CPLD12_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CPLD14_VIRT,
                .pfn            = __phys_to_pfn(CPLD14_PHYS),
-               .length         =       CPLD14_SIZE,
+               .length         = CPLD14_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CPLD16_VIRT,
                .pfn            = __phys_to_pfn(CPLD16_PHYS),
-               .length         =       CPLD16_SIZE,
+               .length         = CPLD16_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CPLD18_VIRT,
                .pfn            = __phys_to_pfn(CPLD18_PHYS),
-               .length         =       CPLD18_SIZE,
+               .length         = CPLD18_SIZE,
                .type           = MT_DEVICE
-       }, {
+       },
+       {
                .virtual        = CPLD1A_VIRT,
                .pfn            = __phys_to_pfn(CPLD1A_PHYS),
-               .length         =       CPLD1A_SIZE,
+               .length         = CPLD1A_SIZE,
                .type           = MT_DEVICE
        },
-       /* This mapping is redundant since the smc driver performs another. */
-/*     { CPLD00_VIRT,  CPLD00_PHYS,    CPLD00_SIZE,    MT_DEVICE }, */
 };
 
 void __init
-lpd7a400_map_io(void)
+lpd7a40x_map_io(void)
 {
-       iotable_init (lpd7a400_io_desc, ARRAY_SIZE (lpd7a400_io_desc));
-
-               /* Fixup (improve) Static Memory Controller settings */
-       SMC_BCR0 = 0x200039af;  /* Boot Flash */
-       SMC_BCR6 = 0x1000fbe0;  /* CPLD */
-       SMC_BCR7 = 0x1000b2c2;  /* Compact Flash */
+       iotable_init (lpd7a40x_io_desc, ARRAY_SIZE (lpd7a40x_io_desc));
 }
 
 #ifdef CONFIG_MACH_LPD7A400
@@ -320,7 +400,7 @@ MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
        .phys_io        = 0x80000000,
        .io_pg_offst    = ((io_p2v (0x80000000))>>18) & 0xfffc,
        .boot_params    = 0xc0000100,
-       .map_io         = lpd7a400_map_io,
+       .map_io         = lpd7a40x_map_io,
        .init_irq       = lh7a400_init_irq,
        .timer          = &lh7a40x_timer,
        .init_machine   = lpd7a40x_init,
@@ -335,7 +415,7 @@ MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
        .phys_io        = 0x80000000,
        .io_pg_offst    = ((io_p2v (0x80000000))>>18) & 0xfffc,
        .boot_params    = 0xc0000100,
-       .map_io         = lpd7a400_map_io,
+       .map_io         = lpd7a40x_map_io,
        .init_irq       = lh7a404_init_irq,
        .timer          = &lh7a40x_timer,
        .init_machine   = lpd7a40x_init,
diff --git a/arch/arm/mach-lh7a40x/clcd.c b/arch/arm/mach-lh7a40x/clcd.c
new file mode 100644 (file)
index 0000000..93751fe
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ *  arch/arm/mach-lh7a40x/clcd.c
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  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/config.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+
+//#include <linux/module.h>
+//#include <linux/time.h>
+//#include <asm/hardware.h>
+
+//#include <asm/mach/time.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#define HRTFTC_HRSETUP         __REG(HRTFTC_PHYS + 0x00)
+#define HRTFTC_HRCON           __REG(HRTFTC_PHYS + 0x04)
+#define HRTFTC_HRTIMING1       __REG(HRTFTC_PHYS + 0x08)
+#define HRTFTC_HRTIMING2       __REG(HRTFTC_PHYS + 0x0c)
+
+#define ALI_SETUP              __REG(ALI_PHYS + 0x00)
+#define ALI_CONTROL            __REG(ALI_PHYS + 0x04)
+#define ALI_TIMING1            __REG(ALI_PHYS + 0x08)
+#define ALI_TIMING2            __REG(ALI_PHYS + 0x0c)
+
+#include "lcd-panel.h"
+
+static void lh7a40x_clcd_disable (struct clcd_fb *fb)
+{
+#if defined (CONFIG_MACH_LPD7A400)
+       CPLD_CONTROL &= ~(1<<1);        /* Disable LCD Vee */
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+       GPIO_PCD  &= ~(1<<3);           /* Disable LCD Vee */
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+       HRTFTC_HRSETUP &= ~(1<<13);     /* Disable HRTFT controller */
+#endif
+
+#if defined (CONFIG_ARCH_LH7A404)
+       ALI_SETUP &= ~(1<<13);          /* Disable ALI */
+#endif
+}
+
+static void lh7a40x_clcd_enable (struct clcd_fb *fb)
+{
+       struct clcd_panel_extra* extra
+               = (struct clcd_panel_extra*) fb->board_data;
+
+#if defined (CONFIG_MACH_LPD7A400)
+       CPLD_CONTROL |= (1<<1);         /* Enable LCD Vee */
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+       GPIO_PCDD &= ~(1<<3);           /* Enable LCD Vee */
+       GPIO_PCD  |=  (1<<3);
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+
+       if (extra) {
+               HRTFTC_HRSETUP
+                       = (1 << 13)
+                       | ((fb->fb.var.xres - 1) << 4)
+                       | 0xc
+                       | (extra->hrmode ? 1 : 0);
+               HRTFTC_HRCON
+                       = ((extra->clsen ? 1 : 0) << 1)
+                       | ((extra->spsen ? 1 : 0) << 0);
+               HRTFTC_HRTIMING1
+                       = (extra->pcdel << 8)
+                       | (extra->revdel << 4)
+                       | (extra->lpdel << 0);
+               HRTFTC_HRTIMING2
+                       = (extra->spldel << 9)
+                       | (extra->pc2del << 0);
+       }
+       else
+               HRTFTC_HRSETUP
+                       = (1 << 13)
+                       | 0xc;
+#endif
+
+#if defined (CONFIG_ARCH_LH7A404)
+
+       if (extra) {
+               ALI_SETUP
+                       = (1 << 13)
+                       | ((fb->fb.var.xres - 1) << 4)
+                       | 0xc
+                       | (extra->hrmode ? 1 : 0);
+               ALI_CONTROL
+                       = ((extra->clsen ? 1 : 0) << 1)
+                       | ((extra->spsen ? 1 : 0) << 0);
+               ALI_TIMING1
+                       = (extra->pcdel << 8)
+                       | (extra->revdel << 4)
+                       | (extra->lpdel << 0);
+               ALI_TIMING2
+                       = (extra->spldel << 9)
+                       | (extra->pc2del << 0);
+       }
+       else
+               ALI_SETUP
+                       = (1 << 13)
+                       | 0xc;
+#endif
+
+}
+
+#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
+
+static int lh7a40x_clcd_setup (struct clcd_fb *fb)
+{
+       dma_addr_t dma;
+       u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
+                            *(lcd_panel.bpp/8));
+
+       fb->panel = &lcd_panel;
+
+               /* Enforce the sync polarity defaults */
+       if (!(fb->panel->tim2 & TIM2_IHS))
+               fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
+       if (!(fb->panel->tim2 & TIM2_IVS))
+               fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
+
+#if defined (HAS_LCD_PANEL_EXTRA)
+       fb->board_data = &lcd_panel_extra;
+#endif
+
+       fb->fb.screen_base
+               = dma_alloc_writecombine (&fb->dev->dev, len,
+                                         &dma, GFP_KERNEL);
+       printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
+               fb->fb.screen_base, (void*) dma, len,
+               (void*) io_p2v (CLCDC_PHYS));
+       printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
+
+       if (!fb->fb.screen_base) {
+               printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+               return -ENOMEM;
+       }
+
+#if defined (USE_RGB555)
+       fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
+#endif
+
+       fb->fb.fix.smem_start = dma;
+       fb->fb.fix.smem_len = len;
+
+               /* Drive PE4 high to prevent CPLD crash */
+       GPIO_PEDD |= (1<<4);
+       GPIO_PED  |= (1<<4);
+
+       GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
+
+//     fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
+//     fb->fb.fbops->fb_set_par (&fb->fb);
+
+       return 0;
+}
+
+static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+       return dma_mmap_writecombine(&fb->dev->dev, vma,
+                                    fb->fb.screen_base,
+                                    fb->fb.fix.smem_start,
+                                    fb->fb.fix.smem_len);
+}
+
+static void lh7a40x_clcd_remove (struct clcd_fb *fb)
+{
+       dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
+                              fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board clcd_platform_data = {
+       .name           = "lh7a40x FB",
+       .check          = clcdfb_check,
+       .decode         = clcdfb_decode,
+       .enable         = lh7a40x_clcd_enable,
+       .setup          = lh7a40x_clcd_setup,
+       .mmap           = lh7a40x_clcd_mmap,
+       .remove         = lh7a40x_clcd_remove,
+       .disable        = lh7a40x_clcd_disable,
+};
+
+#define IRQ_CLCDC (IRQ_LCDINTR)
+
+#define AMBA_DEVICE(name,busid,base,plat,pid)                  \
+static struct amba_device name##_device = {                    \
+       .dev = {                                                \
+               .coherent_dma_mask = ~0,                        \
+               .bus_id = busid,                                \
+               .platform_data = plat,                          \
+               },                                              \
+       .res = {                                                \
+               .start  = base##_PHYS,                          \
+               .end    = (base##_PHYS) + (4*1024) - 1,         \
+               .flags  = IORESOURCE_MEM,                       \
+               },                                              \
+       .dma_mask       = ~0,                                   \
+       .irq            = { IRQ_##base, },                      \
+       /* .dma         = base##_DMA,*/                         \
+       .periphid = pid,                                        \
+}
+
+AMBA_DEVICE(clcd,  "cldc-lh7a40x",  CLCDC,     &clcd_platform_data, 0x41110);
+
+static struct amba_device *amba_devs[] __initdata = {
+       &clcd_device,
+};
+
+void __init lh7a40x_clcd_init (void)
+{
+       int i;
+       int result;
+       printk ("CLCD: registering amba devices\n");
+       for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+               struct amba_device *d = amba_devs[i];
+               result = amba_device_register(d, &iomem_resource);
+               printk ("  %d -> %d\n", i ,result);
+       }
+}
diff --git a/arch/arm/mach-lh7a40x/clocks.c b/arch/arm/mach-lh7a40x/clocks.c
new file mode 100644 (file)
index 0000000..2291afe
--- /dev/null
@@ -0,0 +1,199 @@
+/* arch/arm/mach-lh7a40x/clocks.c
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  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/config.h>
+#include <linux/cpufreq.h>
+#include <asm/hardware.h>
+#include <asm/arch/clocks.h>
+#include <linux/err.h>
+
+struct module;
+struct icst525_params;
+
+struct clk {
+       struct list_head node;
+       unsigned long rate;
+       struct module *owner;
+       const char *name;
+//     void *data;
+//     const struct icst525_params *params;
+//     void (*setvco)(struct clk *, struct icst525_vco vco);
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+
+/* ----- */
+
+#define MAINDIV1(c)    (((c) >>  7) & 0x0f)
+#define MAINDIV2(c)    (((c) >> 11) & 0x1f)
+#define PS(c)          (((c) >> 18) & 0x03)
+#define PREDIV(c)      (((c) >>  2) & 0x1f)
+#define HCLKDIV(c)     (((c) >>  0) & 0x02)
+#define PCLKDIV(c)     (((c) >> 16) & 0x03)
+
+unsigned int cpufreq_get (unsigned int cpu) /* in kHz */
+{
+       return fclkfreq_get ()/1000;
+}
+EXPORT_SYMBOL(cpufreq_get);
+
+unsigned int fclkfreq_get (void)
+{
+       unsigned int clkset = CSC_CLKSET;
+       unsigned int gclk
+               = XTAL_IN
+               / (1 << PS(clkset))
+               * (MAINDIV1(clkset) + 2)
+               / (PREDIV(clkset)   + 2)
+               * (MAINDIV2(clkset) + 2)
+               ;
+       return gclk;
+}
+
+unsigned int hclkfreq_get (void)
+{
+       unsigned int clkset = CSC_CLKSET;
+       unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1);
+
+       return hclk;
+}
+
+unsigned int pclkfreq_get (void)
+{
+       unsigned int clkset = CSC_CLKSET;
+       int pclkdiv = PCLKDIV(clkset);
+       unsigned int pclk;
+       if (pclkdiv == 0x3)
+               pclkdiv = 0x2;
+       pclk = hclkfreq_get () / (1 << pclkdiv);
+
+       return pclk;
+}
+
+/* ----- */
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+
+struct clk *clk_get (struct device *dev, const char *id)
+{
+       struct clk *p;
+       struct clk *clk = ERR_PTR(-ENOENT);
+
+       down (&clocks_sem);
+       list_for_each_entry (p, &clocks, node) {
+               if (strcmp (id, p->name) == 0
+                   && try_module_get(p->owner)) {
+                       clk = p;
+                       break;
+               }
+       }
+       up (&clocks_sem);
+
+       return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put (struct clk *clk)
+{
+       module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable (struct clk *clk)
+{
+       return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable (struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_use (struct clk *clk)
+{
+       return 0;
+}
+EXPORT_SYMBOL(clk_use);
+
+void clk_unuse (struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_unuse);
+
+unsigned long clk_get_rate (struct clk *clk)
+{
+       return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate (struct clk *clk, unsigned long rate)
+{
+       return rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate (struct clk *clk, unsigned long rate)
+{
+       int ret = -EIO;
+       return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+#if 0
+/*
+ * These are fixed clocks.
+ */
+static struct clk kmi_clk = {
+       .name   = "KMIREFCLK",
+       .rate   = 24000000,
+};
+
+static struct clk uart_clk = {
+       .name   = "UARTCLK",
+       .rate   = 24000000,
+};
+
+static struct clk mmci_clk = {
+       .name   = "MCLK",
+       .rate   = 33000000,
+};
+#endif
+
+static struct clk clcd_clk = {
+       .name   = "CLCDCLK",
+       .rate   = 0,
+};
+
+int clk_register (struct clk *clk)
+{
+       down (&clocks_sem);
+       list_add (&clk->node, &clocks);
+       up (&clocks_sem);
+       return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister (struct clk *clk)
+{
+       down (&clocks_sem);
+       list_del (&clk->node);
+       up (&clocks_sem);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static int __init clk_init (void)
+{
+       clk_register(&clcd_clk);
+       return 0;
+}
+arch_initcall(clk_init);
index ea8de7e3ab1ba3011274de8360c12d993bb0ddfd..18e8bb4eb202280446f251f20dc7f5f006a20d35 100644 (file)
@@ -12,6 +12,7 @@ extern struct sys_timer lh7a40x_timer;
 
 extern void lh7a400_init_irq (void);
 extern void lh7a404_init_irq (void);
+extern void lh7a40x_clcd_init (void);
 extern void lh7a40x_init_board_irq (void);
 
 #define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs)
index e902e3d87da4e998978685bbf586291a8407992c..2685a81454d260e79ebbcd60b4a6cd8c34721c1c 100644 (file)
 
 static unsigned char irq_pri_vic1[] = {
 #if defined (USE_PRIORITIES)
-IRQ_GPIO3INTR,
+       IRQ_GPIO3INTR,                  /* CPLD */
+       IRQ_DMAM2P4, IRQ_DMAM2P5,       /* AC97 */
 #endif
 };
 static unsigned char irq_pri_vic2[] = {
 #if defined (USE_PRIORITIES)
-       IRQ_T3UI, IRQ_GPIO7INTR,
+       IRQ_T3UI,                       /* Timer */
+       IRQ_GPIO7INTR,                  /* CPLD */
        IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR,
+       IRQ_LCDINTR,                    /* LCD */
+       IRQ_TSCINTR,                    /* ADC/Touchscreen */
 #endif
 };
 
@@ -98,10 +102,19 @@ static struct irqchip lh7a404_gpio_vic2_chip = {
 
   /* IRQ initialization */
 
+#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
+extern void* branch_irq_lh7a400;
+#endif
+
 void __init lh7a404_init_irq (void)
 {
        int irq;
 
+#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
+#define NOP 0xe1a00000                 /* mov r0, r0 */
+       branch_irq_lh7a400 = NOP;
+#endif
+
        VIC1_INTENCLR = 0xffffffff;
        VIC2_INTENCLR = 0xffffffff;
        VIC1_INTSEL = 0;                /* All IRQs */
diff --git a/arch/arm/mach-lh7a40x/lcd-panel.h b/arch/arm/mach-lh7a40x/lcd-panel.h
new file mode 100644 (file)
index 0000000..4fb2efc
--- /dev/null
@@ -0,0 +1,346 @@
+/* lcd-panel.h
+     $Id$
+
+   written by Marc Singer
+   18 Jul 2005
+
+   Copyright (C) 2005 Marc Singer
+
+   -----------
+   DESCRIPTION
+   -----------
+
+   Only one panel may be defined at a time.
+
+   The pixel clock is calculated to be no greater than the target.
+
+   Each timing value is accompanied by a specification comment.
+
+     UNITS/MIN/TYP/MAX
+
+   Most of the units will be in clocks.
+
+   USE_RGB555
+
+     Define this macro to configure the AMBA LCD controller to use an
+     RGB555 encoding for the pels instead of the normal RGB565.
+
+   LPD9520, LPD79524, LPD7A400, LPD7A404-10, LPD7A404-11
+
+     These boards are best approximated by 555 for all panels.  Some
+     can use an extra low-order bit of blue in bit 16 of the color
+     value, but we don't have a way to communicate this non-linear
+     mapping to the kernel.
+
+*/
+
+#if !defined (__LCD_PANEL_H__)
+#    define   __LCD_PANEL_H__
+
+#if defined (MACH_LPD79520)\
+ || defined (MACH_LPD79524)\
+ || defined (MACH_LPD7A400)\
+ || defined (MACH_LPD7A404)
+# define USE_RGB555
+#endif
+
+struct clcd_panel_extra {
+       unsigned int hrmode;
+       unsigned int clsen;
+       unsigned int spsen;
+       unsigned int pcdel;
+       unsigned int revdel;
+       unsigned int lpdel;
+       unsigned int spldel;
+       unsigned int pc2del;
+};
+
+#define NS_TO_CLOCK(ns,c)      ((((ns)*((c)/1000) + (1000000 - 1))/1000000))
+#define CLOCK_TO_DIV(e,c)      (((c) + (e) - 1)/(e))
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
+
+       /* Logic Product Development LCD 3.5" QVGA HRTFT -10 */
+       /* Sharp PN LQ035Q7DB02 w/HRTFT controller chip */
+
+#define PIX_CLOCK_TARGET       (6800000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "3.5in QVGA (LQ035Q7DB02)",
+               .xres           = 240,
+               .yres           = 320,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 16,
+               .right_margin   = 21,
+               .upper_margin   = 8,                    // line/8/8/8
+               .lower_margin   = 5,
+               .hsync_len      = 61,
+               .vsync_len      = NS_TO_CLOCK (60, PIX_CLOCK),
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IPC | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#define HAS_LCD_PANEL_EXTRA
+
+static struct clcd_panel_extra lcd_panel_extra = {
+       .hrmode = 1,
+       .clsen = 1,
+       .spsen = 1,
+       .pcdel = 8,
+       .revdel = 7,
+       .lpdel = 13,
+       .spldel = 77,
+       .pc2del = 208,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02
+
+       /* Logic Product Development LCD 5.7" QVGA -10 */
+       /* Sharp PN LQ057Q3DC02 */
+       /* QVGA mode, V/Q=LOW */
+
+/* From Sharp on 2006.1.3.  I believe some of the values are incorrect
+ * based on the datasheet.
+
+    Timing0    TIMING1         TIMING2         CONTROL
+    0x140A0C4C 0x080504EF      0x013F380D      0x00000829
+    HBP= 20    VBP=  8         BCD=  0
+    HFP= 10    VFP=  5         CPL=319
+    HSW= 12    VSW=  1         IOE=  0
+    PPL= 19    LPP=239         IPC=  1
+                               IHS=  1
+                               IVS=  1
+                               ACB=  0
+                               CSEL= 0
+                               PCD= 13
+
+ */
+
+/* The full horozontal cycle (Th) is clock/360/400/450. */
+/* The full vertical   cycle (Tv) is line/251/262/280. */
+
+#define PIX_CLOCK_TARGET       (6300000) /* -/6.3/7 MHz */
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "5.7in QVGA (LQ057Q3DC02)",
+               .xres           = 320,
+               .yres           = 240,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 11,
+               .right_margin   = 400-11-320-2,
+               .upper_margin   = 7,                    // line/7/7/7
+               .lower_margin   = 262-7-240-2,
+               .hsync_len      = 2,                    // clk/2/96/200
+               .vsync_len      = 2,                    // line/2/-/34
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ64D343
+
+       /* Logic Product Development LCD 6.4" VGA -10 */
+       /* Sharp PN LQ64D343 */
+
+/* The full horozontal cycle (Th) is clock/750/800/900. */
+/* The full vertical   cycle (Tv) is line/515/525/560. */
+
+#define PIX_CLOCK_TARGET       (28330000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "6.4in QVGA (LQ64D343)",
+               .xres           = 640,
+               .yres           = 480,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 32,
+               .right_margin   = 800-32-640-96,
+               .upper_margin   = 32,                   // line/34/34/34
+               .lower_margin   = 540-32-480-2,
+               .hsync_len      = 96,                   // clk/2/96/200
+               .vsync_len      = 2,                    // line/2/-/34
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ10D368
+
+       /* Logic Product Development LCD 10.4" VGA -10 */
+       /* Sharp PN LQ10D368 */
+
+#define PIX_CLOCK_TARGET       (28330000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "10.4in VGA (LQ10D368)",
+               .xres           = 640,
+               .yres           = 480,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 21,
+               .right_margin   = 15,
+               .upper_margin   = 34,
+               .lower_margin   = 5,
+               .hsync_len      = 96,
+               .vsync_len      = 16,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41
+
+       /* Logic Product Development LCD 12.1" SVGA -10 */
+       /* Sharp PN LQ121S1DG41, was LQ121S1DG31 */
+
+/* Note that with a 99993900 Hz HCLK, it is not possible to hit the
+ * target clock frequency range of 35MHz to 42MHz. */
+
+/* If the target pixel clock is substantially lower than the panel
+ * spec, this is done to prevent the LCD display from glitching when
+ * the CPU is under load.  A pixel clock higher than 25MHz
+ * (empirically determined) will compete with the CPU for bus cycles
+ * for the Ethernet chip.  However, even a pixel clock of 10MHz
+ * competes with Compact Flash interface during some operations
+ * (fdisk, e2fsck).  And, at that speed the display may have a visible
+ * flicker. */
+
+/* The full horozontal cycle (Th) is clock/832/1056/1395. */
+
+#define PIX_CLOCK_TARGET       (20000000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "12.1in SVGA (LQ121S1DG41)",
+               .xres           = 800,
+               .yres           = 600,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 89,           // ns/5/-/(1/PIX_CLOCK)-10
+               .right_margin   = 1056-800-89-128,
+               .upper_margin   = 23,           // line/23/23/23
+               .lower_margin   = 44,
+               .hsync_len      = 128,          // clk/2/128/200
+               .vsync_len      = 4,            // line/2/4/6
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_HITACHI
+
+       /* Hitachi*/
+       /* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
+
+#define PIX_CLOCK_TARGET       (49000000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "Hitachi 800x480",
+               .xres           = 800,
+               .yres           = 480,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 88,
+               .right_margin   = 40,
+               .upper_margin   = 32,
+               .lower_margin   = 11,
+               .hsync_len      = 128,
+               .vsync_len      = 2,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IPC | TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+
+#if defined CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE
+
+       /* AU Optotronics  A070VW01 7.0 Wide Screen color Display*/
+       /* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
+
+#define PIX_CLOCK_TARGET       (10000000)
+#define PIX_CLOCK_DIVIDER      CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK              (HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+       .mode   = {
+               .name           = "7.0in Wide (A070VW01)",
+               .xres           = 480,
+               .yres           = 234,
+               .pixclock       = PIX_CLOCK,
+               .left_margin    = 30,
+               .right_margin   = 25,
+               .upper_margin   = 14,
+               .lower_margin   = 12,
+               .hsync_len      = 100,
+               .vsync_len      = 1,
+               .vmode          = FB_VMODE_NONINTERLACED,
+       },
+       .width          = -1,
+       .height         = -1,
+       .tim2           = TIM2_IPC | TIM2_IHS | TIM2_IVS
+                       | (PIX_CLOCK_DIVIDER - 2),
+       .cntl           = CNTL_LCDTFT | CNTL_WATERMARK,
+       .bpp            = 16,
+};
+
+#endif
+
+#undef NS_TO_CLOCK
+#undef CLOCK_TO_DIV
+
+#endif  /* __LCD_PANEL_H__ */
diff --git a/arch/arm/mach-lh7a40x/ssp-cpld.c b/arch/arm/mach-lh7a40x/ssp-cpld.c
new file mode 100644 (file)
index 0000000..a108301
--- /dev/null
@@ -0,0 +1,343 @@
+/* arch/arm/mach-lh7a40x/ssp-cpld.c
+ *
+ *  Copyright (C) 2004,2005 Marc Singer
+ *
+ *  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.
+ *
+ * SSP/SPI driver for the CardEngine CPLD.
+ *
+ */
+
+/* NOTES
+   -----
+
+   o *** This driver is cribbed from the 7952x implementation.
+        Some comments may not apply.
+
+   o This driver contains sufficient logic to control either the
+     serial EEPROMs or the audio codec.  It is included in the kernel
+     to support the codec.  The EEPROMs are really the responsibility
+     of the boot loader and should probably be left alone.
+
+   o The code must be augmented to cope with multiple, simultaneous
+     clients.
+     o The audio codec writes to the codec chip whenever playback
+       starts.
+     o The touchscreen driver writes to the ads chip every time it
+       samples.
+     o The audio codec must write 16 bits, but the touch chip writes
+       are 8 bits long.
+     o We need to be able to keep these configurations separate while
+       simultaneously active.
+
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+//#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+//#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/ssp.h>
+
+//#define TALK
+
+#if defined (TALK)
+#define PRINTK(f...)           printk (f)
+#else
+#define PRINTK(f...)           do {} while (0)
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+# define CPLD_SPID             __REGP16(CPLD06_VIRT) /* SPI data */
+# define CPLD_SPIC             __REGP16(CPLD08_VIRT) /* SPI control */
+# define CPLD_SPIC_CS_CODEC    (1<<0)
+# define CPLD_SPIC_CS_TOUCH    (1<<1)
+# define CPLD_SPIC_WRITE       (0<<2)
+# define CPLD_SPIC_READ                (1<<2)
+# define CPLD_SPIC_DONE                (1<<3) /* r/o */
+# define CPLD_SPIC_LOAD                (1<<4)
+# define CPLD_SPIC_START       (1<<4)
+# define CPLD_SPIC_LOADED      (1<<5) /* r/o */
+#endif
+
+#define CPLD_SPI               __REGP16(CPLD0A_VIRT) /* SPI operation */
+#define CPLD_SPI_CS_EEPROM     (1<<3)
+#define CPLD_SPI_SCLK          (1<<2)
+#define CPLD_SPI_TX_SHIFT      (1)
+#define CPLD_SPI_TX            (1<<CPLD_SPI_TX_SHIFT)
+#define CPLD_SPI_RX_SHIFT      (0)
+#define CPLD_SPI_RX            (1<<CPLD_SPI_RX_SHIFT)
+
+/* *** FIXME: these timing values are substantially larger than the
+   *** chip requires. We may implement an nsleep () function. */
+#define T_SKH  1               /* Clock time high (us) */
+#define T_SKL  1               /* Clock time low (us) */
+#define T_CS   1               /* Minimum chip select low time (us)  */
+#define T_CSS  1               /* Minimum chip select setup time (us)  */
+#define T_DIS  1               /* Data setup time (us) */
+
+        /* EEPROM SPI bits */
+#define P_START                (1<<9)
+#define P_WRITE                (1<<7)
+#define P_READ         (2<<7)
+#define P_ERASE                (3<<7)
+#define P_EWDS         (0<<7)
+#define P_WRAL         (0<<7)
+#define P_ERAL         (0<<7)
+#define P_EWEN         (0<<7)
+#define P_A_EWDS       (0<<5)
+#define P_A_WRAL       (1<<5)
+#define P_A_ERAL       (2<<5)
+#define P_A_EWEN       (3<<5)
+
+struct ssp_configuration {
+       int device;
+       int mode;
+       int speed;
+       int frame_size_write;
+       int frame_size_read;
+};
+
+static struct ssp_configuration ssp_configuration;
+static spinlock_t ssp_lock;
+
+static void enable_cs (void)
+{
+       switch (ssp_configuration.device) {
+       case DEVICE_EEPROM:
+               CPLD_SPI |= CPLD_SPI_CS_EEPROM;
+               break;
+       }
+       udelay (T_CSS);
+}
+
+static void disable_cs (void)
+{
+       switch (ssp_configuration.device) {
+       case DEVICE_EEPROM:
+               CPLD_SPI &= ~CPLD_SPI_CS_EEPROM;
+               break;
+       }
+       udelay (T_CS);
+}
+
+static void pulse_clock (void)
+{
+       CPLD_SPI |=  CPLD_SPI_SCLK;
+       udelay (T_SKH);
+       CPLD_SPI &= ~CPLD_SPI_SCLK;
+       udelay (T_SKL);
+}
+
+
+/* execute_spi_command
+
+   sends an spi command to a device.  It first sends cwrite bits from
+   v.  If cread is greater than zero it will read cread bits
+   (discarding the leading 0 bit) and return them.  If cread is less
+   than zero it will check for completetion status and return 0 on
+   success or -1 on timeout.  If cread is zero it does nothing other
+   than sending the command.
+
+   On the LPD7A400, we can only read or write multiples of 8 bits on
+   the codec and the touch screen device.  Here, we round up.
+
+*/
+
+static int execute_spi_command (int v, int cwrite, int cread)
+{
+       unsigned long l = 0;
+
+#if defined (CONFIG_MACH_LPD7A400)
+       /* The codec and touch devices cannot be bit-banged.  Instead,
+        * the CPLD provides an eight-bit shift register and a crude
+        * interface.  */
+       if (   ssp_configuration.device == DEVICE_CODEC
+           || ssp_configuration.device == DEVICE_TOUCH) {
+               int select = 0;
+
+               PRINTK ("spi(%d %d.%d) 0x%04x",
+                       ssp_configuration.device, cwrite, cread,
+                       v);
+#if defined (TALK)
+               if (ssp_configuration.device == DEVICE_CODEC)
+                       PRINTK (" 0x%03x -> %2d", v & 0x1ff, (v >> 9) & 0x7f);
+#endif
+               PRINTK ("\n");
+
+               if (ssp_configuration.device == DEVICE_CODEC)
+                       select = CPLD_SPIC_CS_CODEC;
+               if (ssp_configuration.device == DEVICE_TOUCH)
+                       select = CPLD_SPIC_CS_TOUCH;
+               if (cwrite) {
+                       for (cwrite = (cwrite + 7)/8; cwrite-- > 0; ) {
+                               CPLD_SPID = (v >> (8*cwrite)) & 0xff;
+                               CPLD_SPIC = select | CPLD_SPIC_LOAD;
+                               while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
+                                       ;
+                               CPLD_SPIC = select;
+                               while (!(CPLD_SPIC & CPLD_SPIC_DONE))
+                                       ;
+                       }
+                       v = 0;
+               }
+               if (cread) {
+                       mdelay (2);     /* *** FIXME: required by ads7843? */
+                       v = 0;
+                       for (cread = (cread + 7)/8; cread-- > 0;) {
+                               CPLD_SPID = 0;
+                               CPLD_SPIC = select | CPLD_SPIC_READ
+                                       | CPLD_SPIC_START;
+                               while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
+                                       ;
+                               CPLD_SPIC = select | CPLD_SPIC_READ;
+                               while (!(CPLD_SPIC & CPLD_SPIC_DONE))
+                                       ;
+                               v = (v << 8) | CPLD_SPID;
+                       }
+               }
+               return v;
+       }
+#endif
+
+       PRINTK ("spi(%d) 0x%04x -> 0x%x\r\n", ssp_configuration.device,
+               v & 0x1ff, (v >> 9) & 0x7f);
+
+       enable_cs ();
+
+       v <<= CPLD_SPI_TX_SHIFT; /* Correction for position of SPI_TX bit */
+       while (cwrite--) {
+               CPLD_SPI
+                       = (CPLD_SPI & ~CPLD_SPI_TX)
+                       | ((v >> cwrite) & CPLD_SPI_TX);
+               udelay (T_DIS);
+               pulse_clock ();
+       }
+
+       if (cread < 0) {
+               int delay = 10;
+               disable_cs ();
+               udelay (1);
+               enable_cs ();
+
+               l = -1;
+               do {
+                       if (CPLD_SPI & CPLD_SPI_RX) {
+                               l = 0;
+                               break;
+                       }
+               } while (udelay (1), --delay);
+       }
+       else
+       /* We pulse the clock before the data to skip the leading zero. */
+               while (cread-- > 0) {
+                       pulse_clock ();
+                       l = (l<<1)
+                               | (((CPLD_SPI & CPLD_SPI_RX)
+                                   >> CPLD_SPI_RX_SHIFT) & 0x1);
+               }
+
+       disable_cs ();
+       return l;
+}
+
+static int ssp_init (void)
+{
+       spin_lock_init (&ssp_lock);
+       memset (&ssp_configuration, 0, sizeof (ssp_configuration));
+       return 0;
+}
+
+
+/* ssp_chip_select
+
+   drops the chip select line for the CPLD shift-register controlled
+   devices.  It doesn't enable chip
+
+*/
+
+static void ssp_chip_select (int enable)
+{
+#if defined (CONFIG_MACH_LPD7A400)
+       int select;
+
+       if (ssp_configuration.device == DEVICE_CODEC)
+               select = CPLD_SPIC_CS_CODEC;
+       else if (ssp_configuration.device == DEVICE_TOUCH)
+               select = CPLD_SPIC_CS_TOUCH;
+       else
+               return;
+
+       if (enable)
+               CPLD_SPIC = select;
+       else
+               CPLD_SPIC = 0;
+#endif
+}
+
+static void ssp_acquire (void)
+{
+       spin_lock (&ssp_lock);
+}
+
+static void ssp_release (void)
+{
+       ssp_chip_select (0);    /* just in case */
+       spin_unlock (&ssp_lock);
+}
+
+static int ssp_configure (int device, int mode, int speed,
+                          int frame_size_write, int frame_size_read)
+{
+       ssp_configuration.device                = device;
+       ssp_configuration.mode                  = mode;
+       ssp_configuration.speed                 = speed;
+       ssp_configuration.frame_size_write      = frame_size_write;
+       ssp_configuration.frame_size_read       = frame_size_read;
+
+       return 0;
+}
+
+static int ssp_read (void)
+{
+       return execute_spi_command (0, 0, ssp_configuration.frame_size_read);
+}
+
+static int ssp_write (u16 data)
+{
+       execute_spi_command (data, ssp_configuration.frame_size_write, 0);
+       return 0;
+}
+
+static int ssp_write_read (u16 data)
+{
+       return execute_spi_command (data, ssp_configuration.frame_size_write,
+                                   ssp_configuration.frame_size_read);
+}
+
+struct ssp_driver lh7a40x_cpld_ssp_driver = {
+       .init           = ssp_init,
+       .acquire        = ssp_acquire,
+       .release        = ssp_release,
+       .configure      = ssp_configure,
+       .chip_select    = ssp_chip_select,
+       .read           = ssp_read,
+       .write          = ssp_write,
+       .write_read     = ssp_write_read,
+};
+
+
+MODULE_AUTHOR("Marc Singer");
+MODULE_DESCRIPTION("LPD7A40X CPLD SPI driver");
+MODULE_LICENSE("GPL");
index be377e331f255baeceb7530f41dfbd00b8694c9c..ef9af375fcc469e2b0773940d43e89020ae67541 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  *  arch/arm/mach-lh7a40x/time.c
  *
  *  Copyright (C) 2004 Logic Product Development
@@ -57,7 +57,7 @@ static struct irqaction lh7a40x_timer_irq = {
        .handler        = lh7a40x_timer_interrupt,
 };
 
-static void __init lh7a40x_timer_init(void)
+static void __init lh7a40x_timer_init (void)
 {
                                /* Stop/disable all timers */
        TIMER_CONTROL1 = 0;
diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile
new file mode 100644 (file)
index 0000000..b457ca0
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y                  := core.o irq.o time.o clock.o gpio.o serial.o dma.o
+obj-m                  :=
+obj-n                  :=
+obj-                   :=
+
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
diff --git a/arch/arm/mach-pnx4008/Makefile.boot b/arch/arm/mach-pnx4008/Makefile.boot
new file mode 100644 (file)
index 0000000..44c7117
--- /dev/null
@@ -0,0 +1,4 @@
+   zreladdr-y          := 0x80008000
+params_phys-y          := 0x80000100
+initrd_phys-y          := 0x80800000
+
diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c
new file mode 100644 (file)
index 0000000..285b22f
--- /dev/null
@@ -0,0 +1,1010 @@
+/*
+ * arch/arm/mach-pnx4008/clock.c
+ *
+ * Clock control driver for PNX4008
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ * Generic clock management functions are partially based on:
+ *  linux/arch/arm/mach-omap/clock.c
+ *
+ * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <asm/semaphore.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include "clock.h"
+
+/*forward declaration*/
+static struct clk per_ck;
+static struct clk hclk_ck;
+static struct clk ck_1MHz;
+static struct clk ck_13MHz;
+static struct clk ck_pll1;
+static int local_set_rate(struct clk *clk, u32 rate);
+
+static inline void clock_lock(void)
+{
+       local_irq_disable();
+}
+
+static inline void clock_unlock(void)
+{
+       local_irq_enable();
+}
+
+static void propagate_rate(struct clk *clk)
+{
+       struct clk *tmp_clk;
+
+       tmp_clk = clk;
+       while (tmp_clk->propagate_next) {
+               tmp_clk = tmp_clk->propagate_next;
+               local_set_rate(tmp_clk, tmp_clk->user_rate);
+       }
+}
+
+static inline void clk_reg_disable(struct clk *clk)
+{
+       if (clk->enable_reg)
+               __raw_writel(__raw_readl(clk->enable_reg) &
+                            ~(1 << clk->enable_shift), clk->enable_reg);
+}
+
+static inline void clk_reg_enable(struct clk *clk)
+{
+       if (clk->enable_reg)
+               __raw_writel(__raw_readl(clk->enable_reg) |
+                            (1 << clk->enable_shift), clk->enable_reg);
+}
+
+static inline void clk_reg_disable1(struct clk *clk)
+{
+       if (clk->enable_reg1)
+               __raw_writel(__raw_readl(clk->enable_reg1) &
+                            ~(1 << clk->enable_shift1), clk->enable_reg1);
+}
+
+static inline void clk_reg_enable1(struct clk *clk)
+{
+       if (clk->enable_reg1)
+               __raw_writel(__raw_readl(clk->enable_reg1) |
+                            (1 << clk->enable_shift1), clk->enable_reg1);
+}
+
+static int clk_wait_for_pll_lock(struct clk *clk)
+{
+       int i;
+       i = 0;
+       while (i++ < 0xFFF && !(__raw_readl(clk->scale_reg) & 1)) ;     /*wait for PLL to lock */
+
+       if (!(__raw_readl(clk->scale_reg) & 1)) {
+               printk(KERN_ERR
+                      "%s ERROR: failed to lock, scale reg data: %x\n",
+                      clk->name, __raw_readl(clk->scale_reg));
+               return -1;
+       }
+       return 0;
+}
+
+static int switch_to_dirty_13mhz(struct clk *clk)
+{
+       int i;
+       int ret;
+       u32 tmp_reg;
+
+       ret = 0;
+
+       if (!clk->rate)
+               clk_reg_enable1(clk);
+
+       tmp_reg = __raw_readl(clk->parent_switch_reg);
+       /*if 13Mhz clock selected, select 13'MHz (dirty) source from OSC */
+       if (!(tmp_reg & 1)) {
+               tmp_reg |= (1 << 1);    /* Trigger switch to 13'MHz (dirty) clock */
+               __raw_writel(tmp_reg, clk->parent_switch_reg);
+               i = 0;
+               while (i++ < 0xFFF && !(__raw_readl(clk->parent_switch_reg) & 1)) ;     /*wait for 13'MHz selection status */
+
+               if (!(__raw_readl(clk->parent_switch_reg) & 1)) {
+                       printk(KERN_ERR
+                              "%s ERROR: failed to select 13'MHz, parent sw reg data: %x\n",
+                              clk->name, __raw_readl(clk->parent_switch_reg));
+                       ret = -1;
+               }
+       }
+
+       if (!clk->rate)
+               clk_reg_disable1(clk);
+
+       return ret;
+}
+
+static int switch_to_clean_13mhz(struct clk *clk)
+{
+       int i;
+       int ret;
+       u32 tmp_reg;
+
+       ret = 0;
+
+       if (!clk->rate)
+               clk_reg_enable1(clk);
+
+       tmp_reg = __raw_readl(clk->parent_switch_reg);
+       /*if 13'Mhz clock selected, select 13MHz (clean) source from OSC */
+       if (tmp_reg & 1) {
+               tmp_reg &= ~(1 << 1);   /* Trigger switch to 13MHz (clean) clock */
+               __raw_writel(tmp_reg, clk->parent_switch_reg);
+               i = 0;
+               while (i++ < 0xFFF && (__raw_readl(clk->parent_switch_reg) & 1)) ;      /*wait for 13MHz selection status */
+
+               if (__raw_readl(clk->parent_switch_reg) & 1) {
+                       printk(KERN_ERR
+                              "%s ERROR: failed to select 13MHz, parent sw reg data: %x\n",
+                              clk->name, __raw_readl(clk->parent_switch_reg));
+                       ret = -1;
+               }
+       }
+
+       if (!clk->rate)
+               clk_reg_disable1(clk);
+
+       return ret;
+}
+
+static int set_13MHz_parent(struct clk *clk, struct clk *parent)
+{
+       int ret = -EINVAL;
+
+       if (parent == &ck_13MHz)
+               ret = switch_to_clean_13mhz(clk);
+       else if (parent == &ck_pll1)
+               ret = switch_to_dirty_13mhz(clk);
+
+       return ret;
+}
+
+#define PLL160_MIN_FCCO 156000
+#define PLL160_MAX_FCCO 320000
+
+/*
+ * Calculate pll160 settings.
+ * Possible input: up to 320MHz with step of clk->parent->rate.
+ * In PNX4008 parent rate for pll160s may be either 1 or 13MHz.
+ * Ignored paths: "feedback" (bit 13 set), "div-by-N".
+ * Setting ARM PLL4 rate to 0 will put CPU into direct run mode.
+ * Setting PLL5 and PLL3 rate to 0 will disable USB and DSP clock input.
+ * Please refer to PNX4008 IC manual for details.
+ */
+
+static int pll160_set_rate(struct clk *clk, u32 rate)
+{
+       u32 tmp_reg, tmp_m, tmp_2p, i;
+       u32 parent_rate;
+       int ret = -EINVAL;
+
+       parent_rate = clk->parent->rate;
+
+       if (!parent_rate)
+               goto out;
+
+       /* set direct run for ARM or disable output for others  */
+       clk_reg_disable(clk);
+
+       /* disable source input as well (ignored for ARM) */
+       clk_reg_disable1(clk);
+
+       tmp_reg = __raw_readl(clk->scale_reg);
+       tmp_reg &= ~0x1ffff;    /*clear all settings, power down */
+       __raw_writel(tmp_reg, clk->scale_reg);
+
+       rate -= rate % parent_rate;     /*round down the input */
+
+       if (rate > PLL160_MAX_FCCO)
+               rate = PLL160_MAX_FCCO;
+
+       if (!rate) {
+               clk->rate = 0;
+               ret = 0;
+               goto out;
+       }
+
+       clk_reg_enable1(clk);
+       tmp_reg = __raw_readl(clk->scale_reg);
+
+       if (rate == parent_rate) {
+               /*enter direct bypass mode */
+               tmp_reg |= ((1 << 14) | (1 << 15));
+               __raw_writel(tmp_reg, clk->scale_reg);
+               clk->rate = parent_rate;
+               clk_reg_enable(clk);
+               ret = 0;
+               goto out;
+       }
+
+       i = 0;
+       for (tmp_2p = 1; tmp_2p < 16; tmp_2p <<= 1) {
+               if (rate * tmp_2p >= PLL160_MIN_FCCO)
+                       break;
+               i++;
+       }
+
+       if (tmp_2p > 1)
+               tmp_reg |= ((i - 1) << 11);
+       else
+               tmp_reg |= (1 << 14);   /*direct mode, no divide */
+
+       tmp_m = rate * tmp_2p;
+       tmp_m /= parent_rate;
+
+       tmp_reg |= (tmp_m - 1) << 1;    /*calculate M */
+       tmp_reg |= (1 << 16);   /*power up PLL */
+       __raw_writel(tmp_reg, clk->scale_reg);
+
+       if (clk_wait_for_pll_lock(clk) < 0) {
+               clk_reg_disable(clk);
+               clk_reg_disable1(clk);
+
+               tmp_reg = __raw_readl(clk->scale_reg);
+               tmp_reg &= ~0x1ffff;    /*clear all settings, power down */
+               __raw_writel(tmp_reg, clk->scale_reg);
+               clk->rate = 0;
+               ret = -EFAULT;
+               goto out;
+       }
+
+       clk->rate = (tmp_m * parent_rate) / tmp_2p;
+
+       if (clk->flags & RATE_PROPAGATES)
+               propagate_rate(clk);
+
+       clk_reg_enable(clk);
+       ret = 0;
+
+out:
+       return ret;
+}
+
+/*configure PER_CLK*/
+static int per_clk_set_rate(struct clk *clk, u32 rate)
+{
+       u32 tmp;
+
+       tmp = __raw_readl(clk->scale_reg);
+       tmp &= ~(0x1f << 2);
+       tmp |= ((clk->parent->rate / clk->rate) - 1) << 2;
+       __raw_writel(tmp, clk->scale_reg);
+       clk->rate = rate;
+       return 0;
+}
+
+/*configure HCLK*/
+static int hclk_set_rate(struct clk *clk, u32 rate)
+{
+       u32 tmp;
+       tmp = __raw_readl(clk->scale_reg);
+       tmp = tmp & ~0x3;
+       switch (rate) {
+       case 1:
+               break;
+       case 2:
+               tmp |= 1;
+               break;
+       case 4:
+               tmp |= 2;
+               break;
+       }
+
+       __raw_writel(tmp, clk->scale_reg);
+       clk->rate = rate;
+       return 0;
+}
+
+static u32 hclk_round_rate(struct clk *clk, u32 rate)
+{
+       switch (rate) {
+       case 1:
+       case 4:
+               return rate;
+       }
+       return 2;
+}
+
+static u32 per_clk_round_rate(struct clk *clk, u32 rate)
+{
+       return CLK_RATE_13MHZ;
+}
+
+static int on_off_set_rate(struct clk *clk, u32 rate)
+{
+       if (rate) {
+               clk_reg_enable(clk);
+               clk->rate = 1;
+       } else {
+               clk_reg_disable(clk);
+               clk->rate = 0;
+       }
+       return 0;
+}
+
+static int on_off_inv_set_rate(struct clk *clk, u32 rate)
+{
+       if (rate) {
+               clk_reg_disable(clk);   /*enable bit is inverted */
+               clk->rate = 1;
+       } else {
+               clk_reg_enable(clk);
+               clk->rate = 0;
+       }
+       return 0;
+}
+
+static u32 on_off_round_rate(struct clk *clk, u32 rate)
+{
+       return (rate ? 1 : 0);
+}
+
+static u32 pll4_round_rate(struct clk *clk, u32 rate)
+{
+       if (rate > CLK_RATE_208MHZ)
+               rate = CLK_RATE_208MHZ;
+       if (rate == CLK_RATE_208MHZ && hclk_ck.user_rate == 1)
+               rate = CLK_RATE_208MHZ - CLK_RATE_13MHZ;
+       return (rate - (rate % (hclk_ck.user_rate * CLK_RATE_13MHZ)));
+}
+
+static u32 pll3_round_rate(struct clk *clk, u32 rate)
+{
+       if (rate > CLK_RATE_208MHZ)
+               rate = CLK_RATE_208MHZ;
+       return (rate - rate % CLK_RATE_13MHZ);
+}
+
+static u32 pll5_round_rate(struct clk *clk, u32 rate)
+{
+       return (rate ? CLK_RATE_48MHZ : 0);
+}
+
+static u32 ck_13MHz_round_rate(struct clk *clk, u32 rate)
+{
+       return (rate ? CLK_RATE_13MHZ : 0);
+}
+
+static int ck_13MHz_set_rate(struct clk *clk, u32 rate)
+{
+       if (rate) {
+               clk_reg_disable(clk);   /*enable bit is inverted */
+               udelay(500);
+               clk->rate = CLK_RATE_13MHZ;
+               ck_1MHz.rate = CLK_RATE_1MHZ;
+       } else {
+               clk_reg_enable(clk);
+               clk->rate = 0;
+               ck_1MHz.rate = 0;
+       }
+       return 0;
+}
+
+static int pll1_set_rate(struct clk *clk, u32 rate)
+{
+#if 0 /* doesn't work on some boards, probably a HW BUG */
+       if (rate) {
+               clk_reg_disable(clk);   /*enable bit is inverted */
+               if (!clk_wait_for_pll_lock(clk)) {
+                       clk->rate = CLK_RATE_13MHZ;
+               } else {
+                       clk_reg_enable(clk);
+                       clk->rate = 0;
+               }
+
+       } else {
+               clk_reg_enable(clk);
+               clk->rate = 0;
+       }
+#endif
+       return 0;
+}
+
+/* Clock sources */
+
+static struct clk osc_13MHz = {
+       .name = "osc_13MHz",
+       .flags = FIXED_RATE,
+       .rate = CLK_RATE_13MHZ,
+};
+
+static struct clk ck_13MHz = {
+       .name = "ck_13MHz",
+       .parent = &osc_13MHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &ck_13MHz_round_rate,
+       .set_rate = &ck_13MHz_set_rate,
+       .enable_reg = OSC13CTRL_REG,
+       .enable_shift = 0,
+       .rate = CLK_RATE_13MHZ,
+};
+
+static struct clk osc_32KHz = {
+       .name = "osc_32KHz",
+       .flags = FIXED_RATE,
+       .rate = CLK_RATE_32KHZ,
+};
+
+/*attached to PLL5*/
+static struct clk ck_1MHz = {
+       .name = "ck_1MHz",
+       .flags = FIXED_RATE | PARENT_SET_RATE,
+       .parent = &ck_13MHz,
+};
+
+/* PLL1 (397) - provides 13' MHz clock */
+static struct clk ck_pll1 = {
+       .name = "ck_pll1",
+       .parent = &osc_32KHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &ck_13MHz_round_rate,
+       .set_rate = &pll1_set_rate,
+       .enable_reg = PLLCTRL_REG,
+       .enable_shift = 1,
+       .scale_reg = PLLCTRL_REG,
+       .rate = CLK_RATE_13MHZ,
+};
+
+/* CPU/Bus PLL */
+static struct clk ck_pll4 = {
+       .name = "ck_pll4",
+       .parent = &ck_pll1,
+       .flags = RATE_PROPAGATES | NEEDS_INITIALIZATION,
+       .propagate_next = &per_ck,
+       .round_rate = &pll4_round_rate,
+       .set_rate = &pll160_set_rate,
+       .rate = CLK_RATE_208MHZ,
+       .scale_reg = HCLKPLLCTRL_REG,
+       .enable_reg = PWRCTRL_REG,
+       .enable_shift = 2,
+       .parent_switch_reg = SYSCLKCTRL_REG,
+       .set_parent = &set_13MHz_parent,
+};
+
+/* USB PLL */
+static struct clk ck_pll5 = {
+       .name = "ck_pll5",
+       .parent = &ck_1MHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &pll5_round_rate,
+       .set_rate = &pll160_set_rate,
+       .scale_reg = USBCTRL_REG,
+       .enable_reg = USBCTRL_REG,
+       .enable_shift = 18,
+       .enable_reg1 = USBCTRL_REG,
+       .enable_shift1 = 17,
+};
+
+/* XPERTTeak DSP PLL */
+static struct clk ck_pll3 = {
+       .name = "ck_pll3",
+       .parent = &ck_pll1,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &pll3_round_rate,
+       .set_rate = &pll160_set_rate,
+       .scale_reg = DSPPLLCTRL_REG,
+       .enable_reg = DSPCLKCTRL_REG,
+       .enable_shift = 3,
+       .enable_reg1 = DSPCLKCTRL_REG,
+       .enable_shift1 = 2,
+       .parent_switch_reg = DSPCLKCTRL_REG,
+       .set_parent = &set_13MHz_parent,
+};
+
+static struct clk hclk_ck = {
+       .name = "hclk_ck",
+       .parent = &ck_pll4,
+       .flags = PARENT_SET_RATE,
+       .set_rate = &hclk_set_rate,
+       .round_rate = &hclk_round_rate,
+       .scale_reg = HCLKDIVCTRL_REG,
+       .rate = 2,
+       .user_rate = 2,
+};
+
+static struct clk per_ck = {
+       .name = "per_ck",
+       .parent = &ck_pll4,
+       .flags = FIXED_RATE,
+       .propagate_next = &hclk_ck,
+       .set_rate = &per_clk_set_rate,
+       .round_rate = &per_clk_round_rate,
+       .scale_reg = HCLKDIVCTRL_REG,
+       .rate = CLK_RATE_13MHZ,
+       .user_rate = CLK_RATE_13MHZ,
+};
+
+static struct clk m2hclk_ck = {
+       .name = "m2hclk_ck",
+       .parent = &hclk_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_inv_set_rate,
+       .rate = 1,
+       .enable_shift = 6,
+       .enable_reg = PWRCTRL_REG,
+};
+
+static struct clk vfp9_ck = {
+       .name = "vfp9_ck",
+       .parent = &ck_pll4,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .rate = 1,
+       .enable_shift = 4,
+       .enable_reg = VFP9CLKCTRL_REG,
+};
+
+static struct clk keyscan_ck = {
+       .name = "keyscan_ck",
+       .parent = &osc_32KHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = KEYCLKCTRL_REG,
+};
+
+static struct clk touch_ck = {
+       .name = "touch_ck",
+       .parent = &osc_32KHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = TSCLKCTRL_REG,
+};
+
+static struct clk pwm1_ck = {
+       .name = "pwm1_ck",
+       .parent = &osc_32KHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = PWMCLKCTRL_REG,
+};
+
+static struct clk pwm2_ck = {
+       .name = "pwm2_ck",
+       .parent = &osc_32KHz,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 2,
+       .enable_reg = PWMCLKCTRL_REG,
+};
+
+static struct clk jpeg_ck = {
+       .name = "jpeg_ck",
+       .parent = &hclk_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = JPEGCLKCTRL_REG,
+};
+
+static struct clk ms_ck = {
+       .name = "ms_ck",
+       .parent = &ck_pll4,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 5,
+       .enable_reg = MSCTRL_REG,
+};
+
+static struct clk dum_ck = {
+       .name = "dum_ck",
+       .parent = &hclk_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = DUMCLKCTRL_REG,
+};
+
+static struct clk flash_ck = {
+       .name = "flash_ck",
+       .parent = &hclk_ck,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 1,      /* Only MLC clock supported */
+       .enable_reg = FLASHCLKCTRL_REG,
+};
+
+static struct clk i2c0_ck = {
+       .name = "i2c0_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = I2CCLKCTRL_REG,
+};
+
+static struct clk i2c1_ck = {
+       .name = "i2c1_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 1,
+       .enable_reg = I2CCLKCTRL_REG,
+};
+
+static struct clk i2c2_ck = {
+       .name = "i2c2_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 2,
+       .enable_reg = USB_OTG_CLKCTRL_REG,
+};
+
+static struct clk spi0_ck = {
+       .name = "spi0_ck",
+       .parent = &hclk_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = SPICTRL_REG,
+};
+
+static struct clk spi1_ck = {
+       .name = "spi1_ck",
+       .parent = &hclk_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 4,
+       .enable_reg = SPICTRL_REG,
+};
+
+static struct clk dma_ck = {
+       .name = "dma_ck",
+       .parent = &hclk_ck,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 0,
+       .enable_reg = DMACLKCTRL_REG,
+};
+
+static struct clk uart3_ck = {
+       .name = "uart3_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .rate = 1,
+       .enable_shift = 0,
+       .enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart4_ck = {
+       .name = "uart4_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 1,
+       .enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart5_ck = {
+       .name = "uart5_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .rate = 1,
+       .enable_shift = 2,
+       .enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart6_ck = {
+       .name = "uart6_ck",
+       .parent = &per_ck,
+       .flags = NEEDS_INITIALIZATION,
+       .round_rate = &on_off_round_rate,
+       .set_rate = &on_off_set_rate,
+       .enable_shift = 3,
+       .enable_reg = UARTCLKCTRL_REG,
+};
+
+/* These clocks are visible outside this module
+ * and can be initialized
+ */
+static struct clk *onchip_clks[] = {
+       &ck_13MHz,
+       &ck_pll1,
+       &ck_pll4,
+       &ck_pll5,
+       &ck_pll3,
+       &vfp9_ck,
+       &m2hclk_ck,
+       &hclk_ck,
+       &dma_ck,
+       &flash_ck,
+       &dum_ck,
+       &keyscan_ck,
+       &pwm1_ck,
+       &pwm2_ck,
+       &jpeg_ck,
+       &ms_ck,
+       &touch_ck,
+       &i2c0_ck,
+       &i2c1_ck,
+       &i2c2_ck,
+       &spi0_ck,
+       &spi1_ck,
+       &uart3_ck,
+       &uart4_ck,
+       &uart5_ck,
+       &uart6_ck,
+};
+
+static int local_set_rate(struct clk *clk, u32 rate)
+{
+       int ret = -EINVAL;
+       if (clk->set_rate) {
+
+               if (clk->user_rate == clk->rate && clk->parent->rate) {
+                       /* if clock enabled or rate not set */
+                       clk->user_rate = clk->round_rate(clk, rate);
+                       ret = clk->set_rate(clk, clk->user_rate);
+               } else
+                       clk->user_rate = clk->round_rate(clk, rate);
+               ret = 0;
+       }
+       return ret;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       int ret = -EINVAL;
+
+       if (clk->flags & FIXED_RATE)
+               goto out;
+
+       clock_lock();
+       if ((clk->flags & PARENT_SET_RATE) && clk->parent) {
+
+               clk->user_rate = clk->round_rate(clk, rate);
+               /* parent clock needs to be refreshed
+                  for the setting to take effect */
+       } else {
+               ret = local_set_rate(clk, rate);
+       }
+       ret = 0;
+       clock_unlock();
+
+out:
+       return ret;
+}
+
+EXPORT_SYMBOL(clk_set_rate);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       struct clk *clk = ERR_PTR(-ENOENT);
+       struct clk **clkp;
+
+       clock_lock();
+       for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+            clkp++) {
+               if (strcmp(id, (*clkp)->name) == 0
+                   && try_module_get((*clkp)->owner)) {
+                       clk = (*clkp);
+                       break;
+               }
+       }
+       clock_unlock();
+
+       return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+       clock_lock();
+       if (clk && !IS_ERR(clk))
+               module_put(clk->owner);
+       clock_unlock();
+}
+EXPORT_SYMBOL(clk_put);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       unsigned long ret;
+       clock_lock();
+       ret = clk->rate;
+       clock_unlock();
+       return ret;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+static int local_clk_enable(struct clk *clk)
+{
+       int ret = 0;
+
+       if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
+           && clk->user_rate)
+               ret = clk->set_rate(clk, clk->user_rate);
+       return ret;
+}
+
+static void local_clk_disable(struct clk *clk)
+{
+       if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
+               clk->set_rate(clk, 0);
+}
+
+int clk_enable(struct clk *clk)
+{
+       int ret = 0;
+
+       clock_lock();
+       ret = local_clk_enable(clk);
+       clock_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+       clock_lock();
+       local_clk_disable(clk);
+       clock_unlock();
+}
+
+EXPORT_SYMBOL(clk_disable);
+
+static void local_clk_unuse(struct clk *clk)
+{
+       if (clk->usecount > 0 && !(--clk->usecount)) {
+               local_clk_disable(clk);
+               if (clk->parent)
+                       local_clk_unuse(clk->parent);
+       }
+}
+
+static int local_clk_use(struct clk *clk)
+{
+       int ret = 0;
+       if (clk->usecount++ == 0) {
+               if (clk->parent)
+                       ret = local_clk_use(clk->parent);
+
+               if (ret != 0) {
+                       clk->usecount--;
+                       goto out;
+               }
+
+               ret = local_clk_enable(clk);
+
+               if (ret != 0 && clk->parent) {
+                       local_clk_unuse(clk->parent);
+                       clk->usecount--;
+               }
+       }
+out:
+       return ret;
+}
+
+/* The main purpose of clk_use ans clk_unuse functions
+ * is to control switching 13MHz oscillator and PLL1 (13'MHz),
+ * so that they are disabled whenever none of PLL2-5 is using them.
+ * Although in theory these functions should work with any clock,
+ * please use them only on PLL2 - PLL5 to avoid confusion.
+ */
+int clk_use(struct clk *clk)
+{
+       int ret = 0;
+
+       clock_lock();
+       ret = local_clk_use(clk);
+       clock_unlock();
+       return ret;
+}
+EXPORT_SYMBOL(clk_use);
+
+void clk_unuse(struct clk *clk)
+{
+
+       clock_lock();
+       local_clk_unuse(clk);
+       clock_unlock();
+}
+
+EXPORT_SYMBOL(clk_unuse);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       long ret;
+       clock_lock();
+       if (clk->round_rate)
+               ret = clk->round_rate(clk, rate);
+       else
+               ret = clk->rate;
+       clock_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       int ret = -ENODEV;
+       if (!clk->set_parent)
+               goto out;
+
+       clock_lock();
+       ret = clk->set_parent(clk, parent);
+       if (!ret)
+               clk->parent = parent;
+       clock_unlock();
+
+out:
+       return ret;
+}
+
+EXPORT_SYMBOL(clk_set_parent);
+
+static int __init clk_init(void)
+{
+       struct clk **clkp;
+
+       /* Disable autoclocking, as it doesn't seem to work */
+       __raw_writel(0xff, AUTOCLK_CTRL);
+
+       for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+            clkp++) {
+               if (((*clkp)->flags & NEEDS_INITIALIZATION)
+                   && ((*clkp)->set_rate)) {
+                       (*clkp)->user_rate = (*clkp)->rate;
+                       local_set_rate((*clkp), (*clkp)->user_rate);
+                       if ((*clkp)->set_parent)
+                               (*clkp)->set_parent((*clkp), (*clkp)->parent);
+               }
+               pr_debug("%s: clock %s, rate %ld\n",
+                       __FUNCTION__, (*clkp)->name, (*clkp)->rate);
+       }
+
+       clk_use(&ck_pll4);
+
+       /* if ck_13MHz is not used, disable it. */
+       if (ck_13MHz.usecount == 0)
+               local_clk_disable(&ck_13MHz);
+
+       /* Disable autoclocking */
+       __raw_writeb(0xff, AUTOCLK_CTRL);
+
+       return 0;
+}
+
+arch_initcall(clk_init);
diff --git a/arch/arm/mach-pnx4008/clock.h b/arch/arm/mach-pnx4008/clock.h
new file mode 100644 (file)
index 0000000..cd58f37
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * arch/arm/mach-pnx4008/clock.h
+ *
+ * Clock control driver for PNX4008 - internal header file
+ *
+ * Author: Vitaly Wool <source@mvista.com>
+ *
+ * 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ARCH_ARM_PNX4008_CLOCK_H__
+#define __ARCH_ARM_PNX4008_CLOCK_H__
+
+struct clk {
+       struct list_head node;
+       struct module *owner;
+       const char *name;
+       struct clk *parent;
+       struct clk *propagate_next;
+       u32 rate;
+       u32 user_rate;
+       s8 usecount;
+       u32 flags;
+       u32 scale_reg;
+       u8 enable_shift;
+       u32 enable_reg;
+       u8 enable_shift1;
+       u32 enable_reg1;
+       u32 parent_switch_reg;
+        u32(*round_rate) (struct clk *, u32);
+       int (*set_rate) (struct clk *, u32);
+       int (*set_parent) (struct clk * clk, struct clk * parent);
+};
+
+/* Flags */
+#define RATE_PROPAGATES      (1<<0)
+#define NEEDS_INITIALIZATION (1<<1)
+#define PARENT_SET_RATE      (1<<2)
+#define FIXED_RATE           (1<<3)
+
+#endif
diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c
new file mode 100644 (file)
index 0000000..ba91daa
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * arch/arm/mach-pnx4008/core.c
+ *
+ * PNX4008 core startup code
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev,
+ * Grigory Tolstolytkin, Dmitry Pervushin <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/serial_8250.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <asm/arch/irq.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dma.h>
+
+struct resource spipnx_0_resources[] = {
+       {
+               .start = PNX4008_SPI1_BASE,
+               .end = PNX4008_SPI1_BASE + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = PER_SPI1_REC_XMIT,
+               .flags = IORESOURCE_DMA,
+       }, {
+               .start = SPI1_INT,
+               .flags = IORESOURCE_IRQ,
+       }, {
+               .flags = 0,
+       },
+};
+
+struct resource spipnx_1_resources[] = {
+       {
+               .start = PNX4008_SPI2_BASE,
+               .end = PNX4008_SPI2_BASE + SZ_4K,
+               .flags = IORESOURCE_MEM,
+       }, {
+               .start = PER_SPI2_REC_XMIT,
+               .flags = IORESOURCE_DMA,
+       }, {
+               .start = SPI2_INT,
+               .flags = IORESOURCE_IRQ,
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct spi_board_info spi_board_info[] __initdata = {
+       {
+               .modalias       = "m25p80",
+               .max_speed_hz   = 1000000,
+               .bus_num        = 1,
+               .chip_select    = 0,
+       },
+};
+
+static struct platform_device spipnx_1 = {
+       .name = "spipnx",
+       .id = 1,
+       .num_resources = ARRAY_SIZE(spipnx_0_resources),
+       .resource = spipnx_0_resources,
+       .dev = {
+               .coherent_dma_mask = 0xFFFFFFFF,
+               },
+};
+
+static struct platform_device spipnx_2 = {
+       .name = "spipnx",
+       .id = 2,
+       .num_resources = ARRAY_SIZE(spipnx_1_resources),
+       .resource = spipnx_1_resources,
+       .dev = {
+               .coherent_dma_mask = 0xFFFFFFFF,
+               },
+};
+
+static struct plat_serial8250_port platform_serial_ports[] = {
+       {
+               .membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART5_BASE)),
+               .mapbase = (unsigned long)PNX4008_UART5_BASE,
+               .irq = IIR5_INT,
+               .uartclk = PNX4008_UART_CLK,
+               .regshift = 2,
+               .iotype = UPIO_MEM,
+               .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
+       },
+       {
+               .membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART3_BASE)),
+               .mapbase = (unsigned long)PNX4008_UART3_BASE,
+               .irq = IIR3_INT,
+               .uartclk = PNX4008_UART_CLK,
+               .regshift = 2,
+               .iotype = UPIO_MEM,
+               .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
+        },
+       {}
+};
+
+static struct platform_device serial_device = {
+       .name = "serial8250",
+       .id = PLAT8250_DEV_PLATFORM,
+       .dev = {
+               .platform_data = &platform_serial_ports,
+       },
+};
+
+static struct platform_device *devices[] __initdata = {
+       &spipnx_1,
+       &spipnx_2,
+       &serial_device,
+};
+
+
+extern void pnx4008_uart_init(void);
+
+static void __init pnx4008_init(void)
+{
+       /*disable all START interrupt sources,
+          and clear all START interrupt flags */
+       __raw_writel(0, START_INT_ER_REG(SE_PIN_BASE_INT));
+       __raw_writel(0, START_INT_ER_REG(SE_INT_BASE_INT));
+       __raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
+       __raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
+
+       platform_add_devices(devices, ARRAY_SIZE(devices));
+       spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+       /* Switch on the UART clocks */
+       pnx4008_uart_init();
+}
+
+static struct map_desc pnx4008_io_desc[] __initdata = {
+       {
+               .virtual        = IO_ADDRESS(PNX4008_IRAM_BASE),
+               .pfn            = __phys_to_pfn(PNX4008_IRAM_BASE),
+               .length         = SZ_64K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = IO_ADDRESS(PNX4008_NDF_FLASH_BASE),
+               .pfn            = __phys_to_pfn(PNX4008_NDF_FLASH_BASE),
+               .length         = SZ_1M - SZ_128K,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = IO_ADDRESS(PNX4008_JPEG_CONFIG_BASE),
+               .pfn            = __phys_to_pfn(PNX4008_JPEG_CONFIG_BASE),
+               .length         = SZ_128K * 3,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = IO_ADDRESS(PNX4008_DMA_CONFIG_BASE),
+               .pfn            = __phys_to_pfn(PNX4008_DMA_CONFIG_BASE),
+               .length         = SZ_1M,
+               .type           = MT_DEVICE,
+       }, {
+               .virtual        = IO_ADDRESS(PNX4008_AHB2FAB_BASE),
+               .pfn            = __phys_to_pfn(PNX4008_AHB2FAB_BASE),
+               .length         = SZ_1M,
+               .type           = MT_DEVICE,
+       },
+};
+
+void __init pnx4008_map_io(void)
+{
+       iotable_init(pnx4008_io_desc, ARRAY_SIZE(pnx4008_io_desc));
+}
+
+extern struct sys_timer pnx4008_timer;
+
+MACHINE_START(PNX4008, "Philips PNX4008")
+       /* Maintainer: MontaVista Software Inc. */
+       .phys_io                = 0x40090000,
+       .io_pg_offst            = (0xf4090000 >> 18) & 0xfffc,
+       .boot_params            = 0x80000100,
+       .map_io                 = pnx4008_map_io,
+       .init_irq               = pnx4008_init_irq,
+       .init_machine           = pnx4008_init,
+       .timer                  = &pnx4008_timer,
+MACHINE_END
diff --git a/arch/arm/mach-pnx4008/dma.c b/arch/arm/mach-pnx4008/dma.c
new file mode 100644 (file)
index 0000000..981aa9d
--- /dev/null
@@ -0,0 +1,1109 @@
+/*
+ *  linux/arch/arm/mach-pnx4008/dma.c
+ *
+ *  PNX4008 DMA registration and IRQ dispatching
+ *
+ *  Author:    Vitaly Wool
+ *  Copyright: MontaVista Software Inc. (c) 2005
+ *
+ *  Based on the code from Nicolas Pitre
+ *
+ *  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/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+#include <asm/dma-mapping.h>
+#include <asm/io.h>
+#include <asm/mach/dma.h>
+#include <asm/arch/clock.h>
+
+static struct dma_channel {
+       char *name;
+       void (*irq_handler) (int, int, void *, struct pt_regs *);
+       void *data;
+       struct pnx4008_dma_ll *ll;
+       u32 ll_dma;
+       void *target_addr;
+       int target_id;
+} dma_channels[MAX_DMA_CHANNELS];
+
+static struct ll_pool {
+       void *vaddr;
+       void *cur;
+       dma_addr_t dma_addr;
+       int count;
+} ll_pool;
+
+static spinlock_t ll_lock = SPIN_LOCK_UNLOCKED;
+
+struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t * ll_dma)
+{
+       struct pnx4008_dma_ll *ll = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ll_lock, flags);
+       if (ll_pool.count > 4) { /* can give one more */
+               ll = *(struct pnx4008_dma_ll **) ll_pool.cur;
+               *ll_dma = ll_pool.dma_addr + ((void *)ll - ll_pool.vaddr);
+               *(void **)ll_pool.cur = **(void ***)ll_pool.cur;
+               memset(ll, 0, sizeof(*ll));
+               ll_pool.count--;
+       }
+       spin_unlock_irqrestore(&ll_lock, flags);
+
+       return ll;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_alloc_ll_entry);
+
+void pnx4008_free_ll_entry(struct pnx4008_dma_ll * ll, dma_addr_t ll_dma)
+{
+       unsigned long flags;
+
+       if (ll) {
+               if ((unsigned long)((long)ll - (long)ll_pool.vaddr) > 0x4000) {
+                       printk(KERN_ERR "Trying to free entry not allocated by DMA\n");
+                       BUG();
+               }
+
+               if (ll->flags & DMA_BUFFER_ALLOCATED)
+                       ll->free(ll->alloc_data);
+
+               spin_lock_irqsave(&ll_lock, flags);
+               *(long *)ll = *(long *)ll_pool.cur;
+               *(long *)ll_pool.cur = (long)ll;
+               ll_pool.count++;
+               spin_unlock_irqrestore(&ll_lock, flags);
+       }
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_ll_entry);
+
+void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll * ll)
+{
+       struct pnx4008_dma_ll *ptr;
+       u32 dma;
+
+       while (ll) {
+               dma = ll->next_dma;
+               ptr = ll->next;
+               pnx4008_free_ll_entry(ll, ll_dma);
+
+               ll_dma = dma;
+               ll = ptr;
+       }
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_ll);
+
+static int dma_channels_requested = 0;
+
+static inline void dma_increment_usage(void)
+{
+       if (!dma_channels_requested++) {
+               struct clk *clk = clk_get(0, "dma_ck");
+               if (!IS_ERR(clk)) {
+                       clk_set_rate(clk, 1);
+                       clk_put(clk);
+               }
+               pnx4008_config_dma(-1, -1, 1);
+       }
+}
+static inline void dma_decrement_usage(void)
+{
+       if (!--dma_channels_requested) {
+               struct clk *clk = clk_get(0, "dma_ck");
+               if (!IS_ERR(clk)) {
+                       clk_set_rate(clk, 0);
+                       clk_put(clk);
+               }
+               pnx4008_config_dma(-1, -1, 0);
+
+       }
+}
+
+static spinlock_t dma_lock = SPIN_LOCK_UNLOCKED;
+
+static inline void pnx4008_dma_lock(void)
+{
+       spin_lock_irq(&dma_lock);
+}
+
+static inline void pnx4008_dma_unlock(void)
+{
+       spin_unlock_irq(&dma_lock);
+}
+
+#define VALID_CHANNEL(c)       (((c) >= 0) && ((c) < MAX_DMA_CHANNELS))
+
+int pnx4008_request_channel(char *name, int ch,
+                           void (*irq_handler) (int, int, void *,
+                                                struct pt_regs *), void *data)
+{
+       int i, found = 0;
+
+       /* basic sanity checks */
+       if (!name || (ch != -1 && !VALID_CHANNEL(ch)))
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+
+       /* try grabbing a DMA channel with the requested priority */
+       for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
+               if (!dma_channels[i].name && (ch == -1 || ch == i)) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found) {
+               dma_increment_usage();
+               dma_channels[i].name = name;
+               dma_channels[i].irq_handler = irq_handler;
+               dma_channels[i].data = data;
+               dma_channels[i].ll = NULL;
+               dma_channels[i].ll_dma = 0;
+       } else {
+               printk(KERN_WARNING "No more available DMA channels for %s\n",
+                      name);
+               i = -ENODEV;
+       }
+
+       pnx4008_dma_unlock();
+       return i;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_request_channel);
+
+void pnx4008_free_channel(int ch)
+{
+       if (!dma_channels[ch].name) {
+               printk(KERN_CRIT
+                      "%s: trying to free channel %d which is already freed\n",
+                      __FUNCTION__, ch);
+               return;
+       }
+
+       pnx4008_dma_lock();
+       pnx4008_free_ll(dma_channels[ch].ll_dma, dma_channels[ch].ll);
+       dma_channels[ch].ll = NULL;
+       dma_decrement_usage();
+
+       dma_channels[ch].name = NULL;
+       pnx4008_dma_unlock();
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_channel);
+
+int pnx4008_config_dma(int ahb_m1_be, int ahb_m2_be, int enable)
+{
+       unsigned long dma_cfg = __raw_readl(DMAC_CONFIG);
+
+       switch (ahb_m1_be) {
+       case 0:
+               dma_cfg &= ~(1 << 1);
+               break;
+       case 1:
+               dma_cfg |= (1 << 1);
+               break;
+       default:
+               break;
+       }
+
+       switch (ahb_m2_be) {
+       case 0:
+               dma_cfg &= ~(1 << 2);
+               break;
+       case 1:
+               dma_cfg |= (1 << 2);
+               break;
+       default:
+               break;
+       }
+
+       switch (enable) {
+       case 0:
+               dma_cfg &= ~(1 << 0);
+               break;
+       case 1:
+               dma_cfg |= (1 << 0);
+               break;
+       default:
+               break;
+       }
+
+       pnx4008_dma_lock();
+       __raw_writel(dma_cfg, DMAC_CONFIG);
+       pnx4008_dma_unlock();
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_config_dma);
+
+int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl * ch_ctrl,
+                            unsigned long *ctrl)
+{
+       int i = 0, dbsize, sbsize, err = 0;
+
+       if (!ctrl || !ch_ctrl) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       *ctrl = 0;
+
+       switch (ch_ctrl->tc_mask) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 31);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+
+       switch (ch_ctrl->cacheable) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 30);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->bufferable) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 29);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->priv_mode) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 28);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->di) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 27);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->si) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 26);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->dest_ahb1) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 25);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->src_ahb1) {
+       case 0:
+               break;
+       case 1:
+               *ctrl |= (1 << 24);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->dwidth) {
+       case WIDTH_BYTE:
+               *ctrl &= ~(7 << 21);
+               break;
+       case WIDTH_HWORD:
+               *ctrl &= ~(7 << 21);
+               *ctrl |= (1 << 21);
+               break;
+       case WIDTH_WORD:
+               *ctrl &= ~(7 << 21);
+               *ctrl |= (2 << 21);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_ctrl->swidth) {
+       case WIDTH_BYTE:
+               *ctrl &= ~(7 << 18);
+               break;
+       case WIDTH_HWORD:
+               *ctrl &= ~(7 << 18);
+               *ctrl |= (1 << 18);
+               break;
+       case WIDTH_WORD:
+               *ctrl &= ~(7 << 18);
+               *ctrl |= (2 << 18);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       dbsize = ch_ctrl->dbsize;
+       while (!(dbsize & 1)) {
+               i++;
+               dbsize >>= 1;
+       }
+       if (ch_ctrl->dbsize != 1 || i > 8 || i == 1) {
+               err = -EINVAL;
+               goto out;
+       } else if (i > 1)
+               i--;
+       *ctrl &= ~(7 << 15);
+       *ctrl |= (i << 15);
+
+       sbsize = ch_ctrl->sbsize;
+       while (!(sbsize & 1)) {
+               i++;
+               sbsize >>= 1;
+       }
+       if (ch_ctrl->sbsize != 1 || i > 8 || i == 1) {
+               err = -EINVAL;
+               goto out;
+       } else if (i > 1)
+               i--;
+       *ctrl &= ~(7 << 12);
+       *ctrl |= (i << 12);
+
+       if (ch_ctrl->tr_size > 0x7ff) {
+               err = -E2BIG;
+               goto out;
+       }
+       *ctrl &= ~0x7ff;
+       *ctrl |= ch_ctrl->tr_size & 0x7ff;
+
+out:
+       return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_pack_control);
+
+int pnx4008_dma_parse_control(unsigned long ctrl,
+                             struct pnx4008_dma_ch_ctrl * ch_ctrl)
+{
+       int err = 0;
+
+       if (!ch_ctrl) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       ch_ctrl->tr_size = ctrl & 0x7ff;
+       ctrl >>= 12;
+
+       ch_ctrl->sbsize = 1 << (ctrl & 7);
+       if (ch_ctrl->sbsize > 1)
+               ch_ctrl->sbsize <<= 1;
+       ctrl >>= 3;
+
+       ch_ctrl->dbsize = 1 << (ctrl & 7);
+       if (ch_ctrl->dbsize > 1)
+               ch_ctrl->dbsize <<= 1;
+       ctrl >>= 3;
+
+       switch (ctrl & 7) {
+       case 0:
+               ch_ctrl->swidth = WIDTH_BYTE;
+               break;
+       case 1:
+               ch_ctrl->swidth = WIDTH_HWORD;
+               break;
+       case 2:
+               ch_ctrl->swidth = WIDTH_WORD;
+               break;
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       ctrl >>= 3;
+
+       switch (ctrl & 7) {
+       case 0:
+               ch_ctrl->dwidth = WIDTH_BYTE;
+               break;
+       case 1:
+               ch_ctrl->dwidth = WIDTH_HWORD;
+               break;
+       case 2:
+               ch_ctrl->dwidth = WIDTH_WORD;
+               break;
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       ctrl >>= 3;
+
+       ch_ctrl->src_ahb1 = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->dest_ahb1 = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->si = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->di = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->priv_mode = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->bufferable = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->cacheable = ctrl & 1;
+       ctrl >>= 1;
+
+       ch_ctrl->tc_mask = ctrl & 1;
+
+out:
+       return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_parse_control);
+
+int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config * ch_cfg,
+                           unsigned long *cfg)
+{
+       int err = 0;
+
+       if (!cfg || !ch_cfg) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       *cfg = 0;
+
+       switch (ch_cfg->halt) {
+       case 0:
+               break;
+       case 1:
+               *cfg |= (1 << 18);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_cfg->active) {
+       case 0:
+               break;
+       case 1:
+               *cfg |= (1 << 17);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_cfg->lock) {
+       case 0:
+               break;
+       case 1:
+               *cfg |= (1 << 16);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_cfg->itc) {
+       case 0:
+               break;
+       case 1:
+               *cfg |= (1 << 15);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_cfg->ie) {
+       case 0:
+               break;
+       case 1:
+               *cfg |= (1 << 14);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       switch (ch_cfg->flow_cntrl) {
+       case FC_MEM2MEM_DMA:
+               *cfg &= ~(7 << 11);
+               break;
+       case FC_MEM2PER_DMA:
+               *cfg &= ~(7 << 11);
+               *cfg |= (1 << 11);
+               break;
+       case FC_PER2MEM_DMA:
+               *cfg &= ~(7 << 11);
+               *cfg |= (2 << 11);
+               break;
+       case FC_PER2PER_DMA:
+               *cfg &= ~(7 << 11);
+               *cfg |= (3 << 11);
+               break;
+       case FC_PER2PER_DPER:
+               *cfg &= ~(7 << 11);
+               *cfg |= (4 << 11);
+               break;
+       case FC_MEM2PER_PER:
+               *cfg &= ~(7 << 11);
+               *cfg |= (5 << 11);
+               break;
+       case FC_PER2MEM_PER:
+               *cfg &= ~(7 << 11);
+               *cfg |= (6 << 11);
+               break;
+       case FC_PER2PER_SPER:
+               *cfg |= (7 << 11);
+               break;
+
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+       *cfg &= ~(0x1f << 6);
+       *cfg |= ((ch_cfg->dest_per & 0x1f) << 6);
+
+       *cfg &= ~(0x1f << 1);
+       *cfg |= ((ch_cfg->src_per & 0x1f) << 1);
+
+out:
+       return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_pack_config);
+
+int pnx4008_dma_parse_config(unsigned long cfg,
+                            struct pnx4008_dma_ch_config * ch_cfg)
+{
+       int err = 0;
+
+       if (!ch_cfg) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       cfg >>= 1;
+
+       ch_cfg->src_per = cfg & 0x1f;
+       cfg >>= 5;
+
+       ch_cfg->dest_per = cfg & 0x1f;
+       cfg >>= 5;
+
+       switch (cfg & 7) {
+       case 0:
+               ch_cfg->flow_cntrl = FC_MEM2MEM_DMA;
+               break;
+       case 1:
+               ch_cfg->flow_cntrl = FC_MEM2PER_DMA;
+               break;
+       case 2:
+               ch_cfg->flow_cntrl = FC_PER2MEM_DMA;
+               break;
+       case 3:
+               ch_cfg->flow_cntrl = FC_PER2PER_DMA;
+               break;
+       case 4:
+               ch_cfg->flow_cntrl = FC_PER2PER_DPER;
+               break;
+       case 5:
+               ch_cfg->flow_cntrl = FC_MEM2PER_PER;
+               break;
+       case 6:
+               ch_cfg->flow_cntrl = FC_PER2MEM_PER;
+               break;
+       case 7:
+               ch_cfg->flow_cntrl = FC_PER2PER_SPER;
+       }
+       cfg >>= 3;
+
+       ch_cfg->ie = cfg & 1;
+       cfg >>= 1;
+
+       ch_cfg->itc = cfg & 1;
+       cfg >>= 1;
+
+       ch_cfg->lock = cfg & 1;
+       cfg >>= 1;
+
+       ch_cfg->active = cfg & 1;
+       cfg >>= 1;
+
+       ch_cfg->halt = cfg & 1;
+
+out:
+       return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_parse_config);
+
+void pnx4008_dma_split_head_entry(struct pnx4008_dma_config * config,
+                                 struct pnx4008_dma_ch_ctrl * ctrl)
+{
+       int new_len = ctrl->tr_size, num_entries = 0;
+       int old_len = new_len;
+       int src_width, dest_width, count = 1;
+
+       switch (ctrl->swidth) {
+       case WIDTH_BYTE:
+               src_width = 1;
+               break;
+       case WIDTH_HWORD:
+               src_width = 2;
+               break;
+       case WIDTH_WORD:
+               src_width = 4;
+               break;
+       default:
+               return;
+       }
+
+       switch (ctrl->dwidth) {
+       case WIDTH_BYTE:
+               dest_width = 1;
+               break;
+       case WIDTH_HWORD:
+               dest_width = 2;
+               break;
+       case WIDTH_WORD:
+               dest_width = 4;
+               break;
+       default:
+               return;
+       }
+
+       while (new_len > 0x7FF) {
+               num_entries++;
+               new_len = (ctrl->tr_size + num_entries) / (num_entries + 1);
+       }
+       if (num_entries != 0) {
+               struct pnx4008_dma_ll *ll = NULL;
+               config->ch_ctrl &= ~0x7ff;
+               config->ch_ctrl |= new_len;
+               if (!config->is_ll) {
+                       config->is_ll = 1;
+                       while (num_entries) {
+                               if (!ll) {
+                                       config->ll =
+                                           pnx4008_alloc_ll_entry(&config->
+                                                                  ll_dma);
+                                       ll = config->ll;
+                               } else {
+                                       ll->next =
+                                           pnx4008_alloc_ll_entry(&ll->
+                                                                  next_dma);
+                                       ll = ll->next;
+                               }
+
+                               if (ctrl->si)
+                                       ll->src_addr =
+                                           config->src_addr +
+                                           src_width * new_len * count;
+                               else
+                                       ll->src_addr = config->src_addr;
+                               if (ctrl->di)
+                                       ll->dest_addr =
+                                           config->dest_addr +
+                                           dest_width * new_len * count;
+                               else
+                                       ll->dest_addr = config->dest_addr;
+                               ll->ch_ctrl = config->ch_ctrl & 0x7fffffff;
+                               ll->next_dma = 0;
+                               ll->next = NULL;
+                               num_entries--;
+                               count++;
+                       }
+               } else {
+                       struct pnx4008_dma_ll *ll_old = config->ll;
+                       unsigned long ll_dma_old = config->ll_dma;
+                       while (num_entries) {
+                               if (!ll) {
+                                       config->ll =
+                                           pnx4008_alloc_ll_entry(&config->
+                                                                  ll_dma);
+                                       ll = config->ll;
+                               } else {
+                                       ll->next =
+                                           pnx4008_alloc_ll_entry(&ll->
+                                                                  next_dma);
+                                       ll = ll->next;
+                               }
+
+                               if (ctrl->si)
+                                       ll->src_addr =
+                                           config->src_addr +
+                                           src_width * new_len * count;
+                               else
+                                       ll->src_addr = config->src_addr;
+                               if (ctrl->di)
+                                       ll->dest_addr =
+                                           config->dest_addr +
+                                           dest_width * new_len * count;
+                               else
+                                       ll->dest_addr = config->dest_addr;
+                               ll->ch_ctrl = config->ch_ctrl & 0x7fffffff;
+                               ll->next_dma = 0;
+                               ll->next = NULL;
+                               num_entries--;
+                               count++;
+                       }
+                       ll->next_dma = ll_dma_old;
+                       ll->next = ll_old;
+               }
+               /* adjust last length/tc */
+               ll->ch_ctrl = config->ch_ctrl & (~0x7ff);
+               ll->ch_ctrl |= old_len - new_len * (count - 1);
+               config->ch_ctrl &= 0x7fffffff;
+       }
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_split_head_entry);
+
+void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll * cur_ll,
+                               struct pnx4008_dma_ch_ctrl * ctrl)
+{
+       int new_len = ctrl->tr_size, num_entries = 0;
+       int old_len = new_len;
+       int src_width, dest_width, count = 1;
+
+       switch (ctrl->swidth) {
+       case WIDTH_BYTE:
+               src_width = 1;
+               break;
+       case WIDTH_HWORD:
+               src_width = 2;
+               break;
+       case WIDTH_WORD:
+               src_width = 4;
+               break;
+       default:
+               return;
+       }
+
+       switch (ctrl->dwidth) {
+       case WIDTH_BYTE:
+               dest_width = 1;
+               break;
+       case WIDTH_HWORD:
+               dest_width = 2;
+               break;
+       case WIDTH_WORD:
+               dest_width = 4;
+               break;
+       default:
+               return;
+       }
+
+       while (new_len > 0x7FF) {
+               num_entries++;
+               new_len = (ctrl->tr_size + num_entries) / (num_entries + 1);
+       }
+       if (num_entries != 0) {
+               struct pnx4008_dma_ll *ll = NULL;
+               cur_ll->ch_ctrl &= ~0x7ff;
+               cur_ll->ch_ctrl |= new_len;
+               if (!cur_ll->next) {
+                       while (num_entries) {
+                               if (!ll) {
+                                       cur_ll->next =
+                                           pnx4008_alloc_ll_entry(&cur_ll->
+                                                                  next_dma);
+                                       ll = cur_ll->next;
+                               } else {
+                                       ll->next =
+                                           pnx4008_alloc_ll_entry(&ll->
+                                                                  next_dma);
+                                       ll = ll->next;
+                               }
+
+                               if (ctrl->si)
+                                       ll->src_addr =
+                                           cur_ll->src_addr +
+                                           src_width * new_len * count;
+                               else
+                                       ll->src_addr = cur_ll->src_addr;
+                               if (ctrl->di)
+                                       ll->dest_addr =
+                                           cur_ll->dest_addr +
+                                           dest_width * new_len * count;
+                               else
+                                       ll->dest_addr = cur_ll->dest_addr;
+                               ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff;
+                               ll->next_dma = 0;
+                               ll->next = NULL;
+                               num_entries--;
+                               count++;
+                       }
+               } else {
+                       struct pnx4008_dma_ll *ll_old = cur_ll->next;
+                       unsigned long ll_dma_old = cur_ll->next_dma;
+                       while (num_entries) {
+                               if (!ll) {
+                                       cur_ll->next =
+                                           pnx4008_alloc_ll_entry(&cur_ll->
+                                                                  next_dma);
+                                       ll = cur_ll->next;
+                               } else {
+                                       ll->next =
+                                           pnx4008_alloc_ll_entry(&ll->
+                                                                  next_dma);
+                                       ll = ll->next;
+                               }
+
+                               if (ctrl->si)
+                                       ll->src_addr =
+                                           cur_ll->src_addr +
+                                           src_width * new_len * count;
+                               else
+                                       ll->src_addr = cur_ll->src_addr;
+                               if (ctrl->di)
+                                       ll->dest_addr =
+                                           cur_ll->dest_addr +
+                                           dest_width * new_len * count;
+                               else
+                                       ll->dest_addr = cur_ll->dest_addr;
+                               ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff;
+                               ll->next_dma = 0;
+                               ll->next = NULL;
+                               num_entries--;
+                               count++;
+                       }
+
+                       ll->next_dma = ll_dma_old;
+                       ll->next = ll_old;
+               }
+               /* adjust last length/tc */
+               ll->ch_ctrl = cur_ll->ch_ctrl & (~0x7ff);
+               ll->ch_ctrl |= old_len - new_len * (count - 1);
+               cur_ll->ch_ctrl &= 0x7fffffff;
+       }
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_split_ll_entry);
+
+int pnx4008_config_channel(int ch, struct pnx4008_dma_config * config)
+{
+       if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+       __raw_writel(config->src_addr, DMAC_Cx_SRC_ADDR(ch));
+       __raw_writel(config->dest_addr, DMAC_Cx_DEST_ADDR(ch));
+
+       if (config->is_ll)
+               __raw_writel(config->ll_dma, DMAC_Cx_LLI(ch));
+       else
+               __raw_writel(0, DMAC_Cx_LLI(ch));
+
+       __raw_writel(config->ch_ctrl, DMAC_Cx_CONTROL(ch));
+       __raw_writel(config->ch_cfg, DMAC_Cx_CONFIG(ch));
+       pnx4008_dma_unlock();
+
+       return 0;
+
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_config_channel);
+
+int pnx4008_channel_get_config(int ch, struct pnx4008_dma_config * config)
+{
+       if (!VALID_CHANNEL(ch) || !dma_channels[ch].name || !config)
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+       config->ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+       config->ch_ctrl = __raw_readl(DMAC_Cx_CONTROL(ch));
+
+       config->ll_dma = __raw_readl(DMAC_Cx_LLI(ch));
+       config->is_ll = config->ll_dma ? 1 : 0;
+
+       config->src_addr = __raw_readl(DMAC_Cx_SRC_ADDR(ch));
+       config->dest_addr = __raw_readl(DMAC_Cx_DEST_ADDR(ch));
+       pnx4008_dma_unlock();
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_channel_get_config);
+
+int pnx4008_dma_ch_enable(int ch)
+{
+       unsigned long ch_cfg;
+
+       if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+       ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+       ch_cfg |= 1;
+       __raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch));
+       pnx4008_dma_unlock();
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enable);
+
+int pnx4008_dma_ch_disable(int ch)
+{
+       unsigned long ch_cfg;
+
+       if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+       ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+       ch_cfg &= ~1;
+       __raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch));
+       pnx4008_dma_unlock();
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_disable);
+
+int pnx4008_dma_ch_enabled(int ch)
+{
+       unsigned long ch_cfg;
+
+       if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+               return -EINVAL;
+
+       pnx4008_dma_lock();
+       ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+       pnx4008_dma_unlock();
+
+       return ch_cfg & 1;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enabled);
+
+static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       int i;
+       unsigned long dint = __raw_readl(DMAC_INT_STAT);
+       unsigned long tcint = __raw_readl(DMAC_INT_TC_STAT);
+       unsigned long eint = __raw_readl(DMAC_INT_ERR_STAT);
+       unsigned long i_bit;
+
+       for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
+               i_bit = 1 << i;
+               if (dint & i_bit) {
+                       struct dma_channel *channel = &dma_channels[i];
+
+                       if (channel->name && channel->irq_handler) {
+                               int cause = 0;
+
+                               if (eint & i_bit)
+                                       cause |= DMA_ERR_INT;
+                               if (tcint & i_bit)
+                                       cause |= DMA_TC_INT;
+                               channel->irq_handler(i, cause, channel->data,
+                                                    regs);
+                       } else {
+                               /*
+                                * IRQ for an unregistered DMA channel
+                                */
+                               printk(KERN_WARNING
+                                      "spurious IRQ for DMA channel %d\n", i);
+                       }
+                       if (tcint & i_bit)
+                               __raw_writel(i_bit, DMAC_INT_TC_CLEAR);
+                       if (eint & i_bit)
+                               __raw_writel(i_bit, DMAC_INT_ERR_CLEAR);
+               }
+       }
+       return IRQ_HANDLED;
+}
+
+static int __init pnx4008_dma_init(void)
+{
+       int ret, i;
+
+       ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
+       if (ret) {
+               printk(KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
+               goto out;
+       }
+
+       ll_pool.count = 0x4000 / sizeof(struct pnx4008_dma_ll);
+       ll_pool.cur = ll_pool.vaddr =
+           dma_alloc_coherent(NULL, ll_pool.count * sizeof(struct pnx4008_dma_ll),
+                              &ll_pool.dma_addr, GFP_KERNEL);
+
+       if (!ll_pool.vaddr) {
+               ret = -ENOMEM;
+               free_irq(DMA_INT, NULL);
+               goto out;
+       }
+
+       for (i = 0; i < ll_pool.count - 1; i++) {
+               void **addr = ll_pool.vaddr + i * sizeof(struct pnx4008_dma_ll);
+               *addr = (void *)addr + sizeof(struct pnx4008_dma_ll);
+       }
+       *(long *)(ll_pool.vaddr +
+                 (ll_pool.count - 1) * sizeof(struct pnx4008_dma_ll)) =
+           (long)ll_pool.vaddr;
+
+       __raw_writel(1, DMAC_CONFIG);
+
+out:
+       return ret;
+}
+arch_initcall(pnx4008_dma_init);
diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c
new file mode 100644 (file)
index 0000000..e1ce050
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * arch/arm/mach-pnx4008/gpio.c
+ *
+ * PNX4008 GPIO driver
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/arch/platform.h>
+#include <asm/arch/gpio.h>
+
+/* register definitions */
+#define PIO_VA_BASE    IO_ADDRESS(PNX4008_PIO_BASE)
+
+#define PIO_INP_STATE  (0x00U)
+#define PIO_OUTP_SET   (0x04U)
+#define PIO_OUTP_CLR   (0x08U)
+#define PIO_OUTP_STATE (0x0CU)
+#define PIO_DRV_SET    (0x10U)
+#define PIO_DRV_CLR    (0x14U)
+#define PIO_DRV_STATE  (0x18U)
+#define PIO_SDINP_STATE        (0x1CU)
+#define PIO_SDOUTP_SET (0x20U)
+#define PIO_SDOUTP_CLR (0x24U)
+#define PIO_MUX_SET    (0x28U)
+#define PIO_MUX_CLR    (0x2CU)
+#define PIO_MUX_STATE  (0x30U)
+
+static inline void gpio_lock(void)
+{
+       local_irq_disable();
+}
+
+static inline void gpio_unlock(void)
+{
+       local_irq_enable();
+}
+
+/* Inline functions */
+static inline int gpio_read_bit(u32 reg, int gpio)
+{
+       u32 bit, val;
+       int ret = -EFAULT;
+
+       if (gpio < 0)
+               goto out;
+
+       bit = GPIO_BIT(gpio);
+       if (bit) {
+               val = __raw_readl(PIO_VA_BASE + reg);
+               ret = (val & bit) ? 1 : 0;
+       }
+out:
+       return ret;
+}
+
+static inline int gpio_set_bit(u32 reg, int gpio)
+{
+       u32 bit, val;
+       int ret = -EFAULT;
+
+       if (gpio < 0)
+               goto out;
+
+       bit = GPIO_BIT(gpio);
+       if (bit) {
+               val = __raw_readl(PIO_VA_BASE + reg);
+               val |= bit;
+               __raw_writel(val, PIO_VA_BASE + reg);
+               ret = 0;
+       }
+out:
+       return ret;
+}
+
+/* Very simple access control, bitmap for allocated/free */
+static unsigned long access_map[4];
+#define INP_INDEX      0
+#define OUTP_INDEX     1
+#define GPIO_INDEX     2
+#define MUX_INDEX      3
+
+/*GPIO to Input Mapping */
+static short gpio_to_inp_map[32] = {
+       -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, 10, 11, 12, 13, 14, 24, -1
+};
+
+/*GPIO to Mux Mapping */
+static short gpio_to_mux_map[32] = {
+       -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, 0, 1, 4, 5, -1
+};
+
+/*Output to Mux Mapping */
+static short outp_to_mux_map[32] = {
+       -1, -1, -1, 6, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, 2, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+int pnx4008_gpio_register_pin(unsigned short pin)
+{
+       unsigned long bit = GPIO_BIT(pin);
+       int ret = -EBUSY;       /* Already in use */
+
+       gpio_lock();
+
+       if (GPIO_ISBID(pin)) {
+               if (access_map[GPIO_INDEX] & bit)
+                       goto out;
+               access_map[GPIO_INDEX] |= bit;
+
+       } else if (GPIO_ISRAM(pin)) {
+               if (access_map[GPIO_INDEX] & bit)
+                       goto out;
+               access_map[GPIO_INDEX] |= bit;
+
+       } else if (GPIO_ISMUX(pin)) {
+               if (access_map[MUX_INDEX] & bit)
+                       goto out;
+               access_map[MUX_INDEX] |= bit;
+
+       } else if (GPIO_ISOUT(pin)) {
+               if (access_map[OUTP_INDEX] & bit)
+                       goto out;
+               access_map[OUTP_INDEX] |= bit;
+
+       } else if (GPIO_ISIN(pin)) {
+               if (access_map[INP_INDEX] & bit)
+                       goto out;
+               access_map[INP_INDEX] |= bit;
+       } else
+               goto out;
+       ret = 0;
+
+out:
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_register_pin);
+
+int pnx4008_gpio_unregister_pin(unsigned short pin)
+{
+       unsigned long bit = GPIO_BIT(pin);
+       int ret = -EFAULT;      /* Not registered */
+
+       gpio_lock();
+
+       if (GPIO_ISBID(pin)) {
+               if (~access_map[GPIO_INDEX] & bit)
+                       goto out;
+               access_map[GPIO_INDEX] &= ~bit;
+       } else if (GPIO_ISRAM(pin)) {
+               if (~access_map[GPIO_INDEX] & bit)
+                       goto out;
+               access_map[GPIO_INDEX] &= ~bit;
+       } else if (GPIO_ISMUX(pin)) {
+               if (~access_map[MUX_INDEX] & bit)
+                       goto out;
+               access_map[MUX_INDEX] &= ~bit;
+       } else if (GPIO_ISOUT(pin)) {
+               if (~access_map[OUTP_INDEX] & bit)
+                       goto out;
+               access_map[OUTP_INDEX] &= ~bit;
+       } else if (GPIO_ISIN(pin)) {
+               if (~access_map[INP_INDEX] & bit)
+                       goto out;
+               access_map[INP_INDEX] &= ~bit;
+       } else
+               goto out;
+       ret = 0;
+
+out:
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
+
+unsigned long pnx4008_gpio_read_pin(unsigned short pin)
+{
+       unsigned long ret = -EFAULT;
+       int gpio = GPIO_BIT_MASK(pin);
+       gpio_lock();
+       if (GPIO_ISOUT(pin)) {
+               ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
+       } else if (GPIO_ISRAM(pin)) {
+               if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {
+                       ret = gpio_read_bit(PIO_SDINP_STATE, gpio);
+               }
+       } else if (GPIO_ISBID(pin)) {
+               ret = gpio_read_bit(PIO_DRV_STATE, gpio);
+               if (ret > 0)
+                       ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
+               else if (ret == 0)
+                       ret =
+                           gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);
+       } else if (GPIO_ISIN(pin)) {
+               ret = gpio_read_bit(PIO_INP_STATE, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin);
+
+/* Write Value to output */
+int pnx4008_gpio_write_pin(unsigned short pin, int output)
+{
+       int gpio = GPIO_BIT_MASK(pin);
+       int ret = -EFAULT;
+
+       gpio_lock();
+       if (GPIO_ISOUT(pin)) {
+               printk( "writing '%x' to '%x'\n",
+                               gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );
+               ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);
+       } else if (GPIO_ISRAM(pin)) {
+               if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
+                       ret = gpio_set_bit(output ? PIO_SDOUTP_SET :
+                                          PIO_SDOUTP_CLR, gpio);
+       } else if (GPIO_ISBID(pin)) {
+               if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
+                       ret = gpio_set_bit(output ? PIO_OUTP_SET :
+                                          PIO_OUTP_CLR, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_write_pin);
+
+/* Value = 1 : Set GPIO pin as output */
+/* Value = 0 : Set GPIO pin as input */
+int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
+{
+       int gpio = GPIO_BIT_MASK(pin);
+       int ret = -EFAULT;
+
+       gpio_lock();
+       if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
+               ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
+
+/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
+int pnx4008_gpio_read_pin_direction(unsigned short pin)
+{
+       int gpio = GPIO_BIT_MASK(pin);
+       int ret = -EFAULT;
+
+       gpio_lock();
+       if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
+               ret = gpio_read_bit(PIO_DRV_STATE, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
+
+/* Value = 1 : Set pin to muxed function  */
+/* Value = 0 : Set pin as GPIO */
+int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
+{
+       int gpio = GPIO_BIT_MASK(pin);
+       int ret = -EFAULT;
+
+       gpio_lock();
+       if (GPIO_ISBID(pin)) {
+               ret =
+                   gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
+                                gpio_to_mux_map[gpio]);
+       } else if (GPIO_ISOUT(pin)) {
+               ret =
+                   gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
+                                outp_to_mux_map[gpio]);
+       } else if (GPIO_ISMUX(pin)) {
+               ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
+
+/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
+int pnx4008_gpio_read_pin_mux(unsigned short pin)
+{
+       int gpio = GPIO_BIT_MASK(pin);
+       int ret = -EFAULT;
+
+       gpio_lock();
+       if (GPIO_ISBID(pin)) {
+               ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);
+       } else if (GPIO_ISOUT(pin)) {
+               ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);
+       } else if (GPIO_ISMUX(pin)) {
+               ret = gpio_read_bit(PIO_MUX_STATE, gpio);
+       }
+       gpio_unlock();
+       return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);
diff --git a/arch/arm/mach-pnx4008/irq.c b/arch/arm/mach-pnx4008/irq.c
new file mode 100644 (file)
index 0000000..9b0a8e0
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * arch/arm/mach-pnx4008/irq.c
+ *
+ * PNX4008 IRQ controller driver
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/arch/irq.h>
+
+static u8 pnx4008_irq_type[NR_IRQS] = PNX4008_IRQ_TYPES;
+
+static void pnx4008_mask_irq(unsigned int irq)
+{
+       __raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */
+}
+
+static void pnx4008_unmask_irq(unsigned int irq)
+{
+       __raw_writel(__raw_readl(INTC_ER(irq)) | INTC_BIT(irq), INTC_ER(irq));  /* unmask interrupt */
+}
+
+static void pnx4008_mask_ack_irq(unsigned int irq)
+{
+       __raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */
+       __raw_writel(INTC_BIT(irq), INTC_SR(irq));      /* clear interrupt status */
+}
+
+static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
+{
+       switch (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);
+               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);
+               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);
+               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);
+               break;
+
+       /* IRQT_BOTHEDGE is not supported */
+       default:
+               printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type);
+               return -1;
+       }
+       return 0;
+}
+
+static struct irqchip pnx4008_irq_chip = {
+       .ack = pnx4008_mask_ack_irq,
+       .mask = pnx4008_mask_irq,
+       .unmask = pnx4008_unmask_irq,
+       .set_type = pnx4008_set_irq_type,
+};
+
+void __init pnx4008_init_irq(void)
+{
+       unsigned int i;
+
+       /* configure and enable IRQ 0,1,30,31 (cascade interrupts) mask all others */
+       pnx4008_set_irq_type(SUB1_IRQ_N, pnx4008_irq_type[SUB1_IRQ_N]);
+       pnx4008_set_irq_type(SUB2_IRQ_N, pnx4008_irq_type[SUB2_IRQ_N]);
+       pnx4008_set_irq_type(SUB1_FIQ_N, pnx4008_irq_type[SUB1_FIQ_N]);
+       pnx4008_set_irq_type(SUB2_FIQ_N, pnx4008_irq_type[SUB2_FIQ_N]);
+
+       __raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) |
+                       (1 << SUB2_IRQ_N) | (1 << SUB1_IRQ_N),
+               INTC_ER(MAIN_BASE_INT));
+       __raw_writel(0, INTC_ER(SIC1_BASE_INT));
+       __raw_writel(0, INTC_ER(SIC2_BASE_INT));
+
+       /* configure all other IRQ's */
+       for (i = 0; i < NR_IRQS; i++) {
+               if (i == SUB2_FIQ_N || i == SUB1_FIQ_N ||
+                       i == SUB2_IRQ_N || i == SUB1_IRQ_N)
+                       continue;
+               set_irq_flags(i, IRQF_VALID);
+               set_irq_chip(i, &pnx4008_irq_chip);
+               pnx4008_set_irq_type(i, pnx4008_irq_type[i]);
+       }
+}
+
diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c
new file mode 100644 (file)
index 0000000..3649cd3
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * arch/arm/mach-pnx4008/pm.c
+ *
+ * Power Management driver for PNX4008
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/pm.h>
+#include <linux/rtc.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/clock.h>
+
+#define SRAM_VA IO_ADDRESS(PNX4008_IRAM_BASE)
+
+static void *saved_sram;
+
+static struct clk *pll4_clk;
+
+static inline void pnx4008_standby(void)
+{
+       void (*pnx4008_cpu_standby_ptr) (void);
+
+       local_irq_disable();
+       local_fiq_disable();
+
+       clk_disable(pll4_clk);
+
+       /*saving portion of SRAM to be used by suspend function. */
+       memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_standby_sz);
+
+       /*make sure SRAM copy gets physically written into SDRAM.
+          SDRAM will be placed into self-refresh during power down */
+       flush_cache_all();
+
+       /*copy suspend function into SRAM */
+       memcpy((void *)SRAM_VA, pnx4008_cpu_standby, pnx4008_cpu_standby_sz);
+
+       /*do suspend */
+       pnx4008_cpu_standby_ptr = (void *)SRAM_VA;
+       pnx4008_cpu_standby_ptr();
+
+       /*restoring portion of SRAM that was used by suspend function */
+       memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_standby_sz);
+
+       clk_enable(pll4_clk);
+
+       local_fiq_enable();
+       local_irq_enable();
+}
+
+static inline void pnx4008_suspend(void)
+{
+       void (*pnx4008_cpu_suspend_ptr) (void);
+
+       local_irq_disable();
+       local_fiq_disable();
+
+       clk_disable(pll4_clk);
+
+       __raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
+       __raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
+
+       /*saving portion of SRAM to be used by suspend function. */
+       memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_suspend_sz);
+
+       /*make sure SRAM copy gets physically written into SDRAM.
+          SDRAM will be placed into self-refresh during power down */
+       flush_cache_all();
+
+       /*copy suspend function into SRAM */
+       memcpy((void *)SRAM_VA, pnx4008_cpu_suspend, pnx4008_cpu_suspend_sz);
+
+       /*do suspend */
+       pnx4008_cpu_suspend_ptr = (void *)SRAM_VA;
+       pnx4008_cpu_suspend_ptr();
+
+       /*restoring portion of SRAM that was used by suspend function */
+       memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_suspend_sz);
+
+       clk_enable(pll4_clk);
+
+       local_fiq_enable();
+       local_irq_enable();
+}
+
+static int pnx4008_pm_enter(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_STANDBY:
+               pnx4008_standby();
+               break;
+       case PM_SUSPEND_MEM:
+               pnx4008_suspend();
+               break;
+       case PM_SUSPEND_DISK:
+               return -ENOTSUPP;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int pnx4008_pm_prepare(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_STANDBY:
+       case PM_SUSPEND_MEM:
+               break;
+
+       case PM_SUSPEND_DISK:
+               return -ENOTSUPP;
+               break;
+
+       default:
+               return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static int pnx4008_pm_finish(suspend_state_t state)
+{
+       return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops pnx4008_pm_ops = {
+       .prepare = pnx4008_pm_prepare,
+       .enter = pnx4008_pm_enter,
+       .finish = pnx4008_pm_finish,
+};
+
+static int __init pnx4008_pm_init(void)
+{
+       u32 sram_size_to_allocate;
+
+       pll4_clk = clk_get(0, "ck_pll4");
+       if (IS_ERR(pll4_clk)) {
+               printk(KERN_ERR
+                      "PM Suspend cannot acquire ARM(PLL4) clock control\n");
+               return PTR_ERR(pll4_clk);
+       }
+
+       if (pnx4008_cpu_standby_sz > pnx4008_cpu_suspend_sz)
+               sram_size_to_allocate = pnx4008_cpu_standby_sz;
+       else
+               sram_size_to_allocate = pnx4008_cpu_suspend_sz;
+
+       saved_sram = kmalloc(sram_size_to_allocate, GFP_ATOMIC);
+       if (!saved_sram) {
+               printk(KERN_ERR
+                      "PM Suspend: cannot allocate memory to save portion of SRAM\n");
+               clk_put(pll4_clk);
+               return -ENOMEM;
+       }
+
+       pm_set_ops(&pnx4008_pm_ops);
+       return 0;
+}
+
+late_initcall(pnx4008_pm_init);
diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c
new file mode 100644 (file)
index 0000000..2e1e04c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *  linux/arch/arm/mach-pnx4008/serial.c
+ *
+ *  PNX4008 UART initialization
+ *
+ *  Copyright: MontaVista Software Inc. (c) 2005
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/hardware.h>
+
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <asm/arch/pm.h>
+
+#include <asm/arch/clock.h>
+
+#define UART_3         0
+#define UART_4         1
+#define UART_5         2
+#define UART_6         3
+#define UART_UNKNOWN   (-1)
+
+#define UART3_BASE_VA  IO_ADDRESS(PNX4008_UART3_BASE)
+#define UART4_BASE_VA  IO_ADDRESS(PNX4008_UART4_BASE)
+#define UART5_BASE_VA  IO_ADDRESS(PNX4008_UART5_BASE)
+#define UART6_BASE_VA  IO_ADDRESS(PNX4008_UART6_BASE)
+
+#define UART_FCR_OFFSET                8
+#define UART_FIFO_SIZE         64
+
+void pnx4008_uart_init(void)
+{
+       u32 tmp;
+       int i = UART_FIFO_SIZE;
+
+       __raw_writel(0xC1, UART5_BASE_VA + UART_FCR_OFFSET);
+       __raw_writel(0xC1, UART3_BASE_VA + UART_FCR_OFFSET);
+
+       /* Send a NULL to fix the UART HW bug */
+       __raw_writel(0x00, UART5_BASE_VA);
+       __raw_writel(0x00, UART3_BASE_VA);
+
+       while (i--) {
+               tmp = __raw_readl(UART5_BASE_VA);
+               tmp = __raw_readl(UART3_BASE_VA);
+       }
+       __raw_writel(0, UART5_BASE_VA + UART_FCR_OFFSET);
+       __raw_writel(0, UART3_BASE_VA + UART_FCR_OFFSET);
+
+       /* setup wakeup interrupt */
+       start_int_set_rising_edge(SE_U3_RX_INT);
+       start_int_ack(SE_U3_RX_INT);
+       start_int_umask(SE_U3_RX_INT);
+
+       start_int_set_rising_edge(SE_U5_RX_INT);
+       start_int_ack(SE_U5_RX_INT);
+       start_int_umask(SE_U5_RX_INT);
+}
+
diff --git a/arch/arm/mach-pnx4008/sleep.S b/arch/arm/mach-pnx4008/sleep.S
new file mode 100644 (file)
index 0000000..93c802b
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * linux/arch/arm/mach-pnx4008/sleep.S
+ *
+ * PNX4008 support for STOP mode and SDRAM self-refresh
+ *
+ * Authors: Dmitry Chigirev, Vitaly Wool <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE)
+#define PWR_CTRL_REG_OFFS 0x44
+
+#define SDRAM_CFG_VA_BASE IO_ADDRESS(PNX4008_SDRAM_CFG_BASE)
+#define MPMC_STATUS_REG_OFFS 0x4
+
+               .text
+
+ENTRY(pnx4008_cpu_suspend)
+       @this function should be entered in Direct run mode.
+
+       @ save registers on stack
+       stmfd   sp!, {r0 - r6, lr}
+
+       @ setup Power Manager base address in r4
+       @ and put it's value in r5
+       mov     r4, #(PWRMAN_VA_BASE & 0xff000000)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
+       ldr     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ setup SDRAM controller base address in r2
+       @ and put it's value in r3
+       mov     r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
+       ldr     r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
+
+       @ clear SDRAM self-refresh bit latch
+       and     r5, r5, #(~(1 << 8))
+       @ clear SDRAM self-refresh bit
+       and     r5, r5, #(~(1 << 9))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ do save current bit settings in r1
+       mov     r1, r5
+
+       @ set SDRAM self-refresh bit
+       orr     r5, r5, #(1 << 9)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ set SDRAM self-refresh bit latch
+       orr     r5, r5, #(1 << 8)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ clear SDRAM self-refresh bit latch
+       and     r5, r5, #(~(1 << 8))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ clear SDRAM self-refresh bit
+       and     r5, r5, #(~(1 << 9))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ wait for SDRAM to get into self-refresh mode
+2:     ldr     r3, [r2, #MPMC_STATUS_REG_OFFS]
+       tst     r3, #(1 << 2)
+       beq     2b
+
+       @ to prepare SDRAM to get out of self-refresh mode after wakeup
+       orr     r5, r5, #(1 << 7)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ do enter stop mode
+       orr     r5, r5, #(1 << 0)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+
+       @ sleeping now...
+
+       @ coming out of STOP mode into Direct Run mode
+       @ clear STOP mode and SDRAM self-refresh bits
+       str     r1, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ wait for SDRAM to get out self-refresh mode
+3:     ldr     r3, [r2, #MPMC_STATUS_REG_OFFS]
+       tst     r3, #5
+       bne     3b
+
+       @ restore regs and return
+       ldmfd   sp!, {r0 - r6, pc}
+
+ENTRY(pnx4008_cpu_suspend_sz)
+       .word   . - pnx4008_cpu_suspend
+
+ENTRY(pnx4008_cpu_standby)
+       @ save registers on stack
+       stmfd   sp!, {r0 - r6, lr}
+
+       @ setup Power Manager base address in r4
+       @ and put it's value in r5
+       mov     r4, #(PWRMAN_VA_BASE & 0xff000000)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
+       orr     r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
+       ldr     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ setup SDRAM controller base address in r2
+       @ and put it's value in r3
+       mov     r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
+       orr     r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
+       ldr     r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
+
+       @ clear SDRAM self-refresh bit latch
+       and     r5, r5, #(~(1 << 8))
+       @ clear SDRAM self-refresh bit
+       and     r5, r5, #(~(1 << 9))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ do save current bit settings in r1
+       mov     r1, r5
+
+       @ set SDRAM self-refresh bit
+       orr     r5, r5, #(1 << 9)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ set SDRAM self-refresh bit latch
+       orr     r5, r5, #(1 << 8)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ clear SDRAM self-refresh bit latch
+       and     r5, r5, #(~(1 << 8))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ clear SDRAM self-refresh bit
+       and     r5, r5, #(~(1 << 9))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ wait for SDRAM to get into self-refresh mode
+2:     ldr     r3, [r2, #MPMC_STATUS_REG_OFFS]
+       tst     r3, #(1 << 2)
+       beq     2b
+
+       @ set 'get out of self-refresh mode after wakeup' bit
+       orr     r5, r5, #(1 << 7)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       mcr     p15, 0, r0, c7, c0, 4   @ kinda sleeping now...
+
+       @ set SDRAM self-refresh bit latch
+       orr     r5, r5, #(1 << 8)
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ clear SDRAM self-refresh bit latch
+       and     r5, r5, #(~(1 << 8))
+       str     r5, [r4, #PWR_CTRL_REG_OFFS]
+
+       @ wait for SDRAM to get out self-refresh mode
+3:     ldr     r3, [r2, #MPMC_STATUS_REG_OFFS]
+       tst     r3, #5
+       bne     3b
+
+       @ restore regs and return
+       ldmfd   sp!, {r0 - r6, pc}
+
+ENTRY(pnx4008_cpu_standby_sz)
+       .word   . - pnx4008_cpu_standby
+
+ENTRY(pnx4008_cache_clean_invalidate)
+       stmfd   sp!, {r0 - r6, lr}
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+       mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
+#else
+1:     mrc     p15, 0, r15, c7, c14, 3         @ test,clean,invalidate
+       bne     1b
+#endif
+       ldmfd   sp!, {r0 - r6, pc}
diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c
new file mode 100644 (file)
index 0000000..4ce6806
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * arch/arm/mach-pnx4008/time.c
+ *
+ * PNX4008 Timers
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev, Grigory Tolstolytkin <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <asm/errno.h>
+
+/*! Note: all timers are UPCOUNTING */
+
+/*!
+ * Returns number of us since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long pnx4008_gettimeoffset(void)
+{
+       u32 ticks_to_match =
+           __raw_readl(HSTIM_MATCH0) - __raw_readl(HSTIM_COUNTER);
+       u32 elapsed = LATCH - ticks_to_match;
+       return (elapsed * (tick_nsec / 1000)) / LATCH;
+}
+
+/*!
+ * IRQ handler for the timer
+ */
+static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id,
+                                          struct pt_regs *regs)
+{
+       if (__raw_readl(HSTIM_INT) & MATCH0_INT) {
+
+               write_seqlock(&xtime_lock);
+
+               do {
+                       timer_tick(regs);
+
+                       /*
+                        * this algorithm takes care of possible delay
+                        * for this interrupt handling longer than a normal
+                        * timer period
+                        */
+                       __raw_writel(__raw_readl(HSTIM_MATCH0) + LATCH,
+                                    HSTIM_MATCH0);
+                       __raw_writel(MATCH0_INT, HSTIM_INT);    /* clear interrupt */
+
+                       /*
+                        * The goal is to keep incrementing HSTIM_MATCH0
+                        * register until HSTIM_MATCH0 indicates time after
+                        * what HSTIM_COUNTER indicates.
+                        */
+               } while ((signed)
+                        (__raw_readl(HSTIM_MATCH0) -
+                         __raw_readl(HSTIM_COUNTER)) < 0);
+
+               write_sequnlock(&xtime_lock);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction pnx4008_timer_irq = {
+       .name = "PNX4008 Tick Timer",
+       .flags = SA_INTERRUPT | SA_TIMER,
+       .handler = pnx4008_timer_interrupt
+};
+
+/*!
+ * Set up timer and timer interrupt.
+ */
+static __init void pnx4008_setup_timer(void)
+{
+       __raw_writel(RESET_COUNT, MSTIM_CTRL);
+       while (__raw_readl(MSTIM_COUNTER)) ;    /* wait for reset to complete. 100% guarantee event */
+       __raw_writel(0, MSTIM_CTRL);    /* stop the timer */
+       __raw_writel(0, MSTIM_MCTRL);
+
+       __raw_writel(RESET_COUNT, HSTIM_CTRL);
+       while (__raw_readl(HSTIM_COUNTER)) ;    /* wait for reset to complete. 100% guarantee event */
+       __raw_writel(0, HSTIM_CTRL);
+       __raw_writel(0, HSTIM_MCTRL);
+       __raw_writel(0, HSTIM_CCR);
+       __raw_writel(12, HSTIM_PMATCH); /* scale down to 1 MHZ */
+       __raw_writel(LATCH, HSTIM_MATCH0);
+       __raw_writel(MR0_INT, HSTIM_MCTRL);
+
+       setup_irq(HSTIMER_INT, &pnx4008_timer_irq);
+
+       __raw_writel(COUNT_ENAB | DEBUG_EN, HSTIM_CTRL);        /*start timer, stop when JTAG active */
+}
+
+/* Timer Clock Control in PM register */
+#define TIMCLK_CTRL_REG  IO_ADDRESS((PNX4008_PWRMAN_BASE + 0xBC))
+#define WATCHDOG_CLK_EN                   1
+#define TIMER_CLK_EN                      2    /* HS and MS timers? */
+
+static u32 timclk_ctrl_reg_save;
+
+void pnx4008_timer_suspend(void)
+{
+       timclk_ctrl_reg_save = __raw_readl(TIMCLK_CTRL_REG);
+       __raw_writel(0, TIMCLK_CTRL_REG);       /* disable timers */
+}
+
+void pnx4008_timer_resume(void)
+{
+       __raw_writel(timclk_ctrl_reg_save, TIMCLK_CTRL_REG);    /* enable timers */
+}
+
+struct sys_timer pnx4008_timer = {
+       .init = pnx4008_setup_timer,
+       .offset = pnx4008_gettimeoffset,
+       .suspend = pnx4008_timer_suspend,
+       .resume = pnx4008_timer_resume,
+};
+
index 3e26d7ce5bb287c4aca023c7d9edbb6cd1ad82c7..1ab26c6914f25f2f13fe91ce55b2bb5eb4d33c3a 100644 (file)
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <asm/arch/pxa2xx_spi.h>
+
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/mach-types.h>
@@ -196,6 +200,78 @@ static struct resource smc91x_resources[] = {
        },
 };
 
+/* ADS7846 is connected through SSP ... and if your board has J5 populated,
+ * you can select it to replace the ucb1400 by switching the touchscreen cable
+ * (to J5) and poking board registers (as done below).  Else it's only useful
+ * for the temperature sensors.
+ */
+static struct resource pxa_ssp_resources[] = {
+       [0] = {
+               .start  = __PREG(SSCR0_P(1)),
+               .end    = __PREG(SSCR0_P(1)) + 0x14,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = IRQ_SSP,
+               .end    = IRQ_SSP,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct pxa2xx_spi_master pxa_ssp_master_info = {
+       .ssp_type       = PXA25x_SSP,
+       .clock_enable   = CKEN3_SSP,
+       .num_chipselect = 0,
+};
+
+static struct platform_device pxa_ssp = {
+       .name           = "pxa2xx-spi",
+       .id             = 1,
+       .resource       = pxa_ssp_resources,
+       .num_resources  = ARRAY_SIZE(pxa_ssp_resources),
+       .dev = {
+               .platform_data  = &pxa_ssp_master_info,
+       },
+};
+
+static int lubbock_ads7846_pendown_state(void)
+{
+       /* TS_BUSY is bit 8 in LUB_MISC_RD, but pendown is irq-only */
+       return 0;
+}
+
+static struct ads7846_platform_data ads_info = {
+       .model                  = 7846,
+       .vref_delay_usecs       = 100,          /* internal, no cap */
+       .get_pendown_state      = lubbock_ads7846_pendown_state,
+       // .x_plate_ohms                = 500,  /* GUESS! */
+       // .y_plate_ohms                = 500,  /* GUESS! */
+};
+
+static void ads7846_cs(u32 command)
+{
+       static const unsigned   TS_nCS = 1 << 11;
+       lubbock_set_misc_wr(TS_nCS, (command == PXA2XX_CS_ASSERT) ? 0 : TS_nCS);
+}
+
+static struct pxa2xx_spi_chip ads_hw = {
+       .tx_threshold           = 1,
+       .rx_threshold           = 2,
+       .cs_control             = ads7846_cs,
+};
+
+static struct spi_board_info spi_board_info[] __initdata = { {
+       .modalias       = "ads7846",
+       .platform_data  = &ads_info,
+       .controller_data = &ads_hw,
+       .irq            = LUBBOCK_BB_IRQ,
+       .max_speed_hz   = 120000 /* max sample rate at 3V */
+                               * 26 /* command + data + overhead */,
+       .bus_num        = 1,
+       .chip_select    = 0,
+},
+};
+
 static struct platform_device smc91x_device = {
        .name           = "smc91x",
        .id             = -1,
@@ -272,6 +348,7 @@ static struct platform_device *devices[] __initdata = {
        &smc91x_device,
        &lubbock_flash_device[0],
        &lubbock_flash_device[1],
+       &pxa_ssp,
 };
 
 static struct pxafb_mach_info sharp_lm8v31 __initdata = {
@@ -400,6 +477,8 @@ static void __init lubbock_init(void)
        lubbock_flash_data[flashboot^1].name = "application-flash";
        lubbock_flash_data[flashboot].name = "boot-rom";
        (void) platform_add_devices(devices, ARRAY_SIZE(devices));
+
+       spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 }
 
 static struct map_desc lubbock_io_desc[] __initdata = {
@@ -416,6 +495,11 @@ static void __init lubbock_map_io(void)
        pxa_map_io();
        iotable_init(lubbock_io_desc, ARRAY_SIZE(lubbock_io_desc));
 
+       /* SSP data pins */
+       pxa_gpio_mode(GPIO23_SCLK_MD);
+       pxa_gpio_mode(GPIO25_STXD_MD);
+       pxa_gpio_mode(GPIO26_SRXD_MD);
+
        /* This enables the BTUART */
        pxa_gpio_mode(GPIO42_BTRXD_MD);
        pxa_gpio_mode(GPIO43_BTTXD_MD);
index 02e188d98e7d6d8565c4d06a2ddf9988776126e1..b307f11951dfa9d7d14e8b206c4d2abe02f60fea 100644 (file)
@@ -493,6 +493,7 @@ static void __init mainstone_map_io(void)
 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
        /* Maintainer: MontaVista Software Inc. */
        .phys_io        = 0x40000000,
+       .boot_params    = 0xa0000100,   /* BLOB boot parameter setting */
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = mainstone_map_io,
        .init_irq       = mainstone_init_irq,
index 19b372df544a094a086c05cc3e438c9fb7a606b6..44bcb8097c7ada753a985170a4e2e3a44df2be9c 100644 (file)
@@ -371,6 +371,7 @@ static int spitz_ohci_init(struct device *dev)
 static struct pxaohci_platform_data spitz_ohci_platform_data = {
        .port_mode      = PMM_NPS_MODE,
        .init           = spitz_ohci_init,
+       .power_budget   = 150,
 };
 
 
index ce7d81000695e38718c15a0567e00bdffcdc54df..0c334136db7c05343a0503c3d6ba12371942eea8 100644 (file)
@@ -70,6 +70,18 @@ config ARCH_S3C2440
        help
          Say Y here if you are using the SMDK2440.
 
+config SMDK2440_CPU2440
+       bool "SMDK2440 with S3C2440 cpu module"
+       depends on ARCH_S3C2440
+       default y if ARCH_S3C2440
+       select CPU_S3C2440
+
+config SMDK2440_CPU2442
+       bool "SMDM2440 with S3C2442 cpu module"
+       depends on ARCH_S3C2440
+       select CPU_S3C2442
+
+
 config MACH_VR1000
        bool "Thorcom VR1000"
        select CPU_S3C2410
@@ -109,12 +121,26 @@ config CPU_S3C2410
          Support for S3C2410 and S3C2410A family from the S3C24XX line
          of Samsung Mobile CPUs.
 
+config CPU_S3C244X
+       bool
+       depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
+       help
+         Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
+
 config CPU_S3C2440
        bool
        depends on ARCH_S3C2410
+       select CPU_S3C244X
        help
          Support for S3C2440 Samsung Mobile CPU based systems.
 
+config CPU_S3C2442
+       bool
+       depends on ARCH_S3C2420
+       select CPU_S3C244X
+       help
+         Support for S3C2442 Samsung Mobile CPU based systems.
+
 comment "S3C2410 Boot"
 
 config S3C2410_BOOT_WATCHDOG
@@ -170,7 +196,7 @@ config S3C2410_PM_DEBUG
        depends on ARCH_S3C2410 && PM
        help
          Say Y here if you want verbose debugging from the PM Suspend and
-         Resume code. See `Documentation/arm/Samsing-S3C24XX/Suspend.txt`
+         Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
          for more information.
 
 config S3C2410_PM_CHECK
index 3e5712db6b52af5adcca41afd649786dd48bfe37..5e09355cd4f443d43cddf229bcc3882a0cd2ff2b 100644 (file)
@@ -24,6 +24,11 @@ obj-$(CONFIG_S3C2410_DMA)  += dma.o
 obj-$(CONFIG_PM)          += pm.o sleep.o
 obj-$(CONFIG_PM_SIMTEC)           += pm-simtec.o
 
+# S3C244X support
+
+obj-$(CONFIG_CPU_S3C244X)  += s3c244x.o
+obj-$(CONFIG_CPU_S3C244X)  += s3c244x-irq.o
+
 # S3C2440 support
 
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440.o s3c2440-dsc.o
@@ -31,6 +36,11 @@ obj-$(CONFIG_CPU_S3C2440)  += s3c2440-irq.o
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440-clock.o
 obj-$(CONFIG_CPU_S3C2440)  += s3c2410-gpio.o
 
+# S3C2442 support
+
+obj-$(CONFIG_CPU_S3C2442)  += s3c2442.o
+obj-$(CONFIG_CPU_S3C2442)  += s3c2442-clock.o
+
 # bast extras
 
 obj-$(CONFIG_BAST_PC104_IRQ)   += bast-irq.o
index 6de713ad319a1c798c3444da58c2f545d933fb37..99d174612b53ee34a5004842efc7c281f890d8b6 100644 (file)
@@ -70,7 +70,7 @@ void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable)
                clkcon &= ~clocks;
 
        /* ensure none of the special function bits set */
-       clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
+       clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER | 3);
 
        __raw_writel(clkcon, S3C2410_CLKCON);
 }
index c940890f621f1902fe761773acd2aa9b999b8188..a40eaa6561771bbd3c09410b9e06b6e1cc6967de 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/irq.h>
 
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/leds-gpio.h>
 
 #include <asm/arch/nand.h>
 
 #include "devs.h"
 #include "pm.h"
 
+/* LED devices */
+
+static struct s3c24xx_led_platdata smdk_pdata_led4 = {
+       .gpio           = S3C2410_GPF4,
+       .flags          = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+       .name           = "led4",
+       .def_trigger    = "timer",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led5 = {
+       .gpio           = S3C2410_GPF5,
+       .flags          = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+       .name           = "led5",
+       .def_trigger    = "nand-disk",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led6 = {
+       .gpio           = S3C2410_GPF6,
+       .flags          = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+       .name           = "led6",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led7 = {
+       .gpio           = S3C2410_GPF7,
+       .flags          = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+       .name           = "led7",
+};
+
+static struct platform_device smdk_led4 = {
+       .name           = "s3c24xx_led",
+       .id             = 0,
+       .dev            = {
+               .platform_data = &smdk_pdata_led4,
+       },
+};
+
+static struct platform_device smdk_led5 = {
+       .name           = "s3c24xx_led",
+       .id             = 1,
+       .dev            = {
+               .platform_data = &smdk_pdata_led5,
+       },
+};
+
+static struct platform_device smdk_led6 = {
+       .name           = "s3c24xx_led",
+       .id             = 2,
+       .dev            = {
+               .platform_data = &smdk_pdata_led6,
+       },
+};
+
+static struct platform_device smdk_led7 = {
+       .name           = "s3c24xx_led",
+       .id             = 3,
+       .dev            = {
+               .platform_data = &smdk_pdata_led7,
+       },
+};
+
 /* NAND parititon from 2.4.18-swl5 */
 
 static struct mtd_partition smdk_default_nand_part[] = {
@@ -111,6 +172,10 @@ static struct s3c2410_platform_nand smdk_nand_info = {
 
 static struct platform_device __initdata *smdk_devs[] = {
        &s3c_device_nand,
+       &smdk_led4,
+       &smdk_led5,
+       &smdk_led6,
+       &smdk_led7,
 };
 
 void __init smdk_machine_init(void)
index 70c34fcf78586c6cba26ca01675078a64baf0ea3..52842e6e86e6ce6954f0515db99e8257d4ff55af 100644 (file)
 #include <asm/mach/map.h>
 
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-serial.h>
 
 #include "cpu.h"
+#include "devs.h"
 #include "clock.h"
 #include "s3c2400.h"
 #include "s3c2410.h"
+#include "s3c244x.h"
 #include "s3c2440.h"
+#include "s3c2442.h"
 
 struct cpu_table {
        unsigned long   idcode;
@@ -59,6 +63,7 @@ struct cpu_table {
 static const char name_s3c2400[]  = "S3C2400";
 static const char name_s3c2410[]  = "S3C2410";
 static const char name_s3c2440[]  = "S3C2440";
+static const char name_s3c2442[]  = "S3C2442";
 static const char name_s3c2410a[] = "S3C2410A";
 static const char name_s3c2440a[] = "S3C2440A";
 
@@ -84,21 +89,30 @@ static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x32440000,
                .idmask         = 0xffffffff,
-               .map_io         = s3c2440_map_io,
-               .init_clocks    = s3c2440_init_clocks,
-               .init_uarts     = s3c2440_init_uarts,
+               .map_io         = s3c244x_map_io,
+               .init_clocks    = s3c244x_init_clocks,
+               .init_uarts     = s3c244x_init_uarts,
                .init           = s3c2440_init,
                .name           = name_s3c2440
        },
        {
                .idcode         = 0x32440001,
                .idmask         = 0xffffffff,
-               .map_io         = s3c2440_map_io,
-               .init_clocks    = s3c2440_init_clocks,
-               .init_uarts     = s3c2440_init_uarts,
+               .map_io         = s3c244x_map_io,
+               .init_clocks    = s3c244x_init_clocks,
+               .init_uarts     = s3c244x_init_uarts,
                .init           = s3c2440_init,
                .name           = name_s3c2440a
        },
+       {
+               .idcode         = 0x32440aaa,
+               .idmask         = 0xffffffff,
+               .map_io         = s3c244x_map_io,
+               .init_clocks    = s3c244x_init_clocks,
+               .init_uarts     = s3c244x_init_uarts,
+               .init           = s3c2442_init,
+               .name           = name_s3c2442
+       },
        {
                .idcode         = 0x0,   /* S3C2400 doesn't have an idcode */
                .idmask         = 0xffffffff,
@@ -175,13 +189,13 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
                panic("Unknown S3C24XX CPU");
        }
 
+       printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
+
        if (cpu->map_io == NULL || cpu->init == NULL) {
                printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
                panic("Unsupported S3C24XX CPU");
        }
 
-       printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
-
        (cpu->map_io)(mach_desc, size);
 }
 
@@ -208,6 +222,49 @@ void __init s3c24xx_init_clocks(int xtal)
                (cpu->init_clocks)(xtal);
 }
 
+/* uart management */
+
+static int nr_uarts __initdata = 0;
+
+static struct s3c2410_uartcfg uart_cfgs[3];
+
+/* s3c24xx_init_uartdevs
+ *
+ * copy the specified platform data and configuration into our central
+ * set of devices, before the data is thrown away after the init process.
+ *
+ * This also fills in the array passed to the serial driver for the
+ * early initialisation of the console.
+*/
+
+void __init s3c24xx_init_uartdevs(char *name,
+                                 struct s3c24xx_uart_resources *res,
+                                 struct s3c2410_uartcfg *cfg, int no)
+{
+       struct platform_device *platdev;
+       struct s3c2410_uartcfg *cfgptr = uart_cfgs;
+       struct s3c24xx_uart_resources *resp;
+       int uart;
+
+       memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);
+
+       for (uart = 0; uart < no; uart++, cfg++, cfgptr++) {
+               platdev = s3c24xx_uart_src[cfgptr->hwport];
+
+               resp = res + cfgptr->hwport;
+
+               s3c24xx_uart_devs[uart] = platdev;
+
+               platdev->name = name;
+               platdev->resource = resp->resources;
+               platdev->num_resources = resp->nr_resources;
+
+               platdev->dev.platform_data = cfgptr;
+       }
+
+       nr_uarts = no;
+}
+
 void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 {
        if (cpu == NULL)
@@ -232,6 +289,10 @@ static int __init s3c_arch_init(void)
        if (ret != 0)
                return ret;
 
+       ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts);
+       if (ret != 0)
+               return ret;
+
        if (board != NULL) {
                struct platform_device **ptr = board->devices;
                int i;
index fc1067783f6d18ee7fb8a0572be4c9d81b871a17..40862899b2f199464a0e9dbc320fc6feb9ffd5ce 100644 (file)
@@ -31,6 +31,8 @@
 #define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
 
 /* forward declaration */
+struct s3c24xx_uart_resources;
+struct platform_device;
 struct s3c2410_uartcfg;
 struct map_desc;
 
@@ -44,6 +46,10 @@ extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 
 extern void s3c24xx_init_clocks(int xtal);
 
+extern void s3c24xx_init_uartdevs(char *name,
+                                 struct s3c24xx_uart_resources *res,
+                                 struct s3c2410_uartcfg *cfg, int no);
+
 /* the board structure is used at first initialsation time
  * to get info such as the devices to register for this
  * board. This is done because platfrom_add_devices() cannot
@@ -68,3 +74,4 @@ extern struct sys_timer s3c24xx_timer;
 /* system device classes */
 
 extern struct sysdev_class s3c2440_sysclass;
+extern struct sysdev_class s3c2442_sysclass;
index ca09ba516e4c1d92b5b7c4b090b702c2668702ef..ad3845e329ba26d8af79d6e50c6e878694dcca68 100644 (file)
 #include <asm/arch/regs-serial.h>
 
 #include "devs.h"
+#include "cpu.h"
 
 /* Serial port registrations */
 
-struct platform_device *s3c24xx_uart_devs[3];
+static struct resource s3c2410_uart0_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_UART0,
+               .end   = S3C2410_PA_UART0 + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_S3CUART_RX0,
+               .end   = IRQ_S3CUART_ERR0,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource s3c2410_uart1_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_UART1,
+               .end   = S3C2410_PA_UART1 + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_S3CUART_RX1,
+               .end   = IRQ_S3CUART_ERR1,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource s3c2410_uart2_resource[] = {
+       [0] = {
+               .start = S3C2410_PA_UART2,
+               .end   = S3C2410_PA_UART2 + 0x3fff,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_S3CUART_RX2,
+               .end   = IRQ_S3CUART_ERR2,
+               .flags = IORESOURCE_IRQ,
+       }
+};
+
+struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
+       [0] = {
+               .resources      = s3c2410_uart0_resource,
+               .nr_resources   = ARRAY_SIZE(s3c2410_uart0_resource),
+       },
+       [1] = {
+               .resources      = s3c2410_uart1_resource,
+               .nr_resources   = ARRAY_SIZE(s3c2410_uart1_resource),
+       },
+       [2] = {
+               .resources      = s3c2410_uart2_resource,
+               .nr_resources   = ARRAY_SIZE(s3c2410_uart2_resource),
+       },
+};
+
+/* yart devices */
+
+static struct platform_device s3c24xx_uart_device0 = {
+       .id             = 0,
+};
+
+static struct platform_device s3c24xx_uart_device1 = {
+       .id             = 1,
+};
+
+static struct platform_device s3c24xx_uart_device2 = {
+       .id             = 2,
+};
+
+struct platform_device *s3c24xx_uart_src[3] = {
+       &s3c24xx_uart_device0,
+       &s3c24xx_uart_device1,
+       &s3c24xx_uart_device2,
+};
+
+struct platform_device *s3c24xx_uart_devs[3] = {
+};
 
 /* USB Host Controller */
 
index 52c4bab5c7615590ec167bfe0658ba2fe1a2e663..fa124ed920e0dca9474941a422a3f16066fb97e0 100644 (file)
 #include <linux/config.h>
 #include <linux/platform_device.h>
 
+struct s3c24xx_uart_resources {
+       struct resource         *resources;
+       unsigned long            nr_resources;
+};
+
+extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
+
 extern struct platform_device *s3c24xx_uart_devs[];
+extern struct platform_device *s3c24xx_uart_src[];
 
 extern struct platform_device s3c_device_usb;
 extern struct platform_device s3c_device_lcd;
index cc97fbf66291e58551021bb2815c4cb5010f2cb9..52bf718137d415d81c0f49253fe738fcebf92b61 100644 (file)
@@ -131,7 +131,7 @@ static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
 };
 
 
-static struct s3c2410_uartcfg anubis_uartcfgs[] = {
+static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
        [0] = {
                .hwport      = 0,
                .flags       = 0,
index 995bb8add33176febe146fb1361b686b804c3cf4..947234df816003208defcd54e44ee44df9000913 100644 (file)
@@ -208,7 +208,7 @@ static struct s3c24xx_uart_clksrc bast_serial_clocks[] = {
 };
 
 
-static struct s3c2410_uartcfg bast_uartcfgs[] = {
+static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
        [0] = {
                .hwport      = 0,
                .flags       = 0,
index 646a3a5d33a50547ead10b3a201abc1e82ee3ced..aec431b2830a93d2ba5503816d706301a241a402 100644 (file)
@@ -72,7 +72,7 @@ static struct map_desc h1940_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg h1940_uartcfgs[] = {
+static struct s3c2410_uartcfg h1940_uartcfgs[] __initdata = {
        [0] = {
                .hwport      = 0,
                .flags       = 0,
index 07d09509a626cada03ca104f159d8a7e717cd0c1..065a1d4e860b53fd15fe8cd789917a1ffe471b26 100644 (file)
@@ -51,7 +51,7 @@ static struct map_desc nexcoder_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg nexcoder_uartcfgs[] = {
+static struct s3c2410_uartcfg nexcoder_uartcfgs[] __initdata = {
        [0] = {
                .hwport      = 0,
                .flags       = 0,
index ae0787557751909d5983d703c295f4e5638a6c9d..858fd03c6bc524d978546e2e1779fa771ff492cd 100644 (file)
@@ -95,8 +95,7 @@ static struct s3c24xx_uart_clksrc osiris_serial_clocks[] = {
        }
 };
 
-
-static struct s3c2410_uartcfg osiris_uartcfgs[] = {
+static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
        [0] = {
                .hwport      = 0,
                .flags       = 0,
@@ -107,7 +106,7 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] = {
                .clocks_size = ARRAY_SIZE(osiris_serial_clocks)
        },
        [1] = {
-               .hwport      = 2,
+               .hwport      = 1,
                .flags       = 0,
                .ucon        = UCON,
                .ulcon       = ULCON,
index b39daedf93ca4dd5088921994e08b6597258c40e..c71673fd9955e24558b9be628644cd48890fb60f 100644 (file)
@@ -45,7 +45,7 @@ static struct map_desc otom11_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg otom11_uartcfgs[] = {
+static struct s3c2410_uartcfg otom11_uartcfgs[] __initdata = {
        [0] = {
                .hwport      = 0,
                .flags       = 0,
index 2db932d72c5ae1047f75d880af5b6fd21f75e9c3..25f7e9f4dcee3a669b4f4717953fdeab84bc9247 100644 (file)
@@ -65,7 +65,7 @@ static struct map_desc smdk2410_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
+static struct s3c2410_uartcfg smdk2410_uartcfgs[] __initdata = {
        [0] = {
                .hwport      = 0,
                .flags       = 0,
index 5fffd1d51047b373cb0539658b61d1c859bb203e..d661c6b7ff5650811efa40a3afc66868aaa7ac21 100644 (file)
@@ -86,7 +86,7 @@ static struct map_desc smdk2440_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg smdk2440_uartcfgs[] = {
+static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = {
        [0] = {
                .hwport      = 0,
                .flags       = 0,
index 785fc9cdcf7c6b5d4877ab1c29e746e3bd600086..d18efb279d3dc89da1daea77fcdb0242ed3619a5 100644 (file)
@@ -166,7 +166,7 @@ static struct s3c24xx_uart_clksrc vr1000_serial_clocks[] = {
        }
 };
 
-static struct s3c2410_uartcfg vr1000_uartcfgs[] = {
+static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = {
        [0] = {
                .hwport      = 0,
                .flags       = 0,
index fe57d966a34d126b62194950ea10882f6c3a20fc..43e9a550a203d762e4f2f0dbcf013ad5b9d70787 100644 (file)
@@ -58,7 +58,11 @@ unsigned long s3c_pm_flags;
 
 /* cache functions from arch/arm/mm/proc-arm920.S */
 
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 extern void arm920_flush_kern_cache_all(void);
+#else
+static void arm920_flush_kern_cache_all(void) { }
+#endif
 
 #define PFX "s3c24xx-pm: "
 
index 0a2013a7654922161631ae5da0043834f9ed7e7e..0852e87a79c4c49742d3ec78b4e2615fa04a1297 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "s3c2410.h"
 #include "cpu.h"
+#include "devs.h"
 #include "clock.h"
 
 /* Initial IO mappings */
@@ -55,93 +56,13 @@ static struct map_desc s3c2410_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
 };
 
-static struct resource s3c_uart0_resource[] = {
-       [0] = {
-               .start = S3C2410_PA_UART0,
-               .end   = S3C2410_PA_UART0 + 0x3fff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3CUART_RX0,
-               .end   = IRQ_S3CUART_ERR0,
-               .flags = IORESOURCE_IRQ,
-       }
-
-};
-
-static struct resource s3c_uart1_resource[] = {
-       [0] = {
-               .start = S3C2410_PA_UART1,
-               .end   = S3C2410_PA_UART1 + 0x3fff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3CUART_RX1,
-               .end   = IRQ_S3CUART_ERR1,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static struct resource s3c_uart2_resource[] = {
-       [0] = {
-               .start = S3C2410_PA_UART2,
-               .end   = S3C2410_PA_UART2 + 0x3fff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3CUART_RX2,
-               .end   = IRQ_S3CUART_ERR2,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
 /* our uart devices */
 
-static struct platform_device s3c_uart0 = {
-       .name             = "s3c2410-uart",
-       .id               = 0,
-       .num_resources    = ARRAY_SIZE(s3c_uart0_resource),
-       .resource         = s3c_uart0_resource,
-};
-
-
-static struct platform_device s3c_uart1 = {
-       .name             = "s3c2410-uart",
-       .id               = 1,
-       .num_resources    = ARRAY_SIZE(s3c_uart1_resource),
-       .resource         = s3c_uart1_resource,
-};
-
-static struct platform_device s3c_uart2 = {
-       .name             = "s3c2410-uart",
-       .id               = 2,
-       .num_resources    = ARRAY_SIZE(s3c_uart2_resource),
-       .resource         = s3c_uart2_resource,
-};
-
-static struct platform_device *uart_devices[] __initdata = {
-       &s3c_uart0,
-       &s3c_uart1,
-       &s3c_uart2
-};
-
-static int s3c2410_uart_count = 0;
-
 /* uart registration process */
 
 void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 {
-       struct platform_device *platdev;
-       int uart;
-
-       for (uart = 0; uart < no; uart++, cfg++) {
-               platdev = uart_devices[cfg->hwport];
-
-               s3c24xx_uart_devs[uart] = platdev;
-               platdev->dev.platform_data = cfg;
-       }
-
-       s3c2410_uart_count = uart;
+       s3c24xx_init_uartdevs("s3c2410-uart", s3c2410_uart_resources, cfg, no);
 }
 
 /* s3c2410_map_io
@@ -193,5 +114,5 @@ int __init s3c2410_init(void)
 {
        printk("S3C2410: Initialising architecture\n");
 
-       return platform_add_devices(s3c24xx_uart_devs, s3c2410_uart_count);
+       return 0;
 }
index 278d0044c85d7c3315e46363094c3c125bb85dfe..acfe3870727ba24fa2fb12bc1823305a4fcb1b58 100644 (file)
@@ -100,73 +100,12 @@ static struct irqchip s3c_irq_wdtac97 = {
        .ack        = s3c_irq_wdtac97_ack,
 };
 
-/* camera irq */
-
-static void s3c_irq_demux_cam(unsigned int irq,
-                             struct irqdesc *desc,
-                             struct pt_regs *regs)
-{
-       unsigned int subsrc, submsk;
-       struct irqdesc *mydesc;
-
-       /* read the current pending interrupts, and the mask
-        * for what it is available */
-
-       subsrc = __raw_readl(S3C2410_SUBSRCPND);
-       submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-       subsrc &= ~submsk;
-       subsrc >>= 11;
-       subsrc &= 3;
-
-       if (subsrc != 0) {
-               if (subsrc & 1) {
-                       mydesc = irq_desc + IRQ_S3C2440_CAM_C;
-                       desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
-               }
-               if (subsrc & 2) {
-                       mydesc = irq_desc + IRQ_S3C2440_CAM_P;
-                       desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
-               }
-       }
-}
-
-#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
-
-static void
-s3c_irq_cam_mask(unsigned int irqno)
-{
-       s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
-}
-
-static void
-s3c_irq_cam_unmask(unsigned int irqno)
-{
-       s3c_irqsub_unmask(irqno, INTMSK_CAM);
-}
-
-static void
-s3c_irq_cam_ack(unsigned int irqno)
-{
-       s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
-}
-
-static struct irqchip s3c_irq_cam = {
-       .mask       = s3c_irq_cam_mask,
-       .unmask     = s3c_irq_cam_unmask,
-       .ack        = s3c_irq_cam_ack,
-};
-
 static int s3c2440_irq_add(struct sys_device *sysdev)
 {
        unsigned int irqno;
 
        printk("S3C2440: IRQ Support\n");
 
-       set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
-       set_irq_handler(IRQ_NFCON, do_level_IRQ);
-       set_irq_flags(IRQ_NFCON, IRQF_VALID);
-
        /* add new chained handler for wdt, ac7 */
 
        set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
@@ -179,18 +118,6 @@ static int s3c2440_irq_add(struct sys_device *sysdev)
                set_irq_flags(irqno, 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_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_flags(irqno, IRQF_VALID);
-       }
-
        return 0;
 }
 
@@ -198,10 +125,10 @@ static struct sysdev_driver s3c2440_irq_driver = {
        .add    = s3c2440_irq_add,
 };
 
-static int s3c24xx_irq_driver(void)
+static int s3c2440_irq_init(void)
 {
        return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
 }
 
-arch_initcall(s3c24xx_irq_driver);
+arch_initcall(s3c2440_irq_init);
 
index b7fe6d9453fbac0bc4f4d0d39fb3f2b0df925bf0..0ab50f44f318bef575e414ef24d44430996492ce 100644 (file)
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/s3c2440.c
  *
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2004-2006 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
  * Samsung S3C2440 Mobile CPU support
@@ -8,16 +8,6 @@
  * 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.
- *
- * Modifications:
- *     24-Aug-2004 BJD  Start of s3c2440 support
- *     12-Oct-2004 BJD  Moved clock info out to clock.c
- *     01-Nov-2004 BJD  Fixed clock build code
- *     09-Nov-2004 BJD  Added sysdev for power management
- *     04-Nov-2004 BJD  New serial registration
- *     15-Nov-2004 BJD  Rename the i2c device for the s3c2440
- *     14-Jan-2005 BJD  Moved clock init code into seperate function
- *     14-Jan-2005 BJD  Removed un-used clock bits
 */
 
 #include <linux/kernel.h>
 #include "cpu.h"
 #include "pm.h"
 
-
-static struct map_desc s3c2440_iodesc[] __initdata = {
-       IODESC_ENT(USBHOST),
-       IODESC_ENT(CLKPWR),
-       IODESC_ENT(LCD),
-       IODESC_ENT(TIMER),
-       IODESC_ENT(ADC),
-       IODESC_ENT(WATCHDOG),
-};
-
-static struct resource s3c_uart0_resource[] = {
-       [0] = {
-               .start = S3C2410_PA_UART0,
-               .end   = S3C2410_PA_UART0 + 0x3fff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3CUART_RX0,
-               .end   = IRQ_S3CUART_ERR0,
-               .flags = IORESOURCE_IRQ,
-       }
-
-};
-
-static struct resource s3c_uart1_resource[] = {
-       [0] = {
-               .start = S3C2410_PA_UART1,
-               .end   = S3C2410_PA_UART1 + 0x3fff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3CUART_RX1,
-               .end   = IRQ_S3CUART_ERR1,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-static struct resource s3c_uart2_resource[] = {
-       [0] = {
-               .start = S3C2410_PA_UART2,
-               .end   = S3C2410_PA_UART2 + 0x3fff,
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start = IRQ_S3CUART_RX2,
-               .end   = IRQ_S3CUART_ERR2,
-               .flags = IORESOURCE_IRQ,
-       }
-};
-
-/* our uart devices */
-
-static struct platform_device s3c_uart0 = {
-       .name             = "s3c2440-uart",
-       .id               = 0,
-       .num_resources    = ARRAY_SIZE(s3c_uart0_resource),
-       .resource         = s3c_uart0_resource,
-};
-
-static struct platform_device s3c_uart1 = {
-       .name             = "s3c2440-uart",
-       .id               = 1,
-       .num_resources    = ARRAY_SIZE(s3c_uart1_resource),
-       .resource         = s3c_uart1_resource,
-};
-
-static struct platform_device s3c_uart2 = {
-       .name             = "s3c2440-uart",
-       .id               = 2,
-       .num_resources    = ARRAY_SIZE(s3c_uart2_resource),
-       .resource         = s3c_uart2_resource,
-};
-
-static struct platform_device *uart_devices[] __initdata = {
-       &s3c_uart0,
-       &s3c_uart1,
-       &s3c_uart2
-};
-
-/* uart initialisation */
-
-static int __initdata s3c2440_uart_count;
-
-void __init s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-       struct platform_device *platdev;
-       int uart;
-
-       for (uart = 0; uart < no; uart++, cfg++) {
-               platdev = uart_devices[cfg->hwport];
-
-               s3c24xx_uart_devs[uart] = platdev;
-               platdev->dev.platform_data = cfg;
-       }
-
-       s3c2440_uart_count = uart;
-}
-
-
-#ifdef CONFIG_PM
-
-static struct sleep_save s3c2440_sleep[] = {
-       SAVE_ITEM(S3C2440_DSC0),
-       SAVE_ITEM(S3C2440_DSC1),
-       SAVE_ITEM(S3C2440_GPJDAT),
-       SAVE_ITEM(S3C2440_GPJCON),
-       SAVE_ITEM(S3C2440_GPJUP)
-};
-
-static int s3c2440_suspend(struct sys_device *dev, pm_message_t state)
-{
-       s3c2410_pm_do_save(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep));
-       return 0;
-}
-
-static int s3c2440_resume(struct sys_device *dev)
-{
-       s3c2410_pm_do_restore(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep));
-       return 0;
-}
-
-#else
-#define s3c2440_suspend NULL
-#define s3c2440_resume  NULL
-#endif
-
-struct sysdev_class s3c2440_sysclass = {
-       set_kset_name("s3c2440-core"),
-       .suspend        = s3c2440_suspend,
-       .resume         = s3c2440_resume
-};
-
 static struct sys_device s3c2440_sysdev = {
        .cls            = &s3c2440_sysclass,
 };
 
-void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
+int __init s3c2440_init(void)
 {
-       /* register our io-tables */
-
-       iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc));
-       iotable_init(mach_desc, size);
-
-       /* rename any peripherals used differing from the s3c2410 */
-
-       s3c_device_i2c.name  = "s3c2440-i2c";
-       s3c_device_nand.name = "s3c2440-nand";
+       printk("S3C2440: Initialising architecture\n");
 
        /* change irq for watchdog */
 
        s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
        s3c_device_wdt.resource[1].end   = IRQ_S3C2440_WDT;
-}
-
-void __init s3c2440_init_clocks(int xtal)
-{
-       unsigned long clkdiv;
-       unsigned long camdiv;
-       unsigned long hclk, fclk, pclk;
-       int hdiv = 1;
-
-       /* now we've got our machine bits initialised, work out what
-        * clocks we've got */
-
-       fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
-
-       clkdiv = __raw_readl(S3C2410_CLKDIVN);
-       camdiv = __raw_readl(S3C2440_CAMDIVN);
-
-       /* work out clock scalings */
-
-       switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
-       case S3C2440_CLKDIVN_HDIVN_1:
-               hdiv = 1;
-               break;
-
-       case S3C2440_CLKDIVN_HDIVN_2:
-               hdiv = 2;
-               break;
-
-       case S3C2440_CLKDIVN_HDIVN_4_8:
-               hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
-               break;
-
-       case S3C2440_CLKDIVN_HDIVN_3_6:
-               hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
-               break;
-       }
-
-       hclk = fclk / hdiv;
-       pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
-
-       /* print brief summary of clocks, etc */
-
-       printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
-              print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
-
-       /* initialise the clocks here, to allow other things like the
-        * console to use them, and to add new ones after the initialisation
-        */
-
-       s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
-}
-
-/* need to register class before we actually register the device, and
- * we also need to ensure that it has been initialised before any of the
- * drivers even try to use it (even if not on an s3c2440 based system)
- * as a driver which may support both 2410 and 2440 may try and use it.
-*/
-
-static int __init s3c2440_core_init(void)
-{
-       return sysdev_class_register(&s3c2440_sysclass);
-}
-
-core_initcall(s3c2440_core_init);
-
-int __init s3c2440_init(void)
-{
-       int ret;
-
-       printk("S3C2440: Initialising architecture\n");
 
-       ret = sysdev_register(&s3c2440_sysdev);
-       if (ret != 0)
-               printk(KERN_ERR "failed to register sysdev for s3c2440\n");
-       else
-               ret = platform_add_devices(s3c24xx_uart_devs, s3c2440_uart_count);
+       /* register our system device for everything else */
 
-       return ret;
+       return sysdev_register(&s3c2440_sysdev);
 }
diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2410/s3c2442-clock.c
new file mode 100644 (file)
index 0000000..5b7b301
--- /dev/null
@@ -0,0 +1,171 @@
+/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2442 Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+
+#include <asm/hardware.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+/* S3C2442 extended clock support */
+
+static unsigned long s3c2442_camif_upll_round(struct clk *clk,
+                                             unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       int div;
+
+       if (rate > parent_rate)
+               return parent_rate;
+
+       div = parent_rate / rate;
+
+       if (div == 3)
+               return parent_rate / 3;
+
+       /* note, we remove the +/- 1 calculations for the divisor */
+
+       div /= 2;
+
+       if (div < 1)
+               div = 1;
+       else if (div > 16)
+               div = 16;
+
+       return parent_rate / (div * 2);
+}
+
+static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
+{
+       unsigned long parent_rate = clk_get_rate(clk->parent);
+       unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
+
+       rate = s3c2442_camif_upll_round(clk, rate);
+
+       camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
+
+       if (rate == parent_rate) {
+               camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
+       } else if ((parent_rate / rate) == 3) {
+               camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+               camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
+       } else {
+               camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
+               camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+               camdivn |= (((parent_rate / rate) / 2) - 1);
+       }
+
+       __raw_writel(camdivn, S3C2440_CAMDIVN);
+
+       return 0;
+}
+
+/* Extra S3C2442 clocks */
+
+static struct clk s3c2442_clk_cam = {
+       .name           = "camif",
+       .id             = -1,
+       .enable         = s3c24xx_clkcon_enable,
+       .ctrlbit        = S3C2440_CLKCON_CAMERA,
+};
+
+static struct clk s3c2442_clk_cam_upll = {
+       .name           = "camif-upll",
+       .id             = -1,
+       .set_rate       = s3c2442_camif_upll_setrate,
+       .round_rate     = s3c2442_camif_upll_round,
+};
+
+static int s3c2442_clk_add(struct sys_device *sysdev)
+{
+       unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
+       unsigned long clkdivn;
+       struct clk *clk_h;
+       struct clk *clk_p;
+       struct clk *clk_upll;
+
+       printk("S3C2442: Clock Support, DVS %s\n",
+              (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
+
+       clk_p = clk_get(NULL, "pclk");
+       clk_h = clk_get(NULL, "hclk");
+       clk_upll = clk_get(NULL, "upll");
+
+       if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) {
+               printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
+               return -EINVAL;
+       }
+
+       /* check rate of UPLL, and if it is near 96MHz, then change
+        * to using half the UPLL rate for the system */
+
+       if (clk_get_rate(clk_upll) > (94 * MHZ)) {
+               clk_usb_bus.rate = clk_get_rate(clk_upll) / 2;
+
+               mutex_lock(&clocks_mutex);
+
+               clkdivn = __raw_readl(S3C2410_CLKDIVN);
+               clkdivn |= S3C2440_CLKDIVN_UCLK;
+               __raw_writel(clkdivn, S3C2410_CLKDIVN);
+
+               mutex_unlock(&clocks_mutex);
+       }
+
+       s3c2442_clk_cam.parent = clk_h;
+       s3c2442_clk_cam_upll.parent = clk_upll;
+
+       s3c24xx_register_clock(&s3c2442_clk_cam);
+       s3c24xx_register_clock(&s3c2442_clk_cam_upll);
+
+       clk_disable(&s3c2442_clk_cam);
+
+       return 0;
+}
+
+static struct sysdev_driver s3c2442_clk_driver = {
+       .add    = s3c2442_clk_add,
+};
+
+static __init int s3c2442_clk_init(void)
+{
+       return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver);
+}
+
+arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2410/s3c2442.c
new file mode 100644 (file)
index 0000000..debae24
--- /dev/null
@@ -0,0 +1,52 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2442 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2442.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+#include "pm.h"
+
+static struct sys_device s3c2442_sysdev = {
+       .cls            = &s3c2442_sysclass,
+};
+
+int __init s3c2442_init(void)
+{
+       printk("S3C2442: Initialising architecture\n");
+
+       return sysdev_register(&s3c2442_sysdev);
+}
diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/arch/arm/mach-s3c2410/s3c2442.h
new file mode 100644 (file)
index 0000000..0ae37d2
--- /dev/null
@@ -0,0 +1,17 @@
+/* arch/arm/mach-s3c2410/s3c2442.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2442
+extern  int s3c2442_init(void);
+#else
+#define s3c2442_init NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c
new file mode 100644 (file)
index 0000000..2aadca1
--- /dev/null
@@ -0,0 +1,142 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Changelog:
+ *     25-Jul-2005 BJD         Split from irq.c
+ *
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "cpu.h"
+#include "pm.h"
+#include "irq.h"
+
+/* camera irq */
+
+static void s3c_irq_demux_cam(unsigned int irq,
+                             struct irqdesc *desc,
+                             struct pt_regs *regs)
+{
+       unsigned int subsrc, submsk;
+       struct irqdesc *mydesc;
+
+       /* read the current pending interrupts, and the mask
+        * for what it is available */
+
+       subsrc = __raw_readl(S3C2410_SUBSRCPND);
+       submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+       subsrc &= ~submsk;
+       subsrc >>= 11;
+       subsrc &= 3;
+
+       if (subsrc != 0) {
+               if (subsrc & 1) {
+                       mydesc = irq_desc + IRQ_S3C2440_CAM_C;
+                       desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
+               }
+               if (subsrc & 2) {
+                       mydesc = irq_desc + IRQ_S3C2440_CAM_P;
+                       desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
+               }
+       }
+}
+
+#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
+
+static void
+s3c_irq_cam_mask(unsigned int irqno)
+{
+       s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
+}
+
+static void
+s3c_irq_cam_unmask(unsigned int irqno)
+{
+       s3c_irqsub_unmask(irqno, INTMSK_CAM);
+}
+
+static void
+s3c_irq_cam_ack(unsigned int irqno)
+{
+       s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
+}
+
+static struct irqchip s3c_irq_cam = {
+       .mask       = s3c_irq_cam_mask,
+       .unmask     = s3c_irq_cam_unmask,
+       .ack        = s3c_irq_cam_ack,
+};
+
+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_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_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_flags(irqno, IRQF_VALID);
+       }
+
+       return 0;
+}
+
+static struct sysdev_driver s3c244x_irq_driver = {
+       .add    = s3c244x_irq_add,
+};
+
+static int s3c2440_irq_init(void)
+{
+       return sysdev_driver_register(&s3c2440_sysclass, &s3c244x_irq_driver);
+}
+
+arch_initcall(s3c2440_irq_init);
+
+
+static int s3c2442_irq_init(void)
+{
+       return sysdev_driver_register(&s3c2442_sysclass, &s3c244x_irq_driver);
+}
+
+arch_initcall(s3c2442_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/mach-s3c2410/s3c244x.c
new file mode 100644 (file)
index 0000000..96852a7
--- /dev/null
@@ -0,0 +1,182 @@
+/* linux/arch/arm/mach-s3c2410/s3c244x.c
+ *
+ * Copyright (c) 2004-2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 and S3C2442 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2440.h"
+#include "s3c244x.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+#include "pm.h"
+
+static struct map_desc s3c244x_iodesc[] __initdata = {
+       IODESC_ENT(CLKPWR),
+       IODESC_ENT(TIMER),
+       IODESC_ENT(WATCHDOG),
+       IODESC_ENT(LCD),
+       IODESC_ENT(ADC),
+       IODESC_ENT(USBHOST),
+};
+
+/* uart initialisation */
+
+void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+       s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
+}
+
+void __init s3c244x_map_io(struct map_desc *mach_desc, int size)
+{
+       /* register our io-tables */
+
+       iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));
+       iotable_init(mach_desc, size);
+
+       /* rename any peripherals used differing from the s3c2410 */
+
+       s3c_device_i2c.name  = "s3c2440-i2c";
+       s3c_device_nand.name = "s3c2440-nand";
+}
+
+void __init s3c244x_init_clocks(int xtal)
+{
+       unsigned long clkdiv;
+       unsigned long camdiv;
+       unsigned long hclk, fclk, pclk;
+       int hdiv = 1;
+
+       /* now we've got our machine bits initialised, work out what
+        * clocks we've got */
+
+       fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
+
+       clkdiv = __raw_readl(S3C2410_CLKDIVN);
+       camdiv = __raw_readl(S3C2440_CAMDIVN);
+
+       /* work out clock scalings */
+
+       switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
+       case S3C2440_CLKDIVN_HDIVN_1:
+               hdiv = 1;
+               break;
+
+       case S3C2440_CLKDIVN_HDIVN_2:
+               hdiv = 2;
+               break;
+
+       case S3C2440_CLKDIVN_HDIVN_4_8:
+               hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+               break;
+
+       case S3C2440_CLKDIVN_HDIVN_3_6:
+               hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
+               break;
+       }
+
+       hclk = fclk / hdiv;
+       pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
+
+       /* print brief summary of clocks, etc */
+
+       printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+              print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+       /* initialise the clocks here, to allow other things like the
+        * console to use them, and to add new ones after the initialisation
+        */
+
+       s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save s3c244x_sleep[] = {
+       SAVE_ITEM(S3C2440_DSC0),
+       SAVE_ITEM(S3C2440_DSC1),
+       SAVE_ITEM(S3C2440_GPJDAT),
+       SAVE_ITEM(S3C2440_GPJCON),
+       SAVE_ITEM(S3C2440_GPJUP)
+};
+
+static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
+{
+       s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+       return 0;
+}
+
+static int s3c244x_resume(struct sys_device *dev)
+{
+       s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+       return 0;
+}
+
+#else
+#define s3c244x_suspend NULL
+#define s3c244x_resume  NULL
+#endif
+
+/* Since the S3C2442 and S3C2440 share  items, put both sysclasses here */
+
+struct sysdev_class s3c2440_sysclass = {
+       set_kset_name("s3c2440-core"),
+       .suspend        = s3c244x_suspend,
+       .resume         = s3c244x_resume
+};
+
+struct sysdev_class s3c2442_sysclass = {
+       set_kset_name("s3c2442-core"),
+       .suspend        = s3c244x_suspend,
+       .resume         = s3c244x_resume
+};
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2440 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+static int __init s3c2440_core_init(void)
+{
+       return sysdev_class_register(&s3c2440_sysclass);
+}
+
+core_initcall(s3c2440_core_init);
+
+static int __init s3c2442_core_init(void)
+{
+       return sysdev_class_register(&s3c2442_sysclass);
+}
+
+core_initcall(s3c2442_core_init);
diff --git a/arch/arm/mach-s3c2410/s3c244x.h b/arch/arm/mach-s3c2410/s3c244x.h
new file mode 100644 (file)
index 0000000..3e7f5f7
--- /dev/null
@@ -0,0 +1,25 @@
+/* arch/arm/mach-s3c2410/s3c2440.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2440 and S3C2442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+
+extern void s3c244x_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c244x_init_clocks(int xtal);
+
+#else
+#define s3c244x_init_clocks NULL
+#define s3c244x_init_uarts NULL
+#define s3c244x_map_io NULL
+#endif
index 73de2eaca22a1c136db339177eb95d1acc4a7610..5f6761ed96b207cdcae72642b693a52c0ca94242 100644 (file)
@@ -66,7 +66,9 @@ ENTRY(s3c2410_cpu_suspend)
        @@ flush the caches to ensure everything is back out to
        @@ SDRAM before the core powers down
 
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
        bl      arm920_flush_kern_cache_all
+#endif
 
        @@ prepare cpu to sleep
 
index 9e02bc3712a00b5046245e71a13c1c99101bbcbc..af6d2775cf8237e34aecd21f8039083acbabc5db 100644 (file)
@@ -59,6 +59,14 @@ neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
                if (irr & (IRR_ETHERNET | IRR_USAR)) {
                        desc->chip->mask(irq);
 
+                       /*
+                        * Ack the interrupt now to prevent re-entering
+                        * this neponset handler.  Again, this is safe
+                        * since we'll check the IRR register prior to
+                        * leaving.
+                        */
+                       desc->chip->ack(irq);
+
                        if (irr & IRR_ETHERNET) {
                                d = irq_desc + IRQ_NEPONSET_SMC9196;
                                desc_handle_irq(IRQ_NEPONSET_SMC9196, d, regs);
index 799697d32decb052f60cb50190541194f65bb92e..cebd48a3dae4b757f7a44c95030e6dafe2945a95 100644 (file)
@@ -112,10 +112,9 @@ void __init versatile_init_irq(void)
 {
        unsigned int i;
 
-       vic_init(VA_VIC_BASE, IRQ_VIC_START, ~(1 << 31));
+       vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0);
 
-       set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq);
-       enable_irq(IRQ_VICSOURCE31);
+       set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq);
 
        /* Do second interrupt controller */
        writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
index c55b739e10bafaa002df9c9a56b678b1cd9368f8..1ff2f073a55d6be2eff3531cad6079ca5e45279b 100644 (file)
@@ -121,8 +121,8 @@ config CPU_ARM925T
 # ARM926T
 config CPU_ARM926T
        bool "Support ARM926T processor"
-       depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB
-       default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX
+       depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008
+       default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008
        select CPU_32v5
        select CPU_ABRT_EV5TJ
        select CPU_CACHE_VIVT
index f14b2d0f3690a002cf396bfa521c57eae068a242..95273de4f772515780e2eac97ed2ae892ac52a0d 100644 (file)
@@ -376,7 +376,7 @@ void __init build_mem_type_table(void)
                ecc_mask = 0;
        }
 
-       if (cpu_arch <= CPU_ARCH_ARMv5TEJ) {
+       if (cpu_arch <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) {
                for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
                        if (mem_types[i].prot_l1)
                                mem_types[i].prot_l1 |= PMD_BIT4;
@@ -631,7 +631,7 @@ void setup_mm_for_reboot(char mode)
                pgd = init_mm.pgd;
 
        base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
-       if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ)
+       if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
                base_pmdval |= PMD_BIT4;
 
        for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
index 80873b36c3f7a562657a32d9de47e790972cb2d9..8d32e21fe151a919630dc866205974888b624e3a 100644 (file)
@@ -427,12 +427,13 @@ __xsc3_setup:
 #endif
        mcr     p15, 0, r0, c1, c0, 1           @ set auxiliary control reg
        mrc     p15, 0, r0, c1, c0, 0           @ get control register
-       bic     r0, r0, #0x0200                 @ .... ..R. .... ....
        bic     r0, r0, #0x0002                 @ .... .... .... ..A.
        orr     r0, r0, #0x0005                 @ .... .... .... .C.M
 #if BTB_ENABLE
+       bic     r0, r0, #0x0200                 @ .... ..R. .... ....
        orr     r0, r0, #0x3900                 @ ..VI Z..S .... ....
 #else
+       bic     r0, r0, #0x0a00                 @ .... Z.R. .... ....
        orr     r0, r0, #0x3100                 @ ..VI ...S .... ....
 #endif
 #if L2_CACHE_ENABLE
index daee69579b1c6cd6dba672b79c48a2197453f56a..40e5aba3ad3d425f1545ff7e199e1356a56e38d8 100644 (file)
@@ -1066,14 +1066,6 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = {
                     DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
                     },
         },
-       {
-        .callback = disable_acpi_pci,
-        .ident = "HP xw9300",
-        .matches = {
-                   DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                   DMI_MATCH(DMI_PRODUCT_NAME, "HP xw9300 Workstation"),
-                   },
-       },
        {}
 };
 
index 2e3b643a4dc4df57552562015349c7657ca5b5d6..1649a175a206ab4bd6ed0add0040580ff83d036e 100644 (file)
@@ -5,17 +5,34 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/acpi.h>
+
 #include <asm/pci-direct.h>
 #include <asm/acpi.h>
 #include <asm/apic.h>
 
+#ifdef CONFIG_ACPI
+
+static int nvidia_hpet_detected __initdata;
+
+static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
+{
+       nvidia_hpet_detected = 1;
+       return 0;
+}
+#endif
+
 static int __init check_bridge(int vendor, int device)
 {
 #ifdef CONFIG_ACPI
-       /* According to Nvidia all timer overrides are bogus. Just ignore
-          them all. */
+       /* According to Nvidia all timer overrides are bogus unless HPET
+          is enabled. */
        if (vendor == PCI_VENDOR_ID_NVIDIA) {
-               acpi_skip_timer_override = 1;
+               nvidia_hpet_detected = 0;
+               acpi_table_parse(ACPI_HPET, nvidia_hpet_check);
+               if (nvidia_hpet_detected == 0) {
+                       acpi_skip_timer_override = 1;
+               }
        }
 #endif
        if (vendor == PCI_VENDOR_ID_ATI && timer_over_8254 == 1) {
index 3852d0a4c1b5e2f35dc168399d12b97882ca8938..1a7bdcef19261deff5a7ea8ee13d5a8ddb434a19 100644 (file)
@@ -104,7 +104,7 @@ acpi_processor_set_performance (
 {
        u16                     port = 0;
        u8                      bit_width = 0;
-       int                     ret = 0;
+       int                     ret;
        u32                     value = 0;
        int                     i = 0;
        struct cpufreq_freqs    cpufreq_freqs;
@@ -195,7 +195,6 @@ acpi_processor_set_performance (
                        udelay(10);
                }
        } else {
-               i = 0;
                value = (u32) data->acpi_data.states[state].status;
        }
 
@@ -444,14 +443,15 @@ static struct freq_attr* acpi_cpufreq_attr[] = {
 };
 
 static struct cpufreq_driver acpi_cpufreq_driver = {
-       .verify         = acpi_cpufreq_verify,
-       .target         = acpi_cpufreq_target,
-       .init           = acpi_cpufreq_cpu_init,
-       .exit           = acpi_cpufreq_cpu_exit,
-       .resume         = acpi_cpufreq_resume,
-       .name           = "acpi-cpufreq",
-       .owner          = THIS_MODULE,
-       .attr           = acpi_cpufreq_attr,
+       .verify = acpi_cpufreq_verify,
+       .target = acpi_cpufreq_target,
+       .init   = acpi_cpufreq_cpu_init,
+       .exit   = acpi_cpufreq_cpu_exit,
+       .resume = acpi_cpufreq_resume,
+       .name   = "acpi-cpufreq",
+       .owner  = THIS_MODULE,
+       .attr   = acpi_cpufreq_attr,
+       .flags  = CPUFREQ_STICKY,
 };
 
 
index f275e0d4aee525a5868963e6e8240a2b531cb2cd..0d49d73d1b711274387f6f23988415073774bc78 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) 2004  Sebastian Witt <se.witt@gmx.net>
+ * (C) 2004-2006  Sebastian Witt <se.witt@gmx.net>
  *
  *  Licensed under the terms of the GNU GPL License version 2.
  *  Based upon reverse engineered information
@@ -90,7 +90,7 @@ static int nforce2_calc_pll(unsigned int fsb)
 
        /* Try to calculate multiplier and divider up to 4 times */
        while (((mul == 0) || (div == 0)) && (tried <= 3)) {
-               for (xdiv = 1; xdiv <= 0x80; xdiv++)
+               for (xdiv = 2; xdiv <= 0x80; xdiv++)
                        for (xmul = 1; xmul <= 0xfe; xmul++)
                                if (nforce2_calc_fsb(NFORCE2_PLL(xmul, xdiv)) ==
                                    fsb + tried) {
@@ -117,8 +117,7 @@ static void nforce2_write_pll(int pll)
        int temp;
 
        /* Set the pll addr. to 0x00 */
-       temp = 0x00;
-       pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLADR, temp);
+       pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLADR, 0);
 
        /* Now write the value in all 64 registers */
        for (temp = 0; temp <= 0x3f; temp++)
@@ -266,7 +265,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
        if (freqs.old == freqs.new)
                return 0;
 
-       dprintk(KERN_INFO "cpufreq: Old CPU frequency %d kHz, new %d kHz\n",
+       dprintk("Old CPU frequency %d kHz, new %d kHz\n",
               freqs.old, freqs.new);
 
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
@@ -278,7 +277,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
                printk(KERN_ERR "cpufreq: Changing FSB to %d failed\n",
                        target_fsb);
        else
-               dprintk(KERN_INFO "cpufreq: Changed FSB successfully to %d\n",
+               dprintk("Changed FSB successfully to %d\n",
                        target_fsb);
 
        /* Enable IRQs */
index 8ef38544453c24cb8488d3202ed23750890d4566..146f607e9c44addc0e5cbb3856b2763cadd46173 100644 (file)
@@ -77,13 +77,17 @@ static char speedbuffer[8];
 
 static char *print_speed(int speed)
 {
-       if (speed > 1000) {
-               if (speed%1000 == 0)
-                       sprintf (speedbuffer, "%dGHz", speed/1000);
-               else
-                       sprintf (speedbuffer, "%d.%dGHz", speed/1000, (speed%1000)/100);
-       } else
-               sprintf (speedbuffer, "%dMHz", speed);
+       if (speed < 1000) {
+               snprintf(speedbuffer, sizeof(speedbuffer),"%dMHz", speed);
+               return speedbuffer;
+       }
+
+       if (speed%1000 == 0)
+               snprintf(speedbuffer, sizeof(speedbuffer),
+                       "%dGHz", speed/1000);
+       else
+               snprintf(speedbuffer, sizeof(speedbuffer),
+                       "%d.%dGHz", speed/1000, (speed%1000)/100);
 
        return speedbuffer;
 }
@@ -675,7 +679,7 @@ static int __init longhaul_init(void)
 
 static void __exit longhaul_exit(void)
 {
-       int i=0;
+       int i;
 
        for (i=0; i < numscales; i++) {
                if (clock_ratio[i] == maxmult) {
index e3868de4dc2e9c6bdb1a0ab74fef819b926ea195..b2689514295ab361057623dd7c2afb56d7deb81e 100644 (file)
@@ -223,7 +223,6 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
                /* set to 0 to try_hi perf_pctg */
                msr_lo &= 0xFFFFFF80;
                msr_hi &= 0xFFFFFF80;
-               msr_lo |= 0;
                msr_hi |= try_hi;
                wrmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
 
index 2bf4237cb94ea85e8bd3d39ee4242643e1fdf3b8..694d4793bf6ae5f1aaf1bddae150e958f572fecf 100644 (file)
@@ -452,23 +452,23 @@ static int powernow_decode_bios (int maxfid, int startvid)
 
                        pst = (struct pst_s *) p;
 
-                       for (i = 0 ; i <psb->numpst; i++) {
+                       for (j=0; j<psb->numpst; j++) {
                                pst = (struct pst_s *) p;
                                number_scales = pst->numpstates;
 
                                if ((etuple == pst->cpuid) && check_fsb(pst->fsbspeed) &&
                                    (maxfid==pst->maxfid) && (startvid==pst->startvid))
                                {
-                                       dprintk ("PST:%d (@%p)\n", i, pst);
+                                       dprintk ("PST:%d (@%p)\n", j, pst);
                                        dprintk (" cpuid: 0x%x  fsb: %d  maxFID: 0x%x  startvid: 0x%x\n",
                                                 pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
 
                                        ret = get_ranges ((char *) pst + sizeof (struct pst_s));
                                        return ret;
-
                                } else {
+                                       unsigned int k;
                                        p = (char *) pst + sizeof (struct pst_s);
-                                       for (j=0 ; j < number_scales; j++)
+                                       for (k=0; k<number_scales; k++)
                                                p+=2;
                                }
                        }
@@ -581,10 +581,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
 
        rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
 
-       /* recalibrate cpu_khz */
-       result = recalibrate_cpu_khz();
-       if (result)
-               return result;
+       recalibrate_cpu_khz();
 
        fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
        if (!fsb) {
index 71fffa17442530949dccf45aa210c2e371188a59..b4277f58f40c395a575963c2d4726b364a597aa9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *   (c) 2003, 2004, 2005 Advanced Micro Devices, Inc.
+ *   (c) 2003-2006 Advanced Micro Devices, Inc.
  *  Your use of this code is subject to the terms and conditions of the
  *  GNU general public license version 2. See "COPYING" or
  *  http://www.gnu.org/licenses/gpl.html
  *  Based upon datasheets & sample CPUs kindly provided by AMD.
  *
  *  Valuable input gratefully received from Dave Jones, Pavel Machek,
- *  Dominik Brodowski, and others.
+ *  Dominik Brodowski, Jacob Shin, and others.
  *  Originally developed by Paul Devriendt.
  *  Processor information obtained from Chapter 9 (Power and Thermal Management)
  *  of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
  *  Opteron Processors" available for download from www.amd.com
  *
- *  Tables for specific CPUs can be infrerred from
+ *  Tables for specific CPUs can be inferred from
  *     http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
  */
 
@@ -46,7 +46,7 @@
 
 #define PFX "powernow-k8: "
 #define BFX PFX "BIOS error: "
-#define VERSION "version 1.60.2"
+#define VERSION "version 2.00.00"
 #include "powernow-k8.h"
 
 /* serialize freq changes  */
@@ -54,6 +54,8 @@ static DEFINE_MUTEX(fidvid_mutex);
 
 static struct powernow_k8_data *powernow_data[NR_CPUS];
 
+static int cpu_family = CPU_OPTERON;
+
 #ifndef CONFIG_SMP
 static cpumask_t cpu_core_map[1];
 #endif
@@ -64,16 +66,36 @@ static u32 find_freq_from_fid(u32 fid)
        return 800 + (fid * 100);
 }
 
+
 /* Return a frequency in KHz, given an input fid */
 static u32 find_khz_freq_from_fid(u32 fid)
 {
        return 1000 * find_freq_from_fid(fid);
 }
 
-/* Return a voltage in miliVolts, given an input vid */
-static u32 find_millivolts_from_vid(struct powernow_k8_data *data, u32 vid)
+/* Return a frequency in MHz, given an input fid and did */
+static u32 find_freq_from_fiddid(u32 fid, u32 did)
+{
+       return 100 * (fid + 0x10) >> did;
+}
+
+static u32 find_khz_freq_from_fiddid(u32 fid, u32 did)
 {
-       return 1550-vid*25;
+       return 1000 * find_freq_from_fiddid(fid, did);
+}
+
+static u32 find_fid_from_pstate(u32 pstate)
+{
+       u32 hi, lo;
+       rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi);
+       return lo & HW_PSTATE_FID_MASK;
+}
+
+static u32 find_did_from_pstate(u32 pstate)
+{
+       u32 hi, lo;
+       rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi);
+       return (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
 }
 
 /* Return the vco fid for an input fid
@@ -98,6 +120,9 @@ static int pending_bit_stuck(void)
 {
        u32 lo, hi;
 
+       if (cpu_family)
+               return 0;
+
        rdmsr(MSR_FIDVID_STATUS, lo, hi);
        return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0;
 }
@@ -111,6 +136,14 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
        u32 lo, hi;
        u32 i = 0;
 
+       if (cpu_family) {
+               rdmsr(MSR_PSTATE_STATUS, lo, hi);
+               i = lo & HW_PSTATE_MASK;
+               rdmsr(MSR_PSTATE_DEF_BASE + i, lo, hi);
+               data->currfid = lo & HW_PSTATE_FID_MASK;
+               data->currdid = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
+               return 0;
+       }
        do {
                if (i++ > 10000) {
                        dprintk("detected change pending stuck\n");
@@ -175,7 +208,7 @@ static int write_new_fid(struct powernow_k8_data *data, u32 fid)
        do {
                wrmsr(MSR_FIDVID_CTL, lo, data->plllock * PLL_LOCK_CONVERSION);
                if (i++ > 100) {
-                       printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
+                       printk(KERN_ERR PFX "Hardware error - pending bit very stuck - no further pstate changes possible\n");
                        return 1;
                }
        } while (query_current_values_with_pending_wait(data));
@@ -255,7 +288,15 @@ static int decrease_vid_code_by_step(struct powernow_k8_data *data, u32 reqvid,
        return 0;
 }
 
-/* Change the fid and vid, by the 3 phases. */
+/* Change hardware pstate by single MSR write */
+static int transition_pstate(struct powernow_k8_data *data, u32 pstate)
+{
+       wrmsr(MSR_PSTATE_CTRL, pstate, 0);
+       data->currfid = find_fid_from_pstate(pstate);
+       return 0;
+}
+
+/* Change Opteron/Athlon64 fid and vid, by the 3 phases. */
 static int transition_fid_vid(struct powernow_k8_data *data, u32 reqfid, u32 reqvid)
 {
        if (core_voltage_pre_transition(data, reqvid))
@@ -474,26 +515,35 @@ static int check_supported_cpu(unsigned int cpu)
                goto out;
 
        eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
-       if ((eax & CPUID_XFAM) != CPUID_XFAM_K8)
+       if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) &&
+           ((eax & CPUID_XFAM) < CPUID_XFAM_10H))
                goto out;
 
-       if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
-           ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) {
-               printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
-               goto out;
-       }
+       if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) {
+               if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
+                   ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) {
+                       printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
+                       goto out;
+               }
 
-       eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
-       if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
-               printk(KERN_INFO PFX
-                      "No frequency change capabilities detected\n");
-               goto out;
-       }
+               eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
+               if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
+                       printk(KERN_INFO PFX
+                              "No frequency change capabilities detected\n");
+                       goto out;
+               }
 
-       cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
-       if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
-               printk(KERN_INFO PFX "Power state transitions not supported\n");
-               goto out;
+               cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
+               if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
+                       printk(KERN_INFO PFX "Power state transitions not supported\n");
+                       goto out;
+               }
+       } else { /* must be a HW Pstate capable processor */
+               cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
+               if ((edx & USE_HW_PSTATE) == USE_HW_PSTATE)
+                       cpu_family = CPU_HW_PSTATE;
+               else
+                       goto out;
        }
 
        rc = 1;
@@ -547,12 +597,18 @@ static void print_basics(struct powernow_k8_data *data)
 {
        int j;
        for (j = 0; j < data->numps; j++) {
-               if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID)
-                       printk(KERN_INFO PFX "   %d : fid 0x%x (%d MHz), vid 0x%x (%d mV)\n", j,
+               if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
+                       if (cpu_family) {
+                       printk(KERN_INFO PFX "   %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8,
+                               (data->powernow_table[j].index & 0xff0000) >> 16,
+                               data->powernow_table[j].frequency/1000);
+                       } else {
+                       printk(KERN_INFO PFX "   %d : fid 0x%x (%d MHz), vid 0x%x\n", j,
                                data->powernow_table[j].index & 0xff,
                                data->powernow_table[j].frequency/1000,
-                               data->powernow_table[j].index >> 8,
-                               find_millivolts_from_vid(data, data->powernow_table[j].index >> 8));
+                               data->powernow_table[j].index >> 8);
+                       }
+               }
        }
        if (data->batps)
                printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps);
@@ -702,7 +758,7 @@ static int find_psb_table(struct powernow_k8_data *data)
 #ifdef CONFIG_X86_POWERNOW_K8_ACPI
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
 {
-       if (!data->acpi_data.state_count)
+       if (!data->acpi_data.state_count || cpu_family)
                return;
 
        data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK;
@@ -715,9 +771,8 @@ static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned
 
 static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
 {
-       int i;
-       int cntlofreq = 0;
        struct cpufreq_frequency_table *powernow_table;
+       int ret_val;
 
        if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
                dprintk("register performance failed: bad ACPI data\n");
@@ -746,6 +801,85 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
                goto err_out;
        }
 
+       if (cpu_family)
+               ret_val = fill_powernow_table_pstate(data, powernow_table);
+       else
+               ret_val = fill_powernow_table_fidvid(data, powernow_table);
+       if (ret_val)
+               goto err_out_mem;
+
+       powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END;
+       powernow_table[data->acpi_data.state_count].index = 0;
+       data->powernow_table = powernow_table;
+
+       /* fill in data */
+       data->numps = data->acpi_data.state_count;
+       print_basics(data);
+       powernow_k8_acpi_pst_values(data, 0);
+
+       /* notify BIOS that we exist */
+       acpi_processor_notify_smm(THIS_MODULE);
+
+       return 0;
+
+err_out_mem:
+       kfree(powernow_table);
+
+err_out:
+       acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
+
+       /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
+       data->acpi_data.state_count = 0;
+
+       return -ENODEV;
+}
+
+static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
+{
+       int i;
+
+       for (i = 0; i < data->acpi_data.state_count; i++) {
+               u32 index;
+               u32 hi = 0, lo = 0;
+               u32 fid;
+               u32 did;
+
+               index = data->acpi_data.states[i].control & HW_PSTATE_MASK;
+               if (index > MAX_HW_PSTATE) {
+                       printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index);
+                       printk(KERN_ERR PFX "Please report to BIOS manufacturer\n");
+               }
+               rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
+               if (!(hi & HW_PSTATE_VALID_MASK)) {
+                       dprintk("invalid pstate %d, ignoring\n", index);
+                       powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+                       continue;
+               }
+
+               fid = lo & HW_PSTATE_FID_MASK;
+               did = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
+
+               dprintk("   %d : fid 0x%x, did 0x%x\n", index, fid, did);
+
+               powernow_table[i].index = index | (fid << HW_FID_INDEX_SHIFT) | (did << HW_DID_INDEX_SHIFT);
+
+               powernow_table[i].frequency = find_khz_freq_from_fiddid(fid, did);
+
+               if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
+                       printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n",
+                               powernow_table[i].frequency,
+                               (unsigned int) (data->acpi_data.states[i].core_frequency * 1000));
+                       powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+                       continue;
+               }
+       }
+       return 0;
+}
+
+static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
+{
+       int i;
+       int cntlofreq = 0;
        for (i = 0; i < data->acpi_data.state_count; i++) {
                u32 fid;
                u32 vid;
@@ -786,7 +920,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
                                if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
                                    (powernow_table[i].index != powernow_table[cntlofreq].index)) {
                                        printk(KERN_ERR PFX "Too many lo freq table entries\n");
-                                       goto err_out_mem;
+                                       return 1;
                                }
 
                                dprintk("double low frequency table entry, ignoring it.\n");
@@ -804,31 +938,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
                        continue;
                }
        }
-
-       powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END;
-       powernow_table[data->acpi_data.state_count].index = 0;
-       data->powernow_table = powernow_table;
-
-       /* fill in data */
-       data->numps = data->acpi_data.state_count;
-       print_basics(data);
-       powernow_k8_acpi_pst_values(data, 0);
-
-       /* notify BIOS that we exist */
-       acpi_processor_notify_smm(THIS_MODULE);
-
        return 0;
-
-err_out_mem:
-       kfree(powernow_table);
-
-err_out:
-       acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
-
-       /* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
-       data->acpi_data.state_count = 0;
-
-       return -ENODEV;
 }
 
 static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data)
@@ -844,20 +954,20 @@ static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned
 #endif /* CONFIG_X86_POWERNOW_K8_ACPI */
 
 /* Take a frequency, and issue the fid/vid transition command */
-static int transition_frequency(struct powernow_k8_data *data, unsigned int index)
+static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned int index)
 {
-       u32 fid;
-       u32 vid;
+       u32 fid = 0;
+       u32 vid = 0;
        int res, i;
        struct cpufreq_freqs freqs;
 
        dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
 
+       /* fid/vid correctness check for k8 */
        /* fid are the lower 8 bits of the index we stored into
-        * the cpufreq frequency table in find_psb_table, vid are
-        * the upper 8 bits.
+        * the cpufreq frequency table in find_psb_table, vid
+        * are the upper 8 bits.
         */
-
        fid = data->powernow_table[index].index & 0xFF;
        vid = (data->powernow_table[index].index & 0xFF00) >> 8;
 
@@ -881,22 +991,58 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
 
        dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n",
                smp_processor_id(), fid, vid);
-
-       freqs.cpu = data->cpu;
        freqs.old = find_khz_freq_from_fid(data->currfid);
        freqs.new = find_khz_freq_from_fid(fid);
-       for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
+
+       for_each_cpu_mask(i, *(data->available_cores)) {
                freqs.cpu = i;
                cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
        }
 
        res = transition_fid_vid(data, fid, vid);
-
        freqs.new = find_khz_freq_from_fid(data->currfid);
-       for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
+
+       for_each_cpu_mask(i, *(data->available_cores)) {
                freqs.cpu = i;
                cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-        }
+       }
+       return res;
+}
+
+/* Take a frequency, and issue the hardware pstate transition command */
+static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned int index)
+{
+       u32 fid = 0;
+       u32 did = 0;
+       u32 pstate = 0;
+       int res, i;
+       struct cpufreq_freqs freqs;
+
+       dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
+
+       /* get fid did for hardware pstate transition */
+       pstate = index & HW_PSTATE_MASK;
+       if (pstate > MAX_HW_PSTATE)
+               return 0;
+       fid = (index & HW_FID_INDEX_MASK) >> HW_FID_INDEX_SHIFT;
+       did = (index & HW_DID_INDEX_MASK) >> HW_DID_INDEX_SHIFT;
+       freqs.old = find_khz_freq_from_fiddid(data->currfid, data->currdid);
+       freqs.new = find_khz_freq_from_fiddid(fid, did);
+
+       for_each_cpu_mask(i, *(data->available_cores)) {
+               freqs.cpu = i;
+               cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       }
+
+       res = transition_pstate(data, pstate);
+       data->currfid = find_fid_from_pstate(pstate);
+       data->currdid = find_did_from_pstate(pstate);
+       freqs.new = find_khz_freq_from_fiddid(data->currfid, data->currdid);
+
+       for_each_cpu_mask(i, *(data->available_cores)) {
+               freqs.cpu = i;
+               cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+       }
        return res;
 }
 
@@ -933,18 +1079,21 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
        dprintk("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
                pol->cpu, targfreq, pol->min, pol->max, relation);
 
-       if (query_current_values_with_pending_wait(data)) {
-               ret = -EIO;
+       if (query_current_values_with_pending_wait(data))
                goto err_out;
-       }
 
-       dprintk("targ: curr fid 0x%x, vid 0x%x\n",
+       if (cpu_family)
+               dprintk("targ: curr fid 0x%x, did 0x%x\n",
+                       data->currfid, data->currvid);
+       else {
+               dprintk("targ: curr fid 0x%x, vid 0x%x\n",
                data->currfid, data->currvid);
 
-       if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
-               printk(KERN_INFO PFX
-                       "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
-                       checkfid, data->currfid, checkvid, data->currvid);
+               if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
+                       printk(KERN_INFO PFX
+                               "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
+                               checkfid, data->currfid, checkvid, data->currvid);
+               }
        }
 
        if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
@@ -954,7 +1103,11 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
 
        powernow_k8_acpi_pst_values(data, newstate);
 
-       if (transition_frequency(data, newstate)) {
+       if (cpu_family)
+               ret = transition_frequency_pstate(data, newstate);
+       else
+               ret = transition_frequency_fidvid(data, newstate);
+       if (ret) {
                printk(KERN_ERR PFX "transition frequency failed\n");
                ret = 1;
                mutex_unlock(&fidvid_mutex);
@@ -962,7 +1115,10 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
        }
        mutex_unlock(&fidvid_mutex);
 
-       pol->cur = find_khz_freq_from_fid(data->currfid);
+       if (cpu_family)
+               pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid);
+       else
+               pol->cur = find_khz_freq_from_fid(data->currfid);
        ret = 0;
 
 err_out:
@@ -1007,14 +1163,13 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
                 * Use the PSB BIOS structure. This is only availabe on
                 * an UP version, and is deprecated by AMD.
                 */
-
                if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
                        printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n");
                        kfree(data);
                        return -ENODEV;
                }
                if (pol->cpu != 0) {
-                       printk(KERN_ERR PFX "init not cpu 0\n");
+                       printk(KERN_ERR PFX "No _PSS objects for CPU other than CPU0\n");
                        kfree(data);
                        return -ENODEV;
                }
@@ -1042,20 +1197,28 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
        if (query_current_values_with_pending_wait(data))
                goto err_out;
 
-       fidvid_msr_init();
+       if (!cpu_family)
+               fidvid_msr_init();
 
        /* run on any CPU again */
        set_cpus_allowed(current, oldmask);
 
        pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
-       pol->cpus = cpu_core_map[pol->cpu];
+       if (cpu_family)
+               pol->cpus = cpumask_of_cpu(pol->cpu);
+       else
+               pol->cpus = cpu_core_map[pol->cpu];
+       data->available_cores = &(pol->cpus);
 
        /* Take a crude guess here.
         * That guess was in microseconds, so multiply with 1000 */
        pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US)
            + (3 * (1 << data->irt) * 10)) * 1000;
 
-       pol->cur = find_khz_freq_from_fid(data->currfid);
+       if (cpu_family)
+               pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid);
+       else
+               pol->cur = find_khz_freq_from_fid(data->currfid);
        dprintk("policy current frequency %d kHz\n", pol->cur);
 
        /* min/max the cpu is capable of */
@@ -1069,8 +1232,12 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 
        cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
 
-       printk("cpu_init done, current fid 0x%x, vid 0x%x\n",
-              data->currfid, data->currvid);
+       if (cpu_family)
+               dprintk("cpu_init done, current fid 0x%x, did 0x%x\n",
+                       data->currfid, data->currdid);
+       else
+               dprintk("cpu_init done, current fid 0x%x, vid 0x%x\n",
+                       data->currfid, data->currvid);
 
        powernow_data[pol->cpu] = data;
 
@@ -1156,8 +1323,9 @@ static int __cpuinit powernowk8_init(void)
        }
 
        if (supported_cpus == num_online_cpus()) {
-               printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron "
-                       "processors (" VERSION ")\n", supported_cpus);
+               printk(KERN_INFO PFX "Found %d %s "
+                       "processors (" VERSION ")\n", supported_cpus,
+                       boot_cpu_data.x86_model_id);
                return cpufreq_register_driver(&cpufreq_amd64_driver);
        }
 
index 79a7c5c87edcfe602dad0382d767824b88473db2..bf8ad9e43da3e4a006f5720c30c900bfa5e97a5c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  (c) 2003, 2004, 2005 Advanced Micro Devices, Inc.
+ *  (c) 2003-2006 Advanced Micro Devices, Inc.
  *  Your use of this code is subject to the terms and conditions of the
  *  GNU general public license version 2. See "COPYING" or
  *  http://www.gnu.org/licenses/gpl.html
@@ -21,8 +21,8 @@ struct powernow_k8_data {
        u32 plllock; /* pll lock time, units 1 us */
         u32 exttype; /* extended interface = 1 */
 
-       /* keep track of the current fid / vid */
-       u32 currvid, currfid;
+       /* keep track of the current fid / vid or did */
+       u32 currvid, currfid, currdid;
 
        /* the powernow_table includes all frequency and vid/fid pairings:
         * fid are the lower 8 bits of the index, vid are the upper 8 bits.
@@ -34,6 +34,10 @@ struct powernow_k8_data {
         * used to determine valid frequency/vid/fid states */
        struct acpi_processor_performance acpi_data;
 #endif
+       /* we need to keep track of associated cores, but let cpufreq
+        * handle hotplug events - so just point at cpufreq pol->cpus
+        * structure */
+       cpumask_t *available_cores;
 };
 
 
@@ -43,6 +47,7 @@ struct powernow_k8_data {
 #define CPUID_XFAM_K8                  0
 #define CPUID_XMOD                     0x000f0000      /* extended model */
 #define CPUID_XMOD_REV_G               0x00060000
+#define CPUID_XFAM_10H                         0x00100000      /* family 0x10 */
 #define CPUID_USE_XFAM_XMOD            0x00000f00
 #define CPUID_GET_MAX_CAPABILITIES     0x80000000
 #define CPUID_FREQ_VOLT_CAPABILITIES   0x80000007
@@ -79,6 +84,32 @@ struct powernow_k8_data {
 #define MSR_S_HI_CURRENT_VID      0x0000003f
 #define MSR_C_HI_STP_GNT_BENIGN          0x00000001
 
+
+/* Hardware Pstate _PSS and MSR definitions */
+#define USE_HW_PSTATE          0x00000080
+#define HW_PSTATE_FID_MASK     0x0000003f
+#define HW_PSTATE_DID_MASK     0x000001c0
+#define HW_PSTATE_DID_SHIFT    6
+#define HW_PSTATE_MASK                 0x00000007
+#define HW_PSTATE_VALID_MASK   0x80000000
+#define HW_FID_INDEX_SHIFT     8
+#define HW_FID_INDEX_MASK      0x0000ff00
+#define HW_DID_INDEX_SHIFT     16
+#define HW_DID_INDEX_MASK      0x00ff0000
+#define HW_WATTS_MASK          0xff
+#define HW_PWR_DVR_MASK                0x300
+#define HW_PWR_DVR_SHIFT       8
+#define HW_PWR_MAX_MULT                3
+#define MAX_HW_PSTATE          8       /* hw pstate supports up to 8 */
+#define MSR_PSTATE_DEF_BASE    0xc0010064 /* base of Pstate MSRs */
+#define MSR_PSTATE_STATUS      0xc0010063 /* Pstate Status MSR */
+#define MSR_PSTATE_CTRL        0xc0010062 /* Pstate control MSR */
+
+/* define the two driver architectures */
+#define CPU_OPTERON 0
+#define CPU_HW_PSTATE 1
+
+
 /*
  * There are restrictions frequencies have to follow:
  * - only 1 entry in the low fid table ( <=1.4GHz )
@@ -182,6 +213,9 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
 
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
 
+static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
+static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
+
 #ifdef CONFIG_SMP
 static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
 {
index b0ff9075708c4142d3f70eab9300547ca22f0666..ce54ff12c15d1b9c0c7df76065704ebfa5fa1232 100644 (file)
@@ -250,7 +250,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
 
        if (model->cpu_id == NULL) {
                /* No match at all */
-               dprintk(KERN_INFO PFX "no support for CPU model \"%s\": "
+               dprintk("no support for CPU model \"%s\": "
                       "send /proc/cpuinfo to " MAINTAINER "\n",
                       cpu->x86_model_id);
                return -ENOENT;
@@ -258,10 +258,10 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
 
        if (model->op_points == NULL) {
                /* Matched a non-match */
-               dprintk(KERN_INFO PFX "no table support for CPU model \"%s\"\n",
+               dprintk("no table support for CPU model \"%s\"\n",
                       cpu->x86_model_id);
 #ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-               dprintk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
+               dprintk("try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
 #endif
                return -ENOENT;
        }
@@ -368,7 +368,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
 
        /* register with ACPI core */
        if (acpi_processor_register_performance(&p, cpu)) {
-               dprintk(KERN_INFO PFX "obtaining ACPI data failed\n");
+               dprintk("obtaining ACPI data failed\n");
                return -EIO;
        }
 
@@ -465,7 +465,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
        kfree(centrino_model[cpu]);
  err_unreg:
        acpi_processor_unregister_performance(&p, cpu);
-       dprintk(KERN_INFO PFX "invalid ACPI data\n");
+       dprintk("invalid ACPI data\n");
        return (result);
 }
 #else
@@ -499,7 +499,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
                        centrino_cpu[policy->cpu] = &cpu_ids[i];
 
                if (!centrino_cpu[policy->cpu]) {
-                       dprintk(KERN_INFO PFX "found unsupported CPU with "
+                       dprintk("found unsupported CPU with "
                        "Enhanced SpeedStep: send /proc/cpuinfo to "
                        MAINTAINER "\n");
                        return -ENODEV;
index 846e1639ef7ce4bb928673b1705a1590345db247..dd6b0e3386ce8f3af2c65d74853d0b001ae07440 100644 (file)
@@ -1547,15 +1547,18 @@ void __init setup_arch(char **cmdline_p)
        if (efi_enabled)
                efi_map_memmap();
 
-#ifdef CONFIG_X86_IO_APIC
-       check_acpi_pci();       /* Checks more than just ACPI actually */
-#endif
-
 #ifdef CONFIG_ACPI
        /*
         * Parse the ACPI tables for possible boot-time SMP configuration.
         */
        acpi_boot_table_init();
+#endif
+
+#ifdef CONFIG_X86_IO_APIC
+       check_acpi_pci();       /* Checks more than just ACPI actually */
+#endif
+
+#ifdef CONFIG_ACPI
        acpi_boot_init();
 
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)
index f48bef15b4f0dd5de72d4bbcc39f8c4f881947b6..af56987f69b02503c82cdc2a48660f56db02153a 100644 (file)
@@ -315,3 +315,4 @@ ENTRY(sys_call_table)
        .long sys_splice
        .long sys_sync_file_range
        .long sys_tee                   /* 315 */
+       .long sys_vmsplice
index cea5b3ce4b5766c9747294090542e4eb063b75eb..d55fa7b187ab656f9c581b11c5dfc12f7186f82e 100644 (file)
@@ -93,9 +93,11 @@ int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid
        int i;
        for (i = 0; apic_probe[i]; ++i) { 
                if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) { 
-                       genapic = apic_probe[i];
-                       printk(KERN_INFO "Switched to APIC driver `%s'.\n", 
-                              genapic->name);
+                       if (!cmdline_apic) {
+                               genapic = apic_probe[i];
+                               printk(KERN_INFO "Switched to APIC driver `%s'.\n",
+                                      genapic->name);
+                       }
                        return 1;
                } 
        } 
@@ -107,9 +109,11 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
        int i;
        for (i = 0; apic_probe[i]; ++i) { 
                if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { 
-                       genapic = apic_probe[i];
-                       printk(KERN_INFO "Switched to APIC driver `%s'.\n", 
-                              genapic->name);
+                       if (!cmdline_apic) {
+                               genapic = apic_probe[i];
+                               printk(KERN_INFO "Switched to APIC driver `%s'.\n",
+                                      genapic->name);
+                       }
                        return 1;
                } 
        } 
index ee5fbb02b28f4f56caa06531d424b8136b0e6748..35e038a974c6227940cc4ebe7c5ead85d52e4a65 100644 (file)
@@ -13,7 +13,7 @@ choice
        default SGI_IP22
 
 config MIPS_MTX1
-       bool "Support for 4G Systems MTX-1 board"
+       bool "4G Systems MTX-1 board"
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select SOC_AU1500
@@ -119,8 +119,34 @@ config MIPS_MIRAGE
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
+config BASLER_EXCITE
+       bool "Basler eXcite smart camera support"
+       select DMA_COHERENT
+       select HW_HAS_PCI
+       select IRQ_CPU
+       select IRQ_CPU_RM7K
+       select IRQ_CPU_RM9K
+       select SERIAL_RM9000
+       select SYS_HAS_CPU_RM9000
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
+       help
+         The eXcite is a smart camera platform manufactured by
+         Basler Vision Technologies AG
+
+config BASLER_EXCITE_PROTOTYPE
+       bool "Support for pre-release units"
+       depends on BASLER_EXCITE
+       default n
+       help
+         Pre-series (prototype) units are different from later ones in
+         some ways. Select this option if you have one of these. Please
+         note that a kernel built with this option selected will not be
+         able to run on normal units.
+
 config MIPS_COBALT
-       bool "Support for Cobalt Server"
+       bool "Cobalt Server"
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select I8259
@@ -132,7 +158,7 @@ config MIPS_COBALT
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config MACH_DECSTATION
-       bool "Support for DECstations"
+       bool "DECstations"
        select BOOT_ELF32
        select DMA_NONCOHERENT
        select EARLY_PRINTK
@@ -142,6 +168,9 @@ config MACH_DECSTATION
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
        select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_SUPPORTS_128HZ
+       select SYS_SUPPORTS_256HZ
+       select SYS_SUPPORTS_1024HZ
        help
          This enables support for DEC's MIPS based workstations.  For details
          see the Linux/MIPS FAQ on <http://www.linux-mips.org/> and the
@@ -158,7 +187,7 @@ config MACH_DECSTATION
          otherwise choose R3000.
 
 config MIPS_EV64120
-       bool "Support for Galileo EV64120 Evaluation board (EXPERIMENTAL)"
+       bool "Galileo EV64120 Evaluation board (EXPERIMENTAL)"
        depends on EXPERIMENTAL
        select DMA_NONCOHERENT
        select HW_HAS_PCI
@@ -175,7 +204,7 @@ config MIPS_EV64120
          kernel for this platform.
 
 config MIPS_EV96100
-       bool "Support for Galileo EV96100 Evaluation board (EXPERIMENTAL)"
+       bool "Galileo EV96100 Evaluation board (EXPERIMENTAL)"
        depends on EXPERIMENTAL
        select DMA_NONCOHERENT
        select HW_HAS_PCI
@@ -195,7 +224,7 @@ config MIPS_EV96100
          here if you wish to build a kernel for this platform.
 
 config MIPS_IVR
-       bool "Support for Globespan IVR board"
+       bool "Globespan IVR board"
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select ITE_BOARD_GEN
@@ -211,7 +240,7 @@ config MIPS_IVR
          build a kernel for this platform.
 
 config MIPS_ITE8172
-       bool "Support for ITE 8172G board"
+       bool "ITE 8172G board"
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select ITE_BOARD_GEN
@@ -228,7 +257,7 @@ config MIPS_ITE8172
          a kernel for this platform.
 
 config MACH_JAZZ
-       bool "Support for the Jazz family of machines"
+       bool "Jazz family of machines"
        select ARC
        select ARC32
        select ARCH_MAY_HAVE_PC_FDC
@@ -239,6 +268,7 @@ config MACH_JAZZ
        select SYS_HAS_CPU_R4X00
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+       select SYS_SUPPORTS_100HZ
        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.
@@ -246,7 +276,7 @@ config MACH_JAZZ
         Olivetti M700-10 workstations.
 
 config LASAT
-       bool "Support for LASAT Networks platforms"
+       bool "LASAT Networks platforms"
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select MIPS_GT64120
@@ -258,7 +288,7 @@ config LASAT
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config MIPS_ATLAS
-       bool "Support for MIPS Atlas board"
+       bool "MIPS Atlas board"
        select BOOT_ELF32
        select DMA_NONCOHERENT
        select IRQ_CPU
@@ -283,7 +313,7 @@ config MIPS_ATLAS
          board.
 
 config MIPS_MALTA
-       bool "Support for MIPS Malta board"
+       bool "MIPS Malta board"
        select ARCH_MAY_HAVE_PC_FDC
        select BOOT_ELF32
        select HAVE_STD_PC_SERIAL_PORT
@@ -311,7 +341,7 @@ config MIPS_MALTA
          board.
 
 config MIPS_SEAD
-       bool "Support for MIPS SEAD board (EXPERIMENTAL)"
+       bool "MIPS SEAD board (EXPERIMENTAL)"
        depends on EXPERIMENTAL
        select IRQ_CPU
        select DMA_NONCOHERENT
@@ -327,8 +357,29 @@ config MIPS_SEAD
          This enables support for the MIPS Technologies SEAD evaluation
          board.
 
+config WR_PPMC
+       bool "Support for Wind River PPMC board"
+       select IRQ_CPU
+       select BOOT_ELF32
+       select DMA_NONCOHERENT
+       select HW_HAS_PCI
+       select MIPS_GT64120
+       select SWAP_IO_SPACE
+       select SYS_HAS_CPU_MIPS32_R1
+       select SYS_HAS_CPU_MIPS32_R2
+       select SYS_HAS_CPU_MIPS64_R1
+       select SYS_HAS_CPU_NEVADA
+       select SYS_HAS_CPU_RM7000
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       help
+         This enables support for the Wind River MIPS32 4KC PPMC evaluation
+         board, which is based on GT64120 bridge chip.
+
 config MIPS_SIM
-       bool 'Support for MIPS simulator (MIPSsim)'
+       bool 'MIPS simulator (MIPSsim)'
        select DMA_NONCOHERENT
        select IRQ_CPU
        select SYS_HAS_CPU_MIPS32_R1
@@ -341,7 +392,7 @@ config MIPS_SIM
          emulator.
 
 config MOMENCO_JAGUAR_ATX
-       bool "Support for Momentum Jaguar board"
+       bool "Momentum Jaguar board"
        select BOOT_ELF32
        select DMA_NONCOHERENT
        select HW_HAS_PCI
@@ -361,7 +412,7 @@ config MOMENCO_JAGUAR_ATX
          Momentum Computer <http://www.momenco.com/>.
 
 config MOMENCO_OCELOT
-       bool "Support for Momentum Ocelot board"
+       bool "Momentum Ocelot board"
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select IRQ_CPU
@@ -378,7 +429,7 @@ config MOMENCO_OCELOT
          Momentum Computer <http://www.momenco.com/>.
 
 config MOMENCO_OCELOT_3
-       bool "Support for Momentum Ocelot-3 board"
+       bool "Momentum Ocelot-3 board"
        select BOOT_ELF32
        select DMA_NONCOHERENT
        select HW_HAS_PCI
@@ -397,7 +448,7 @@ config MOMENCO_OCELOT_3
          PMC-Sierra Rm79000 core.
 
 config MOMENCO_OCELOT_C
-       bool "Support for Momentum Ocelot-C board"
+       bool "Momentum Ocelot-C board"
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select IRQ_CPU
@@ -414,7 +465,7 @@ config MOMENCO_OCELOT_C
          Momentum Computer <http://www.momenco.com/>.
 
 config MOMENCO_OCELOT_G
-       bool "Support for Momentum Ocelot-G board"
+       bool "Momentum Ocelot-G board"
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select IRQ_CPU
@@ -431,62 +482,25 @@ config MOMENCO_OCELOT_G
          Momentum Computer <http://www.momenco.com/>.
 
 config MIPS_XXS1500
-       bool "Support for MyCable XXS1500 board"
+       bool "MyCable XXS1500 board"
        select DMA_NONCOHERENT
        select SOC_AU1500
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config PNX8550_V2PCI
-       bool "Support for Philips PNX8550 based Viper2-PCI board"
+       bool "Philips PNX8550 based Viper2-PCI board"
+       depends on BROKEN
        select PNX8550
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config PNX8550_JBS
-       bool "Support for Philips PNX8550 based JBS board"
+       bool "Philips PNX8550 based JBS board"
+       depends on BROKEN
        select PNX8550
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
-config DDB5074
-       bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-       select DDB5XXX_COMMON
-       select DMA_NONCOHERENT
-       select HAVE_STD_PC_SERIAL_PORT
-       select HW_HAS_PCI
-       select IRQ_CPU
-       select I8259
-       select ISA
-       select SYS_HAS_CPU_R5000
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-       select SYS_SUPPORTS_LITTLE_ENDIAN
-       help
-         This enables support for the VR5000-based NEC DDB Vrc-5074
-         evaluation board.
-
-config DDB5476
-       bool "Support for NEC DDB Vrc-5476"
-       select DDB5XXX_COMMON
-       select DMA_NONCOHERENT
-       select HAVE_STD_PC_SERIAL_PORT
-       select HW_HAS_PCI
-       select IRQ_CPU
-       select I8259
-       select ISA
-       select SYS_HAS_CPU_R5432
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-       select SYS_SUPPORTS_LITTLE_ENDIAN
-       help
-         This enables support for the R5432-based NEC DDB Vrc-5476
-         evaluation board.
-
-         Features : kernel debugging, serial terminal, NFS root fs, on-board
-         ether port USB, AC97, PCI, PCI VGA card & framebuffer console,
-         IDE controller, PS2 keyboard, PS2 mouse, etc.
-
 config DDB5477
-       bool "Support for NEC DDB Vrc-5477"
+       bool "NEC DDB Vrc-5477"
        select DDB5XXX_COMMON
        select DMA_NONCOHERENT
        select HW_HAS_PCI
@@ -504,13 +518,13 @@ config DDB5477
          ether port USB, AC97, PCI, etc.
 
 config MACH_VR41XX
-       bool "Support for NEC VR4100 series based machines"
+       bool "NEC VR41XX-based machines"
        select SYS_HAS_CPU_VR41XX
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
 
 config PMC_YOSEMITE
-       bool "Support for PMC-Sierra Yosemite eval board"
+       bool "PMC-Sierra Yosemite eval board"
        select DMA_COHERENT
        select HW_HAS_PCI
        select IRQ_CPU
@@ -527,7 +541,7 @@ config PMC_YOSEMITE
          manufactured by PMC-Sierra.
 
 config QEMU
-       bool "Support for Qemu"
+       bool "Qemu"
        select DMA_COHERENT
        select GENERIC_ISA_DMA
        select HAVE_STD_PC_SERIAL_PORT
@@ -546,8 +560,22 @@ config QEMU
          simulate actual MIPS hardware platforms.  More information on Qemu
          can be found at http://www.linux-mips.org/wiki/Qemu.
 
+config MARKEINS
+       bool "Support for NEC EMMA2RH Mark-eins"
+       select DMA_NONCOHERENT
+       select HW_HAS_PCI
+       select IRQ_CPU
+       select SWAP_IO_SPACE
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_HAS_CPU_R5000
+       help
+         This enables support for the R5432-based NEC Mark-eins
+         boards with R5500 CPU.
+
 config SGI_IP22
-       bool "Support for SGI IP22 (Indy/Indigo2)"
+       bool "SGI IP22 (Indy/Indigo2)"
        select ARC
        select ARC32
        select BOOT_ELF32
@@ -555,6 +583,7 @@ config SGI_IP22
        select HW_HAS_EISA
        select IP22_CPU_SCACHE
        select IRQ_CPU
+       select NO_ISA if ISA
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_R4X00
        select SYS_HAS_CPU_R5000
@@ -567,7 +596,7 @@ config SGI_IP22
          that runs on these, say Y here.
 
 config SGI_IP27
-       bool "Support for SGI IP27 (Origin200/2000)"
+       bool "SGI IP27 (Origin200/2000)"
        select ARC
        select ARC64
        select BOOT_ELF64
@@ -577,13 +606,14 @@ config SGI_IP27
        select SYS_HAS_CPU_R10000
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_NUMA
        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
          here.
 
 config SGI_IP32
-       bool "Support for SGI IP32 (O2) (EXPERIMENTAL)"
+       bool "SGI IP32 (O2) (EXPERIMENTAL)"
        depends on EXPERIMENTAL
        select ARC
        select ARC32
@@ -604,7 +634,7 @@ config SGI_IP32
          If you want this kernel to run on SGI O2 workstation, say Y here.
 
 config SIBYTE_BIGSUR
-       bool "Support for Sibyte BCM91480B-BigSur"
+       bool "Sibyte BCM91480B-BigSur"
        select BOOT_ELF32
        select DMA_COHERENT
        select PCI_DOMAINS
@@ -615,7 +645,7 @@ config SIBYTE_BIGSUR
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config SIBYTE_SWARM
-       bool "Support for Sibyte BCM91250A-SWARM"
+       bool "Sibyte BCM91250A-SWARM"
        select BOOT_ELF32
        select DMA_COHERENT
        select SIBYTE_SB1250
@@ -626,7 +656,7 @@ config SIBYTE_SWARM
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config SIBYTE_SENTOSA
-       bool "Support for Sibyte BCM91250E-Sentosa"
+       bool "Sibyte BCM91250E-Sentosa"
        depends on EXPERIMENTAL
        select BOOT_ELF32
        select DMA_COHERENT
@@ -637,7 +667,7 @@ config SIBYTE_SENTOSA
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config SIBYTE_RHONE
-       bool "Support for Sibyte BCM91125E-Rhone"
+       bool "Sibyte BCM91125E-Rhone"
        depends on EXPERIMENTAL
        select BOOT_ELF32
        select DMA_COHERENT
@@ -648,7 +678,7 @@ config SIBYTE_RHONE
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config SIBYTE_CARMEL
-       bool "Support for Sibyte BCM91120x-Carmel"
+       bool "Sibyte BCM91120x-Carmel"
        depends on EXPERIMENTAL
        select BOOT_ELF32
        select DMA_COHERENT
@@ -659,7 +689,7 @@ config SIBYTE_CARMEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config SIBYTE_PTSWARM
-       bool "Support for Sibyte BCM91250PT-PTSWARM"
+       bool "Sibyte BCM91250PT-PTSWARM"
        depends on EXPERIMENTAL
        select BOOT_ELF32
        select DMA_COHERENT
@@ -671,7 +701,7 @@ config SIBYTE_PTSWARM
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config SIBYTE_LITTLESUR
-       bool "Support for Sibyte BCM91250C2-LittleSur"
+       bool "Sibyte BCM91250C2-LittleSur"
        depends on EXPERIMENTAL
        select BOOT_ELF32
        select DMA_COHERENT
@@ -683,7 +713,7 @@ config SIBYTE_LITTLESUR
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config SIBYTE_CRHINE
-       bool "Support for Sibyte BCM91120C-CRhine"
+       bool "Sibyte BCM91120C-CRhine"
        depends on EXPERIMENTAL
        select BOOT_ELF32
        select DMA_COHERENT
@@ -694,7 +724,7 @@ config SIBYTE_CRHINE
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config SIBYTE_CRHONE
-       bool "Support for Sibyte BCM91125C-CRhone"
+       bool "Sibyte BCM91125C-CRhone"
        depends on EXPERIMENTAL
        select BOOT_ELF32
        select DMA_COHERENT
@@ -706,9 +736,9 @@ config SIBYTE_CRHONE
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config SNI_RM200_PCI
-       bool "Support for SNI RM200 PCI"
-       select ARC
-       select ARC32
+       bool "SNI RM200 PCI"
+       select ARC if CPU_LITTLE_ENDIAN
+       select ARC32 if CPU_LITTLE_ENDIAN
        select ARCH_MAY_HAVE_PC_FDC
        select BOOT_ELF32
        select DMA_NONCOHERENT
@@ -719,10 +749,13 @@ config SNI_RM200_PCI
        select I8253
        select I8259
        select ISA
+       select SWAP_IO_SPACE if CPU_BIG_ENDIAN
        select SYS_HAS_CPU_R4X00
+       select SYS_HAS_CPU_R5000
+       select R5000_CPU_SCACHE
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-       select SYS_SUPPORTS_BIG_ENDIAN if EXPERIMENTAL
+       select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_HIGHMEM
        select SYS_SUPPORTS_LITTLE_ENDIAN
        help
@@ -732,7 +765,7 @@ config SNI_RM200_PCI
          support this machine type.
 
 config TOSHIBA_JMR3927
-       bool "Support for Toshiba JMR-TX3927 board"
+       bool "Toshiba JMR-TX3927 board"
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select MIPS_TX3927
@@ -743,7 +776,7 @@ config TOSHIBA_JMR3927
        select TOSHIBA_BOARDS
 
 config TOSHIBA_RBTX4927
-       bool "Support for Toshiba TBTX49[23]7 board"
+       bool "Toshiba TBTX49[23]7 board"
        select DMA_NONCOHERENT
        select HAS_TXX9_SERIAL
        select HW_HAS_PCI
@@ -760,7 +793,7 @@ config TOSHIBA_RBTX4927
          support this machine type
 
 config TOSHIBA_RBTX4938
-       bool "Support for Toshiba RBTX4938 board"
+       bool "Toshiba RBTX4938 board"
        select HAVE_STD_PC_SERIAL_PORT
        select DMA_NONCOHERENT
        select GENERIC_ISA_DMA
@@ -979,6 +1012,11 @@ config SOC_PNX8550
 config SWAP_IO_SPACE
        bool
 
+config EMMA2RH
+       bool
+       depends on MARKEINS
+       default y
+
 #
 # Unfortunately not all GT64120 systems run the chip at the same clock.
 # As the user for the clock rate and try to minimize the available options.
@@ -1411,13 +1449,12 @@ config PAGE_SIZE_8KB
 
 config PAGE_SIZE_16KB
        bool "16kB"
-       depends on EXPERIMENTAL && !CPU_R3000 && !CPU_TX39XX
+       depends on !CPU_R3000 && !CPU_TX39XX
        help
          Using 16kB page size will result in higher performance kernel at
          the price of higher memory consumption.  This option is available on
-         all non-R3000 family processor.  Not that at the time of this
-         writing this option is still high experimental; there are also
-         issues with compatibility of user applications.
+         all non-R3000 family processors.  Note that you will need a suitable
+         Linux distribution to support this.
 
 config PAGE_SIZE_64KB
        bool "64kB"
@@ -1426,8 +1463,7 @@ config PAGE_SIZE_64KB
          Using 64kB page size will result in higher performance kernel at
          the price of higher memory consumption.  This option is available on
          all non-R3000 family processor.  Not that at the time of this
-         writing this option is still high experimental; there are also
-         issues with compatibility of user applications.
+         writing this option is still high experimental.
 
 endchoice
 
@@ -1609,6 +1645,28 @@ config ARCH_FLATMEM_ENABLE
        def_bool y
        depends on !NUMA
 
+config ARCH_DISCONTIGMEM_ENABLE
+       bool
+       default y if SGI_IP27
+       help
+         Say Y to upport efficient handling of discontiguous physical memory,
+         for architectures which are either NUMA (Non-Uniform Memory Access)
+         or have huge holes in the physical address space for other reasons.
+         See <file:Documentation/vm/numa> for more.
+
+config NUMA
+       bool "NUMA Support"
+       depends on SYS_SUPPORTS_NUMA
+       help
+         Say Y to compile the kernel to support NUMA (Non-Uniform Memory
+         Access).  This option improves performance on systems with more
+         than two nodes; on two node systems it is generally better to
+         leave it disabled; on single node systems disable this option
+         disabled.
+
+config SYS_SUPPORTS_NUMA
+       bool
+
 config NODES_SHIFT
        int
        default "6"
@@ -1653,6 +1711,77 @@ config NR_CPUS
          This is purely to save memory - each supported CPU adds
          approximately eight kilobytes to the kernel image.
 
+#
+# Timer Interrupt Frequency Configuration
+#
+
+choice
+       prompt "Timer frequency"
+       default HZ_250
+       help
+        Allows the configuration of the timer frequency.
+
+       config HZ_48
+               bool "48 HZ" if SYS_SUPPORTS_48HZ
+
+       config HZ_100
+               bool "100 HZ" if SYS_SUPPORTS_100HZ || SYS_SUPPORTS_ARBIT_HZ
+
+       config HZ_128
+               bool "128 HZ" if SYS_SUPPORTS_128HZ || SYS_SUPPORTS_ARBIT_HZ
+
+       config HZ_250
+               bool "250 HZ" if SYS_SUPPORTS_250HZ || SYS_SUPPORTS_ARBIT_HZ
+
+       config HZ_256
+               bool "256 HZ" if SYS_SUPPORTS_256HZ || SYS_SUPPORTS_ARBIT_HZ
+
+       config HZ_1000
+               bool "1000 HZ" if SYS_SUPPORTS_1000HZ || SYS_SUPPORTS_ARBIT_HZ
+
+       config HZ_1024
+               bool "1024 HZ" if SYS_SUPPORTS_1024HZ || SYS_SUPPORTS_ARBIT_HZ
+
+endchoice
+
+config SYS_SUPPORTS_48HZ
+       bool
+
+config SYS_SUPPORTS_100HZ
+       bool
+
+config SYS_SUPPORTS_128HZ
+       bool
+
+config SYS_SUPPORTS_250HZ
+       bool
+
+config SYS_SUPPORTS_256HZ
+       bool
+
+config SYS_SUPPORTS_1000HZ
+       bool
+
+config SYS_SUPPORTS_1024HZ
+       bool
+
+config SYS_SUPPORTS_ARBIT_HZ
+       bool
+       default y if !SYS_SUPPORTS_48HZ && !SYS_SUPPORTS_100HZ && \
+                    !SYS_SUPPORTS_128HZ && !SYS_SUPPORTS_250HZ && \
+                    !SYS_SUPPORTS_256HZ && !SYS_SUPPORTS_1000HZ && \
+                    !SYS_SUPPORTS_1024HZ
+
+config HZ
+       int
+       default 48 if HZ_48
+       default 100 if HZ_100
+       default 128 if HZ_128
+       default 250 if HZ_250
+       default 256 if HZ_256
+       default 1000 if HZ_1000
+       default 1024 if HZ_1024
+
 source "kernel/Kconfig.preempt"
 
 config RTC_DS1742
@@ -1712,6 +1841,9 @@ source "drivers/pci/Kconfig"
 config ISA
        bool
 
+config NO_ISA
+       bool
+
 config EISA
        bool "EISA support"
        depends on HW_HAS_EISA
@@ -1842,6 +1974,32 @@ config PM
        bool "Power Management support (EXPERIMENTAL)"
        depends on EXPERIMENTAL && SOC_AU1X00
 
+config APM
+        tristate "Advanced Power Management Emulation"
+       depends on PM
+        ---help---
+         APM is a BIOS specification for saving power using several different
+         techniques. This is mostly useful for battery powered systems with
+         APM compliant BIOSes. If you say Y here, the system time will be
+         reset after a RESUME operation, the /proc/apm device will provide
+         battery status information, and user-space programs will receive
+         notification of APM "events" (e.g. battery status change).
+
+         In order to use APM, you will need supporting software. For location
+         and more information, read <file:Documentation/pm.txt> and the
+         Battery Powered Linux mini-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         This driver does not spin down disk drives (see the hdparm(8)
+         manpage ("man 8 hdparm") for that), and it doesn't turn off
+         VESA-compliant "green" monitors.
+
+         Generally, if you don't have a battery in your machine, there isn't
+         much point in using this driver and you should say N. If you get
+         random kernel OOPSes or reboots that don't seem to be related to
+         anything, try disabling/enabling this option (or disabling/enabling
+         APM in your BIOS).
+
 endmenu
 
 source "net/Kconfig"
index 133900aca992040a04481e9a2069b1c44f5461ec..d5930148495a8522368ac4ff5d3ab30c3c566ab3 100644 (file)
@@ -83,6 +83,8 @@ cflags-y                      += -msoft-float
 LDFLAGS_vmlinux                        += -G 0 -static -n -nostdlib
 MODFLAGS                       += -mlong-calls
 
+cflags-y += -ffreestanding
+
 #
 # We explicitly add the endianness specifier if needed, this allows
 # to compile kernels with a toolchain for the other endianness. We
@@ -284,6 +286,13 @@ core-$(CONFIG_MIPS_EV96100)        += arch/mips/galileo-boards/ev96100/
 cflags-$(CONFIG_MIPS_EV96100)  += -Iinclude/asm-mips/mach-ev96100
 load-$(CONFIG_MIPS_EV96100)    += 0xffffffff80100000
 
+#
+# Wind River PPMC Board (4KC + GT64120)
+#
+core-$(CONFIG_WR_PPMC)         += arch/mips/gt64120/wrppmc/
+cflags-$(CONFIG_WR_PPMC)               += -Iinclude/asm-mips/mach-wrppmc
+load-$(CONFIG_WR_PPMC)         += 0xffffffff80100000
+
 #
 # Globespan IVR eval board with QED 5231 CPU
 #
@@ -378,6 +387,13 @@ core-$(CONFIG_MOMENCO_OCELOT_3)    += arch/mips/momentum/ocelot_3/
 cflags-$(CONFIG_MOMENCO_OCELOT_3)      += -Iinclude/asm-mips/mach-ocelot3
 load-$(CONFIG_MOMENCO_OCELOT_3)        += 0xffffffff80100000
 
+#
+# Basler eXcite
+#
+core-$(CONFIG_BASLER_EXCITE)   += arch/mips/basler/excite/
+cflags-$(CONFIG_BASLER_EXCITE) += -Iinclude/asm-mips/mach-excite
+load-$(CONFIG_BASLER_EXCITE)   += 0x80100000
+
 #
 # Momentum Jaguar ATX
 #
@@ -394,18 +410,6 @@ load-$(CONFIG_MOMENCO_JAGUAR_ATX)  += 0xffffffff80100000
 #
 core-$(CONFIG_DDB5XXX_COMMON)  += arch/mips/ddb5xxx/common/
 
-#
-# NEC DDB Vrc-5074
-#
-core-$(CONFIG_DDB5074)         += arch/mips/ddb5xxx/ddb5074/
-load-$(CONFIG_DDB5074)         += 0xffffffff80080000
-
-#
-# NEC DDB Vrc-5476
-#
-core-$(CONFIG_DDB5476)         += arch/mips/ddb5xxx/ddb5476/
-load-$(CONFIG_DDB5476)         += 0xffffffff80080000
-
 #
 # NEC DDB Vrc-5477
 #
@@ -468,6 +472,15 @@ libs-$(CONFIG_PNX8550_JBS) += arch/mips/philips/pnx8550/jbs/
 #cflags-$(CONFIG_PNX8550_JBS)  += -Iinclude/asm-mips/mach-pnx8550
 load-$(CONFIG_PNX8550_JBS)     += 0xffffffff80060000
 
+# NEC EMMA2RH boards
+#
+core-$(CONFIG_EMMA2RH)          += arch/mips/emma2rh/common/
+cflags-$(CONFIG_EMMA2RH)        += -Iinclude/asm-mips/mach-emma2rh
+
+# NEC EMMA2RH Mark-eins
+core-$(CONFIG_MARKEINS)         += arch/mips/emma2rh/markeins/
+load-$(CONFIG_MARKEINS)         += 0xffffffff88100000
+
 #
 # SGI IP22 (Indy/Indigo2)
 #
index 0b2c03c5231984e3647f961f5a0a2a2f5e995a2a..5a1e3687cafa92ffd11237f67b4a3df6905330b8 100644 (file)
@@ -55,7 +55,7 @@
  * Careful if you change match 2 request!
  * The interrupt handler is called directly from the low level dispatch code.
  */
-au1xxx_irq_map_t au1xxx_ic0_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_ic0_map[] = {
 
 #if defined(CONFIG_SOC_AU1000)
        { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
@@ -220,5 +220,5 @@ au1xxx_irq_map_t au1xxx_ic0_map[] = {
 
 };
 
-int au1xxx_ic0_nr_irqs = sizeof(au1xxx_ic0_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_ic0_nr_irqs = ARRAY_SIZE(au1xxx_ic0_map);
 
index da61de7761549d89c3e5bc08204ebbdfdea5cd2a..afe05ec12c27d31326d73937081eb7e0631d1c33 100644 (file)
@@ -68,6 +68,7 @@
 
 extern void set_debug_traps(void);
 extern irq_cpustat_t irq_stat [NR_CPUS];
+extern void mips_timer_interrupt(struct pt_regs *regs);
 
 static void setup_local_irq(unsigned int irq, int type, int int_req);
 static unsigned int startup_irq(unsigned int irq);
index 4e5a6e1a9a6ed1313baccf87b20d380702da3713..b1392abac809b7da4ed9a572e5ad44db585afedd 100644 (file)
 
 /* TBD */
 static struct resource pci_io_resource = {
-       "pci IO space",
-       (u32)PCI_IO_START,
-       (u32)PCI_IO_END,
-       IORESOURCE_IO
+       .start  = PCI_IO_START,
+       .end    = PCI_IO_END,
+       .name   = "PCI IO space",
+       .flags  = IORESOURCE_IO
 };
 
 static struct resource pci_mem_resource = {
-       "pci memory space",
-       (u32)PCI_MEM_START,
-       (u32)PCI_MEM_END,
-       IORESOURCE_MEM
+       .start  = PCI_MEM_START,
+       .end    = PCI_MEM_END,
+       .name   = "PCI memory space",
+       .flags  = IORESOURCE_MEM
 };
 
 extern struct pci_ops au1x_pci_ops;
index 9c171afd9a534f121e1e4c0ff5c0c8165e9951e8..ae7d8c57bf3f8d889758f02607a2ad0aec16e4c2 100644 (file)
@@ -1,10 +1,9 @@
 /*
  *
  * BRIEF MODULE DESCRIPTION
- *    PROM library initialisation code, assuming a version of
- *    pmon is the boot code.
+ *    PROM library initialisation code, assuming YAMON is the boot loader.
  *
- * Copyright 2000,2001 MontaVista Software Inc.
+ * Copyright 2000, 2001, 2006 MontaVista Software Inc.
  * Author: MontaVista Software, Inc.
  *             ppopov@mvista.com or source@mvista.com
  *
@@ -49,9 +48,9 @@ extern char **prom_argv, **prom_envp;
 
 typedef struct
 {
-    char *name;
-/*    char *val; */
-}t_env_var;
+       char *name;
+       char *val;
+} t_env_var;
 
 
 char * prom_getcmdline(void)
@@ -85,21 +84,16 @@ char *prom_getenv(char *envname)
 {
        /*
         * Return a pointer to the given environment variable.
-        * Environment variables are stored in the form of "memsize=64".
         */
 
        t_env_var *env = (t_env_var *)prom_envp;
-       int i;
-
-       i = strlen(envname);
 
-       while(env->name) {
-               if(strncmp(envname, env->name, i) == 0) {
-                       return(env->name + strlen(envname) + 1);
-               }
+       while (env->name) {
+               if (strcmp(envname, env->name) == 0)
+                       return env->val;
                env++;
        }
-       return(NULL);
+       return NULL;
 }
 
 inline unsigned char str2hexnum(unsigned char c)
index 307e98c29ddc34cd2af39d5f6beb6a749b301605..97165b6b3894a07908e16379fe4b639ebe4cd163 100644 (file)
@@ -49,17 +49,13 @@ extern void __init board_setup(void);
 extern void au1000_restart(char *);
 extern void au1000_halt(void);
 extern void au1000_power_off(void);
-extern struct resource ioport_resource;
-extern struct resource iomem_resource;
-extern void (*board_time_init)(void);
 extern void au1x_time_init(void);
-extern void (*board_timer_setup)(struct irqaction *irq);
 extern void au1x_timer_setup(struct irqaction *irq);
 extern void au1xxx_time_init(void);
 extern void au1xxx_timer_setup(struct irqaction *irq);
 extern void set_cpuspec(void);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        struct  cpu_spec *sp;
        char *argptr;
index 44dac3b0df3b2575e705e1a7925928a18a9c7194..683d9da84b6695832193c8c5fe0e2b61496ed1fb 100644 (file)
@@ -112,6 +112,11 @@ sdsleep:
        mtc0    k0, CP0_PAGEMASK
        lw      k0, 0x14(sp)
        mtc0    k0, CP0_CONFIG
+
+       /* We need to catch the ealry Alchemy SOCs with
+        * the write-only Config[OD] bit and set it back to one...
+        */
+       jal     au1x00_fixup_config_od
        lw      $1, PT_R1(sp)
        lw      $2, PT_R2(sp)
        lw      $3, PT_R3(sp)
index f85f1524b36639a1c9c2e9bf0e7ef8673afb4c97..842e1b5ac4a1a3a6454e448dc5a136584d3f5409 100644 (file)
 #include <linux/mc146818rtc.h>
 #include <linux/timex.h>
 
-extern void do_softirq(void);
-extern volatile unsigned long wall_jiffies;
-unsigned long missed_heart_beats = 0;
-
 static unsigned long r4k_offset; /* Amount to increment compare reg each time */
 static unsigned long r4k_cur;    /* What counter should be at next timer irq */
 int    no_au1xxx_32khz;
@@ -116,6 +112,7 @@ void mips_timer_interrupt(struct pt_regs *regs)
 
 null:
        ack_r4ktimer(0);
+       irq_exit();
 }
 
 #ifdef CONFIG_PM
@@ -387,10 +384,9 @@ static unsigned long do_fast_pm_gettimeoffset(void)
 }
 #endif
 
-void au1xxx_timer_setup(struct irqaction *irq)
+void __init au1xxx_timer_setup(struct irqaction *irq)
 {
-        unsigned int est_freq;
-       extern unsigned long (*do_gettimeoffset)(void);
+       unsigned int est_freq;
 
        printk("calculating r4koff... ");
        r4k_offset = cal_r4koff();
index 5cb1166be35c8f2d0cb6691d0ff8794f001c7cb4..57d60401905ee321bfaee456a9465ef78265e16c 100644 (file)
@@ -47,7 +47,7 @@
 #include <asm/system.h>
 #include <asm/au1000.h>
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 
        { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
        { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
@@ -57,4 +57,4 @@ au1xxx_irq_map_t au1xxx_irq_map[] = {
        { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
index f63024a9893aa8bd9be968c4cf15dd92cee2484f..0138c5b7c86010516dce394fc0757d8299586324 100644 (file)
@@ -80,7 +80,7 @@ char irq_tab_alchemy[][5] __initdata = {
 #endif
 
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 
 #ifndef CONFIG_MIPS_MIRAGE
 #ifdef CONFIG_MIPS_DB1550
@@ -101,4 +101,4 @@ au1xxx_irq_map_t au1xxx_irq_map[] = {
 
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
index 6eacaa0daa4918b55d563a819ceaf35681259d42..14e1ed37cf6b30d4aaceed1eae16258ef4bad36a 100644 (file)
 #include <asm/system.h>
 #include <asm/au1000.h>
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 
        /* { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, */
        { AU1000_GPIO_21, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
index f9a0a8b9def25f865cbea8ee5768dfbf345f5414..4693a4eb2b829972966a0ee1306b54cb07ade10e 100644 (file)
@@ -58,7 +58,7 @@ char irq_tab_alchemy[][5] __initdata = {
  [7] = { -1, INTD, INTC, INTX, INTX},   /* IDSEL 07 - AdapterD-Slot1 (bottom) */
 };
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
        { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
        { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
        { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
@@ -66,4 +66,4 @@ au1xxx_irq_map_t au1xxx_irq_map[] = {
        { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
index a3c460e3c23e72983619c834435a2834783d2777..156500ba467ff191ce880334249088a01d5ebbf4 100644 (file)
@@ -47,8 +47,8 @@
 #include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
        { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
index 43be7158b9ab7e3a58c9ddcd9097cf53c4fdbbf3..d986916221b71db881f1241ffbfecf773169b90c 100644 (file)
 #include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
        { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted#
        { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card STSCHG#
        { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card IRQ#
        { AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, // DC_IRQ#
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
index 59e70e5cf325ef23c151b4585ab020fcd535c5d9..bacc0c6bfe675e5f3570371ea4f98a9004664ee7 100644 (file)
 #define PB1200_INT_END DB1200_INT_END
 #endif
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
        { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, // This is exteranl interrupt cascade
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
 
 /*
  *     Support for External interrupts on the PbAu1200 Development platform.
index 8cb76c2edb5e970ce61dba6d95b8349e3134d731..409d1612bb63ec64e72381afbd487060b6da0485 100644 (file)
@@ -52,7 +52,7 @@ char irq_tab_alchemy[][5] __initdata = {
  [13] = { -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot */
 };
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
        { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
        { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
        { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
@@ -60,4 +60,4 @@ au1xxx_irq_map_t au1xxx_irq_map[] = {
        { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
index 47c7a1c19f4b5d78eb19c64ba8d1d0c5d309d654..24a9d186cf5ab779e4c6306902671cf771687d6b 100644 (file)
@@ -52,9 +52,9 @@ char irq_tab_alchemy[][5] __initdata = {
  [13] =        { -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot 1 (right) */
 };
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
        { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
        { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
index 52f2f7daeb0559bdfaab23050c0c159823b72c6e..3844c6429e275a1af7f6bc1647c5db9944204dde 100644 (file)
@@ -47,7 +47,7 @@
 #include <asm/system.h>
 #include <asm/au1000.h>
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
        { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
        { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
        { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
@@ -63,4 +63,4 @@ au1xxx_irq_map_t au1xxx_irq_map[] = {
        { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/basler/excite/Makefile b/arch/mips/basler/excite/Makefile
new file mode 100644 (file)
index 0000000..519142c
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for Basler eXcite
+#
+
+obj-$(CONFIG_BASLER_EXCITE)    += excite_irq.o excite_prom.o excite_setup.o \
+                                  excite_device.o excite_procfs.o
+
+obj-$(CONFIG_KGDB)             += excite_dbg_io.o
+obj-m                          += excite_iodev.o
diff --git a/arch/mips/basler/excite/excite_dbg_io.c b/arch/mips/basler/excite/excite_dbg_io.c
new file mode 100644 (file)
index 0000000..83f6bdd
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/gdb-stub.h>
+#include <asm/rm9k-ocd.h>
+#include <excite.h>
+
+#if defined(CONFIG_SERIAL_8250) && CONFIG_SERIAL_8250_NR_UARTS > 1
+#error Debug port used by serial driver
+#endif
+
+#define UART_CLK               25000000
+#define BASE_BAUD              (UART_CLK / 16)
+#define REGISTER_BASE_0                0x0208UL
+#define REGISTER_BASE_1                0x0238UL
+
+#define REGISTER_BASE_DBG      REGISTER_BASE_1
+
+#define CPRR   0x0004
+#define UACFG  0x0200
+#define UAINTS 0x0204
+#define UARBR  (REGISTER_BASE_DBG + 0x0000)
+#define UATHR  (REGISTER_BASE_DBG + 0x0004)
+#define UADLL  (REGISTER_BASE_DBG + 0x0008)
+#define UAIER  (REGISTER_BASE_DBG + 0x000c)
+#define UADLH  (REGISTER_BASE_DBG + 0x0010)
+#define UAIIR  (REGISTER_BASE_DBG + 0x0014)
+#define UAFCR  (REGISTER_BASE_DBG + 0x0018)
+#define UALCR  (REGISTER_BASE_DBG + 0x001c)
+#define UAMCR  (REGISTER_BASE_DBG + 0x0020)
+#define UALSR  (REGISTER_BASE_DBG + 0x0024)
+#define UAMSR  (REGISTER_BASE_DBG + 0x0028)
+#define UASCR  (REGISTER_BASE_DBG + 0x002c)
+
+#define        PARITY_NONE     0
+#define        PARITY_ODD      0x08
+#define        PARITY_EVEN     0x18
+#define        PARITY_MARK     0x28
+#define        PARITY_SPACE    0x38
+
+#define        DATA_5BIT       0x0
+#define        DATA_6BIT       0x1
+#define        DATA_7BIT       0x2
+#define        DATA_8BIT       0x3
+
+#define        STOP_1BIT       0x0
+#define        STOP_2BIT       0x4
+
+#define BAUD_DBG       57600
+#define        PARITY_DBG      PARITY_NONE
+#define        DATA_DBG        DATA_8BIT
+#define        STOP_DBG        STOP_1BIT
+
+/* Initialize the serial port for KGDB debugging */
+void __init excite_kgdb_init(void)
+{
+       const u32 divisor = BASE_BAUD / BAUD_DBG;
+
+       /* Take the UART out of reset */
+       titan_writel(0x00ff1cff, CPRR);
+       titan_writel(0x00000000, UACFG);
+       titan_writel(0x00000002, UACFG);
+
+       titan_writel(0x0, UALCR);
+       titan_writel(0x0, UAIER);
+
+       /* Disable FIFOs */
+       titan_writel(0x00, UAFCR);
+
+       titan_writel(0x80, UALCR);
+       titan_writel(divisor & 0xff, UADLL);
+       titan_writel((divisor & 0xff00) >> 8, UADLH);
+       titan_writel(0x0, UALCR);
+
+       titan_writel(DATA_DBG | PARITY_DBG | STOP_DBG, UALCR);
+
+       /* Enable receiver interrupt */
+       titan_readl(UARBR);
+       titan_writel(0x1, UAIER);
+}
+
+int getDebugChar(void)
+{
+       while (!(titan_readl(UALSR) & 0x1));
+       return titan_readl(UARBR);
+}
+
+int putDebugChar(int data)
+{
+       while (!(titan_readl(UALSR) & 0x20));
+       titan_writel(data, UATHR);
+       return 1;
+}
+
+/* KGDB interrupt handler */
+asmlinkage void excite_kgdb_inthdl(struct pt_regs *regs)
+{
+       if (unlikely(
+               ((titan_readl(UAIIR) & 0x7) == 4)
+               && ((titan_readl(UARBR) & 0xff) == 0x3)))
+                       set_async_breakpoint(&regs->cp0_epc);
+}
diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c
new file mode 100644 (file)
index 0000000..34ec767
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/err.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <asm/types.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+#include <rm9k_eth.h>
+#include <rm9k_wdt.h>
+#include <rm9k_xicap.h>
+#include <excite_nandflash.h>
+
+#include "excite_iodev.h"
+
+#define RM9K_GE_UNIT   0
+#define XICAP_UNIT     0
+#define NAND_UNIT      0
+
+#define DLL_TIMEOUT    3               /* seconds */
+
+
+#define RINIT(__start__, __end__, __name__, __parent__) {      \
+       .name   = __name__ "_0",                                \
+       .start  = (__start__),                                  \
+       .end    = (__end__),                                    \
+       .flags  = 0,                                            \
+       .parent = (__parent__)                                  \
+}
+
+#define RINIT_IRQ(__irq__, __name__) { \
+       .name   = __name__ "_0",        \
+       .start  = (__irq__),            \
+       .end    = (__irq__),            \
+       .flags  = IORESOURCE_IRQ,       \
+       .parent = NULL                  \
+}
+
+
+
+enum {
+       slice_xicap,
+       slice_eth
+};
+
+
+
+static struct resource
+       excite_ctr_resource = {
+               .name           = "GPI counters",
+               .start          = 0,
+               .end            = 5,
+               .flags          = 0,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_gpislice_resource = {
+               .name           = "GPI slices",
+               .start          = 0,
+               .end            = 1,
+               .flags          = 0,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_mdio_channel_resource = {
+               .name           = "MDIO channels",
+               .start          = 0,
+               .end            = 1,
+               .flags          = 0,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_fifomem_resource = {
+               .name           = "FIFO memory",
+               .start          = 0,
+               .end            = 767,
+               .flags          = 0,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_scram_resource = {
+               .name           = "Scratch RAM",
+               .start          = EXCITE_PHYS_SCRAM,
+               .end            = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
+               .flags          = IORESOURCE_MEM,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_fpga_resource = {
+               .name           = "System FPGA",
+               .start          = EXCITE_PHYS_FPGA,
+               .end            = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
+               .flags          = IORESOURCE_MEM,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_nand_resource = {
+               .name           = "NAND flash control",
+               .start          = EXCITE_PHYS_NAND,
+               .end            = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
+               .flags          = IORESOURCE_MEM,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       },
+       excite_titan_resource = {
+               .name           = "TITAN registers",
+               .start          = EXCITE_PHYS_TITAN,
+               .end            = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
+               .flags          = IORESOURCE_MEM,
+               .parent         = NULL,
+               .sibling        = NULL,
+               .child          = NULL
+       };
+
+
+
+static void adjust_resources(struct resource *res, unsigned int n)
+{
+       struct resource *p;
+       const unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM
+                                  | IORESOURCE_IRQ | IORESOURCE_DMA;
+
+       for (p = res; p < res + n; p++) {
+               const struct resource * const parent = p->parent;
+               if (parent) {
+                       p->start += parent->start;
+                       p->end   += parent->start;
+                       p->flags =  parent->flags & mask;
+               }
+       }
+}
+
+
+
+#if defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE)
+static struct resource xicap_rsrc[] = {
+       RINIT(0x4840, 0x486f, XICAP_RESOURCE_FIFO_RX, &excite_titan_resource),
+       RINIT(0x4940, 0x494b, XICAP_RESOURCE_FIFO_TX, &excite_titan_resource),
+       RINIT(0x5040, 0x5127, XICAP_RESOURCE_XDMA, &excite_titan_resource),
+       RINIT(0x1000, 0x112f, XICAP_RESOURCE_PKTPROC, &excite_titan_resource),
+       RINIT(0x1100, 0x110f, XICAP_RESOURCE_PKT_STREAM, &excite_fpga_resource),
+       RINIT(0x0800, 0x0bff, XICAP_RESOURCE_DMADESC, &excite_scram_resource),
+       RINIT(slice_xicap, slice_xicap, XICAP_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
+       RINIT(0x0100, 0x02ff, XICAP_RESOURCE_FIFO_BLK, &excite_fifomem_resource),
+       RINIT_IRQ(TITAN_IRQ,  XICAP_RESOURCE_IRQ)
+};
+
+static struct platform_device xicap_pdev = {
+       .name           = XICAP_NAME,
+       .id             = XICAP_UNIT,
+       .num_resources  = ARRAY_SIZE(xicap_rsrc),
+       .resource       = xicap_rsrc
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init xicap_devinit(void)
+{
+       unsigned long tend;
+       u32 reg;
+       int retval;
+
+       adjust_resources(xicap_rsrc, ARRAY_SIZE(xicap_rsrc));
+
+       /* Power up the slice and configure it. */
+       reg = titan_readl(CPTC1R);
+       reg &= ~(0x11100 << slice_xicap);
+       titan_writel(reg, CPTC1R);
+
+       /* Enable slice & DLL. */
+       reg= titan_readl(CPRR);
+       reg &= ~(0x00030003 << (slice_xicap * 2));
+       titan_writel(reg, CPRR);
+
+       /* Wait for DLLs to lock */
+       tend = jiffies + DLL_TIMEOUT * HZ;
+       while (time_before(jiffies, tend)) {
+               if (!(~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))))
+                       break;
+               yield();
+       }
+
+       if (~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))) {
+               printk(KERN_ERR "%s: DLL not locked after %u seconds\n",
+                      xicap_pdev.name, DLL_TIMEOUT);
+               retval = -ETIME;
+       } else {
+               /* Register platform device */
+               retval = platform_device_register(&xicap_pdev);
+       }
+
+       return retval;
+}
+
+device_initcall(xicap_devinit);
+#endif /* defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) */
+
+
+
+#if defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE)
+static struct resource wdt_rsrc[] = {
+       RINIT(0, 0, WDT_RESOURCE_COUNTER, &excite_ctr_resource),
+       RINIT(0x0084, 0x008f, WDT_RESOURCE_REGS, &excite_titan_resource),
+       RINIT_IRQ(TITAN_IRQ,  WDT_RESOURCE_IRQ)
+};
+
+static struct platform_device wdt_pdev = {
+       .name           = WDT_NAME,
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(wdt_rsrc),
+       .resource       = wdt_rsrc
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init wdt_devinit(void)
+{
+       adjust_resources(wdt_rsrc, ARRAY_SIZE(wdt_rsrc));
+       return platform_device_register(&wdt_pdev);
+}
+
+device_initcall(wdt_devinit);
+#endif /* defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) */
+
+
+
+static struct resource excite_nandflash_rsrc[] = {
+       RINIT(0x2000, 0x201f, EXCITE_NANDFLASH_RESOURCE_REGS,  &excite_nand_resource)
+};
+
+static struct platform_device excite_nandflash_pdev = {
+       .name           = "excite_nand",
+       .id             = NAND_UNIT,
+       .num_resources  = ARRAY_SIZE(excite_nandflash_rsrc),
+       .resource       = excite_nandflash_rsrc
+};
+
+/*
+ * Create a platform device for the access to the nand-flash
+ * port
+ */
+static int __init excite_nandflash_devinit(void)
+{
+       adjust_resources(excite_nandflash_rsrc, ARRAY_SIZE(excite_nandflash_rsrc));
+
+        /* nothing to be done here */
+
+        /* Register platform device */
+       return platform_device_register(&excite_nandflash_pdev);
+}
+
+device_initcall(excite_nandflash_devinit);
+
+
+
+static struct resource iodev_rsrc[] = {
+       RINIT_IRQ(FPGA1_IRQ,  IODEV_RESOURCE_IRQ)
+};
+
+static struct platform_device io_pdev = {
+       .name           = IODEV_NAME,
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(iodev_rsrc),
+       .resource       = iodev_rsrc
+};
+
+/*
+ * Create a platform device for the external I/O ports.
+ */
+static int __init io_devinit(void)
+{
+       adjust_resources(iodev_rsrc, ARRAY_SIZE(iodev_rsrc));
+       return platform_device_register(&io_pdev);
+}
+
+device_initcall(io_devinit);
+
+
+
+
+#if defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE)
+static struct resource rm9k_ge_rsrc[] = {
+       RINIT(0x2200, 0x27ff, RM9K_GE_RESOURCE_MAC, &excite_titan_resource),
+       RINIT(0x1800, 0x1fff, RM9K_GE_RESOURCE_MSTAT, &excite_titan_resource),
+       RINIT(0x2000, 0x212f, RM9K_GE_RESOURCE_PKTPROC, &excite_titan_resource),
+       RINIT(0x5140, 0x5227, RM9K_GE_RESOURCE_XDMA, &excite_titan_resource),
+       RINIT(0x4870, 0x489f, RM9K_GE_RESOURCE_FIFO_RX, &excite_titan_resource),
+       RINIT(0x494c, 0x4957, RM9K_GE_RESOURCE_FIFO_TX, &excite_titan_resource),
+       RINIT(0x0000, 0x007f, RM9K_GE_RESOURCE_FIFOMEM_RX, &excite_fifomem_resource),
+       RINIT(0x0080, 0x00ff, RM9K_GE_RESOURCE_FIFOMEM_TX, &excite_fifomem_resource),
+       RINIT(0x0180, 0x019f, RM9K_GE_RESOURCE_PHY, &excite_titan_resource),
+       RINIT(0x0000, 0x03ff, RM9K_GE_RESOURCE_DMADESC_RX, &excite_scram_resource),
+       RINIT(0x0400, 0x07ff, RM9K_GE_RESOURCE_DMADESC_TX, &excite_scram_resource),
+       RINIT(slice_eth, slice_eth, RM9K_GE_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
+       RINIT(0, 0, RM9K_GE_RESOURCE_MDIO_CHANNEL, &excite_mdio_channel_resource),
+       RINIT_IRQ(TITAN_IRQ,  RM9K_GE_RESOURCE_IRQ_MAIN),
+       RINIT_IRQ(PHY_IRQ, RM9K_GE_RESOURCE_IRQ_PHY)
+};
+
+static struct platform_device rm9k_ge_pdev = {
+       .name           = RM9K_GE_NAME,
+       .id             = RM9K_GE_UNIT,
+       .num_resources  = ARRAY_SIZE(rm9k_ge_rsrc),
+       .resource       = rm9k_ge_rsrc
+};
+
+
+
+/*
+ * Create a platform device for the Ethernet port.
+ */
+static int __init rm9k_ge_devinit(void)
+{
+       u32 reg;
+
+       adjust_resources(rm9k_ge_rsrc, ARRAY_SIZE(rm9k_ge_rsrc));
+
+       /* Power up the slice and configure it. */
+       reg = titan_readl(CPTC1R);
+       reg &= ~(0x11000 << slice_eth);
+       reg |= 0x100 << slice_eth;
+       titan_writel(reg, CPTC1R);
+
+       /* Take the MAC out of reset, reset the DLLs. */
+       reg = titan_readl(CPRR);
+       reg &= ~(0x00030000 << (slice_eth * 2));
+       reg |= 0x3 << (slice_eth * 2);
+       titan_writel(reg, CPRR);
+
+       return platform_device_register(&rm9k_ge_pdev);
+}
+
+device_initcall(rm9k_ge_devinit);
+#endif /* defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) */
+
+
+
+static int __init excite_setup_devs(void)
+{
+       int res;
+       u32 reg;
+
+       /* Enable xdma and fifo interrupts */
+       reg = titan_readl(0x0050);
+       titan_writel(reg | 0x18000000, 0x0050);
+
+       res = request_resource(&iomem_resource, &excite_titan_resource);
+       if (res)
+               return res;
+       res = request_resource(&iomem_resource, &excite_scram_resource);
+       if (res)
+               return res;
+       res = request_resource(&iomem_resource, &excite_fpga_resource);
+       if (res)
+               return res;
+       res = request_resource(&iomem_resource, &excite_nand_resource);
+       if (res)
+               return res;
+       excite_fpga_resource.flags = excite_fpga_resource.parent->flags &
+                                  ( IORESOURCE_IO | IORESOURCE_MEM
+                                  | IORESOURCE_IRQ | IORESOURCE_DMA);
+       excite_nand_resource.flags = excite_nand_resource.parent->flags &
+                                  ( IORESOURCE_IO | IORESOURCE_MEM
+                                  | IORESOURCE_IRQ | IORESOURCE_DMA);
+
+       return 0;
+}
+
+arch_initcall(excite_setup_devs);
+
diff --git a/arch/mips/basler/excite/excite_flashtest.c b/arch/mips/basler/excite/excite_flashtest.c
new file mode 100644 (file)
index 0000000..f0024a8
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+*  Copyright (C) 2005 by Basler Vision Technologies AG
+*  Author: Thies Moeller <thies.moeller@baslerweb.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+
+#include <excite.h>
+
+#include <asm/io.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+#include <asm/rm9k-ocd.h> // for ocd_write
+#include <linux/workqueue.h> // for queue
+
+#include "excite_nandflash.h"
+#include "nandflash.h"
+
+#define PFX "excite flashtest: "
+typedef void __iomem *io_reg_t;
+
+#define io_readb(__a__)                __raw_readb((__a__))
+#define io_writeb(__v__, __a__)        __raw_writeb((__v__), (__a__))
+
+
+
+static inline const struct resource *excite_nandflash_get_resource(
+       struct platform_device *d, unsigned long flags, const char *basename)
+{
+       const char fmt[] = "%s_%u";
+       char buf[80];
+
+       if (unlikely(snprintf(buf, sizeof buf, fmt, basename, d->id) >= sizeof buf))
+               return NULL;
+
+       return platform_get_resource_byname(d, flags, buf);
+}
+
+static inline io_reg_t
+excite_nandflash_map_regs(struct platform_device *d, const char *basename)
+{
+       void *result = NULL;
+       const struct resource *const r =
+           excite_nandflash_get_resource(d, IORESOURCE_MEM, basename);
+       if (r)
+          result = ioremap_nocache(r->start, r->end + 1 - r->start);
+       return result;
+}
+
+/* controller and mtd information */
+
+struct excite_nandflash_drvdata {
+       struct mtd_info board_mtd;
+       struct nand_chip board_chip;
+       io_reg_t regs;
+};
+
+
+/* command and control functions */
+static void excite_nandflash_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+       struct nand_chip *this = mtd->priv;
+       io_reg_t regs = container_of(mtd,struct excite_nandflash_drvdata,board_mtd)->regs;
+
+       switch (cmd) {
+       /* Select the command latch */
+       case NAND_CTL_SETCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_CMD;
+               break;
+       /* Deselect the command latch */
+       case NAND_CTL_CLRCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_DATA;
+               break;
+       /* Select the address latch */
+       case NAND_CTL_SETALE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_ADDR;
+               break;
+       /* Deselect the address latch */
+       case NAND_CTL_CLRALE: this->IO_ADDR_W = regs  + EXCITE_NANDFLASH_DATA;
+               break;
+       /* Select the chip  -- not used */
+       case NAND_CTL_SETNCE:
+               break;
+       /* Deselect the chip -- not used */
+       case NAND_CTL_CLRNCE:
+               break;
+       }
+
+       this->IO_ADDR_R = this->IO_ADDR_W;
+}
+
+/* excite_nandflash_devready()
+ *
+ * returns 0 if the nand is busy, 1 if it is ready
+ */
+static int excite_nandflash_devready(struct mtd_info *mtd)
+{
+       struct excite_nandflash_drvdata *drvdata =
+           container_of(mtd, struct excite_nandflash_drvdata, board_mtd);
+
+       return io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
+}
+
+/* device management functions */
+
+/* excite_nandflash_remove
+ *
+ * called by device layer to remove the driver
+ * the binding to the mtd and all allocated
+ * resources are released
+ */
+static int excite_nandflash_remove(struct device *dev)
+{
+       struct excite_nandflash_drvdata *this = dev_get_drvdata(dev);
+
+       pr_info(PFX "remove");
+
+       dev_set_drvdata(dev, NULL);
+
+       if (this == NULL) {
+               pr_debug(PFX "call remove without private data!!");
+               return 0;
+       }
+
+
+       /* free the common resources */
+       if (this->regs != NULL) {
+               iounmap(this->regs);
+               this->regs = NULL;
+       }
+
+       kfree(this);
+
+       return 0;
+}
+
+static int elapsed;
+
+void my_workqueue_handler(void *arg)
+{
+       elapsed = 1;
+}
+
+DECLARE_WORK(sigElapsed, my_workqueue_handler, 0);
+
+
+/* excite_nandflash_probe
+ *
+ * called by device layer when it finds a device matching
+ * one our driver can handled. This code checks to see if
+ * it can allocate all necessary resources then calls the
+ * nand layer to look for devices
+*/
+static int excite_nandflash_probe(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+
+       struct excite_nandflash_drvdata *drvdata;           /* private driver data     */
+       struct nand_chip              *board_chip;  /* private flash chip data */
+       struct mtd_info               *board_mtd;   /* mtd info for this board */
+
+       int err      = 0;
+       int count    = 0;
+       struct timeval tv,endtv;
+       unsigned int dt;
+
+       pr_info(PFX "probe dev: (%p)\n", dev);
+
+       pr_info(PFX "adjust LB timing\n");
+       ocd_writel(0x00000330, LDP2);
+
+       drvdata = kmalloc(sizeof(*drvdata), GFP_KERNEL);
+       if (unlikely(!drvdata)) {
+               printk(KERN_ERR PFX "no memory for drvdata\n");
+               err = -ENOMEM;
+               goto mem_error;
+       }
+
+       /* Initialize structures */
+       memset(drvdata, 0, sizeof(*drvdata));
+
+       /* bind private data into driver */
+       dev_set_drvdata(dev, drvdata);
+
+       /* allocate and map the resource */
+       drvdata->regs =
+           excite_nandflash_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS);
+
+       if (unlikely(!drvdata->regs)) {
+               printk(KERN_ERR PFX "cannot reserve register region\n");
+               err = -ENXIO;
+               goto io_error;
+       }
+
+       /* initialise our chip */
+       board_chip = &drvdata->board_chip;
+
+       board_chip->IO_ADDR_R = drvdata->regs + EXCITE_NANDFLASH_DATA;
+       board_chip->IO_ADDR_W = drvdata->regs + EXCITE_NANDFLASH_DATA;
+
+       board_chip->hwcontrol = excite_nandflash_hwcontrol;
+       board_chip->dev_ready = excite_nandflash_devready;
+
+       board_chip->chip_delay = 25;
+       #if 0
+       /* TODO: speedup the initial scan */
+       board_chip->options = NAND_USE_FLASH_BBT;
+       #endif
+       board_chip->eccmode = NAND_ECC_SOFT;
+
+       /* link chip to mtd */
+       board_mtd = &drvdata->board_mtd;
+       board_mtd->priv = board_chip;
+
+
+       pr_info(PFX "FlashTest\n");
+       elapsed = 0;
+/*     schedule_delayed_work(&sigElapsed, 1*HZ);
+       while (!elapsed) {
+               io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
+               count++;
+       }
+       pr_info(PFX "reads in 1 sec --> %d\n",count);
+*/
+       do_gettimeofday(&tv);
+       for (count = 0 ; count < 1000000; count ++) {
+               io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
+       }
+       do_gettimeofday(&endtv);
+       dt = (endtv.tv_sec - tv.tv_sec) * 1000000 + endtv.tv_usec  - tv.tv_usec;
+       pr_info(PFX "%8d us timeval\n",dt);
+       pr_info(PFX "EndFlashTest\n");
+
+/*      return with error to unload everything
+*/
+io_error:
+       iounmap(drvdata->regs);
+
+mem_error:
+       kfree(drvdata);
+
+       if (err == 0)
+               err = -EINVAL;
+       return err;
+}
+
+static struct device_driver excite_nandflash_driver = {
+       .name = "excite_nand",
+       .bus = &platform_bus_type,
+       .probe = excite_nandflash_probe,
+       .remove = excite_nandflash_remove,
+};
+
+static int __init excite_nandflash_init(void)
+{
+       pr_info(PFX "register Driver (Rev: $Revision:$)\n");
+       return driver_register(&excite_nandflash_driver);
+}
+
+static void __exit excite_nandflash_exit(void)
+{
+       driver_unregister(&excite_nandflash_driver);
+       pr_info(PFX "Driver unregistered");
+}
+
+module_init(excite_nandflash_init);
+module_exit(excite_nandflash_exit);
+
+MODULE_AUTHOR("Thies Moeller <thies.moeller@baslerweb.com>");
+MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/basler/excite/excite_fpga.h b/arch/mips/basler/excite/excite_fpga.h
new file mode 100644 (file)
index 0000000..38fcda7
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef EXCITE_FPGA_H_INCLUDED
+#define EXCITE_FPGA_H_INCLUDED
+
+
+/**
+ * Adress alignment of the individual FPGA bytes.
+ * The address arrangement of the individual bytes of the FPGA is two
+ * byte aligned at the embedded MK2 platform.
+ */
+#ifdef EXCITE_CCI_FPGA_MK2
+typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2)));
+#else
+typedef unsigned char excite_cci_fpga_align_t;
+#endif
+
+
+/**
+ * Size of Dual Ported RAM.
+ */
+#define EXCITE_DPR_SIZE 263
+
+
+/**
+ * Size of Reserved Status Fields in Dual Ported RAM.
+ */
+#define EXCITE_DPR_STATUS_SIZE 7
+
+
+
+/**
+ * FPGA.
+ * Hardware register layout of the FPGA interface. The FPGA must accessed
+ * byte wise solely.
+ * @see EXCITE_CCI_DPR_MK2
+ */
+typedef struct excite_fpga {
+
+       /**
+        * Dual Ported RAM.
+        */
+       excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE];
+
+       /**
+        * Status.
+        */
+       excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE];
+
+#ifdef EXCITE_CCI_FPGA_MK2
+       /**
+        * RM9000 Interrupt.
+        * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite.
+        */
+       excite_cci_fpga_align_t rm9k_int;
+#else
+       /**
+        * MK2 Interrupt.
+        * Write access initiates interrupt at the ARM processor of the MK2.
+        */
+       excite_cci_fpga_align_t mk2_int;
+
+       excite_cci_fpga_align_t gap[0x1000-0x10f];
+
+       /**
+        * IRQ Source/Acknowledge.
+        */
+       excite_cci_fpga_align_t rm9k_irq_src;
+
+       /**
+        * IRQ Mask.
+        * Set bits enable the related interrupt.
+        */
+       excite_cci_fpga_align_t rm9k_irq_mask;
+#endif
+
+
+} excite_fpga;
+
+
+
+#endif /* ndef EXCITE_FPGA_H_INCLUDED */
diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c
new file mode 100644 (file)
index 0000000..91121e5
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ *  Copyright (C) 2005 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+
+#include "excite_iodev.h"
+
+
+
+static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int);
+static int __init iodev_probe(struct device *);
+static int __exit iodev_remove(struct device *);
+static int iodev_open(struct inode *, struct file *);
+static int iodev_release(struct inode *, struct file *);
+static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *);
+static unsigned int iodev_poll(struct file *, struct poll_table_struct *);
+static irqreturn_t iodev_irqhdl(int, void *, struct pt_regs *);
+
+
+
+static const char iodev_name[] = "iodev";
+static unsigned int iodev_irq;
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+
+
+static struct file_operations fops =
+{
+       .owner          = THIS_MODULE,
+       .open           = iodev_open,
+       .release        = iodev_release,
+       .read           = iodev_read,
+       .poll           = iodev_poll
+};
+
+static struct miscdevice miscdev =
+{
+       .minor          = MISC_DYNAMIC_MINOR,
+       .name           = iodev_name,
+       .fops           = &fops
+};
+
+static struct device_driver iodev_driver =
+{
+       .name           = (char *) iodev_name,
+       .bus            = &platform_bus_type,
+       .owner          = THIS_MODULE,
+       .probe          = iodev_probe,
+       .remove         = __exit_p(iodev_remove)
+};
+
+
+
+static const struct resource *
+iodev_get_resource(struct platform_device *pdv, const char *name,
+                    unsigned int type)
+{
+       char buf[80];
+       if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf)
+               return NULL;
+       return platform_get_resource_byname(pdv, type, buf);
+}
+
+
+
+/* No hotplugging on the platform bus - use __init */
+static int __init iodev_probe(struct device *dev)
+{
+       struct platform_device * const pdv = to_platform_device(dev);
+       const struct resource * const ri =
+               iodev_get_resource(pdv, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ);
+
+       if (unlikely(!ri))
+               return -ENXIO;
+
+       iodev_irq = ri->start;
+       return misc_register(&miscdev);
+}
+
+
+
+static int __exit iodev_remove(struct device *dev)
+{
+       return misc_deregister(&miscdev);
+}
+
+
+
+static int iodev_open(struct inode *i, struct file *f)
+{
+       return request_irq(iodev_irq, iodev_irqhdl, SA_INTERRUPT,
+                          iodev_name, &miscdev);
+}
+
+
+
+static int iodev_release(struct inode *i, struct file *f)
+{
+       free_irq(iodev_irq, &miscdev);
+       return 0;
+}
+
+
+
+
+static ssize_t
+iodev_read(struct file *f, char __user *d, size_t s, loff_t *o)
+{
+       ssize_t ret;
+       DEFINE_WAIT(w);
+
+       prepare_to_wait(&wq, &w, TASK_INTERRUPTIBLE);
+       if (!signal_pending(current))
+               schedule();
+       ret = signal_pending(current) ? -ERESTARTSYS : 0;
+       finish_wait(&wq, &w);
+       return ret;
+}
+
+
+static unsigned int iodev_poll(struct file *f, struct poll_table_struct *p)
+{
+       poll_wait(f, &wq, p);
+       return POLLOUT | POLLWRNORM;
+}
+
+
+
+
+static irqreturn_t iodev_irqhdl(int irq, void *ctxt, struct pt_regs *regs)
+{
+       wake_up(&wq);
+       return IRQ_HANDLED;
+}
+
+
+
+static int __init iodev_init_module(void)
+{
+       return driver_register(&iodev_driver);
+}
+
+
+
+static void __exit iodev_cleanup_module(void)
+{
+       driver_unregister(&iodev_driver);
+}
+
+module_init(iodev_init_module);
+module_exit(iodev_cleanup_module);
+
+
+
+MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
+MODULE_DESCRIPTION("Basler eXcite i/o interrupt handler");
+MODULE_VERSION("0.0");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/basler/excite/excite_iodev.h b/arch/mips/basler/excite/excite_iodev.h
new file mode 100644 (file)
index 0000000..cbfbb5d
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __EXCITE_IODEV_H__
+#define __EXCITE_IODEV_H__
+
+/* Device name */
+#define IODEV_NAME             "iodev"
+
+/* Resource names */
+#define IODEV_RESOURCE_IRQ     "excite_iodev_irq"
+
+#endif /* __EXCITE_IODEV_H__ */
diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c
new file mode 100644 (file)
index 0000000..511ad87
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ *  Copyright (C) by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslereb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+
+extern asmlinkage void excite_handle_int(void);
+
+/*
+ * Initialize the interrupt handler
+ */
+void __init arch_init_irq(void)
+{
+       mips_cpu_irq_init(0);
+       rm7k_cpu_irq_init(8);
+       rm9k_cpu_irq_init(12);
+
+#ifdef CONFIG_KGDB
+       excite_kgdb_init();
+#endif
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       const u32
+               interrupts = read_c0_cause() >> 8,
+               mask = ((read_c0_status() >> 8) & 0x000000ff) |
+                      (read_c0_intcontrol() & 0x0000ff00),
+               pending = interrupts & mask;
+       u32 msgintflags, msgintmask, msgint;
+
+       /* process timer interrupt */
+       if (pending & (1 << TIMER_IRQ)) {
+               do_IRQ(TIMER_IRQ, regs);
+               return;
+       }
+
+       /* Process PCI interrupts */
+#if USB_IRQ < 10
+       msgintflags = ocd_readl(INTP0Status0 + (USB_MSGINT / 0x20 * 0x10));
+       msgintmask  = ocd_readl(INTP0Mask0 + (USB_MSGINT / 0x20 * 0x10));
+       msgint      = msgintflags & msgintmask & (0x1 << (USB_MSGINT % 0x20));
+       if ((pending & (1 << USB_IRQ)) && msgint) {
+#else
+       if (pending & (1 << USB_IRQ)) {
+#endif
+               do_IRQ(USB_IRQ, regs);
+               return;
+       }
+
+       /* Process TITAN interrupts */
+       msgintflags = ocd_readl(INTP0Status0 + (TITAN_MSGINT / 0x20 * 0x10));
+       msgintmask  = ocd_readl(INTP0Mask0 + (TITAN_MSGINT / 0x20 * 0x10));
+       msgint      = msgintflags & msgintmask & (0x1 << (TITAN_MSGINT % 0x20));
+       if ((pending & (1 << TITAN_IRQ)) && msgint) {
+               ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10));
+#if defined(CONFIG_KGDB)
+               excite_kgdb_inthdl(regs);
+#endif
+               do_IRQ(TITAN_IRQ, regs);
+               return;
+       }
+
+       /* Process FPGA line #0 interrupts */
+       msgintflags = ocd_readl(INTP0Status0 + (FPGA0_MSGINT / 0x20 * 0x10));
+       msgintmask  = ocd_readl(INTP0Mask0 + (FPGA0_MSGINT / 0x20 * 0x10));
+       msgint      = msgintflags & msgintmask & (0x1 << (FPGA0_MSGINT % 0x20));
+       if ((pending & (1 << FPGA0_IRQ)) && msgint) {
+               do_IRQ(FPGA0_IRQ, regs);
+               return;
+       }
+
+       /* Process FPGA line #1 interrupts */
+       msgintflags = ocd_readl(INTP0Status0 + (FPGA1_MSGINT / 0x20 * 0x10));
+       msgintmask  = ocd_readl(INTP0Mask0 + (FPGA1_MSGINT / 0x20 * 0x10));
+       msgint      = msgintflags & msgintmask & (0x1 << (FPGA1_MSGINT % 0x20));
+       if ((pending & (1 << FPGA1_IRQ)) && msgint) {
+               do_IRQ(FPGA1_IRQ, regs);
+               return;
+       }
+
+       /* Process PHY interrupts */
+       msgintflags = ocd_readl(INTP0Status0 + (PHY_MSGINT / 0x20 * 0x10));
+       msgintmask  = ocd_readl(INTP0Mask0 + (PHY_MSGINT / 0x20 * 0x10));
+       msgint      = msgintflags & msgintmask & (0x1 << (PHY_MSGINT % 0x20));
+       if ((pending & (1 << PHY_IRQ)) && msgint) {
+               do_IRQ(PHY_IRQ, regs);
+               return;
+       }
+
+       /* Process spurious interrupts */
+       spurious_interrupt(regs);
+}
diff --git a/arch/mips/basler/excite/excite_procfs.c b/arch/mips/basler/excite/excite_procfs.c
new file mode 100644 (file)
index 0000000..c62be03
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  Copyright (C) 2004, 2005 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  Procfs support for Basler eXcite
+ *
+ *  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/config.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+
+static int excite_get_unit_id(char *buf, char **addr, off_t offs, int size)
+{
+       const int len = snprintf(buf, PAGE_SIZE, "%06x", unit_id);
+       const int w = len - offs;
+       *addr = buf + offs;
+       return w < size ? w : size;
+}
+
+static int
+excite_bootrom_read(char *page, char **start, off_t off, int count,
+                 int *eof, void *data)
+{
+       void __iomem * src;
+
+       if (off >= EXCITE_SIZE_BOOTROM) {
+               *eof = 1;
+               return 0;
+       }
+
+       if ((off + count) > EXCITE_SIZE_BOOTROM)
+               count = EXCITE_SIZE_BOOTROM - off;
+
+       src = ioremap(EXCITE_PHYS_BOOTROM + off, count);
+       if (src) {
+               memcpy_fromio(page, src, count);
+               iounmap(src);
+               *start = page;
+       } else {
+               count = -ENOMEM;
+       }
+
+       return count;
+}
+
+void excite_procfs_init(void)
+{
+       /* Create & populate /proc/excite */
+       struct proc_dir_entry * const pdir = proc_mkdir("excite", &proc_root);
+       if (pdir) {
+               struct proc_dir_entry * e;
+
+               e = create_proc_info_entry("unit_id", S_IRUGO, pdir,
+                                          excite_get_unit_id);
+               if (e) e->size = 6;
+
+               e = create_proc_read_entry("bootrom", S_IRUGO, pdir,
+                                          excite_bootrom_read, NULL);
+               if (e) e->size = EXCITE_SIZE_BOOTROM;
+       }
+}
diff --git a/arch/mips/basler/excite/excite_prom.c b/arch/mips/basler/excite/excite_prom.c
new file mode 100644 (file)
index 0000000..84724b2
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ *  Copyright (C) 2004, 2005 by Thomas Koeller (thomas.koeller@baslerweb.com)
+ *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
+ *  Manish Lachwani.
+ *
+ *  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/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/string.h>
+
+#include <excite.h>
+
+/* This struct is used by Redboot to pass arguments to the kernel */
+typedef struct
+{
+       char *name;
+       char *val;
+} t_env_var;
+
+struct parmblock {
+       t_env_var memsize;
+       t_env_var modetty0;
+       t_env_var ethaddr;
+       t_env_var env_end;
+       char *argv[2];
+       char text[0];
+};
+
+static unsigned int prom_argc;
+static const char ** prom_argv;
+static const t_env_var * prom_env;
+
+static void prom_halt(void) __attribute__((noreturn));
+static void prom_exit(void) __attribute__((noreturn));
+
+
+
+const char *get_system_type(void)
+{
+       return "Basler eXcite";
+}
+
+/*
+ * Halt the system
+ */
+static void prom_halt(void)
+{
+       printk(KERN_NOTICE "\n** System halted.\n");
+       while (1)
+               asm volatile (
+                       "\t.set\tmips3\n"
+                       "\twait\n"
+                       "\t.set\tmips0\n"
+               );
+}
+
+/*
+ * Reset the CPU and re-enter Redboot
+ */
+static void prom_exit(void)
+{
+       unsigned int i;
+       volatile unsigned char * const flg =
+               (volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_DPR);
+
+       /* Clear the watchdog reset flag, set the reboot flag */
+       *flg &= ~0x01;
+       *flg |= 0x80;
+
+       for (i = 0; i < 10; i++) {
+               *(volatile unsigned char *)  (EXCITE_ADDR_FPGA + EXCITE_FPGA_SYSCTL) = 0x02;
+               iob();
+               mdelay(1000);
+       }
+
+       printk(KERN_NOTICE "Reset failed\n");
+       prom_halt();
+}
+
+static const char __init *prom_getenv(char *name)
+{
+       const t_env_var * p;
+       for (p = prom_env; p->name != NULL; p++)
+               if(strcmp(name, p->name) == 0)
+                       break;
+       return p->val;
+}
+
+/*
+ * Init routine which accepts the variables from Redboot
+ */
+void __init prom_init(void)
+{
+       const struct parmblock * const pb = (struct parmblock *) fw_arg2;
+
+       prom_argc = fw_arg0;
+       prom_argv = (const char **) fw_arg1;
+       prom_env = &pb->memsize;
+
+       /* Callbacks for halt, restart */
+       _machine_restart = (void (*)(char *)) prom_exit;
+       _machine_halt = prom_halt;
+
+#ifdef CONFIG_32BIT
+       /* copy command line */
+       strcpy(arcs_cmdline, prom_argv[1]);
+       memsize = simple_strtol(prom_getenv("memsize"), NULL, 16);
+       strcpy(modetty, prom_getenv("modetty0"));
+#endif /* CONFIG_32BIT */
+
+#ifdef CONFIG_64BIT
+#      error 64 bit support not implemented
+#endif /* CONFIG_64BIT */
+
+       mips_machgroup = MACH_GROUP_TITAN;
+       mips_machtype = MACH_TITAN_EXCITE;
+}
+
+/* This is called from free_initmem(), so we need to provide it */
+void __init prom_free_prom_memory(void)
+{
+       /* Nothing to do */
+}
diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c
new file mode 100644 (file)
index 0000000..005b025
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ *  Copyright (C) 2004, 2005 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
+ *  Manish Lachwani.
+ *
+ *  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/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/pgtable-32.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+
+#define TITAN_UART_CLK 25000000
+
+#if 1
+/* normal serial port assignment */
+#define REGBASE_SER0   0x0208
+#define REGBASE_SER1   0x0238
+#define MASK_SER0      0x1
+#define MASK_SER1      0x2
+#else
+/* serial ports swapped */
+#define REGBASE_SER0   0x0238
+#define REGBASE_SER1   0x0208
+#define MASK_SER0      0x2
+#define MASK_SER1      0x1
+#endif
+
+unsigned long memsize;
+char modetty[30];
+unsigned int titan_irq = TITAN_IRQ;
+static void __iomem * ctl_regs;
+u32 unit_id;
+
+volatile void __iomem * const ocd_base = (void *) (EXCITE_ADDR_OCD);
+volatile void __iomem * const titan_base = (void *) (EXCITE_ADDR_TITAN);
+
+/* Protect access to shared GPI registers */
+spinlock_t titan_lock = SPIN_LOCK_UNLOCKED;
+int titan_irqflags;
+
+
+static void excite_timer_init(void)
+{
+       const u32 modebit5 = ocd_readl(0x00e4);
+       unsigned int
+               mult = ((modebit5 >> 11) & 0x1f) + 2,
+               div = ((modebit5 >> 16) & 0x1f) + 2;
+
+       if (div == 33) div = 1;
+       mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2;
+}
+
+static void excite_timer_setup(struct irqaction *irq)
+{
+       /* The eXcite platform uses the alternate timer interrupt */
+       set_c0_intcontrol(0x80);
+       setup_irq(TIMER_IRQ, irq);
+}
+
+static int __init excite_init_console(void)
+{
+#if defined(CONFIG_SERIAL_8250)
+       static __initdata char serr[] =
+               KERN_ERR "Serial port #%u setup failed\n";
+       struct uart_port up;
+
+       /* Take the DUART out of reset */
+       titan_writel(0x00ff1cff, CPRR);
+
+#if defined(CONFIG_KGDB) || (CONFIG_SERIAL_8250_NR_UARTS > 1)
+       /* Enable both ports */
+       titan_writel(MASK_SER0 | MASK_SER1, UACFG);
+#else
+       /* Enable port #0 only */
+       titan_writel(MASK_SER0, UACFG);
+#endif /* defined(CONFIG_KGDB) */
+
+       /*
+        * Set up serial port #0. Do not use autodetection; the result is
+        * not what we want.
+        */
+       memset(&up, 0, sizeof(up));
+       up.membase      = (char *) titan_addr(REGBASE_SER0);
+       up.irq          = TITAN_IRQ;
+       up.uartclk      = TITAN_UART_CLK;
+       up.regshift     = 0;
+       up.iotype       = UPIO_MEM32;
+       up.type         = PORT_RM9000;
+       up.flags        = UPF_SHARE_IRQ;
+       up.line         = 0;
+       if (early_serial_setup(&up))
+               printk(serr, up.line);
+
+#if CONFIG_SERIAL_8250_NR_UARTS > 1
+       /* And now for port #1. */
+       up.membase      = (char *) titan_addr(REGBASE_SER1);
+       up.line         = 1;
+       if (early_serial_setup(&up))
+               printk(serr, up.line);
+#endif /* CONFIG_SERIAL_8250_NR_UARTS > 1 */
+#else
+       /* Leave the DUART in reset */
+       titan_writel(0x00ff3cff, CPRR);
+#endif  /* defined(CONFIG_SERIAL_8250) */
+
+       return 0;
+}
+
+static int __init excite_platform_init(void)
+{
+       unsigned int i;
+       unsigned char buf[3];
+       u8 reg;
+       void __iomem * dpr;
+
+       /* BIU buffer allocations */
+       ocd_writel(8, CPURSLMT);        /* CPU */
+       titan_writel(4, CPGRWL);        /* GPI / Ethernet */
+
+       /* Map control registers located in FPGA */
+       ctl_regs = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_SYSCTL, 16);
+       if (!ctl_regs)
+               panic("eXcite: failed to map platform control registers\n");
+       memcpy_fromio(buf, ctl_regs + 2, ARRAY_SIZE(buf));
+       unit_id = buf[0] | (buf[1] << 8) | (buf[2] << 16);
+
+       /* Clear the reboot flag */
+       dpr = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_DPR, 1);
+       reg = __raw_readb(dpr);
+       __raw_writeb(reg & 0x7f, dpr);
+       iounmap(dpr);
+
+       /* Interrupt controller setup */
+       for (i = INTP0Status0; i < INTP0Status0 + 0x80; i += 0x10) {
+               ocd_writel(0x00000000, i + 0x04);
+               ocd_writel(0xffffffff, i + 0x0c);
+       }
+       ocd_writel(0x2, NMICONFIG);
+
+       ocd_writel(0x1 << (TITAN_MSGINT % 0x20),
+                  INTP0Mask0 + (0x10 * (TITAN_MSGINT / 0x20)));
+       ocd_writel((0x1 << (FPGA0_MSGINT % 0x20))
+                  | ocd_readl(INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))),
+                  INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20)));
+       ocd_writel((0x1 << (FPGA1_MSGINT % 0x20))
+                  | ocd_readl(INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))),
+                  INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20)));
+       ocd_writel((0x1 << (PHY_MSGINT % 0x20))
+                  | ocd_readl(INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))),
+                  INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20)));
+#if USB_IRQ < 10
+       ocd_writel((0x1 << (USB_MSGINT % 0x20))
+                  | ocd_readl(INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))),
+                  INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20)));
+#endif
+       /* Enable the packet FIFO, XDMA and XDMA arbiter */
+       titan_writel(0x00ff18ff, CPRR);
+
+       /*
+        * Set up the PADMUX. Power down all ethernet slices,
+        * they will be powered up and configured at device startup.
+        */
+       titan_writel(0x00878206, CPTC1R);
+       titan_writel(0x00001100, CPTC0R); /* latch PADMUX, enable WCIMODE */
+
+       /* Reset and enable the FIFO block */
+       titan_writel(0x00000001, SDRXFCIE);
+       titan_writel(0x00000001, SDTXFCIE);
+       titan_writel(0x00000100, SDRXFCIE);
+       titan_writel(0x00000000, SDTXFCIE);
+
+       /*
+        * Initialize the common interrupt shared by all components of
+        * the GPI/Ethernet subsystem.
+        */
+       titan_writel((EXCITE_PHYS_OCD >> 12), CPCFG0);
+       titan_writel(TITAN_MSGINT, CPCFG1);
+
+       /*
+        * XDMA configuration.
+        * In order for the XDMA to be sharable among multiple drivers,
+        * the setup must be done here in the platform. The reason is that
+        * this setup can only be done while the XDMA is in reset. If this
+        * were done in a driver, it would interrupt all other drivers
+        * using the XDMA.
+        */
+       titan_writel(0x80021dff, GXCFG);        /* XDMA reset */
+       titan_writel(0x00000000, CPXCISRA);
+       titan_writel(0x00000000, CPXCISRB);     /* clear pending interrupts */
+#if defined (CONFIG_HIGHMEM)
+#      error change for HIGHMEM support!
+#else
+       titan_writel(0x00000000, GXDMADRPFX);   /* buffer address prefix */
+#endif
+       titan_writel(0, GXDMA_DESCADR);
+
+       for (i = 0x5040; i <= 0x5300; i += 0x0040)
+               titan_writel(0x80080000, i);    /* reset channel */
+
+       titan_writel((0x1 << 29)                        /* no sparse tx descr. */
+                    | (0x1 << 28)                      /* no sparse rx descr. */
+                    | (0x1 << 23) | (0x1 << 24)        /* descriptor coherency */
+                    | (0x1 << 21) | (0x1 << 22)        /* data coherency */
+                    | (0x1 << 17)
+                    | 0x1dff,
+                    GXCFG);
+
+#if defined(CONFIG_SMP)
+#      error No SMP support
+#else
+       /* All interrupts go to core #0 only. */
+       titan_writel(0x1f007fff, CPDST0A);
+       titan_writel(0x00000000, CPDST0B);
+       titan_writel(0x0000ff3f, CPDST1A);
+       titan_writel(0x00000000, CPDST1B);
+       titan_writel(0x00ffffff, CPXDSTA);
+       titan_writel(0x00000000, CPXDSTB);
+#endif
+
+       /* Enable DUART interrupts, disable everything else. */
+       titan_writel(0x04000000, CPGIG0ER);
+       titan_writel(0x000000c0, CPGIG1ER);
+
+       excite_procfs_init();
+       return 0;
+}
+
+void __init plat_setup(void)
+{
+       volatile u32 * const boot_ocd_base = (u32 *) 0xbf7fc000;
+
+       /* Announce RAM to system */
+       add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
+
+       /* Set up timer initialization hooks */
+       board_time_init = excite_timer_init;
+       board_timer_setup = excite_timer_setup;
+
+       /* Set up the peripheral address map */
+       *(boot_ocd_base + (LKB9 / sizeof (u32))) = 0;
+       *(boot_ocd_base + (LKB10 / sizeof (u32))) = 0;
+       *(boot_ocd_base + (LKB11 / sizeof (u32))) = 0;
+       *(boot_ocd_base + (LKB12 / sizeof (u32))) = 0;
+       wmb();
+       *(boot_ocd_base + (LKB0 / sizeof (u32))) = EXCITE_PHYS_OCD >> 4;
+       wmb();
+
+       ocd_writel((EXCITE_PHYS_TITAN >> 4) | 0x1UL, LKB5);
+       ocd_writel(((EXCITE_SIZE_TITAN >> 4) & 0x7fffff00) - 0x100, LKM5);
+       ocd_writel((EXCITE_PHYS_SCRAM >> 4) | 0x1UL, LKB13);
+       ocd_writel(((EXCITE_SIZE_SCRAM >> 4) & 0xffffff00) - 0x100, LKM13);
+
+       /* Local bus slot #0 */
+       ocd_writel(0x00040510, LDP0);
+       ocd_writel((EXCITE_PHYS_BOOTROM >> 4) | 0x1UL, LKB9);
+       ocd_writel(((EXCITE_SIZE_BOOTROM >> 4) & 0x03ffff00) - 0x100, LKM9);
+
+       /* Local bus slot #2 */
+       ocd_writel(0x00000330, LDP2);
+       ocd_writel((EXCITE_PHYS_FPGA >> 4) | 0x1, LKB11);
+       ocd_writel(((EXCITE_SIZE_FPGA >> 4) - 0x100) & 0x03ffff00, LKM11);
+
+       /* Local bus slot #3 */
+       ocd_writel(0x00123413, LDP3);
+       ocd_writel((EXCITE_PHYS_NAND >> 4) | 0x1, LKB12);
+       ocd_writel(((EXCITE_SIZE_NAND >> 4) - 0x100) & 0x03ffff00, LKM12);
+}
+
+
+
+console_initcall(excite_init_console);
+arch_initcall(excite_platform_init);
+
+EXPORT_SYMBOL(titan_lock);
+EXPORT_SYMBOL(titan_irqflags);
+EXPORT_SYMBOL(titan_irq);
+EXPORT_SYMBOL(ocd_base);
+EXPORT_SYMBOL(titan_base);
index 45c2d27c7564f4fabc2579c8529bd808af7e5ed0..300797d5f558178fec6cdd2af5174b4b30971e58 100644 (file)
@@ -41,3 +41,8 @@ void __init cobalt_early_console(void)
 
        printk("Cobalt: early console registered\n");
 }
+
+void __init disable_early_printk(void)
+{
+       unregister_console(&cons_info);
+}
index 4f9ea121002389cdbd5ce874017efbc0e40d12af..ca719d6398bd81b06689288b233f13873d210e04 100644 (file)
@@ -68,19 +68,46 @@ static void __init cobalt_timer_setup(struct irqaction *irq)
 extern struct pci_ops gt64111_pci_ops;
 
 static struct resource cobalt_mem_resource = {
-       "PCI memory", GT64111_MEM_BASE, GT64111_MEM_END, IORESOURCE_MEM
+       .start  = GT64111_MEM_BASE,
+       .end    = GT64111_MEM_END,
+       .name   = "PCI memory",
+       .flags  = IORESOURCE_MEM
 };
 
 static struct resource cobalt_io_resource = {
-       "PCI I/O", 0x1000, 0xffff, IORESOURCE_IO
+       .start  = 0x1000,
+       .end    = 0xffff,
+       .name   = "PCI I/O",
+       .flags  = IORESOURCE_IO
 };
 
 static struct resource cobalt_io_resources[] = {
-       { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
-       { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
-       { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
-       { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
-       { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+       {
+               .start  = 0x00,
+               .end    = 0x1f,
+               .name   = "dma1",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x40,
+               .end    = 0x5f,
+               .name   = "timer",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x60,
+               .end    = 0x6f,
+               .name   = "keyboard",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x80,
+               .end    = 0x8f,
+               .name   = "dma page reg",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0xc0,
+               .end    = 0xdf,
+               .name   = "dma2",
+               .flags  = IORESOURCE_BUSY
+       },
 };
 
 #define COBALT_IO_RESOURCES (sizeof(cobalt_io_resources)/sizeof(struct resource))
@@ -93,7 +120,7 @@ static struct pci_controller cobalt_pci_controller = {
        .io_offset      = 0 - GT64111_IO_BASE
 };
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        static struct uart_port uart;
        unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0);
index 4b080bcb258fe65c4b502a8ae1833ac792728339..0cc1b3c5195978f5cd395f0d33448663712a780e 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_ATLAS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -143,6 +141,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# 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=100
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index d85cda58d6509a0f00b81a3c850d994de1d68302..dabf90a94b2103a93e09b6fc56779d5c2cfd485d 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -145,6 +143,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_PREEMPT_NONE=y
index ca0af1683a00ecb4f9e52bfa8db194a1a0ee7062..aeb7be804799f06c04b14f2c5bb344faee8d3caa 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -132,6 +130,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 7d269e609282e53c64ea0279b4449a50bdca9781..d680d3e17112f38909ab4a80375adffa30bb1bc5 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_COBALT=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -129,6 +127,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 579b665e33392eaa9342dd93727d974e9cee0fa3..6a7aa401462fd3bc824d595625d793737c5e8bb4 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_DB1000=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index e5eb53867422f1ff792a8ca63d3a0ea3f628c1f0..5c2da563e528cbd2559d6f5d7575e4cd76302afd 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_DB1100=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index a43fb2329fd5bd66b657da637c3bd2aefd87e6da..85ef90ce0944d0d0a4d027b7641f000bb2a48f2b 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_DB1200=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index ad632d87c4ef5f58e9e06fe51a78fe79e6cf6f88..6f757d8a5a6c75b3263afc298994d9c3082dc40d 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_DB1500=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -132,6 +130,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 8130e23dc25503a7b2e5972a7b848db22ad4449c..da4c7e811bef5a644ea1557fcd8559908664c48b 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_DB1550=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -131,6 +129,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 8c911b67141507651e027616b138885a999c219d..c1c6bfee970ea9f280a793c65a508377c5a2e86c 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 CONFIG_DDB5477=y
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -129,6 +127,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index d838496e114f0622ddfe982bf44b50d8a5532ad6..d5d0d3faae94adadedae912508d067a0cfc7e17d 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MACH_DECSTATION=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -128,6 +126,17 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_128=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_128HZ=y
+CONFIG_SYS_SUPPORTS_256HZ=y
+CONFIG_SYS_SUPPORTS_1024HZ=y
+CONFIG_HZ=128
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 0760f43189104a44c5d003dcbe959d456ad9b40c..439677ba751cdc1ab991da96385cd93e62783944 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
new file mode 100644 (file)
index 0000000..01f29f4
--- /dev/null
@@ -0,0 +1,1207 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Sun Jun 18 13:46:53 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_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+CONFIG_MARKEINS=y
+# 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_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_EMMA2RH=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+CONFIG_CPU_R5000=y
+# 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_R5000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_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_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# 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_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=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_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# 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=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_FWMARK is not set
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=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=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER 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
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM 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=0x1e000000
+CONFIG_MTD_PHYSMAP_LEN=0x02000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# 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=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB 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
+# CONFIG_LAN_SAA9730 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
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# 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_RTC=m
+CONFIG_GEN_RTC=m
+CONFIG_GEN_RTC_X=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
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_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_NFORCE2 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=y
+# CONFIG_I2C_DEBUG_ALGO is not set
+CONFIG_I2C_DEBUG_BUS=y
+# 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_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_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=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
+
+#
+# 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
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT 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_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+# 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=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT=""
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS0,115200 mem=192m ip=bootp root=/dev/nfs rw"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
index 7067f608b22c7cc7dce54e5acf8f740a9cf5d480..5248a1d8131d45cf28313e5cb7b49a893124c7a4 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_EV64120=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -131,6 +129,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 00b56ed0e6383f8ec7b66fa7dc0b9c76f2d6b7f3..4858491ce669e704426f8d9578cd233dccdd9d3b 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_EV96100=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -135,6 +133,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
new file mode 100644 (file)
index 0000000..f2ce64c
--- /dev/null
@@ -0,0 +1,1220 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16-rc4
+# Thu Feb 23 13:15:27 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_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD 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_BASLER_EXCITE=y
+# CONFIG_BASLER_EXCITE_PROTOTYPE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_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_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_COHERENT=y
+CONFIG_SERIAL_RM9000=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_IRQ_CPU_RM9K=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_RM9000=y
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_RM9000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED 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_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_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_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=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_LEGACY_PROC is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# 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=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER 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 is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI 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_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD 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=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_BASLER_EXCITE=y
+# CONFIG_MTD_NAND_BASLER_EXCITE_RDNBY is not set
+# CONFIG_MTD_NAND_BASLER_EXCITE_PERF is not set
+# 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_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=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+
+#
+# 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 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_TITAN_GE is not set
+CONFIG_RM9K_GE=m
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_WDT_RM9K_GPI=m
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_DD=y
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=m
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_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 Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_MON is not set
+
+#
+# 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_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_ARTTFT=m
+# CONFIG_USB_ARTTOUCH is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# EDAC - error detection and reporting (RAS)
+#
+
+#
+# eXcite frame capture support
+#
+CONFIG_EXCITE_FCAP=m
+CONFIG_EXCITE_FCAP_GPI=m
+
+#
+# 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_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=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=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_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=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# 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=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_DES 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 is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
index 607e2985ffe3b927467151a09f7f6f69d28faf1b..879ba1ad99caf2076bc7c56a302c6166679d02c9 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
index f724b4b2ecf271ddeef531842bcbe6696215f90b..bb142680643075c64fc42ccb0b8ed74dfe86e5dd 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -63,7 +61,7 @@ CONFIG_SGI_IP27=y
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
-# CONFIG_SGI_SN0_N_MODE is not set
+# CONFIG_SGI_SN_N_MODE is not set
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_NUMA=y
 # CONFIG_MAPPED_KERNEL is not set
@@ -135,6 +133,15 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_NEED_MULTIPLE_NODES=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_MIGRATION=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=64
index 8f11d3565b2d51d2793e16fb8e057f112552e8ab..31b3c92a384118afe825816e7b81b218661a0be8 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
index 757adf23853d297b129d3c66f877a03b9f5f9d34..809bae9013ac6517814fd22d7396d92fb8e0e1ba 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_ITE8172=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 021761a8a237c00c71a8af5500cd03e1f4b069c9..55108fd678444aacbece191a9230561fbf2b5df1 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_IVR=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -127,6 +125,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 08f6c30b0abce6d3a48c0717b1e0b11fe49ec1c8..ef2843436057d9c351a909fff015fd4631812201 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MOMENCO_JAGUAR_ATX=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_SMP is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
index 38b1e026e10d745e562ac16d62883d44b73e79ec..5ef5a08289a57fa51b4da033ed9b39bfa40937e7 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -125,6 +123,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 4d25990a0a05ee0ea7b69002574fe152a4250080..eabcff26fc0edc9b369b0eff06fdd64cf6943941 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_LASAT=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -134,6 +132,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 977f52be51dc4bb369ee197c9261b467ca9ce249..b73cff0d83ca058d951f50deb19bbdcd536def38 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_MALTA=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -154,6 +152,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# 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=100
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 00560e0143f1be7eea26c3ff3caf28b578534d6e..8dd27b55413d7ed40e5fbfd05fcf6f43e5cb4217 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_SIM=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -138,6 +136,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 286a018375b2367853fa1dea237e649f7540fd03..5d6ff3c352c94e84aa64155c86c856f7cbff5f97 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -132,6 +130,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 1ce4310fd92af245e3643c198444e648c4fdafa7..fe5e3dd915f58ab5ee11e5cf0a5c1300fa5cfaa7 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MOMENCO_OCELOT_3=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_SMP is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
index 8a6aa5012f89f9319afd722d21ba2b891508ad48..f4a33ce47e500bdf35acc7bf7b911593ede1e687 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MOMENCO_OCELOT_C=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -133,6 +131,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index f9ee35eeb76270bf19fc3bd17e3cb79bacfd4c98..21dea9549febd02f6802749273beca48544dd5ad 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MOMENCO_OCELOT=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -137,6 +135,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index b48bdee2411fc294c68fe3342486f1c3442cd72e..c63b1ca8c8b3085b4adbc311d0be2b39d6c25057 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MOMENCO_OCELOT_G=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 01aac40634b41c03088c0d078bccabebafdc02e4..6f5c7261e9deb709a7ed537d13b73158bfd627bd 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_PB1100=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -132,6 +130,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 398c3c265b9fda6a3aa704c5fb880dd4a6e29e39..5676f3747fd553717602356f47946f858d8d4b74 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_PB1500=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -131,6 +129,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index ea282a53bb66b26f1166376f5544593c89111af1..a1c479fa613b08692f9757a7d80aa7556d62bc05 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_PB1550=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -131,6 +129,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 4c57e564db0b037ffb6a64fc2984c545ecda1b52..b2d991b80309a6bdb0c93b4f2658cb48d4694aed 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 CONFIG_PNX8550_JBS=y
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 3c8f35162fecaa73f8e9593fa8a89f5097242863..fe092ac92e894ea16150b970a2ab5c834662bdfd 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 CONFIG_PNX8550_V2PCI=y
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 4bcc01dea041d2bb292a6cf4624e0caaaf3ab0d0..db8701344cee416e33f72d072586aab46f268b82 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -128,6 +126,15 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_SMP is not set
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# 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=100
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 3d441932e43a416357abdf20ca649df8b08d69a1..b16731f3684b9829c98b930d076ecd2d75f4bcee 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -138,6 +136,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index edfb9679a25af6fc98766a1c622a16949486005e..8b0dd8651264bbdb1f504e8ac44debc4c80aeac0 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -138,6 +136,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
index e388a3dae0a98c8ecc0889f23dac09969808e76d..ff34ed66fe6594ab0941fda18872e60939ab38d5 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -149,6 +147,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PREEMPT_NONE=y
index 6b8a6a416a25a935a4bcb392fe05f1a253e5a653..77edeae7f018d1eef71f1816c480bbd0d5ed5ea6 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS_SEAD=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -134,6 +132,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index dba0bdcdcf2962da64fafa517caba45b1329edab..6aa229d548510b4df6cd13b09bd44472232b0ecc 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -134,6 +132,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 5a924c1a5803a0b8d5c17bbe20370e97a862f475..a187b1f0004cec3cd94a7c5876198830e698e5c2 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -134,6 +132,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index 9f215ea350dcccd48134899bd5a03a4061ecaaa0..258457fcbe11e22e595c2b4d603244a825896258 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -135,6 +133,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
index ac7765eb8da755b27c40266490d0c97fb4ba22a0..68af54f746e124c72aa037acb4f727c341e5dca5 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
similarity index 68%
rename from arch/mips/configs/ddb5476_defconfig
rename to arch/mips/configs/wrppmc_defconfig
index 8d88ac1bbfeb71a6c3b87e23f29b55ed52123277..40572a3c8cac30ada0e38113f83d223b81472747 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc2
-# Mon Apr 24 14:51:00 2006
+# Linux kernel version: 2.6.16.11
+# Fri May  5 17:11:22 2006
 #
 CONFIG_MIPS=y
 
@@ -32,6 +32,7 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_ATLAS is not set
 # CONFIG_MIPS_MALTA is not set
 # CONFIG_MIPS_SEAD is not set
+CONFIG_WR_PPMC=y
 # CONFIG_MIPS_SIM is not set
 # CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
@@ -41,8 +42,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-CONFIG_DDB5476=y
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -64,24 +63,23 @@ CONFIG_DDB5476=y
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_I8259=y
-# CONFIG_CPU_BIG_ENDIAN is not set
-CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
-CONFIG_DDB5XXX_COMMON=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
-CONFIG_HAVE_STD_PC_SERIAL_PORT=y
 
 #
 # CPU selection
 #
-# CONFIG_CPU_MIPS32_R1 is not set
+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
@@ -92,7 +90,7 @@ CONFIG_HAVE_STD_PC_SERIAL_PORT=y
 # CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_TX49XX is not set
 # CONFIG_CPU_R5000 is not set
-CONFIG_CPU_R5432=y
+# CONFIG_CPU_R5432 is not set
 # CONFIG_CPU_R6000 is not set
 # CONFIG_CPU_NEVADA is not set
 # CONFIG_CPU_R8000 is not set
@@ -100,11 +98,16 @@ CONFIG_CPU_R5432=y
 # CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5432=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_CPU_MIPS64_R1=y
+CONFIG_SYS_HAS_CPU_NEVADA=y
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
 #
 # Kernel type
@@ -115,11 +118,15 @@ 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 is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED 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
@@ -129,6 +136,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -145,27 +161,31 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
 #
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
+# CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
-CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_EPOLL=y
+# CONFIG_EPOLL is not set
 CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -174,14 +194,18 @@ CONFIG_BASE_SMALL=0
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_KMOD is not set
 
 #
 # Block layer
 #
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -201,7 +225,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
-CONFIG_ISA=y
+CONFIG_PCI_LEGACY_PROC=y
 CONFIG_MMU=y
 
 #
@@ -212,13 +236,16 @@ CONFIG_MMU=y
 #
 # PCI Hotplug Support
 #
-# CONFIG_HOTPLUG_PCI is not set
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
 
 #
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=y
 CONFIG_TRAD_SIGNALS=y
 
 #
@@ -231,35 +258,33 @@ CONFIG_NET=y
 #
 # CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
+CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-CONFIG_NET_KEY=y
+# CONFIG_NET_KEY is not set
 CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_FIB_HASH=y
 CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
+CONFIG_IP_PNP_RARP=y
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+CONFIG_ARPD=y
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -301,13 +326,7 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -318,13 +337,12 @@ CONFIG_WIRELESS_EXT=y
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -339,7 +357,6 @@ CONFIG_PROC_EVENTS=y
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
@@ -352,52 +369,24 @@ CONFIG_PROC_EVENTS=y
 # 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 is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_IDE_ARM is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
-CONFIG_RAID_ATTRS=y
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
 #
 # Multi-device support (RAID and LVM)
 #
@@ -440,34 +429,48 @@ CONFIG_PHYLIB=y
 #
 # MII PHY device drivers
 #
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+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_NET_VENDOR_SMC is not set
 # CONFIG_DM9000 is not set
-# CONFIG_NET_VENDOR_RACAL is not set
 
 #
 # Tulip family network device support
 #
 # CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
 # CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI 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=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -483,6 +486,7 @@ CONFIG_NET_ETHERNET=y
 # 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
 
@@ -529,46 +533,18 @@ CONFIG_NET_ETHERNET=y
 #
 # Input device support
 #
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+# CONFIG_INPUT is not set
 
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
+# 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 is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -576,9 +552,8 @@ CONFIG_HW_CONSOLE=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -600,8 +575,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
+CONFIG_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -637,13 +611,19 @@ CONFIG_LEGACY_PTY_COUNT=256
 #
 # Hardware Monitoring support
 #
-# CONFIG_HWMON is not set
+CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
 # Misc devices
 #
 
+#
+# Multimedia Capabilities Port drivers
+#
+
 #
 # Multimedia devices
 #
@@ -657,49 +637,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 #
 # Graphics support
 #
-CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_MACMODES is not set
-CONFIG_FB_FIRMWARE_EDID=y
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
 
 #
 # Sound
@@ -711,7 +649,6 @@ CONFIG_DUMMY_CONSOLE=y
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_USB is not set
 
 #
@@ -728,19 +665,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 #
 # CONFIG_MMC is not set
 
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
 #
 # InfiniBand support
 #
@@ -750,17 +674,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
-#
-# Real Time Clock
-#
-# 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_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
@@ -774,7 +691,7 @@ CONFIG_INOTIFY=y
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -795,9 +712,10 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -821,12 +739,14 @@ CONFIG_RAMFS=y
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
@@ -861,46 +781,19 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="ip=any"
+CONFIG_CMDLINE="console=ttyS0,115200n8"
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
 
 #
 # Hardware crypto devices
@@ -909,9 +802,7 @@ CONFIG_CRYPTO_CRC32C=y
 #
 # Library routines
 #
-# CONFIG_CRC_CCITT is not set
+CONFIG_CRC_CCITT=y
 CONFIG_CRC16=y
 CONFIG_CRC32=y
 CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
index b52d709de962b016a8021d508bae9fba2b2cc3e6..7ece2c008e9b5644381e8e249e3ef68cbbb23cb6 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 CONFIG_PMC_YOSEMITE=y
@@ -130,6 +128,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PREEMPT_NONE=y
index b8d1f7489f3b26c35e34a43fdddf659d4c986e81..00c62c1c28a35baafc6201f199c0f6241b4edffd 100644 (file)
@@ -56,13 +56,7 @@ void __init prom_init(void)
 
        mips_machgroup = MACH_GROUP_NEC_DDB;
 
-#if defined(CONFIG_DDB5074)
-       mips_machtype = MACH_NEC_DDB5074;
-       add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
-#elif defined(CONFIG_DDB5476)
-       mips_machtype = MACH_NEC_DDB5476;
-       add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
-#elif defined(CONFIG_DDB5477)
+#if defined(CONFIG_DDB5477)
        ddb5477_runtime_detection();
        add_memory_region(0, board_ram_size, BOOT_MEM_RAM);
 #endif
diff --git a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile
deleted file mode 100644 (file)
index 304c021..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines
-# under Linux.
-#
-
-obj-y                  += setup.o irq.o nile4_pic.o
-
-EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c
deleted file mode 100644 (file)
index 60c087b..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *  arch/mips/ddb5074/irq.c -- NEC DDB Vrc-5074 interrupt routines
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-
-#include <asm/i8259.h>
-#include <asm/io.h>
-#include <asm/irq_cpu.h>
-#include <asm/ptrace.h>
-#include <asm/nile4.h>
-#include <asm/ddb5xxx/ddb5xxx.h>
-#include <asm/ddb5xxx/ddb5074.h>
-
-
-static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
-
-#define M1543_PNP_CONFIG       0x03f0  /* PnP Config Port */
-#define M1543_PNP_INDEX                0x03f0  /* PnP Index Port */
-#define M1543_PNP_DATA         0x03f1  /* PnP Data Port */
-
-#define M1543_PNP_ALT_CONFIG   0x0370  /* Alternative PnP Config Port */
-#define M1543_PNP_ALT_INDEX    0x0370  /* Alternative PnP Index Port */
-#define M1543_PNP_ALT_DATA     0x0371  /* Alternative PnP Data Port */
-
-#define M1543_INT1_MASTER_CTRL 0x0020  /* INT_1 (master) Control Register */
-#define M1543_INT1_MASTER_MASK 0x0021  /* INT_1 (master) Mask Register */
-
-#define M1543_INT1_SLAVE_CTRL  0x00a0  /* INT_1 (slave) Control Register */
-#define M1543_INT1_SLAVE_MASK  0x00a1  /* INT_1 (slave) Mask Register */
-
-#define M1543_INT1_MASTER_ELCR 0x04d0  /* INT_1 (master) Edge/Level Control */
-#define M1543_INT1_SLAVE_ELCR  0x04d1  /* INT_1 (slave) Edge/Level Control */
-
-
-static void m1543_irq_setup(void)
-{
-       /*
-        *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
-        *  the possible IO sources in the M1543 are in use by us.  We will
-        *  use the following mapping:
-        *
-        *      IRQ1  - keyboard (default set by M1543)
-        *      IRQ3  - reserved for UART B (default set by M1543) (note that
-        *              the schematics for the DDB Vrc-5074 board seem to
-        *              indicate that IRQ3 is connected to the DS1386
-        *              watchdog timer interrupt output so we might have
-        *              a conflict)
-        *      IRQ4  - reserved for UART A (default set by M1543)
-        *      IRQ5  - parallel (default set by M1543)
-        *      IRQ8  - DS1386 time of day (RTC) interrupt
-        *      IRQ12 - mouse
-        */
-
-       /*
-        *  Assing mouse interrupt to IRQ12
-        */
-
-       /* Enter configuration mode */
-       outb(0x51, M1543_PNP_CONFIG);
-       outb(0x23, M1543_PNP_CONFIG);
-
-       /* Select logical device 7 (Keyboard) */
-       outb(0x07, M1543_PNP_INDEX);
-       outb(0x07, M1543_PNP_DATA);
-
-       /* Select IRQ12 */
-       outb(0x72, M1543_PNP_INDEX);
-       outb(0x0c, M1543_PNP_DATA);
-
-       outb(0x30, M1543_PNP_INDEX);
-       printk("device 7, 0x30: %02x\n",inb(M1543_PNP_DATA));
-
-       outb(0x70, M1543_PNP_INDEX);
-       printk("device 7, 0x70: %02x\n",inb(M1543_PNP_DATA));
-
-       /* Leave configration mode */
-       outb(0xbb, M1543_PNP_CONFIG);
-
-
-}
-
-static void ddb_local0_irqdispatch(struct pt_regs *regs)
-{
-       u32 mask;
-       int nile4_irq;
-
-       mask = nile4_get_irq_stat(0);
-
-       /* Handle the timer interrupt first */
-#if 0
-       if (mask & (1 << NILE4_INT_GPT)) {
-               do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
-               mask &= ~(1 << NILE4_INT_GPT);
-       }
-#endif
-       for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
-               if (mask & 1) {
-                       if (nile4_irq == NILE4_INT_INTE) {
-                               int i8259_irq;
-
-                               nile4_clear_irq(NILE4_INT_INTE);
-                               i8259_irq = nile4_i8259_iack();
-                               do_IRQ(i8259_irq, regs);
-                       } else
-                               do_IRQ(nile4_to_irq(nile4_irq), regs);
-
-               }
-}
-
-static void ddb_local1_irqdispatch(void)
-{
-       printk("ddb_local1_irqdispatch called\n");
-}
-
-static void ddb_buserror_irq(void)
-{
-       printk("ddb_buserror_irq called\n");
-}
-
-static void ddb_8254timer_irq(void)
-{
-       printk("ddb_8254timer_irq called\n");
-}
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
-{
-       unsigned int pending = read_c0_cause() & read_c0_status();
-
-       if (pending & CAUSEF_IP2)
-               ddb_local0_irqdispatch(regs);
-       else if (pending & CAUSEF_IP3)
-               ddb_local1_irqdispatch();
-       else if (pending & CAUSEF_IP6)
-               ddb_buserror_irq();
-       else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
-               ddb_8254timer_irq();
-}
-
-void __init arch_init_irq(void)
-{
-       /* setup cascade interrupts */
-       setup_irq(NILE4_IRQ_BASE  + NILE4_INT_INTE, &irq_cascade);
-       setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
-
-       nile4_irq_setup(NILE4_IRQ_BASE);
-       m1543_irq_setup();
-       init_i8259_irqs();
-
-
-       printk("CPU_IRQ_BASE: %d\n",CPU_IRQ_BASE);
-
-       mips_cpu_irq_init(CPU_IRQ_BASE);
-
-       printk("enabling 8259 cascade\n");
-
-       ddb5074_led_hex(0);
-
-       /* Enable the interrupt cascade */
-       nile4_enable_irq(NILE4_IRQ_BASE+IRQ_I8259_CASCADE);
-}
diff --git a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
deleted file mode 100644 (file)
index 8743ffc..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- *  arch/mips/ddb5476/nile4.c --
- *     low-level PIC code for NEC Vrc-5476 (Nile 4)
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  Copyright 2001 MontaVista Software Inc.
- *  Author: jsun@mvista.com or jsun@junsun.net
- *
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-
-#include <asm/addrspace.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-static int irq_base;
-
-/*
- *  Interrupt Programming
- */
-void nile4_map_irq(int nile4_irq, int cpu_irq)
-{
-       u32 offset, t;
-
-       offset = DDB_INTCTRL;
-       if (nile4_irq >= 8) {
-               offset += 4;
-               nile4_irq -= 8;
-       }
-       t = ddb_in32(offset);
-       t &= ~(7 << (nile4_irq * 4));
-       t |= cpu_irq << (nile4_irq * 4);
-       ddb_out32(offset, t);
-}
-
-void nile4_map_irq_all(int cpu_irq)
-{
-       u32 all, t;
-
-       all = cpu_irq;
-       all |= all << 4;
-       all |= all << 8;
-       all |= all << 16;
-       t = ddb_in32(DDB_INTCTRL);
-       t &= 0x88888888;
-       t |= all;
-       ddb_out32(DDB_INTCTRL, t);
-       t = ddb_in32(DDB_INTCTRL + 4);
-       t &= 0x88888888;
-       t |= all;
-       ddb_out32(DDB_INTCTRL + 4, t);
-}
-
-void nile4_enable_irq(unsigned int nile4_irq)
-{
-       u32 offset, t;
-
-       nile4_irq-=irq_base;
-
-       ddb5074_led_hex(8);
-
-       offset = DDB_INTCTRL;
-       if (nile4_irq >= 8) {
-               offset += 4;
-               nile4_irq -= 8;
-       }
-       ddb5074_led_hex(9);
-       t = ddb_in32(offset);
-       ddb5074_led_hex(0xa);
-       t |= 8 << (nile4_irq * 4);
-       ddb_out32(offset, t);
-       ddb5074_led_hex(0xb);
-}
-
-void nile4_disable_irq(unsigned int nile4_irq)
-{
-       u32 offset, t;
-
-       nile4_irq-=irq_base;
-
-       offset = DDB_INTCTRL;
-       if (nile4_irq >= 8) {
-               offset += 4;
-               nile4_irq -= 8;
-       }
-       t = ddb_in32(offset);
-       t &= ~(8 << (nile4_irq * 4));
-       ddb_out32(offset, t);
-}
-
-void nile4_disable_irq_all(void)
-{
-       ddb_out32(DDB_INTCTRL, 0);
-       ddb_out32(DDB_INTCTRL + 4, 0);
-}
-
-u16 nile4_get_irq_stat(int cpu_irq)
-{
-       return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2);
-}
-
-void nile4_enable_irq_output(int cpu_irq)
-{
-       u32 t;
-
-       t = ddb_in32(DDB_INTSTAT1 + 4);
-       t |= 1 << (16 + cpu_irq);
-       ddb_out32(DDB_INTSTAT1, t);
-}
-
-void nile4_disable_irq_output(int cpu_irq)
-{
-       u32 t;
-
-       t = ddb_in32(DDB_INTSTAT1 + 4);
-       t &= ~(1 << (16 + cpu_irq));
-       ddb_out32(DDB_INTSTAT1, t);
-}
-
-void nile4_set_pci_irq_polarity(int pci_irq, int high)
-{
-       u32 t;
-
-       t = ddb_in32(DDB_INTPPES);
-       if (high)
-               t &= ~(1 << (pci_irq * 2));
-       else
-               t |= 1 << (pci_irq * 2);
-       ddb_out32(DDB_INTPPES, t);
-}
-
-void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
-{
-       u32 t;
-
-       t = ddb_in32(DDB_INTPPES);
-       if (level)
-               t |= 2 << (pci_irq * 2);
-       else
-               t &= ~(2 << (pci_irq * 2));
-       ddb_out32(DDB_INTPPES, t);
-}
-
-void nile4_clear_irq(int nile4_irq)
-{
-       nile4_irq-=irq_base;
-       ddb_out32(DDB_INTCLR, 1 << nile4_irq);
-}
-
-void nile4_clear_irq_mask(u32 mask)
-{
-       ddb_out32(DDB_INTCLR, mask);
-}
-
-u8 nile4_i8259_iack(void)
-{
-       u8 irq;
-       u32 reg;
-
-       /* Set window 0 for interrupt acknowledge */
-       reg = ddb_in32(DDB_PCIINIT0);
-
-       ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
-       irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
-       /* restore window 0 for PCI I/O space */
-       // ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
-       ddb_out32(DDB_PCIINIT0, reg);
-
-       /* i8269.c set the base vector to be 0x0 */
-       return irq ;
-}
-
-static unsigned int nile4_irq_startup(unsigned int irq) {
-
-       nile4_enable_irq(irq);
-       return 0;
-
-}
-
-static void nile4_ack_irq(unsigned int irq) {
-
-    ddb5074_led_hex(4);
-
-       nile4_clear_irq(irq);
-    ddb5074_led_hex(2);
-       nile4_disable_irq(irq);
-
-    ddb5074_led_hex(0);
-}
-
-static void nile4_irq_end(unsigned int irq) {
-
-       ddb5074_led_hex(3);
-       if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-       ddb5074_led_hex(5);
-               nile4_enable_irq(irq);
-       ddb5074_led_hex(7);
-       }
-
-       ddb5074_led_hex(1);
-}
-
-#define nile4_irq_shutdown nile4_disable_irq
-
-static hw_irq_controller nile4_irq_controller = {
-       .typename = "nile4",
-       .startup = nile4_irq_startup,
-       .shutdown = nile4_irq_shutdown,
-       .enable = nile4_enable_irq,
-       .disable = nile4_disable_irq,
-       .ack = nile4_ack_irq,
-       .end = nile4_irq_end,
-};
-
-void nile4_irq_setup(u32 base) {
-
-       int i;
-
-       irq_base=base;
-
-       /* Map all interrupts to CPU int #0 */
-       nile4_map_irq_all(0);
-
-       /* PCI INTA#-E# must be level triggered */
-       nile4_set_pci_irq_level_or_edge(0, 1);
-       nile4_set_pci_irq_level_or_edge(1, 1);
-       nile4_set_pci_irq_level_or_edge(2, 1);
-       nile4_set_pci_irq_level_or_edge(3, 1);
-       nile4_set_pci_irq_level_or_edge(4, 1);
-
-       /* PCI INTA#-D# must be active low, INTE# must be active high */
-       nile4_set_pci_irq_polarity(0, 0);
-       nile4_set_pci_irq_polarity(1, 0);
-       nile4_set_pci_irq_polarity(2, 0);
-       nile4_set_pci_irq_polarity(3, 0);
-       nile4_set_pci_irq_polarity(4, 1);
-
-
-       for (i = 0; i < 16; i++) {
-               nile4_clear_irq(i);
-               nile4_disable_irq(i);
-       }
-
-       /* Enable CPU int #0 */
-       nile4_enable_irq_output(0);
-
-       for (i= base; i< base + NUM_NILE4_INTERRUPTS; i++) {
-               irq_desc[i].status = IRQ_DISABLED;
-               irq_desc[i].action = NULL;
-               irq_desc[i].depth = 1;
-               irq_desc[i].handler = &nile4_irq_controller;
-       }
-}
-
-#if defined(CONFIG_RUNTIME_DEBUG)
-void nile4_dump_irq_status(void)
-{
-       printk(KERN_DEBUG "
-              CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4),
-              (void *) ddb_in32(DDB_CPUSTAT));
-       printk(KERN_DEBUG "
-              INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4),
-              (void *) ddb_in32(DDB_INTCTRL));
-       printk(KERN_DEBUG
-              "INTSTAT0 = %p:%p\n",
-              (void *) ddb_in32(DDB_INTSTAT0 + 4),
-              (void *) ddb_in32(DDB_INTSTAT0));
-       printk(KERN_DEBUG
-              "INTSTAT1 = %p:%p\n",
-              (void *) ddb_in32(DDB_INTSTAT1 + 4),
-              (void *) ddb_in32(DDB_INTSTAT1));
-       printk(KERN_DEBUG
-              "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4),
-              (void *) ddb_in32(DDB_INTCLR));
-       printk(KERN_DEBUG
-              "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4),
-              (void *) ddb_in32(DDB_INTPPES));
-}
-
-#endif
diff --git a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c
deleted file mode 100644 (file)
index 91456b0..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *  arch/mips/ddb5074/setup.c -- NEC DDB Vrc-5074 setup routines
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <linux/init.h>
-#include <linux/kbd_ll.h>
-#include <linux/kernel.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/pm.h>
-
-#include <asm/addrspace.h>
-#include <asm/bcache.h>
-#include <asm/irq.h>
-#include <asm/reboot.h>
-#include <asm/gdb-stub.h>
-#include <asm/time.h>
-#include <asm/nile4.h>
-#include <asm/ddb5xxx/ddb5074.h>
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
-
-static void ddb_machine_restart(char *command)
-{
-       u32 t;
-
-       /* PCI cold reset */
-       t = nile4_in32(NILE4_PCICTRL + 4);
-       t |= 0x40000000;
-       nile4_out32(NILE4_PCICTRL + 4, t);
-       /* CPU cold reset */
-       t = nile4_in32(NILE4_CPUSTAT);
-       t |= 1;
-       nile4_out32(NILE4_CPUSTAT, t);
-       /* Call the PROM */
-       back_to_prom();
-}
-
-static void ddb_machine_halt(void)
-{
-       printk("DDB Vrc-5074 halted.\n");
-       do {
-       } while (1);
-}
-
-static void ddb_machine_power_off(void)
-{
-       printk("DDB Vrc-5074 halted. Please turn off the power.\n");
-       do {
-       } while (1);
-}
-
-extern void rtc_ds1386_init(unsigned long base);
-
-extern void (*board_timer_setup) (struct irqaction * irq);
-
-static void __init ddb_timer_init(struct irqaction *irq)
-{
-       /* set the clock to 1 Hz */
-       nile4_out32(NILE4_T2CTRL, 1000000);
-       /* enable the General-Purpose Timer */
-       nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
-       /* reset timer */
-       nile4_out32(NILE4_T2CNTR, 0);
-       /* enable interrupt */
-       setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
-       nile4_enable_irq(nile4_to_irq(NILE4_INT_GPT));
-       change_c0_status(ST0_IM,
-                         IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
-
-}
-
-static void __init ddb_time_init(void)
-{
-       /* we have ds1396 RTC chip */
-       rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
-}
-
-
-
-void __init plat_setup(void)
-{
-       set_io_port_base(NILE4_PCI_IO_BASE);
-       isa_slot_offset = NILE4_PCI_MEM_BASE;
-       board_timer_setup = ddb_timer_init;
-       board_time_init = ddb_time_init;
-
-
-       _machine_restart = ddb_machine_restart;
-       _machine_halt = ddb_machine_halt;
-       pm_power_off = ddb_machine_power_off;
-
-       ddb_out32(DDB_BAR0, 0);
-
-       ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, 0x10);
-       ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE , 0x10);
-
-       /* Reboot on panic */
-       panic_timeout = 180;
-}
-
-#define USE_NILE4_SERIAL       0
-
-#if USE_NILE4_SERIAL
-#define ns16550_in(reg)                nile4_in8((reg)*8)
-#define ns16550_out(reg, val)  nile4_out8((reg)*8, (val))
-#else
-#define NS16550_BASE           (NILE4_PCI_IO_BASE+0x03f8)
-static inline u8 ns16550_in(u32 reg)
-{
-       return *(volatile u8 *) (NS16550_BASE + reg);
-}
-
-static inline void ns16550_out(u32 reg, u8 val)
-{
-       *(volatile u8 *) (NS16550_BASE + reg) = val;
-}
-#endif
-
-#define NS16550_RBR            0
-#define NS16550_THR            0
-#define NS16550_DLL            0
-#define NS16550_IER            1
-#define NS16550_DLM            1
-#define NS16550_FCR            2
-#define NS16550_IIR            2
-#define NS16550_LCR            3
-#define NS16550_MCR            4
-#define NS16550_LSR            5
-#define NS16550_MSR            6
-#define NS16550_SCR            7
-
-#define NS16550_LSR_DR         0x01    /* Data ready */
-#define NS16550_LSR_OE         0x02    /* Overrun */
-#define NS16550_LSR_PE         0x04    /* Parity error */
-#define NS16550_LSR_FE         0x08    /* Framing error */
-#define NS16550_LSR_BI         0x10    /* Break */
-#define NS16550_LSR_THRE       0x20    /* Xmit holding register empty */
-#define NS16550_LSR_TEMT       0x40    /* Xmitter empty */
-#define NS16550_LSR_ERR                0x80    /* Error */
-
-
-void _serinit(void)
-{
-#if USE_NILE4_SERIAL
-       ns16550_out(NS16550_LCR, 0x80);
-       ns16550_out(NS16550_DLM, 0x00);
-       ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */
-       ns16550_out(NS16550_LCR, 0x00);
-       ns16550_out(NS16550_LCR, 0x03);
-       ns16550_out(NS16550_FCR, 0x47);
-#else
-       /* done by PMON */
-#endif
-}
-
-void _putc(char c)
-{
-       while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
-       ns16550_out(NS16550_THR, c);
-       if (c == '\n') {
-               while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
-               ns16550_out(NS16550_THR, '\r');
-       }
-}
-
-void _puts(const char *s)
-{
-       char c;
-       while ((c = *s++))
-               _putc(c);
-}
-
-char _getc(void)
-{
-       while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
-       return ns16550_in(NS16550_RBR);
-}
-
-int _testc(void)
-{
-       return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
-}
-
-
-/*
- *  Hexadecimal 7-segment LED
- */
-void ddb5074_led_hex(int hex)
-{
-       outb(hex, 0x80);
-}
-
-
-/*
- *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
- */
-struct pci_dev *pci_pmu = NULL;
-
-void ddb5074_led_d2(int on)
-{
-       u8 t;
-
-       if (pci_pmu) {
-               pci_read_config_byte(pci_pmu, 0x7e, &t);
-               if (on)
-                       t &= 0x7f;
-               else
-                       t |= 0x80;
-               pci_write_config_byte(pci_pmu, 0x7e, t);
-       }
-}
-
-void ddb5074_led_d3(int on)
-{
-       u8 t;
-
-       if (pci_pmu) {
-               pci_read_config_byte(pci_pmu, 0x7e, &t);
-               if (on)
-                       t &= 0xbf;
-               else
-                       t |= 0x40;
-               pci_write_config_byte(pci_pmu, 0x7e, t);
-       }
-}
diff --git a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile
deleted file mode 100644 (file)
index ab0312c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the NEC DDB Vrc-5476 specific kernel interface routines
-# under Linux.
-#
-
-obj-y                  += setup.o irq.o nile4_pic.o vrc5476_irq.o
-obj-$(CONFIG_KGDB)     += dbg_io.o
-
-EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5476/dbg_io.c b/arch/mips/ddb5xxx/ddb5476/dbg_io.c
deleted file mode 100644 (file)
index 85e9e50..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * kgdb io functions for DDB5476.  We use the second serial port.
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.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.
- *
- */
-
-/* ======================= CONFIG ======================== */
-
-/* [jsun] we use the second serial port for kdb */
-#define         BASE                    0xa60002f8
-#define         MAX_BAUD                115200
-
-/* distance in bytes between two serial registers */
-#define         REG_OFFSET              1
-
-/*
- * 0 - kgdb does serial init
- * 1 - kgdb skip serial init
- */
-static int remoteDebugInitialized = 0;
-
-/*
- * the default baud rate *if* kgdb does serial init
- */
-#define                BAUD_DEFAULT            UART16550_BAUD_38400
-
-/* ======================= END OF CONFIG ======================== */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-#define         UART16550_BAUD_2400             2400
-#define         UART16550_BAUD_4800             4800
-#define         UART16550_BAUD_9600             9600
-#define         UART16550_BAUD_19200            19200
-#define         UART16550_BAUD_38400            38400
-#define         UART16550_BAUD_57600            57600
-#define         UART16550_BAUD_115200           115200
-
-#define         UART16550_PARITY_NONE           0
-#define         UART16550_PARITY_ODD            0x08
-#define         UART16550_PARITY_EVEN           0x18
-#define         UART16550_PARITY_MARK           0x28
-#define         UART16550_PARITY_SPACE          0x38
-
-#define         UART16550_DATA_5BIT             0x0
-#define         UART16550_DATA_6BIT             0x1
-#define         UART16550_DATA_7BIT             0x2
-#define         UART16550_DATA_8BIT             0x3
-
-#define         UART16550_STOP_1BIT             0x0
-#define         UART16550_STOP_2BIT             0x4
-
-/* register offset */
-#define         OFS_RCV_BUFFER          0
-#define         OFS_TRANS_HOLD          0
-#define         OFS_SEND_BUFFER         0
-#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
-#define         OFS_INTR_ID             (2*REG_OFFSET)
-#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
-#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
-#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
-#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
-#define         OFS_LINE_STATUS         (5*REG_OFFSET)
-#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
-#define         OFS_RS232_INPUT         (6*REG_OFFSET)
-#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
-
-#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
-#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
-#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
-        /* disable interrupts */
-        UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
-        /* set up buad rate */
-        {
-                uint32 divisor;
-
-                /* set DIAB bit */
-                UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
-                /* set divisor */
-                divisor = MAX_BAUD / baud;
-                UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
-                UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
-                /* clear DIAB bit */
-                UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
-        }
-
-        /* set data format */
-        UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-
-uint8 getDebugChar(void)
-{
-        if (!remoteDebugInitialized) {
-                remoteDebugInitialized = 1;
-                debugInit(BAUD_DEFAULT,
-                          UART16550_DATA_8BIT,
-                          UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-        }
-
-        while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
-        return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
-        if (!remoteDebugInitialized) {
-                remoteDebugInitialized = 1;
-                debugInit(BAUD_DEFAULT,
-                          UART16550_DATA_8BIT,
-                          UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-        }
-
-        while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
-        UART16550_WRITE(OFS_SEND_BUFFER, byte);
-        return 1;
-}
diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c
deleted file mode 100644 (file)
index 7583a1f..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *  arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- * Re-write the whole thing to use new irq.c file.
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-
-#include <asm/i8259.h>
-#include <asm/io.h>
-#include <asm/ptrace.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-#define M1543_PNP_CONFIG       0x03f0  /* PnP Config Port */
-#define M1543_PNP_INDEX                0x03f0  /* PnP Index Port */
-#define M1543_PNP_DATA         0x03f1  /* PnP Data Port */
-
-#define M1543_PNP_ALT_CONFIG   0x0370  /* Alternative PnP Config Port */
-#define M1543_PNP_ALT_INDEX    0x0370  /* Alternative PnP Index Port */
-#define M1543_PNP_ALT_DATA     0x0371  /* Alternative PnP Data Port */
-
-#define M1543_INT1_MASTER_CTRL 0x0020  /* INT_1 (master) Control Register */
-#define M1543_INT1_MASTER_MASK 0x0021  /* INT_1 (master) Mask Register */
-
-#define M1543_INT1_SLAVE_CTRL  0x00a0  /* INT_1 (slave) Control Register */
-#define M1543_INT1_SLAVE_MASK  0x00a1  /* INT_1 (slave) Mask Register */
-
-#define M1543_INT1_MASTER_ELCR 0x04d0  /* INT_1 (master) Edge/Level Control */
-#define M1543_INT1_SLAVE_ELCR  0x04d1  /* INT_1 (slave) Edge/Level Control */
-
-static void m1543_irq_setup(void)
-{
-       /*
-        *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
-        *  the possible IO sources in the M1543 are in use by us.  We will
-        *  use the following mapping:
-        *
-        *      IRQ1  - keyboard (default set by M1543)
-        *      IRQ3  - reserved for UART B (default set by M1543) (note that
-        *              the schematics for the DDB Vrc-5476 board seem to
-        *              indicate that IRQ3 is connected to the DS1386
-        *              watchdog timer interrupt output so we might have
-        *              a conflict)
-        *      IRQ4  - reserved for UART A (default set by M1543)
-        *      IRQ5  - parallel (default set by M1543)
-        *      IRQ8  - DS1386 time of day (RTC) interrupt
-        *      IRQ9  - USB (hardwired in ddb_setup)
-        *      IRQ10 - PMU (hardwired in ddb_setup)
-        *      IRQ12 - mouse
-        *      IRQ14,15 - IDE controller (need to be confirmed, jsun)
-        */
-
-       /*
-        *  Assing mouse interrupt to IRQ12
-        */
-
-       /* Enter configuration mode */
-       outb(0x51, M1543_PNP_CONFIG);
-       outb(0x23, M1543_PNP_CONFIG);
-
-       /* Select logical device 7 (Keyboard) */
-       outb(0x07, M1543_PNP_INDEX);
-       outb(0x07, M1543_PNP_DATA);
-
-       /* Select IRQ12 */
-       outb(0x72, M1543_PNP_INDEX);
-       outb(0x0c, M1543_PNP_DATA);
-
-       /* Leave configration mode */
-       outb(0xbb, M1543_PNP_CONFIG);
-}
-
-static void nile4_irq_setup(void)
-{
-       int i;
-
-       /* Map all interrupts to CPU int #0 (IP2) */
-       nile4_map_irq_all(0);
-
-       /* PCI INTA#-E# must be level triggered */
-       nile4_set_pci_irq_level_or_edge(0, 1);
-       nile4_set_pci_irq_level_or_edge(1, 1);
-       nile4_set_pci_irq_level_or_edge(2, 1);
-       nile4_set_pci_irq_level_or_edge(3, 1);
-
-       /* PCI INTA#, B#, D# must be active low, INTC# must be active high */
-       nile4_set_pci_irq_polarity(0, 0);
-       nile4_set_pci_irq_polarity(1, 0);
-       nile4_set_pci_irq_polarity(2, 1);
-       nile4_set_pci_irq_polarity(3, 0);
-
-       for (i = 0; i < 16; i++)
-               nile4_clear_irq(i);
-
-       /* Enable CPU int #0 */
-       nile4_enable_irq_output(0);
-
-       /* memory resource acquire in ddb_setup */
-}
-
-static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
-static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
-
-extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
-extern void mips_cpu_irq_init(u32 irq_base);
-extern void vrc5476_irq_init(u32 irq_base);
-
-extern void vrc5476_irq_dispatch(struct pt_regs *regs);
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
-{
-       unsigned int pending = read_c0_cause() & read_c0_status();
-
-       if (pending & STATUSF_IP7)
-               do_IRQ(CPU_IRQ_BASE + 7, regs);
-       else if (pending & STATUSF_IP2)
-               vrc5476_irq_dispatch(regs);
-       else if (pending & STATUSF_IP3)
-               do_IRQ(CPU_IRQ_BASE + 3, regs);
-       else if (pending & STATUSF_IP4)
-               do_IRQ(CPU_IRQ_BASE + 4, regs);
-       else if (pending & STATUSF_IP5)
-               do_IRQ(CPU_IRQ_BASE + 5, regs);
-       else if (pending & STATUSF_IP6)
-               do_IRQ(CPU_IRQ_BASE + 6, regs);
-       else if (pending & STATUSF_IP0)
-               do_IRQ(CPU_IRQ_BASE, regs);
-       else if (pending & STATUSF_IP1)
-               do_IRQ(CPU_IRQ_BASE + 1, regs);
-
-       vrc5476_irq_dispatch(regs);
-}
-
-void __init arch_init_irq(void)
-{
-       /* hardware initialization */
-       nile4_irq_setup();
-       m1543_irq_setup();
-
-       /* controller setup */
-       init_i8259_irqs();
-       vrc5476_irq_init(VRC5476_IRQ_BASE);
-       mips_cpu_irq_init(CPU_IRQ_BASE);
-
-       /* setup cascade interrupts */
-       setup_irq(VRC5476_IRQ_BASE + VRC5476_I8259_CASCADE, &irq_cascade);
-       setup_irq(CPU_IRQ_BASE + CPU_VRC5476_CASCADE, &irq_cascade);
-
-       /* setup error interrupts for debugging */
-       setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CPCE, &irq_error);
-       setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CNTD, &irq_error);
-       setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_MCE, &irq_error);
-       setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
-       setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
-       setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
-}
diff --git a/arch/mips/ddb5xxx/ddb5476/nile4_pic.c b/arch/mips/ddb5xxx/ddb5476/nile4_pic.c
deleted file mode 100644 (file)
index e930cee..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- *  arch/mips/ddb5476/nile4.c --
- *     low-level PIC code for NEC Vrc-5476 (Nile 4)
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  Copyright 2001 MontaVista Software Inc.
- *  Author: jsun@mvista.com or jsun@junsun.net
- *
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#include <asm/addrspace.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-
-/*
- *  Interrupt Programming
- */
-void nile4_map_irq(int nile4_irq, int cpu_irq)
-{
-       u32 offset, t;
-
-       offset = DDB_INTCTRL;
-       if (nile4_irq >= 8) {
-               offset += 4;
-               nile4_irq -= 8;
-       }
-       t = ddb_in32(offset);
-       t &= ~(7 << (nile4_irq * 4));
-       t |= cpu_irq << (nile4_irq * 4);
-       ddb_out32(offset, t);
-}
-
-void nile4_map_irq_all(int cpu_irq)
-{
-       u32 all, t;
-
-       all = cpu_irq;
-       all |= all << 4;
-       all |= all << 8;
-       all |= all << 16;
-       t = ddb_in32(DDB_INTCTRL);
-       t &= 0x88888888;
-       t |= all;
-       ddb_out32(DDB_INTCTRL, t);
-       t = ddb_in32(DDB_INTCTRL + 4);
-       t &= 0x88888888;
-       t |= all;
-       ddb_out32(DDB_INTCTRL + 4, t);
-}
-
-void nile4_enable_irq(int nile4_irq)
-{
-       u32 offset, t;
-
-       offset = DDB_INTCTRL;
-       if (nile4_irq >= 8) {
-               offset += 4;
-               nile4_irq -= 8;
-       }
-       t = ddb_in32(offset);
-       t |= 8 << (nile4_irq * 4);
-       ddb_out32(offset, t);
-}
-
-void nile4_disable_irq(int nile4_irq)
-{
-       u32 offset, t;
-
-       offset = DDB_INTCTRL;
-       if (nile4_irq >= 8) {
-               offset += 4;
-               nile4_irq -= 8;
-       }
-       t = ddb_in32(offset);
-       t &= ~(8 << (nile4_irq * 4));
-       ddb_out32(offset, t);
-}
-
-void nile4_disable_irq_all(void)
-{
-       ddb_out32(DDB_INTCTRL, 0);
-       ddb_out32(DDB_INTCTRL + 4, 0);
-}
-
-u16 nile4_get_irq_stat(int cpu_irq)
-{
-       return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2);
-}
-
-void nile4_enable_irq_output(int cpu_irq)
-{
-       u32 t;
-
-       t = ddb_in32(DDB_INTSTAT1 + 4);
-       t |= 1 << (16 + cpu_irq);
-       ddb_out32(DDB_INTSTAT1, t);
-}
-
-void nile4_disable_irq_output(int cpu_irq)
-{
-       u32 t;
-
-       t = ddb_in32(DDB_INTSTAT1 + 4);
-       t &= ~(1 << (16 + cpu_irq));
-       ddb_out32(DDB_INTSTAT1, t);
-}
-
-void nile4_set_pci_irq_polarity(int pci_irq, int high)
-{
-       u32 t;
-
-       t = ddb_in32(DDB_INTPPES);
-       if (high)
-               t &= ~(1 << (pci_irq * 2));
-       else
-               t |= 1 << (pci_irq * 2);
-       ddb_out32(DDB_INTPPES, t);
-}
-
-void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
-{
-       u32 t;
-
-       t = ddb_in32(DDB_INTPPES);
-       if (level)
-               t |= 2 << (pci_irq * 2);
-       else
-               t &= ~(2 << (pci_irq * 2));
-       ddb_out32(DDB_INTPPES, t);
-}
-
-void nile4_clear_irq(int nile4_irq)
-{
-       ddb_out32(DDB_INTCLR, 1 << nile4_irq);
-}
-
-void nile4_clear_irq_mask(u32 mask)
-{
-       ddb_out32(DDB_INTCLR, mask);
-}
-
-u8 nile4_i8259_iack(void)
-{
-       u8 irq;
-       u32 reg;
-
-       /* Set window 0 for interrupt acknowledge */
-       reg = ddb_in32(DDB_PCIINIT0);
-
-       ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
-       irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
-       /* restore window 0 for PCI I/O space */
-       // ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
-       ddb_out32(DDB_PCIINIT0, reg);
-
-       /* i8269.c set the base vector to be 0x0 */
-       return irq + I8259_IRQ_BASE;
-}
-
-#if defined(CONFIG_RUNTIME_DEBUG)
-void nile4_dump_irq_status(void)
-{
-       printk(KERN_DEBUG "
-              CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4),
-              (void *) ddb_in32(DDB_CPUSTAT));
-       printk(KERN_DEBUG "
-              INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4),
-              (void *) ddb_in32(DDB_INTCTRL));
-       printk(KERN_DEBUG
-              "INTSTAT0 = %p:%p\n",
-              (void *) ddb_in32(DDB_INTSTAT0 + 4),
-              (void *) ddb_in32(DDB_INTSTAT0));
-       printk(KERN_DEBUG
-              "INTSTAT1 = %p:%p\n",
-              (void *) ddb_in32(DDB_INTSTAT1 + 4),
-              (void *) ddb_in32(DDB_INTSTAT1));
-       printk(KERN_DEBUG
-              "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4),
-              (void *) ddb_in32(DDB_INTCLR));
-       printk(KERN_DEBUG
-              "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4),
-              (void *) ddb_in32(DDB_INTPPES));
-}
-#endif
diff --git a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c
deleted file mode 100644 (file)
index c902ade..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- *  arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <linux/init.h>
-#include <linux/kbd_ll.h>
-#include <linux/kernel.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
-
-#include <asm/addrspace.h>
-#include <asm/bcache.h>
-#include <asm/irq.h>
-#include <asm/reboot.h>
-#include <asm/gdb-stub.h>
-#include <asm/time.h>
-#include <asm/debug.h>
-#include <asm/traps.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-// #define USE_CPU_COUNTER_TIMER       /* whether we use cpu counter */
-
-#ifdef USE_CPU_COUNTER_TIMER
-
-#define CPU_COUNTER_FREQUENCY           83000000
-#else
-/* otherwise we use general purpose timer */
-#define TIMER_FREQUENCY                        83000000
-#define TIMER_BASE                     DDB_T2CTRL
-#define TIMER_IRQ                      (VRC5476_IRQ_BASE + VRC5476_IRQ_GPT)
-#endif
-
-static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
-
-static void ddb_machine_restart(char *command)
-{
-       u32 t;
-
-       /* PCI cold reset */
-       t = ddb_in32(DDB_PCICTRL + 4);
-       t |= 0x40000000;
-       ddb_out32(DDB_PCICTRL + 4, t);
-       /* CPU cold reset */
-       t = ddb_in32(DDB_CPUSTAT);
-       t |= 1;
-       ddb_out32(DDB_CPUSTAT, t);
-       /* Call the PROM */
-       back_to_prom();
-}
-
-static void ddb_machine_halt(void)
-{
-       printk(KERN_NOTICE "DDB Vrc-5476 halted.\n");
-       while (1);
-}
-
-static void ddb_machine_power_off(void)
-{
-       printk(KERN_NOTICE "DDB Vrc-5476 halted. Please turn off the power.\n");
-       while (1);
-}
-
-extern void rtc_ds1386_init(unsigned long base);
-
-static void __init ddb_time_init(void)
-{
-#if defined(USE_CPU_COUNTER_TIMER)
-       mips_hpt_frequency = CPU_COUNTER_FREQUENCY;
-#endif
-
-       /* we have ds1396 RTC chip */
-       rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
-}
-
-
-extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
-static void __init ddb_timer_setup(struct irqaction *irq)
-{
-#if defined(USE_CPU_COUNTER_TIMER)
-
-       unsigned int count;
-
-       /* we are using the cpu counter for timer interrupts */
-       setup_irq(CPU_IRQ_BASE + 7, irq);
-
-       /* to generate the first timer interrupt */
-       count = read_c0_count();
-       write_c0_compare(count + 1000);
-
-#else
-
-       ddb_out32(TIMER_BASE, TIMER_FREQUENCY/HZ);
-       ddb_out32(TIMER_BASE+4, 0x1);   /* enable timer */
-       setup_irq(TIMER_IRQ, irq);
-#endif
-}
-
-static struct {
-       struct resource dma1;
-       struct resource timer;
-       struct resource rtc;
-       struct resource dma_page_reg;
-       struct resource dma2;
-} ddb5476_ioport = {
-       {
-       "dma1", 0x00, 0x1f, IORESOURCE_BUSY}, {
-       "timer", 0x40, 0x5f, IORESOURCE_BUSY}, {
-       "rtc", 0x70, 0x7f, IORESOURCE_BUSY}, {
-       "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, {
-       "dma2", 0xc0, 0xdf, IORESOURCE_BUSY}
-};
-
-static struct {
-       struct resource nile4;
-} ddb5476_iomem = {
-       { "Nile 4", DDB_BASE, DDB_BASE + DDB_SIZE - 1, IORESOURCE_BUSY}
-};
-
-
-static void ddb5476_board_init(void);
-
-void __init plat_setup(void)
-{
-       set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE));
-
-       board_time_init = ddb_time_init;
-       board_timer_setup = ddb_timer_setup;
-
-       _machine_restart = ddb_machine_restart;
-       _machine_halt = ddb_machine_halt;
-       pm_power_off = ddb_machine_power_off;
-
-       /* request io port/mem resources  */
-       if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) ||
-           request_resource(&ioport_resource, &ddb5476_ioport.timer) ||
-           request_resource(&ioport_resource, &ddb5476_ioport.rtc) ||
-           request_resource(&ioport_resource,
-                            &ddb5476_ioport.dma_page_reg)
-           || request_resource(&ioport_resource, &ddb5476_ioport.dma2)
-           || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) {
-               printk
-                   ("ddb_setup - requesting oo port resources failed.\n");
-               for (;;);
-       }
-
-       /* Reboot on panic */
-       panic_timeout = 180;
-
-       /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
-       /* *(long*)0xbfa00218 = 0x8; */
-
-       /* board initialization stuff */
-       ddb5476_board_init();
-}
-
-/*
- * We don't trust bios.  We essentially does hardware re-initialization
- * as complete as possible, as far as we know we can safely do.
- */
-static void ddb5476_board_init(void)
-{
-       /* ----------- setup PDARs ------------ */
-       /* check SDRAM0, whether we are on MEM bus does not matter */
-       db_assert((ddb_in32(DDB_SDRAM0) & 0xffffffef) ==
-                 ddb_calc_pdar(DDB_SDRAM_BASE, DDB_SDRAM_SIZE, 32, 0, 1));
-
-       /* SDRAM1 should be turned off.  What is this for anyway ? */
-       db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0);
-
-       /* flash 1&2, DDB status, DDB control */
-       ddb_set_pdar(DDB_DCS2, DDB_DCS2_BASE, DDB_DCS2_SIZE, 16, 0, 0);
-       ddb_set_pdar(DDB_DCS3, DDB_DCS3_BASE, DDB_DCS3_SIZE, 16, 0, 0);
-       ddb_set_pdar(DDB_DCS4, DDB_DCS4_BASE, DDB_DCS4_SIZE, 8, 0, 0);
-       ddb_set_pdar(DDB_DCS5, DDB_DCS5_BASE, DDB_DCS5_SIZE, 8, 0, 0);
-
-       /* shut off other pdar so they don't accidentally get into the way */
-       ddb_set_pdar(DDB_DCS6, 0xffffffff, 0, 32, 0, 0);
-       ddb_set_pdar(DDB_DCS7, 0xffffffff, 0, 32, 0, 0);
-       ddb_set_pdar(DDB_DCS8, 0xffffffff, 0, 32, 0, 0);
-
-       /* verify VRC5477 base addr */
-       /* don't care about some details */
-       db_assert((ddb_in32(DDB_INTCS) & 0xffffff0f) ==
-                 ddb_calc_pdar(DDB_INTCS_BASE, DDB_INTCS_SIZE, 8, 0, 0));
-
-       /* verify BOOT ROM addr */
-       /* don't care about some details */
-       db_assert((ddb_in32(DDB_BOOTCS) & 0xffffff0f) ==
-                 ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0));
-
-       /* setup PCI windows - window1 for MEM/config, window0 for IO */
-       ddb_set_pdar(DDB_PCIW0, DDB_PCI_IO_BASE, DDB_PCI_IO_SIZE, 32, 0, 1);
-       ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
-
-       ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1);
-       ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32);
-
-       /* ----------- setup PDARs ------------ */
-       /* this is problematic - it will reset Aladin which cause we loose
-        * serial port, and we don't know how to set up Aladin chip again.
-        */
-       // ddb_pci_reset_bus();
-
-       ddb_out32(DDB_BAR0, 0x00000008);
-
-       ddb_out32(DDB_BARC, 0xffffffff);
-       ddb_out32(DDB_BARB, 0xffffffff);
-       ddb_out32(DDB_BAR1, 0xffffffff);
-       ddb_out32(DDB_BAR2, 0xffffffff);
-       ddb_out32(DDB_BAR3, 0xffffffff);
-       ddb_out32(DDB_BAR4, 0xffffffff);
-       ddb_out32(DDB_BAR5, 0xffffffff);
-       ddb_out32(DDB_BAR6, 0xffffffff);
-       ddb_out32(DDB_BAR7, 0xffffffff);
-       ddb_out32(DDB_BAR8, 0xffffffff);
-
-       /* ----------- switch PCI1 to PCI CONFIG space  ------------ */
-       ddb_set_pdar(DDB_PCIW1, DDB_PCI_CONFIG_BASE, DDB_PCI_CONFIG_SIZE, 32, 0, 1);
-       ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_CFG, 0x0, DDB_PCI_ACCESS_32);
-
-       /* ----- M1543 PCI setup ------ */
-
-       /* we know M1543 PCI-ISA controller is at addr:18 */
-       /* xxxx1010 makes USB at addr:13 and PMU at addr:14 */
-       *(volatile unsigned char *) 0xa8040072 &= 0xf0;
-       *(volatile unsigned char *) 0xa8040072 |= 0xa;
-
-       /* setup USB interrupt to IRQ 9, (bit 0:3 - 0001)
-        * no IOCHRDY signal, (bit 7 - 1)
-        * M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1)
-        * Make USB Master INTAJ level to edge conversion (bit 4 - 1)
-        */
-       *(unsigned char *) 0xa8040074 = 0xd1;
-
-       /* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011)
-        * SCI routing to IRQ 13 disabled (bit 7 - 1)
-        * SCI interrupt level to edge conversion bypassed (bit 4 - 0)
-        */
-       *(unsigned char *) 0xa8040076 = 0x83;
-
-       /* setup IDE controller
-        * enable IDE controller (bit 6 - 1)
-        * IDE IDSEL to be addr:24 (bit 4:5 - 11)
-        * no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
-        * no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0)
-        * primary IRQ is 14, secondary is 15 (bit 1:0 - 01
-        */
-       // *(unsigned char*)0xa8040058 = 0x71;
-       // *(unsigned char*)0xa8040058 = 0x79;
-       // *(unsigned char*)0xa8040058 = 0x74;              // use SIRQ, primary tri-state
-       *(unsigned char *) 0xa8040058 = 0x75;   // primary tri-state
-
-#if 0
-       /* this is not necessary if M5229 does not use SIRQ */
-       *(unsigned char *) 0xa8040044 = 0x0d;   // primary to IRQ 14
-       *(unsigned char *) 0xa8040075 = 0x0d;   // secondary to IRQ 14
-#endif
-
-       /* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */
-       /* M5229 IDSEL is addr:24; see above setting */
-       *(unsigned char *) 0xa9000050 |= 0x1;
-
-       /* enable bus master (bit 2)  and IO decoding  (bit 0) */
-       *(unsigned char *) 0xa9000004 |= 0x5;
-
-       /* enable native, copied from arch/ppc/k2boot/head.S */
-       /* TODO - need volatile, need to be portable */
-       *(unsigned char *) 0xa9000009 = 0xff;
-
-       /* ----- end of M1543 PCI setup ------ */
-
-       /* ----- reset on-board ether chip  ------ */
-       *((volatile u32 *) 0xa8020004) |= 1;    /* decode I/O */
-       *((volatile u32 *) 0xa8020010) = 0;     /* set BAR address */
-
-       /* send reset command */
-       *((volatile u32 *) 0xa6000000) = 1;     /* do a soft reset */
-
-       /* disable ether chip */
-       *((volatile u32 *) 0xa8020004) = 0;     /* disable any decoding */
-
-       /* put it into sleep */
-       *((volatile u32 *) 0xa8020040) = 0x80000000;
-
-       /* ----- end of reset on-board ether chip  ------ */
-
-       /* ----------- switch PCI1 back to PCI MEM space  ------------ */
-       ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1);
-       ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32);
-}
diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
deleted file mode 100644 (file)
index a3c5e7b..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * The irq controller for vrc5476.
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.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 <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-
-#include <asm/system.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-static int irq_base;
-
-static void vrc5476_irq_enable(uint irq)
-{
-       nile4_enable_irq(irq - irq_base);
-}
-
-static void vrc5476_irq_disable(uint irq)
-{
-       nile4_disable_irq(irq - irq_base);
-}
-
-static unsigned int vrc5476_irq_startup(uint irq)
-{
-       nile4_enable_irq(irq - irq_base);
-       return 0;
-}
-
-#define vrc5476_irq_shutdown   vrc5476_irq_disable
-
-static void vrc5476_irq_ack(uint irq)
-{
-       nile4_clear_irq(irq - irq_base);
-       nile4_disable_irq(irq - irq_base);
-}
-
-static void vrc5476_irq_end(uint irq)
-{
-       if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               vrc5476_irq_enable(irq);
-}
-
-static hw_irq_controller vrc5476_irq_controller = {
-       .typename = "vrc5476",
-       .startup = vrc5476_irq_startup,
-       .shutdown = vrc5476_irq_shutdown,
-       .enable = vrc5476_irq_enable,
-       .disable = vrc5476_irq_disable,
-       .ack = vrc5476_irq_ack,
-       .end = vrc5476_irq_end
-};
-
-void __init
-vrc5476_irq_init(u32 base)
-{
-       u32 i;
-
-       irq_base = base;
-       for (i= base; i< base + NUM_VRC5476_IRQ; i++) {
-               irq_desc[i].status = IRQ_DISABLED;
-               irq_desc[i].action = NULL;
-               irq_desc[i].depth = 1;
-               irq_desc[i].handler = &vrc5476_irq_controller;
-       }
-}
-
-
-void
-vrc5476_irq_dispatch(struct pt_regs *regs)
-{
-       u32 mask;
-       int nile4_irq;
-
-       mask = nile4_get_irq_stat(0);
-
-       /* quick check for possible time interrupt */
-       if (mask & (1 << VRC5476_IRQ_GPT)) {
-               do_IRQ(VRC5476_IRQ_BASE + VRC5476_IRQ_GPT, regs);
-               return;
-       }
-
-       /* check for i8259 interrupts */
-       if (mask & (1 << VRC5476_I8259_CASCADE)) {
-               int i8259_irq = nile4_i8259_iack();
-               do_IRQ(I8259_IRQ_BASE + i8259_irq, regs);
-               return;
-       }
-
-       /* regular nile4 interrupts (we should not really have any */
-       for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) {
-               if (mask & 1) {
-                       do_IRQ(VRC5476_IRQ_BASE + nile4_irq, regs);
-                       return;
-               }
-       }
-       spurious_interrupt(regs);
-}
index 1d18d590495b138ac7687d94ecdd1c8b3302cafb..385bbdb10170a058e065b6400615f626f340d98a 100644 (file)
@@ -86,7 +86,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
         /* disable interrupts */
         UART16550_WRITE(OFS_INTR_ENABLE, 0);
 
-        /* set up buad rate */
+        /* set up baud rate */
         {
                 uint32 divisor;
 
index 2f566034cc44a3b112ac9a9381feb52296531c97..93167ecdb424cc0799ecbce7eef14f1e1972ae73 100644 (file)
@@ -171,7 +171,7 @@ static void ddb5477_board_init(void);
 extern struct pci_controller ddb5477_ext_controller;
 extern struct pci_controller ddb5477_io_controller;
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        /* initialize board - we don't trust the loader */
         ddb5477_board_init();
index ad5d436d80c19bae206c86a6623b3aaa8e486263..9c707b9ceb65fdac4871408901f7abc5fa5b9062 100644 (file)
@@ -147,7 +147,7 @@ static void __init dec_be_init(void)
 extern void dec_time_init(void);
 extern void dec_timer_setup(struct irqaction *);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        board_be_init = dec_be_init;
        board_time_init = dec_time_init;
index 74cb055d4bf64d859923a6aeb33fa23bded02f84..76e4d09ff4d2bc55ddd11acee8d5b25b5d28f509 100644 (file)
@@ -181,7 +181,7 @@ void __init dec_time_init(void)
        }
 
        /* Set up the rate of periodic DS1287 interrupts.  */
-       CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A);
+       CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A);
 }
 
 EXPORT_SYMBOL(do_settimeofday);
index 607e2985ffe3b927467151a09f7f6f69d28faf1b..879ba1ad99caf2076bc7c56a302c6166679d02c9 100644 (file)
@@ -41,8 +41,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/emma2rh/common/Makefile b/arch/mips/emma2rh/common/Makefile
new file mode 100644 (file)
index 0000000..859121b
--- /dev/null
@@ -0,0 +1,13 @@
+#
+#  arch/mips/emma2rh/common/Makefile
+#       Makefile for the common code of NEC EMMA2RH based board.
+#
+#  Copyright (C) NEC Electronics Corporation 2005-2006
+#
+#  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.
+#
+
+obj-$(CONFIG_MARKEINS) += irq.o irq_emma2rh.o prom.o
diff --git a/arch/mips/emma2rh/common/irq.c b/arch/mips/emma2rh/common/irq.c
new file mode 100644 (file)
index 0000000..b075281
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *  arch/mips/emma2rh/common/irq.c
+ *      This file is common irq dispatcher.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
+ *
+ *     Copyright 2001 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.
+ *
+ *  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/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+
+#include <asm/i8259.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/debug.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+/*
+ * the first level int-handler will jump here if it is a emma2rh irq
+ */
+asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs)
+{
+       u32 intStatus;
+       u32 bitmask;
+       u32 i;
+
+       intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_0)
+           & emma2rh_in32(EMMA2RH_BHIF_INT_EN_0);
+
+#ifdef EMMA2RH_SW_CASCADE
+       if (intStatus &
+           (1 << ((EMMA2RH_SW_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) {
+               u32 swIntStatus;
+               swIntStatus = emma2rh_in32(EMMA2RH_BHIF_SW_INT)
+                   & emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
+               for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
+                       if (swIntStatus & bitmask) {
+                               do_IRQ(EMMA2RH_SW_IRQ_BASE + i, regs);
+                               return;
+                       }
+               }
+       }
+#endif
+
+       for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
+               if (intStatus & bitmask) {
+                       do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+                       return;
+               }
+       }
+
+       intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_1)
+           & emma2rh_in32(EMMA2RH_BHIF_INT_EN_1);
+
+#ifdef EMMA2RH_GPIO_CASCADE
+       if (intStatus &
+           (1 << ((EMMA2RH_GPIO_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) {
+               u32 gpioIntStatus;
+               gpioIntStatus = emma2rh_in32(EMMA2RH_GPIO_INT_ST)
+                   & emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+               for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
+                       if (gpioIntStatus & bitmask) {
+                               do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i, regs);
+                               return;
+                       }
+               }
+       }
+#endif
+
+       for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) {
+               if (intStatus & bitmask) {
+                       do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+                       return;
+               }
+       }
+
+       intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_2)
+           & emma2rh_in32(EMMA2RH_BHIF_INT_EN_2);
+
+       for (i = 64, bitmask = 1; i < 96; i++, bitmask <<= 1) {
+               if (intStatus & bitmask) {
+                       do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+                       return;
+               }
+       }
+}
diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c
new file mode 100644 (file)
index 0000000..b886aa9
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *  arch/mips/emma2rh/common/irq_emma2rh.c
+ *      This file defines the irq handler for EMMA2RH.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c
+ *
+ *     Copyright 2001 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.
+ *
+ *  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
+ */
+
+/*
+ * EMMA2RH defines 64 IRQs.
+ *
+ * This file exports one function:
+ *     emma2rh_irq_init(u32 irq_base);
+ */
+
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+/* number of total irqs supported by EMMA2RH */
+#define        NUM_EMMA2RH_IRQ         96
+
+static int emma2rh_irq_base = -1;
+
+void ll_emma2rh_irq_enable(int);
+void ll_emma2rh_irq_disable(int);
+
+static void emma2rh_irq_enable(unsigned int irq)
+{
+       ll_emma2rh_irq_enable(irq - emma2rh_irq_base);
+}
+
+static void emma2rh_irq_disable(unsigned int irq)
+{
+       ll_emma2rh_irq_disable(irq - emma2rh_irq_base);
+}
+
+static unsigned int emma2rh_irq_startup(unsigned int irq)
+{
+       emma2rh_irq_enable(irq);
+       return 0;
+}
+
+#define        emma2rh_irq_shutdown    emma2rh_irq_disable
+
+static void emma2rh_irq_ack(unsigned int irq)
+{
+       /* disable interrupt - some handler will re-enable the irq
+        * and if the interrupt is leveled, we will have infinite loop
+        */
+       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);
+}
+
+hw_irq_controller emma2rh_irq_controller = {
+       .typename = "emma2rh_irq",
+       .startup = emma2rh_irq_startup,
+       .shutdown = emma2rh_irq_shutdown,
+       .enable = emma2rh_irq_enable,
+       .disable = emma2rh_irq_disable,
+       .ack = emma2rh_irq_ack,
+       .end = emma2rh_irq_end,
+       .set_affinity = NULL    /* no affinity stuff for UP */
+};
+
+void emma2rh_irq_init(u32 irq_base)
+{
+       u32 i;
+
+       for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ; i++) {
+               irq_desc[i].status = IRQ_DISABLED;
+               irq_desc[i].action = NULL;
+               irq_desc[i].depth = 1;
+               irq_desc[i].handler = &emma2rh_irq_controller;
+       }
+
+       emma2rh_irq_base = irq_base;
+}
+
+void ll_emma2rh_irq_enable(int emma2rh_irq)
+{
+       u32 reg_value;
+       u32 reg_bitmask;
+       u32 reg_index;
+
+       reg_index = EMMA2RH_BHIF_INT_EN_0
+           + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0)
+           * (emma2rh_irq / 32);
+       reg_value = emma2rh_in32(reg_index);
+       reg_bitmask = 0x1 << (emma2rh_irq % 32);
+       db_assert((reg_value & reg_bitmask) == 0);
+       emma2rh_out32(reg_index, reg_value | reg_bitmask);
+}
+
+void ll_emma2rh_irq_disable(int emma2rh_irq)
+{
+       u32 reg_value;
+       u32 reg_bitmask;
+       u32 reg_index;
+
+       reg_index = EMMA2RH_BHIF_INT_EN_0
+           + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0)
+           * (emma2rh_irq / 32);
+       reg_value = emma2rh_in32(reg_index);
+       reg_bitmask = 0x1 << (emma2rh_irq % 32);
+       db_assert((reg_value & reg_bitmask) != 0);
+       emma2rh_out32(reg_index, reg_value & ~reg_bitmask);
+}
diff --git a/arch/mips/emma2rh/common/prom.c b/arch/mips/emma2rh/common/prom.c
new file mode 100644 (file)
index 0000000..8bba0b0
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  arch/mips/emma2rh/common/prom.c
+ *      This file is prom file.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/common/prom.c
+ *
+ *     Copyright 2001 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.
+ *
+ *  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/config.h>
+#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 <asm/emma2rh/emma2rh.h>
+#include <asm/debug.h>
+
+const char *get_system_type(void)
+{
+       switch (mips_machtype) {
+       case MACH_NEC_MARKEINS:
+               return "NEC EMMA2RH Mark-eins";
+       default:
+               return "Unknown NEC board";
+       }
+}
+
+/* [jsun@junsun.net] PMON passes arguments in C main() style */
+void __init prom_init(void)
+{
+       int argc = fw_arg0;
+       char **arg = (char **)fw_arg1;
+       int i;
+
+       /* if user passes kernel args, ignore the default one */
+       if (argc > 1)
+               arcs_cmdline[0] = '\0';
+
+       /* arg[0] is "g", the rest is boot parameters */
+       for (i = 1; i < argc; i++) {
+               if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+                   >= sizeof(arcs_cmdline))
+                       break;
+               strcat(arcs_cmdline, arg[i]);
+               strcat(arcs_cmdline, " ");
+       }
+
+       mips_machgroup = MACH_GROUP_NEC_EMMA2RH;
+
+#if defined(CONFIG_MARKEINS)
+       mips_machtype = MACH_NEC_MARKEINS;
+       add_memory_region(0, EMMA2RH_RAM_SIZE, BOOT_MEM_RAM);
+#endif
+
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff --git a/arch/mips/emma2rh/markeins/Makefile b/arch/mips/emma2rh/markeins/Makefile
new file mode 100644 (file)
index 0000000..14fc268
--- /dev/null
@@ -0,0 +1,13 @@
+#
+#  arch/mips/emma2rh/markeins/Makefile
+#       Makefile for the common code of NEC EMMA2RH based board.
+#
+#  Copyright (C) NEC Electronics Corporation 2005-2006
+#
+#  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.
+#
+
+obj-$(CONFIG_MARKEINS) += irq.o irq_markeins.o setup.o led.o platform.o
diff --git a/arch/mips/emma2rh/markeins/irq.c b/arch/mips/emma2rh/markeins/irq.c
new file mode 100644 (file)
index 0000000..76dc3fa
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *  arch/mips/emma2rh/markeins/irq.c
+ *      This file defines the irq handler for EMMA2RH.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
+ *
+ *     Copyright 2001 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.
+ *
+ *  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/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/delay.h>
+
+#include <asm/i8259.h>
+#include <asm/irq_cpu.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/debug.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+/*
+ * IRQ mapping
+ *
+ *  0-7: 8 CPU interrupts
+ *     0 -     software interrupt 0
+ *     1 -     software interrupt 1
+ *     2 -     most Vrc5477 interrupts are routed to this pin
+ *     3 -     (optional) some other interrupts routed to this pin for debugg
+ *     4 -     not used
+ *     5 -     not used
+ *     6 -     not used
+ *     7 -     cpu timer (used by default)
+ *
+ */
+
+extern void emma2rh_sw_irq_init(u32 base);
+extern void emma2rh_gpio_irq_init(u32 base);
+extern void emma2rh_irq_init(u32 base);
+extern asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs);
+
+static struct irqaction irq_cascade = {
+          .handler = no_action,
+          .flags = 0,
+          .mask = CPU_MASK_NONE,
+          .name = "cascade",
+          .dev_id = NULL,
+          .next = NULL,
+};
+
+void __init arch_init_irq(void)
+{
+       u32 reg;
+
+       db_run(printk("markeins_irq_setup invoked.\n"));
+
+       /* by default, interrupts are disabled. */
+       emma2rh_out32(EMMA2RH_BHIF_INT_EN_0, 0);
+       emma2rh_out32(EMMA2RH_BHIF_INT_EN_1, 0);
+       emma2rh_out32(EMMA2RH_BHIF_INT_EN_2, 0);
+       emma2rh_out32(EMMA2RH_BHIF_INT1_EN_0, 0);
+       emma2rh_out32(EMMA2RH_BHIF_INT1_EN_1, 0);
+       emma2rh_out32(EMMA2RH_BHIF_INT1_EN_2, 0);
+       emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, 0);
+
+       clear_c0_status(0xff00);
+       set_c0_status(0x0400);
+
+#define GPIO_PCI (0xf<<15)
+       /* setup GPIO interrupt for PCI interface */
+       /* direction input */
+       reg = emma2rh_in32(EMMA2RH_GPIO_DIR);
+       emma2rh_out32(EMMA2RH_GPIO_DIR, reg & ~GPIO_PCI);
+       /* disable interrupt */
+       reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+       emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg & ~GPIO_PCI);
+       /* level triggerd */
+       reg = emma2rh_in32(EMMA2RH_GPIO_INT_MODE);
+       emma2rh_out32(EMMA2RH_GPIO_INT_MODE, reg | GPIO_PCI);
+       reg = emma2rh_in32(EMMA2RH_GPIO_INT_CND_A);
+       emma2rh_out32(EMMA2RH_GPIO_INT_CND_A, reg & (~GPIO_PCI));
+       /* interrupt clear */
+       emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~GPIO_PCI);
+
+       /* init all controllers */
+       emma2rh_irq_init(EMMA2RH_IRQ_BASE);
+       emma2rh_sw_irq_init(EMMA2RH_SW_IRQ_BASE);
+       emma2rh_gpio_irq_init(EMMA2RH_GPIO_IRQ_BASE);
+       mips_cpu_irq_init(CPU_IRQ_BASE);
+
+       /* setup cascade interrupts */
+       setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade);
+       setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade);
+       setup_irq(CPU_IRQ_BASE + CPU_EMMA2RH_CASCADE, &irq_cascade);
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+        unsigned int pending = read_c0_status() & read_c0_cause();
+
+       if (pending & STATUSF_IP7)
+               do_IRQ(CPU_IRQ_BASE + 7, regs);
+       else if (pending & STATUSF_IP2)
+               emma2rh_irq_dispatch(regs);
+       else if (pending & STATUSF_IP1)
+               do_IRQ(CPU_IRQ_BASE + 1, regs);
+       else if (pending & STATUSF_IP0)
+               do_IRQ(CPU_IRQ_BASE + 0, regs);
+       else
+               spurious_interrupt(regs);
+}
+
+
diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c
new file mode 100644 (file)
index 0000000..1783fda
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ *  arch/mips/emma2rh/markeins/irq_markeins.c
+ *      This file defines the irq handler for Mark-eins.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c
+ *
+ *     Copyright 2001 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.
+ *
+ *  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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/debug.h>
+#include <asm/emma2rh/emma2rh.h>
+
+static int emma2rh_sw_irq_base = -1;
+static int emma2rh_gpio_irq_base = -1;
+
+void ll_emma2rh_sw_irq_enable(int reg);
+void ll_emma2rh_sw_irq_disable(int reg);
+void ll_emma2rh_gpio_irq_enable(int reg);
+void ll_emma2rh_gpio_irq_disable(int reg);
+
+static void emma2rh_sw_irq_enable(unsigned int irq)
+{
+       ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base);
+}
+
+static void emma2rh_sw_irq_disable(unsigned int irq)
+{
+       ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base);
+}
+
+static unsigned int emma2rh_sw_irq_startup(unsigned int irq)
+{
+       emma2rh_sw_irq_enable(irq);
+       return 0;
+}
+
+#define emma2rh_sw_irq_shutdown emma2rh_sw_irq_disable
+
+static void emma2rh_sw_irq_ack(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);
+}
+
+hw_irq_controller emma2rh_sw_irq_controller = {
+       .typename = "emma2rh_sw_irq",
+       .startup = emma2rh_sw_irq_startup,
+       .shutdown = emma2rh_sw_irq_shutdown,
+       .enable = emma2rh_sw_irq_enable,
+       .disable = emma2rh_sw_irq_disable,
+       .ack = emma2rh_sw_irq_ack,
+       .end = emma2rh_sw_irq_end,
+       .set_affinity = NULL,
+};
+
+void emma2rh_sw_irq_init(u32 irq_base)
+{
+       u32 i;
+
+       for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++) {
+               irq_desc[i].status = IRQ_DISABLED;
+               irq_desc[i].action = NULL;
+               irq_desc[i].depth = 2;
+               irq_desc[i].handler = &emma2rh_sw_irq_controller;
+       }
+
+       emma2rh_sw_irq_base = irq_base;
+}
+
+void ll_emma2rh_sw_irq_enable(int irq)
+{
+       u32 reg;
+
+       db_assert(irq >= 0);
+       db_assert(irq < NUM_EMMA2RH_IRQ_SW);
+
+       reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
+       reg |= 1 << irq;
+       emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
+}
+
+void ll_emma2rh_sw_irq_disable(int irq)
+{
+       u32 reg;
+
+       db_assert(irq >= 0);
+       db_assert(irq < 32);
+
+       reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
+       reg &= ~(1 << irq);
+       emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
+}
+
+static void emma2rh_gpio_irq_enable(unsigned int irq)
+{
+       ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base);
+}
+
+static void emma2rh_gpio_irq_disable(unsigned int irq)
+{
+       ll_emma2rh_gpio_irq_disable(irq - emma2rh_gpio_irq_base);
+}
+
+static unsigned int emma2rh_gpio_irq_startup(unsigned int irq)
+{
+       emma2rh_gpio_irq_enable(irq);
+       return 0;
+}
+
+#define emma2rh_gpio_irq_shutdown emma2rh_gpio_irq_disable
+
+static void emma2rh_gpio_irq_ack(unsigned int irq)
+{
+       irq -= emma2rh_gpio_irq_base;
+       emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
+       ll_emma2rh_gpio_irq_disable(irq);
+}
+
+static void emma2rh_gpio_irq_end(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base);
+}
+
+hw_irq_controller emma2rh_gpio_irq_controller = {
+       .typename = "emma2rh_gpio_irq",
+       .startup = emma2rh_gpio_irq_startup,
+       .shutdown = emma2rh_gpio_irq_shutdown,
+       .enable = emma2rh_gpio_irq_enable,
+       .disable = emma2rh_gpio_irq_disable,
+       .ack = emma2rh_gpio_irq_ack,
+       .end = emma2rh_gpio_irq_end,
+       .set_affinity = NULL,
+};
+
+void emma2rh_gpio_irq_init(u32 irq_base)
+{
+       u32 i;
+
+       for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_GPIO; i++) {
+               irq_desc[i].status = IRQ_DISABLED;
+               irq_desc[i].action = NULL;
+               irq_desc[i].depth = 2;
+               irq_desc[i].handler = &emma2rh_gpio_irq_controller;
+       }
+
+       emma2rh_gpio_irq_base = irq_base;
+}
+
+void ll_emma2rh_gpio_irq_enable(int irq)
+{
+       u32 reg;
+
+       db_assert(irq >= 0);
+       db_assert(irq < NUM_EMMA2RH_IRQ_GPIO);
+
+       reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+       reg |= 1 << irq;
+       emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
+}
+
+void ll_emma2rh_gpio_irq_disable(int irq)
+{
+       u32 reg;
+
+       db_assert(irq >= 0);
+       db_assert(irq < NUM_EMMA2RH_IRQ_GPIO);
+
+       reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+       reg &= ~(1 << irq);
+       emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
+}
diff --git a/arch/mips/emma2rh/markeins/led.c b/arch/mips/emma2rh/markeins/led.c
new file mode 100644 (file)
index 0000000..b65254c
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  arch/mips/emma2rh/markeins/led.c
+ *      This file defines the led display for Mark-eins.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/emma2rh/emma2rh.h>
+
+const unsigned long clear = 0x20202020;
+
+#define LED_BASE 0xb1400038
+
+void markeins_led_clear(void)
+{
+       emma2rh_out32(LED_BASE, clear);
+       emma2rh_out32(LED_BASE + 4, clear);
+}
+
+void markeins_led(const char *str)
+{
+       int i;
+       int len = strlen(str);
+
+       markeins_led_clear();
+       if (len > 8)
+               len = 8;
+
+       if (emma2rh_in32(0xb0000800) & (0x1 << 18))
+               for (i = 0; i < len; i++)
+                       emma2rh_out8(LED_BASE + i, str[i]);
+       else
+               for (i = 0; i < len; i++)
+                       emma2rh_out8(LED_BASE + (i & 4) + (3 - (i & 3)),
+                                    str[i]);
+}
+
+void markeins_led_hex(u32 val)
+{
+       char str[10];
+
+       sprintf(str, "%08x", val);
+       markeins_led(str);
+}
diff --git a/arch/mips/emma2rh/markeins/platform.c b/arch/mips/emma2rh/markeins/platform.c
new file mode 100644 (file)
index 0000000..6c1eeae
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ *  arch/mips/emma2rh/markeins/platofrm.c
+ *      This file sets up platform devices for EMMA2RH Mark-eins.
+ *
+ *  Copyright(C) MontaVista Software Inc, 2006
+ *
+ *  Author: dmitry pervushin <dpervushin@ru.mvista.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This 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/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/traps.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+
+#define I2C_EMMA2RH "emma2rh-iic" /* must be in sync with IIC driver */
+
+static struct resource i2c_emma_resources_0[] = {
+       { NULL, EMMA2RH_IRQ_PIIC0, EMMA2RH_IRQ_PIIC0, IORESOURCE_IRQ },
+       { NULL, KSEG1ADDR(EMMA2RH_PIIC0_BASE), KSEG1ADDR(EMMA2RH_PIIC0_BASE + 0x1000), 0 },
+};
+
+struct resource i2c_emma_resources_1[] = {
+       { NULL, EMMA2RH_IRQ_PIIC1, EMMA2RH_IRQ_PIIC1, IORESOURCE_IRQ },
+       { NULL, KSEG1ADDR(EMMA2RH_PIIC1_BASE), KSEG1ADDR(EMMA2RH_PIIC1_BASE + 0x1000), 0 },
+};
+
+struct resource i2c_emma_resources_2[] = {
+       { NULL, EMMA2RH_IRQ_PIIC2, EMMA2RH_IRQ_PIIC2, IORESOURCE_IRQ },
+       { NULL, KSEG1ADDR(EMMA2RH_PIIC2_BASE), KSEG1ADDR(EMMA2RH_PIIC2_BASE + 0x1000), 0 },
+};
+
+struct platform_device i2c_emma_devices[] = {
+       [0] = {
+               .name = I2C_EMMA2RH,
+               .id = 0,
+               .resource = i2c_emma_resources_0,
+               .num_resources = ARRAY_SIZE(i2c_emma_resources_0),
+       },
+       [1] = {
+               .name = I2C_EMMA2RH,
+               .id = 1,
+               .resource = i2c_emma_resources_1,
+               .num_resources = ARRAY_SIZE(i2c_emma_resources_1),
+       },
+       [2] = {
+               .name = I2C_EMMA2RH,
+               .id = 2,
+               .resource = i2c_emma_resources_2,
+               .num_resources = ARRAY_SIZE(i2c_emma_resources_2),
+       },
+};
+
+#define EMMA2RH_SERIAL_CLOCK 18544000
+#define EMMA2RH_SERIAL_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST
+
+static struct  plat_serial8250_port platform_serial_ports[] = {
+       [0] = {
+         .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3),
+         .irq = EMMA2RH_IRQ_PFUR0,
+         .uartclk = EMMA2RH_SERIAL_CLOCK,
+         .regshift = 4,
+         .iotype = UPIO_MEM,
+         .flags = EMMA2RH_SERIAL_FLAGS,
+       },
+       [1] = {
+         .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3),
+         .irq = EMMA2RH_IRQ_PFUR1,
+         .uartclk = EMMA2RH_SERIAL_CLOCK,
+         .regshift = 4,
+         .iotype = UPIO_MEM,
+         .flags = EMMA2RH_SERIAL_FLAGS,
+       },
+       [2] = {
+         .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3),
+         .irq = EMMA2RH_IRQ_PFUR2,
+         .uartclk = EMMA2RH_SERIAL_CLOCK,
+         .regshift = 4,
+         .iotype = UPIO_MEM,
+         .flags = EMMA2RH_SERIAL_FLAGS,
+       },
+       [3] = {
+        .flags = 0,
+       },
+};
+
+static struct  platform_device serial_emma = {
+       .name = "serial8250",
+       .dev = {
+               .platform_data = &platform_serial_ports,
+       },
+};
+
+static struct platform_device *devices[] = {
+       &i2c_emma_devices[0],
+       &i2c_emma_devices[1],
+       &i2c_emma_devices[2],
+       &serial_emma,
+};
+
+static struct mtd_partition markeins_parts[] = {
+       [0] = {
+               .name = "RootFS",
+               .offset = 0x00000000,
+               .size = 0x00c00000,
+       },
+       [1] = {
+               .name = "boot code area",
+               .offset = MTDPART_OFS_APPEND,
+               .size = 0x00100000,
+       },
+       [2] = {
+               .name = "kernel image",
+               .offset = MTDPART_OFS_APPEND,
+               .size = 0x00300000,
+       },
+       [3] = {
+               .name = "RootFS2",
+               .offset = MTDPART_OFS_APPEND,
+               .size = 0x00c00000,
+       },
+       [4] = {
+               .name = "boot code area2",
+               .offset = MTDPART_OFS_APPEND,
+               .size = 0x00100000,
+       },
+       [5] = {
+               .name = "kernel image2",
+               .offset = MTDPART_OFS_APPEND,
+               .size = MTDPART_SIZ_FULL,
+       },
+};
+
+static int __init platform_devices_setup(void)
+{
+       physmap_set_partitions(markeins_parts, ARRAY_SIZE(markeins_parts));
+       return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+arch_initcall(platform_devices_setup);
+
diff --git a/arch/mips/emma2rh/markeins/setup.c b/arch/mips/emma2rh/markeins/setup.c
new file mode 100644 (file)
index 0000000..7d98fdb
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *  arch/mips/emma2rh/markeins/setup.c
+ *      This file is setup for EMMA2RH Mark-eins.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/setup.c.
+ *
+ *     Copyright 2001 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.
+ *
+ *  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/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/ioport.h>
+#include <linux/param.h>       /* for HZ */
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/traps.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+#define        USE_CPU_COUNTER_TIMER   /* whether we use cpu counter */
+
+extern void markeins_led(const char *);
+
+static int bus_frequency = 0;
+
+static void markeins_machine_restart(char *command)
+{
+       static void (*back_to_prom) (void) = (void (*)(void))0xbfc00000;
+
+       printk("cannot EMMA2RH Mark-eins restart.\n");
+       markeins_led("restart.");
+       back_to_prom();
+}
+
+static void markeins_machine_halt(void)
+{
+       printk("EMMA2RH Mark-eins halted.\n");
+       markeins_led("halted.");
+       while (1) ;
+}
+
+static void markeins_machine_power_off(void)
+{
+       printk("EMMA2RH Mark-eins halted. Please turn off the power.\n");
+       markeins_led("poweroff.");
+       while (1) ;
+}
+
+static unsigned long clock[4] = { 166500000, 187312500, 199800000, 210600000 };
+
+static unsigned int __init detect_bus_frequency(unsigned long rtc_base)
+{
+       u32 reg;
+
+       /* detect from boot strap */
+       reg = emma2rh_in32(EMMA2RH_BHIF_STRAP_0);
+       reg = (reg >> 4) & 0x3;
+       return clock[reg];
+}
+
+static void __init emma2rh_time_init(void)
+{
+       u32 reg;
+       if (bus_frequency == 0)
+               bus_frequency = detect_bus_frequency(0);
+
+       reg = emma2rh_in32(EMMA2RH_BHIF_STRAP_0);
+       if ((reg & 0x3) == 0)
+               reg = (reg >> 6) & 0x3;
+       else {
+               reg = emma2rh_in32(EMMA2RH_BHIF_MAIN_CTRL);
+               reg = (reg >> 4) & 0x3;
+       }
+       mips_hpt_frequency = (bus_frequency * (4 + reg)) / 4 / 2;
+}
+
+static void __init emma2rh_timer_setup(struct irqaction *irq)
+{
+       /* we are using the cpu counter for timer interrupts */
+       setup_irq(CPU_IRQ_BASE + 7, irq);
+}
+
+static void markeins_board_init(void);
+extern void markeins_irq_setup(void);
+
+static void inline __init markeins_sio_setup(void)
+{
+#ifdef CONFIG_KGDB_8250
+       struct uart_port emma_port;
+
+       memset(&emma_port, 0, sizeof(emma_port));
+
+       emma_port.flags =
+           UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+       emma_port.iotype = UPIO_MEM;
+       emma_port.regshift = 4; /* I/O addresses are every 8 bytes */
+       emma_port.uartclk = 18544000;   /* Clock rate of the chip */
+
+       emma_port.line = 0;
+       emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3);
+       emma_port.membase = (u8*)emma_port.mapbase;
+       early_serial_setup(&emma_port);
+
+       emma_port.line = 1;
+       emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3);
+       emma_port.membase = (u8*)emma_port.mapbase;
+       early_serial_setup(&emma_port);
+
+       emma_port.irq = EMMA2RH_IRQ_PFUR1;
+       kgdb8250_add_port(1, &emma_port);
+#endif
+}
+
+void __init plat_mem_setup(void)
+{
+       /* initialize board - we don't trust the loader */
+       markeins_board_init();
+
+       set_io_port_base(KSEG1ADDR(EMMA2RH_PCI_IO_BASE));
+
+       board_time_init = emma2rh_time_init;
+       board_timer_setup = emma2rh_timer_setup;
+
+       _machine_restart = markeins_machine_restart;
+       _machine_halt = markeins_machine_halt;
+       pm_power_off = markeins_machine_power_off;
+
+       /* setup resource limits */
+       ioport_resource.start = EMMA2RH_PCI_IO_BASE;
+       ioport_resource.end = EMMA2RH_PCI_IO_BASE + EMMA2RH_PCI_IO_SIZE - 1;
+       iomem_resource.start = EMMA2RH_IO_BASE;
+       iomem_resource.end = EMMA2RH_ROM_BASE - 1;
+
+       /* Reboot on panic */
+       panic_timeout = 180;
+
+       markeins_sio_setup();
+}
+
+static void __init markeins_board_init(void)
+{
+       u32 val;
+
+       val = emma2rh_in32(EMMA2RH_PBRD_INT_EN);        /* open serial interrupts. */
+       emma2rh_out32(EMMA2RH_PBRD_INT_EN, val | 0xaa);
+       val = emma2rh_in32(EMMA2RH_PBRD_CLKSEL);        /* set serial clocks. */
+       emma2rh_out32(EMMA2RH_PBRD_CLKSEL, val | 0x5);  /* 18MHz */
+       emma2rh_out32(EMMA2RH_PCI_CONTROL, 0);
+
+       markeins_led("MVL E2RH");
+}
index 78dbb18edeb8ae256b4b020bf35915857b1a0c0e..a04aea6123daf5ab3bd461f9138e927777864ed0 100644 (file)
@@ -55,7 +55,7 @@ extern void mips_reboot_setup(void);
 
 unsigned char mac_0_1[12];
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        unsigned int config = read_c0_config();
        unsigned int status = read_c0_status();
index 16e34a546e547d0cfe9dc15c1fc04785fb3fc1db..8f0d835491ff46bfce7252479607d3cf4f7a4393 100644 (file)
@@ -149,7 +149,7 @@ void serial_set(int channel, unsigned long baud)
 #else
        /*
         * Note: Set baud rate, hardcoded here for rate of 115200
-        * since became unsure of above "buad rate" algorithm (??).
+        * since became unsure of above "baud rate" algorithm (??).
         */
        outreg(channel, LCR, 0x83);
        outreg(channel, DLM, 0x00);     // See note above
index 6d859d1e7a2d0308ff45cab6a48b4f2ed7eee9d0..4236da31ecc679abafd9af5e4c50f55d163ffe79 100644 (file)
@@ -71,7 +71,7 @@ unsigned long __init prom_free_prom_memory(void)
  */
 extern void gt64120_time_init(void);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        _machine_restart = galileo_machine_restart;
        _machine_halt = galileo_machine_halt;
index 8720bccfdea250dd9eddbe580c22b8f4e75fa60e..f0a6a38fcf4d9fae50fc20da3b7c1505ebc451ef 100644 (file)
@@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
        /* disable interrupts */
        UART16550_WRITE(OFS_INTR_ENABLE, 0);
 
-       /* set up buad rate */
+       /* set up baud rate */
        {
                uint32 divisor;
 
index 20b65d3d2151579149daca9a978429a7d3374a1e..1193a22c469376febb694ae9fe5dbb1cf749331d 100644 (file)
@@ -152,7 +152,7 @@ void PMON_v2_setup()
        gt64120_base = 0xe0000000;
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache);
        unsigned int tmpword;
diff --git a/arch/mips/gt64120/wrppmc/Makefile b/arch/mips/gt64120/wrppmc/Makefile
new file mode 100644 (file)
index 0000000..72606b9
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright 2006 Wind River System, Inc.
+# Author: Rongkai.Zhan <rongkai.zhan@windriver.com>
+#
+# Makefile for the Wind River MIPS 4KC PPMC Eval Board
+#
+
+obj-y  += int-handler.o irq.o reset.o setup.o time.o pci.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/gt64120/wrppmc/int-handler.S b/arch/mips/gt64120/wrppmc/int-handler.S
new file mode 100644 (file)
index 0000000..edee7b3
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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, 2003 by Ralf Baechle
+ * Copyright (C) Wind River System Inc. Rongkai.Zhan <rongkai.zhan@windriver.com>
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/mach-wrppmc/mach-gt64120.h>
+
+       .align  5
+       .set    noat
+NESTED(handle_IRQ, PT_SIZE, sp)
+       SAVE_ALL
+       CLI                             # Important: mark KERNEL mode !
+       .set    at
+
+       mfc0    t0, CP0_CAUSE           # get pending interrupts
+       mfc0    t1, CP0_STATUS          # get enabled interrupts
+       and     t0, t0, t1              # get allowed interrupts
+       andi    t0, t0, 0xFF00
+       beqz    t0, 1f
+       move    a1, sp                  # Prepare 'struct pt_regs *regs' pointer
+
+       andi    t1, t0, CAUSEF_IP7      # CPU Compare/Count internal timer
+       bnez    t1, handle_cputimer_irq
+       andi    t1, t0, CAUSEF_IP6      # UART 16550 port
+       bnez    t1, handle_uart_irq
+       andi    t1, t0, CAUSEF_IP3      # PCI INT_A
+       bnez    t1, handle_pci_intA_irq
+
+       /* wrong alarm or masked ... */
+1:     j       spurious_interrupt
+       nop
+END(handle_IRQ)
+
+       .align  5
+handle_cputimer_irq:
+       li      a0, WRPPMC_MIPS_TIMER_IRQ
+       jal     do_IRQ
+       j       ret_from_irq
+
+       .align  5
+handle_uart_irq:
+       li      a0, WRPPMC_UART16550_IRQ
+       jal     do_IRQ
+       j       ret_from_irq
+
+       .align  5
+handle_pci_intA_irq:
+       li      a0, WRPPMC_PCI_INTA_IRQ
+       jal     do_IRQ
+       j       ret_from_irq
+
diff --git a/arch/mips/gt64120/wrppmc/irq.c b/arch/mips/gt64120/wrppmc/irq.c
new file mode 100644 (file)
index 0000000..8605687
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * irq.c: GT64120 Interrupt Controller
+ *
+ * Copyright (C) 2006, Wind River System Inc.
+ * Author: Rongkai.Zhan, <rongkai.zhan@windriver.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.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/irq_cpu.h>
+#include <asm/gt64120.h>
+
+extern asmlinkage void handle_IRQ(void);
+
+/**
+ * Initialize GT64120 Interrupt Controller
+ */
+void gt64120_init_pic(void)
+{
+       /* clear CPU Interrupt Cause Registers */
+       GT_WRITE(GT_INTRCAUSE_OFS, (0x1F << 21));
+       GT_WRITE(GT_HINTRCAUSE_OFS, 0x00);
+
+       /* Disable all interrupts from GT64120 bridge chip */
+       GT_WRITE(GT_INTRMASK_OFS, 0x00);
+       GT_WRITE(GT_HINTRMASK_OFS, 0x00);
+       GT_WRITE(GT_PCI0_ICMASK_OFS, 0x00);
+       GT_WRITE(GT_PCI0_HICMASK_OFS, 0x00);
+}
+
+void __init arch_init_irq(void)
+{
+       /* enable all CPU interrupt bits. */
+       set_c0_status(ST0_IM);  /* IE bit is still 0 */
+
+       /* Install MIPS Interrupt Trap Vector */
+       set_except_vector(0, handle_IRQ);
+
+       /* IRQ 0 - 7 are for MIPS common irq_cpu controller */
+       mips_cpu_irq_init(0);
+
+       gt64120_init_pic();
+}
diff --git a/arch/mips/gt64120/wrppmc/pci.c b/arch/mips/gt64120/wrppmc/pci.c
new file mode 100644 (file)
index 0000000..2fbe934
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * pci.c: GT64120 PCI support.
+ *
+ * Copyright (C) 2006, Wind River System Inc. Rongkai.Zhan <rongkai.zhan@windriver.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <asm/gt64120.h>
+
+extern struct pci_ops gt64120_pci_ops;
+
+static struct resource pci0_io_resource = {
+       .name  = "pci_0 io",
+       .start = GT_PCI_IO_BASE,
+       .end   = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1,
+       .flags = IORESOURCE_IO,
+};
+
+static struct resource pci0_mem_resource = {
+       .name  = "pci_0 memory",
+       .start = GT_PCI_MEM_BASE,
+       .end   = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1,
+       .flags = IORESOURCE_MEM,
+};
+
+static struct pci_controller hose_0 = {
+       .pci_ops        = &gt64120_pci_ops,
+       .io_resource    = &pci0_io_resource,
+       .mem_resource   = &pci0_mem_resource,
+};
+
+static int __init gt64120_pci_init(void)
+{
+       u32 tmp;
+
+       tmp = GT_READ(GT_PCI0_CMD_OFS);         /* Huh??? -- Ralf  */
+       tmp = GT_READ(GT_PCI0_BARE_OFS);
+
+       /* reset the whole PCI I/O space range */
+       ioport_resource.start = GT_PCI_IO_BASE;
+       ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+
+       register_pci_controller(&hose_0);
+       return 0;
+}
+
+arch_initcall(gt64120_pci_init);
diff --git a/arch/mips/gt64120/wrppmc/reset.c b/arch/mips/gt64120/wrppmc/reset.c
new file mode 100644 (file)
index 0000000..b97039c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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) 1997 Ralf Baechle
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+
+void wrppmc_machine_restart(char *command)
+{
+       /*
+        * Ouch, we're still alive ... This time we take the silver bullet ...
+        * ... and find that we leave the hardware in a state in which the
+        * kernel in the flush locks up somewhen during of after the PCI
+        * detection stuff.
+        */
+       local_irq_disable();
+       set_c0_status(ST0_BEV | ST0_ERL);
+       change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+       flush_cache_all();
+       write_c0_wired(0);
+       __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void wrppmc_machine_halt(void)
+{
+       local_irq_disable();
+
+       printk(KERN_NOTICE "You can safely turn off the power\n");
+       while (1) {
+               __asm__(
+                       ".set\tmips3\n\t"
+                       "wait\n\t"
+                       ".set\tmips0"
+               );
+       }
+}
+
+void wrppmc_machine_power_off(void)
+{
+       wrppmc_machine_halt();
+}
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c
new file mode 100644 (file)
index 0000000..20c591e
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * setup.c: Setup pointers to hardware dependent routines.
+ *
+ * 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) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006, Wind River System Inc. Rongkai.zhan <rongkai.zhan@windriver.com>
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/pm.h>
+
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/gt64120.h>
+
+unsigned long gt64120_base = KSEG1ADDR(0x14000000);
+
+#ifdef WRPPMC_EARLY_DEBUG
+
+static volatile unsigned char * wrppmc_led = \
+       (volatile unsigned char *)KSEG1ADDR(WRPPMC_LED_BASE);
+
+/*
+ * PPMC LED control register:
+ * -) bit[0] controls DS1 LED (1 - OFF, 0 - ON)
+ * -) bit[1] controls DS2 LED (1 - OFF, 0 - ON)
+ * -) bit[2] controls DS4 LED (1 - OFF, 0 - ON)
+ */
+void wrppmc_led_on(int mask)
+{
+       unsigned char value = *wrppmc_led;
+
+       value &= (0xF8 | mask);
+       *wrppmc_led = value;
+}
+
+/* If mask = 0, turn off all LEDs */
+void wrppmc_led_off(int mask)
+{
+       unsigned char value = *wrppmc_led;
+
+       value |= (0x7 & mask);
+       *wrppmc_led = value;
+}
+
+/*
+ * We assume that bootloader has initialized UART16550 correctly
+ */
+void __init wrppmc_early_putc(char ch)
+{
+       static volatile unsigned char *wrppmc_uart = \
+               (volatile unsigned char *)KSEG1ADDR(WRPPMC_UART16550_BASE);
+       unsigned char value;
+
+       /* Wait until Transmit-Holding-Register is empty */
+       while (1) {
+               value = *(wrppmc_uart + 5);
+               if (value & 0x20)
+                       break;
+       }
+
+       *wrppmc_uart = ch;
+}
+
+void __init wrppmc_early_printk(const char *fmt, ...)
+{
+       static char pbuf[256] = {'\0', };
+       char *ch = pbuf;
+       va_list args;
+       unsigned int i;
+
+       memset(pbuf, 0, 256);
+       va_start(args, fmt);
+       i = vsprintf(pbuf, fmt, args);
+       va_end(args);
+
+       /* Print the string */
+       while (*ch != '\0') {
+               wrppmc_early_putc(*ch);
+               /* if print '\n', also print '\r' */
+               if (*ch++ == '\n')
+                       wrppmc_early_putc('\r');
+       }
+}
+#endif /* WRPPMC_EARLY_DEBUG */
+
+unsigned long __init prom_free_prom_memory(void)
+{
+       return 0;
+}
+
+#ifdef CONFIG_SERIAL_8250
+static void wrppmc_setup_serial(void)
+{
+       struct uart_port up;
+
+       memset(&up, 0x00, sizeof(struct uart_port));
+
+       /*
+        * A note about mapbase/membase
+        * -) mapbase is the physical address of the IO port.
+        * -) membase is an 'ioremapped' cookie.
+        */
+       up.line = 0;
+       up.type = PORT_16550;
+       up.iotype = UPIO_MEM;
+       up.mapbase = WRPPMC_UART16550_BASE;
+       up.membase = ioremap(up.mapbase, 8);
+       up.irq = WRPPMC_UART16550_IRQ;
+       up.uartclk = WRPPMC_UART16550_CLOCK;
+       up.flags = UPF_SKIP_TEST/* | UPF_BOOT_AUTOCONF */;
+       up.regshift = 0;
+
+       early_serial_setup(&up);
+}
+#endif
+
+void __init plat_setup(void)
+{
+       extern void wrppmc_time_init(void);
+       extern void wrppmc_timer_setup(struct irqaction *);
+       extern void wrppmc_machine_restart(char *command);
+       extern void wrppmc_machine_halt(void);
+       extern void wrppmc_machine_power_off(void);
+
+       _machine_restart = wrppmc_machine_restart;
+       _machine_halt    = wrppmc_machine_halt;
+       pm_power_off     = wrppmc_machine_power_off;
+
+       /* Use MIPS Count/Compare Timer */
+       board_time_init   = wrppmc_time_init;
+       board_timer_setup = wrppmc_timer_setup;
+
+       /* This makes the operations of 'in/out[bwl]' to the
+        * physical address ( < KSEG0) can work via KSEG1
+        */
+       set_io_port_base(KSEG1);
+
+#ifdef CONFIG_SERIAL_8250
+       wrppmc_setup_serial();
+#endif
+}
+
+const char *get_system_type(void)
+{
+       return "Wind River PPMC (GT64120)";
+}
+
+/*
+ * Initializes basic routines and structures pointers, memory size (as
+ * given by the bios and saves the command line.
+ */
+void __init prom_init(void)
+{
+       mips_machgroup = MACH_GROUP_GALILEO;
+       mips_machtype = MACH_EV64120A;
+
+       add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM);
+       add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA);
+
+       wrppmc_early_printk("prom_init: GT64120 SDRAM Bank 0: 0x%x - 0x%08lx\n",
+                       WRPPMC_SDRAM_SCS0_BASE, (WRPPMC_SDRAM_SCS0_BASE + WRPPMC_SDRAM_SCS0_SIZE));
+}
diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c
new file mode 100644 (file)
index 0000000..175d22a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * time.c: MIPS CPU Count/Compare timer hookup
+ *
+ * Author: Mark.Zhan, <rongkai.zhan@windriver.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.
+ *
+ * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006, Wind River System Inc.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/param.h>       /* for HZ */
+#include <linux/irq.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
+
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/gt64120.h>
+
+#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */
+
+void __init wrppmc_timer_setup(struct irqaction *irq)
+{
+       /* Install ISR for timer interrupt */
+       setup_irq(WRPPMC_MIPS_TIMER_IRQ, irq);
+
+       /* to generate the first timer interrupt */
+       write_c0_compare(mips_hpt_frequency/HZ);
+       write_c0_count(0);
+}
+
+/*
+ * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect
+ *
+ * NOTE: We disable all GT64120 timers, and use MIPS processor internal
+ * timer as the source of kernel clock tick.
+ */
+void __init wrppmc_time_init(void)
+{
+       /* Disable GT64120 timers */
+       GT_WRITE(GT_TC_CONTROL_OFS, 0x00);
+       GT_WRITE(GT_TC0_OFS, 0x00);
+       GT_WRITE(GT_TC1_OFS, 0x00);
+       GT_WRITE(GT_TC2_OFS, 0x00);
+       GT_WRITE(GT_TC3_OFS, 0x00);
+
+       /* Use MIPS compare/count internal timer */
+       mips_hpt_frequency = WRPPMC_CPU_CLK_FREQ;
+}
index c4f8530fd07e95c129c6c11ae3f7a530c360838e..6a7ccaf9350247d1fea9a44d427151ee2e71b918 100644 (file)
@@ -72,7 +72,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
        /* disable interrupts */
        UART16550_WRITE(OFS_INTR_ENABLE, 0);
 
-       /* set up buad rate */
+       /* set up baud rate */
        {
                uint32 divisor;
 
index fc73c8d69df7cd2a3a18f8c191662695ce17deac..da6ae0991199a4214bb6e2ad227864fb49351aa3 100644 (file)
@@ -72,11 +72,29 @@ struct {
     struct resource flash;
     struct resource boot;
 } it8172_resources = {
-    { "RAM",           0,          0,          IORESOURCE_MEM }, /* to be initted */
-    { "PCI Mem",       0x10000000, 0x13FFFFFF, IORESOURCE_MEM },
-    { "PCI I/O",       0x14000000, 0x17FFFFFF                 },
-    { "Flash",         0x08000000, 0x0CFFFFFF                 },
-    { "Boot ROM",      0x1FC00000, 0x1FFFFFFF                 }
+       {
+               .start  = 0,                            /* to be initted */
+               .end    = 0,
+               .name   = "RAM",
+               .flags  = IORESOURCE_MEM
+       }, {
+               .start  = 0x10000000,
+               .end    = 0x13FFFFFF,
+               .name   = "PCI Mem",
+               .flags  = IORESOURCE_MEM
+       }, {
+               .start  = 0x14000000,
+               .end    = 0x17FFFFFF
+               .name   = "PCI I/O",
+       }, {
+               .start  = 0x08000000,
+               .end    = 0x0CFFFFFF
+               .name   = "Flash",
+       }, {
+               .start  = 0x1FC00000,
+               .end    = 0x1FFFFFFF
+               .name   = "Boot ROM",
+       }
 };
 #else
 struct {
@@ -89,14 +107,44 @@ struct {
     struct resource flash;
     struct resource boot;
 } it8172_resources = {
-    { "RAM",           0,          0,          IORESOURCE_MEM }, /* to be initted */
-    { "PCI Mem0",      0x0C000000, 0x0FFFFFFF, IORESOURCE_MEM },
-    { "PCI Mem1",      0x10000000, 0x13FFFFFF, IORESOURCE_MEM },
-    { "PCI I/O",       0x14000000, 0x17FFFFFF                 },
-    { "PCI Mem2",      0x1A000000, 0x1BFFFFFF, IORESOURCE_MEM },
-    { "PCI Mem3",      0x1C000000, 0x1FBFFFFF, IORESOURCE_MEM },
-    { "Flash",         0x08000000, 0x0CFFFFFF                 },
-    { "Boot ROM",      0x1FC00000, 0x1FFFFFFF                 }
+       {
+               .start  = 0,                            /* to be initted */
+               .end    = 0,
+               .name   = "RAM",
+               .flags  = IORESOURCE_MEM
+       }, {
+               .start  = 0x0C000000,
+               .end    = 0x0FFFFFFF,
+               .name   = "PCI Mem0",
+               .flags  = IORESOURCE_MEM
+        }, {
+               .start  = 0x10000000,
+               .end    = 0x13FFFFFF,
+               .name   = "PCI Mem1",
+               .flags  = IORESOURCE_MEM
+        }, {
+               .start  = 0x14000000,
+               .end    = 0x17FFFFFF
+               .name   = "PCI I/O",
+       }, {
+               .start  = 0x1A000000,
+               .end    = 0x1BFFFFFF,
+               .name   = "PCI Mem2",
+               .flags  = IORESOURCE_MEM
+       }, {
+               .start  = 0x1C000000,
+               .end    = 0x1FBFFFFF,
+               .name   = "PCI Mem3",
+               .flags  = IORESOURCE_MEM
+       }, {
+               .start  = 0x08000000,
+               .end    = 0x0CFFFFFF
+               .name   = "Flash",
+       }, {
+               .start  = 0x1FC00000,
+               .end    = 0x1FFFFFFF
+               .name   = "Boot ROM",
+       }
 };
 #endif
 
@@ -106,7 +154,7 @@ void __init it8172_init_ram_resource(unsigned long memsize)
        it8172_resources.ram.end = memsize;
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        unsigned short dsr;
        char *argptr;
index 4036dc4345515fd1c251d96c0a63012ad10b8898..c8d0df7d0c36ceed402bb68913183e3518152556 100644 (file)
@@ -52,7 +52,7 @@ static struct resource jazz_io_resources[] = {
        { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
 };
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        int i;
 
index 9359cc4134946cb6c5fb99b1bd33c6343f47d3f4..308e6cdcd24523edba00e8b7d97d3d13cac603d1 100644 (file)
@@ -82,17 +82,54 @@ struct {
     struct resource sio0;
     struct resource sio1;
 } jmr3927_resources = {
-    { "RAM0",           0,         0x01FFFFFF,  IORESOURCE_MEM },
-    { "RAM1",          0x02000000, 0x03FFFFFF,  IORESOURCE_MEM },
-    { "PCIMEM",        0x08000000, 0x07FFFFFF,  IORESOURCE_MEM },
-    { "IOB",           0x10000000, 0x13FFFFFF                  },
-    { "IOC",           0x14000000, 0x14FFFFFF                  },
-    { "PCIIO",         0x15000000, 0x15FFFFFF                  },
-    { "JMY1394",       0x1D000000, 0x1D3FFFFF                  },
-    { "ROM1",          0x1E000000, 0x1E3FFFFF                  },
-    { "ROM0",          0x1FC00000, 0x1FFFFFFF                  },
-    { "SIO0",          0xFFFEF300, 0xFFFEF3FF                  },
-    { "SIO1",          0xFFFEF400, 0xFFFEF4FF                  },
+       {
+               .start  = 0,
+               .end    = 0x01FFFFFF,
+               .name   = "RAM0",
+               .flags = IORESOURCE_MEM
+       }, {
+               .start  = 0x02000000,
+               .end    = 0x03FFFFFF,
+               .name   = "RAM1",
+               .flags = IORESOURCE_MEM
+       }, {
+               .start  = 0x08000000,
+               .end    = 0x07FFFFFF,
+               .name   = "PCIMEM",
+               .flags = IORESOURCE_MEM
+       }, {
+               .start  = 0x10000000,
+               .end    = 0x13FFFFFF,
+               .name   = "IOB"
+       }, {
+               .start  = 0x14000000,
+               .end    = 0x14FFFFFF,
+               .name   = "IOC"
+       }, {
+               .start  = 0x15000000,
+               .end    = 0x15FFFFFF,
+               .name   = "PCIIO"
+       }, {
+               .start  = 0x1D000000,
+               .end    = 0x1D3FFFFF,
+               .name   = "JMY1394"
+       }, {
+               .start  = 0x1E000000,
+               .end    = 0x1E3FFFFF,
+               .name   = "ROM1"
+       }, {
+               .start  = 0x1FC00000,
+               .end    = 0x1FFFFFFF,
+               .name   = "ROM0"
+       }, {
+               .start  = 0xFFFEF300,
+               .end    = 0xFFFEF3FF,
+               .name   = "SIO0"
+       }, {
+               .start  = 0xFFFEF400,
+               .end    = 0xFFFEF4FF,
+               .name   = "SIO1"
+       },
 };
 
 /* don't enable - see errata */
@@ -201,7 +238,7 @@ static void jmr3927_board_init(void);
 extern struct resource pci_io_resource;
 extern struct resource pci_mem_resource;
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        char *argptr;
 
index 34e8a256765c3f2a811e6c6edc701ccb6544b032..881c467c698241d2902454b603de9b4e4dae4ae7 100644 (file)
@@ -13,6 +13,8 @@ binfmt_irix-objs      := irixelf.o irixinv.o irixioctl.o irixsig.o    \
 
 obj-$(CONFIG_MODULES)          += mips_ksyms.o module.o
 
+obj-$(CONFIG_APM)              += apm.o
+
 obj-$(CONFIG_CPU_R3000)                += r2300_fpu.o r2300_switch.o
 obj-$(CONFIG_CPU_TX39XX)       += r2300_fpu.o r2300_switch.o
 obj-$(CONFIG_CPU_TX49XX)       += r4k_fpu.o r4k_switch.o
diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c
new file mode 100644 (file)
index 0000000..15f46b4
--- /dev/null
@@ -0,0 +1,605 @@
+/*
+ * bios-less APM driver for MIPS Linux
+ *  Jamey Hicks <jamey@crl.dec.com>
+ *  adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * APM 1.2 Reference:
+ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
+ *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Microsoft at:
+ *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/apm_bios.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+
+#include <asm/apm.h> /* apm_power_info */
+#include <asm/system.h>
+
+/*
+ * The apm_bios device is one of the misc char devices.
+ * This is its minor number.
+ */
+#define APM_MINOR_DEV  134
+
+/*
+ * See Documentation/Config.help for the configuration options.
+ *
+ * Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
+ *     apm=on/off                      enable/disable APM
+ */
+
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS         16
+
+struct apm_queue {
+       unsigned int            event_head;
+       unsigned int            event_tail;
+       apm_event_t             events[APM_MAX_EVENTS];
+};
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+       struct list_head        list;
+
+       unsigned int            suser: 1;
+       unsigned int            writer: 1;
+       unsigned int            reader: 1;
+
+       int                     suspend_result;
+       unsigned int            suspend_state;
+#define SUSPEND_NONE   0               /* no suspend pending */
+#define SUSPEND_PENDING        1               /* suspend pending read */
+#define SUSPEND_READ   2               /* suspend read, pending ack */
+#define SUSPEND_ACKED  3               /* suspend acked */
+#define SUSPEND_DONE   4               /* suspend completed */
+
+       struct apm_queue        queue;
+};
+
+/*
+ * Local variables
+ */
+static int suspends_pending;
+static int apm_disabled;
+static int mips_apm_active;
+
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+
+/*
+ * This is a list of everyone who has opened /dev/apm_bios
+ */
+static DECLARE_RWSEM(user_list_lock);
+static LIST_HEAD(apm_user_list);
+
+/*
+ * kapmd info.  kapmd provides us a process context to handle
+ * "APM" events within - specifically necessary if we're going
+ * to be suspending the system.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
+static DECLARE_COMPLETION(kapmd_exit);
+static DEFINE_SPINLOCK(kapmd_queue_lock);
+static struct apm_queue kapmd_queue;
+
+
+static const char driver_version[] = "1.13";   /* no spaces */
+
+
+
+/*
+ * Compatibility cruft until the IPAQ people move over to the new
+ * interface.
+ */
+static void __apm_get_power_status(struct apm_power_info *info)
+{
+}
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
+EXPORT_SYMBOL(apm_get_power_status);
+
+
+/*
+ * APM event queue management.
+ */
+static inline int queue_empty(struct apm_queue *q)
+{
+       return q->event_head == q->event_tail;
+}
+
+static inline apm_event_t queue_get_event(struct apm_queue *q)
+{
+       q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+       return q->events[q->event_tail];
+}
+
+static void queue_add_event(struct apm_queue *q, apm_event_t event)
+{
+       q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
+       if (q->event_head == q->event_tail) {
+               static int notified;
+
+               if (notified++ == 0)
+                   printk(KERN_ERR "apm: an event queue overflowed\n");
+               q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+       }
+       q->events[q->event_head] = event;
+}
+
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+       if (as->suser && as->writer) {
+               switch (event) {
+               case APM_SYS_SUSPEND:
+               case APM_USER_SUSPEND:
+                       /*
+                        * If this user already has a suspend pending,
+                        * don't queue another one.
+                        */
+                       if (as->suspend_state != SUSPEND_NONE)
+                               return;
+
+                       as->suspend_state = SUSPEND_PENDING;
+                       suspends_pending++;
+                       break;
+               }
+       }
+       queue_add_event(&as->queue, event);
+}
+
+static void queue_event(apm_event_t event, struct apm_user *sender)
+{
+       struct apm_user *as;
+
+       down_read(&user_list_lock);
+       list_for_each_entry(as, &apm_user_list, list) {
+               if (as != sender && as->reader)
+                       queue_event_one_user(as, event);
+       }
+       up_read(&user_list_lock);
+       wake_up_interruptible(&apm_waitqueue);
+}
+
+static void apm_suspend(void)
+{
+       struct apm_user *as;
+       int err = pm_suspend(PM_SUSPEND_MEM);
+
+       /*
+        * Anyone on the APM queues will think we're still suspended.
+        * Send a message so everyone knows we're now awake again.
+        */
+       queue_event(APM_NORMAL_RESUME, NULL);
+
+       /*
+        * Finally, wake up anyone who is sleeping on the suspend.
+        */
+       down_read(&user_list_lock);
+       list_for_each_entry(as, &apm_user_list, list) {
+               as->suspend_result = err;
+               as->suspend_state = SUSPEND_DONE;
+       }
+       up_read(&user_list_lock);
+
+       wake_up(&apm_suspend_waitqueue);
+}
+
+static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
+{
+       struct apm_user *as = fp->private_data;
+       apm_event_t event;
+       int i = count, ret = 0;
+
+       if (count < sizeof(apm_event_t))
+               return -EINVAL;
+
+       if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
+               return -EAGAIN;
+
+       wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
+
+       while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
+               event = queue_get_event(&as->queue);
+
+               ret = -EFAULT;
+               if (copy_to_user(buf, &event, sizeof(event)))
+                       break;
+
+               if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
+                       as->suspend_state = SUSPEND_READ;
+
+               buf += sizeof(event);
+               i -= sizeof(event);
+       }
+
+       if (i < count)
+               ret = count - i;
+
+       return ret;
+}
+
+static unsigned int apm_poll(struct file *fp, poll_table * wait)
+{
+       struct apm_user *as = fp->private_data;
+
+       poll_wait(fp, &apm_waitqueue, wait);
+       return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
+}
+
+/*
+ * apm_ioctl - handle APM ioctl
+ *
+ * APM_IOC_SUSPEND
+ *   This IOCTL is overloaded, and performs two functions.  It is used to:
+ *     - initiate a suspend
+ *     - acknowledge a suspend read from /dev/apm_bios.
+ *   Only when everyone who has opened /dev/apm_bios with write permission
+ *   has acknowledge does the actual suspend happen.
+ */
+static int
+apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
+{
+       struct apm_user *as = filp->private_data;
+       unsigned long flags;
+       int err = -EINVAL;
+
+       if (!as->suser || !as->writer)
+               return -EPERM;
+
+       switch (cmd) {
+       case APM_IOC_SUSPEND:
+               as->suspend_result = -EINTR;
+
+               if (as->suspend_state == SUSPEND_READ) {
+                       /*
+                        * If we read a suspend command from /dev/apm_bios,
+                        * then the corresponding APM_IOC_SUSPEND ioctl is
+                        * interpreted as an acknowledge.
+                        */
+                       as->suspend_state = SUSPEND_ACKED;
+                       suspends_pending--;
+               } else {
+                       /*
+                        * Otherwise it is a request to suspend the system.
+                        * Queue an event for all readers, and expect an
+                        * acknowledge from all writers who haven't already
+                        * acknowledged.
+                        */
+                       queue_event(APM_USER_SUSPEND, as);
+               }
+
+               /*
+                * If there are no further acknowledges required, suspend
+                * the system.
+                */
+               if (suspends_pending == 0)
+                       apm_suspend();
+
+               /*
+                * Wait for the suspend/resume to complete.  If there are
+                * pending acknowledges, we wait here for them.
+                *
+                * Note that we need to ensure that the PM subsystem does
+                * not kick us out of the wait when it suspends the threads.
+                */
+               flags = current->flags;
+               current->flags |= PF_NOFREEZE;
+
+               /*
+                * Note: do not allow a thread which is acking the suspend
+                * to escape until the resume is complete.
+                */
+               if (as->suspend_state == SUSPEND_ACKED)
+                       wait_event(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+               else
+                       wait_event_interruptible(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+
+               current->flags = flags;
+               err = as->suspend_result;
+               as->suspend_state = SUSPEND_NONE;
+               break;
+       }
+
+       return err;
+}
+
+static int apm_release(struct inode * inode, struct file * filp)
+{
+       struct apm_user *as = filp->private_data;
+       filp->private_data = NULL;
+
+       down_write(&user_list_lock);
+       list_del(&as->list);
+       up_write(&user_list_lock);
+
+       /*
+        * We are now unhooked from the chain.  As far as new
+        * events are concerned, we no longer exist.  However, we
+        * need to balance suspends_pending, which means the
+        * possibility of sleeping.
+        */
+       if (as->suspend_state != SUSPEND_NONE) {
+               suspends_pending -= 1;
+               if (suspends_pending == 0)
+                       apm_suspend();
+       }
+
+       kfree(as);
+       return 0;
+}
+
+static int apm_open(struct inode * inode, struct file * filp)
+{
+       struct apm_user *as;
+
+       as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
+       if (as) {
+               /*
+                * XXX - this is a tiny bit broken, when we consider BSD
+                * process accounting. If the device is opened by root, we
+                * instantly flag that we used superuser privs. Who knows,
+                * we might close the device immediately without doing a
+                * privileged operation -- cevans
+                */
+               as->suser = capable(CAP_SYS_ADMIN);
+               as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
+               as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+
+               down_write(&user_list_lock);
+               list_add(&as->list, &apm_user_list);
+               up_write(&user_list_lock);
+
+               filp->private_data = as;
+       }
+
+       return as ? 0 : -ENOMEM;
+}
+
+static struct file_operations apm_bios_fops = {
+       .owner          = THIS_MODULE,
+       .read           = apm_read,
+       .poll           = apm_poll,
+       .ioctl          = apm_ioctl,
+       .open           = apm_open,
+       .release        = apm_release,
+};
+
+static struct miscdevice apm_device = {
+       .minor          = APM_MINOR_DEV,
+       .name           = "apm_bios",
+       .fops           = &apm_bios_fops
+};
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Arguments, with symbols from linux/apm_bios.h.
+ *
+ *   0) Linux driver version (this will change if format changes)
+ *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
+ *   2) APM flags from APM Installation Check (0x00):
+ *     bit 0: APM_16_BIT_SUPPORT
+ *     bit 1: APM_32_BIT_SUPPORT
+ *     bit 2: APM_IDLE_SLOWS_CLOCK
+ *     bit 3: APM_BIOS_DISABLED
+ *     bit 4: APM_BIOS_DISENGAGED
+ *   3) AC line status
+ *     0x00: Off-line
+ *     0x01: On-line
+ *     0x02: On backup power (BIOS >= 1.1 only)
+ *     0xff: Unknown
+ *   4) Battery status
+ *     0x00: High
+ *     0x01: Low
+ *     0x02: Critical
+ *     0x03: Charging
+ *     0x04: Selected battery not present (BIOS >= 1.2 only)
+ *     0xff: Unknown
+ *   5) Battery flag
+ *     bit 0: High
+ *     bit 1: Low
+ *     bit 2: Critical
+ *     bit 3: Charging
+ *     bit 7: No system battery
+ *     0xff: Unknown
+ *   6) Remaining battery life (percentage of charge):
+ *     0-100: valid
+ *     -1: Unknown
+ *   7) Remaining battery life (time units):
+ *     Number of remaining minutes or seconds
+ *     -1: Unknown
+ *   8) min = minutes; sec = seconds
+ */
+static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+{
+       struct apm_power_info info;
+       char *units;
+       int ret;
+
+       info.ac_line_status = 0xff;
+       info.battery_status = 0xff;
+       info.battery_flag   = 0xff;
+       info.battery_life   = -1;
+       info.time           = -1;
+       info.units          = -1;
+
+       if (apm_get_power_status)
+               apm_get_power_status(&info);
+
+       switch (info.units) {
+       default:        units = "?";    break;
+       case 0:         units = "min";  break;
+       case 1:         units = "sec";  break;
+       }
+
+       ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+                    driver_version, APM_32_BIT_SUPPORT,
+                    info.ac_line_status, info.battery_status,
+                    info.battery_flag, info.battery_life,
+                    info.time, units);
+
+       return ret;
+}
+#endif
+
+static int kapmd(void *arg)
+{
+       daemonize("kapmd");
+       current->flags |= PF_NOFREEZE;
+
+       do {
+               apm_event_t event;
+
+               wait_event_interruptible(kapmd_wait,
+                               !queue_empty(&kapmd_queue) || !mips_apm_active);
+
+               if (!mips_apm_active)
+                       break;
+
+               spin_lock_irq(&kapmd_queue_lock);
+               event = 0;
+               if (!queue_empty(&kapmd_queue))
+                       event = queue_get_event(&kapmd_queue);
+               spin_unlock_irq(&kapmd_queue_lock);
+
+               switch (event) {
+               case 0:
+                       break;
+
+               case APM_LOW_BATTERY:
+               case APM_POWER_STATUS_CHANGE:
+                       queue_event(event, NULL);
+                       break;
+
+               case APM_USER_SUSPEND:
+               case APM_SYS_SUSPEND:
+                       queue_event(event, NULL);
+                       if (suspends_pending == 0)
+                               apm_suspend();
+                       break;
+
+               case APM_CRITICAL_SUSPEND:
+                       apm_suspend();
+                       break;
+               }
+       } while (1);
+
+       complete_and_exit(&kapmd_exit, 0);
+}
+
+static int __init apm_init(void)
+{
+       int ret;
+
+       if (apm_disabled) {
+               printk(KERN_NOTICE "apm: disabled on user request.\n");
+               return -ENODEV;
+       }
+
+       mips_apm_active = 1;
+
+       ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
+       if (ret < 0) {
+               mips_apm_active = 0;
+               return ret;
+       }
+
+#ifdef CONFIG_PROC_FS
+       create_proc_info_entry("apm", 0, NULL, apm_get_info);
+#endif
+
+       ret = misc_register(&apm_device);
+       if (ret != 0) {
+               remove_proc_entry("apm", NULL);
+
+               mips_apm_active = 0;
+               wake_up(&kapmd_wait);
+               wait_for_completion(&kapmd_exit);
+       }
+
+       return ret;
+}
+
+static void __exit apm_exit(void)
+{
+       misc_deregister(&apm_device);
+       remove_proc_entry("apm", NULL);
+
+       mips_apm_active = 0;
+       wake_up(&kapmd_wait);
+       wait_for_completion(&kapmd_exit);
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_LICENSE("GPL");
+
+#ifndef MODULE
+static int __init apm_setup(char *str)
+{
+       while ((str != NULL) && (*str != '\0')) {
+               if (strncmp(str, "off", 3) == 0)
+                       apm_disabled = 1;
+               if (strncmp(str, "on", 2) == 0)
+                       apm_disabled = 0;
+               str = strchr(str, ',');
+               if (str != NULL)
+                       str += strspn(str, ", \t");
+       }
+       return 1;
+}
+
+__setup("apm=", apm_setup);
+#endif
+
+/**
+ * apm_queue_event - queue an APM event for kapmd
+ * @event: APM event
+ *
+ * Queue an APM event for kapmd to process and ultimately take the
+ * appropriate action.  Only a subset of events are handled:
+ *   %APM_LOW_BATTERY
+ *   %APM_POWER_STATUS_CHANGE
+ *   %APM_USER_SUSPEND
+ *   %APM_SYS_SUSPEND
+ *   %APM_CRITICAL_SUSPEND
+ */
+void apm_queue_event(apm_event_t event)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&kapmd_queue_lock, flags);
+       queue_add_event(&kapmd_queue, event);
+       spin_unlock_irqrestore(&kapmd_queue_lock, flags);
+
+       wake_up_interruptible(&kapmd_wait);
+}
+EXPORT_SYMBOL(apm_queue_event);
index 92b28b674d6f615be8ab8894ea117e06018f44d1..f1bb6a2dc5fcdc6c898ba6921b84314e4f2815b1 100644 (file)
@@ -141,72 +141,72 @@ void output_thread_defines(void)
 void output_thread_fpu_defines(void)
 {
        offset("#define THREAD_FPR0    ",
-              struct task_struct, thread.fpu.hard.fpr[0]);
+              struct task_struct, thread.fpu.fpr[0]);
        offset("#define THREAD_FPR1    ",
-              struct task_struct, thread.fpu.hard.fpr[1]);
+              struct task_struct, thread.fpu.fpr[1]);
        offset("#define THREAD_FPR2    ",
-              struct task_struct, thread.fpu.hard.fpr[2]);
+              struct task_struct, thread.fpu.fpr[2]);
        offset("#define THREAD_FPR3    ",
-              struct task_struct, thread.fpu.hard.fpr[3]);
+              struct task_struct, thread.fpu.fpr[3]);
        offset("#define THREAD_FPR4    ",
-              struct task_struct, thread.fpu.hard.fpr[4]);
+              struct task_struct, thread.fpu.fpr[4]);
        offset("#define THREAD_FPR5    ",
-              struct task_struct, thread.fpu.hard.fpr[5]);
+              struct task_struct, thread.fpu.fpr[5]);
        offset("#define THREAD_FPR6    ",
-              struct task_struct, thread.fpu.hard.fpr[6]);
+              struct task_struct, thread.fpu.fpr[6]);
        offset("#define THREAD_FPR7    ",
-              struct task_struct, thread.fpu.hard.fpr[7]);
+              struct task_struct, thread.fpu.fpr[7]);
        offset("#define THREAD_FPR8    ",
-              struct task_struct, thread.fpu.hard.fpr[8]);
+              struct task_struct, thread.fpu.fpr[8]);
        offset("#define THREAD_FPR9    ",
-              struct task_struct, thread.fpu.hard.fpr[9]);
+              struct task_struct, thread.fpu.fpr[9]);
        offset("#define THREAD_FPR10   ",
-              struct task_struct, thread.fpu.hard.fpr[10]);
+              struct task_struct, thread.fpu.fpr[10]);
        offset("#define THREAD_FPR11   ",
-              struct task_struct, thread.fpu.hard.fpr[11]);
+              struct task_struct, thread.fpu.fpr[11]);
        offset("#define THREAD_FPR12   ",
-              struct task_struct, thread.fpu.hard.fpr[12]);
+              struct task_struct, thread.fpu.fpr[12]);
        offset("#define THREAD_FPR13   ",
-              struct task_struct, thread.fpu.hard.fpr[13]);
+              struct task_struct, thread.fpu.fpr[13]);
        offset("#define THREAD_FPR14   ",
-              struct task_struct, thread.fpu.hard.fpr[14]);
+              struct task_struct, thread.fpu.fpr[14]);
        offset("#define THREAD_FPR15   ",
-              struct task_struct, thread.fpu.hard.fpr[15]);
+              struct task_struct, thread.fpu.fpr[15]);
        offset("#define THREAD_FPR16   ",
-              struct task_struct, thread.fpu.hard.fpr[16]);
+              struct task_struct, thread.fpu.fpr[16]);
        offset("#define THREAD_FPR17   ",
-              struct task_struct, thread.fpu.hard.fpr[17]);
+              struct task_struct, thread.fpu.fpr[17]);
        offset("#define THREAD_FPR18   ",
-              struct task_struct, thread.fpu.hard.fpr[18]);
+              struct task_struct, thread.fpu.fpr[18]);
        offset("#define THREAD_FPR19   ",
-              struct task_struct, thread.fpu.hard.fpr[19]);
+              struct task_struct, thread.fpu.fpr[19]);
        offset("#define THREAD_FPR20   ",
-              struct task_struct, thread.fpu.hard.fpr[20]);
+              struct task_struct, thread.fpu.fpr[20]);
        offset("#define THREAD_FPR21   ",
-              struct task_struct, thread.fpu.hard.fpr[21]);
+              struct task_struct, thread.fpu.fpr[21]);
        offset("#define THREAD_FPR22   ",
-              struct task_struct, thread.fpu.hard.fpr[22]);
+              struct task_struct, thread.fpu.fpr[22]);
        offset("#define THREAD_FPR23   ",
-              struct task_struct, thread.fpu.hard.fpr[23]);
+              struct task_struct, thread.fpu.fpr[23]);
        offset("#define THREAD_FPR24   ",
-              struct task_struct, thread.fpu.hard.fpr[24]);
+              struct task_struct, thread.fpu.fpr[24]);
        offset("#define THREAD_FPR25   ",
-              struct task_struct, thread.fpu.hard.fpr[25]);
+              struct task_struct, thread.fpu.fpr[25]);
        offset("#define THREAD_FPR26   ",
-              struct task_struct, thread.fpu.hard.fpr[26]);
+              struct task_struct, thread.fpu.fpr[26]);
        offset("#define THREAD_FPR27   ",
-              struct task_struct, thread.fpu.hard.fpr[27]);
+              struct task_struct, thread.fpu.fpr[27]);
        offset("#define THREAD_FPR28   ",
-              struct task_struct, thread.fpu.hard.fpr[28]);
+              struct task_struct, thread.fpu.fpr[28]);
        offset("#define THREAD_FPR29   ",
-              struct task_struct, thread.fpu.hard.fpr[29]);
+              struct task_struct, thread.fpu.fpr[29]);
        offset("#define THREAD_FPR30   ",
-              struct task_struct, thread.fpu.hard.fpr[30]);
+              struct task_struct, thread.fpu.fpr[30]);
        offset("#define THREAD_FPR31   ",
-              struct task_struct, thread.fpu.hard.fpr[31]);
+              struct task_struct, thread.fpu.fpr[31]);
 
        offset("#define THREAD_FCR31   ",
-              struct task_struct, thread.fpu.hard.fcr31);
+              struct task_struct, thread.fpu.fcr31);
        linefeed;
 }
 
@@ -272,8 +272,8 @@ void output_sc_defines(void)
        text("/* Linux sigcontext offsets. */");
        offset("#define SC_REGS       ", struct sigcontext, sc_regs);
        offset("#define SC_FPREGS     ", struct sigcontext, sc_fpregs);
-       offset("#define SC_MDHI       ", struct sigcontext, sc_hi);
-       offset("#define SC_MDLO       ", struct sigcontext, sc_lo);
+       offset("#define SC_MDHI       ", struct sigcontext, sc_mdhi);
+       offset("#define SC_MDLO       ", struct sigcontext, sc_mdlo);
        offset("#define SC_PC         ", struct sigcontext, sc_pc);
        offset("#define SC_FPC_CSR    ", struct sigcontext, sc_fpc_csr);
        linefeed;
index b6232d9033cb68c0e1a5a14cde042b83aa95161e..76fd3f22c76624363d94b7e4b870d0e798ff282d 100644 (file)
@@ -178,7 +178,7 @@ int __compute_return_epc(struct pt_regs *regs)
                if (is_fpu_owner())
                        asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
                else
-                       fcr31 = current->thread.fpu.hard.fcr31;
+                       fcr31 = current->thread.fpu.fcr31;
                preempt_enable();
 
                bit = (insn.i_format.rt >> 2);
index 47a087b6c11ba881d33d2aa2d3aaf2ffce50374a..d268827c62bdd167459e8e43d2467781ff9f879a 100644 (file)
@@ -206,7 +206,7 @@ static inline void check_daddi(void)
                "daddi  %0, %1, %3\n\t"
                ".set   pop"
                : "=r" (v), "=&r" (tmp)
-               : "I" (0xffffffffffffdb9a), "I" (0x1234));
+               : "I" (0xffffffffffffdb9aUL), "I" (0x1234));
        set_except_vector(12, handler);
        local_irq_restore(flags);
 
@@ -224,7 +224,7 @@ static inline void check_daddi(void)
                "dsrl   %1, %1, 1\n\t"
                "daddi  %0, %1, %3"
                : "=r" (v), "=&r" (tmp)
-               : "I" (0xffffffffffffdb9a), "I" (0x1234));
+               : "I" (0xffffffffffffdb9aUL), "I" (0x1234));
        set_except_vector(12, handler);
        local_irq_restore(flags);
 
@@ -280,7 +280,7 @@ static inline void check_daddiu(void)
                "daddu  %1, %2\n\t"
                ".set   pop"
                : "=&r" (v), "=&r" (w), "=&r" (tmp)
-               : "I" (0xffffffffffffdb9a), "I" (0x1234));
+               : "I" (0xffffffffffffdb9aUL), "I" (0x1234));
 
        if (v == w) {
                printk("no.\n");
@@ -296,7 +296,7 @@ static inline void check_daddiu(void)
                "addiu  %1, $0, %4\n\t"
                "daddu  %1, %2"
                : "=&r" (v), "=&r" (w), "=&r" (tmp)
-               : "I" (0xffffffffffffdb9a), "I" (0x1234));
+               : "I" (0xffffffffffffdb9aUL), "I" (0x1234));
 
        if (v == w) {
                printk("yes.\n");
index 58b3b14873cb572a10d9a87e2b57cece1fc061b8..8c2c359a05f413bd089a8eb40cf64781ac8bb89a 100644 (file)
@@ -121,6 +121,7 @@ static inline void check_wait(void)
        case CPU_24K:
        case CPU_25KF:
        case CPU_34K:
+       case CPU_74K:
        case CPU_PR4450:
                cpu_wait = r4k_wait;
                printk(" available.\n");
@@ -432,6 +433,15 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
                             MIPS_CPU_LLSC;
                c->tlbsize = 64;
                break;
+       case PRID_IMP_R14000:
+               c->cputype = CPU_R14000;
+               c->isa_level = MIPS_CPU_ISA_IV;
+               c->options = MIPS_CPU_TLB | MIPS_CPU_4K_CACHE | MIPS_CPU_4KEX |
+                            MIPS_CPU_FPU | MIPS_CPU_32FPR |
+                            MIPS_CPU_COUNTER | MIPS_CPU_WATCH |
+                            MIPS_CPU_LLSC;
+               c->tlbsize = 64;
+               break;
        }
 }
 
@@ -593,6 +603,9 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
        case PRID_IMP_34K:
                c->cputype = CPU_34K;
                break;
+       case PRID_IMP_74K:
+               c->cputype = CPU_74K;
+               break;
        }
 }
 
@@ -642,7 +655,7 @@ static inline void cpu_probe_sibyte(struct cpuinfo_mips *c)
        case PRID_IMP_SB1:
                c->cputype = CPU_SB1;
                /* FPU in pass1 is known to have issues. */
-               if ((c->processor_id & 0xff) < 0x20)
+               if ((c->processor_id & 0xff) < 0x02)
                        c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
                break;
        case PRID_IMP_SB1A:
index d101d2fb24caab6f8283647a20a5c37768f30c05..a9c6de1b954257e8e30e73518009f7cf3d1444ae 100644 (file)
@@ -101,7 +101,7 @@ FEXPORT(restore_all)                        # restore full frame
        EMT
 1:
        mfc0    v1, CP0_TCSTATUS
-       /* We set IXMT above, XOR should cler it here */
+       /* We set IXMT above, XOR should clear it here */
        xori    v1, v1, TCSTATUS_IXMT
        or      v1, v0, v1
        mtc0    v1, CP0_TCSTATUS
index 10f28fb9f008a92fc89b68c89734233297e8472b..5fd7a8af0c6256bc720c7fa232ee14d551be3e63 100644 (file)
                 */
                mfc0    k0, CP0_CAUSE
                andi    k0, k0, 0x7c
-               add     k1, k1, k0
-               PTR_L   k0, saved_vectors(k1)
-               jr      k0
+#ifdef CONFIG_64BIT
+               dsll    k0, k0, 1
+#endif
+               PTR_L   k1, saved_vectors(k0)
+               jr      k1
                nop
 1:
                move    k0, sp
index 2125ba5f1d9b20b2d2e0fe282e6513b399546478..0cb8ed5662f3d2cbaa1f0ac6cde7cbfa6f5ff8bb 100644 (file)
@@ -302,11 +302,11 @@ static struct irqaction irq2 = {
 };
 
 static struct resource pic1_io_resource = {
-       "pic1", 0x20, 0x3f, IORESOURCE_BUSY
+       .name = "pic1", .start = 0x20, .end = 0x3f, .flags = IORESOURCE_BUSY
 };
 
 static struct resource pic2_io_resource = {
-       "pic2", 0xa0, 0xbf, IORESOURCE_BUSY
+       .name = "pic2", .start = 0xa0, .end = 0xbf, .flags = IORESOURCE_BUSY
 };
 
 /*
index 8150f071f80afdb28da541119655369ac6686312..a9bf6cc3abd183bd4a9cbd124be08851e6b0ee46 100644 (file)
@@ -260,7 +260,7 @@ irix_sigreturn(struct pt_regs *regs)
 
                for(i = 0; i < 32; i++)
                        error |= __get_user(fregs[i], &context->fpregs[i]);
-               error |= __get_user(current->thread.fpu.hard.fcr31, &context->fpcsr);
+               error |= __get_user(current->thread.fpu.fcr31, &context->fpcsr);
        }
 
        /* XXX do sigstack crapola here... XXX */
index e54a7f442f8adc271af20fcf7ac310e9fb9e8bb0..d7bf0215bc1d28eb40160366afbdd59b41fea470 100644 (file)
@@ -288,6 +288,9 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
                sym = (Elf_Sym *)sechdrs[symindex].sh_addr
                        + ELF_MIPS_R_SYM(rel[i]);
                if (!sym->st_value) {
+                       /* Ignore unresolved weak symbol */
+                       if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
+                               continue;
                        printk(KERN_WARNING "%s: Unknown symbol %s\n",
                               me->name, strtab + sym->st_name);
                        return -ENOENT;
@@ -325,6 +328,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
                sym = (Elf_Sym *)sechdrs[symindex].sh_addr
                        + ELF_MIPS_R_SYM(rel[i]);
                if (!sym->st_value) {
+                       /* Ignore unresolved weak symbol */
+                       if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
+                               continue;
                        printk(KERN_WARNING "%s: Unknown symbol %s\n",
                               me->name, strtab + sym->st_name);
                        return -ENOENT;
index 84ab959f924ac57d1b05edc73aa48ce84c2da04f..9def554f335b8f430dd0483dcca482b83c083d07 100644 (file)
@@ -42,6 +42,7 @@ static const char *cpu_name[] = {
        [CPU_R8000]     = "R8000",
        [CPU_R10000]    = "R10000",
        [CPU_R12000]    = "R12000",
+       [CPU_R14000]    = "R14000",
        [CPU_R4300]     = "R4300",
        [CPU_R4650]     = "R4650",
        [CPU_R4700]     = "R4700",
@@ -74,6 +75,7 @@ static const char *cpu_name[] = {
        [CPU_24K]       = "MIPS 24K",
        [CPU_25KF]      = "MIPS 25Kf",
        [CPU_34K]       = "MIPS 34K",
+       [CPU_74K]       = "MIPS 74K",
        [CPU_VR4111]    = "NEC VR4111",
        [CPU_VR4121]    = "NEC VR4121",
        [CPU_VR4122]    = "NEC VR4122",
index 9b4733c12395ba59012408249cace1386f30bc84..1d44025188d8328b08a519f81ecb6e113cf4cf20 100644 (file)
@@ -120,11 +120,11 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
                        __put_user ((__u64) -1, i + (__u64 __user *) data);
        }
 
+       __put_user (child->thread.fpu.fcr31, data + 64);
+
        if (cpu_has_fpu) {
                unsigned int flags, tmp;
 
-               __put_user (child->thread.fpu.hard.fcr31, data + 64);
-
                preempt_disable();
                if (cpu_has_mipsmt) {
                        unsigned int vpflags = dvpe();
@@ -142,7 +142,6 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data)
                preempt_enable();
                __put_user (tmp, data + 65);
        } else {
-               __put_user (child->thread.fpu.soft.fcr31, data + 64);
                __put_user ((__u32) 0, data + 65);
        }
 
@@ -162,10 +161,7 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data)
        for (i = 0; i < 32; i++)
                __get_user (fregs[i], i + (__u64 __user *) data);
 
-       if (cpu_has_fpu)
-               __get_user (child->thread.fpu.hard.fcr31, data + 64);
-       else
-               __get_user (child->thread.fpu.soft.fcr31, data + 64);
+       __get_user (child->thread.fpu.fcr31, data + 64);
 
        /* FIR may not be written.  */
 
@@ -241,10 +237,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        tmp = regs->lo;
                        break;
                case FPC_CSR:
-                       if (cpu_has_fpu)
-                               tmp = child->thread.fpu.hard.fcr31;
-                       else
-                               tmp = child->thread.fpu.soft.fcr31;
+                       tmp = child->thread.fpu.fcr31;
                        break;
                case FPC_EIR: { /* implementation / version register */
                        unsigned int flags;
@@ -336,9 +329,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 
                        if (!tsk_used_math(child)) {
                                /* FP not yet used  */
-                               memset(&child->thread.fpu.hard, ~0,
-                                      sizeof(child->thread.fpu.hard));
-                               child->thread.fpu.hard.fcr31 = 0;
+                               memset(&child->thread.fpu, ~0,
+                                      sizeof(child->thread.fpu));
+                               child->thread.fpu.fcr31 = 0;
                        }
 #ifdef CONFIG_32BIT
                        /*
@@ -369,10 +362,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        regs->lo = data;
                        break;
                case FPC_CSR:
-                       if (cpu_has_fpu)
-                               child->thread.fpu.hard.fcr31 = data;
-                       else
-                               child->thread.fpu.soft.fcr31 = data;
+                       child->thread.fpu.fcr31 = data;
                        break;
                case DSP_BASE ... DSP_BASE + 5: {
                        dspreg_t *dregs;
index 8704dc0496ea7f2427b4fd111dbbb54397955b0f..f40ecd8be05fc7b5376a4b24856d9236f17fb5c2 100644 (file)
@@ -166,10 +166,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                        tmp = regs->lo;
                        break;
                case FPC_CSR:
-                       if (cpu_has_fpu)
-                               tmp = child->thread.fpu.hard.fcr31;
-                       else
-                               tmp = child->thread.fpu.soft.fcr31;
+                       tmp = child->thread.fpu.fcr31;
                        break;
                case FPC_EIR: { /* implementation / version register */
                        unsigned int flags;
@@ -288,9 +285,9 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
 
                        if (!tsk_used_math(child)) {
                                /* FP not yet used  */
-                               memset(&child->thread.fpu.hard, ~0,
-                                      sizeof(child->thread.fpu.hard));
-                               child->thread.fpu.hard.fcr31 = 0;
+                               memset(&child->thread.fpu, ~0,
+                                      sizeof(child->thread.fpu));
+                               child->thread.fpu.fcr31 = 0;
                        }
                        /*
                         * The odd registers are actually the high order bits
@@ -318,10 +315,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                        regs->lo = data;
                        break;
                case FPC_CSR:
-                       if (cpu_has_fpu)
-                               child->thread.fpu.hard.fcr31 = data;
-                       else
-                               child->thread.fpu.soft.fcr31 = data;
+                       child->thread.fpu.fcr31 = data;
                        break;
                case DSP_BASE ... DSP_BASE + 5: {
                        dspreg_t *dregs;
index 0b1b54acee9ffeb538a6667da285ee6c82a54777..db94e556fc97939eaad0dbcc540d088145c41fe9 100644 (file)
@@ -75,8 +75,8 @@
        and     t0, t0, t1
        LONG_S  t0, ST_OFF(t3)
 
-       fpu_save_double a0 t1 t0 t2             # c0_status passed in t1
-                                               # clobbers t0 and t2
+       fpu_save_double a0 t0 t1                # c0_status passed in t0
+                                               # clobbers t1
 1:
 
        /*
  */
 LEAF(_save_fp)
 #ifdef CONFIG_64BIT
-       mfc0    t1, CP0_STATUS
+       mfc0    t0, CP0_STATUS
 #endif
-       fpu_save_double a0 t1 t0 t2             # clobbers t1
+       fpu_save_double a0 t0 t1                # clobbers t1
        jr      ra
        END(_save_fp)
 
@@ -139,7 +139,10 @@ LEAF(_save_fp)
  * Restore a thread's fp context.
  */
 LEAF(_restore_fp)
-       fpu_restore_double a0, t1               # clobbers t1
+#ifdef CONFIG_64BIT
+       mfc0    t0, CP0_STATUS
+#endif
+       fpu_restore_double a0 t0 t1             # clobbers t1
        jr      ra
        END(_restore_fp)
 
index b53a9207f530a9db07d58c19b556b9d1cc379594..8efb23a841317a03a385f7ccb2c8d9b47b250475 100644 (file)
@@ -209,7 +209,7 @@ sys_call_table:
        PTR     sys_fork
        PTR     sys_read
        PTR     sys_write
-       PTR     sys_open                        /* 4005 */
+       PTR     compat_sys_open                 /* 4005 */
        PTR     sys_close
        PTR     sys_waitpid
        PTR     sys_creat
index bcf1b10e518f8be4b4302e13bb3186d1e1773438..bfcec8d9bfe4bb4f202bf61c501f49738e12611c 100644 (file)
@@ -246,7 +246,7 @@ static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_en
 #ifdef CONFIG_64BIT
        /* HACK: Guess if the sign extension was forgotten */
        if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
-               start |= 0xffffffff00000000;
+               start |= 0xffffffff00000000UL;
 #endif
 
        end = start + size;
@@ -355,8 +355,6 @@ static inline void bootmem_init(void)
        }
 #endif
 
-       memory_present(0, first_usable_pfn, max_low_pfn);
-
        /* Initialize the boot-time allocator with low memory only.  */
        bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
 
@@ -410,6 +408,7 @@ static inline void bootmem_init(void)
 
                /* Register lowmem ranges */
                free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+               memory_present(0, curr_pfn, curr_pfn + size - 1);
        }
 
        /* Reserve the bootmap memory.  */
@@ -419,17 +418,20 @@ static inline void bootmem_init(void)
 #ifdef CONFIG_BLK_DEV_INITRD
        initrd_below_start_ok = 1;
        if (initrd_start) {
-               unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start);
+               unsigned long initrd_size = ((unsigned char *)initrd_end) -
+                       ((unsigned char *)initrd_start);
+               const int width = sizeof(long) * 2;
+
                printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
                       (void *)initrd_start, initrd_size);
 
                if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
                        printk("initrd extends beyond end of memory "
                               "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
-                              sizeof(long) * 2,
-                              (unsigned long long)CPHYSADDR(initrd_end),
-                              sizeof(long) * 2,
-                              (unsigned long long)PFN_PHYS(max_low_pfn));
+                              width,
+                              (unsigned long long) CPHYSADDR(initrd_end),
+                              width,
+                              (unsigned long long) PFN_PHYS(max_low_pfn));
                        initrd_start = initrd_end = 0;
                        initrd_reserve_bootmem = 0;
                }
@@ -440,6 +442,48 @@ static inline void bootmem_init(void)
 #endif /* CONFIG_BLK_DEV_INITRD  */
 }
 
+/*
+ * arch_mem_init - initialize memory managment subsystem
+ *
+ *  o plat_mem_setup() detects the memory configuration and will record detected
+ *    memory areas using add_memory_region.
+ *  o parse_cmdline_early() parses the command line for mem= options which,
+ *    iff detected, will override the results of the automatic detection.
+ *
+ * At this stage the memory configuration of the system is known to the
+ * kernel but generic memory managment system is still entirely uninitialized.
+ *
+ *  o bootmem_init()
+ *  o sparse_init()
+ *  o paging_init()
+ *
+ * At this stage the bootmem allocator is ready to use.
+ *
+ * NOTE: historically plat_mem_setup did the entire platform initialization.
+ *       This was rather impractical because it meant plat_mem_setup had to
+ * get away without any kind of memory allocator.  To keep old code from
+ * breaking plat_setup was just renamed to plat_setup and a second platform
+ * initialization hook for anything else was introduced.
+ */
+
+extern void plat_mem_setup(void);
+
+static void __init arch_mem_init(char **cmdline_p)
+{
+       /* call board setup routine */
+       plat_mem_setup();
+
+       strlcpy(command_line, arcs_cmdline, sizeof(command_line));
+       strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+
+       *cmdline_p = command_line;
+
+       parse_cmdline_early();
+       bootmem_init();
+       sparse_init();
+       paging_init();
+}
+
 static inline void resource_init(void)
 {
        int i;
@@ -493,8 +537,6 @@ static inline void resource_init(void)
 #undef MAXMEM
 #undef MAXMEM_PFN
 
-extern void plat_setup(void);
-
 void __init setup_arch(char **cmdline_p)
 {
        cpu_probe();
@@ -509,18 +551,8 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #endif
 
-       /* call board setup routine */
-       plat_setup();
-
-       strlcpy(command_line, arcs_cmdline, sizeof(command_line));
-       strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-
-       *cmdline_p = command_line;
+       arch_mem_init(cmdline_p);
 
-       parse_cmdline_early();
-       bootmem_init();
-       sparse_init();
-       paging_init();
        resource_init();
 #ifdef CONFIG_SMP
        plat_smp_setup();
index 3ca786215d48c172fe0948c450c359d16e3f3c20..ce6cb915c0a7a703ab6c49a2e269d4de1256db38 100644 (file)
@@ -31,7 +31,6 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
        save_gp_reg(31);
 #undef save_gp_reg
 
-#ifdef CONFIG_32BIT
        err |= __put_user(regs->hi, &sc->sc_mdhi);
        err |= __put_user(regs->lo, &sc->sc_mdlo);
        if (cpu_has_dsp) {
@@ -43,20 +42,6 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
                err |= __put_user(mflo3(), &sc->sc_lo3);
                err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
        }
-#endif
-#ifdef CONFIG_64BIT
-       err |= __put_user(regs->hi, &sc->sc_hi[0]);
-       err |= __put_user(regs->lo, &sc->sc_lo[0]);
-       if (cpu_has_dsp) {
-               err |= __put_user(mfhi1(), &sc->sc_hi[1]);
-               err |= __put_user(mflo1(), &sc->sc_lo[1]);
-               err |= __put_user(mfhi2(), &sc->sc_hi[2]);
-               err |= __put_user(mflo2(), &sc->sc_lo[2]);
-               err |= __put_user(mfhi3(), &sc->sc_hi[3]);
-               err |= __put_user(mflo3(), &sc->sc_lo[3]);
-               err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
-       }
-#endif
 
        err |= __put_user(!!used_math(), &sc->sc_used_math);
 
@@ -92,7 +77,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
        err |= __get_user(regs->cp0_epc, &sc->sc_pc);
-#ifdef CONFIG_32BIT
        err |= __get_user(regs->hi, &sc->sc_mdhi);
        err |= __get_user(regs->lo, &sc->sc_mdlo);
        if (cpu_has_dsp) {
@@ -104,20 +88,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
                err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
                err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
        }
-#endif
-#ifdef CONFIG_64BIT
-       err |= __get_user(regs->hi, &sc->sc_hi[0]);
-       err |= __get_user(regs->lo, &sc->sc_lo[0]);
-       if (cpu_has_dsp) {
-               err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
-               err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
-               err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
-               err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
-               err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
-               err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
-               err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
-       }
-#endif
 
 #define restore_gp_reg(i) do {                                         \
        err |= __get_user(regs->regs[i], &sc->sc_regs[i]);              \
index d42f358754ad829129663f01350d7c0757f8f078..298f82fe8440a43d1a8140ed8a256d44595ed6d8 100644 (file)
@@ -247,6 +247,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        current_thread_info()->cpu = 0;
        smp_tune_scheduling();
        plat_prepare_cpus(max_cpus);
+#ifndef CONFIG_HOTPLUG_CPU
+       cpu_present_map = cpu_possible_map;
+#endif
 }
 
 /* preload SMP state for boot cpu */
@@ -442,7 +445,7 @@ static int __init topology_init(void)
        int cpu;
        int ret;
 
-       for_each_cpu(cpu) {
+       for_each_present_cpu(cpu) {
                ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL);
                if (ret)
                        printk(KERN_WARNING "topology_init: register_cpu %d "
index 2aeaa2fd4b322a1ebec61d1861eda4aab1ad4e0a..5e8a18a8e2bda49d4ac59388d6df985eeafe4b1d 100644 (file)
@@ -276,31 +276,9 @@ void sys_set_thread_area(unsigned long addr)
 
 asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
 {
-       int     tmp, len;
-       char    __user *name;
+       int     tmp;
 
        switch(cmd) {
-       case SETNAME: {
-               char nodename[__NEW_UTS_LEN + 1];
-
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-
-               name = (char __user *) arg1;
-
-               len = strncpy_from_user(nodename, name, __NEW_UTS_LEN);
-               if (len < 0)
-                       return -EFAULT;
-
-               down_write(&uts_sem);
-               strncpy(system_utsname.nodename, nodename, len);
-               nodename[__NEW_UTS_LEN] = '\0';
-               strlcpy(system_utsname.nodename, nodename,
-                       sizeof(system_utsname.nodename));
-               up_write(&uts_sem);
-               return 0;
-       }
-
        case MIPS_ATOMIC_SET:
                printk(KERN_CRIT "How did I get here?\n");
                return -EINVAL;
@@ -313,9 +291,6 @@ asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
        case FLUSH_CACHE:
                __flush_cache_all();
                return 0;
-
-       case MIPS_RDNVRAM:
-               return -EIO;
        }
 
        return -EINVAL;
index 4901f0a37fca2b3ddb2de93dcf998873b10e6643..ad16eceb24dd34bba57f2673dc2fa31ace1cd8fc 100644 (file)
@@ -65,7 +65,7 @@ extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
 
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-       struct mips_fpu_soft_struct *ctx);
+       struct mips_fpu_struct *ctx);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -600,8 +600,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                preempt_enable();
 
                /* Run the emulator */
-               sig = fpu_emulator_cop1Handler (regs,
-                       &current->thread.fpu.soft);
+               sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu);
 
                preempt_disable();
 
@@ -610,7 +609,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                 * We can't allow the emulated instruction to leave any of
                 * the cause bit set in $fcr31.
                 */
-               current->thread.fpu.soft.fcr31 &= ~FPU_CSR_ALL_X;
+               current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
 
                /* Restore the hardware register state */
                restore_fp(current);
@@ -755,7 +754,7 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 
                if (!cpu_has_fpu) {
                        int sig = fpu_emulator_cop1Handler(regs,
-                                               &current->thread.fpu.soft);
+                                               &current->thread.fpu);
                        if (sig)
                                force_sig(sig, current);
 #ifdef CONFIG_MIPS_MT_FPAFF
@@ -819,15 +818,30 @@ asmlinkage void do_watch(struct pt_regs *regs)
 
 asmlinkage void do_mcheck(struct pt_regs *regs)
 {
+       const int field = 2 * sizeof(unsigned long);
+       int multi_match = regs->cp0_status & ST0_TS;
+
        show_regs(regs);
-       dump_tlb_all();
+
+       if (multi_match) {
+               printk("Index   : %0x\n", read_c0_index());
+               printk("Pagemask: %0x\n", read_c0_pagemask());
+               printk("EntryHi : %0*lx\n", field, read_c0_entryhi());
+               printk("EntryLo0: %0*lx\n", field, read_c0_entrylo0());
+               printk("EntryLo1: %0*lx\n", field, read_c0_entrylo1());
+               printk("\n");
+               dump_tlb_all();
+       }
+
+       show_code((unsigned int *) regs->cp0_epc);
+
        /*
         * Some chips may have other causes of machine check (e.g. SB1
         * graduation timer)
         */
        panic("Caught Machine Check exception - %scaused by multiple "
              "matching entries in the TLB.",
-             (regs->cp0_status & ST0_TS) ? "" : "not ");
+             (multi_match) ? "" : "not ");
 }
 
 asmlinkage void do_mt(struct pt_regs *regs)
@@ -902,6 +916,7 @@ static inline void parity_protection_init(void)
 {
        switch (current_cpu_data.cputype) {
        case CPU_24K:
+       case CPU_34K:
        case CPU_5KC:
                write_c0_ecc(0x80000000);
                back_to_back_c0_hazard();
index 14fa00e3cdfa6007332e58fbd84fc9eba3c4d1ac..b84d1f9ce28ef169e0fbb633ba184c5341e03e40 100644 (file)
@@ -151,23 +151,13 @@ SECTIONS
 
   /* This is the MIPS specific mdebug section.  */
   .mdebug : { *(.mdebug) }
-  /* These are needed for ELF backends which have not yet been
-     converted to the new style linker.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  /* DWARF debug sections.
-     Symbols in the .debug DWARF section are relative to the beginning of the
-     section so we begin .debug at 0.  It's not clear yet what needs to happen
-     for the others.   */
-  .debug          0 : { *(.debug) }
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  .line           0 : { *(.line) }
+
+  STABS_DEBUG
+
+  DWARF_DEBUG
+
   /* These must appear regardless of  .  */
   .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
   .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
-  .comment : { *(.comment) }
   .note : { *(.note) }
 }
index bb70a8240e610026dae01c69d4c3b195b9ac4833..3f64277429e43860483c2adbc7dd62f17537940c 100644 (file)
@@ -155,7 +155,7 @@ void __init serial_init(void)
 }
 #endif
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        int i;
        lasat_misc  = &lasat_misc_info[mips_machtype];
index cf12caf80774e1520903de5b30e03b01fdcfc569..b225543f5302dc2ed7ad3ea4cc28daa84d40c3e0 100644 (file)
@@ -7,4 +7,7 @@ lib-y   += csum_partial_copy.o memcpy.o promlib.o strlen_user.o strncpy_user.o \
 
 obj-y  += iomap.o
 
+# libgcc-style stuff needed in the kernel
+lib-y += ashldi3.o ashrdi3.o lshrdi3.o
+
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c
new file mode 100644 (file)
index 0000000..beb80f3
--- /dev/null
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashldi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               w.s.low = 0;
+               w.s.high = (unsigned int) uu.s.low << -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.low >> bm;
+
+               w.s.low = (unsigned int) uu.s.low << b;
+               w.s.high = ((unsigned int) uu.s.high << b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c
new file mode 100644 (file)
index 0000000..c884a91
--- /dev/null
@@ -0,0 +1,31 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashrdi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               /* w.s.high = 1..1 or 0..0 */
+               w.s.high =
+                   uu.s.high >> 31;
+               w.s.low = uu.s.high >> -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+               w.s.high = uu.s.high >> b;
+               w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/mips/lib/libgcc.h b/arch/mips/lib/libgcc.h
new file mode 100644 (file)
index 0000000..3f19d1c
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __ASM_LIBGCC_H
+#define __ASM_LIBGCC_H
+
+#include <asm/byteorder.h>
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+#ifdef __BIG_ENDIAN
+struct DWstruct {
+       int high, low;
+};
+#elif defined(__LITTLE_ENDIAN)
+struct DWstruct {
+       int low, high;
+};
+#else
+#error I feel sick.
+#endif
+
+typedef union
+{
+       struct DWstruct s;
+       long long ll;
+} DWunion;
+
+#endif /* __ASM_LIBGCC_H */
diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c
new file mode 100644 (file)
index 0000000..dcf8d68
--- /dev/null
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __lshrdi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               w.s.high = 0;
+               w.s.low = (unsigned int) uu.s.high >> -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+               w.s.high = (unsigned int) uu.s.high >> b;
+               w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__lshrdi3);
index aa5818a0d8848f7b6bb863aafee6b54ab74fd97c..3f0d5d26d506d27abc452b394268a57532df00b4 100644 (file)
 
 /* Function which emulates a floating point instruction. */
 
-static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
+static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
        mips_instruction);
 
 #if __mips >= 4 && __mips != 32
 static int fpux_emu(struct pt_regs *,
-       struct mips_fpu_soft_struct *, mips_instruction);
+       struct mips_fpu_struct *, mips_instruction);
 #endif
 
-/* Further private data for which no space exists in mips_fpu_soft_struct */
+/* Further private data for which no space exists in mips_fpu_struct */
 
 struct mips_fpu_emulator_stats fpuemustats;
 
@@ -203,7 +203,7 @@ static int isBranchInstr(mips_instruction * i)
  * Two instructions if the instruction is in a branch delay slot.
  */
 
-static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
+static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 {
        mips_instruction ir;
        void * emulpc, *contpc;
@@ -595,7 +595,7 @@ DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub,);
 DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
 DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
 
-static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
        mips_instruction ir)
 {
        unsigned rcsr = 0;      /* resulting csr */
@@ -759,7 +759,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
 /*
  * Emulate a single COP1 arithmetic instruction.
  */
-static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
        mips_instruction ir)
 {
        int rfmt;               /* resulting format */
@@ -1233,8 +1233,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
        return 0;
 }
 
-int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-       struct mips_fpu_soft_struct *ctx)
+int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 {
        unsigned long oldepc, prevepc;
        mips_instruction insn;
index a1962eb460f827f5d9dfc24dd0739159333d9a54..39a71de16f47ed8ccfaadc575f2330a0a3dcbadb 100644 (file)
@@ -29,7 +29,9 @@
 
 ieee754dp ieee754dp_fint(int x)
 {
-       COMPXDP;
+       u64 xm;
+       int xe;
+       int xs;
 
        CLEARCX;
 
index eae90a866aa19e1bb60477f5ef98f828bf68a32c..f08f223e488a3a68a07038124dc045811b20bf98 100644 (file)
@@ -29,7 +29,9 @@
 
 ieee754dp ieee754dp_flong(s64 x)
 {
-       COMPXDP;
+       u64 xm;
+       int xe;
+       int xs;
 
        CLEARCX;
 
index 171f177c0f88a66ac84159baa7dabe54be612adf..dd917332792c644ab1273fa23abf5d95b6c448db 100644 (file)
@@ -329,7 +329,7 @@ struct _ieee754_csr {
        unsigned pad0:7;
 #endif
 };
-#define ieee754_csr (*(struct _ieee754_csr *)(&current->thread.fpu.soft.fcr31))
+#define ieee754_csr (*(struct _ieee754_csr *)(&current->thread.fpu.fcr31))
 
 static inline unsigned ieee754_getrm(void)
 {
index d187ab71c2ff17d4178248fa625cfe86f9a6a940..56ca0c6a7178f935f30b6e730718b86e4d47425a 100644 (file)
@@ -39,9 +39,9 @@ void fpu_emulator_init_fpu(void)
                printk("Algorithmics/MIPS FPU Emulator v1.5\n");
        }
 
-       current->thread.fpu.soft.fcr31 = 0;
+       current->thread.fpu.fcr31 = 0;
        for (i = 0; i < 32; i++) {
-               current->thread.fpu.soft.fpr[i] = SIGNALLING_NAN;
+               current->thread.fpu.fpr[i] = SIGNALLING_NAN;
        }
 }
 
@@ -59,10 +59,9 @@ int fpu_emulator_save_context(struct sigcontext *sc)
 
        for (i = 0; i < 32; i++) {
                err |=
-                   __put_user(current->thread.fpu.soft.fpr[i],
-                              &sc->sc_fpregs[i]);
+                   __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
        }
-       err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+       err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
 
        return err;
 }
@@ -74,10 +73,9 @@ int fpu_emulator_restore_context(struct sigcontext *sc)
 
        for (i = 0; i < 32; i++) {
                err |=
-                   __get_user(current->thread.fpu.soft.fpr[i],
-                              &sc->sc_fpregs[i]);
+                   __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
        }
-       err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+       err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
 
        return err;
 }
@@ -94,10 +92,9 @@ int fpu_emulator_save_context32(struct sigcontext32 *sc)
 
        for (i = 0; i < 32; i+=2) {
                err |=
-                   __put_user(current->thread.fpu.soft.fpr[i],
-                              &sc->sc_fpregs[i]);
+                   __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
        }
-       err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+       err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
 
        return err;
 }
@@ -109,10 +106,9 @@ int fpu_emulator_restore_context32(struct sigcontext32 *sc)
 
        for (i = 0; i < 32; i+=2) {
                err |=
-                   __get_user(current->thread.fpu.soft.fpr[i],
-                              &sc->sc_fpregs[i]);
+                   __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
        }
-       err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+       err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
 
        return err;
 }
index 7aac13afb09a6b2b706507611501da910337949d..e88e125e01c2f394b2dcf4d97730207a11cc0d0d 100644 (file)
@@ -29,7 +29,9 @@
 
 ieee754sp ieee754sp_fint(int x)
 {
-       COMPXSP;
+       unsigned xm;
+       int xe;
+       int xs;
 
        CLEARCX;
 
index 3d6c1d11c17889bfea252f2c78d4711e0f3049e4..26d6919a269af143ad590d58233d5a8bd8b80310 100644 (file)
@@ -29,7 +29,9 @@
 
 ieee754sp ieee754sp_flong(s64 x)
 {
-       COMPXDP;                /* <--- need 64-bit mantissa temp */
+       u64 xm;         /* <--- need 64-bit mantissa temp */
+       int xe;
+       int xs;
 
        CLEARCX;
 
index c20d401ecf80d5ed29e320ec0bd5e4e2c002a6d1..8cc9effcb832d5a6eccd161d632af28b92b82295 100644 (file)
@@ -50,7 +50,7 @@ const char *get_system_type(void)
        return "MIPS Atlas";
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        mips_pcibios_init();
 
index bc4d093685bbec8725ab448723700f691b8d3ac8..fd492562584aabea44489f7ad622d49ebdacc90e 100644 (file)
@@ -76,6 +76,15 @@ struct prom_pmemblock * __init prom_getmdesc(void)
                        memsize = simple_strtol(memsize_str, NULL, 0);
                }
        }
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       /*
+        * SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
+        * word of physical memory
+        */
+       memsize -= PAGE_SIZE;
+#endif
+
        memset(mdesc, 0, sizeof(mdesc));
 
        mdesc[0].type = yamon_dontuse;
index b8488aab6df1cd17bfd4c2e902e4ba69daf4f2fe..0766e434b6bde10283c6dc627eca4e330bafa5de 100644 (file)
@@ -53,11 +53,11 @@ extern void kgdb_config(void);
 #endif
 
 struct resource standard_io_resources[] = {
-       { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
-       { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
-       { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
-       { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
-       { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+       { .name = "dma1", .start = 0x00, .end = 0x1f, .flags = IORESOURCE_BUSY },
+       { .name = "timer", .start = 0x40, .end = 0x5f, .flags = IORESOURCE_BUSY },
+       { .name = "keyboard", .start = 0x60, .end = 0x6f, .flags = IORESOURCE_BUSY },
+       { .name = "dma page reg", .start = 0x80, .end = 0x8f, .flags = IORESOURCE_BUSY },
+       { .name = "dma2", .start = 0xc0, .end = 0xdf, .flags = IORESOURCE_BUSY },
 };
 
 #ifdef CONFIG_MTD
@@ -111,7 +111,7 @@ void __init fd_activate(void)
 }
 #endif
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        unsigned int i;
 
index 6c6c8eeedbcebc00e4fc7332e45719717db9ad5b..cf967170fe295ebaa4e191b47c16f925a0c7ab3e 100644 (file)
@@ -33,25 +33,6 @@ void core_send_ipi(int cpu, unsigned int action)
 #endif /* CONFIG_MIPS_MT_SMTC */
 }
 
-/*
- * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
- */
-
-void __init prom_build_cpu_map(void)
-{
-       int nextslot;
-
-       /*
-        * As of November, 2004, MIPSsim only simulates one core
-        * at a time.  However, that core may be a MIPS MT core
-        * with multiple virtual processors and thread contexts.
-        */
-
-       if (read_c0_config3() & (1<<2)) {
-               nextslot = mipsmt_build_cpu_map(1);
-       }
-}
-
 /*
  * Platform "CPU" startup hook
  */
index 4266ce445174e4bd67866f3aa783b7a8b6b4b1be..6430f11f3a9596532b4c1b21bcbb3e69337d2bf3 100644 (file)
@@ -45,7 +45,7 @@ const char *get_system_type(void)
        return "MIPS SEAD";
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        ioport_resource.end = 0x7fffffff;
 
index a2fd62997ca3c3b9ee7337d3622834761b2ccb88..15a5dac4ae19ad1122b99e06c2f4abc1813e959b 100644 (file)
@@ -50,7 +50,7 @@ const char *get_system_type(void)
        return "MIPSsim";
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        set_io_port_base(0xbfd00000);
 
index b7084e7c4bf9b7c4bce0ee742301ddfe198e85d5..004070956cca6862da7115aaf955174ae67f152a 100644 (file)
@@ -50,27 +50,6 @@ void core_send_ipi(int cpu, unsigned int action)
 
 }
 
-/*
- * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
- */
-
-void __init prom_build_cpu_map(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-       int nextslot;
-
-       /*
-        * As of November, 2004, MIPSsim only simulates one core
-        * at a time.  However, that core may be a MIPS MT core
-        * with multiple virtual processors and thread contexts.
-        */
-
-       if (read_c0_config3() & (1<<2)) {
-               nextslot = mipsmt_build_cpu_map(1);
-       }
-#endif /* CONFIG_MIPS_MT_SMTC */
-}
-
 /*
  * Platform "CPU" startup hook
  */
index 4182e1176faeaeb1181af9fe7d12094b42db1fc4..4a43924cd4fccd1f3415a79bc0562d20420632c8 100644 (file)
 #include <asm/war.h>
 #include <asm/cacheflush.h> /* for run_uncached() */
 
+
+/*
+ * Special Variant of smp_call_function for use by cache functions:
+ *
+ *  o No return value
+ *  o collapses to normal function call on UP kernels
+ *  o collapses to normal function call on systems with a single shared
+ *    primary cache.
+ */
+static inline void r4k_on_each_cpu(void (*func) (void *info), void *info,
+                                   int retry, int wait)
+{
+       preempt_disable();
+
+#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
+       smp_call_function(func, info, retry, wait);
+#endif
+       func(info);
+       preempt_enable();
+}
+
 /*
  * Must die.
  */
@@ -299,7 +320,7 @@ static void r4k_flush_cache_all(void)
        if (!cpu_has_dc_aliases)
                return;
 
-       on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1);
 }
 
 static inline void local_r4k___flush_cache_all(void * args)
@@ -314,13 +335,14 @@ static inline void local_r4k___flush_cache_all(void * args)
        case CPU_R4400MC:
        case CPU_R10000:
        case CPU_R12000:
+       case CPU_R14000:
                r4k_blast_scache();
        }
 }
 
 static void r4k___flush_cache_all(void)
 {
-       on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1);
+       r4k_on_each_cpu(local_r4k___flush_cache_all, NULL, 1, 1);
 }
 
 static inline void local_r4k_flush_cache_range(void * args)
@@ -341,7 +363,7 @@ static inline void local_r4k_flush_cache_range(void * args)
 static void r4k_flush_cache_range(struct vm_area_struct *vma,
        unsigned long start, unsigned long end)
 {
-       on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
 }
 
 static inline void local_r4k_flush_cache_mm(void * args)
@@ -370,7 +392,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm)
        if (!cpu_has_dc_aliases)
                return;
 
-       on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1);
 }
 
 struct flush_cache_page_args {
@@ -461,7 +483,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
        args.addr = addr;
        args.pfn = pfn;
 
-       on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
 }
 
 static inline void local_r4k_flush_data_cache_page(void * addr)
@@ -471,7 +493,7 @@ static inline void local_r4k_flush_data_cache_page(void * addr)
 
 static void r4k_flush_data_cache_page(unsigned long addr)
 {
-       on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr, 1, 1);
 }
 
 struct flush_icache_range_args {
@@ -514,7 +536,7 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
        args.start = start;
        args.end = end;
 
-       on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1);
        instruction_hazard();
 }
 
@@ -590,7 +612,7 @@ static void r4k_flush_icache_page(struct vm_area_struct *vma,
        args.vma = vma;
        args.page = page;
 
-       on_each_cpu(local_r4k_flush_icache_page, &args, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_icache_page, &args, 1, 1);
 }
 
 
@@ -689,7 +711,7 @@ static void local_r4k_flush_cache_sigtramp(void * arg)
 
 static void r4k_flush_cache_sigtramp(unsigned long addr)
 {
-       on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr, 1, 1);
+       r4k_on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr, 1, 1);
 }
 
 static void r4k_flush_icache_all(void)
@@ -812,6 +834,7 @@ static void __init probe_pcache(void)
 
        case CPU_R10000:
        case CPU_R12000:
+       case CPU_R14000:
                icache_size = 1 << (12 + ((config & R10K_CONF_IC) >> 29));
                c->icache.linesz = 64;
                c->icache.ways = 2;
@@ -965,9 +988,11 @@ static void __init probe_pcache(void)
                c->dcache.flags |= MIPS_CACHE_PINDEX;
        case CPU_R10000:
        case CPU_R12000:
+       case CPU_R14000:
        case CPU_SB1:
                break;
        case CPU_24K:
+       case CPU_34K:
                if (!(read_c0_config7() & (1 << 16)))
        default:
                        if (c->dcache.waysize > PAGE_SIZE)
@@ -1091,6 +1116,7 @@ static void __init setup_scache(void)
 
        case CPU_R10000:
        case CPU_R12000:
+       case CPU_R14000:
                scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16);
                c->scache.linesz = 64 << ((config >> 13) & 1);
                c->scache.ways = 2;
@@ -1135,6 +1161,31 @@ static void __init setup_scache(void)
        c->options |= MIPS_CPU_SUBSET_CACHES;
 }
 
+void au1x00_fixup_config_od(void)
+{
+       /*
+        * c0_config.od (bit 19) was write only (and read as 0)
+        * on the early revisions of Alchemy SOCs.  It disables the bus
+        * transaction overlapping and needs to be set to fix various errata.
+        */
+       switch (read_c0_prid()) {
+       case 0x00030100: /* Au1000 DA */
+       case 0x00030201: /* Au1000 HA */
+       case 0x00030202: /* Au1000 HB */
+       case 0x01030200: /* Au1500 AB */
+       /*
+        * Au1100 errata actually keeps silence about this bit, so we set it
+        * just in case for those revisions that require it to be set according
+        * to arch/mips/au1000/common/cputable.c
+        */
+       case 0x02030200: /* Au1100 AB */
+       case 0x02030201: /* Au1100 BA */
+       case 0x02030202: /* Au1100 BC */
+               set_c0_config(1 << 19);
+               break;
+       }
+}
+
 static inline void coherency_setup(void)
 {
        change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
@@ -1155,6 +1206,15 @@ static inline void coherency_setup(void)
        case CPU_R4400MC:
                clear_c0_config(CONF_CU);
                break;
+       /*
+        * We need to catch the ealry Alchemy SOCs with
+        * the write-only co_config.od bit and set it back to one...
+        */
+       case CPU_AU1000: /* rev. DA, HA, HB */
+       case CPU_AU1100: /* rev. AB, BA, BC ?? */
+       case CPU_AU1500: /* rev. AB */
+               au1x00_fixup_config_od();
+               break;
        }
 }
 
index c22308b93ff05ce04aee860042733a63dc2bf713..33f6e1cdfd5b409341488e4e2f15424f82451c3b 100644 (file)
@@ -227,7 +227,7 @@ void __init mem_init(void)
        for (tmp = 0; tmp < max_low_pfn; tmp++)
                if (page_is_ram(tmp)) {
                        ram++;
-                       if (PageReserved(mem_map+tmp))
+                       if (PageReserved(pfn_to_page(tmp)))
                                reservedpages++;
                }
 
index e4390dc3eb48e29d9b9a950d5a020d27af32676e..b7c749232ffef80bb50c131f2853965aa7e72396 100644 (file)
@@ -357,6 +357,7 @@ void __init build_clear_page(void)
 
                case CPU_R10000:
                case CPU_R12000:
+               case CPU_R14000:
                        pref_src_mode = Pref_LoadStreamed;
                        pref_dst_mode = Pref_StoreStreamed;
                        break;
index 9dca099ba16b01b907568d9f387f5ea9d693d665..965cb4c4359db6b03c8f737b0a609e6d134ad9b6 100644 (file)
@@ -413,7 +413,6 @@ out:
        return ret;
 }
 
-extern void __init sanitize_tlb_entries(void);
 static void __init probe_tlb(unsigned long config)
 {
        struct cpuinfo_mips *c = &current_cpu_data;
index 053dbacac56bdf4d5a797b0d115ddb1951297aa0..54507be2ab5bb07f967f23e9c8305ab5f2ddf48a 100644 (file)
@@ -875,6 +875,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
 
        case CPU_R10000:
        case CPU_R12000:
+       case CPU_R14000:
        case CPU_4KC:
        case CPU_SB1:
        case CPU_SB1A:
@@ -906,6 +907,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
        case CPU_4KEC:
        case CPU_24K:
        case CPU_34K:
+       case CPU_74K:
                i_ehb(p);
                tlbw(p);
                break;
index 542eac82b63c2908065fcd51bda2625c4b2e1aed..d7dea0a136aabedd95a98f0646e756ffce77c8ab 100644 (file)
@@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
        /* disable interrupts */
        UART16550_WRITE(OFS_INTR_ENABLE, 0);
 
-       /* set up buad rate */
+       /* set up baud rate */
        {
                uint32 divisor;
 
index 1379c76845dc6619436c064400f46226777130c1..df1485501ce631ed6ff262b0dbbdb8014919739a 100644 (file)
@@ -359,7 +359,7 @@ static __init int __init ja_pci_init(void)
 
 arch_initcall(ja_pci_init);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        unsigned int tmpword;
 
index c69195234309687d3f03d52aa6a3fbace55fefbb..8c53490ba6f10acdb2c69a536dcacaac7f20ed29 100644 (file)
@@ -313,7 +313,7 @@ static __init int __init ja_pci_init(void)
 
 arch_initcall(ja_pci_init);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        unsigned int tmpword;
 
index 8720bccfdea250dd9eddbe580c22b8f4e75fa60e..f0a6a38fcf4d9fae50fc20da3b7c1505ebc451ef 100644 (file)
@@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
        /* disable interrupts */
        UART16550_WRITE(OFS_INTR_ENABLE, 0);
 
-       /* set up buad rate */
+       /* set up baud rate */
        {
                uint32 divisor;
 
index a3e6f5575592a2e63cc3c4991d4e24b8b2776739..257e1d1b72ddf1006a8cd31292f774bf47d13b48 100644 (file)
@@ -231,7 +231,7 @@ void momenco_time_init(void)
        rtc_mips_set_time = m48t37y_set_time;
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        unsigned int tmpword;
 
index 8720bccfdea250dd9eddbe580c22b8f4e75fa60e..f0a6a38fcf4d9fae50fc20da3b7c1505ebc451ef 100644 (file)
@@ -73,7 +73,7 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
        /* disable interrupts */
        UART16550_WRITE(OFS_INTR_ENABLE, 0);
 
-       /* set up buad rate */
+       /* set up baud rate */
        {
                uint32 divisor;
 
index fed4e8eee116bc0a4555a20d6f64091304246d74..72143ab1e9008c164299a0dd46b2140bb1c10aa0 100644 (file)
@@ -162,7 +162,7 @@ static void __init setup_l3cache(unsigned long size)
        printk("Done\n");
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache);
        unsigned int tmpword;
index f2b4862aaae505fbcb8e902214633b6078d64fe4..c31e4cff64e043437a9019bfeae3890c2ee043eb 100644 (file)
@@ -14,8 +14,8 @@
 
 #include "op_impl.h"
 
-extern struct op_mips_model op_model_mipsxx __attribute__((weak));
-extern struct op_mips_model op_model_rm9000 __attribute__((weak));
+extern struct op_mips_model op_model_mipsxx_ops __attribute__((weak));
+extern struct op_mips_model op_model_rm9000_ops __attribute__((weak));
 
 static struct op_mips_model *model;
 
@@ -80,13 +80,14 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
        case CPU_24K:
        case CPU_25KF:
        case CPU_34K:
+       case CPU_74K:
        case CPU_SB1:
        case CPU_SB1A:
-               lmodel = &op_model_mipsxx;
+               lmodel = &op_model_mipsxx_ops;
                break;
 
        case CPU_RM9000:
-               lmodel = &op_model_rm9000;
+               lmodel = &op_model_rm9000_ops;
                break;
        };
 
index 95d488ca075473be4d4e0a3e0d032a0c413eaf27..f26a00e13204dd62b6848120f14a6d46af00b39e 100644 (file)
@@ -23,7 +23,7 @@
 
 #define M_COUNTER_OVERFLOW             (1UL    << 31)
 
-struct op_mips_model op_model_mipsxx;
+struct op_mips_model op_model_mipsxx_ops;
 
 static struct mipsxx_register_config {
        unsigned int control[4];
@@ -34,7 +34,7 @@ static struct mipsxx_register_config {
 
 static void mipsxx_reg_setup(struct op_counter_config *ctr)
 {
-       unsigned int counters = op_model_mipsxx.num_counters;
+       unsigned int counters = op_model_mipsxx_ops.num_counters;
        int i;
 
        /* Compute the performance counter control word.  */
@@ -62,7 +62,7 @@ static void mipsxx_reg_setup(struct op_counter_config *ctr)
 
 static void mipsxx_cpu_setup (void *args)
 {
-       unsigned int counters = op_model_mipsxx.num_counters;
+       unsigned int counters = op_model_mipsxx_ops.num_counters;
 
        switch (counters) {
        case 4:
@@ -83,7 +83,7 @@ static void mipsxx_cpu_setup (void *args)
 /* Start all counters on current CPU */
 static void mipsxx_cpu_start(void *args)
 {
-       unsigned int counters = op_model_mipsxx.num_counters;
+       unsigned int counters = op_model_mipsxx_ops.num_counters;
 
        switch (counters) {
        case 4:
@@ -100,7 +100,7 @@ static void mipsxx_cpu_start(void *args)
 /* Stop all counters on current CPU */
 static void mipsxx_cpu_stop(void *args)
 {
-       unsigned int counters = op_model_mipsxx.num_counters;
+       unsigned int counters = op_model_mipsxx_ops.num_counters;
 
        switch (counters) {
        case 4:
@@ -116,7 +116,7 @@ static void mipsxx_cpu_stop(void *args)
 
 static int mipsxx_perfcount_handler(struct pt_regs *regs)
 {
-       unsigned int counters = op_model_mipsxx.num_counters;
+       unsigned int counters = op_model_mipsxx_ops.num_counters;
        unsigned int control;
        unsigned int counter;
        int handled = 0;
@@ -187,33 +187,37 @@ static int __init mipsxx_init(void)
 
        reset_counters(counters);
 
-       op_model_mipsxx.num_counters = counters;
+       op_model_mipsxx_ops.num_counters = counters;
        switch (current_cpu_data.cputype) {
        case CPU_20KC:
-               op_model_mipsxx.cpu_type = "mips/20K";
+               op_model_mipsxx_ops.cpu_type = "mips/20K";
                break;
 
        case CPU_24K:
-               op_model_mipsxx.cpu_type = "mips/24K";
+               op_model_mipsxx_ops.cpu_type = "mips/24K";
                break;
 
        case CPU_25KF:
-               op_model_mipsxx.cpu_type = "mips/25K";
+               op_model_mipsxx_ops.cpu_type = "mips/25K";
                break;
 
 #ifndef CONFIG_SMP
        case CPU_34K:
-               op_model_mipsxx.cpu_type = "mips/34K";
+               op_model_mipsxx_ops.cpu_type = "mips/34K";
+               break;
+
+       case CPU_74K:
+               op_model_mipsxx_ops.cpu_type = "mips/74K";
                break;
 #endif
 
        case CPU_5KC:
-               op_model_mipsxx.cpu_type = "mips/5K";
+               op_model_mipsxx_ops.cpu_type = "mips/5K";
                break;
 
        case CPU_SB1:
        case CPU_SB1A:
-               op_model_mipsxx.cpu_type = "mips/sb1";
+               op_model_mipsxx_ops.cpu_type = "mips/sb1";
                break;
 
        default:
@@ -229,12 +233,12 @@ static int __init mipsxx_init(void)
 
 static void mipsxx_exit(void)
 {
-       reset_counters(op_model_mipsxx.num_counters);
+       reset_counters(op_model_mipsxx_ops.num_counters);
 
        perf_irq = null_perf_irq;
 }
 
-struct op_mips_model op_model_mipsxx = {
+struct op_mips_model op_model_mipsxx_ops = {
        .reg_setup      = mipsxx_reg_setup,
        .cpu_setup      = mipsxx_cpu_setup,
        .init           = mipsxx_init,
index 9b75e41c78ef891a02021db2cf40d5c004c7e391..b7063fefa65b46d80c658697fbe629f9e95bd4f4 100644 (file)
@@ -126,7 +126,7 @@ static void rm9000_exit(void)
        free_irq(rm9000_perfcount_irq, NULL);
 }
 
-struct op_mips_model op_model_rm9000 = {
+struct op_mips_model op_model_rm9000_ops = {
        .reg_setup      = rm9000_reg_setup,
        .cpu_setup      = rm9000_cpu_setup,
        .init           = rm9000_init,
index 16205b587338a400f54455420be0ef7cdb90fd57..465778c5d816064e127d77164b7eef4a2ec6d769 100644 (file)
@@ -18,12 +18,12 @@ obj-$(CONFIG_MIPS_NILE4)    += ops-nile4.o
 obj-$(CONFIG_MIPS_TX3927)      += ops-tx3927.o
 obj-$(CONFIG_PCI_VR41XX)       += ops-vr41xx.o pci-vr41xx.o
 obj-$(CONFIG_NEC_CMBVR4133)    += fixup-vr4133.o
+obj-$(CONFIG_MARKEINS)         += ops-emma2rh.o pci-emma2rh.o fixup-emma2rh.o
 
 #
 # These are still pretty much in the old state, watch, go blind.
 #
-obj-$(CONFIG_DDB5074)          += fixup-ddb5074.o pci-ddb5074.o ops-ddb5074.o
-obj-$(CONFIG_DDB5476)          += ops-ddb5476.o pci-ddb5476.o
+obj-$(CONFIG_BASLER_EXCITE)    = ops-titan.o pci-excite.o fixup-excite.o
 obj-$(CONFIG_DDB5477)          += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
 obj-$(CONFIG_LASAT)            += pci-lasat.o
 obj-$(CONFIG_MIPS_ATLAS)       += fixup-atlas.o
@@ -43,7 +43,7 @@ obj-$(CONFIG_MOMENCO_OCELOT_C)        += fixup-ocelot-c.o pci-ocelot-c.o
 obj-$(CONFIG_MOMENCO_OCELOT_G) += fixup-ocelot-g.o pci-ocelot-g.o
 obj-$(CONFIG_PMC_YOSEMITE)     += fixup-yosemite.o ops-titan.o ops-titan-ht.o \
                                   pci-yosemite.o
-obj-$(CONFIG_SGI_IP27)         += pci-ip27.o
+obj-$(CONFIG_SGI_IP27)         += ops-bridge.o pci-ip27.o
 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
@@ -57,3 +57,4 @@ obj-$(CONFIG_TOSHIBA_RBTX4927)        += fixup-rbtx4927.o ops-tx4927.o
 obj-$(CONFIG_TOSHIBA_RBTX4938) += fixup-tx4938.o ops-tx4938.o
 obj-$(CONFIG_VICTOR_MPC30X)    += fixup-mpc30x.o
 obj-$(CONFIG_ZAO_CAPCELLA)     += fixup-capcella.o
+obj-$(CONFIG_WR_PPMC)          += fixup-wrppmc.o
diff --git a/arch/mips/pci/fixup-ddb5074.c b/arch/mips/pci/fixup-ddb5074.c
deleted file mode 100644 (file)
index 5a4a7c2..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * It's nice to have the LEDs on the GPIO pins available for debugging
- */
-static void ddb5074_fixup(struct pci_dev *dev)
-{
-       extern struct pci_dev *pci_pmu;
-       u8 t8;
-
-       pci_pmu = dev;  /* for LEDs D2 and D3 */
-       /* Program the lines for LEDs D2 and D3 to output */
-       pci_read_config_byte(dev, 0x7d, &t8);
-       t8 |= 0xc0;
-       pci_write_config_byte(dev, 0x7d, t8);
-       /* Turn LEDs D2 and D3 off */
-       pci_read_config_byte(dev, 0x7e, &t8);
-       t8 |= 0xc0;
-       pci_write_config_byte(dev, 0x7e, t8);
-}
-
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
-         ddb5074_fixup);
diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c
new file mode 100644 (file)
index 0000000..3a34cd0
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *  arch/mips/pci/fixup-emma2rh.c
+ *      This file defines the PCI configration.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c
+ *
+ *     Copyright 2001 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.
+ *
+ *  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/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+#define EMMA2RH_PCI_HOST_SLOT 0x09
+#define EMMA2RH_USB_SLOT 0x03
+#define PCI_DEVICE_ID_NEC_EMMA2RH      0x014b /* EMMA2RH PCI Host */
+
+/*
+ * we fix up irqs based on the slot number.
+ * The first entry is at AD:11.
+ * Fortunately this works because, although we have two pci buses,
+ * they all have different slot numbers (except for rockhopper slot 20
+ * which is handled below).
+ *
+ */
+
+#define        MAX_SLOT_NUM 10
+static unsigned char irq_map[][5] __initdata = {
+       [3] = {0, MARKEINS_PCI_IRQ_INTB, MARKEINS_PCI_IRQ_INTC,
+              MARKEINS_PCI_IRQ_INTD, 0,},
+       [4] = {0, MARKEINS_PCI_IRQ_INTA, 0, 0, 0,},
+       [5] = {0, 0, 0, 0, 0,},
+       [6] = {0, MARKEINS_PCI_IRQ_INTC, MARKEINS_PCI_IRQ_INTD,
+              MARKEINS_PCI_IRQ_INTA, MARKEINS_PCI_IRQ_INTB,},
+};
+
+static void __devinit nec_usb_controller_fixup(struct pci_dev *dev)
+{
+       if (PCI_SLOT(dev->devfn) == EMMA2RH_USB_SLOT)
+               /* on board USB controller configuration */
+               pci_write_config_dword(dev, 0xe4, 1 << 5);
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+                       nec_usb_controller_fixup);
+
+/*
+ * Prevent the PCI layer from seeing the resources allocated to this device
+ * if it is the host bridge by marking it as such.  These resources are of
+ * no consequence to the PCI layer (they are handled elsewhere).
+ */
+static void __devinit emma2rh_pci_host_fixup(struct pci_dev *dev)
+{
+       int i;
+
+       if (PCI_SLOT(dev->devfn) == EMMA2RH_PCI_HOST_SLOT) {
+               dev->class &= 0xff;
+               dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
+               for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+                       dev->resource[i].start = 0;
+                       dev->resource[i].end = 0;
+                       dev->resource[i].flags = 0;
+               }
+       }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH,
+                        emma2rh_pci_host_fixup);
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       return irq_map[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       return 0;
+}
diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c
new file mode 100644 (file)
index 0000000..1da696d
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <excite.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (pin == 0)
+               return -1;
+
+       return USB_IRQ;         /* USB controller is the only PCI device */
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       return 0;
+}
diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c
new file mode 100644 (file)
index 0000000..3357c13
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * fixup-wrppmc.c: PPMC board specific PCI fixup
+ *
+ * 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, Wind River Inc. Rongkai.zhan (rongkai.zhan@windriver.com)
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/gt64120.h>
+
+/* PCI interrupt pins */
+#define PCI_INTA               1
+#define PCI_INTB               2
+#define PCI_INTC               3
+#define PCI_INTD               4
+
+#define PCI_SLOT_MAXNR 32 /* Each PCI bus has 32 physical slots */
+
+static char pci_irq_tab[PCI_SLOT_MAXNR][5] __initdata = {
+       /* 0    INTA   INTB   INTC   INTD */
+       [0] = {0, 0, 0, 0, 0},          /* Slot 0: GT64120 PCI bridge */
+       [6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0},
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       return pci_irq_tab[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       return 0;
+}
diff --git a/arch/mips/pci/ops-bridge.c b/arch/mips/pci/ops-bridge.c
new file mode 100644 (file)
index 0000000..1fa0992
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * 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, 2000, 04, 06 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/pci.h>
+#include <asm/paccess.h>
+#include <asm/pci/bridge.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn0/hub.h>
+
+/*
+ * The Bridge ASIC supports both type 0 and type 1 access.  Type 1 is
+ * not really documented, so right now I can't write code which uses it.
+ * Therefore we use type 0 accesses for now even though they won't work
+ * correcly for PCI-to-PCI bridges.
+ *
+ * The function is complicated by the ultimate brokeness of the IOC3 chip
+ * which is used in SGI systems.  The IOC3 can only handle 32-bit PCI
+ * accesses and does only decode parts of it's address space.
+ */
+
+static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
+                                int where, int size, u32 * value)
+{
+       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+       bridge_t *bridge = bc->base;
+       int slot = PCI_SLOT(devfn);
+       int fn = PCI_FUNC(devfn);
+       volatile void *addr;
+       u32 cf, shift, mask;
+       int res;
+
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at it for real ...
+        */
+       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+               goto oh_my_gawd;
+
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
+
+       if (size == 1)
+               res = get_dbe(*value, (u8 *) addr);
+       else if (size == 2)
+               res = get_dbe(*value, (u16 *) addr);
+       else
+               res = get_dbe(*value, (u32 *) addr);
+
+       return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at the wrong register.
+        */
+       if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
+               *value = 0;
+               return PCIBIOS_SUCCESSFUL;
+       }
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * anything but 32-bit words ...
+        */
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       shift = ((where & 3) << 3);
+       mask = (0xffffffffU >> ((4 - size) << 3));
+       *value = (cf >> shift) & mask;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
+                                int where, int size, u32 * value)
+{
+       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+       bridge_t *bridge = bc->base;
+       int busno = bus->number;
+       int slot = PCI_SLOT(devfn);
+       int fn = PCI_FUNC(devfn);
+       volatile void *addr;
+       u32 cf, shift, mask;
+       int res;
+
+       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+       addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at it for real ...
+        */
+       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+               goto oh_my_gawd;
+
+       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+       addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
+
+       if (size == 1)
+               res = get_dbe(*value, (u8 *) addr);
+       else if (size == 2)
+               res = get_dbe(*value, (u16 *) addr);
+       else
+               res = get_dbe(*value, (u32 *) addr);
+
+       return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at the wrong register.
+        */
+       if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
+               *value = 0;
+               return PCIBIOS_SUCCESSFUL;
+       }
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * anything but 32-bit words ...
+        */
+       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+       addr = &bridge->b_type1_cfg.c[(fn << 8) | where];
+
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       shift = ((where & 3) << 3);
+       mask = (0xffffffffU >> ((4 - size) << 3));
+       *value = (cf >> shift) & mask;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_read_config(struct pci_bus *bus, unsigned int devfn,
+                          int where, int size, u32 * value)
+{
+       if (bus->number > 0)
+               return pci_conf1_read_config(bus, devfn, where, size, value);
+
+       return pci_conf0_read_config(bus, devfn, where, size, value);
+}
+
+static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
+                                 int where, int size, u32 value)
+{
+       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+       bridge_t *bridge = bc->base;
+       int slot = PCI_SLOT(devfn);
+       int fn = PCI_FUNC(devfn);
+       volatile void *addr;
+       u32 cf, shift, mask, smask;
+       int res;
+
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at it for real ...
+        */
+       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+               goto oh_my_gawd;
+
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
+
+       if (size == 1) {
+               res = put_dbe(value, (u8 *) addr);
+       } else if (size == 2) {
+               res = put_dbe(value, (u16 *) addr);
+       } else {
+               res = put_dbe(value, (u32 *) addr);
+       }
+
+       if (res)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to touch the wrong register.
+        */
+       if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
+               return PCIBIOS_SUCCESSFUL;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * anything but 32-bit words ...
+        */
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       shift = ((where & 3) << 3);
+       mask = (0xffffffffU >> ((4 - size) << 3));
+       smask = mask << shift;
+
+       cf = (cf & ~smask) | ((value & mask) << shift);
+       if (put_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
+                                 int where, int size, u32 value)
+{
+       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+       bridge_t *bridge = bc->base;
+       int slot = PCI_SLOT(devfn);
+       int fn = PCI_FUNC(devfn);
+       int busno = bus->number;
+       volatile void *addr;
+       u32 cf, shift, mask, smask;
+       int res;
+
+       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+       addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to look at it for real ...
+        */
+       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+               goto oh_my_gawd;
+
+       addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
+
+       if (size == 1) {
+               res = put_dbe(value, (u8 *) addr);
+       } else if (size == 2) {
+               res = put_dbe(value, (u16 *) addr);
+       } else {
+               res = put_dbe(value, (u32 *) addr);
+       }
+
+       if (res)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't even give the
+        * generic PCI code a chance to touch the wrong register.
+        */
+       if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
+               return PCIBIOS_SUCCESSFUL;
+
+       /*
+        * IOC3 is fucked fucked beyond believe ...  Don't try to access
+        * anything but 32-bit words ...
+        */
+       addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+       if (get_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       shift = ((where & 3) << 3);
+       mask = (0xffffffffU >> ((4 - size) << 3));
+       smask = mask << shift;
+
+       cf = (cf & ~smask) | ((value & mask) << shift);
+       if (put_dbe(cf, (u32 *) addr))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_write_config(struct pci_bus *bus, unsigned int devfn,
+       int where, int size, u32 value)
+{
+       if (bus->number > 0)
+               return pci_conf1_write_config(bus, devfn, where, size, value);
+
+       return pci_conf0_write_config(bus, devfn, where, size, value);
+}
+
+struct pci_ops bridge_pci_ops = {
+       .read   = pci_read_config,
+       .write  = pci_write_config,
+};
diff --git a/arch/mips/pci/ops-ddb5074.c b/arch/mips/pci/ops-ddb5074.c
deleted file mode 100644 (file)
index 89f97be..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/ddb5xxx/ddb5476/pci_ops.c
- *     Define the pci_ops for DB5477.
- *
- * Much of the code is derived from the original DDB5074 port by
- * Geert Uytterhoeven <geert@sonycom.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.
- *
- */
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#include <asm/addrspace.h>
-#include <asm/debug.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-/*
- * config_swap structure records what set of pdar/pmr are used
- * to access pci config space.  It also provides a place hold the
- * original values for future restoring.
- */
-struct pci_config_swap {
-       u32 pdar;
-       u32 pmr;
-       u32 config_base;
-       u32 config_size;
-       u32 pdar_backup;
-       u32 pmr_backup;
-};
-
-/*
- * On DDB5476, we have one set of swap registers
- */
-struct pci_config_swap ext_pci_swap = {
-       DDB_PCIW0,
-       DDB_PCIINIT0,
-       DDB_PCI_CONFIG_BASE,
-       DDB_PCI_CONFIG_SIZE
-};
-
-static int pci_config_workaround = 1;
-
-/*
- * access config space
- */
-static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus,        /* 0 means top level bus */
-                                        u32 slot_num)
-{
-       u32 pci_addr = 0;
-       u32 pciinit_offset = 0;
-       u32 virt_addr = swap->config_base;
-       u32 option;
-
-       if (pci_config_workaround) {
-               if (slot_num == 5)
-                       slot_num = 14;
-       } else {
-               if (slot_num == 5)
-                       return DDB_BASE + DDB_PCI_BASE;
-       }
-
-       /* minimum pdar (window) size is 2MB */
-       db_assert(swap->config_size >= (2 << 20));
-
-       db_assert(slot_num < (1 << 5));
-       db_assert(bus < (1 << 8));
-
-       /* backup registers */
-       swap->pdar_backup = ddb_in32(swap->pdar);
-       swap->pmr_backup = ddb_in32(swap->pmr);
-
-       /* set the pdar (pci window) register */
-       ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32,      /* 32 bit wide */
-                    0,         /* not on local memory bus */
-                    0);        /* not visible from PCI bus (N/A) */
-
-       /*
-        * calcuate the absolute pci config addr;
-        * according to the spec, we start scanning from adr:11 (0x800)
-        */
-       if (bus == 0) {
-               /* type 0 config */
-               pci_addr = 0x00040000 << slot_num;
-       } else {
-               /* type 1 config */
-               pci_addr = 0x00040000 << slot_num;
-               panic
-                   ("ddb_access_config_base: we don't support type 1 config Yet");
-       }
-
-       /*
-        * if pci_addr is less than pci config window size,  we set
-        * pciinit_offset to 0 and adjust the virt_address.
-        * Otherwise we will try to adjust pciinit_offset.
-        */
-       if (pci_addr < swap->config_size) {
-               virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
-               pciinit_offset = 0;
-       } else {
-               db_assert((pci_addr & (swap->config_size - 1)) == 0);
-               virt_addr = KSEG1ADDR(swap->config_base);
-               pciinit_offset = pci_addr;
-       }
-
-       /* set the pmr register */
-       option = DDB_PCI_ACCESS_32;
-       if (bus != 0)
-               option |= DDB_PCI_CFGTYPE1;
-       ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
-
-       return virt_addr;
-}
-
-static inline void ddb_close_config_base(struct pci_config_swap *swap)
-{
-       ddb_out32(swap->pdar, swap->pdar_backup);
-       ddb_out32(swap->pmr, swap->pmr_backup);
-}
-
-static int read_config_dword(struct pci_config_swap *swap,
-                            struct pci_dev *dev, u32 where, u32 * val)
-{
-       u32 bus, slot_num, func_num;
-       u32 base;
-
-       db_assert((where & 3) == 0);
-       db_assert(where < (1 << 8));
-
-       /* check if the bus is top-level */
-       if (dev->bus->parent != NULL) {
-               bus = dev->bus->number;
-               db_assert(bus != 0);
-       } else {
-               bus = 0;
-       }
-
-       slot_num = PCI_SLOT(dev->devfn);
-       func_num = PCI_FUNC(dev->devfn);
-       base = ddb_access_config_base(swap, bus, slot_num);
-       *val = *(volatile u32 *) (base + (func_num << 8) + where);
-       ddb_close_config_base(swap);
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int read_config_word(struct pci_config_swap *swap,
-                           struct pci_dev *dev, u32 where, u16 * val)
-{
-       int status;
-       u32 result;
-
-       db_assert((where & 1) == 0);
-
-       status = read_config_dword(swap, dev, where & ~3, &result);
-       if (where & 2)
-               result >>= 16;
-       *val = result & 0xffff;
-       return status;
-}
-
-static int read_config_byte(struct pci_config_swap *swap,
-                           struct pci_dev *dev, u32 where, u8 * val)
-{
-       int status;
-       u32 result;
-
-       status = read_config_dword(swap, dev, where & ~3, &result);
-       if (where & 1)
-               result >>= 8;
-       if (where & 2)
-               result >>= 16;
-       *val = result & 0xff;
-       return status;
-}
-
-static int write_config_dword(struct pci_config_swap *swap,
-                             struct pci_dev *dev, u32 where, u32 val)
-{
-       u32 bus, slot_num, func_num;
-       u32 base;
-
-       db_assert((where & 3) == 0);
-       db_assert(where < (1 << 8));
-
-       /* check if the bus is top-level */
-       if (dev->bus->parent != NULL) {
-               bus = dev->bus->number;
-               db_assert(bus != 0);
-       } else {
-               bus = 0;
-       }
-
-       slot_num = PCI_SLOT(dev->devfn);
-       func_num = PCI_FUNC(dev->devfn);
-       base = ddb_access_config_base(swap, bus, slot_num);
-       *(volatile u32 *) (base + (func_num << 8) + where) = val;
-       ddb_close_config_base(swap);
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_word(struct pci_config_swap *swap,
-                            struct pci_dev *dev, u32 where, u16 val)
-{
-       int status, shift = 0;
-       u32 result;
-
-       db_assert((where & 1) == 0);
-
-       status = read_config_dword(swap, dev, where & ~3, &result);
-       if (status != PCIBIOS_SUCCESSFUL)
-               return status;
-
-       if (where & 2)
-               shift += 16;
-       result &= ~(0xffff << shift);
-       result |= val << shift;
-       return write_config_dword(swap, dev, where & ~3, result);
-}
-
-static int write_config_byte(struct pci_config_swap *swap,
-                            struct pci_dev *dev, u32 where, u8 val)
-{
-       int status, shift = 0;
-       u32 result;
-
-       status = read_config_dword(swap, dev, where & ~3, &result);
-       if (status != PCIBIOS_SUCCESSFUL)
-               return status;
-
-       if (where & 2)
-               shift += 16;
-       if (where & 1)
-               shift += 8;
-       result &= ~(0xff << shift);
-       result |= val << shift;
-       return write_config_dword(swap, dev, where & ~3, result);
-}
-
-#define        MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
-static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \
-{ \
-     return rw##_config_##unitname(pciswap, \
-                                   dev, \
-                                   where, \
-                                   val); \
-}
-
-MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
-
-    MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
-
-struct pci_ops ddb5476_ext_pci_ops = {
-       extpci_read_config_byte,
-       extpci_read_config_word,
-       extpci_read_config_dword,
-       extpci_write_config_byte,
-       extpci_write_config_word,
-       extpci_write_config_dword
-};
diff --git a/arch/mips/pci/ops-ddb5476.c b/arch/mips/pci/ops-ddb5476.c
deleted file mode 100644 (file)
index 12da58e..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/ddb5xxx/ddb5476/pci_ops.c
- *     Define the pci_ops for DB5477.
- *
- * Much of the code is derived from the original DDB5074 port by
- * Geert Uytterhoeven <geert@sonycom.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.
- *
- */
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#include <asm/addrspace.h>
-#include <asm/debug.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-/*
- * config_swap structure records what set of pdar/pmr are used
- * to access pci config space.  It also provides a place hold the
- * original values for future restoring.
- */
-struct pci_config_swap {
-       u32 pdar;
-       u32 pmr;
-       u32 config_base;
-       u32 config_size;
-       u32 pdar_backup;
-       u32 pmr_backup;
-};
-
-/*
- * On DDB5476, we have one set of swap registers
- */
-struct pci_config_swap ext_pci_swap = {
-       DDB_PCIW0,
-       DDB_PCIINIT0,
-       DDB_PCI_CONFIG_BASE,
-       DDB_PCI_CONFIG_SIZE
-};
-
-static int pci_config_workaround = 1;
-
-/*
- * access config space
- */
-static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus,        /* 0 means top level bus */
-                                        u32 slot_num)
-{
-       u32 pci_addr = 0;
-       u32 pciinit_offset = 0;
-       u32 virt_addr = swap->config_base;
-       u32 option;
-
-       if (pci_config_workaround) {
-               /* [jsun] work around Vrc5476 controller itself, returnning
-                * slot 0 essentially makes vrc5476 invisible
-                */
-               if (slot_num == 12)
-                       slot_num = 0;
-
-#if 0
-               /* BUG : skip P2P bridge for now */
-               if (slot_num == 5)
-                       slot_num = 0;
-#endif
-
-       } else {
-               /* now we have to be hornest, returning the true
-                * PCI config headers for vrc5476
-                */
-               if (slot_num == 12) {
-                       swap->pdar_backup = ddb_in32(swap->pdar);
-                       swap->pmr_backup = ddb_in32(swap->pmr);
-                       return DDB_BASE + DDB_PCI_BASE;
-               }
-       }
-
-       /* minimum pdar (window) size is 2MB */
-       db_assert(swap->config_size >= (2 << 20));
-
-       db_assert(slot_num < (1 << 5));
-       db_assert(bus < (1 << 8));
-
-       /* backup registers */
-       swap->pdar_backup = ddb_in32(swap->pdar);
-       swap->pmr_backup = ddb_in32(swap->pmr);
-
-       /* set the pdar (pci window) register */
-       ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32,      /* 32 bit wide */
-                    0,         /* not on local memory bus */
-                    0);        /* not visible from PCI bus (N/A) */
-
-       /*
-        * calcuate the absolute pci config addr;
-        * according to the spec, we start scanning from adr:11 (0x800)
-        */
-       if (bus == 0) {
-               /* type 0 config */
-               pci_addr = 0x800 << slot_num;
-       } else {
-               /* type 1 config */
-               pci_addr = (bus << 16) | (slot_num << 11);
-               /* panic("ddb_access_config_base: we don't support type 1 config Yet"); */
-       }
-
-       /*
-        * if pci_addr is less than pci config window size,  we set
-        * pciinit_offset to 0 and adjust the virt_address.
-        * Otherwise we will try to adjust pciinit_offset.
-        */
-       if (pci_addr < swap->config_size) {
-               virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
-               pciinit_offset = 0;
-       } else {
-               db_assert((pci_addr & (swap->config_size - 1)) == 0);
-               virt_addr = KSEG1ADDR(swap->config_base);
-               pciinit_offset = pci_addr;
-       }
-
-       /* set the pmr register */
-       option = DDB_PCI_ACCESS_32;
-       if (bus != 0)
-               option |= DDB_PCI_CFGTYPE1;
-       ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
-
-       return virt_addr;
-}
-
-static inline void ddb_close_config_base(struct pci_config_swap *swap)
-{
-       ddb_out32(swap->pdar, swap->pdar_backup);
-       ddb_out32(swap->pmr, swap->pmr_backup);
-}
-
-static int read_config_dword(struct pci_config_swap *swap,
-                            struct pci_dev *dev, u32 where, u32 * val)
-{
-       u32 bus, slot_num, func_num;
-       u32 base;
-
-       db_assert((where & 3) == 0);
-       db_assert(where < (1 << 8));
-
-       /* check if the bus is top-level */
-       if (dev->bus->parent != NULL) {
-               bus = dev->bus->number;
-               db_assert(bus != 0);
-       } else {
-               bus = 0;
-       }
-
-       slot_num = PCI_SLOT(dev->devfn);
-       func_num = PCI_FUNC(dev->devfn);
-       base = ddb_access_config_base(swap, bus, slot_num);
-       *val = *(volatile u32 *) (base + (func_num << 8) + where);
-       ddb_close_config_base(swap);
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int read_config_word(struct pci_config_swap *swap,
-                           struct pci_dev *dev, u32 where, u16 * val)
-{
-       int status;
-       u32 result;
-
-       db_assert((where & 1) == 0);
-
-       status = read_config_dword(swap, dev, where & ~3, &result);
-       if (where & 2)
-               result >>= 16;
-       *val = result & 0xffff;
-       return status;
-}
-
-static int read_config_byte(struct pci_config_swap *swap,
-                           struct pci_dev *dev, u32 where, u8 * val)
-{
-       int status;
-       u32 result;
-
-       status = read_config_dword(swap, dev, where & ~3, &result);
-       if (where & 1)
-               result >>= 8;
-       if (where & 2)
-               result >>= 16;
-       *val = result & 0xff;
-       return status;
-}
-
-static int write_config_dword(struct pci_config_swap *swap,
-                             struct pci_dev *dev, u32 where, u32 val)
-{
-       u32 bus, slot_num, func_num;
-       u32 base;
-
-       db_assert((where & 3) == 0);
-       db_assert(where < (1 << 8));
-
-       /* check if the bus is top-level */
-       if (dev->bus->parent != NULL) {
-               bus = dev->bus->number;
-               db_assert(bus != 0);
-       } else {
-               bus = 0;
-       }
-
-       slot_num = PCI_SLOT(dev->devfn);
-       func_num = PCI_FUNC(dev->devfn);
-       base = ddb_access_config_base(swap, bus, slot_num);
-       *(volatile u32 *) (base + (func_num << 8) + where) = val;
-       ddb_close_config_base(swap);
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_word(struct pci_config_swap *swap,
-                            struct pci_dev *dev, u32 where, u16 val)
-{
-       int status, shift = 0;
-       u32 result;
-
-       db_assert((where & 1) == 0);
-
-       status = read_config_dword(swap, dev, where & ~3, &result);
-       if (status != PCIBIOS_SUCCESSFUL)
-               return status;
-
-       if (where & 2)
-               shift += 16;
-       result &= ~(0xffff << shift);
-       result |= val << shift;
-       return write_config_dword(swap, dev, where & ~3, result);
-}
-
-static int write_config_byte(struct pci_config_swap *swap,
-                            struct pci_dev *dev, u32 where, u8 val)
-{
-       int status, shift = 0;
-       u32 result;
-
-       status = read_config_dword(swap, dev, where & ~3, &result);
-       if (status != PCIBIOS_SUCCESSFUL)
-               return status;
-
-       if (where & 2)
-               shift += 16;
-       if (where & 1)
-               shift += 8;
-       result &= ~(0xff << shift);
-       result |= val << shift;
-       return write_config_dword(swap, dev, where & ~3, result);
-}
-
-#define        MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
-static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \
-{ \
-     return rw##_config_##unitname(pciswap, \
-                                   dev, \
-                                   where, \
-                                   val); \
-}
-
-MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
-
-    MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
-
-struct pci_ops ddb5476_ext_pci_ops = {
-       extpci_read_config_byte,
-       extpci_read_config_word,
-       extpci_read_config_dword,
-       extpci_write_config_byte,
-       extpci_write_config_word,
-       extpci_write_config_dword
-};
diff --git a/arch/mips/pci/ops-emma2rh.c b/arch/mips/pci/ops-emma2rh.c
new file mode 100644 (file)
index 0000000..e21b11b
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ *  arch/mips/pci/ops-emma2rh.c
+ *      This file defines the PCI operation for EMMA2RH.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/pci/ops-vr41xx.c
+ *
+ *     Copyright 2001 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.
+ *
+ *  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/config.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+#define RTABORT (0x1<<9)
+#define RMABORT (0x1<<10)
+#define EMMA2RH_PCI_SLOT_NUM 9 /* 0000:09.0 is final PCI device */
+
+/*
+ * access config space
+ */
+
+static int check_args(struct pci_bus *bus, u32 devfn, u32 * bus_num)
+{
+       /* check if the bus is top-level */
+       if (bus->parent != NULL) {
+               *bus_num = bus->number;
+               db_assert(bus_num != 0);
+       } else
+               *bus_num = 0;
+
+       if (*bus_num == 0) {
+               /* Type 0 */
+               if (PCI_SLOT(devfn) >= 10)
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+       } else {
+               /* Type 1 */
+               if ((*bus_num >= 64) || (PCI_SLOT(devfn) >= 16))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+       return 0;
+}
+
+static inline int set_pci_configuration_address(unsigned char bus_num,
+                                               unsigned int devfn, int where)
+{
+       u32 config_win0;
+
+       emma2rh_out32(EMMA2RH_PCI_INT, ~RMABORT);
+       if (bus_num == 0)
+               /*
+                * Type 0 configuration
+                */
+               config_win0 = (1 << (22 + PCI_SLOT(devfn))) | (5 << 9);
+       else
+               /*
+                * Type 1 configuration
+                */
+               config_win0 = (bus_num << 26) | (PCI_SLOT(devfn) << 22) |
+                   (1 << 15) | (5 << 9);
+
+       emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, config_win0);
+
+       return 0;
+}
+
+static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where,
+                          int size, uint32_t * val)
+{
+       u32 bus_num;
+       u32 base = KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE);
+       u32 backup_win0;
+       u32 data;
+
+       *val = 0xffffffffU;
+
+       if (check_args(bus, devfn, &bus_num) == PCIBIOS_DEVICE_NOT_FOUND)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       backup_win0 = emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR);
+
+       if (set_pci_configuration_address(bus_num, devfn, where) < 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       data =
+           *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) +
+                             (where & 0xfffffffc));
+
+       switch (size) {
+       case 1:
+               *val = (data >> ((where & 3) << 3)) & 0xffU;
+               break;
+       case 2:
+               *val = (data >> ((where & 2) << 3)) & 0xffffU;
+               break;
+       case 4:
+               *val = data;
+               break;
+       default:
+               emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+
+       if (emma2rh_in32(EMMA2RH_PCI_INT) & RMABORT)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where,
+                           int size, u32 val)
+{
+       u32 bus_num;
+       u32 base = KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE);
+       u32 backup_win0;
+       u32 data;
+       int shift;
+
+       if (check_args(bus, devfn, &bus_num) == PCIBIOS_DEVICE_NOT_FOUND)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       backup_win0 = emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR);
+
+       if (set_pci_configuration_address(bus_num, devfn, where) < 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /* read modify write */
+       data =
+           *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) +
+                             (where & 0xfffffffc));
+
+       switch (size) {
+       case 1:
+               shift = (where & 3) << 3;
+               data &= ~(0xffU << shift);
+               data |= ((val & 0xffU) << shift);
+               break;
+       case 2:
+               shift = (where & 2) << 3;
+               data &= ~(0xffffU << shift);
+               data |= ((val & 0xffffU) << shift);
+               break;
+       case 4:
+               data = val;
+               break;
+       default:
+               emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+       *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) +
+                         (where & 0xfffffffc)) = data;
+
+       emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+       if (emma2rh_in32(EMMA2RH_PCI_INT) & RMABORT)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops emma2rh_pci_ops = {
+       .read = pci_config_read,
+       .write = pci_config_write,
+};
index b7a8b9a6f9dbb436478f5318ef0118420d032828..ba8328505a0af4d4eb081c7e411a02da80e17af1 100644 (file)
 static struct resource pci_mem_resource_1;
 
 static struct resource pci_io_resource = {
-       "io pci IO space",
-       0x14018000,
-       0x17FFFFFF,
-       IORESOURCE_IO
+       .start  = 0x14018000,
+       .end    = 0x17FFFFFF,
+       .name   = "io pci IO space",
+       .flags  = IORESOURCE_IO
 };
 
 static struct resource pci_mem_resource_0 = {
-       "ext pci memory space 0/1",
-       0x10101000,
-       0x13FFFFFF,
-       IORESOURCE_MEM,
-       &pci_mem_resource_0,
-       NULL,
-       &pci_mem_resource_1
+       .start  = 0x10101000,
+       .end    = 0x13FFFFFF,
+       .name   = "ext pci memory space 0/1",
+       .flags  = IORESOURCE_MEM,
+       .parent = &pci_mem_resource_0,
+       .sibling = NULL,
+       .child  = &pci_mem_resource_1
 };
 
 static struct resource pci_mem_resource_1 = {
-       "ext pci memory space 2/3",
-       0x1A000000,
-       0x1FBFFFFF,
-       IORESOURCE_MEM,
-       &pci_mem_resource_0,
-       NULL,
-       NULL
+       .start  = 0x1A000000,
+       .end    = 0x1FBFFFFF,
+       .name   = "ext pci memory space 2/3",
+       .flags  = IORESOURCE_MEM,
+       .parent = &pci_mem_resource_0
 };
 
 extern struct pci_ops it8172_pci_ops;
index 62bdd19c7f8e9814ae4e7aeec525dd0a1f32d0f7..2b0ccd6d9dcd98bc7c6894389dc40a24433ea860 100644 (file)
@@ -47,13 +47,13 @@ static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int reg,
 
        switch (size) {
        case 1:
-               *val = *(volatile  u8 *) (PCIMT_CONFIG_DATA + (reg & 3));
+               *val = inb(PCIMT_CONFIG_DATA + (reg & 3));
                break;
        case 2:
-               *val = *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2));
+               *val = inw(PCIMT_CONFIG_DATA + (reg & 2));
                break;
        case 4:
-               *val = *(volatile u32 *) PCIMT_CONFIG_DATA;
+               *val = inl(PCIMT_CONFIG_DATA);
                break;
        }
 
@@ -70,13 +70,13 @@ static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int reg,
 
        switch (size) {
        case 1:
-               *(volatile  u8 *) (PCIMT_CONFIG_DATA + (reg & 3)) = val;
+               outb (val, PCIMT_CONFIG_DATA + (reg & 3));
                break;
        case 2:
-               *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2)) = val;
+               outw (val, PCIMT_CONFIG_DATA + (reg & 2));
                break;
        case 4:
-               *(volatile u32 *) PCIMT_CONFIG_DATA = val;
+               outl (val, PCIMT_CONFIG_DATA);
                break;
        }
 
index 233ec6f2054d74248b8d7d2e032bca2817bafa40..ebf8fc40e9b293ff924e2584a772f1a57090b9bb 100644 (file)
 #include <linux/pci.h>
 #include <linux/kernel.h>
 
-#include <asm/titan_dep.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/rm9k-ocd.h>
 
+/*
+ * PCI specific defines
+ */
+#define        TITAN_PCI_0_CONFIG_ADDRESS      0x780
+#define        TITAN_PCI_0_CONFIG_DATA         0x784
+
+/*
+ * Titan PCI Config Read Byte
+ */
 static int titan_read_config(struct pci_bus *bus, unsigned int devfn, int reg,
        int size, u32 * val)
 {
@@ -43,8 +54,8 @@ static int titan_read_config(struct pci_bus *bus, unsigned int devfn, int reg,
 
 
        /* start the configuration cycle */
-       TITAN_WRITE(TITAN_PCI_0_CONFIG_ADDRESS, address);
-       tmp = TITAN_READ(TITAN_PCI_0_CONFIG_DATA) >> ((reg & 3) << 3);
+       ocd_writel(address, TITAN_PCI_0_CONFIG_ADDRESS);
+       tmp = ocd_readl(TITAN_PCI_0_CONFIG_DATA) >> ((reg & 3) << 3);
 
        switch (size) {
        case 1:
@@ -71,20 +82,20 @@ static int titan_write_config(struct pci_bus *bus, unsigned int devfn, int reg,
                (reg & 0xfc) | 0x80000000;
 
        /* start the configuration cycle */
-       TITAN_WRITE(TITAN_PCI_0_CONFIG_ADDRESS, address);
+       ocd_writel(address, TITAN_PCI_0_CONFIG_ADDRESS);
 
        /* write the data */
        switch (size) {
        case 1:
-               TITAN_WRITE_8(TITAN_PCI_0_CONFIG_DATA + (~reg & 0x3), val);
+               ocd_writeb(val, TITAN_PCI_0_CONFIG_DATA + (~reg & 0x3));
                break;
 
        case 2:
-               TITAN_WRITE_16(TITAN_PCI_0_CONFIG_DATA + (~reg & 0x2), val);
+               ocd_writew(val, TITAN_PCI_0_CONFIG_DATA + (~reg & 0x2));
                break;
 
        case 4:
-               TITAN_WRITE(TITAN_PCI_0_CONFIG_DATA, val);
+               ocd_writel(val, TITAN_PCI_0_CONFIG_DATA);
                break;
        }
 
diff --git a/arch/mips/pci/pci-ddb5074.c b/arch/mips/pci/pci-ddb5074.c
deleted file mode 100644 (file)
index 73f9cee..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/debug.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-static struct resource extpci_io_resource = {
-       "pci IO space",
-       0x1000,                 /* leave some room for ISA bus */
-       DDB_PCI_IO_SIZE - 1,
-       IORESOURCE_IO
-};
-
-static struct resource extpci_mem_resource = {
-       "pci memory space",
-       DDB_PCI_MEM_BASE + 0x00100000,  /* leave 1 MB for RTC */
-       DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1,
-       IORESOURCE_MEM
-};
-
-extern struct pci_ops ddb5476_ext_pci_ops;
-
-struct pci_controller ddb5476_controller = {
-       .pci_ops        = &ddb5476_ext_pci_ops,
-       .io_resource    = &extpci_io_resource,
-       .mem_resource   = &extpci_mem_resource,
-};
-
-#define     PCI_EXT_INTA        8
-#define     PCI_EXT_INTB        9
-#define     PCI_EXT_INTC        10
-#define     PCI_EXT_INTD        11
-#define     PCI_EXT_INTE        12
-
-#define     MAX_SLOT_NUM        14
-
-static unsigned char irq_map[MAX_SLOT_NUM] = {
-  [ 0] = nile4_to_irq(PCI_EXT_INTE),
-  [ 1] = nile4_to_irq(PCI_EXT_INTA),
-  [ 2] = nile4_to_irq(PCI_EXT_INTA),
-  [ 3] = nile4_to_irq(PCI_EXT_INTB),
-  [ 4] = nile4_to_irq(PCI_EXT_INTC),
-  [ 5] = nile4_to_irq(NILE4_INT_UART),
-  [10] = nile4_to_irq(PCI_EXT_INTE),
-  [13] = nile4_to_irq(PCI_EXT_INTE),
-};
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       return irq_map[slot];
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-       return 0;
-}
-
-void __init ddb_pci_reset_bus(void)
-{
-       u32 temp;
-
-       /*
-        * I am not sure about the "official" procedure, the following
-        * steps work as far as I know:
-        * We first set PCI cold reset bit (bit 31) in PCICTRL-H.
-        * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H.
-        * The same is true for both PCI channels.
-        */
-       temp = ddb_in32(DDB_PCICTRL + 4);
-       temp |= 0x80000000;
-       ddb_out32(DDB_PCICTRL + 4, temp);
-       temp &= ~0xc0000000;
-       ddb_out32(DDB_PCICTRL + 4, temp);
-
-}
diff --git a/arch/mips/pci/pci-ddb5476.c b/arch/mips/pci/pci-ddb5476.c
deleted file mode 100644 (file)
index 90dd495..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/debug.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-static struct resource extpci_io_resource = {
-       "pci IO space",
-       0x1000,                 /* leave some room for ISA bus */
-       DDB_PCI_IO_SIZE - 1,
-       IORESOURCE_IO
-};
-
-static struct resource extpci_mem_resource = {
-       "pci memory space",
-       DDB_PCI_MEM_BASE + 0x00100000,  /* leave 1 MB for RTC */
-       DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1,
-       IORESOURCE_MEM
-};
-
-extern struct pci_ops ddb5476_ext_pci_ops;
-
-struct pci_controller ddb5476_controller = {
-       .pci_ops        = &ddb5476_ext_pci_ops,
-       .io_resource    = &extpci_io_resource,
-       .mem_resource   = &extpci_mem_resource
-};
-
-
-/*
- * we fix up irqs based on the slot number.
- * The first entry is at AD:11.
- *
- * This does not work for devices on sub-buses yet.
- */
-
-/*
- * temporary
- */
-
-#define                PCI_EXT_INTA            8
-#define                PCI_EXT_INTB            9
-#define                PCI_EXT_INTC            10
-#define                PCI_EXT_INTD            11
-#define                PCI_EXT_INTE            12
-
-/*
- * based on ddb5477 manual page 11
- */
-#define                MAX_SLOT_NUM            21
-static unsigned char irq_map[MAX_SLOT_NUM] = {
- [ 2] = 9,                             /* AD:13        USB             */
- [ 3] = 10,                            /* AD:14        PMU             */
- [ 5] = 0,                             /* AD:16        P2P bridge      */
- [ 6] = nile4_to_irq(PCI_EXT_INTB),    /* AD:17                        */
- [ 7] =        nile4_to_irq(PCI_EXT_INTC),     /* AD:18                        */
- [ 8] = nile4_to_irq(PCI_EXT_INTD),    /* AD:19                        */
- [ 9] = nile4_to_irq(PCI_EXT_INTA),    /* AD:20                        */
- [13] = 14,                            /* AD:24 HD controller, M5229   */
-};
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       return irq_map[slot];
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-       return 0;
-}
-
-void __init ddb_pci_reset_bus(void)
-{
-       u32 temp;
-
-       /*
-        * I am not sure about the "official" procedure, the following
-        * steps work as far as I know:
-        * We first set PCI cold reset bit (bit 31) in PCICTRL-H.
-        * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H.
-        * The same is true for both PCI channels.
-        */
-       temp = ddb_in32(DDB_PCICTRL + 4);
-       temp |= 0x80000000;
-       ddb_out32(DDB_PCICTRL + 4, temp);
-       temp &= ~0xc0000000;
-       ddb_out32(DDB_PCICTRL + 4, temp);
-
-}
index 826d653184e576d1322c496d87a850102be309f6..d071bc375b11a90efa8b375e16c4a7053c373200 100644 (file)
 #include <asm/ddb5xxx/ddb5xxx.h>
 
 static struct resource extpci_io_resource = {
-       "ext pci IO space",
-       DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + 0x4000,
-       DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE - 1,
-       IORESOURCE_IO
+       .start  = DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + 0x4000,
+       .end    = DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE - 1,
+       .name   = "ext pci IO space",
+       .flags  = IORESOURCE_IO
 };
 
 static struct resource extpci_mem_resource = {
-       "ext pci memory space",
-       DDB_PCI0_MEM_BASE + 0x100000,
-       DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE - 1,
-       IORESOURCE_MEM
+       .start  = DDB_PCI0_MEM_BASE + 0x100000,
+       .end    = DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE - 1,
+       .name   = "ext pci memory space",
+       .flags  = IORESOURCE_MEM
 };
 
 static struct resource iopci_io_resource = {
-       "io pci IO space",
-       DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE,
-       DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE - 1,
-       IORESOURCE_IO
+       .start  = DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE,
+       .end    = DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE - 1,
+       .name   = "io pci IO space",
+       .flags  = IORESOURCE_IO
 };
 
 static struct resource iopci_mem_resource = {
-       "ext pci memory space",
-       DDB_PCI1_MEM_BASE,
-       DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE - 1,
-       IORESOURCE_MEM
+       .start  = DDB_PCI1_MEM_BASE,
+       .end    = DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE - 1,
+       .name   = "ext pci memory space",
+       .flags  = IORESOURCE_MEM
 };
 
 extern struct pci_ops ddb5477_ext_pci_ops;
diff --git a/arch/mips/pci/pci-emma2rh.c b/arch/mips/pci/pci-emma2rh.c
new file mode 100644 (file)
index 0000000..0f8b230
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  arch/mips/pci/pci-emma2rh.c
+ *      This file defines the PCI configration.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c
+ *
+ *     Copyright 2001 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.
+ *
+ *  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/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+static struct resource pci_io_resource = {
+       .name = "pci IO space",
+       .start = EMMA2RH_PCI_IO_BASE,
+       .end = EMMA2RH_PCI_IO_BASE + EMMA2RH_PCI_IO_SIZE - 1,
+       .flags = IORESOURCE_IO,
+};
+
+static struct resource pci_mem_resource = {
+       .name = "pci memory space",
+       .start = EMMA2RH_PCI_MEM_BASE,
+       .end = EMMA2RH_PCI_MEM_BASE + EMMA2RH_PCI_MEM_SIZE - 1,
+       .flags = IORESOURCE_MEM,
+};
+
+extern struct pci_ops emma2rh_pci_ops;
+
+static struct pci_controller emma2rh_pci_controller = {
+       .pci_ops = &emma2rh_pci_ops,
+       .mem_resource = &pci_mem_resource,
+       .io_resource = &pci_io_resource,
+       .mem_offset = -0x04000000,
+       .io_offset = 0,
+};
+
+static void __init emma2rh_pci_init(void)
+{
+       /* setup PCI interface */
+       emma2rh_out32(EMMA2RH_PCI_ARBIT_CTR, 0x70f);
+
+       emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, 0x80000a18);
+       emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_COMMAND,
+                     PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_CAP_LIST |
+                     PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+       emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_BASE_ADDRESS_0, 0x10000000);
+       emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_BASE_ADDRESS_1, 0x00000000);
+
+       emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, 0x12000000 | 0x218);
+       emma2rh_out32(EMMA2RH_PCI_IWIN1_CTR, 0x18000000 | 0x600);
+       emma2rh_out32(EMMA2RH_PCI_INIT_ESWP, 0x00000200);
+
+       emma2rh_out32(EMMA2RH_PCI_TWIN_CTR, 0x00009200);
+       emma2rh_out32(EMMA2RH_PCI_TWIN_BADR, 0x00000000);
+       emma2rh_out32(EMMA2RH_PCI_TWIN0_DADR, 0x00000000);
+       emma2rh_out32(EMMA2RH_PCI_TWIN1_DADR, 0x00000000);
+}
+
+static int __init emma2rh_pci_setup(void)
+{
+       emma2rh_pci_init();
+       register_pci_controller(&emma2rh_pci_controller);
+       return 0;
+}
+
+arch_initcall(emma2rh_pci_setup);
diff --git a/arch/mips/pci/pci-excite.c b/arch/mips/pci/pci-excite.c
new file mode 100644 (file)
index 0000000..3c86c77
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <asm/rm9k-ocd.h>
+#include <excite.h>
+
+
+extern struct pci_ops titan_pci_ops;
+
+
+static struct resource
+       mem_resource =  {
+               .name   = "PCI memory",
+               .start  = EXCITE_PHYS_PCI_MEM,
+               .end    = EXCITE_PHYS_PCI_MEM + EXCITE_SIZE_PCI_MEM - 1,
+               .flags  = IORESOURCE_MEM
+       },
+       io_resource = {
+               .name   = "PCI I/O",
+               .start  = EXCITE_PHYS_PCI_IO,
+               .end    = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1,
+               .flags  = IORESOURCE_IO
+       };
+
+
+static struct pci_controller bx_controller = {
+       .pci_ops        = &titan_pci_ops,
+       .mem_resource   = &mem_resource,
+       .mem_offset     = 0x00000000UL,
+       .io_resource    = &io_resource,
+       .io_offset      = 0x00000000UL
+};
+
+
+static char
+       iopage_failed[] __initdata   = "Cannot allocate PCI I/O page",
+       modebits_no_pci[] __initdata = "PCI is not configured in mode bits";
+
+#define RM9000x2_OCD_HTSC      0x0604
+#define RM9000x2_OCD_HTBHL     0x060c
+#define RM9000x2_OCD_PCIHRST   0x078c
+
+#define RM9K_OCD_MODEBIT1      0x00d4 /* (MODEBIT1) Mode Bit 1 */
+#define RM9K_OCD_CPHDCR                0x00f4 /* CPU-PCI/HT Data Control. */
+
+#define PCISC_FB2B             0x00000200
+#define PCISC_MWICG            0x00000010
+#define PCISC_EMC              0x00000004
+#define PCISC_ERMA             0x00000002
+
+
+
+static int __init basler_excite_pci_setup(void)
+{
+       const unsigned int fullbars = memsize / (256 << 20);
+       unsigned int i;
+
+       /* Check modebits to see if PCI is really enabled. */
+       if (!((ocd_readl(RM9K_OCD_MODEBIT1) >> (47-32)) & 0x1))
+               panic(modebits_no_pci);
+
+       if (NULL == request_mem_region(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO,
+                                      "Memory-mapped PCI I/O page"))
+               panic(iopage_failed);
+
+       /* Enable PCI 0 as master for config cycles */
+       ocd_writel(PCISC_EMC | PCISC_ERMA, RM9000x2_OCD_HTSC);
+
+
+       /* Set up latency timer */
+       ocd_writel(0x8008, RM9000x2_OCD_HTBHL);
+
+       /*  Setup host IO and Memory space */
+       ocd_writel((EXCITE_PHYS_PCI_IO >> 4) | 1, LKB7);
+       ocd_writel(((EXCITE_SIZE_PCI_IO >> 4) & 0x7fffff00) - 0x100, LKM7);
+       ocd_writel((EXCITE_PHYS_PCI_MEM >> 4) | 1, LKB8);
+       ocd_writel(((EXCITE_SIZE_PCI_MEM >> 4) & 0x7fffff00) - 0x100, LKM8);
+
+       /* Set up PCI BARs to map all installed memory */
+       for (i = 0; i < 6; i++) {
+               const unsigned int bar = 0x610 + i * 4;
+
+               if (i < fullbars) {
+                       ocd_writel(0x10000000 * i, bar);
+                       ocd_writel(0x01000000 * i, bar + 0x140);
+                       ocd_writel(0x0ffff029, bar + 0x100);
+                       continue;
+               }
+
+               if (i == fullbars) {
+                       int o;
+                       u32 mask;
+
+                       const unsigned long rem = memsize - i * 0x10000000;
+                       if (!rem) {
+                               ocd_writel(0x00000000, bar + 0x100);
+                               continue;
+                       }
+
+                       o = ffs(rem) - 1;
+                       if (rem & ~(0x1 << o))
+                               o++;
+                       mask = ((0x1 << o) & 0x0ffff000) - 0x1000;
+                       ocd_writel(0x10000000 * i, bar);
+                       ocd_writel(0x01000000 * i, bar + 0x140);
+                       ocd_writel(0x00000029 | mask, bar + 0x100);
+                       continue;
+               }
+
+               ocd_writel(0x00000000, bar + 0x100);
+       }
+
+       /* Finally, enable the PCI interupt */
+#if USB_IRQ > 7
+       set_c0_intcontrol(1 << USB_IRQ);
+#else
+       set_c0_status(1 << (USB_IRQ + 8));
+#endif
+
+       ioport_resource.start = EXCITE_PHYS_PCI_IO;
+       ioport_resource.end = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1;
+       set_io_port_base((unsigned long) ioremap_nocache(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO));
+       register_pci_controller(&bx_controller);
+       return 0;
+}
+
+
+arch_initcall(basler_excite_pci_setup);
index 6002d2a6a262b019d770ff6cf4f3532a13cde873..80eb9af9ecdffb3c7ec0ab883903a6ac082f05aa 100644 (file)
@@ -40,297 +40,7 @@ static struct bridge_controller bridges[MAX_PCI_BUSSES];
 struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
 int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
 
-/*
- * The Bridge ASIC supports both type 0 and type 1 access.  Type 1 is
- * not really documented, so right now I can't write code which uses it.
- * Therefore we use type 0 accesses for now even though they won't work
- * correcly for PCI-to-PCI bridges.
- *
- * The function is complicated by the ultimate brokeness of the IOC3 chip
- * which is used in SGI systems.  The IOC3 can only handle 32-bit PCI
- * accesses and does only decode parts of it's address space.
- */
-
-static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
-                                int where, int size, u32 * value)
-{
-       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
-       bridge_t *bridge = bc->base;
-       int slot = PCI_SLOT(devfn);
-       int fn = PCI_FUNC(devfn);
-       volatile void *addr;
-       u32 cf, shift, mask;
-       int res;
-
-       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
-       if (get_dbe(cf, (u32 *) addr))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
-        * generic PCI code a chance to look at it for real ...
-        */
-       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-               goto oh_my_gawd;
-
-       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
-
-       if (size == 1)
-               res = get_dbe(*value, (u8 *) addr);
-       else if (size == 2)
-               res = get_dbe(*value, (u16 *) addr);
-       else
-               res = get_dbe(*value, (u32 *) addr);
-
-       return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
-
-oh_my_gawd:
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
-        * generic PCI code a chance to look at the wrong register.
-        */
-       if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
-               *value = 0;
-               return PCIBIOS_SUCCESSFUL;
-       }
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't try to access
-        * anything but 32-bit words ...
-        */
-       addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
-
-       if (get_dbe(cf, (u32 *) addr))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       shift = ((where & 3) << 3);
-       mask = (0xffffffffU >> ((4 - size) << 3));
-       *value = (cf >> shift) & mask;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
-                                int where, int size, u32 * value)
-{
-       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
-       bridge_t *bridge = bc->base;
-       int busno = bus->number;
-       int slot = PCI_SLOT(devfn);
-       int fn = PCI_FUNC(devfn);
-       volatile void *addr;
-       u32 cf, shift, mask;
-       int res;
-
-       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
-       addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
-       if (get_dbe(cf, (u32 *) addr))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
-        * generic PCI code a chance to look at it for real ...
-        */
-       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-               goto oh_my_gawd;
-
-       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
-       addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
-
-       if (size == 1)
-               res = get_dbe(*value, (u8 *) addr);
-       else if (size == 2)
-               res = get_dbe(*value, (u16 *) addr);
-       else
-               res = get_dbe(*value, (u32 *) addr);
-
-       return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
-
-oh_my_gawd:
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
-        * generic PCI code a chance to look at the wrong register.
-        */
-       if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
-               *value = 0;
-               return PCIBIOS_SUCCESSFUL;
-       }
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't try to access
-        * anything but 32-bit words ...
-        */
-       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
-       addr = &bridge->b_type1_cfg.c[(fn << 8) | where];
-
-       if (get_dbe(cf, (u32 *) addr))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       shift = ((where & 3) << 3);
-       mask = (0xffffffffU >> ((4 - size) << 3));
-       *value = (cf >> shift) & mask;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int pci_read_config(struct pci_bus *bus, unsigned int devfn,
-                          int where, int size, u32 * value)
-{
-       if (bus->number > 0)
-               return pci_conf1_read_config(bus, devfn, where, size, value);
-
-       return pci_conf0_read_config(bus, devfn, where, size, value);
-}
-
-static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
-                                 int where, int size, u32 value)
-{
-       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
-       bridge_t *bridge = bc->base;
-       int slot = PCI_SLOT(devfn);
-       int fn = PCI_FUNC(devfn);
-       volatile void *addr;
-       u32 cf, shift, mask, smask;
-       int res;
-
-       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
-       if (get_dbe(cf, (u32 *) addr))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
-        * generic PCI code a chance to look at it for real ...
-        */
-       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-               goto oh_my_gawd;
-
-       addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
-
-       if (size == 1) {
-               res = put_dbe(value, (u8 *) addr);
-       } else if (size == 2) {
-               res = put_dbe(value, (u16 *) addr);
-       } else {
-               res = put_dbe(value, (u32 *) addr);
-       }
-
-       if (res)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       return PCIBIOS_SUCCESSFUL;
-
-oh_my_gawd:
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
-        * generic PCI code a chance to touch the wrong register.
-        */
-       if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
-               return PCIBIOS_SUCCESSFUL;
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't try to access
-        * anything but 32-bit words ...
-        */
-       addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
-
-       if (get_dbe(cf, (u32 *) addr))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       shift = ((where & 3) << 3);
-       mask = (0xffffffffU >> ((4 - size) << 3));
-       smask = mask << shift;
-
-       cf = (cf & ~smask) | ((value & mask) << shift);
-       if (put_dbe(cf, (u32 *) addr))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
-                                 int where, int size, u32 value)
-{
-       struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
-       bridge_t *bridge = bc->base;
-       int slot = PCI_SLOT(devfn);
-       int fn = PCI_FUNC(devfn);
-       int busno = bus->number;
-       volatile void *addr;
-       u32 cf, shift, mask, smask;
-       int res;
-
-       bridge->b_pci_cfg = (busno << 16) | (slot << 11);
-       addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
-       if (get_dbe(cf, (u32 *) addr))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
-        * generic PCI code a chance to look at it for real ...
-        */
-       if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-               goto oh_my_gawd;
-
-       addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
-
-       if (size == 1) {
-               res = put_dbe(value, (u8 *) addr);
-       } else if (size == 2) {
-               res = put_dbe(value, (u16 *) addr);
-       } else {
-               res = put_dbe(value, (u32 *) addr);
-       }
-
-       if (res)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       return PCIBIOS_SUCCESSFUL;
-
-oh_my_gawd:
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't even give the
-        * generic PCI code a chance to touch the wrong register.
-        */
-       if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
-               return PCIBIOS_SUCCESSFUL;
-
-       /*
-        * IOC3 is fucked fucked beyond believe ...  Don't try to access
-        * anything but 32-bit words ...
-        */
-       addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
-
-       if (get_dbe(cf, (u32 *) addr))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       shift = ((where & 3) << 3);
-       mask = (0xffffffffU >> ((4 - size) << 3));
-       smask = mask << shift;
-
-       cf = (cf & ~smask) | ((value & mask) << shift);
-       if (put_dbe(cf, (u32 *) addr))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int pci_write_config(struct pci_bus *bus, unsigned int devfn,
-       int where, int size, u32 value)
-{
-       if (bus->number > 0)
-               return pci_conf1_write_config(bus, devfn, where, size, value);
-
-       return pci_conf0_write_config(bus, devfn, where, size, value);
-}
-
-static struct pci_ops bridge_pci_ops = {
-       .read = pci_read_config,
-       .write = pci_write_config,
-};
+extern struct pci_ops bridge_pci_ops;
 
 int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid)
 {
@@ -370,8 +80,7 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid)
        bc->widget_id = widget_id;
        bc->nasid = nasid;
 
-       bc->baddr = (u64)masterwid << 60;
-       bc->baddr |= (1UL << 56);       /* Barrier set */
+       bc->baddr = (u64)masterwid << 60 | PCI64_ATTR_BAR;
 
        /*
         * point to this bridge
index f02ef6e36b02cf19e0dee3a66241835f2cf362ca..cb84f4e8ccae693c2829a4e04e1df60e79431bb5 100644 (file)
 #include <asm/debug.h>
 
 struct resource pci_io_resource = {
-       "IO MEM",
-       0x1000,                 /* reserve regacy I/O space */
-       0x1000 + JMR3927_PCIIO_SIZE - 1,
-       IORESOURCE_IO
+       .name   = "IO MEM",
+       .start  = 0x1000,                       /* reserve regacy I/O space */
+       .end    = 0x1000 + JMR3927_PCIIO_SIZE - 1,
+       .flags  = IORESOURCE_IO
 };
 
 struct resource pci_mem_resource = {
-       "PCI MEM",
-       JMR3927_PCIMEM,
-       JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1,
-       IORESOURCE_MEM
+       .name   = "PCI MEM",
+       .start  = JMR3927_PCIMEM,
+       .end    = JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1,
+       .flags  = IORESOURCE_MEM
 };
 
 extern struct pci_ops jmr3927_pci_ops;
index 3da8a4ee6baa41d5f13c9e561b6cc2b26fe28313..2b9495dce6baf5f635d5d665fa8e67d4d7a84c61 100644 (file)
@@ -71,13 +71,13 @@ static inline void pci0WriteConfigReg(unsigned int offset, unsigned int data)
 }
 
 static struct resource ocelot_mem_resource = {
-       iomem_resource.start = GT_PCI_MEM_BASE;
-       iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1;
+       start   = GT_PCI_MEM_BASE;
+       end     = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1;
 };
 
 static struct resource ocelot_io_resource = {
-       ioport_resource.start = GT_PCI_IO_BASE;
-       ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+       start   = GT_PCI_IO_BASE;
+       end     = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
 };
 
 static struct pci_controller ocelot_pci_controller = {
index dac9ed4b0ccf690df67474b92b4774a8e0c8f2e7..0357946f30e6ec5d2719446eaf68a9b86e980b98 100644 (file)
 extern struct pci_ops titan_pci_ops;
 
 static struct resource py_mem_resource = {
-       "Titan PCI MEM", 0xe0000000UL, 0xe3ffffffUL, IORESOURCE_MEM
+       .start  = 0xe0000000UL,
+       .end    = 0xe3ffffffUL,
+       .name   = "Titan PCI MEM",
+       .flags  = IORESOURCE_MEM
 };
 
 /*
@@ -26,7 +29,10 @@ static struct resource py_mem_resource = {
 #define TITAN_IO_BASE  0xe8000000UL
 
 static struct resource py_io_resource = {
-       "Titan IO MEM", 0x00001000UL, TITAN_IO_SIZE - 1, IORESOURCE_IO,
+       .start  = 0x00001000UL,
+       .end    = TITAN_IO_SIZE - 1,
+       .name   = "Titan IO MEM",
+       .flags  = IORESOURCE_IO,
 };
 
 static struct pci_controller py_controller = {
index 21402ffd7c98a907dafc91d8193d5735d325a44d..4dfce154d4af1cb33e7b35410f3a747d34c47555 100644 (file)
@@ -76,11 +76,6 @@ pcibios_align_resource(void *data, struct resource *res,
        res->start = start;
 }
 
-struct pci_controller * __init alloc_pci_controller(void)
-{
-       return alloc_bootmem(sizeof(struct pci_controller));
-}
-
 void __init register_pci_controller(struct pci_controller *hose)
 {
        *hose_tail = hose;
index baa6905f649fb5023af19aab12024a451170236a..eee4f3dfc410e248d5caf1e625b14dcbbb273ff3 100644 (file)
 #include <nand.h>
 
 static struct resource pci_io_resource = {
-       "pci IO space",
-       (u32)(PNX8550_PCIIO + 0x1000),  /* reserve regacy I/O space */
-       (u32)(PNX8550_PCIIO + PNX8550_PCIIO_SIZE),
-       IORESOURCE_IO
+       .start  = PNX8550_PCIIO + 0x1000,       /* reserve regacy I/O space */
+       .end    = PNX8550_PCIIO + PNX8550_PCIIO_SIZE,
+       .name   = "pci IO space",
+       .flags  = IORESOURCE_IO
 };
 
 static struct resource pci_mem_resource = {
-       "pci memory space",
-       (u32)(PNX8550_PCIMEM),
-       (u32)(PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1),
-       IORESOURCE_MEM
+       .start  = PNX8550_PCIMEM,
+       .end    = PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1,
+       .name   = "pci memory space",
+       .flags  = IORESOURCE_MEM
 };
 
 extern struct pci_ops pnx8550_pci_ops;
index 0d8a77619391d702a85af054bdff218553576b7e..0e791f4f6ea3bf41b384346c082737c30046ae8d 100644 (file)
@@ -58,10 +58,27 @@ extern void prom_printf(char *fmt, ...);
 extern char *prom_getcmdline(void);
 
 struct resource standard_io_resources[] = {
-       {"dma1", 0x00, 0x1f, IORESOURCE_BUSY},
-       {"timer", 0x40, 0x5f, IORESOURCE_BUSY},
-       {"dma page reg", 0x80, 0x8f, IORESOURCE_BUSY},
-       {"dma2", 0xc0, 0xdf, IORESOURCE_BUSY},
+       {
+               .start  = .0x00,
+               .end    = 0x1f,
+               .name   = "dma1",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x40,
+               .end    = 0x5f,
+               .name   = "timer",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x80,
+               .end    = 0x8f,
+               .name   = "dma page reg",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0xc0,
+               .end    = 0xdf,
+               .name   = "dma2",
+               .flags  = IORESOURCE_BUSY
+       },
 };
 
 #define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
@@ -82,7 +99,7 @@ unsigned long get_system_mem_size(void)
 
 int pnx8550_console_port = -1;
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        int i;
        char* argptr;
index 3f724d661bdbf6d0f79aa56c7bc3b2793669cf23..aa0d6ff3c6ec83641cd17d1ac3e64fc9af0f4481 100644 (file)
@@ -218,7 +218,7 @@ static void __init py_late_time_init(void)
        py_rtc_setup();
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        board_time_init = yosemite_time_init;
        late_time_init = py_late_time_init;
index 730f459f3e9920e0efeaa257ad88063eb8ed0265..078cd3029c9ff9228b561e59690b6ef631727db6 100644 (file)
@@ -2,6 +2,6 @@
 # Makefile for Qemu specific kernel interface routines under Linux.
 #
 
-obj-y          = q-firmware.o q-irq.o q-mem.o q-setup.o
+obj-y          = q-firmware.o q-irq.o q-mem.o q-setup.o q-reset.o
 
 obj-$(CONFIG_SMP) += q-smp.o
diff --git a/arch/mips/qemu/q-reset.c b/arch/mips/qemu/q-reset.c
new file mode 100644 (file)
index 0000000..c04ebcf
--- /dev/null
@@ -0,0 +1,34 @@
+#include <linux/config.h>
+
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/cacheflush.h>
+#include <asm/qemu.h>
+
+static void qemu_machine_restart(char *command)
+{
+       volatile unsigned int *reg = (unsigned int *)QEMU_RESTART_REG;
+
+       set_c0_status(ST0_BEV | ST0_ERL);
+       change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+       flush_cache_all();
+       write_c0_wired(0);
+       *reg = 42;
+       while (1)
+               cpu_wait();
+}
+
+static void qemu_machine_halt(void)
+{
+       volatile unsigned int *reg = (unsigned int *)QEMU_HALT_REG;
+
+       *reg = 42;
+       while (1)
+               cpu_wait();
+}
+
+void qemu_reboot_setup(void)
+{
+       _machine_restart = qemu_machine_restart;
+       _machine_halt = qemu_machine_halt;
+}
index 022eb1af6db12f5f8942b34061c4907096b29e9a..e100d6072e3100210653088bfe44d51cc25c7a74 100644 (file)
@@ -2,6 +2,8 @@
 #include <asm/io.h>
 #include <asm/time.h>
 
+extern void qemu_reboot_setup(void);
+
 #define QEMU_PORT_BASE 0xb4000000
 
 const char *get_system_type(void)
@@ -18,8 +20,10 @@ static void __init qemu_timer_setup(struct irqaction *irq)
        setup_irq(0, irq);
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        set_io_port_base(QEMU_PORT_BASE);
        board_timer_setup = qemu_timer_setup;
+
+       qemu_reboot_setup();
 }
index 7018e1833e85dd7ab577c9f43b1bcaa48c7f42c5..d7138906eb10e13fca53702ddf1464db66a1f57b 100644 (file)
@@ -53,7 +53,7 @@ EXPORT_SYMBOL(ip22_do_break);
 extern void ip22_be_init(void) __init;
 extern void ip22_time_init(void) __init;
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        char *ctype;
        char *cserial;
index 7b0bc44372433d3b0f6becd1af2836bd7a1d8ed1..f14ef38646d02258cf7997844bb76c60f7c12414 100644 (file)
@@ -4,31 +4,29 @@
 #        This options adds support for userspace processes upto 16TB size.
 #        Normally the limit is just .5TB.
 
-config SGI_SN0_N_MODE
-       bool "IP27 N-Mode"
+choice
+       prompt "Node addressing mode"
        depends on SGI_IP27
-       help
-         The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be
-         configured in either N-Modes which allows for more nodes or M-Mode
-         which allows for more memory.  Your system is most probably
-         running in M-Mode, so you should say N here.
+       default SGI_SN_M_MODE
 
-config ARCH_DISCONTIGMEM_ENABLE
-       bool
-       default y if SGI_IP27
+config SGI_SN_M_MODE
+       bool "IP27 M-Mode"
        help
-         Say Y to upport efficient handling of discontiguous physical memory,
-         for architectures which are either NUMA (Non-Uniform Memory Access)
-         or have huge holes in the physical address space for other reasons.
-         See <file:Documentation/vm/numa> for more.
+         The nodes of Origin, Onyx, Fuel and Tezro systems can be configured
+         in either N-Modes which allows for more nodes or M-Mode which allows
+         for more memory.  Your hardware is almost certainly running in
+         M-Mode, so choose M-mode here.
 
-config NUMA
-       bool "NUMA Support"
-       depends on SGI_IP27
+config SGI_SN_N_MODE
+       bool "IP27 N-Mode"
+       depends on EXPERIMENTAL
        help
-         Say Y to compile the kernel to support NUMA (Non-Uniform Memory
-         Access).  This option is for configuring high-end multiprocessor
-         server machines.  If in doubt, say N.
+         The nodes of Origin, Onyx, Fuel and Tezro systems can be configured
+         in either N-Modes which allows for more nodes or M-Mode which allows
+         for more memory.  Your hardware is almost certainly running in
+         M-Mode, so choose M-mode here.
+
+endchoice
 
 config MAPPED_KERNEL
        bool "Mapped kernel support"
index 8651a0e75404aa28e8232fd233f8b998245b0ba8..a6b490e99709f49c064224d31fd7816a48cb474e 100644 (file)
@@ -196,7 +196,7 @@ extern void ip27_setup_console(void);
 extern void ip27_time_init(void);
 extern void ip27_reboot_setup(void);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        hubreg_t p, e, n_mode;
        nasid_t nid;
@@ -228,7 +228,7 @@ void __init plat_setup(void)
         */
        n_mode = LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_MORENODES_MASK;
        printk("Machine is in %c mode.\n", n_mode ? 'N' : 'M');
-#ifdef CONFIG_SGI_SN0_N_MODE
+#ifdef CONFIG_SGI_SN_N_MODE
        if (!n_mode)
                panic("Kernel compiled for M mode.");
 #else
index 2e643d2f51cbb7b909e859c5f4aae0cfbae1dde7..0b61a39ce2bb1f116f991b94d481aa6cd2825096 100644 (file)
@@ -360,7 +360,7 @@ static struct hw_interrupt_type bridge_irq_type = {
 
 static unsigned long irq_map[NR_IRQS / BITS_PER_LONG];
 
-static int allocate_irqno(void)
+int allocate_irqno(void)
 {
        int irq;
 
index 36b662e27b6ec45117e20337086064ad7798393c..1fb860c7ac6dd60f96204ae67142a1231d99c4f5 100644 (file)
@@ -89,11 +89,13 @@ static int set_rtc_mmss(unsigned long nowtime)
 }
 #endif
 
+static unsigned int rt_timer_irq;
+
 void ip27_rt_timer_interrupt(struct pt_regs *regs)
 {
        int cpu = smp_processor_id();
        int cpuA = cputoslice(cpu) == 0;
-       int irq = 9;                            /* XXX Assign number */
+       unsigned int irq = rt_timer_irq;
 
        irq_enter();
        write_seqlock(&xtime_lock);
@@ -179,13 +181,68 @@ static __init unsigned long get_m48t35_time(void)
         return mktime(year, month, date, hour, min, sec);
 }
 
+static void startup_rt_irq(unsigned int irq)
+{
+}
+
+static void shutdown_rt_irq(unsigned int irq)
+{
+}
+
+static void enable_rt_irq(unsigned int irq)
+{
+}
+
+static void disable_rt_irq(unsigned int irq)
+{
+}
+
+static void mask_and_ack_rt(unsigned int irq)
+{
+}
+
+static void end_rt_irq(unsigned int irq)
+{
+}
+
+static struct hw_interrupt_type rt_irq_type = {
+       .typename       = "SN HUB RT timer",
+       .startup        = startup_rt_irq,
+       .shutdown       = shutdown_rt_irq,
+       .enable         = enable_rt_irq,
+       .disable        = disable_rt_irq,
+       .ack            = mask_and_ack_rt,
+       .end            = end_rt_irq,
+};
+
+static struct irqaction rt_irqaction = {
+       .handler        = ip27_rt_timer_interrupt,
+       .flags          = SA_INTERRUPT,
+       .mask           = CPU_MASK_NONE,
+       .name           = "timer"
+};
+
+extern int allocate_irqno(void);
+
 static void ip27_timer_setup(struct irqaction *irq)
 {
+       int irqno  = allocate_irqno();
+
+       if (irqno < 0)
+               panic("Can't allocate interrupt number for timer interrupt");
+
+       irq_desc[irqno].status = IRQ_DISABLED;
+       irq_desc[irqno].action = NULL;
+       irq_desc[irqno].depth = 1;
+       irq_desc[irqno].handler = &rt_irq_type;
+
        /* over-write the handler, we use our own way */
        irq->handler = no_action;
 
        /* setup irqaction */
-//     setup_irq(IP27_TIMER_IRQ, irq);         /* XXX Can't do this yet.  */
+       irq_desc[irqno].status |= IRQ_PER_CPU;
+
+       rt_timer_irq = irqno;
 }
 
 void __init ip27_time_init(void)
index de01c9815bddf719f6b40dd85bf0d67dee95913b..8ba08047d164222b31bf6315b66fb51603d3a93a 100644 (file)
 /* issue a PIO read to make sure no PIO writes are pending */
 static void inline flush_crime_bus(void)
 {
-       volatile unsigned long junk = crime->control;
+       crime->control;
 }
 
 static void inline flush_mace_bus(void)
 {
-       volatile unsigned long junk = mace->perif.ctrl.misc;
+       mace->perif.ctrl.misc;
 }
 
 #undef DEBUG_IRQ
index a2dd8ae1ea8f10f2f7bf5d7c77055b277b3120bd..acbdad06fac18f157c6c2fbc7b929d809bf071ad 100644 (file)
@@ -87,7 +87,7 @@ void __init ip32_timer_setup(struct irqaction *irq)
        setup_irq(IP32_R4K_TIMER_IRQ, irq);
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        board_be_init = ip32_be_init;
 
index e545752695a1ea4566808a7390ad565b765b729e..efaf83efd2e4b271a8e09c71e2f6704c0d4b2258 100644 (file)
@@ -110,17 +110,18 @@ void bcm1480_timer_interrupt(struct pt_regs *regs)
        __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
              IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 
-       /*
-        * CPU 0 handles the global timer interrupt job
-        */
        if (cpu == 0) {
+               /*
+                * CPU 0 handles the global timer interrupt job
+                */
                ll_timer_interrupt(irq, regs);
        }
-
-       /*
-        * every CPU should do profiling and process accouting
-        */
-       ll_local_timer_interrupt(irq, regs);
+       else {
+               /*
+                * other CPUs should just do profiling and process accounting
+                */
+               ll_local_timer_interrupt(irq, regs);
+       }
 }
 
 /*
index 0f6e54db4888869c35d639fdc9963a602e62ad8c..f853c32f60a0f7e1b847f289a469b8e2b0932ada 100644 (file)
@@ -435,13 +435,17 @@ static inline int dclz(unsigned long long x)
        return lz;
 }
 
+extern void sb1250_timer_interrupt(struct pt_regs *regs);
+extern void sb1250_mailbox_interrupt(struct pt_regs *regs);
+extern void sb1250_kgdb_interrupt(struct pt_regs *regs);
+
 asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
        unsigned int pending;
 
 #ifdef CONFIG_SIBYTE_SB1250_PROF
        /* Set compare to count to silence count/compare timer interrupts */
-       write_c0_count(read_c0_count());
+       write_c0_compare(read_c0_count());
 #endif
 
        /*
@@ -482,7 +486,7 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
                 * Default...we've hit an IP[2] interrupt, which means we've
                 * got to check the 1250 interrupt registers to figure out what
                 * to do.  Need to detect which CPU we're on, now that
-                ~ smp_affinity is supported.
+                * smp_affinity is supported.
                 */
                mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
                                              R_IMR_INTERRUPT_STATUS_BASE)));
index 4b5f74ff3edd3fd14aa861f0f507e911fc08d1b7..f9e694988cdf18733682531f0f304321a6cf3635 100644 (file)
@@ -72,8 +72,10 @@ const char *get_system_type(void)
 
 void __init swarm_time_init(void)
 {
+#if defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
        /* Setup HPT */
        sb1250_hpt_setup();
+#endif
 }
 
 void __init swarm_timer_setup(struct irqaction *irq)
@@ -103,7 +105,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup)
        return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL);
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
        bcm1480_setup();
index 9c7eaa5fb2106ad5d63ce41bfb8fa63861f440b0..a5eb0adb87c7aa190c1930380f07fe0b9a7b76e6 100644 (file)
@@ -3,5 +3,6 @@
 #
 
 obj-y          += irq.o pcimt_scache.o reset.o setup.o
+obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o
 
 EXTRA_AFLAGS := $(CFLAGS)
index 01ba6c581e3d0ae7d5fae29041cb1c8bd70a794e..a050bb6ae7044939c7b129305f5ba8eb5a1dab07 100644 (file)
 #include <linux/fb.h>
 #include <linux/tty.h>
 
+#ifdef CONFIG_ARC
 #include <asm/arc/types.h>
 #include <asm/sgialib.h>
+#endif
+
 #include <asm/bcache.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
@@ -72,8 +75,7 @@ static inline void sni_pcimt_detect(void)
 
 static void __init sni_display_setup(void)
 {
-#ifdef CONFIG_VT
-#if defined(CONFIG_VGA_CONSOLE)
+#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_ARC)
        struct screen_info *si = &screen_info;
        DISPLAY_STATUS *di;
 
@@ -88,24 +90,54 @@ static void __init sni_display_setup(void)
                si->orig_video_points   = 16;
        }
 #endif
-#endif
 }
 
 static struct resource sni_io_resource = {
-       "PCIMT IO MEM", 0x00001000UL, 0x03bfffffUL, IORESOURCE_IO,
+       .start  = 0x00001000UL,
+       .end    = 0x03bfffffUL,
+       .name   = "PCIMT IO MEM",
+       .flags  = IORESOURCE_IO,
 };
 
 static struct resource pcimt_io_resources[] = {
-       { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
-       { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
-       { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
-       { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
-       { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
-       { "PCI config data", 0xcfc, 0xcff, IORESOURCE_BUSY }
+       {
+               .start  = 0x00,
+               .end    = 0x1f,
+               .name   = "dma1",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  =  0x40,
+               .end    = 0x5f,
+               .name   = "timer",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  =  0x60,
+               .end    = 0x6f,
+               .name   = "keyboard",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  =  0x80,
+               .end    = 0x8f,
+               .name   = "dma page reg",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  =  0xc0,
+               .end    = 0xdf,
+               .name   = "dma2",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  =  0xcfc,
+               .end    = 0xcff,
+               .name   = "PCI config data",
+               .flags  = IORESOURCE_BUSY
+       }
 };
 
 static struct resource sni_mem_resource = {
-       "PCIMT PCI MEM", 0x10000000UL, 0xffffffffUL, IORESOURCE_MEM
+       .start  = 0x10000000UL,
+       .end    = 0xffffffffUL,
+       .name   = "PCIMT PCI MEM",
+       .flags  = IORESOURCE_MEM
 };
 
 /*
@@ -122,19 +154,72 @@ static struct resource sni_mem_resource = {
  * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory
  */
 static struct resource pcimt_mem_resources[] = {
-       { "Video RAM area", 0x100a0000, 0x100bffff, IORESOURCE_BUSY },
-       { "ISA Reserved", 0x100c0000, 0x100fffff, IORESOURCE_BUSY },
-       { "PCI IO", 0x14000000, 0x17bfffff, IORESOURCE_BUSY },
-       { "Cache Replacement Area", 0x17c00000, 0x17ffffff, IORESOURCE_BUSY},
-       { "PCI INT Acknowledge", 0x1a000000, 0x1a000003, IORESOURCE_BUSY },
-       { "Boot PROM", 0x1fc00000, 0x1fc7ffff, IORESOURCE_BUSY},
-       { "Diag PROM", 0x1fc80000, 0x1fcfffff, IORESOURCE_BUSY},
-       { "X-Bus", 0x1fd00000, 0x1fdfffff, IORESOURCE_BUSY},
-       { "BIOS map", 0x1fe00000, 0x1fefffff, IORESOURCE_BUSY},
-       { "NVRAM / EEPROM", 0x1ff00000, 0x1ff7ffff, IORESOURCE_BUSY},
-       { "ASIC PCI", 0x1fff0000, 0x1fffefff, IORESOURCE_BUSY},
-       { "MP Agent", 0x1ffff000, 0x1fffffff, IORESOURCE_BUSY},
-       { "Main Memory", 0x20000000, 0x9fffffff, IORESOURCE_BUSY}
+       {
+               .start  = 0x100a0000,
+               .end    = 0x100bffff,
+               .name   = "Video RAM area",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x100c0000,
+               .end    = 0x100fffff,
+               .name   = "ISA Reserved",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x14000000,
+               .end    = 0x17bfffff,
+               .name   = "PCI IO",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x17c00000,
+               .end    = 0x17ffffff,
+               .name   = "Cache Replacement Area",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x1a000000,
+               .end    = 0x1a000003,
+               .name   = "PCI INT Acknowledge",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x1fc00000,
+               .end    = 0x1fc7ffff,
+               .name   = "Boot PROM",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x1fc80000,
+               .end    = 0x1fcfffff,
+               .name   = "Diag PROM",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x1fd00000,
+               .end    = 0x1fdfffff,
+               .name   = "X-Bus",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x1fe00000,
+               .end    = 0x1fefffff,
+               .name   = "BIOS map",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x1ff00000,
+               .end    = 0x1ff7ffff,
+               .name   = "NVRAM / EEPROM",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x1fff0000,
+               .end    = 0x1fffefff,
+               .name   = "ASIC PCI",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x1ffff000,
+               .end    = 0x1fffffff,
+               .name   = "MP Agent",
+               .flags  = IORESOURCE_BUSY
+       }, {
+               .start  = 0x20000000,
+               .end    = 0x9fffffff,
+               .name   = "Main Memory",
+               .flags  = IORESOURCE_BUSY
+       }
 };
 
 static void __init sni_resource_init(void)
@@ -168,7 +253,7 @@ static inline void sni_pcimt_time_init(void)
        rtc_mips_set_time = mc146818_set_rtc_mmss;
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        sni_pcimt_detect();
        sni_pcimt_sc_init();
diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c
new file mode 100644 (file)
index 0000000..d1d0f1f
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Big Endian PROM code for SNI RM machines
+ *
+ * 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-2006 Florian Lohoff (flo@rfc822.org)
+ * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/addrspace.h>
+#include <asm/sni.h>
+#include <asm/mipsprom.h>
+#include <asm/bootinfo.h>
+
+/* special SNI prom calls */
+/*
+ * This does not exist in all proms - SINIX compares
+ * the prom env variable "version" against "2.0008"
+ * or greater. If lesser it tries to probe interesting
+ * registers
+ */
+#define PROM_GET_MEMCONF       58
+
+#define PROM_VEC               (u64 *)CKSEG1ADDR(0x1fc00000)
+#define PROM_ENTRY(x)          (PROM_VEC + (x))
+
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG_PRINTF(x...)     prom_printf(x)
+#else
+#define DBG_PRINTF(x...)
+#endif
+
+static int *(*__prom_putchar)(int)        = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR);
+static char *(*__prom_getenv)(char *)     = (char *(*)(char *))PROM_ENTRY(PROM_GETENV);
+static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF);
+
+char *prom_getenv (char *s)
+{
+       return __prom_getenv(s);
+}
+
+void prom_printf(char *fmt, ...)
+{
+       va_list args;
+       char ppbuf[1024];
+       char *bptr;
+
+       va_start(args, fmt);
+       vsprintf(ppbuf, fmt, args);
+
+       bptr = ppbuf;
+
+       while (*bptr != 0) {
+               if (*bptr == '\n')
+                       __prom_putchar('\r');
+
+               __prom_putchar(*bptr++);
+       }
+       va_end(args);
+}
+
+unsigned long prom_free_prom_memory(void)
+{
+       return 0;
+}
+
+/*
+ * /proc/cpuinfo system type
+ *
+ */
+static const char *systype = "Unknown";
+const char *get_system_type(void)
+{
+       return systype;
+}
+
+#define SNI_IDPROM_BASE                0xbff00000
+#define SNI_IDPROM_MEMSIZE             (SNI_IDPROM_BASE+0x28)  /* Memsize in 16MB quantities */
+#define SNI_IDPROM_BRDTYPE             (SNI_IDPROM_BASE+0x29)  /* Board Type */
+#define SNI_IDPROM_CPUTYPE             (SNI_IDPROM_BASE+0x30)  /* CPU Type */
+
+#define SNI_IDPROM_SIZE        0x1000
+
+#ifdef DEBUG
+static void sni_idprom_dump(void)
+{
+       int     i;
+
+       prom_printf("SNI IDProm dump (first 128byte):\n");
+       for(i=0;i<128;i++) {
+               if (i%16 == 0)
+                       prom_printf("%04x ", i);
+
+               prom_printf("%02x ", *(unsigned char *) (SNI_IDPROM_BASE+i));
+
+               if (i%16 == 15)
+                       prom_printf("\n");
+       }
+}
+#endif
+
+static void sni_mem_init(void )
+{
+       int i, memsize;
+       struct membank {
+               u32             size;
+               u32             base;
+               u32             size2;
+               u32             pad1;
+               u32             pad2;
+       } memconf[8];
+
+       /* MemSIZE from prom in 16MByte chunks */
+       memsize=*((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
+
+       DBG_PRINTF("IDProm memsize: %lu MByte\n", memsize);
+
+       /* get memory bank layout from prom */
+       __prom_get_memconf(&memconf);
+
+       DBG_PRINTF("prom_get_mem_conf memory configuration:\n");
+       for(i=0;i<8 && memconf[i].size;i++) {
+               prom_printf("Bank%d: %08x @ %08x\n", i,
+                       memconf[i].size, memconf[i].base);
+               add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM);
+       }
+}
+
+void __init prom_init(void)
+{
+       int argc = fw_arg0;
+       char **argv = (void *)fw_arg1;
+       unsigned int sni_brd_type = *(unsigned char *) SNI_IDPROM_BRDTYPE;
+       int i;
+
+       DBG_PRINTF("Found SNI brdtype %02x\n", sni_brd_type);
+
+#ifdef DEBUG
+       sni_idprom_dump();
+#endif
+       sni_mem_init();
+
+       /* copy prom cmdline parameters to kernel cmdline */
+       for (i = 1; i < argc; i++) {
+               strcat(arcs_cmdline, argv[i]);
+               if (i < (argc - 1))
+                       strcat(arcs_cmdline, " ");
+       }
+}
+
index 77c3b66fb9598be5e029daf019fc873f5be5703a..81a5acfe8c4279c8845c072b1ea724c7c8023385 100644 (file)
@@ -64,7 +64,7 @@ static void tx4927_write_buffer_flush(void)
 }
 
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        board_time_init = tx4927_time_init;
        board_timer_setup = tx4927_timer_setup;
index fc992953bf954de63295731b035c99e50031d34a..ef59a5cffc691e9001c1a9dafb7676189ecca214 100644 (file)
@@ -61,7 +61,7 @@ tx4938_write_buffer_flush(void)
 }
 
 void __init
-plat_setup(void)
+plat_mem_setup(void)
 {
        board_time_init = tx4938_time_init;
        board_timer_setup = tx4938_timer_setup;
index 9166cd4557eb01f1b5e7db4777d882ac4a97416c..96e833cd4c14260e6ea40a77ebef990ceae6433d 100644 (file)
@@ -664,7 +664,10 @@ static struct resource rbtx4938_fpga_resource;
 
 static char pcode_str[8];
 static struct resource tx4938_reg_resource = {
-       pcode_str, TX4938_REG_BASE, TX4938_REG_BASE+TX4938_REG_SIZE, IORESOURCE_MEM
+       .start  = TX4938_REG_BASE,
+       .end    = TX4938_REG_BASE + TX4938_REG_SIZE,
+       .name   = pcode_str,
+       .flags  = IORESOURCE_MEM
 };
 
 void __init tx4938_board_setup(void)
index 055a2cdfc841f080b5cadb277a46e5155d05a89d..6046ef23b2bf408ea8762fe48eefa4eb4db281f8 100644 (file)
@@ -4,7 +4,6 @@ config CASIO_E55
        select DMA_NONCOHERENT
        select IRQ_CPU
        select ISA
-       select SYS_HAS_CPU_VR41XX
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
@@ -14,18 +13,15 @@ config IBM_WORKPAD
        select DMA_NONCOHERENT
        select IRQ_CPU
        select ISA
-       select SYS_HAS_CPU_VR41XX
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config NEC_CMBVR4133
        bool "Support for NEC CMB-VR4133"
        depends on MACH_VR41XX
-       select CPU_VR41XX
        select DMA_NONCOHERENT
        select IRQ_CPU
        select HW_HAS_PCI
-       select SYS_HAS_CPU_VR41XX
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
@@ -41,7 +37,6 @@ config TANBAC_TB022X
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select IRQ_CPU
-       select SYS_HAS_CPU_VR41XX
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
        help
@@ -74,7 +69,6 @@ config VICTOR_MPC30X
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select IRQ_CPU
-       select SYS_HAS_CPU_VR41XX
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
@@ -84,7 +78,6 @@ config ZAO_CAPCELLA
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select IRQ_CPU
-       select SYS_HAS_CPU_VR41XX
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
index 707bd0933eedc2da82dd174bb408818da586aafc..915bfa5c07193cc5752e2540bb70b6c829848300 100644 (file)
@@ -58,7 +58,7 @@ static void __init timer_init(void)
        board_timer_setup = setup_timer_irq;
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
        vr41xx_calculate_clock_frequency();
 
index 2d80653aa2af54e866eee220d8193dde6d663c49..f70bd090dacda51fb52b716fb7c8e92e8c27fc1a 100644 (file)
@@ -822,6 +822,7 @@ static void __init prom_send_capabilities(void)
                /* try calling the ibm,client-architecture-support method */
                if (call_prom_ret("call-method", 3, 2, &ret,
                                  ADDR("ibm,client-architecture-support"),
+                                 root,
                                  ADDR(ibm_architecture_vec)) == 0) {
                        /* the call exists... */
                        if (ret)
@@ -1622,6 +1623,15 @@ static int __init prom_find_machine_type(void)
                        if (strstr(p, RELOC("Power Macintosh")) ||
                            strstr(p, RELOC("MacRISC")))
                                return PLATFORM_POWERMAC;
+#ifdef CONFIG_PPC64
+                       /* We must make sure we don't detect the IBM Cell
+                        * blades as pSeries due to some firmware issues,
+                        * so we do it here.
+                        */
+                       if (strstr(p, RELOC("IBM,CBEA")) ||
+                           strstr(p, RELOC("IBM,CPBW-1.0")))
+                               return PLATFORM_GENERIC;
+#endif /* CONFIG_PPC64 */
                        i += sl + 1;
                }
        }
@@ -2057,10 +2067,45 @@ static void __init flatten_device_tree(void)
 
 }
 
-
-static void __init fixup_device_tree(void)
+#ifdef CONFIG_PPC_MAPLE
+/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
+ * The values are bad, and it doesn't even have the right number of cells. */
+static void __init fixup_device_tree_maple(void)
 {
+       phandle isa;
+       u32 isa_ranges[6];
+
+       isa = call_prom("finddevice", 1, 1, ADDR("/ht@0/isa@4"));
+       if (!PHANDLE_VALID(isa))
+               return;
+
+       if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
+               == PROM_ERROR)
+               return;
+
+       if (isa_ranges[0] != 0x1 ||
+               isa_ranges[1] != 0xf4000000 ||
+               isa_ranges[2] != 0x00010000)
+               return;
+
+       prom_printf("fixing up bogus ISA range on Maple...\n");
+
+       isa_ranges[0] = 0x1;
+       isa_ranges[1] = 0x0;
+       isa_ranges[2] = 0x01002000; /* IO space; PCI device = 4 */
+       isa_ranges[3] = 0x0;
+       isa_ranges[4] = 0x0;
+       isa_ranges[5] = 0x00010000;
+       prom_setprop(isa, "/ht@0/isa@4", "ranges",
+                       isa_ranges, sizeof(isa_ranges));
+}
+#else
+#define fixup_device_tree_maple()
+#endif
+
 #if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
+static void __init fixup_device_tree_pmac(void)
+{
        phandle u3, i2c, mpic;
        u32 u3_rev;
        u32 interrupts[2];
@@ -2097,9 +2142,16 @@ static void __init fixup_device_tree(void)
        parent = (u32)mpic;
        prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
                     &parent, sizeof(parent));
-#endif
 }
+#else
+#define fixup_device_tree_pmac()
+#endif
 
+static void __init fixup_device_tree(void)
+{
+       fixup_device_tree_maple();
+       fixup_device_tree_pmac();
+}
 
 static void __init prom_find_boot_cpu(void)
 {
index 01e3c08cb5503617318d05c38ee3f02862e83125..8fdeca2d4597c35295271ff9ea844a91ea856a4d 100644 (file)
@@ -803,10 +803,13 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int
                if (__get_user(cmcp, &ucp->uc_regs))
                        return -EFAULT;
                mcp = (struct mcontext __user *)(u64)cmcp;
+               /* no need to check access_ok(mcp), since mcp < 4GB */
        }
 #else
        if (__get_user(mcp, &ucp->uc_regs))
                return -EFAULT;
+       if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp)))
+               return -EFAULT;
 #endif
        restore_sigmask(&set);
        if (restore_user_regs(regs, mcp, sig))
@@ -908,13 +911,14 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
 {
        struct sig_dbg_op op;
        int i;
+       unsigned char tmp;
        unsigned long new_msr = regs->msr;
 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
        unsigned long new_dbcr0 = current->thread.dbcr0;
 #endif
 
        for (i=0; i<ndbg; i++) {
-               if (__copy_from_user(&op, dbg, sizeof(op)))
+               if (copy_from_user(&op, dbg + i, sizeof(op)))
                        return -EFAULT;
                switch (op.dbg_type) {
                case SIG_DBG_SINGLE_STEPPING:
@@ -959,6 +963,11 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
        current->thread.dbcr0 = new_dbcr0;
 #endif
 
+       if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx))
+           || __get_user(tmp, (u8 __user *) ctx)
+           || __get_user(tmp, (u8 __user *) (ctx + 1) - 1))
+               return -EFAULT;
+
        /*
         * If we get a fault copying the context into the kernel's
         * image of the user's registers, we can't just return -EFAULT
index 27f65b95184d39eadfae53a877afd3e1ba6caafe..c2db642f4cdd44c32695432b9622406204fdd866 100644 (file)
@@ -182,6 +182,8 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
        err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
        if (err)
                return err;
+       if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
+               return -EFAULT;
        /* Copy 33 vec registers (vr0..31 and vscr) from the stack */
        if (v_regs != 0 && (msr & MSR_VEC) != 0)
                err |= __copy_from_user(current->thread.vr, v_regs,
index 33654d1b1b43b596ac70e98cf834a1185157f355..994856e55b7c49f79f008936c249b2ac897ce9f5 100644 (file)
@@ -52,7 +52,7 @@ static inline void __tlbie(unsigned long va, unsigned int psize)
        default:
                penc = mmu_psize_defs[psize].penc;
                va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
-               va |= (0x7f >> (8 - penc)) << 12;
+               va |= penc << 12;
                asm volatile("tlbie %0,1" : : "r" (va) : "memory");
                break;
        }
@@ -74,7 +74,7 @@ static inline void __tlbiel(unsigned long va, unsigned int psize)
        default:
                penc = mmu_psize_defs[psize].penc;
                va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
-               va |= (0x7f >> (8 - penc)) << 12;
+               va |= penc << 12;
                asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)"
                             : : "r"(va) : "memory");
                break;
index 6574b22b3cf3d4eb5feb828583ec721aa4685b6f..fd3e5609e3e004492fdbded682e899f4da21eec8 100644 (file)
@@ -125,14 +125,13 @@ static void __init cell_init_early(void)
 
 static int __init cell_probe(void)
 {
-       /* XXX This is temporary, the Cell maintainer will come up with
-        * more appropriate detection logic
-        */
        unsigned long root = of_get_flat_dt_root();
-       if (!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
-               return 0;
 
-       return 1;
+       if (of_flat_dt_is_compatible(root, "IBM,CBEA") ||
+           of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
+               return 1;
+
+       return 0;
 }
 
 /*
index df2343e1956bc266cc634ac88a217dd51f86d9ce..c896ce83d412917da2820292c32c9b6e4c32dcd1 100644 (file)
@@ -1157,6 +1157,7 @@ EXPORT_SYMBOL_GPL(pmac_i2c_xfer);
 /* some quirks for platform function decoding */
 enum {
        pmac_i2c_quirk_invmask = 0x00000001u,
+       pmac_i2c_quirk_skip = 0x00000002u,
 };
 
 static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
@@ -1172,6 +1173,15 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
                /* XXX Study device-tree's & apple drivers are get the quirks
                 * right !
                 */
+               /* Workaround: It seems that running the clockspreading
+                * properties on the eMac will cause lockups during boot.
+                * The machine seems to work fine without that. So for now,
+                * let's make sure i2c-hwclock doesn't match about "imic"
+                * clocks and we'll figure out if we really need to do
+                * something special about those later.
+                */
+               { "i2c-hwclock", "imic5002", pmac_i2c_quirk_skip },
+               { "i2c-hwclock", "imic5003", pmac_i2c_quirk_skip },
                { "i2c-hwclock", NULL, pmac_i2c_quirk_invmask },
                { "i2c-cpu-voltage", NULL, 0},
                {  "temp-monitor", NULL, 0 },
@@ -1198,6 +1208,8 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
                                if (p->compatible &&
                                    !device_is_compatible(np, p->compatible))
                                        continue;
+                               if (p->quirks & pmac_i2c_quirk_skip)
+                                       break;
                                callback(np, p->quirks);
                                break;
                        }
index 4baa75b1d36ff60a7cb9088a7e6ffa5d10301e0f..f08173b0f06593dd9da152025e728386934a5a30 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 
 #include <asm/semaphore.h>
 #include <asm/prom.h>
@@ -546,6 +547,7 @@ struct pmf_device {
 
 static LIST_HEAD(pmf_devices);
 static spinlock_t pmf_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_MUTEX(pmf_irq_mutex);
 
 static void pmf_release_device(struct kref *kref)
 {
@@ -864,15 +866,17 @@ int pmf_register_irq_client(struct device_node *target,
 
        spin_lock_irqsave(&pmf_lock, flags);
        func = __pmf_find_function(target, name, PMF_FLAGS_INT_GEN);
-       if (func == NULL) {
-               spin_unlock_irqrestore(&pmf_lock, flags);
+       if (func)
+               func = pmf_get_function(func);
+       spin_unlock_irqrestore(&pmf_lock, flags);
+       if (func == NULL)
                return -ENODEV;
-       }
+       mutex_lock(&pmf_irq_mutex);
        if (list_empty(&func->irq_clients))
                func->dev->handlers->irq_enable(func);
        list_add(&client->link, &func->irq_clients);
        client->func = func;
-       spin_unlock_irqrestore(&pmf_lock, flags);
+       mutex_unlock(&pmf_irq_mutex);
 
        return 0;
 }
@@ -881,16 +885,16 @@ EXPORT_SYMBOL_GPL(pmf_register_irq_client);
 void pmf_unregister_irq_client(struct pmf_irq_client *client)
 {
        struct pmf_function *func = client->func;
-       unsigned long flags;
 
        BUG_ON(func == NULL);
 
-       spin_lock_irqsave(&pmf_lock, flags);
+       mutex_lock(&pmf_irq_mutex);
        client->func = NULL;
        list_del(&client->link);
        if (list_empty(&func->irq_clients))
                func->dev->handlers->irq_disable(func);
-       spin_unlock_irqrestore(&pmf_lock, flags);
+       mutex_unlock(&pmf_irq_mutex);
+       pmf_put_function(func);
 }
 EXPORT_SYMBOL_GPL(pmf_unregister_irq_client);
 
index 4d15e396655c1a095ab8c4a5df6600e054ab4c99..b9200fb078157f3498e16f4be98e92a5b8d8194d 100644 (file)
@@ -463,11 +463,23 @@ static int pmac_pm_finish(suspend_state_t state)
        return 0;
 }
 
+static int pmac_pm_valid(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_DISK:
+               return 1;
+       /* can't do any other states via generic mechanism yet */
+       default:
+               return 0;
+       }
+}
+
 static struct pm_ops pmac_pm_ops = {
        .pm_disk_mode   = PM_DISK_SHUTDOWN,
        .prepare        = pmac_pm_prepare,
        .enter          = pmac_pm_enter,
        .finish         = pmac_pm_finish,
+       .valid          = pmac_pm_valid,
 };
 
 #endif /* CONFIG_SOFTWARE_SUSPEND */
index 5f79f01c44f2aff1d88c8edf2375d783195584d1..3ba87835757e2cfd5319d54e6992dd2d313488e7 100644 (file)
@@ -389,6 +389,7 @@ static int __init pSeries_probe_hypertas(unsigned long node,
 
 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);
        if (dtype == NULL)
@@ -396,6 +397,13 @@ static int __init pSeries_probe(void)
        if (strcmp(dtype, "chrp"))
                return 0;
 
+       /* Cell blades firmware claims to be chrp while it's not. Until this
+        * is fixed, we need to avoid those here.
+        */
+       if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0") ||
+           of_flat_dt_is_compatible(root, "IBM,CBEA"))
+               return 0;
+
        DBG("pSeries detected, looking for LPAR capability...\n");
 
        /* Now try to figure out if we are running on LPAR */
index cc7c4aea939751a42985f5bc944614290993ffad..2f5c5e1576175ffb5bc4e3a7e9868dda7bc1caf7 100644 (file)
@@ -134,7 +134,7 @@ main(void)
        DEFINE(TI_TASK, offsetof(struct thread_info, task));
        DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
        DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
-       DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, flags));
+       DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
        DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
        DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
 
index e62b75707f7a3f0551575f936d6258b6c97eb0d8..abb7154de2c7fcba30125b5b1971da761a2a59df 100644 (file)
@@ -279,11 +279,11 @@ static int mpc8272ads_platform_notify(struct device *dev)
        static const struct platform_notify_dev_map dev_map[] = {
                {
                        .bus_id = "fsl-cpm-fcc",
-                       .rtn = mpc8272ads_fixup_enet_pdata
+                       .rtn = mpc8272ads_fixup_enet_pdata,
                },
                {
                        .bus_id = "fsl-cpm-scc:uart",
-                       .rtn = mpc
+                       .rtn = mpc8272ads_fixup_uart_pdata,
                },
                {
                        .bus_id = NULL
@@ -335,15 +335,15 @@ struct platform_device* early_uart_get_pdev(int index)
        struct platform_device* pdev = NULL;
        if(index) { /*assume SCC4 here*/
                pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC4];
-               pinfo = &mpc8272<F12>_uart_pdata[1];
+               pinfo = &mpc8272_uart_pdata[fsid_scc4_uart];
        } else { /*over SCC1*/
                pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC1];
-               pinfo = &mpc8272_uart_pdata[0];
+               pinfo = &mpc8272_uart_pdata[fsid_scc1_uart];
        }
 
        pinfo->uart_clk = bd->bi_intfreq;
        pdev->dev.platform_data = pinfo;
-       ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+       ppc_sys_fixup_mem_resource(pdev, CPM_MAP_ADDR);
        return NULL;
 }
 
index 0636aed7b8271b2f9357c27a6cb9da1a9a63c31b..8692d00c08c42d7e3c33e59b57abbd7f75a6c5fb 100644 (file)
@@ -121,13 +121,13 @@ struct platform_device ppc_sys_platform_devices[] = {
                .num_resources   = 3,
                .resource = (struct resource[]) {
                        {
-                               .name   = "scc_mem",
+                               .name   = "regs",
                                .start  = 0x11A00,
                                .end    = 0x11A1F,
                                .flags  = IORESOURCE_MEM,
                        },
                        {
-                               .name   = "scc_pram",
+                               .name   = "pram",
                                .start  = 0x8000,
                                .end    = 0x80ff,
                                .flags  = IORESOURCE_MEM,
@@ -145,13 +145,13 @@ struct platform_device ppc_sys_platform_devices[] = {
                .num_resources   = 3,
                .resource = (struct resource[]) {
                        {
-                               .name   = "scc_mem",
+                               .name   = "regs",
                                .start  = 0x11A20,
                                .end    = 0x11A3F,
                                .flags  = IORESOURCE_MEM,
                        },
                        {
-                               .name   = "scc_pram",
+                               .name   = "pram",
                                .start  = 0x8100,
                                .end    = 0x81ff,
                                .flags  = IORESOURCE_MEM,
@@ -169,13 +169,13 @@ struct platform_device ppc_sys_platform_devices[] = {
                .num_resources   = 3,
                .resource = (struct resource[]) {
                        {
-                               .name   = "scc_mem",
+                               .name   = "regs",
                                .start  = 0x11A40,
                                .end    = 0x11A5F,
                                .flags  = IORESOURCE_MEM,
                        },
                        {
-                               .name   = "scc_pram",
+                               .name   = "pram",
                                .start  = 0x8200,
                                .end    = 0x82ff,
                                .flags  = IORESOURCE_MEM,
@@ -193,13 +193,13 @@ struct platform_device ppc_sys_platform_devices[] = {
                .num_resources   = 3,
                .resource = (struct resource[]) {
                        {
-                               .name   = "scc_mem",
+                               .name   = "regs",
                                .start  = 0x11A60,
                                .end    = 0x11A7F,
                                .flags  = IORESOURCE_MEM,
                        },
                        {
-                               .name   = "scc_pram",
+                               .name   = "pram",
                                .start  = 0x8300,
                                .end    = 0x83ff,
                                .flags  = IORESOURCE_MEM,
index 433b0fa203e110029aa103fa639ca340560f23af..fee8948162b9a49a7c9767cd6e389db223065ef3 100644 (file)
@@ -139,13 +139,13 @@ struct ppc_sys_spec ppc_sys_specs[] = {
                .ppc_sys_name   = "8272",
                .mask           = 0x0000ff00,
                .value          = 0x00000c00,
-               .num_devices    = 11,
+               .num_devices    = 12,
                .device_list = (enum ppc_sys_devices[])
                {
                        MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
-                       MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SMC1,
-                       MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
-                       MPC82xx_CPM_USB, MPC82xx_SEC1,
+                       MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
+                       MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
+                       MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1,
                },
        },
        /* below is a list of the 8280 family of processors */
index ce19ad4e92ec26bc2e6bf4c7a2d019a97c414529..2a6c6efb68653db8880853d09648d86f21af60b9 100644 (file)
@@ -272,7 +272,7 @@ static inline void stop_hz_timer(void)
        next = next_timer_interrupt();
        do {
                seq = read_seqbegin_irqsave(&xtime_lock, flags);
-               timer = (__u64 next) - (__u64 jiffies) + jiffies_64;
+               timer = ((__u64) next) - ((__u64) jiffies) + jiffies_64;
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
        todval = -1ULL;
        /* Be careful about overflows. */
index a93f5da6855d58b1164ae734c9f5d2991ebbf8c1..40b42c88e6a7876c09598e93d30df54def747338 100644 (file)
@@ -69,6 +69,17 @@ void __init smp_store_cpu_info(int id)
                                                     "clock-frequency", 0);
        cpu_data(id).prom_node = cpu_node;
        cpu_data(id).mid = cpu_get_hwmid(cpu_node);
+
+       /* this is required to tune the scheduler correctly */
+       /* is it possible to have CPUs with different cache sizes? */
+       if (id == boot_cpu_id) {
+               int cache_line,cache_nlines;
+               cache_line = 0x20;
+               cache_line = prom_getintdefault(cpu_node, "ecache-line-size", cache_line);
+               cache_nlines = 0x8000;
+               cache_nlines = prom_getintdefault(cpu_node, "ecache-nlines", cache_nlines);
+               max_cache_size = cache_line * cache_nlines;
+       }
        if (cpu_data(id).mid < 0)
                panic("No MID found for CPU%d at node 0x%08d", id, cpu_node);
 }
index 3eadac5e171e489e157ffbb902609274a017ce17..31c5892f5acc49669c4326bf5162a42ebceb36ea 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/errno.h>
+#include <linux/threads.h>
 #include <asm/thread_info.h>
 #include <asm/asi.h>
 #include <asm/pstate.h>
@@ -493,6 +494,35 @@ tlb_fixup_done:
        call    prom_init
         mov    %l7, %o0                        ! OpenPROM cif handler
 
+       /* Initialize current_thread_info()->cpu as early as possible.
+        * In order to do that accurately we have to patch up the get_cpuid()
+        * assembler sequences.  And that, in turn, requires that we know
+        * if we are on a Starfire box or not.  While we're here, patch up
+        * the sun4v sequences as well.
+        */
+       call    check_if_starfire
+        nop
+       call    per_cpu_patch
+        nop
+       call    sun4v_patch
+        nop
+
+#ifdef CONFIG_SMP
+       call    hard_smp_processor_id
+        nop
+       cmp     %o0, NR_CPUS
+       blu,pt  %xcc, 1f
+        nop
+       call    boot_cpu_id_too_large
+        nop
+       /* Not reached... */
+
+1:
+#else
+       mov     0, %o0
+#endif
+       stb     %o0, [%g6 + TI_CPU]
+
        /* Off we go.... */
        call    start_kernel
         nop
index 2b7a1f316a937e56622e9241de9690c7c8f77c45..0c08952029707c846fb3e152a16d30edd42b453a 100644 (file)
@@ -599,18 +599,128 @@ struct pci_iommu_ops pci_sun4v_iommu_ops = {
 
 /* SUN4V PCI configuration space accessors. */
 
-static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
+struct pdev_entry {
+       struct pdev_entry       *next;
+       u32                     devhandle;
+       unsigned int            bus;
+       unsigned int            device;
+       unsigned int            func;
+};
+
+#define PDEV_HTAB_SIZE 16
+#define PDEV_HTAB_MASK (PDEV_HTAB_SIZE - 1)
+static struct pdev_entry *pdev_htab[PDEV_HTAB_SIZE];
+
+static inline unsigned int pdev_hashfn(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
 {
-       if (bus == pbm->pci_first_busno) {
-               if (device == 0 && func == 0)
-                       return 0;
-               return 1;
+       unsigned int val;
+
+       val = (devhandle ^ (devhandle >> 4));
+       val ^= bus;
+       val ^= device;
+       val ^= func;
+
+       return val & PDEV_HTAB_MASK;
+}
+
+static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
+{
+       struct pdev_entry *p = kmalloc(sizeof(*p), GFP_KERNEL);
+       struct pdev_entry **slot;
+
+       if (!p)
+               return -ENOMEM;
+
+       slot = &pdev_htab[pdev_hashfn(devhandle, bus, device, func)];
+       p->next = *slot;
+       *slot = p;
+
+       p->devhandle = devhandle;
+       p->bus = bus;
+       p->device = device;
+       p->func = func;
+
+       return 0;
+}
+
+/* Recursively descend into the OBP device tree, rooted at toplevel_node,
+ * looking for a PCI device matching bus and devfn.
+ */
+static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn)
+{
+       toplevel_node = prom_getchild(toplevel_node);
+
+       while (toplevel_node != 0) {
+               int ret = obp_find(pregs, toplevel_node, bus, devfn);
+
+               if (ret != 0)
+                       return ret;
+
+               ret = prom_getproperty(toplevel_node, "reg", (char *) pregs,
+                                      sizeof(*pregs) * PROMREG_MAX);
+               if (ret == 0 || ret == -1)
+                       goto next_sibling;
+
+               if (((pregs[0].phys_hi >> 16) & 0xff) == bus &&
+                   ((pregs[0].phys_hi >> 8) & 0xff) == devfn)
+                       break;
+
+       next_sibling:
+               toplevel_node = prom_getsibling(toplevel_node);
+       }
+
+       return toplevel_node;
+}
+
+static int pdev_htab_populate(struct pci_pbm_info *pbm)
+{
+       struct linux_prom_pci_registers pr[PROMREG_MAX];
+       u32 devhandle = pbm->devhandle;
+       unsigned int bus;
+
+       for (bus = pbm->pci_first_busno; bus <= pbm->pci_last_busno; bus++) {
+               unsigned int devfn;
+
+               for (devfn = 0; devfn < 256; devfn++) {
+                       unsigned int device = PCI_SLOT(devfn);
+                       unsigned int func = PCI_FUNC(devfn);
+
+                       if (obp_find(pr, pbm->prom_node, bus, devfn)) {
+                               int err = pdev_htab_add(devhandle, bus,
+                                                       device, func);
+                               if (err)
+                                       return err;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static struct pdev_entry *pdev_find(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
+{
+       struct pdev_entry *p;
+
+       p = pdev_htab[pdev_hashfn(devhandle, bus, device, func)];
+       while (p) {
+               if (p->devhandle == devhandle &&
+                   p->bus == bus &&
+                   p->device == device &&
+                   p->func == func)
+                       break;
+
+               p = p->next;
        }
 
+       return p;
+}
+
+static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
+{
        if (bus < pbm->pci_first_busno ||
            bus > pbm->pci_last_busno)
                return 1;
-       return 0;
+       return pdev_find(pbm->devhandle, bus, device, func) == NULL;
 }
 
 static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
@@ -1063,6 +1173,8 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
 
        pci_sun4v_get_bus_range(pbm);
        pci_sun4v_iommu_init(pbm);
+
+       pdev_htab_populate(pbm);
 }
 
 void sun4v_pci_init(int node, char *model_name)
index 005167f82419b475cb7ae1e4ef109610ba61a5dd..9cf1c88cd774ffbcbe3b58da0574986c4e6860ff 100644 (file)
@@ -220,7 +220,7 @@ char reboot_command[COMMAND_LINE_SIZE];
 
 static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
 
-static void __init per_cpu_patch(void)
+void __init per_cpu_patch(void)
 {
        struct cpuid_patch_entry *p;
        unsigned long ver;
@@ -280,7 +280,7 @@ static void __init per_cpu_patch(void)
        }
 }
 
-static void __init sun4v_patch(void)
+void __init sun4v_patch(void)
 {
        struct sun4v_1insn_patch_entry *p1;
        struct sun4v_2insn_patch_entry *p2;
@@ -315,6 +315,15 @@ static void __init sun4v_patch(void)
        }
 }
 
+#ifdef CONFIG_SMP
+void __init boot_cpu_id_too_large(int cpu)
+{
+       prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
+                   cpu, NR_CPUS);
+       prom_halt();
+}
+#endif
+
 void __init setup_arch(char **cmdline_p)
 {
        /* Initialize PROM console and command line. */
@@ -332,16 +341,6 @@ void __init setup_arch(char **cmdline_p)
        conswitchp = &prom_con;
 #endif
 
-       /* Work out if we are starfire early on */
-       check_if_starfire();
-
-       /* Now we know enough to patch the get_cpuid sequences
-        * used by trap code.
-        */
-       per_cpu_patch();
-
-       sun4v_patch();
-
        boot_flags_init(*cmdline_p);
 
        idprom_init();
index 90eaca3ec9a628c40ba90f27c2a89e825afdf736..f03d52d0b88dd73803cee49b98d9b0aeb90e5d92 100644 (file)
@@ -1264,7 +1264,6 @@ void __init smp_tick_init(void)
        boot_cpu_id = hard_smp_processor_id();
        current_tick_offset = timer_tick_offset;
 
-       cpu_set(boot_cpu_id, cpu_online_map);
        prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1;
 }
 
@@ -1288,6 +1287,40 @@ int setup_profiling_timer(unsigned int multiplier)
        return 0;
 }
 
+static void __init smp_tune_scheduling(void)
+{
+       int instance, node;
+       unsigned int def, smallest = ~0U;
+
+       def = ((tlb_type == hypervisor) ?
+              (3 * 1024 * 1024) :
+              (4 * 1024 * 1024));
+
+       instance = 0;
+       while (!cpu_find_by_instance(instance, &node, NULL)) {
+               unsigned int val;
+
+               val = prom_getintdefault(node, "ecache-size", def);
+               if (val < smallest)
+                       smallest = val;
+
+               instance++;
+       }
+
+       /* Any value less than 256K is nonsense.  */
+       if (smallest < (256U * 1024U))
+               smallest = 256 * 1024;
+
+       max_cache_size = smallest;
+
+       if (smallest < 1U * 1024U * 1024U)
+               printk(KERN_INFO "Using max_cache_size of %uKB\n",
+                      smallest / 1024U);
+       else
+               printk(KERN_INFO "Using max_cache_size of %uMB\n",
+                      smallest / 1024U / 1024U);
+}
+
 /* Constrain the number of cpus to max_cpus.  */
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
@@ -1323,6 +1356,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        }
 
        smp_store_cpu_info(boot_cpu_id);
+       smp_tune_scheduling();
 }
 
 /* Set this up early so that things like the scheduler can init
@@ -1345,18 +1379,6 @@ void __init smp_setup_cpu_possible_map(void)
 
 void __devinit smp_prepare_boot_cpu(void)
 {
-       int cpu = hard_smp_processor_id();
-
-       if (cpu >= NR_CPUS) {
-               prom_printf("Serious problem, boot cpu id >= NR_CPUS\n");
-               prom_halt();
-       }
-
-       current_thread_info()->cpu = cpu;
-       __local_per_cpu_offset = __per_cpu_offset(cpu);
-
-       cpu_set(smp_processor_id(), cpu_online_map);
-       cpu_set(smp_processor_id(), phys_cpu_present_map);
 }
 
 int __devinit __cpu_up(unsigned int cpu)
@@ -1433,4 +1455,7 @@ void __init setup_per_cpu_areas(void)
 
        for (i = 0; i < NR_CPUS; i++, ptr += size)
                memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+
+       /* Setup %g5 for the boot cpu.  */
+       __local_per_cpu_offset = __per_cpu_offset(smp_processor_id());
 }
index 62d8a99271eac044e66906d15f3435944eaa3845..38e569f786ddc490dc009c23640128589e6de6ec 100644 (file)
@@ -297,7 +297,6 @@ EXPORT_SYMBOL(svr4_getcontext);
 EXPORT_SYMBOL(svr4_setcontext);
 EXPORT_SYMBOL(compat_sys_ioctl);
 EXPORT_SYMBOL(sparc32_open);
-EXPORT_SYMBOL(sys_close);
 #endif
 
 /* Special internal versions of library functions. */
index 2793a5d823803cb7b96055802935179d5e3d4333..563db528e031830cdcded747e7fa2ecae7e0ec31 100644 (file)
@@ -1797,7 +1797,9 @@ static const char *sun4v_err_type_to_str(u32 type)
        };
 }
 
-static void sun4v_log_error(struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
+extern void __show_regs(struct pt_regs * regs);
+
+static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
 {
        int cnt;
 
@@ -1830,6 +1832,8 @@ static void sun4v_log_error(struct sun4v_error_entry *ent, int cpu, const char *
               pfx,
               ent->err_raddr, ent->err_size, ent->err_cpu);
 
+       __show_regs(regs);
+
        if ((cnt = atomic_read(ocnt)) != 0) {
                atomic_set(ocnt, 0);
                wmb();
@@ -1862,7 +1866,7 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
 
        put_cpu();
 
-       sun4v_log_error(&local_copy, cpu,
+       sun4v_log_error(regs, &local_copy, cpu,
                        KERN_ERR "RESUMABLE ERROR",
                        &sun4v_resum_oflow_cnt);
 }
@@ -1910,7 +1914,7 @@ void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset)
        }
 #endif
 
-       sun4v_log_error(&local_copy, cpu,
+       sun4v_log_error(regs, &local_copy, cpu,
                        KERN_EMERG "NON-RESUMABLE ERROR",
                        &sun4v_nonresum_oflow_cnt);
 
@@ -2200,7 +2204,6 @@ static inline struct reg_window *kernel_stack_up(struct reg_window *rw)
 void die_if_kernel(char *str, struct pt_regs *regs)
 {
        static int die_counter;
-       extern void __show_regs(struct pt_regs * regs);
        extern void smp_report_regs(void);
        int count = 0;
        
index ba9cd3ccc2b26a3f25bd7a2653c1063bf69d61f1..1d230f693dc4b1806e4c80b8df2918abeee878b8 100644 (file)
@@ -165,8 +165,9 @@ csum_partial_end_cruft:
        sll             %g1, 8, %g1
        or              %o5, %g1, %o4
 
-1:     add             %o2, %o4, %o2
+1:     addcc           %o2, %o4, %o2
+       addc            %g0, %o2, %o2
 
 csum_partial_finish:
        retl
-        mov            %o2, %o0
+        srl            %o2, 0, %o0
index 71af488390646d4e7658af9b96c8240d87995c04..e566c770a0f6372de5e4e7856ff520a9ac8920ac 100644 (file)
@@ -221,11 +221,12 @@ FUNC_NAME:                /* %o0=src, %o1=dst, %o2=len, %o3=sum */
        sll             %g1, 8, %g1
        or              %o5, %g1, %o4
 
-1:     add             %o3, %o4, %o3
+1:     addcc           %o3, %o4, %o3
+       addc            %g0, %o3, %o3
 
 70:
        retl
-        mov            %o3, %o0
+        srl            %o3, 0, %o0
 
 95:    mov             0, GLOBAL_SPARE
        brlez,pn        %o2, 4f
index 7a0e04e34bf96f2cb4a89a6be34cfbe8f1e6cf90..b65ca115ef7778553473a157998ada3c54869051 100644 (file)
@@ -33,5 +33,9 @@ include $(srctree)/arch/i386/Makefile.cpu
 # prevent gcc from keeping the stack 16 byte aligned. Taken from i386.
 cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
 
+# Prevent sprintf in nfsd from being converted to strcpy and resulting in
+# an unresolved reference.
+cflags-y += -ffreestanding
+
 CFLAGS += $(cflags-y)
 USER_CFLAGS += $(cflags-y)
index efa3d33c0be6577a6ab533449ce2ed34032957de..310980b3217395a591a0eeee7a748dcb4fdf2925 100644 (file)
@@ -120,20 +120,11 @@ extern int is_syscall(unsigned long addr);
 extern void free_irq(unsigned int, void *);
 extern int cpu(void);
 
+extern void time_init_kern(void);
+
 /* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
 extern int __cant_sleep(void);
 extern void segv_handler(int sig, union uml_pt_regs *regs);
 extern void sigio_handler(int sig, union uml_pt_regs *regs);
 
 #endif
-
-/*
- * 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 fc0f0b085ca78ffb8416c48cf9a1b23ea283dfaa..166cb09cae4cf9f05079d84ea88ef5f7770551e4 100644 (file)
@@ -69,7 +69,7 @@ static void insert_phys_mapping(struct phys_desc *desc)
                panic("Physical remapping for %p already present",
                      desc->virt);
 
-       rb_link_node(&desc->rb, (*n)->rb_parent, n);
+       rb_link_node(&desc->rb, rb_parent(*n), n);
        rb_insert_color(&desc->rb, &phys_mappings);
 }
 
index 528cf623f8b4144cbf77b4c0337a1ee6ab423185..86f51d04c98df366d7a139468cf3afb08c402251 100644 (file)
@@ -84,6 +84,16 @@ void timer_irq(union uml_pt_regs *regs)
        }
 }
 
+
+void time_init_kern(void)
+{
+       unsigned long long nsecs;
+
+       nsecs = os_nsecs();
+       set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
+                               -nsecs % BILLION);
+}
+
 void do_boot_timer_handler(struct sigcontext * sc)
 {
        struct pt_regs regs;
index 3a0ac38e978bffa982f68badb8e9dd1e168bd3f6..90912aaca7aa154ef577e63bbc0d9c6aa6d87800 100644 (file)
@@ -59,7 +59,7 @@ static __init void do_uml_initcalls(void)
        initcall_t *call;
 
        call = &__uml_initcall_start;
-       while (call < &__uml_initcall_end){;
+       while (call < &__uml_initcall_end){
                (*call)();
                call++;
        }
index 6f7626775acb983e7f2e663d2312533d80c1a792..280c4fb9b585a15813e4cf9669a0b3b258181623 100644 (file)
@@ -81,20 +81,12 @@ void uml_idle_timer(void)
        set_interval(ITIMER_REAL);
 }
 
-extern void ktime_get_ts(struct timespec *ts);
-#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
-
 void time_init(void)
 {
-       struct timespec now;
-
        if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
                panic("Couldn't set SIGVTALRM handler");
        set_interval(ITIMER_VIRTUAL);
-
-       do_posix_clock_monotonic_gettime(&now);
-       wall_to_monotonic.tv_sec = -now.tv_sec;
-       wall_to_monotonic.tv_nsec = -now.tv_nsec;
+       time_init_kern();
 }
 
 unsigned long long os_nsecs(void)
index 749dd1bfe60f9009127adfbd4a958173d280e1b7..710d5fb807e1d6b9ae7e24e7542814aa36b69348 100644 (file)
@@ -99,11 +99,12 @@ long sys_ipc (uint call, int first, int second,
 
        switch (call) {
        case SEMOP:
-               return sys_semtimedop(first, (struct sembuf *) ptr, second,
-                                     NULL);
+               return sys_semtimedop(first, (struct sembuf __user *) ptr,
+                                     second, NULL);
        case SEMTIMEDOP:
-               return sys_semtimedop(first, (struct sembuf *) ptr, second,
-                                     (const struct timespec *) fifth);
+               return sys_semtimedop(first, (struct sembuf __user *) ptr,
+                                     second,
+                                     (const struct timespec __user *) fifth);
        case SEMGET:
                return sys_semget (first, second, third);
        case SEMCTL: {
index a4c46a8af00842078fb03e2f36592f4706abf49c..9edf114faf79c571831fd1ca84127204094bb846 100644 (file)
@@ -21,7 +21,7 @@
 #include "skas.h"
 
 static int copy_sc_from_user_skas(struct pt_regs *regs,
-                                 struct sigcontext *from)
+                                 struct sigcontext __user *from)
 {
        int err = 0;
 
@@ -54,7 +54,8 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
        return(err);
 }
 
-int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
+int copy_sc_to_user_skas(struct sigcontext __user *to,
+                        struct _fpstate __user *to_fp,
                         struct pt_regs *regs, unsigned long mask,
                         unsigned long sp)
 {
@@ -106,10 +107,11 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
 #endif
 
 #ifdef CONFIG_MODE_TT
-int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
+int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
                         int fpsize)
 {
-       struct _fpstate *to_fp, *from_fp;
+       struct _fpstate *to_fp;
+       struct _fpstate __user *from_fp;
        unsigned long sigs;
        int err;
 
@@ -124,13 +126,14 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
        return(err);
 }
 
-int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
+int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
                       struct sigcontext *from, int fpsize, unsigned long sp)
 {
-       struct _fpstate *to_fp, *from_fp;
+       struct _fpstate __user *to_fp;
+       struct _fpstate *from_fp;
        int err;
 
-       to_fp = (fp ? fp : (struct _fpstate *) (to + 1));
+       to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1));
        from_fp = from->fpstate;
        err = copy_to_user(to, from, sizeof(*to));
        /* The SP in the sigcontext is the updated one for the signal
@@ -158,7 +161,8 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
        return(ret);
 }
 
-static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
+static int copy_sc_to_user(struct sigcontext __user *to,
+                          struct _fpstate __user *fp,
                           struct pt_regs *from, unsigned long mask,
                           unsigned long sp)
 {
@@ -169,7 +173,7 @@ static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp,
 
 struct rt_sigframe
 {
-       char *pretcode;
+       char __user *pretcode;
        struct ucontext uc;
        struct siginfo info;
 };
@@ -188,7 +192,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
 
        frame = (struct rt_sigframe __user *)
                round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8;
-        frame = (struct rt_sigframe *) ((unsigned long) frame - 128);
+        frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128);
 
        if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
                goto out;
index 6acee5c4ada6fcdff56ddd95313865dd295df508..6fce9f45dfdc0257aafafaf543afffcfc42127e3 100644 (file)
@@ -45,7 +45,7 @@ static long arch_prctl_tt(int code, unsigned long addr)
        case ARCH_GET_GS:
                ret = arch_prctl(code, (unsigned long) &tmp);
                if(!ret)
-                       ret = put_user(tmp, &addr);
+                       ret = put_user(tmp, (long __user *)addr);
                break;
        default:
                ret = -EINVAL;
index e776139afb2019e804d65ddd468a834ee04d6ed1..926c4743d13b27220cd00494a99f3eb2d74a1ff1 100644 (file)
@@ -339,7 +339,7 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top,
        struct mm_struct *mm = current->mm;
        int i, ret;
 
-       stack_base = IA32_STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
+       stack_base = stack_top - MAX_ARG_PAGES * PAGE_SIZE;
        mm->arg_start = bprm->p + stack_base;
 
        bprm->p += stack_base;
@@ -357,7 +357,7 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top,
        {
                mpnt->vm_mm = mm;
                mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
-               mpnt->vm_end = IA32_STACK_TOP;
+               mpnt->vm_end = stack_top;
                if (executable_stack == EXSTACK_ENABLE_X)
                        mpnt->vm_flags = VM_STACK_FLAGS |  VM_EXEC;
                else if (executable_stack == EXSTACK_DISABLE_X)
index 222b5b46d2b2df6546ab01e67be1d1b92d713667..1ef6028f721ea843936b4994581c67dfa7e1b9c6 100644 (file)
@@ -149,7 +149,7 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsi
                        addr = start;
                if (addr > ei->addr + ei->size) 
                        continue; 
-               while (bad_addr(&addr, size) && addr+size < ei->addr + ei->size)
+               while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
                        ;
                last = addr + size;
                if (last > ei->addr + ei->size)
index c946e4fe67a7937ab15eba697246602c7dc67dbd..586b34c00c489a2d3d495a904c00b158a1abfba4 100644 (file)
@@ -281,12 +281,7 @@ tracesys:
        ja  1f
        movq %r10,%rcx  /* fixup for C */
        call *sys_call_table(,%rax,8)
-       movq %rax,RAX-ARGOFFSET(%rsp)
-1:     SAVE_REST
-       movq %rsp,%rdi
-       call syscall_trace_leave
-       RESTORE_TOP_OF_STACK %rbx
-       RESTORE_REST
+1:     movq %rax,RAX-ARGOFFSET(%rsp)
        /* Use IRET because user could have changed frame */
        jmp int_ret_from_sys_call
        CFI_ENDPROC
index 0de3ea938830f6f8934e39a537fecaec6237b29e..9cc7031b715178cb069243fffb1bdbbe49483e1e 100644 (file)
@@ -271,6 +271,18 @@ __setup("enable_8254_timer", setup_enable_8254_timer);
 #include <linux/pci_ids.h>
 #include <linux/pci.h>
 
+
+#ifdef CONFIG_ACPI
+
+static int nvidia_hpet_detected __initdata;
+
+static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
+{
+       nvidia_hpet_detected = 1;
+       return 0;
+}
+#endif
+
 /* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC
    off. Check for an Nvidia or VIA PCI bridge and turn it off.
    Use pci direct infrastructure because this runs before the PCI subsystem. 
@@ -317,11 +329,19 @@ void __init check_ioapic(void)
                                        return;
                                case PCI_VENDOR_ID_NVIDIA:
 #ifdef CONFIG_ACPI
-                                       /* All timer overrides on Nvidia
-                                          seem to be wrong. Skip them. */
-                                       acpi_skip_timer_override = 1;
-                                       printk(KERN_INFO 
-            "Nvidia board detected. Ignoring ACPI timer override.\n");
+                                       /*
+                                        * All timer overrides on Nvidia are
+                                        * wrong unless HPET is enabled.
+                                        */
+                                       nvidia_hpet_detected = 0;
+                                       acpi_table_parse(ACPI_HPET,
+                                                       nvidia_hpet_check);
+                                       if (nvidia_hpet_detected == 0) {
+                                               acpi_skip_timer_override = 1;
+                                               printk(KERN_INFO "Nvidia board "
+                                                   "detected. Ignoring ACPI "
+                                                   "timer override.\n");
+                                       }
 #endif
                                        /* RED-PEN skip them on mptables too? */
                                        return;
index af035ede70cd43386f240438e2192cb343cab750..a9275c9557cf432ea3187f806c15fb369d72b312 100644 (file)
@@ -54,6 +54,10 @@ dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
        else
 #endif
                node = numa_node_id();
+
+       if (node < first_node(node_online_map))
+               node = first_node(node_online_map);
+
        page = alloc_pages_node(node, gfp, order);
        return page ? page_address(page) : NULL;
 }
index 2480d3f08a470865b90f1dd8cb35e2c6c30a9e1a..82a7c9bfdfa0f3e0bd1945225fd0f86df67b1c96 100644 (file)
@@ -631,10 +631,8 @@ static int __init pci_iommu_init(void)
                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 compiled in.\n"
-                              KERN_ERR "WARNING 32bit PCI may malfunction.\n"
-                              KERN_ERR "You might want to enable "
-                                       "CONFIG_GART_IOMMU\n");
+                                       "but IOMMU not available.\n"
+                              KERN_ERR "WARNING 32bit PCI may malfunction.\n");
                }
                return -1;
        }
index b0444a415bd60670a2314d9e0f9c0c54641a7e56..bf421ed26808cec48cc9ca1207865bcee52f0f07 100644 (file)
@@ -68,7 +68,7 @@ int pmtimer_mark_offset(void)
        offset_delay = delta % (USEC_PER_SEC / HZ);
 
        rdtscll(tsc);
-       vxtime.last_tsc = tsc - offset_delay * cpu_khz;
+       vxtime.last_tsc = tsc - offset_delay * (u64)cpu_khz / 1000;
 
        /* don't calculate delay for first run,
           or if we've got less then a tick */
index f0870bef24d114b521f625952b79e973ed2a5e1c..655b9192eeb3727d85a8921d10cdd4049c2a5232 100644 (file)
@@ -1051,7 +1051,7 @@ static void srat_detect_node(void)
           for now. */
        node = apicid_to_node[hard_smp_processor_id()];
        if (node == NUMA_NO_NODE)
-               node = 0;
+               node = first_node(node_online_map);
        numa_set_node(cpu, node);
 
        if (acpi_numa > 0)
index e1513532df293447a529cd7477b6bbca67363e18..474df22c6ed20fb7aa0f2b6e503dc232d0ec3050 100644 (file)
@@ -399,8 +399,10 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
        /* First clean up the node list */
        for (i = 0; i < MAX_NUMNODES; i++) {
                cutoff_node(i, start, end);
-               if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE)
+               if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE) {
                        unparse_node(i);
+                       node_set_offline(i);
+               }
        }
 
        if (acpi_numa <= 0)
index e25a5d79ab2715b2f3a07ce3331e46cd45ab86f1..0c750393be4acad096f29a53eba1538126e65a63 100644 (file)
@@ -353,10 +353,9 @@ static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset)
 /*
  * rb tree support functions
  */
-#define RB_NONE                (2)
 #define RB_EMPTY(root) ((root)->rb_node == NULL)
-#define ON_RB(node)    ((node)->rb_color != RB_NONE)
-#define RB_CLEAR(node) ((node)->rb_color = RB_NONE)
+#define ON_RB(node)    (rb_parent(node) != node)
+#define RB_CLEAR(node) (rb_set_parent(node, node))
 #define rb_entry_arq(node)     rb_entry((node), struct as_rq, rb_node)
 #define ARQ_RB_ROOT(ad, arq)   (&(ad)->sort_list[(arq)->is_sync])
 #define rq_rb_key(rq)          (rq)->sector
@@ -1648,17 +1647,17 @@ static void as_exit_queue(elevator_t *e)
  * initialize elevator private data (as_data), and alloc a arq for
  * each request on the free lists
  */
-static int as_init_queue(request_queue_t *q, elevator_t *e)
+static void *as_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct as_data *ad;
        int i;
 
        if (!arq_pool)
-               return -ENOMEM;
+               return NULL;
 
        ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
        if (!ad)
-               return -ENOMEM;
+               return NULL;
        memset(ad, 0, sizeof(*ad));
 
        ad->q = q; /* Identify what queue the data belongs to */
@@ -1667,7 +1666,7 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
                                GFP_KERNEL, q->node);
        if (!ad->hash) {
                kfree(ad);
-               return -ENOMEM;
+               return NULL;
        }
 
        ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
@@ -1675,7 +1674,7 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
        if (!ad->arq_pool) {
                kfree(ad->hash);
                kfree(ad);
-               return -ENOMEM;
+               return NULL;
        }
 
        /* anticipatory scheduling helpers */
@@ -1696,14 +1695,13 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
        ad->antic_expire = default_antic_expire;
        ad->batch_expire[REQ_SYNC] = default_read_batch_expire;
        ad->batch_expire[REQ_ASYNC] = default_write_batch_expire;
-       e->elevator_data = ad;
 
        ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC];
        ad->write_batch_count = ad->batch_expire[REQ_ASYNC] / 10;
        if (ad->write_batch_count < 2)
                ad->write_batch_count = 2;
 
-       return 0;
+       return ad;
 }
 
 /*
index 2540dfaa3e385def27a44284bf3e552f986ee15d..6200d9b9af28efbbd5aaac5373995ca8334dbaaf 100644 (file)
@@ -33,7 +33,7 @@ static int cfq_slice_idle = HZ / 70;
 
 #define CFQ_KEY_ASYNC          (0)
 
-static DEFINE_RWLOCK(cfq_exit_lock);
+static DEFINE_SPINLOCK(cfq_exit_lock);
 
 /*
  * for the hash of cfqq inside the cfqd
@@ -60,14 +60,9 @@ static DEFINE_RWLOCK(cfq_exit_lock);
 /*
  * rb-tree defines
  */
-#define RB_NONE                        (2)
 #define RB_EMPTY(node)         ((node)->rb_node == NULL)
-#define RB_CLEAR_COLOR(node)   (node)->rb_color = RB_NONE
 #define RB_CLEAR(node)         do {    \
-       (node)->rb_parent = NULL;       \
-       RB_CLEAR_COLOR((node));         \
-       (node)->rb_right = NULL;        \
-       (node)->rb_left = NULL;         \
+               memset(node, 0, sizeof(*node)); \
 } while (0)
 #define RB_CLEAR_ROOT(root)    ((root)->rb_node = NULL)
 #define rb_entry_crq(node)     rb_entry((node), struct cfq_rq, rb_node)
@@ -133,6 +128,7 @@ struct cfq_data {
        mempool_t *crq_pool;
 
        int rq_in_driver;
+       int hw_tag;
 
        /*
         * schedule slice state info
@@ -500,10 +496,13 @@ static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
 
        /*
         * if queue was preempted, just add to front to be fair. busy_rr
-        * isn't sorted.
+        * isn't sorted, but insert at the back for fairness.
         */
        if (preempted || list == &cfqd->busy_rr) {
-               list_add(&cfqq->cfq_list, list);
+               if (preempted)
+                       list = list->prev;
+
+               list_add_tail(&cfqq->cfq_list, list);
                return;
        }
 
@@ -563,7 +562,6 @@ static inline void cfq_del_crq_rb(struct cfq_rq *crq)
        cfq_update_next_crq(crq);
 
        rb_erase(&crq->rb_node, &cfqq->sort_list);
-       RB_CLEAR_COLOR(&crq->rb_node);
 
        if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
                cfq_del_cfqq_rr(cfqd, cfqq);
@@ -664,6 +662,15 @@ static void cfq_activate_request(request_queue_t *q, struct request *rq)
        struct cfq_data *cfqd = q->elevator->elevator_data;
 
        cfqd->rq_in_driver++;
+
+       /*
+        * If the depth is larger 1, it really could be queueing. But lets
+        * make the mark a little higher - idling could still be good for
+        * low queueing, and a low queueing number could also just indicate
+        * a SCSI mid layer like behaviour where limit+1 is often seen.
+        */
+       if (!cfqd->hw_tag && cfqd->rq_in_driver > 4)
+               cfqd->hw_tag = 1;
 }
 
 static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
@@ -878,6 +885,13 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
        if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1)
                cfqq = list_entry_cfqq(cfqd->cur_rr.next);
 
+       /*
+        * If no new queues are available, check if the busy list has some
+        * before falling back to idle io.
+        */
+       if (!cfqq && !list_empty(&cfqd->busy_rr))
+               cfqq = list_entry_cfqq(cfqd->busy_rr.next);
+
        /*
         * if we have idle queues and no rt or be queues had pending
         * requests, either allow immediate service if the grace period
@@ -1284,7 +1298,7 @@ static void cfq_exit_io_context(struct io_context *ioc)
        /*
         * put the reference this task is holding to the various queues
         */
-       read_lock_irqsave(&cfq_exit_lock, flags);
+       spin_lock_irqsave(&cfq_exit_lock, flags);
 
        n = rb_first(&ioc->cic_root);
        while (n != NULL) {
@@ -1294,7 +1308,7 @@ static void cfq_exit_io_context(struct io_context *ioc)
                n = rb_next(n);
        }
 
-       read_unlock_irqrestore(&cfq_exit_lock, flags);
+       spin_unlock_irqrestore(&cfq_exit_lock, flags);
 }
 
 static struct cfq_io_context *
@@ -1303,17 +1317,12 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
        struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
 
        if (cic) {
-               RB_CLEAR(&cic->rb_node);
-               cic->key = NULL;
-               cic->cfqq[ASYNC] = NULL;
-               cic->cfqq[SYNC] = NULL;
+               memset(cic, 0, sizeof(*cic));
+               RB_CLEAR_COLOR(&cic->rb_node);
                cic->last_end_request = jiffies;
-               cic->ttime_total = 0;
-               cic->ttime_samples = 0;
-               cic->ttime_mean = 0;
+               INIT_LIST_HEAD(&cic->queue_list);
                cic->dtor = cfq_free_io_context;
                cic->exit = cfq_exit_io_context;
-               INIT_LIST_HEAD(&cic->queue_list);
                atomic_inc(&ioc_count);
        }
 
@@ -1400,17 +1409,17 @@ static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
        struct cfq_io_context *cic;
        struct rb_node *n;
 
-       write_lock(&cfq_exit_lock);
+       spin_lock(&cfq_exit_lock);
 
        n = rb_first(&ioc->cic_root);
        while (n != NULL) {
                cic = rb_entry(n, struct cfq_io_context, rb_node);
+
                changed_ioprio(cic);
                n = rb_next(n);
        }
 
-       write_unlock(&cfq_exit_lock);
+       spin_unlock(&cfq_exit_lock);
 
        return 0;
 }
@@ -1458,7 +1467,8 @@ retry:
                 * set ->slice_left to allow preemption for a new process
                 */
                cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
-               cfq_mark_cfqq_idle_window(cfqq);
+               if (!cfqd->hw_tag)
+                       cfq_mark_cfqq_idle_window(cfqq);
                cfq_mark_cfqq_prio_changed(cfqq);
                cfq_init_prio_data(cfqq);
        }
@@ -1475,9 +1485,10 @@ out:
 static void
 cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic)
 {
-       read_lock(&cfq_exit_lock);
+       spin_lock(&cfq_exit_lock);
        rb_erase(&cic->rb_node, &ioc->cic_root);
-       read_unlock(&cfq_exit_lock);
+       list_del_init(&cic->queue_list);
+       spin_unlock(&cfq_exit_lock);
        kmem_cache_free(cfq_ioc_pool, cic);
        atomic_dec(&ioc_count);
 }
@@ -1545,11 +1556,11 @@ restart:
                        BUG();
        }
 
-       read_lock(&cfq_exit_lock);
+       spin_lock(&cfq_exit_lock);
        rb_link_node(&cic->rb_node, parent, p);
        rb_insert_color(&cic->rb_node, &ioc->cic_root);
        list_add(&cic->queue_list, &cfqd->cic_list);
-       read_unlock(&cfq_exit_lock);
+       spin_unlock(&cfq_exit_lock);
 }
 
 /*
@@ -1648,7 +1659,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 {
        int enable_idle = cfq_cfqq_idle_window(cfqq);
 
-       if (!cic->ioc->task || !cfqd->cfq_slice_idle)
+       if (!cic->ioc->task || !cfqd->cfq_slice_idle || cfqd->hw_tag)
                enable_idle = 0;
        else if (sample_valid(cic->ttime_samples)) {
                if (cic->ttime_mean > cfqd->cfq_slice_idle)
@@ -1739,14 +1750,24 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 
        cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
 
+       cic = crq->io_context;
+
        /*
         * we never wait for an async request and we don't allow preemption
         * of an async request. so just return early
         */
-       if (!cfq_crq_is_sync(crq))
+       if (!cfq_crq_is_sync(crq)) {
+               /*
+                * sync process issued an async request, if it's waiting
+                * then expire it and kick rq handling.
+                */
+               if (cic == cfqd->active_cic &&
+                   del_timer(&cfqd->idle_slice_timer)) {
+                       cfq_slice_expired(cfqd, 0);
+                       cfq_start_queueing(cfqd, cfqq);
+               }
                return;
-
-       cic = crq->io_context;
+       }
 
        cfq_update_io_thinktime(cfqd, cic);
        cfq_update_io_seektime(cfqd, cic, crq);
@@ -2164,10 +2185,9 @@ static void cfq_idle_class_timer(unsigned long data)
         * race with a non-idle queue, reset timer
         */
        end = cfqd->last_end_request + CFQ_IDLE_GRACE;
-       if (!time_after_eq(jiffies, end)) {
-               cfqd->idle_class_timer.expires = end;
-               add_timer(&cfqd->idle_class_timer);
-       } else
+       if (!time_after_eq(jiffies, end))
+               mod_timer(&cfqd->idle_class_timer, end);
+       else
                cfq_schedule_dispatch(cfqd);
 
        spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
@@ -2187,7 +2207,7 @@ static void cfq_exit_queue(elevator_t *e)
 
        cfq_shutdown_timer_wq(cfqd);
 
-       write_lock(&cfq_exit_lock);
+       spin_lock(&cfq_exit_lock);
        spin_lock_irq(q->queue_lock);
 
        if (cfqd->active_queue)
@@ -2210,7 +2230,7 @@ static void cfq_exit_queue(elevator_t *e)
        }
 
        spin_unlock_irq(q->queue_lock);
-       write_unlock(&cfq_exit_lock);
+       spin_unlock(&cfq_exit_lock);
 
        cfq_shutdown_timer_wq(cfqd);
 
@@ -2220,14 +2240,14 @@ static void cfq_exit_queue(elevator_t *e)
        kfree(cfqd);
 }
 
-static int cfq_init_queue(request_queue_t *q, elevator_t *e)
+static void *cfq_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct cfq_data *cfqd;
        int i;
 
        cfqd = kmalloc(sizeof(*cfqd), GFP_KERNEL);
        if (!cfqd)
-               return -ENOMEM;
+               return NULL;
 
        memset(cfqd, 0, sizeof(*cfqd));
 
@@ -2257,8 +2277,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
        for (i = 0; i < CFQ_QHASH_ENTRIES; i++)
                INIT_HLIST_HEAD(&cfqd->cfq_hash[i]);
 
-       e->elevator_data = cfqd;
-
        cfqd->queue = q;
 
        cfqd->max_queued = q->nr_requests / 4;
@@ -2285,14 +2303,14 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
        cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
        cfqd->cfq_slice_idle = cfq_slice_idle;
 
-       return 0;
+       return cfqd;
 out_crqpool:
        kfree(cfqd->cfq_hash);
 out_cfqhash:
        kfree(cfqd->crq_hash);
 out_crqhash:
        kfree(cfqd);
-       return -ENOMEM;
+       return NULL;
 }
 
 static void cfq_slab_kill(void)
index 399fa1e60e1fd6b7ca8200b7d5ef14a67b0b7672..c94de8e12fbf8aa5bf827bd982a10df0a930948b 100644 (file)
@@ -165,10 +165,9 @@ deadline_find_drq_hash(struct deadline_data *dd, sector_t offset)
 /*
  * rb tree support functions
  */
-#define RB_NONE                (2)
 #define RB_EMPTY(root) ((root)->rb_node == NULL)
-#define ON_RB(node)    ((node)->rb_color != RB_NONE)
-#define RB_CLEAR(node) ((node)->rb_color = RB_NONE)
+#define ON_RB(node)    (rb_parent(node) != node)
+#define RB_CLEAR(node) (rb_set_parent(node, node))
 #define rb_entry_drq(node)     rb_entry((node), struct deadline_rq, rb_node)
 #define DRQ_RB_ROOT(dd, drq)   (&(dd)->sort_list[rq_data_dir((drq)->request)])
 #define rq_rb_key(rq)          (rq)->sector
@@ -613,24 +612,24 @@ static void deadline_exit_queue(elevator_t *e)
  * initialize elevator private data (deadline_data), and alloc a drq for
  * each request on the free lists
  */
-static int deadline_init_queue(request_queue_t *q, elevator_t *e)
+static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct deadline_data *dd;
        int i;
 
        if (!drq_pool)
-               return -ENOMEM;
+               return NULL;
 
        dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
        if (!dd)
-               return -ENOMEM;
+               return NULL;
        memset(dd, 0, sizeof(*dd));
 
        dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES,
                                GFP_KERNEL, q->node);
        if (!dd->hash) {
                kfree(dd);
-               return -ENOMEM;
+               return NULL;
        }
 
        dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
@@ -638,7 +637,7 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
        if (!dd->drq_pool) {
                kfree(dd->hash);
                kfree(dd);
-               return -ENOMEM;
+               return NULL;
        }
 
        for (i = 0; i < DL_HASH_ENTRIES; i++)
@@ -653,8 +652,7 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
        dd->writes_starved = writes_starved;
        dd->front_merges = 1;
        dd->fifo_batch = fifo_batch;
-       e->elevator_data = dd;
-       return 0;
+       return dd;
 }
 
 static void deadline_put_request(request_queue_t *q, struct request *rq)
index 8768a367fdded922a17b1c7c47ac24ec993a1628..a0afdd317ceffb3d59f230c775da6c03740a426f 100644 (file)
@@ -121,16 +121,16 @@ static struct elevator_type *elevator_get(const char *name)
        return e;
 }
 
-static int elevator_attach(request_queue_t *q, struct elevator_queue *eq)
+static void *elevator_init_queue(request_queue_t *q, struct elevator_queue *eq)
 {
-       int ret = 0;
+       return eq->ops->elevator_init_fn(q, eq);
+}
 
+static void elevator_attach(request_queue_t *q, struct elevator_queue *eq,
+                          void *data)
+{
        q->elevator = eq;
-
-       if (eq->ops->elevator_init_fn)
-               ret = eq->ops->elevator_init_fn(q, eq);
-
-       return ret;
+       eq->elevator_data = data;
 }
 
 static char chosen_elevator[16];
@@ -181,6 +181,7 @@ int elevator_init(request_queue_t *q, char *name)
        struct elevator_type *e = NULL;
        struct elevator_queue *eq;
        int ret = 0;
+       void *data;
 
        INIT_LIST_HEAD(&q->queue_head);
        q->last_merge = NULL;
@@ -202,10 +203,13 @@ int elevator_init(request_queue_t *q, char *name)
        if (!eq)
                return -ENOMEM;
 
-       ret = elevator_attach(q, eq);
-       if (ret)
+       data = elevator_init_queue(q, eq);
+       if (!data) {
                kobject_put(&eq->kobj);
+               return -ENOMEM;
+       }
 
+       elevator_attach(q, eq, data);
        return ret;
 }
 
@@ -722,13 +726,16 @@ int elv_register_queue(struct request_queue *q)
        return error;
 }
 
+static void __elv_unregister_queue(elevator_t *e)
+{
+       kobject_uevent(&e->kobj, KOBJ_REMOVE);
+       kobject_del(&e->kobj);
+}
+
 void elv_unregister_queue(struct request_queue *q)
 {
-       if (q) {
-               elevator_t *e = q->elevator;
-               kobject_uevent(&e->kobj, KOBJ_REMOVE);
-               kobject_del(&e->kobj);
-       }
+       if (q)
+               __elv_unregister_queue(q->elevator);
 }
 
 int elv_register(struct elevator_type *e)
@@ -780,6 +787,7 @@ EXPORT_SYMBOL_GPL(elv_unregister);
 static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
 {
        elevator_t *old_elevator, *e;
+       void *data;
 
        /*
         * Allocate new elevator
@@ -788,6 +796,12 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
        if (!e)
                return 0;
 
+       data = elevator_init_queue(q, e);
+       if (!data) {
+               kobject_put(&e->kobj);
+               return 0;
+       }
+
        /*
         * Turn on BYPASS and drain all requests w/ elevator private data
         */
@@ -806,19 +820,19 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
                elv_drain_elevator(q);
        }
 
-       spin_unlock_irq(q->queue_lock);
-
        /*
-        * unregister old elevator data
+        * Remember old elevator.
         */
-       elv_unregister_queue(q);
        old_elevator = q->elevator;
 
        /*
         * attach and start new elevator
         */
-       if (elevator_attach(q, e))
-               goto fail;
+       elevator_attach(q, e, data);
+
+       spin_unlock_irq(q->queue_lock);
+
+       __elv_unregister_queue(old_elevator);
 
        if (elv_register_queue(q))
                goto fail_register;
@@ -837,7 +851,6 @@ fail_register:
         */
        elevator_exit(e);
        e = NULL;
-fail:
        q->elevator = old_elevator;
        elv_register_queue(q);
        clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
index f370e4a7fe6d7a26e66f988774c002af6b772725..56a7c620574f86c0338a431354344d149314ce0f 100644 (file)
@@ -65,16 +65,15 @@ noop_latter_request(request_queue_t *q, struct request *rq)
        return list_entry(rq->queuelist.next, struct request, queuelist);
 }
 
-static int noop_init_queue(request_queue_t *q, elevator_t *e)
+static void *noop_init_queue(request_queue_t *q, elevator_t *e)
 {
        struct noop_data *nd;
 
        nd = kmalloc(sizeof(*nd), GFP_KERNEL);
        if (!nd)
-               return -ENOMEM;
+               return NULL;
        INIT_LIST_HEAD(&nd->queue);
-       e->elevator_data = nd;
-       return 0;
+       return nd;
 }
 
 static void noop_exit_queue(elevator_t *e)
index aeb5ab2391e421faf03935992ffa3c0c817f4353..8b11cebe65df5ad396f8fb975e158466f9dd859b 100644 (file)
@@ -72,4 +72,6 @@ source "drivers/edac/Kconfig"
 
 source "drivers/rtc/Kconfig"
 
+source "drivers/dma/Kconfig"
+
 endmenu
index 447d8e68887a1f668312806e8cedd75c8c218247..3c5170310bd0d407277fe5bb36a5cef87de8ba3c 100644 (file)
@@ -74,3 +74,4 @@ obj-$(CONFIG_SGI_SN)          += sn/
 obj-y                          += firmware/
 obj-$(CONFIG_CRYPTO)           += crypto/
 obj-$(CONFIG_SUPERH)           += sh/
+obj-$(CONFIG_DMA_ENGINE)       += dma/
index 07bc6dfe662b34aeb4c83d7476d6cee31c10c70a..8920e8c6e246dba49a30da6c2539dae11ec69316 100644 (file)
@@ -812,6 +812,9 @@ static int irqrouter_resume(struct sys_device *dev)
 
        ACPI_FUNCTION_TRACE("irqrouter_resume");
 
+       /* Make sure SCI is enabled again (Apple firmware bug?) */
+       acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1, ACPI_MTX_DO_NOT_LOCK);
+
        acpi_in_resume = 1;
        list_for_each(node, &acpi_link.entries) {
                link = list_entry(node, struct acpi_pci_link, node);
index abbdb37a7f5f37e062f58800318d66b67a37c5d1..f36db22ce1aeb9b745ee815f6266779f31e98945 100644 (file)
@@ -577,6 +577,8 @@ acpi_processor_register_performance(struct acpi_processor_performance
                return_VALUE(-EBUSY);
        }
 
+       WARN_ON(!performance);
+
        pr->performance = performance;
 
        if (acpi_processor_get_performance_info(pr)) {
@@ -609,7 +611,8 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
                return_VOID;
        }
 
-       kfree(pr->performance->states);
+       if (pr->performance)
+               kfree(pr->performance->states);
        pr->performance = NULL;
 
        acpi_cpufreq_remove_file(pr);
index 662209d3f42d6a551c7001ab5adb62406abfcfb0..2a769cc6f5f9f8181580b6657c0d0625e9c937dd 100644 (file)
@@ -8,7 +8,6 @@
  *
  */
 
-#include <linux/vt_kern.h>
 #include <linux/device.h>
 #include <linux/kallsyms.h>
 #include <linux/pm.h>
@@ -66,6 +65,7 @@ int suspend_device(struct device * dev, pm_message_t state)
        return error;
 }
 
+
 /**
  *     device_suspend - Save state and stop all devices in system.
  *     @state:         Power state to put each device in.
@@ -85,9 +85,6 @@ int device_suspend(pm_message_t state)
 {
        int error = 0;
 
-       if (!is_console_suspend_safe())
-               return -EINVAL;
-
        down(&dpm_sem);
        down(&dpm_list_sem);
        while (!list_empty(&dpm_active) && error == 0) {
index fdff774b8ab944421ad0190486e98cc4c5f458a5..c1434ed118808999a3b05f148ef3b76b0590360f 100644 (file)
@@ -116,8 +116,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
        skb = skb_share_check(skb, GFP_ATOMIC);
        if (skb == NULL)
                return 0;
-       if (skb_is_nonlinear(skb))
-       if (skb_linearize(skb, GFP_ATOMIC) < 0)
+       if (skb_linearize(skb))
                goto exit;
        if (!is_aoe_netif(ifp))
                goto exit;
index a59876a0bfa135bcd39d87991a6cb221831010c6..3170eaa250873bf5f0dae15b88aacf66d2a3ef1e 100644 (file)
@@ -1009,9 +1009,9 @@ int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
                if (fp->f_mode & FMODE_WRITE) {
                        ret = -EROFS;
                        if (cdrom_open_write(cdi))
-                               goto err;
+                               goto err_release;
                        if (!CDROM_CAN(CDC_RAM))
-                               goto err;
+                               goto err_release;
                        ret = 0;
                        cdi->media_written = 0;
                }
@@ -1026,6 +1026,8 @@ int cdrom_open(struct cdrom_device_info *cdi, struct inode *ip, struct file *fp)
            not be mounting, but opening with O_NONBLOCK */
        check_disk_change(ip->i_bdev);
        return 0;
+err_release:
+       cdi->ops->release(cdi);
 err:
        cdi->use_count--;
        return ret;
index f5b01c6d498e10c66efa1becb1cb06a9cd0fd265..fb919bfb2824ef715ddde72f7be31ce048c23e32 100644 (file)
@@ -41,9 +41,9 @@ obj-$(CONFIG_N_HDLC)          += n_hdlc.o
 obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
 obj-$(CONFIG_SX)               += sx.o generic_serial.o
 obj-$(CONFIG_RIO)              += rio/ generic_serial.o
-obj-$(CONFIG_HVC_DRIVER)       += hvc_console.o
 obj-$(CONFIG_HVC_CONSOLE)      += hvc_vio.o hvsi.o
 obj-$(CONFIG_HVC_RTAS)         += hvc_rtas.o
+obj-$(CONFIG_HVC_DRIVER)       += hvc_console.o
 obj-$(CONFIG_RAW_DRIVER)       += raw.o
 obj-$(CONFIG_SGI_SNSC)         += snsc.o snsc_event.o
 obj-$(CONFIG_MMTIMER)          += mmtimer.o
index 0b9cf9c59a213af2aa42f3f9eec0332ee823520f..7c88c060a9e6b3ab908660b6676aef4423488a35 100644 (file)
@@ -86,7 +86,7 @@ config AGP_NVIDIA
 
 config AGP_SIS
        tristate "SiS chipset support"
-       depends on AGP && X86_32
+       depends on AGP
        help
          This option gives you AGP support for the GLX component of
          X on Silicon Integrated Systems [SiS] chipsets.
index 2b5838e64751a3bc3cb0ba005deba67b88cbfdc9..b4e00a343da9162e559f305794ae31cc99842285 100644 (file)
@@ -46,12 +46,6 @@ struct vm_operations_struct alpha_core_agp_vm_ops = {
 };
 
 
-static int alpha_core_agp_nop(void)
-{
-       /* just return success */
-       return 0;
-}
-
 static int alpha_core_agp_fetch_size(void)
 {
        return alpha_core_agp_sizes[0].size;
@@ -120,6 +114,11 @@ static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start,
        return status;
 }
 
+static int alpha_core_agp_create_free_gatt_table(struct agp_bridge_data *a)
+{
+       return 0;
+}
+
 struct agp_bridge_driver alpha_core_agp_driver = {
        .owner                  = THIS_MODULE,
        .aperture_sizes         = alpha_core_agp_sizes,
@@ -135,8 +134,8 @@ struct agp_bridge_driver alpha_core_agp_driver = {
        .tlb_flush              = alpha_core_agp_tlbflush,
        .mask_memory            = agp_generic_mask_memory,
        .cache_flush            = global_cache_flush,
-       .create_gatt_table      = alpha_core_agp_nop,
-       .free_gatt_table        = alpha_core_agp_nop,
+       .create_gatt_table      = alpha_core_agp_create_free_gatt_table,
+       .free_gatt_table        = alpha_core_agp_create_free_gatt_table,
        .insert_memory          = alpha_core_agp_insert_memory,
        .remove_memory          = alpha_core_agp_remove_memory,
        .alloc_by_type          = agp_generic_alloc_by_type,
index 36517d4d1ad9da6fdd80dd2f1180a7269abd7437..ac3c33a2e37d7b7ed7d1b3da0c7428f0e448dec8 100644 (file)
@@ -617,6 +617,9 @@ static int agp_amd64_resume(struct pci_dev *pdev)
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
 
+       if (pdev->vendor == PCI_VENDOR_ID_NVIDIA)
+               nforce3_agp_init(pdev);
+
        return amd_8151_configure();
 }
 
index 4e1891e2c035c97336534bdd9a8ec6b1214d6a37..a92ab53a13703bc4c7df95380613ab2062166503 100644 (file)
@@ -809,12 +809,10 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
                                case U32_APER_SIZE:
                                        bridge->current_size = A_IDX32(bridge);
                                        break;
-                                       /* This case will never really happen. */
+                               /* These cases will never really happen. */
                                case FIXED_APER_SIZE:
                                case LVL2_APER_SIZE:
                                default:
-                                       bridge->current_size =
-                                           bridge->current_size;
                                        break;
                                }
                                temp = bridge->current_size;
index bddcae54b16d08d4cfff5ab427c347c9b4f07476..61ac3809f997cbbb9932a8eb3f0428d63195a2d4 100644 (file)
@@ -736,7 +736,7 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
 static int intel_i915_fetch_size(void)
 {
        struct aper_size_info_fixed *values;
-       u32 temp, offset = 0;
+       u32 temp, offset;
 
 #define I915_256MB_ADDRESS_MASK (1<<27)
 
index 9846defbddb4def2f2ba71a750d48036e5b6ceef..1de1b12043bf09f92db60863ce316780cf3422ed 100644 (file)
@@ -329,7 +329,7 @@ static int agp_uninorth_suspend(struct pci_dev *pdev)
        /* turn off AGP on the bridge */
        agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
        pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
-       bridge->dev_private_data = (void *)cmd;
+       bridge->dev_private_data = (void *)(long)cmd;
        if (cmd & PCI_AGP_COMMAND_AGP) {
                printk("uninorth-agp: disabling AGP on bridge %s\n",
                                pci_name(pdev));
@@ -351,7 +351,7 @@ static int agp_uninorth_resume(struct pci_dev *pdev)
        if (bridge == NULL)
                return -ENODEV;
 
-       command = (u32)bridge->dev_private_data;
+       command = (long)bridge->dev_private_data;
        bridge->dev_private_data = NULL;
        if (!(command & PCI_AGP_COMMAND_AGP))
                return 0;
index 97b0a890ba7f828310342e585e866af36e101136..b8ec25d174787d56c4df0d07294a76f7a4328ff5 100644 (file)
@@ -345,6 +345,12 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata =
                .chipset_name   = "PT880",
        },
 
+       /* PT880 Ultra */
+       {
+               .device_id      = PCI_DEVICE_ID_VIA_PT880ULTRA,
+               .chipset_name   = "PT880 Ultra",
+       },
+
        /* PT890 */
        {
                .device_id      = PCI_DEVICE_ID_VIA_8783_0,
@@ -511,6 +517,7 @@ static struct pci_device_id agp_via_pci_table[] = {
        ID(PCI_DEVICE_ID_VIA_8763_0),
        ID(PCI_DEVICE_ID_VIA_8378_0),
        ID(PCI_DEVICE_ID_VIA_PT880),
+       ID(PCI_DEVICE_ID_VIA_PT880ULTRA),
        ID(PCI_DEVICE_ID_VIA_8783_0),
        ID(PCI_DEVICE_ID_VIA_PX8X0_0),
        ID(PCI_DEVICE_ID_VIA_3269_0),
index b36eef0e9d199ff2751ddba5b77d812bacf489cb..02a7dd7a8a55571cbf261e63a9dcdf3cf7fbb969 100644 (file)
@@ -1184,20 +1184,20 @@ static void port_outl(struct si_sm_io *io, unsigned int offset,
 static void port_cleanup(struct smi_info *info)
 {
        unsigned int addr = info->io.addr_data;
-       int          mapsize;
+       int          idx;
 
        if (addr) {
-               mapsize = ((info->io_size * info->io.regspacing)
-                          - (info->io.regspacing - info->io.regsize));
-
-               release_region (addr, mapsize);
+               for (idx = 0; idx < info->io_size; idx++) {
+                       release_region(addr + idx * info->io.regspacing,
+                                      info->io.regsize);
+               }
        }
 }
 
 static int port_setup(struct smi_info *info)
 {
        unsigned int addr = info->io.addr_data;
-       int          mapsize;
+       int          idx;
 
        if (!addr)
                return -ENODEV;
@@ -1225,16 +1225,22 @@ static int port_setup(struct smi_info *info)
                return -EINVAL;
        }
 
-       /* Calculate the total amount of memory to claim.  This is an
-        * unusual looking calculation, but it avoids claiming any
-        * more memory than it has to.  It will claim everything
-        * between the first address to the end of the last full
-        * register. */
-       mapsize = ((info->io_size * info->io.regspacing)
-                  - (info->io.regspacing - info->io.regsize));
-
-       if (request_region(addr, mapsize, DEVICE_NAME) == NULL)
-               return -EIO;
+       /* Some BIOSes reserve disjoint I/O regions in their ACPI
+        * tables.  This causes problems when trying to register the
+        * entire I/O region.  Therefore we must register each I/O
+        * port separately.
+        */
+       for (idx = 0; idx < info->io_size; idx++) {
+               if (request_region(addr + idx * info->io.regspacing,
+                                  info->io.regsize, DEVICE_NAME) == NULL) {
+                       /* Undo allocations */
+                       while (idx--) {
+                               release_region(addr + idx * info->io.regspacing,
+                                              info->io.regsize);
+                       }
+                       return -EIO;
+               }
+       }
        return 0;
 }
 
index ede365d05387087ba4110a9f97fc74ba6c1971ef..b9371d5bf7906b48d4b340c5a8756c3fa132f516 100644 (file)
@@ -1384,8 +1384,10 @@ do_it_again:
                 * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
                 * we won't get any more characters.
                 */
-               if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)
+               if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) {
+                       n_tty_set_room(tty);
                        check_unthrottle(tty);
+               }
 
                if (b - buf >= minimum)
                        break;
index 128b2632512d07f693d5925ce97791943cf9e3dd..eab5394da66647fe3f86f6d836646cf144f6db79 100644 (file)
@@ -149,7 +149,7 @@ struct cm4000_dev {
 #define        ZERO_DEV(dev)                                           \
        memset(&dev->atr_csum,0,                                \
                sizeof(struct cm4000_dev) -                     \
-               /*link*/ sizeof(struct pcmcia_device) -         \
+               /*link*/ sizeof(struct pcmcia_device *) -       \
                /*node*/ sizeof(dev_node_t) -                   \
                /*atr*/ MAX_ATR*sizeof(char) -                  \
                /*rbuf*/ 512*sizeof(char) -                     \
index e45f0d3d12de5427cf708585d08e3c615d8e087e..a611972024e65942edb58b23d8d176ec6ae456cb 100644 (file)
@@ -105,6 +105,12 @@ static const char* tcpa_event_type_strings[] = {
        "Non-Host Info"
 };
 
+struct tcpa_pc_event {
+       u32 event_id;
+       u32 event_size;
+       u8 event_data[0];
+};
+
 enum tcpa_pc_event_ids {
        SMBIOS = 1,
        BIS_CERT,
@@ -114,14 +120,15 @@ enum tcpa_pc_event_ids {
        NVRAM,
        OPTION_ROM_EXEC,
        OPTION_ROM_CONFIG,
-       OPTION_ROM_MICROCODE,
+       OPTION_ROM_MICROCODE = 10,
        S_CRTM_VERSION,
        S_CRTM_CONTENTS,
        POST_CONTENTS,
+       HOST_TABLE_OF_DEVICES,
 };
 
 static const char* tcpa_pc_event_id_strings[] = {
-       ""
+       "",
        "SMBIOS",
        "BIS Certificate",
        "POST BIOS ",
@@ -130,11 +137,12 @@ static const char* tcpa_pc_event_id_strings[] = {
        "NVRAM",
        "Option ROM",
        "Option ROM config",
-       "Option ROM microcode",
+       "",
+       "Option ROM microcode ",
        "S-CRTM Version",
-       "S-CRTM Contents",
-       "S-CRTM POST Contents",
-       "POST Contents",
+       "S-CRTM Contents ",
+       "POST Contents ",
+       "Table of Devices",
 };
 
 /* returns pointer to start of pos. entry of tcg log */
@@ -206,7 +214,7 @@ static int get_event_name(char *dest, struct tcpa_event *event,
        const char *name = "";
        char data[40] = "";
        int i, n_len = 0, d_len = 0;
-       u32 event_id;
+       struct tcpa_pc_event *pc_event;
 
        switch(event->event_type) {
        case PREBOOT:
@@ -235,31 +243,32 @@ static int get_event_name(char *dest, struct tcpa_event *event,
                }
                break;
        case EVENT_TAG:
-               event_id = be32_to_cpu(*((u32 *)event_entry));
+               pc_event = (struct tcpa_pc_event *)event_entry;
 
                /* ToDo Row data -> Base64 */
 
-               switch (event_id) {
+               switch (pc_event->event_id) {
                case SMBIOS:
                case BIS_CERT:
                case CMOS:
                case NVRAM:
                case OPTION_ROM_EXEC:
                case OPTION_ROM_CONFIG:
-               case OPTION_ROM_MICROCODE:
                case S_CRTM_VERSION:
-               case S_CRTM_CONTENTS:
-               case POST_CONTENTS:
-                       name = tcpa_pc_event_id_strings[event_id];
+                       name = tcpa_pc_event_id_strings[pc_event->event_id];
                        n_len = strlen(name);
                        break;
+               /* hash data */
                case POST_BIOS_ROM:
                case ESCD:
-                       name = tcpa_pc_event_id_strings[event_id];
+               case OPTION_ROM_MICROCODE:
+               case S_CRTM_CONTENTS:
+               case POST_CONTENTS:
+                       name = tcpa_pc_event_id_strings[pc_event->event_id];
                        n_len = strlen(name);
                        for (i = 0; i < 20; i++)
-                               d_len += sprintf(data, "%02x",
-                                               event_entry[8 + i]);
+                               d_len += sprintf(&data[2*i], "%02x",
+                                               pc_event->event_data[i]);
                        break;
                default:
                        break;
@@ -275,53 +284,13 @@ static int get_event_name(char *dest, struct tcpa_event *event,
 
 static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
 {
+       struct tcpa_event *event = v;
+       char *data = v;
+       int i;
 
-       char *eventname;
-       char data[4];
-       u32 help;
-       int i, len;
-       struct tcpa_event *event = (struct tcpa_event *) v;
-       unsigned char *event_entry =
-           (unsigned char *) (v + sizeof(struct tcpa_event));
-
-       eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
-       if (!eventname) {
-               printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
-                      __func__);
-               return -ENOMEM;
-       }
-
-       /* 1st: PCR used is in little-endian format (4 bytes) */
-       help = le32_to_cpu(event->pcr_index);
-       memcpy(data, &help, 4);
-       for (i = 0; i < 4; i++)
-               seq_putc(m, data[i]);
-
-       /* 2nd: SHA1 (20 bytes) */
-       for (i = 0; i < 20; i++)
-               seq_putc(m, event->pcr_value[i]);
-
-       /* 3rd: event type identifier (4 bytes) */
-       help = le32_to_cpu(event->event_type);
-       memcpy(data, &help, 4);
-       for (i = 0; i < 4; i++)
+       for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
                seq_putc(m, data[i]);
 
-       len = 0;
-
-       len += get_event_name(eventname, event, event_entry);
-
-       /* 4th:  filename <= 255 + \'0' delimiter */
-       if (len > TCG_EVENT_NAME_LEN_MAX)
-               len = TCG_EVENT_NAME_LEN_MAX;
-
-       for (i = 0; i < len; i++)
-               seq_putc(m, eventname[i]);
-
-       /* 5th: delimiter */
-       seq_putc(m, '\0');
-
-       kfree(eventname);
        return 0;
 }
 
index f621168f38aec754a418cf4390d9460506a08dec..8ea70625f7ea08bbf2714933cf2e58acd1da44bf 100644 (file)
@@ -457,10 +457,6 @@ static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
        }
 
        vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
-       if ((vendor & 0xFFFF) == 0xFFFF) {
-               rc = -ENODEV;
-               goto out_err;
-       }
 
        /* Default timeouts */
        chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
index acc5d47844eb49a53578f688949f04e039c04962..6c94879e0b99b6f6a369d69a188b347436abe550 100644 (file)
@@ -3238,14 +3238,6 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
        }
 }
 
-int is_console_suspend_safe(void)
-{
-       /* It is unsafe to suspend devices while X has control of the
-        * hardware. Make sure we are running on a kernel-controlled console.
-        */
-       return vc_cons[fg_console].d->vc_mode == KD_TEXT;
-}
-
 /*
  *     Visible symbols for modules
  */
index 9f2f00d82917a748fb021cffcbac4a274e1434a9..05f8ce2cfb4ab77a950a54371c8559b7fa17ef49 100644 (file)
@@ -127,7 +127,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
 
        if (found) {
                cn_queue_free_callback(cbq);
-               atomic_dec_and_test(&dev->refcnt);
+               atomic_dec(&dev->refcnt);
        }
 }
 
index 29b2fa5534ae3221017a49517a5017e56c328b4b..44d1eca83a7250748bf27c637998c3c2973f9657 100644 (file)
@@ -257,7 +257,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
                if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
                        if ((policy) && (policy->cpu == freqs->cpu) &&
                            (policy->cur) && (policy->cur != freqs->old)) {
-                               dprintk(KERN_WARNING "Warning: CPU frequency is"
+                               dprintk("Warning: CPU frequency is"
                                        " %u, cpufreq assumed %u kHz.\n",
                                        freqs->old, policy->cur);
                                freqs->old = policy->cur;
@@ -874,7 +874,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
 {
        struct cpufreq_freqs freqs;
 
-       dprintk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing "
+       dprintk("Warning: CPU frequency out of sync: cpufreq and timing "
               "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
 
        freqs.cpu = cpu;
@@ -1006,7 +1006,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
                struct cpufreq_freqs freqs;
 
                if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
-                       dprintk(KERN_DEBUG "Warning: CPU frequency is %u, "
+                       dprintk("Warning: CPU frequency is %u, "
                               "cpufreq assumed %u kHz.\n",
                               cur_freq, cpu_policy->cur);
 
@@ -1087,7 +1087,7 @@ static int cpufreq_resume(struct sys_device * sysdev)
                        struct cpufreq_freqs freqs;
 
                        if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
-                               dprintk(KERN_WARNING "Warning: CPU frequency"
+                               dprintk("Warning: CPU frequency"
                                       "is %u, cpufreq assumed %u kHz.\n",
                                       cur_freq, cpu_policy->cur);
 
index 9694b6ed3268edfe333214dbc71712c5f28e0fc8..c576c0b3f452629560fd2567a1bc5735011daf92 100644 (file)
@@ -74,7 +74,7 @@ static ssize_t
 show_total_trans(struct cpufreq_policy *policy, char *buf)
 {
        struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
-       if(!stat)
+       if (!stat)
                return 0;
        return sprintf(buf, "%d\n",
                        cpufreq_stats_table[stat->cpu]->total_trans);
@@ -86,7 +86,7 @@ show_time_in_state(struct cpufreq_policy *policy, char *buf)
        ssize_t len = 0;
        int i;
        struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
-       if(!stat)
+       if (!stat)
                return 0;
        cpufreq_stats_update(stat->cpu);
        for (i = 0; i < stat->state_num; i++) {
@@ -104,7 +104,7 @@ show_trans_table(struct cpufreq_policy *policy, char *buf)
        int i, j;
 
        struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
-       if(!stat)
+       if (!stat)
                return 0;
        cpufreq_stats_update(stat->cpu);
        len += snprintf(buf + len, PAGE_SIZE - len, "   From  :    To\n");
index a4818ce889195d81ba5e70e0a19582410e8ac716..551f4ccf87fd9eba99657b713250dd23c5723ad3 100644 (file)
@@ -20,7 +20,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
 {
        unsigned int min_freq = ~0;
        unsigned int max_freq = 0;
-       unsigned int i = 0;
+       unsigned int i;
 
        for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
                unsigned int freq = table[i].frequency;
@@ -51,7 +51,7 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table)
 {
        unsigned int next_larger = ~0;
-       unsigned int i = 0;
+       unsigned int i;
        unsigned int count = 0;
 
        dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu);
@@ -91,20 +91,24 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
                                   unsigned int relation,
                                   unsigned int *index)
 {
-       struct cpufreq_frequency_table optimal = { .index = ~0, };
-       struct cpufreq_frequency_table suboptimal = { .index = ~0, };
+       struct cpufreq_frequency_table optimal = {
+               .index = ~0,
+               .frequency = 0,
+       };
+       struct cpufreq_frequency_table suboptimal = {
+               .index = ~0,
+               .frequency = 0,
+       };
        unsigned int i;
 
        dprintk("request for target %u kHz (relation: %u) for cpu %u\n", target_freq, relation, policy->cpu);
 
        switch (relation) {
        case CPUFREQ_RELATION_H:
-               optimal.frequency = 0;
                suboptimal.frequency = ~0;
                break;
        case CPUFREQ_RELATION_L:
                optimal.frequency = ~0;
-               suboptimal.frequency = 0;
                break;
        }
 
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
new file mode 100644 (file)
index 0000000..30d021d
--- /dev/null
@@ -0,0 +1,34 @@
+#
+# DMA engine configuration
+#
+
+menu "DMA Engine support"
+
+config DMA_ENGINE
+       bool "Support for DMA engines"
+       ---help---
+         DMA engines offload copy operations from the CPU to dedicated
+         hardware, allowing the copies to happen asynchronously.
+
+comment "DMA Clients"
+
+config NET_DMA
+       bool "Network: TCP receive copy offload"
+       depends on DMA_ENGINE && NET
+       default y
+       ---help---
+         This enables the use of DMA engines in the network stack to
+         offload receive copy-to-user operations, freeing CPU cycles.
+         Since this is the main user of the DMA engine, it should be enabled;
+         say Y here.
+
+comment "DMA Devices"
+
+config INTEL_IOATDMA
+       tristate "Intel I/OAT DMA support"
+       depends on DMA_ENGINE && PCI
+       default m
+       ---help---
+         Enable support for the Intel(R) I/OAT DMA engine.
+
+endmenu
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
new file mode 100644 (file)
index 0000000..bdcfdbd
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
+obj-$(CONFIG_NET_DMA) += iovlock.o
+obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
new file mode 100644 (file)
index 0000000..5829143
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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 COPYING.
+ */
+
+/*
+ * This code implements the DMA subsystem. It provides a HW-neutral interface
+ * for other kernel code to use asynchronous memory copy capabilities,
+ * if present, and allows different HW DMA drivers to register as providing
+ * this capability.
+ *
+ * Due to the fact we are accelerating what is already a relatively fast
+ * operation, the code goes to great lengths to avoid additional overhead,
+ * such as locking.
+ *
+ * LOCKING:
+ *
+ * The subsystem keeps two global lists, dma_device_list and dma_client_list.
+ * Both of these are protected by a mutex, dma_list_mutex.
+ *
+ * Each device has a channels list, which runs unlocked but is never modified
+ * once the device is registered, it's just setup by the driver.
+ *
+ * Each client has a channels list, it's only modified under the client->lock
+ * and in an RCU callback, so it's safe to read under rcu_read_lock().
+ *
+ * Each device has a kref, which is initialized to 1 when the device is
+ * registered. A kref_put is done for each class_device registered.  When the
+ * class_device is released, the coresponding kref_put is done in the release
+ * method. Every time one of the device's channels is allocated to a client,
+ * a kref_get occurs.  When the channel is freed, the coresponding kref_put
+ * happens. The device's release function does a completion, so
+ * unregister_device does a remove event, class_device_unregister, a kref_put
+ * for the first reference, then waits on the completion for all other
+ * references to finish.
+ *
+ * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
+ * with a kref and a per_cpu local_t.  A single reference is set when on an
+ * ADDED event, and removed with a REMOVE event.  Net DMA client takes an
+ * extra reference per outstanding transaction.  The relase function does a
+ * kref_put on the device. -ChrisL
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/percpu.h>
+#include <linux/rcupdate.h>
+#include <linux/mutex.h>
+
+static DEFINE_MUTEX(dma_list_mutex);
+static LIST_HEAD(dma_device_list);
+static LIST_HEAD(dma_client_list);
+
+/* --- sysfs implementation --- */
+
+static ssize_t show_memcpy_count(struct class_device *cd, char *buf)
+{
+       struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+       unsigned long count = 0;
+       int i;
+
+       for_each_possible_cpu(i)
+               count += per_cpu_ptr(chan->local, i)->memcpy_count;
+
+       return sprintf(buf, "%lu\n", count);
+}
+
+static ssize_t show_bytes_transferred(struct class_device *cd, char *buf)
+{
+       struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+       unsigned long count = 0;
+       int i;
+
+       for_each_possible_cpu(i)
+               count += per_cpu_ptr(chan->local, i)->bytes_transferred;
+
+       return sprintf(buf, "%lu\n", count);
+}
+
+static ssize_t show_in_use(struct class_device *cd, char *buf)
+{
+       struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+
+       return sprintf(buf, "%d\n", (chan->client ? 1 : 0));
+}
+
+static struct class_device_attribute dma_class_attrs[] = {
+       __ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL),
+       __ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL),
+       __ATTR(in_use, S_IRUGO, show_in_use, NULL),
+       __ATTR_NULL
+};
+
+static void dma_async_device_cleanup(struct kref *kref);
+
+static void dma_class_dev_release(struct class_device *cd)
+{
+       struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+       kref_put(&chan->device->refcount, dma_async_device_cleanup);
+}
+
+static struct class dma_devclass = {
+       .name            = "dma",
+       .class_dev_attrs = dma_class_attrs,
+       .release = dma_class_dev_release,
+};
+
+/* --- client and device registration --- */
+
+/**
+ * dma_client_chan_alloc - try to allocate a channel to a client
+ * @client: &dma_client
+ *
+ * Called with dma_list_mutex held.
+ */
+static struct dma_chan *dma_client_chan_alloc(struct dma_client *client)
+{
+       struct dma_device *device;
+       struct dma_chan *chan;
+       unsigned long flags;
+       int desc;       /* allocated descriptor count */
+
+       /* Find a channel, any DMA engine will do */
+       list_for_each_entry(device, &dma_device_list, global_node) {
+               list_for_each_entry(chan, &device->channels, device_node) {
+                       if (chan->client)
+                               continue;
+
+                       desc = chan->device->device_alloc_chan_resources(chan);
+                       if (desc >= 0) {
+                               kref_get(&device->refcount);
+                               kref_init(&chan->refcount);
+                               chan->slow_ref = 0;
+                               INIT_RCU_HEAD(&chan->rcu);
+                               chan->client = client;
+                               spin_lock_irqsave(&client->lock, flags);
+                               list_add_tail_rcu(&chan->client_node,
+                                                 &client->channels);
+                               spin_unlock_irqrestore(&client->lock, flags);
+                               return chan;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+/**
+ * dma_client_chan_free - release a DMA channel
+ * @chan: &dma_chan
+ */
+void dma_chan_cleanup(struct kref *kref)
+{
+       struct dma_chan *chan = container_of(kref, struct dma_chan, refcount);
+       chan->device->device_free_chan_resources(chan);
+       chan->client = NULL;
+       kref_put(&chan->device->refcount, dma_async_device_cleanup);
+}
+
+static void dma_chan_free_rcu(struct rcu_head *rcu)
+{
+       struct dma_chan *chan = container_of(rcu, struct dma_chan, rcu);
+       int bias = 0x7FFFFFFF;
+       int i;
+       for_each_possible_cpu(i)
+               bias -= local_read(&per_cpu_ptr(chan->local, i)->refcount);
+       atomic_sub(bias, &chan->refcount.refcount);
+       kref_put(&chan->refcount, dma_chan_cleanup);
+}
+
+static void dma_client_chan_free(struct dma_chan *chan)
+{
+       atomic_add(0x7FFFFFFF, &chan->refcount.refcount);
+       chan->slow_ref = 1;
+       call_rcu(&chan->rcu, dma_chan_free_rcu);
+}
+
+/**
+ * dma_chans_rebalance - reallocate channels to clients
+ *
+ * When the number of DMA channel in the system changes,
+ * channels need to be rebalanced among clients
+ */
+static void dma_chans_rebalance(void)
+{
+       struct dma_client *client;
+       struct dma_chan *chan;
+       unsigned long flags;
+
+       mutex_lock(&dma_list_mutex);
+
+       list_for_each_entry(client, &dma_client_list, global_node) {
+               while (client->chans_desired > client->chan_count) {
+                       chan = dma_client_chan_alloc(client);
+                       if (!chan)
+                               break;
+                       client->chan_count++;
+                       client->event_callback(client,
+                                              chan,
+                                              DMA_RESOURCE_ADDED);
+               }
+               while (client->chans_desired < client->chan_count) {
+                       spin_lock_irqsave(&client->lock, flags);
+                       chan = list_entry(client->channels.next,
+                                         struct dma_chan,
+                                         client_node);
+                       list_del_rcu(&chan->client_node);
+                       spin_unlock_irqrestore(&client->lock, flags);
+                       client->chan_count--;
+                       client->event_callback(client,
+                                              chan,
+                                              DMA_RESOURCE_REMOVED);
+                       dma_client_chan_free(chan);
+               }
+       }
+
+       mutex_unlock(&dma_list_mutex);
+}
+
+/**
+ * dma_async_client_register - allocate and register a &dma_client
+ * @event_callback: callback for notification of channel addition/removal
+ */
+struct dma_client *dma_async_client_register(dma_event_callback event_callback)
+{
+       struct dma_client *client;
+
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (!client)
+               return NULL;
+
+       INIT_LIST_HEAD(&client->channels);
+       spin_lock_init(&client->lock);
+       client->chans_desired = 0;
+       client->chan_count = 0;
+       client->event_callback = event_callback;
+
+       mutex_lock(&dma_list_mutex);
+       list_add_tail(&client->global_node, &dma_client_list);
+       mutex_unlock(&dma_list_mutex);
+
+       return client;
+}
+
+/**
+ * dma_async_client_unregister - unregister a client and free the &dma_client
+ * @client:
+ *
+ * Force frees any allocated DMA channels, frees the &dma_client memory
+ */
+void dma_async_client_unregister(struct dma_client *client)
+{
+       struct dma_chan *chan;
+
+       if (!client)
+               return;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(chan, &client->channels, client_node)
+               dma_client_chan_free(chan);
+       rcu_read_unlock();
+
+       mutex_lock(&dma_list_mutex);
+       list_del(&client->global_node);
+       mutex_unlock(&dma_list_mutex);
+
+       kfree(client);
+       dma_chans_rebalance();
+}
+
+/**
+ * dma_async_client_chan_request - request DMA channels
+ * @client: &dma_client
+ * @number: count of DMA channels requested
+ *
+ * Clients call dma_async_client_chan_request() to specify how many
+ * DMA channels they need, 0 to free all currently allocated.
+ * The resulting allocations/frees are indicated to the client via the
+ * event callback.
+ */
+void dma_async_client_chan_request(struct dma_client *client,
+                       unsigned int number)
+{
+       client->chans_desired = number;
+       dma_chans_rebalance();
+}
+
+/**
+ * dma_async_device_register -
+ * @device: &dma_device
+ */
+int dma_async_device_register(struct dma_device *device)
+{
+       static int id;
+       int chancnt = 0;
+       struct dma_chan* chan;
+
+       if (!device)
+               return -ENODEV;
+
+       init_completion(&device->done);
+       kref_init(&device->refcount);
+       device->dev_id = id++;
+
+       /* represent channels in sysfs. Probably want devs too */
+       list_for_each_entry(chan, &device->channels, device_node) {
+               chan->local = alloc_percpu(typeof(*chan->local));
+               if (chan->local == NULL)
+                       continue;
+
+               chan->chan_id = chancnt++;
+               chan->class_dev.class = &dma_devclass;
+               chan->class_dev.dev = NULL;
+               snprintf(chan->class_dev.class_id, BUS_ID_SIZE, "dma%dchan%d",
+                        device->dev_id, chan->chan_id);
+
+               kref_get(&device->refcount);
+               class_device_register(&chan->class_dev);
+       }
+
+       mutex_lock(&dma_list_mutex);
+       list_add_tail(&device->global_node, &dma_device_list);
+       mutex_unlock(&dma_list_mutex);
+
+       dma_chans_rebalance();
+
+       return 0;
+}
+
+/**
+ * dma_async_device_unregister -
+ * @device: &dma_device
+ */
+static void dma_async_device_cleanup(struct kref *kref)
+{
+       struct dma_device *device;
+
+       device = container_of(kref, struct dma_device, refcount);
+       complete(&device->done);
+}
+
+void dma_async_device_unregister(struct dma_device* device)
+{
+       struct dma_chan *chan;
+       unsigned long flags;
+
+       mutex_lock(&dma_list_mutex);
+       list_del(&device->global_node);
+       mutex_unlock(&dma_list_mutex);
+
+       list_for_each_entry(chan, &device->channels, device_node) {
+               if (chan->client) {
+                       spin_lock_irqsave(&chan->client->lock, flags);
+                       list_del(&chan->client_node);
+                       chan->client->chan_count--;
+                       spin_unlock_irqrestore(&chan->client->lock, flags);
+                       chan->client->event_callback(chan->client,
+                                                    chan,
+                                                    DMA_RESOURCE_REMOVED);
+                       dma_client_chan_free(chan);
+               }
+               class_device_unregister(&chan->class_dev);
+       }
+       dma_chans_rebalance();
+
+       kref_put(&device->refcount, dma_async_device_cleanup);
+       wait_for_completion(&device->done);
+}
+
+static int __init dma_bus_init(void)
+{
+       mutex_init(&dma_list_mutex);
+       return class_register(&dma_devclass);
+}
+
+subsys_initcall(dma_bus_init);
+
+EXPORT_SYMBOL(dma_async_client_register);
+EXPORT_SYMBOL(dma_async_client_unregister);
+EXPORT_SYMBOL(dma_async_client_chan_request);
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
+EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
+EXPORT_SYMBOL(dma_async_memcpy_complete);
+EXPORT_SYMBOL(dma_async_memcpy_issue_pending);
+EXPORT_SYMBOL(dma_async_device_register);
+EXPORT_SYMBOL(dma_async_device_unregister);
+EXPORT_SYMBOL(dma_chan_cleanup);
diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c
new file mode 100644 (file)
index 0000000..0fdf7fb
--- /dev/null
@@ -0,0 +1,840 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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 COPYING.
+ */
+
+/*
+ * This driver supports an Intel I/OAT DMA engine, which does asynchronous
+ * copy operations.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include "ioatdma.h"
+#include "ioatdma_io.h"
+#include "ioatdma_registers.h"
+#include "ioatdma_hw.h"
+
+#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
+#define to_ioat_device(dev) container_of(dev, struct ioat_device, common)
+#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
+
+/* internal functions */
+static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void __devexit ioat_remove(struct pci_dev *pdev);
+
+static int enumerate_dma_channels(struct ioat_device *device)
+{
+       u8 xfercap_scale;
+       u32 xfercap;
+       int i;
+       struct ioat_dma_chan *ioat_chan;
+
+       device->common.chancnt = ioatdma_read8(device, IOAT_CHANCNT_OFFSET);
+       xfercap_scale = ioatdma_read8(device, IOAT_XFERCAP_OFFSET);
+       xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
+
+       for (i = 0; i < device->common.chancnt; i++) {
+               ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
+               if (!ioat_chan) {
+                       device->common.chancnt = i;
+                       break;
+               }
+
+               ioat_chan->device = device;
+               ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));
+               ioat_chan->xfercap = xfercap;
+               spin_lock_init(&ioat_chan->cleanup_lock);
+               spin_lock_init(&ioat_chan->desc_lock);
+               INIT_LIST_HEAD(&ioat_chan->free_desc);
+               INIT_LIST_HEAD(&ioat_chan->used_desc);
+               /* This should be made common somewhere in dmaengine.c */
+               ioat_chan->common.device = &device->common;
+               ioat_chan->common.client = NULL;
+               list_add_tail(&ioat_chan->common.device_node,
+                             &device->common.channels);
+       }
+       return device->common.chancnt;
+}
+
+static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
+       struct ioat_dma_chan *ioat_chan,
+       int flags)
+{
+       struct ioat_dma_descriptor *desc;
+       struct ioat_desc_sw *desc_sw;
+       struct ioat_device *ioat_device;
+       dma_addr_t phys;
+
+       ioat_device = to_ioat_device(ioat_chan->common.device);
+       desc = pci_pool_alloc(ioat_device->dma_pool, flags, &phys);
+       if (unlikely(!desc))
+               return NULL;
+
+       desc_sw = kzalloc(sizeof(*desc_sw), flags);
+       if (unlikely(!desc_sw)) {
+               pci_pool_free(ioat_device->dma_pool, desc, phys);
+               return NULL;
+       }
+
+       memset(desc, 0, sizeof(*desc));
+       desc_sw->hw = desc;
+       desc_sw->phys = phys;
+
+       return desc_sw;
+}
+
+#define INITIAL_IOAT_DESC_COUNT 128
+
+static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan);
+
+/* returns the actual number of allocated descriptors */
+static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+       struct ioat_desc_sw *desc = NULL;
+       u16 chanctrl;
+       u32 chanerr;
+       int i;
+       LIST_HEAD(tmp_list);
+
+       /*
+        * In-use bit automatically set by reading chanctrl
+        * If 0, we got it, if 1, someone else did
+        */
+       chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+       if (chanctrl & IOAT_CHANCTRL_CHANNEL_IN_USE)
+               return -EBUSY;
+
+        /* Setup register to interrupt and write completion status on error */
+       chanctrl = IOAT_CHANCTRL_CHANNEL_IN_USE |
+               IOAT_CHANCTRL_ERR_INT_EN |
+               IOAT_CHANCTRL_ANY_ERR_ABORT_EN |
+               IOAT_CHANCTRL_ERR_COMPLETION_EN;
+        ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+
+       chanerr = ioatdma_chan_read32(ioat_chan, IOAT_CHANERR_OFFSET);
+       if (chanerr) {
+               printk("IOAT: CHANERR = %x, clearing\n", chanerr);
+               ioatdma_chan_write32(ioat_chan, IOAT_CHANERR_OFFSET, chanerr);
+       }
+
+       /* Allocate descriptors */
+       for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) {
+               desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
+               if (!desc) {
+                       printk(KERN_ERR "IOAT: Only %d initial descriptors\n", i);
+                       break;
+               }
+               list_add_tail(&desc->node, &tmp_list);
+       }
+       spin_lock_bh(&ioat_chan->desc_lock);
+       list_splice(&tmp_list, &ioat_chan->free_desc);
+       spin_unlock_bh(&ioat_chan->desc_lock);
+
+       /* allocate a completion writeback area */
+       /* doing 2 32bit writes to mmio since 1 64b write doesn't work */
+       ioat_chan->completion_virt =
+               pci_pool_alloc(ioat_chan->device->completion_pool,
+                              GFP_KERNEL,
+                              &ioat_chan->completion_addr);
+       memset(ioat_chan->completion_virt, 0,
+              sizeof(*ioat_chan->completion_virt));
+       ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_LOW,
+                      ((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF);
+       ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_HIGH,
+                      ((u64) ioat_chan->completion_addr) >> 32);
+
+       ioat_start_null_desc(ioat_chan);
+       return i;
+}
+
+static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);
+
+static void ioat_dma_free_chan_resources(struct dma_chan *chan)
+{
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+       struct ioat_device *ioat_device = to_ioat_device(chan->device);
+       struct ioat_desc_sw *desc, *_desc;
+       u16 chanctrl;
+       int in_use_descs = 0;
+
+       ioat_dma_memcpy_cleanup(ioat_chan);
+
+       ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET);
+
+       spin_lock_bh(&ioat_chan->desc_lock);
+       list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
+               in_use_descs++;
+               list_del(&desc->node);
+               pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+               kfree(desc);
+       }
+       list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) {
+               list_del(&desc->node);
+               pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+               kfree(desc);
+       }
+       spin_unlock_bh(&ioat_chan->desc_lock);
+
+       pci_pool_free(ioat_device->completion_pool,
+                     ioat_chan->completion_virt,
+                     ioat_chan->completion_addr);
+
+       /* one is ok since we left it on there on purpose */
+       if (in_use_descs > 1)
+               printk(KERN_ERR "IOAT: Freeing %d in use descriptors!\n",
+                       in_use_descs - 1);
+
+       ioat_chan->last_completion = ioat_chan->completion_addr = 0;
+
+       /* Tell hw the chan is free */
+       chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+       chanctrl &= ~IOAT_CHANCTRL_CHANNEL_IN_USE;
+       ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+}
+
+/**
+ * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction
+ * @chan: IOAT DMA channel handle
+ * @dest: DMA destination address
+ * @src: DMA source address
+ * @len: transaction length in bytes
+ */
+
+static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan,
+                                       dma_addr_t dest,
+                                       dma_addr_t src,
+                                       size_t len)
+{
+       struct ioat_desc_sw *first;
+       struct ioat_desc_sw *prev;
+       struct ioat_desc_sw *new;
+       dma_cookie_t cookie;
+       LIST_HEAD(new_chain);
+       u32 copy;
+       size_t orig_len;
+       dma_addr_t orig_src, orig_dst;
+       unsigned int desc_count = 0;
+       unsigned int append = 0;
+
+       if (!ioat_chan || !dest || !src)
+               return -EFAULT;
+
+       if (!len)
+               return ioat_chan->common.cookie;
+
+       orig_len = len;
+       orig_src = src;
+       orig_dst = dest;
+
+       first = NULL;
+       prev = NULL;
+
+       spin_lock_bh(&ioat_chan->desc_lock);
+
+       while (len) {
+               if (!list_empty(&ioat_chan->free_desc)) {
+                       new = to_ioat_desc(ioat_chan->free_desc.next);
+                       list_del(&new->node);
+               } else {
+                       /* try to get another desc */
+                       new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);
+                       /* will this ever happen? */
+                       /* TODO add upper limit on these */
+                       BUG_ON(!new);
+               }
+
+               copy = min((u32) len, ioat_chan->xfercap);
+
+               new->hw->size = copy;
+               new->hw->ctl = 0;
+               new->hw->src_addr = src;
+               new->hw->dst_addr = dest;
+               new->cookie = 0;
+
+               /* chain together the physical address list for the HW */
+               if (!first)
+                       first = new;
+               else
+                       prev->hw->next = (u64) new->phys;
+
+               prev = new;
+
+               len  -= copy;
+               dest += copy;
+               src  += copy;
+
+               list_add_tail(&new->node, &new_chain);
+               desc_count++;
+       }
+       new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+       new->hw->next = 0;
+
+       /* cookie incr and addition to used_list must be atomic */
+
+       cookie = ioat_chan->common.cookie;
+       cookie++;
+       if (cookie < 0)
+               cookie = 1;
+       ioat_chan->common.cookie = new->cookie = cookie;
+
+       pci_unmap_addr_set(new, src, orig_src);
+       pci_unmap_addr_set(new, dst, orig_dst);
+       pci_unmap_len_set(new, src_len, orig_len);
+       pci_unmap_len_set(new, dst_len, orig_len);
+
+       /* write address into NextDescriptor field of last desc in chain */
+       to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys;
+       list_splice_init(&new_chain, ioat_chan->used_desc.prev);
+
+       ioat_chan->pending += desc_count;
+       if (ioat_chan->pending >= 20) {
+               append = 1;
+               ioat_chan->pending = 0;
+       }
+
+       spin_unlock_bh(&ioat_chan->desc_lock);
+
+       if (append)
+               ioatdma_chan_write8(ioat_chan,
+                                   IOAT_CHANCMD_OFFSET,
+                                   IOAT_CHANCMD_APPEND);
+       return cookie;
+}
+
+/**
+ * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs
+ * @chan: IOAT DMA channel handle
+ * @dest: DMA destination address
+ * @src: DMA source address
+ * @len: transaction length in bytes
+ */
+
+static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan,
+                                               void *dest,
+                                               void *src,
+                                               size_t len)
+{
+       dma_addr_t dest_addr;
+       dma_addr_t src_addr;
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+       dest_addr = pci_map_single(ioat_chan->device->pdev,
+               dest, len, PCI_DMA_FROMDEVICE);
+       src_addr = pci_map_single(ioat_chan->device->pdev,
+               src, len, PCI_DMA_TODEVICE);
+
+       return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+}
+
+/**
+ * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page
+ * @chan: IOAT DMA channel handle
+ * @page: pointer to the page to copy to
+ * @offset: offset into that page
+ * @src: DMA source address
+ * @len: transaction length in bytes
+ */
+
+static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan,
+                                              struct page *page,
+                                              unsigned int offset,
+                                              void *src,
+                                              size_t len)
+{
+       dma_addr_t dest_addr;
+       dma_addr_t src_addr;
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+       dest_addr = pci_map_page(ioat_chan->device->pdev,
+               page, offset, len, PCI_DMA_FROMDEVICE);
+       src_addr = pci_map_single(ioat_chan->device->pdev,
+               src, len, PCI_DMA_TODEVICE);
+
+       return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+}
+
+/**
+ * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages
+ * @chan: IOAT DMA channel handle
+ * @dest_pg: pointer to the page to copy to
+ * @dest_off: offset into that page
+ * @src_pg: pointer to the page to copy from
+ * @src_off: offset into that page
+ * @len: transaction length in bytes. This is guaranteed to not make a copy
+ *      across a page boundary.
+ */
+
+static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan,
+                                             struct page *dest_pg,
+                                             unsigned int dest_off,
+                                             struct page *src_pg,
+                                             unsigned int src_off,
+                                             size_t len)
+{
+       dma_addr_t dest_addr;
+       dma_addr_t src_addr;
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+       dest_addr = pci_map_page(ioat_chan->device->pdev,
+               dest_pg, dest_off, len, PCI_DMA_FROMDEVICE);
+       src_addr = pci_map_page(ioat_chan->device->pdev,
+               src_pg, src_off, len, PCI_DMA_TODEVICE);
+
+       return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+}
+
+/**
+ * ioat_dma_memcpy_issue_pending - push potentially unrecognoized appended descriptors to hw
+ * @chan: DMA channel handle
+ */
+
+static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan)
+{
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+       if (ioat_chan->pending != 0) {
+               ioat_chan->pending = 0;
+               ioatdma_chan_write8(ioat_chan,
+                                   IOAT_CHANCMD_OFFSET,
+                                   IOAT_CHANCMD_APPEND);
+       }
+}
+
+static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
+{
+       unsigned long phys_complete;
+       struct ioat_desc_sw *desc, *_desc;
+       dma_cookie_t cookie = 0;
+
+       prefetch(chan->completion_virt);
+
+       if (!spin_trylock(&chan->cleanup_lock))
+               return;
+
+       /* The completion writeback can happen at any time,
+          so reads by the driver need to be atomic operations
+          The descriptor physical addresses are limited to 32-bits
+          when the CPU can only do a 32-bit mov */
+
+#if (BITS_PER_LONG == 64)
+       phys_complete =
+       chan->completion_virt->full & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
+#else
+       phys_complete = chan->completion_virt->low & IOAT_LOW_COMPLETION_MASK;
+#endif
+
+       if ((chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) ==
+               IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) {
+               printk("IOAT: Channel halted, chanerr = %x\n",
+                       ioatdma_chan_read32(chan, IOAT_CHANERR_OFFSET));
+
+               /* TODO do something to salvage the situation */
+       }
+
+       if (phys_complete == chan->last_completion) {
+               spin_unlock(&chan->cleanup_lock);
+               return;
+       }
+
+       spin_lock_bh(&chan->desc_lock);
+       list_for_each_entry_safe(desc, _desc, &chan->used_desc, node) {
+
+               /*
+                * Incoming DMA requests may use multiple descriptors, due to
+                * exceeding xfercap, perhaps. If so, only the last one will
+                * have a cookie, and require unmapping.
+                */
+               if (desc->cookie) {
+                       cookie = desc->cookie;
+
+                       /* yes we are unmapping both _page and _single alloc'd
+                          regions with unmap_page. Is this *really* that bad?
+                       */
+                       pci_unmap_page(chan->device->pdev,
+                                       pci_unmap_addr(desc, dst),
+                                       pci_unmap_len(desc, dst_len),
+                                       PCI_DMA_FROMDEVICE);
+                       pci_unmap_page(chan->device->pdev,
+                                       pci_unmap_addr(desc, src),
+                                       pci_unmap_len(desc, src_len),
+                                       PCI_DMA_TODEVICE);
+               }
+
+               if (desc->phys != phys_complete) {
+                       /* a completed entry, but not the last, so cleanup */
+                       list_del(&desc->node);
+                       list_add_tail(&desc->node, &chan->free_desc);
+               } else {
+                       /* last used desc. Do not remove, so we can append from
+                          it, but don't look at it next time, either */
+                       desc->cookie = 0;
+
+                       /* TODO check status bits? */
+                       break;
+               }
+       }
+
+       spin_unlock_bh(&chan->desc_lock);
+
+       chan->last_completion = phys_complete;
+       if (cookie != 0)
+               chan->completed_cookie = cookie;
+
+       spin_unlock(&chan->cleanup_lock);
+}
+
+/**
+ * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
+ * @chan: IOAT DMA channel handle
+ * @cookie: DMA transaction identifier
+ */
+
+static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,
+                                            dma_cookie_t cookie,
+                                            dma_cookie_t *done,
+                                            dma_cookie_t *used)
+{
+       struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+       dma_cookie_t last_used;
+       dma_cookie_t last_complete;
+       enum dma_status ret;
+
+       last_used = chan->cookie;
+       last_complete = ioat_chan->completed_cookie;
+
+       if (done)
+               *done= last_complete;
+       if (used)
+               *used = last_used;
+
+       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       if (ret == DMA_SUCCESS)
+               return ret;
+
+       ioat_dma_memcpy_cleanup(ioat_chan);
+
+       last_used = chan->cookie;
+       last_complete = ioat_chan->completed_cookie;
+
+       if (done)
+               *done= last_complete;
+       if (used)
+               *used = last_used;
+
+       return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+/* PCI API */
+
+static struct pci_device_id ioat_pci_tbl[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
+       { 0, }
+};
+
+static struct pci_driver ioat_pci_drv = {
+       .name   = "ioatdma",
+       .id_table = ioat_pci_tbl,
+       .probe  = ioat_probe,
+       .remove = __devexit_p(ioat_remove),
+};
+
+static irqreturn_t ioat_do_interrupt(int irq, void *data, struct pt_regs *regs)
+{
+       struct ioat_device *instance = data;
+       unsigned long attnstatus;
+       u8 intrctrl;
+
+       intrctrl = ioatdma_read8(instance, IOAT_INTRCTRL_OFFSET);
+
+       if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN))
+               return IRQ_NONE;
+
+       if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) {
+               ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+               return IRQ_NONE;
+       }
+
+       attnstatus = ioatdma_read32(instance, IOAT_ATTNSTATUS_OFFSET);
+
+       printk(KERN_ERR "ioatdma error: interrupt! status %lx\n", attnstatus);
+
+       ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+       return IRQ_HANDLED;
+}
+
+static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan)
+{
+       struct ioat_desc_sw *desc;
+
+       spin_lock_bh(&ioat_chan->desc_lock);
+
+       if (!list_empty(&ioat_chan->free_desc)) {
+               desc = to_ioat_desc(ioat_chan->free_desc.next);
+               list_del(&desc->node);
+       } else {
+               /* try to get another desc */
+               spin_unlock_bh(&ioat_chan->desc_lock);
+               desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
+               spin_lock_bh(&ioat_chan->desc_lock);
+               /* will this ever happen? */
+               BUG_ON(!desc);
+       }
+
+       desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
+       desc->hw->next = 0;
+
+       list_add_tail(&desc->node, &ioat_chan->used_desc);
+       spin_unlock_bh(&ioat_chan->desc_lock);
+
+#if (BITS_PER_LONG == 64)
+       ioatdma_chan_write64(ioat_chan, IOAT_CHAINADDR_OFFSET, desc->phys);
+#else
+       ioatdma_chan_write32(ioat_chan,
+                            IOAT_CHAINADDR_OFFSET_LOW,
+                            (u32) desc->phys);
+       ioatdma_chan_write32(ioat_chan, IOAT_CHAINADDR_OFFSET_HIGH, 0);
+#endif
+       ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_START);
+}
+
+/*
+ * Perform a IOAT transaction to verify the HW works.
+ */
+#define IOAT_TEST_SIZE 2000
+
+static int ioat_self_test(struct ioat_device *device)
+{
+       int i;
+       u8 *src;
+       u8 *dest;
+       struct dma_chan *dma_chan;
+       dma_cookie_t cookie;
+       int err = 0;
+
+       src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL);
+       if (!src)
+               return -ENOMEM;
+       dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL);
+       if (!dest) {
+               kfree(src);
+               return -ENOMEM;
+       }
+
+       /* Fill in src buffer */
+       for (i = 0; i < IOAT_TEST_SIZE; i++)
+               src[i] = (u8)i;
+
+       /* Start copy, using first DMA channel */
+       dma_chan = container_of(device->common.channels.next,
+                               struct dma_chan,
+                               device_node);
+       if (ioat_dma_alloc_chan_resources(dma_chan) < 1) {
+               err = -ENODEV;
+               goto out;
+       }
+
+       cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE);
+       ioat_dma_memcpy_issue_pending(dma_chan);
+       msleep(1);
+
+       if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+               printk(KERN_ERR "ioatdma: Self-test copy timed out, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+       if (memcmp(src, dest, IOAT_TEST_SIZE)) {
+               printk(KERN_ERR "ioatdma: Self-test copy failed compare, disabling\n");
+               err = -ENODEV;
+               goto free_resources;
+       }
+
+free_resources:
+       ioat_dma_free_chan_resources(dma_chan);
+out:
+       kfree(src);
+       kfree(dest);
+       return err;
+}
+
+static int __devinit ioat_probe(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
+{
+       int err;
+       unsigned long mmio_start, mmio_len;
+       void *reg_base;
+       struct ioat_device *device;
+
+       err = pci_enable_device(pdev);
+       if (err)
+               goto err_enable_device;
+
+       err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+       if (err)
+               err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       if (err)
+               goto err_set_dma_mask;
+
+       err = pci_request_regions(pdev, ioat_pci_drv.name);
+       if (err)
+               goto err_request_regions;
+
+       mmio_start = pci_resource_start(pdev, 0);
+       mmio_len = pci_resource_len(pdev, 0);
+
+       reg_base = ioremap(mmio_start, mmio_len);
+       if (!reg_base) {
+               err = -ENOMEM;
+               goto err_ioremap;
+       }
+
+       device = kzalloc(sizeof(*device), GFP_KERNEL);
+       if (!device) {
+               err = -ENOMEM;
+               goto err_kzalloc;
+       }
+
+       /* DMA coherent memory pool for DMA descriptor allocations */
+       device->dma_pool = pci_pool_create("dma_desc_pool", pdev,
+               sizeof(struct ioat_dma_descriptor), 64, 0);
+       if (!device->dma_pool) {
+               err = -ENOMEM;
+               goto err_dma_pool;
+       }
+
+       device->completion_pool = pci_pool_create("completion_pool", pdev, sizeof(u64), SMP_CACHE_BYTES, SMP_CACHE_BYTES);
+       if (!device->completion_pool) {
+               err = -ENOMEM;
+               goto err_completion_pool;
+       }
+
+       device->pdev = pdev;
+       pci_set_drvdata(pdev, device);
+#ifdef CONFIG_PCI_MSI
+       if (pci_enable_msi(pdev) == 0) {
+               device->msi = 1;
+       } else {
+               device->msi = 0;
+       }
+#endif
+       err = request_irq(pdev->irq, &ioat_do_interrupt, SA_SHIRQ, "ioat",
+               device);
+       if (err)
+               goto err_irq;
+
+       device->reg_base = reg_base;
+
+       ioatdma_write8(device, IOAT_INTRCTRL_OFFSET, IOAT_INTRCTRL_MASTER_INT_EN);
+       pci_set_master(pdev);
+
+       INIT_LIST_HEAD(&device->common.channels);
+       enumerate_dma_channels(device);
+
+       device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources;
+       device->common.device_free_chan_resources = ioat_dma_free_chan_resources;
+       device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf;
+       device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg;
+       device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg;
+       device->common.device_memcpy_complete = ioat_dma_is_complete;
+       device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending;
+       printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n",
+               device->common.chancnt);
+
+       err = ioat_self_test(device);
+       if (err)
+               goto err_self_test;
+
+       dma_async_device_register(&device->common);
+
+       return 0;
+
+err_self_test:
+err_irq:
+       pci_pool_destroy(device->completion_pool);
+err_completion_pool:
+       pci_pool_destroy(device->dma_pool);
+err_dma_pool:
+       kfree(device);
+err_kzalloc:
+       iounmap(reg_base);
+err_ioremap:
+       pci_release_regions(pdev);
+err_request_regions:
+err_set_dma_mask:
+       pci_disable_device(pdev);
+err_enable_device:
+       return err;
+}
+
+static void __devexit ioat_remove(struct pci_dev *pdev)
+{
+       struct ioat_device *device;
+       struct dma_chan *chan, *_chan;
+       struct ioat_dma_chan *ioat_chan;
+
+       device = pci_get_drvdata(pdev);
+       dma_async_device_unregister(&device->common);
+
+       free_irq(device->pdev->irq, device);
+#ifdef CONFIG_PCI_MSI
+       if (device->msi)
+               pci_disable_msi(device->pdev);
+#endif
+       pci_pool_destroy(device->dma_pool);
+       pci_pool_destroy(device->completion_pool);
+       iounmap(device->reg_base);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       list_for_each_entry_safe(chan, _chan, &device->common.channels, device_node) {
+               ioat_chan = to_ioat_chan(chan);
+               list_del(&chan->device_node);
+               kfree(ioat_chan);
+       }
+       kfree(device);
+}
+
+/* MODULE API */
+MODULE_VERSION("1.7");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Intel Corporation");
+
+static int __init ioat_init_module(void)
+{
+       /* it's currently unsafe to unload this module */
+       /* if forced, worst case is that rmmod hangs */
+       if (THIS_MODULE != NULL)
+               THIS_MODULE->unsafe = 1;
+
+       return pci_module_init(&ioat_pci_drv);
+}
+
+module_init(ioat_init_module);
+
+static void __exit ioat_exit_module(void)
+{
+       pci_unregister_driver(&ioat_pci_drv);
+}
+
+module_exit(ioat_exit_module);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
new file mode 100644 (file)
index 0000000..a5d3b36
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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 COPYING.
+ */
+#ifndef IOATDMA_H
+#define IOATDMA_H
+
+#include <linux/dmaengine.h>
+#include "ioatdma_hw.h"
+#include <linux/init.h>
+#include <linux/dmapool.h>
+#include <linux/cache.h>
+#include <linux/pci_ids.h>
+
+#define IOAT_LOW_COMPLETION_MASK       0xffffffc0
+
+extern struct list_head dma_device_list;
+extern struct list_head dma_client_list;
+
+/**
+ * struct ioat_device - internal representation of a IOAT device
+ * @pdev: PCI-Express device
+ * @reg_base: MMIO register space base address
+ * @dma_pool: for allocating DMA descriptors
+ * @common: embedded struct dma_device
+ * @msi: Message Signaled Interrupt number
+ */
+
+struct ioat_device {
+       struct pci_dev *pdev;
+       void *reg_base;
+       struct pci_pool *dma_pool;
+       struct pci_pool *completion_pool;
+
+       struct dma_device common;
+       u8 msi;
+};
+
+/**
+ * struct ioat_dma_chan - internal representation of a DMA channel
+ * @device:
+ * @reg_base:
+ * @sw_in_use:
+ * @completion:
+ * @completion_low:
+ * @completion_high:
+ * @completed_cookie: last cookie seen completed on cleanup
+ * @cookie: value of last cookie given to client
+ * @last_completion:
+ * @xfercap:
+ * @desc_lock:
+ * @free_desc:
+ * @used_desc:
+ * @resource:
+ * @device_node:
+ */
+
+struct ioat_dma_chan {
+
+       void *reg_base;
+
+       dma_cookie_t completed_cookie;
+       unsigned long last_completion;
+
+       u32 xfercap;    /* XFERCAP register value expanded out */
+
+       spinlock_t cleanup_lock;
+       spinlock_t desc_lock;
+       struct list_head free_desc;
+       struct list_head used_desc;
+
+       int pending;
+
+       struct ioat_device *device;
+       struct dma_chan common;
+
+       dma_addr_t completion_addr;
+       union {
+               u64 full; /* HW completion writeback */
+               struct {
+                       u32 low;
+                       u32 high;
+               };
+       } *completion_virt;
+};
+
+/* wrapper around hardware descriptor format + additional software fields */
+
+/**
+ * struct ioat_desc_sw - wrapper around hardware descriptor
+ * @hw: hardware DMA descriptor
+ * @node:
+ * @cookie:
+ * @phys:
+ */
+
+struct ioat_desc_sw {
+       struct ioat_dma_descriptor *hw;
+       struct list_head node;
+       dma_cookie_t cookie;
+       dma_addr_t phys;
+       DECLARE_PCI_UNMAP_ADDR(src)
+       DECLARE_PCI_UNMAP_LEN(src_len)
+       DECLARE_PCI_UNMAP_ADDR(dst)
+       DECLARE_PCI_UNMAP_LEN(dst_len)
+};
+
+#endif /* IOATDMA_H */
+
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h
new file mode 100644 (file)
index 0000000..4d7a128
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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 COPYING.
+ */
+#ifndef _IOAT_HW_H_
+#define _IOAT_HW_H_
+
+/* PCI Configuration Space Values */
+#define IOAT_PCI_VID                   0x8086
+#define IOAT_PCI_DID                   0x1A38
+#define IOAT_PCI_RID                   0x00
+#define IOAT_PCI_SVID                  0x8086
+#define IOAT_PCI_SID                   0x8086
+#define IOAT_VER                       0x12    /* Version 1.2 */
+
+struct ioat_dma_descriptor {
+       uint32_t        size;
+       uint32_t        ctl;
+       uint64_t        src_addr;
+       uint64_t        dst_addr;
+       uint64_t        next;
+       uint64_t        rsv1;
+       uint64_t        rsv2;
+       uint64_t        user1;
+       uint64_t        user2;
+};
+
+#define IOAT_DMA_DESCRIPTOR_CTL_INT_GN 0x00000001
+#define IOAT_DMA_DESCRIPTOR_CTL_SRC_SN 0x00000002
+#define IOAT_DMA_DESCRIPTOR_CTL_DST_SN 0x00000004
+#define IOAT_DMA_DESCRIPTOR_CTL_CP_STS 0x00000008
+#define IOAT_DMA_DESCRIPTOR_CTL_FRAME  0x00000010
+#define IOAT_DMA_DESCRIPTOR_NUL                0x00000020
+#define IOAT_DMA_DESCRIPTOR_OPCODE     0xFF000000
+
+#endif
diff --git a/drivers/dma/ioatdma_io.h b/drivers/dma/ioatdma_io.h
new file mode 100644 (file)
index 0000000..c0b4bf6
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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 COPYING.
+ */
+#ifndef IOATDMA_IO_H
+#define IOATDMA_IO_H
+
+#include <asm/io.h>
+
+/*
+ * device and per-channel MMIO register read and write functions
+ * this is a lot of anoying inline functions, but it's typesafe
+ */
+
+static inline u8 ioatdma_read8(struct ioat_device *device,
+                               unsigned int offset)
+{
+       return readb(device->reg_base + offset);
+}
+
+static inline u16 ioatdma_read16(struct ioat_device *device,
+                                 unsigned int offset)
+{
+       return readw(device->reg_base + offset);
+}
+
+static inline u32 ioatdma_read32(struct ioat_device *device,
+                                 unsigned int offset)
+{
+       return readl(device->reg_base + offset);
+}
+
+static inline void ioatdma_write8(struct ioat_device *device,
+                                  unsigned int offset, u8 value)
+{
+       writeb(value, device->reg_base + offset);
+}
+
+static inline void ioatdma_write16(struct ioat_device *device,
+                                   unsigned int offset, u16 value)
+{
+       writew(value, device->reg_base + offset);
+}
+
+static inline void ioatdma_write32(struct ioat_device *device,
+                                   unsigned int offset, u32 value)
+{
+       writel(value, device->reg_base + offset);
+}
+
+static inline u8 ioatdma_chan_read8(struct ioat_dma_chan *chan,
+                                    unsigned int offset)
+{
+       return readb(chan->reg_base + offset);
+}
+
+static inline u16 ioatdma_chan_read16(struct ioat_dma_chan *chan,
+                                      unsigned int offset)
+{
+       return readw(chan->reg_base + offset);
+}
+
+static inline u32 ioatdma_chan_read32(struct ioat_dma_chan *chan,
+                                      unsigned int offset)
+{
+       return readl(chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write8(struct ioat_dma_chan *chan,
+                                       unsigned int offset, u8 value)
+{
+       writeb(value, chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write16(struct ioat_dma_chan *chan,
+                                        unsigned int offset, u16 value)
+{
+       writew(value, chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write32(struct ioat_dma_chan *chan,
+                                        unsigned int offset, u32 value)
+{
+       writel(value, chan->reg_base + offset);
+}
+
+#if (BITS_PER_LONG == 64)
+static inline u64 ioatdma_chan_read64(struct ioat_dma_chan *chan,
+                                      unsigned int offset)
+{
+       return readq(chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write64(struct ioat_dma_chan *chan,
+                                        unsigned int offset, u64 value)
+{
+       writeq(value, chan->reg_base + offset);
+}
+#endif
+
+#endif /* IOATDMA_IO_H */
+
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h
new file mode 100644 (file)
index 0000000..41a21ab
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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 COPYING.
+ */
+#ifndef _IOAT_REGISTERS_H_
+#define _IOAT_REGISTERS_H_
+
+
+/* MMIO Device Registers */
+#define IOAT_CHANCNT_OFFSET                    0x00    /*  8-bit */
+
+#define IOAT_XFERCAP_OFFSET                    0x01    /*  8-bit */
+#define IOAT_XFERCAP_4KB                       12
+#define IOAT_XFERCAP_8KB                       13
+#define IOAT_XFERCAP_16KB                      14
+#define IOAT_XFERCAP_32KB                      15
+#define IOAT_XFERCAP_32GB                      0
+
+#define IOAT_GENCTRL_OFFSET                    0x02    /*  8-bit */
+#define IOAT_GENCTRL_DEBUG_EN                  0x01
+
+#define IOAT_INTRCTRL_OFFSET                   0x03    /*  8-bit */
+#define IOAT_INTRCTRL_MASTER_INT_EN            0x01    /* Master Interrupt Enable */
+#define IOAT_INTRCTRL_INT_STATUS               0x02    /* ATTNSTATUS -or- Channel Int */
+#define IOAT_INTRCTRL_INT                      0x04    /* INT_STATUS -and- MASTER_INT_EN */
+
+#define IOAT_ATTNSTATUS_OFFSET                 0x04    /* Each bit is a channel */
+
+#define IOAT_VER_OFFSET                                0x08    /*  8-bit */
+#define IOAT_VER_MAJOR_MASK                    0xF0
+#define IOAT_VER_MINOR_MASK                    0x0F
+#define GET_IOAT_VER_MAJOR(x)                  ((x) & IOAT_VER_MAJOR_MASK)
+#define GET_IOAT_VER_MINOR(x)                  ((x) & IOAT_VER_MINOR_MASK)
+
+#define IOAT_PERPORTOFFSET_OFFSET              0x0A    /* 16-bit */
+
+#define IOAT_INTRDELAY_OFFSET                  0x0C    /* 16-bit */
+#define IOAT_INTRDELAY_INT_DELAY_MASK          0x3FFF  /* Interrupt Delay Time */
+#define IOAT_INTRDELAY_COALESE_SUPPORT         0x8000  /* Interrupt Coalesing Supported */
+
+#define IOAT_DEVICE_STATUS_OFFSET              0x0E    /* 16-bit */
+#define IOAT_DEVICE_STATUS_DEGRADED_MODE       0x0001
+
+
+#define IOAT_CHANNEL_MMIO_SIZE                 0x80    /* Each Channel MMIO space is this size */
+
+/* DMA Channel Registers */
+#define IOAT_CHANCTRL_OFFSET                   0x00    /* 16-bit Channel Control Register */
+#define IOAT_CHANCTRL_CHANNEL_PRIORITY_MASK    0xF000
+#define IOAT_CHANCTRL_CHANNEL_IN_USE           0x0100
+#define IOAT_CHANCTRL_DESCRIPTOR_ADDR_SNOOP_CONTROL    0x0020
+#define IOAT_CHANCTRL_ERR_INT_EN               0x0010
+#define IOAT_CHANCTRL_ANY_ERR_ABORT_EN         0x0008
+#define IOAT_CHANCTRL_ERR_COMPLETION_EN                0x0004
+#define IOAT_CHANCTRL_INT_DISABLE              0x0001
+
+#define IOAT_DMA_COMP_OFFSET                   0x02    /* 16-bit DMA channel compatability */
+#define IOAT_DMA_COMP_V1                       0x0001  /* Compatability with DMA version 1 */
+
+#define IOAT_CHANSTS_OFFSET                    0x04    /* 64-bit Channel Status Register */
+#define IOAT_CHANSTS_OFFSET_LOW                        0x04
+#define IOAT_CHANSTS_OFFSET_HIGH               0x08
+#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR 0xFFFFFFFFFFFFFFC0
+#define IOAT_CHANSTS_SOFT_ERR                  0x0000000000000010
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS       0x0000000000000007
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE        0x0
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE  0x1
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_SUSPENDED     0x2
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED        0x3
+
+#define IOAT_CHAINADDR_OFFSET                  0x0C    /* 64-bit Descriptor Chain Address Register */
+#define IOAT_CHAINADDR_OFFSET_LOW              0x0C
+#define IOAT_CHAINADDR_OFFSET_HIGH             0x10
+
+#define IOAT_CHANCMD_OFFSET                    0x14    /*  8-bit DMA Channel Command Register */
+#define IOAT_CHANCMD_RESET                     0x20
+#define IOAT_CHANCMD_RESUME                    0x10
+#define IOAT_CHANCMD_ABORT                     0x08
+#define IOAT_CHANCMD_SUSPEND                   0x04
+#define IOAT_CHANCMD_APPEND                    0x02
+#define IOAT_CHANCMD_START                     0x01
+
+#define IOAT_CHANCMP_OFFSET                    0x18    /* 64-bit Channel Completion Address Register */
+#define IOAT_CHANCMP_OFFSET_LOW                        0x18
+#define IOAT_CHANCMP_OFFSET_HIGH               0x1C
+
+#define IOAT_CDAR_OFFSET                       0x20    /* 64-bit Current Descriptor Address Register */
+#define IOAT_CDAR_OFFSET_LOW                   0x20
+#define IOAT_CDAR_OFFSET_HIGH                  0x24
+
+#define IOAT_CHANERR_OFFSET                    0x28    /* 32-bit Channel Error Register */
+#define IOAT_CHANERR_DMA_TRANSFER_SRC_ADDR_ERR 0x0001
+#define IOAT_CHANERR_DMA_TRANSFER_DEST_ADDR_ERR        0x0002
+#define IOAT_CHANERR_NEXT_DESCRIPTOR_ADDR_ERR  0x0004
+#define IOAT_CHANERR_NEXT_DESCRIPTOR_ALIGNMENT_ERR     0x0008
+#define IOAT_CHANERR_CHAIN_ADDR_VALUE_ERR      0x0010
+#define IOAT_CHANERR_CHANCMD_ERR               0x0020
+#define IOAT_CHANERR_CHIPSET_UNCORRECTABLE_DATA_INTEGRITY_ERR  0x0040
+#define IOAT_CHANERR_DMA_UNCORRECTABLE_DATA_INTEGRITY_ERR      0x0080
+#define IOAT_CHANERR_READ_DATA_ERR             0x0100
+#define IOAT_CHANERR_WRITE_DATA_ERR            0x0200
+#define IOAT_CHANERR_DESCRIPTOR_CONTROL_ERR    0x0400
+#define IOAT_CHANERR_DESCRIPTOR_LENGTH_ERR     0x0800
+#define IOAT_CHANERR_COMPLETION_ADDR_ERR       0x1000
+#define IOAT_CHANERR_INT_CONFIGURATION_ERR     0x2000
+#define IOAT_CHANERR_SOFT_ERR                  0x4000
+
+#define IOAT_CHANERR_MASK_OFFSET               0x2C    /* 32-bit Channel Error Register */
+
+#endif /* _IOAT_REGISTERS_H_ */
diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c
new file mode 100644 (file)
index 0000000..5ed327e
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Portions based on net/core/datagram.c and copyrighted by their authors.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 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 COPYING.
+ */
+
+/*
+ * This code allows the net stack to make use of a DMA engine for
+ * skb to iovec copies.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/pagemap.h>
+#include <net/tcp.h> /* for memcpy_toiovec */
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+int num_pages_spanned(struct iovec *iov)
+{
+       return
+       ((PAGE_ALIGN((unsigned long)iov->iov_base + iov->iov_len) -
+       ((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT);
+}
+
+/*
+ * Pin down all the iovec pages needed for len bytes.
+ * Return a struct dma_pinned_list to keep track of pages pinned down.
+ *
+ * We are allocating a single chunk of memory, and then carving it up into
+ * 3 sections, the latter 2 whose size depends on the number of iovecs and the
+ * total number of pages, respectively.
+ */
+struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len)
+{
+       struct dma_pinned_list *local_list;
+       struct page **pages;
+       int i;
+       int ret;
+       int nr_iovecs = 0;
+       int iovec_len_used = 0;
+       int iovec_pages_used = 0;
+       long err;
+
+       /* don't pin down non-user-based iovecs */
+       if (segment_eq(get_fs(), KERNEL_DS))
+               return NULL;
+
+       /* determine how many iovecs/pages there are, up front */
+       do {
+               iovec_len_used += iov[nr_iovecs].iov_len;
+               iovec_pages_used += num_pages_spanned(&iov[nr_iovecs]);
+               nr_iovecs++;
+       } while (iovec_len_used < len);
+
+       /* single kmalloc for pinned list, page_list[], and the page arrays */
+       local_list = kmalloc(sizeof(*local_list)
+               + (nr_iovecs * sizeof (struct dma_page_list))
+               + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL);
+       if (!local_list) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /* list of pages starts right after the page list array */
+       pages = (struct page **) &local_list->page_list[nr_iovecs];
+
+       for (i = 0; i < nr_iovecs; i++) {
+               struct dma_page_list *page_list = &local_list->page_list[i];
+
+               len -= iov[i].iov_len;
+
+               if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) {
+                       err = -EFAULT;
+                       goto unpin;
+               }
+
+               page_list->nr_pages = num_pages_spanned(&iov[i]);
+               page_list->base_address = iov[i].iov_base;
+
+               page_list->pages = pages;
+               pages += page_list->nr_pages;
+
+               /* pin pages down */
+               down_read(&current->mm->mmap_sem);
+               ret = get_user_pages(
+                       current,
+                       current->mm,
+                       (unsigned long) iov[i].iov_base,
+                       page_list->nr_pages,
+                       1,      /* write */
+                       0,      /* force */
+                       page_list->pages,
+                       NULL);
+               up_read(&current->mm->mmap_sem);
+
+               if (ret != page_list->nr_pages) {
+                       err = -ENOMEM;
+                       goto unpin;
+               }
+
+               local_list->nr_iovecs = i + 1;
+       }
+
+       return local_list;
+
+unpin:
+       dma_unpin_iovec_pages(local_list);
+out:
+       return ERR_PTR(err);
+}
+
+void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list)
+{
+       int i, j;
+
+       if (!pinned_list)
+               return;
+
+       for (i = 0; i < pinned_list->nr_iovecs; i++) {
+               struct dma_page_list *page_list = &pinned_list->page_list[i];
+               for (j = 0; j < page_list->nr_pages; j++) {
+                       set_page_dirty_lock(page_list->pages[j]);
+                       page_cache_release(page_list->pages[j]);
+               }
+       }
+
+       kfree(pinned_list);
+}
+
+static dma_cookie_t dma_memcpy_to_kernel_iovec(struct dma_chan *chan, struct
+       iovec *iov, unsigned char *kdata, size_t len)
+{
+       dma_cookie_t dma_cookie = 0;
+
+       while (len > 0) {
+               if (iov->iov_len) {
+                       int copy = min_t(unsigned int, iov->iov_len, len);
+                       dma_cookie = dma_async_memcpy_buf_to_buf(
+                                       chan,
+                                       iov->iov_base,
+                                       kdata,
+                                       copy);
+                       kdata += copy;
+                       len -= copy;
+                       iov->iov_len -= copy;
+                       iov->iov_base += copy;
+               }
+               iov++;
+       }
+
+       return dma_cookie;
+}
+
+/*
+ * We have already pinned down the pages we will be using in the iovecs.
+ * Each entry in iov array has corresponding entry in pinned_list->page_list.
+ * Using array indexing to keep iov[] and page_list[] in sync.
+ * Initial elements in iov array's iov->iov_len will be 0 if already copied into
+ *   by another call.
+ * iov array length remaining guaranteed to be bigger than len.
+ */
+dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov,
+       struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len)
+{
+       int iov_byte_offset;
+       int copy;
+       dma_cookie_t dma_cookie = 0;
+       int iovec_idx;
+       int page_idx;
+
+       if (!chan)
+               return memcpy_toiovec(iov, kdata, len);
+
+       /* -> kernel copies (e.g. smbfs) */
+       if (!pinned_list)
+               return dma_memcpy_to_kernel_iovec(chan, iov, kdata, len);
+
+       iovec_idx = 0;
+       while (iovec_idx < pinned_list->nr_iovecs) {
+               struct dma_page_list *page_list;
+
+               /* skip already used-up iovecs */
+               while (!iov[iovec_idx].iov_len)
+                       iovec_idx++;
+
+               page_list = &pinned_list->page_list[iovec_idx];
+
+               iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK);
+               page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK)
+                        - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT;
+
+               /* break up copies to not cross page boundary */
+               while (iov[iovec_idx].iov_len) {
+                       copy = min_t(int, PAGE_SIZE - iov_byte_offset, len);
+                       copy = min_t(int, copy, iov[iovec_idx].iov_len);
+
+                       dma_cookie = dma_async_memcpy_buf_to_pg(chan,
+                                       page_list->pages[page_idx],
+                                       iov_byte_offset,
+                                       kdata,
+                                       copy);
+
+                       len -= copy;
+                       iov[iovec_idx].iov_len -= copy;
+                       iov[iovec_idx].iov_base += copy;
+
+                       if (!len)
+                               return dma_cookie;
+
+                       kdata += copy;
+                       iov_byte_offset = 0;
+                       page_idx++;
+               }
+               iovec_idx++;
+       }
+
+       /* really bad if we ever run out of iovecs */
+       BUG();
+       return -EFAULT;
+}
+
+dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov,
+       struct dma_pinned_list *pinned_list, struct page *page,
+       unsigned int offset, size_t len)
+{
+       int iov_byte_offset;
+       int copy;
+       dma_cookie_t dma_cookie = 0;
+       int iovec_idx;
+       int page_idx;
+       int err;
+
+       /* this needs as-yet-unimplemented buf-to-buff, so punt. */
+       /* TODO: use dma for this */
+       if (!chan || !pinned_list) {
+               u8 *vaddr = kmap(page);
+               err = memcpy_toiovec(iov, vaddr + offset, len);
+               kunmap(page);
+               return err;
+       }
+
+       iovec_idx = 0;
+       while (iovec_idx < pinned_list->nr_iovecs) {
+               struct dma_page_list *page_list;
+
+               /* skip already used-up iovecs */
+               while (!iov[iovec_idx].iov_len)
+                       iovec_idx++;
+
+               page_list = &pinned_list->page_list[iovec_idx];
+
+               iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK);
+               page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK)
+                        - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT;
+
+               /* break up copies to not cross page boundary */
+               while (iov[iovec_idx].iov_len) {
+                       copy = min_t(int, PAGE_SIZE - iov_byte_offset, len);
+                       copy = min_t(int, copy, iov[iovec_idx].iov_len);
+
+                       dma_cookie = dma_async_memcpy_pg_to_pg(chan,
+                                       page_list->pages[page_idx],
+                                       iov_byte_offset,
+                                       page,
+                                       offset,
+                                       copy);
+
+                       len -= copy;
+                       iov[iovec_idx].iov_len -= copy;
+                       iov[iovec_idx].iov_base += copy;
+
+                       if (!len)
+                               return dma_cookie;
+
+                       offset += copy;
+                       iov_byte_offset = 0;
+                       page_idx++;
+               }
+               iovec_idx++;
+       }
+
+       /* really bad if we ever run out of iovecs */
+       BUG();
+       return -EFAULT;
+}
index a140e4536a4ee277fb7fe89e46fa9fdac847debf..766cc969c4d0c784abd0ef926363f2c37c7d735f 100644 (file)
@@ -491,7 +491,7 @@ static struct pci_device_id divil_pci[] = {
 
 #define MSR_LBAR_SMB           0x5140000B
 
-static int scx200_add_cs553x(void)
+static __init int scx200_add_cs553x(void)
 {
        u32     low, hi;
        u32     smb_base;
index 43b96e298363ac9d441235206c33020ab133269a..27c9eb989a9a087196804e1de14aed5a1e7a2d3a 100644 (file)
@@ -345,17 +345,17 @@ sgiioc4_resetproc(ide_drive_t * drive)
 static u8
 sgiioc4_INB(unsigned long port)
 {
-       u8 reg = (u8) inb(port);
+       u8 reg = (u8) readb((void __iomem *) port);
 
        if ((port & 0xFFF) == 0x11C) {  /* Status register of IOC4 */
                if (reg & 0x51) {       /* Not busy...check for interrupt */
                        unsigned long other_ir = port - 0x110;
-                       unsigned int intr_reg = (u32) inl(other_ir);
+                       unsigned int intr_reg = (u32) readl((void __iomem *) other_ir);
 
                        /* Clear the Interrupt, Error bits on the IOC4 */
                        if (intr_reg & 0x03) {
-                               outl(0x03, other_ir);
-                               intr_reg = (u32) inl(other_ir);
+                               writel(0x03, (void __iomem *) other_ir);
+                               intr_reg = (u32) readl((void __iomem *) other_ir);
                        }
                }
        }
@@ -606,6 +606,12 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
        hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off;
        hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
        hwif->ide_dma_timeout = &__ide_dma_timeout;
+
+       /*
+        * The IOC4 uses MMIO rather than Port IO.
+        * It also needs special workarounds for INB.
+        */
+       default_hwif_mmiops(hwif);
        hwif->INB = &sgiioc4_INB;
 }
 
@@ -743,6 +749,6 @@ ioc4_ide_exit(void)
 module_init(ioc4_ide_init);
 module_exit(ioc4_ide_exit);
 
-MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
+MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon");
 MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
 MODULE_LICENSE("GPL");
index 8a23fb54c6939bdbdac285570a45974e74740b48..5413dc43b9f1b2eb5bda4f976434535e91af3e1e 100644 (file)
@@ -845,7 +845,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
                        &sbp2_highlevel, ud->ne->host, &sbp2_ops,
                        sizeof(struct sbp2_status_block), sizeof(quadlet_t),
                        0x010000000000ULL, CSR1212_ALL_SPACE_END);
-       if (!scsi_id->status_fifo_addr) {
+       if (scsi_id->status_fifo_addr == ~0ULL) {
                SBP2_ERR("failed to allocate status FIFO address range");
                goto failed_alloc;
        }
index afc612b8577dc6c6f673fb5d2913031256c49877..ba2d6505e9a45ebaa77a64fac52631baf72e9540 100644 (file)
@@ -29,6 +29,11 @@ config INFINIBAND_USER_ACCESS
          libibverbs, libibcm and a hardware driver library from
          <http://www.openib.org>.
 
+config INFINIBAND_ADDR_TRANS
+       bool
+       depends on INFINIBAND && INET
+       default y
+
 source "drivers/infiniband/hw/mthca/Kconfig"
 source "drivers/infiniband/hw/ipath/Kconfig"
 
index ec3353f24b27598ba4cd4400ce8b13ab29aacc6d..68e73ec2d1f87f77b1a9c327469979aa64859991 100644 (file)
@@ -1,5 +1,7 @@
+infiniband-$(CONFIG_INFINIBAND_ADDR_TRANS)     := ib_addr.o rdma_cm.o
+
 obj-$(CONFIG_INFINIBAND) +=            ib_core.o ib_mad.o ib_sa.o \
-                                       ib_cm.o
+                                       ib_cm.o $(infiniband-y)
 obj-$(CONFIG_INFINIBAND_USER_MAD) +=   ib_umad.o
 obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=        ib_uverbs.o ib_ucm.o
 
@@ -12,8 +14,13 @@ ib_sa-y :=                   sa_query.o
 
 ib_cm-y :=                     cm.o
 
+rdma_cm-y :=                   cma.o
+
+ib_addr-y :=                   addr.o
+
 ib_umad-y :=                   user_mad.o
 
 ib_ucm-y :=                    ucm.o
 
-ib_uverbs-y :=                 uverbs_main.o uverbs_cmd.o uverbs_mem.o
+ib_uverbs-y :=                 uverbs_main.o uverbs_cmd.o uverbs_mem.o \
+                               uverbs_marshall.o
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
new file mode 100644 (file)
index 0000000..d294bbc
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
+ * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+#include <linux/mutex.h>
+#include <linux/inetdevice.h>
+#include <linux/workqueue.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+#include <net/neighbour.h>
+#include <net/route.h>
+#include <rdma/ib_addr.h>
+
+MODULE_AUTHOR("Sean Hefty");
+MODULE_DESCRIPTION("IB Address Translation");
+MODULE_LICENSE("Dual BSD/GPL");
+
+struct addr_req {
+       struct list_head list;
+       struct sockaddr src_addr;
+       struct sockaddr dst_addr;
+       struct rdma_dev_addr *addr;
+       void *context;
+       void (*callback)(int status, struct sockaddr *src_addr,
+                        struct rdma_dev_addr *addr, void *context);
+       unsigned long timeout;
+       int status;
+};
+
+static void process_req(void *data);
+
+static DEFINE_MUTEX(lock);
+static LIST_HEAD(req_list);
+static DECLARE_WORK(work, process_req, NULL);
+static struct workqueue_struct *addr_wq;
+
+static int copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
+                    unsigned char *dst_dev_addr)
+{
+       switch (dev->type) {
+       case ARPHRD_INFINIBAND:
+               dev_addr->dev_type = IB_NODE_CA;
+               break;
+       default:
+               return -EADDRNOTAVAIL;
+       }
+
+       memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
+       memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN);
+       if (dst_dev_addr)
+               memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN);
+       return 0;
+}
+
+int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
+{
+       struct net_device *dev;
+       u32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+       int ret;
+
+       dev = ip_dev_find(ip);
+       if (!dev)
+               return -EADDRNOTAVAIL;
+
+       ret = copy_addr(dev_addr, dev, NULL);
+       dev_put(dev);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_translate_ip);
+
+static void set_timeout(unsigned long time)
+{
+       unsigned long delay;
+
+       cancel_delayed_work(&work);
+
+       delay = time - jiffies;
+       if ((long)delay <= 0)
+               delay = 1;
+
+       queue_delayed_work(addr_wq, &work, delay);
+}
+
+static void queue_req(struct addr_req *req)
+{
+       struct addr_req *temp_req;
+
+       mutex_lock(&lock);
+       list_for_each_entry_reverse(temp_req, &req_list, list) {
+               if (time_after(req->timeout, temp_req->timeout))
+                       break;
+       }
+
+       list_add(&req->list, &temp_req->list);
+
+       if (req_list.next == &req->list)
+               set_timeout(req->timeout);
+       mutex_unlock(&lock);
+}
+
+static void addr_send_arp(struct sockaddr_in *dst_in)
+{
+       struct rtable *rt;
+       struct flowi fl;
+       u32 dst_ip = dst_in->sin_addr.s_addr;
+
+       memset(&fl, 0, sizeof fl);
+       fl.nl_u.ip4_u.daddr = dst_ip;
+       if (ip_route_output_key(&rt, &fl))
+               return;
+
+       arp_send(ARPOP_REQUEST, ETH_P_ARP, rt->rt_gateway, rt->idev->dev,
+                rt->rt_src, NULL, rt->idev->dev->dev_addr, NULL);
+       ip_rt_put(rt);
+}
+
+static int addr_resolve_remote(struct sockaddr_in *src_in,
+                              struct sockaddr_in *dst_in,
+                              struct rdma_dev_addr *addr)
+{
+       u32 src_ip = src_in->sin_addr.s_addr;
+       u32 dst_ip = dst_in->sin_addr.s_addr;
+       struct flowi fl;
+       struct rtable *rt;
+       struct neighbour *neigh;
+       int ret;
+
+       memset(&fl, 0, sizeof fl);
+       fl.nl_u.ip4_u.daddr = dst_ip;
+       fl.nl_u.ip4_u.saddr = src_ip;
+       ret = ip_route_output_key(&rt, &fl);
+       if (ret)
+               goto out;
+
+       /* If the device does ARP internally, return 'done' */
+       if (rt->idev->dev->flags & IFF_NOARP) {
+               copy_addr(addr, rt->idev->dev, NULL);
+               goto put;
+       }
+
+       neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev);
+       if (!neigh) {
+               ret = -ENODATA;
+               goto put;
+       }
+
+       if (!(neigh->nud_state & NUD_VALID)) {
+               ret = -ENODATA;
+               goto release;
+       }
+
+       if (!src_ip) {
+               src_in->sin_family = dst_in->sin_family;
+               src_in->sin_addr.s_addr = rt->rt_src;
+       }
+
+       ret = copy_addr(addr, neigh->dev, neigh->ha);
+release:
+       neigh_release(neigh);
+put:
+       ip_rt_put(rt);
+out:
+       return ret;
+}
+
+static void process_req(void *data)
+{
+       struct addr_req *req, *temp_req;
+       struct sockaddr_in *src_in, *dst_in;
+       struct list_head done_list;
+
+       INIT_LIST_HEAD(&done_list);
+
+       mutex_lock(&lock);
+       list_for_each_entry_safe(req, temp_req, &req_list, list) {
+               if (req->status) {
+                       src_in = (struct sockaddr_in *) &req->src_addr;
+                       dst_in = (struct sockaddr_in *) &req->dst_addr;
+                       req->status = addr_resolve_remote(src_in, dst_in,
+                                                         req->addr);
+               }
+               if (req->status && time_after(jiffies, req->timeout))
+                       req->status = -ETIMEDOUT;
+               else if (req->status == -ENODATA)
+                       continue;
+
+               list_del(&req->list);
+               list_add_tail(&req->list, &done_list);
+       }
+
+       if (!list_empty(&req_list)) {
+               req = list_entry(req_list.next, struct addr_req, list);
+               set_timeout(req->timeout);
+       }
+       mutex_unlock(&lock);
+
+       list_for_each_entry_safe(req, temp_req, &done_list, list) {
+               list_del(&req->list);
+               req->callback(req->status, &req->src_addr, req->addr,
+                             req->context);
+               kfree(req);
+       }
+}
+
+static int addr_resolve_local(struct sockaddr_in *src_in,
+                             struct sockaddr_in *dst_in,
+                             struct rdma_dev_addr *addr)
+{
+       struct net_device *dev;
+       u32 src_ip = src_in->sin_addr.s_addr;
+       u32 dst_ip = dst_in->sin_addr.s_addr;
+       int ret;
+
+       dev = ip_dev_find(dst_ip);
+       if (!dev)
+               return -EADDRNOTAVAIL;
+
+       if (ZERONET(src_ip)) {
+               src_in->sin_family = dst_in->sin_family;
+               src_in->sin_addr.s_addr = dst_ip;
+               ret = copy_addr(addr, dev, dev->dev_addr);
+       } else if (LOOPBACK(src_ip)) {
+               ret = rdma_translate_ip((struct sockaddr *)dst_in, addr);
+               if (!ret)
+                       memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
+       } else {
+               ret = rdma_translate_ip((struct sockaddr *)src_in, addr);
+               if (!ret)
+                       memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
+       }
+
+       dev_put(dev);
+       return ret;
+}
+
+int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
+                   struct rdma_dev_addr *addr, int timeout_ms,
+                   void (*callback)(int status, struct sockaddr *src_addr,
+                                    struct rdma_dev_addr *addr, void *context),
+                   void *context)
+{
+       struct sockaddr_in *src_in, *dst_in;
+       struct addr_req *req;
+       int ret = 0;
+
+       req = kmalloc(sizeof *req, GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+       memset(req, 0, sizeof *req);
+
+       if (src_addr)
+               memcpy(&req->src_addr, src_addr, ip_addr_size(src_addr));
+       memcpy(&req->dst_addr, dst_addr, ip_addr_size(dst_addr));
+       req->addr = addr;
+       req->callback = callback;
+       req->context = context;
+
+       src_in = (struct sockaddr_in *) &req->src_addr;
+       dst_in = (struct sockaddr_in *) &req->dst_addr;
+
+       req->status = addr_resolve_local(src_in, dst_in, addr);
+       if (req->status == -EADDRNOTAVAIL)
+               req->status = addr_resolve_remote(src_in, dst_in, addr);
+
+       switch (req->status) {
+       case 0:
+               req->timeout = jiffies;
+               queue_req(req);
+               break;
+       case -ENODATA:
+               req->timeout = msecs_to_jiffies(timeout_ms) + jiffies;
+               queue_req(req);
+               addr_send_arp(dst_in);
+               break;
+       default:
+               ret = req->status;
+               kfree(req);
+               break;
+       }
+       return ret;
+}
+EXPORT_SYMBOL(rdma_resolve_ip);
+
+void rdma_addr_cancel(struct rdma_dev_addr *addr)
+{
+       struct addr_req *req, *temp_req;
+
+       mutex_lock(&lock);
+       list_for_each_entry_safe(req, temp_req, &req_list, list) {
+               if (req->addr == addr) {
+                       req->status = -ECANCELED;
+                       req->timeout = jiffies;
+                       list_del(&req->list);
+                       list_add(&req->list, &req_list);
+                       set_timeout(req->timeout);
+                       break;
+               }
+       }
+       mutex_unlock(&lock);
+}
+EXPORT_SYMBOL(rdma_addr_cancel);
+
+static int addr_arp_recv(struct sk_buff *skb, struct net_device *dev,
+                        struct packet_type *pkt, struct net_device *orig_dev)
+{
+       struct arphdr *arp_hdr;
+
+       arp_hdr = (struct arphdr *) skb->nh.raw;
+
+       if (arp_hdr->ar_op == htons(ARPOP_REQUEST) ||
+           arp_hdr->ar_op == htons(ARPOP_REPLY))
+               set_timeout(jiffies);
+
+       kfree_skb(skb);
+       return 0;
+}
+
+static struct packet_type addr_arp = {
+       .type           = __constant_htons(ETH_P_ARP),
+       .func           = addr_arp_recv,
+       .af_packet_priv = (void*) 1,
+};
+
+static int addr_init(void)
+{
+       addr_wq = create_singlethread_workqueue("ib_addr_wq");
+       if (!addr_wq)
+               return -ENOMEM;
+
+       dev_add_pack(&addr_arp);
+       return 0;
+}
+
+static void addr_cleanup(void)
+{
+       dev_remove_pack(&addr_arp);
+       destroy_workqueue(addr_wq);
+}
+
+module_init(addr_init);
+module_exit(addr_cleanup);
index 50364c0b090c7b6a141c6bd7e47583422826c351..e05ca2cdc73f44aafd3dd807906d073b33511463 100644 (file)
@@ -191,6 +191,24 @@ int ib_find_cached_pkey(struct ib_device *device,
 }
 EXPORT_SYMBOL(ib_find_cached_pkey);
 
+int ib_get_cached_lmc(struct ib_device *device,
+                     u8                port_num,
+                     u8                *lmc)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       if (port_num < start_port(device) || port_num > end_port(device))
+               return -EINVAL;
+
+       read_lock_irqsave(&device->cache.lock, flags);
+       *lmc = device->cache.lmc_cache[port_num - start_port(device)];
+       read_unlock_irqrestore(&device->cache.lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(ib_get_cached_lmc);
+
 static void ib_cache_update(struct ib_device *device,
                            u8                port)
 {
@@ -251,6 +269,8 @@ static void ib_cache_update(struct ib_device *device,
        device->cache.pkey_cache[port - start_port(device)] = pkey_cache;
        device->cache.gid_cache [port - start_port(device)] = gid_cache;
 
+       device->cache.lmc_cache[port - start_port(device)] = tprops->lmc;
+
        write_unlock_irq(&device->cache.lock);
 
        kfree(old_pkey_cache);
@@ -305,7 +325,13 @@ static void ib_cache_setup_one(struct ib_device *device)
                kmalloc(sizeof *device->cache.gid_cache *
                        (end_port(device) - start_port(device) + 1), GFP_KERNEL);
 
-       if (!device->cache.pkey_cache || !device->cache.gid_cache) {
+       device->cache.lmc_cache = kmalloc(sizeof *device->cache.lmc_cache *
+                                         (end_port(device) -
+                                          start_port(device) + 1),
+                                         GFP_KERNEL);
+
+       if (!device->cache.pkey_cache || !device->cache.gid_cache ||
+           !device->cache.lmc_cache) {
                printk(KERN_WARNING "Couldn't allocate cache "
                       "for %s\n", device->name);
                goto err;
@@ -333,6 +359,7 @@ err_cache:
 err:
        kfree(device->cache.pkey_cache);
        kfree(device->cache.gid_cache);
+       kfree(device->cache.lmc_cache);
 }
 
 static void ib_cache_cleanup_one(struct ib_device *device)
@@ -349,6 +376,7 @@ static void ib_cache_cleanup_one(struct ib_device *device)
 
        kfree(device->cache.pkey_cache);
        kfree(device->cache.gid_cache);
+       kfree(device->cache.lmc_cache);
 }
 
 static struct ib_client cache_client = {
index 86fee43502cd2a977030d48fad69810fc7f0ac0f..450adfe0a4f1c5e4ed847c340e111ca62d000cbb 100644 (file)
@@ -32,7 +32,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: cm.c 2821 2005-07-08 17:07:28Z sean.hefty $
+ * $Id: cm.c 4311 2005-12-05 18:42:01Z sean.hefty $
  */
 
 #include <linux/completion.h>
@@ -132,6 +132,7 @@ struct cm_id_private {
        /* todo: use alternate port on send failure */
        struct cm_av av;
        struct cm_av alt_av;
+       struct ib_cm_compare_data *compare_data;
 
        void *private_data;
        __be64 tid;
@@ -253,23 +254,13 @@ static void cm_set_private_data(struct cm_id_private *cm_id_priv,
        cm_id_priv->private_data_len = private_data_len;
 }
 
-static void cm_set_ah_attr(struct ib_ah_attr *ah_attr, u8 port_num,
-                          u16 dlid, u8 sl, u16 src_path_bits)
-{
-       memset(ah_attr, 0, sizeof ah_attr);
-       ah_attr->dlid = dlid;
-       ah_attr->sl = sl;
-       ah_attr->src_path_bits = src_path_bits;
-       ah_attr->port_num = port_num;
-}
-
-static void cm_init_av_for_response(struct cm_port *port,
-                                   struct ib_wc *wc, struct cm_av *av)
+static void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc,
+                                   struct ib_grh *grh, struct cm_av *av)
 {
        av->port = port;
        av->pkey_index = wc->pkey_index;
-       cm_set_ah_attr(&av->ah_attr, port->port_num, wc->slid,
-                      wc->sl, wc->dlid_path_bits);
+       ib_init_ah_from_wc(port->cm_dev->device, port->port_num, wc,
+                          grh, &av->ah_attr);
 }
 
 static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
@@ -299,9 +290,8 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
                return ret;
 
        av->port = port;
-       cm_set_ah_attr(&av->ah_attr, av->port->port_num,
-                      be16_to_cpu(path->dlid), path->sl,
-                      be16_to_cpu(path->slid) & 0x7F);
+       ib_init_ah_from_path(cm_dev->device, port->port_num, path,
+                            &av->ah_attr);
        av->packet_life_time = path->packet_life_time;
        return 0;
 }
@@ -357,6 +347,41 @@ static struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
        return cm_id_priv;
 }
 
+static void cm_mask_copy(u8 *dst, u8 *src, u8 *mask)
+{
+       int i;
+
+       for (i = 0; i < IB_CM_COMPARE_SIZE / sizeof(unsigned long); i++)
+               ((unsigned long *) dst)[i] = ((unsigned long *) src)[i] &
+                                            ((unsigned long *) mask)[i];
+}
+
+static int cm_compare_data(struct ib_cm_compare_data *src_data,
+                          struct ib_cm_compare_data *dst_data)
+{
+       u8 src[IB_CM_COMPARE_SIZE];
+       u8 dst[IB_CM_COMPARE_SIZE];
+
+       if (!src_data || !dst_data)
+               return 0;
+
+       cm_mask_copy(src, src_data->data, dst_data->mask);
+       cm_mask_copy(dst, dst_data->data, src_data->mask);
+       return memcmp(src, dst, IB_CM_COMPARE_SIZE);
+}
+
+static int cm_compare_private_data(u8 *private_data,
+                                  struct ib_cm_compare_data *dst_data)
+{
+       u8 src[IB_CM_COMPARE_SIZE];
+
+       if (!dst_data)
+               return 0;
+
+       cm_mask_copy(src, private_data, dst_data->mask);
+       return memcmp(src, dst_data->data, IB_CM_COMPARE_SIZE);
+}
+
 static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
 {
        struct rb_node **link = &cm.listen_service_table.rb_node;
@@ -364,14 +389,18 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
        struct cm_id_private *cur_cm_id_priv;
        __be64 service_id = cm_id_priv->id.service_id;
        __be64 service_mask = cm_id_priv->id.service_mask;
+       int data_cmp;
 
        while (*link) {
                parent = *link;
                cur_cm_id_priv = rb_entry(parent, struct cm_id_private,
                                          service_node);
+               data_cmp = cm_compare_data(cm_id_priv->compare_data,
+                                          cur_cm_id_priv->compare_data);
                if ((cur_cm_id_priv->id.service_mask & service_id) ==
                    (service_mask & cur_cm_id_priv->id.service_id) &&
-                   (cm_id_priv->id.device == cur_cm_id_priv->id.device))
+                   (cm_id_priv->id.device == cur_cm_id_priv->id.device) &&
+                   !data_cmp)
                        return cur_cm_id_priv;
 
                if (cm_id_priv->id.device < cur_cm_id_priv->id.device)
@@ -380,6 +409,10 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
                        link = &(*link)->rb_right;
                else if (service_id < cur_cm_id_priv->id.service_id)
                        link = &(*link)->rb_left;
+               else if (service_id > cur_cm_id_priv->id.service_id)
+                       link = &(*link)->rb_right;
+               else if (data_cmp < 0)
+                       link = &(*link)->rb_left;
                else
                        link = &(*link)->rb_right;
        }
@@ -389,16 +422,20 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
 }
 
 static struct cm_id_private * cm_find_listen(struct ib_device *device,
-                                            __be64 service_id)
+                                            __be64 service_id,
+                                            u8 *private_data)
 {
        struct rb_node *node = cm.listen_service_table.rb_node;
        struct cm_id_private *cm_id_priv;
+       int data_cmp;
 
        while (node) {
                cm_id_priv = rb_entry(node, struct cm_id_private, service_node);
+               data_cmp = cm_compare_private_data(private_data,
+                                                  cm_id_priv->compare_data);
                if ((cm_id_priv->id.service_mask & service_id) ==
                     cm_id_priv->id.service_id &&
-                   (cm_id_priv->id.device == device))
+                   (cm_id_priv->id.device == device) && !data_cmp)
                        return cm_id_priv;
 
                if (device < cm_id_priv->id.device)
@@ -407,6 +444,10 @@ static struct cm_id_private * cm_find_listen(struct ib_device *device,
                        node = node->rb_right;
                else if (service_id < cm_id_priv->id.service_id)
                        node = node->rb_left;
+               else if (service_id > cm_id_priv->id.service_id)
+                       node = node->rb_right;
+               else if (data_cmp < 0)
+                       node = node->rb_left;
                else
                        node = node->rb_right;
        }
@@ -730,15 +771,14 @@ retest:
        wait_for_completion(&cm_id_priv->comp);
        while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
                cm_free_work(work);
-       if (cm_id_priv->private_data && cm_id_priv->private_data_len)
-               kfree(cm_id_priv->private_data);
+       kfree(cm_id_priv->compare_data);
+       kfree(cm_id_priv->private_data);
        kfree(cm_id_priv);
 }
 EXPORT_SYMBOL(ib_destroy_cm_id);
 
-int ib_cm_listen(struct ib_cm_id *cm_id,
-                __be64 service_id,
-                __be64 service_mask)
+int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask,
+                struct ib_cm_compare_data *compare_data)
 {
        struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
        unsigned long flags;
@@ -752,7 +792,19 @@ int ib_cm_listen(struct ib_cm_id *cm_id,
                return -EINVAL;
 
        cm_id_priv = container_of(cm_id, struct cm_id_private, id);
-       BUG_ON(cm_id->state != IB_CM_IDLE);
+       if (cm_id->state != IB_CM_IDLE)
+               return -EINVAL;
+
+       if (compare_data) {
+               cm_id_priv->compare_data = kzalloc(sizeof *compare_data,
+                                                  GFP_KERNEL);
+               if (!cm_id_priv->compare_data)
+                       return -ENOMEM;
+               cm_mask_copy(cm_id_priv->compare_data->data,
+                            compare_data->data, compare_data->mask);
+               memcpy(cm_id_priv->compare_data->mask, compare_data->mask,
+                      IB_CM_COMPARE_SIZE);
+       }
 
        cm_id->state = IB_CM_LISTEN;
 
@@ -769,6 +821,8 @@ int ib_cm_listen(struct ib_cm_id *cm_id,
 
        if (cur_cm_id_priv) {
                cm_id->state = IB_CM_IDLE;
+               kfree(cm_id_priv->compare_data);
+               cm_id_priv->compare_data = NULL;
                ret = -EBUSY;
        }
        return ret;
@@ -1241,7 +1295,8 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
 
        /* Find matching listen request. */
        listen_cm_id_priv = cm_find_listen(cm_id_priv->id.device,
-                                          req_msg->service_id);
+                                          req_msg->service_id,
+                                          req_msg->private_data);
        if (!listen_cm_id_priv) {
                spin_unlock_irqrestore(&cm.lock, flags);
                cm_issue_rej(work->port, work->mad_recv_wc,
@@ -1276,6 +1331,7 @@ static int cm_req_handler(struct cm_work *work)
        cm_id_priv = container_of(cm_id, struct cm_id_private, id);
        cm_id_priv->id.remote_id = req_msg->local_comm_id;
        cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
+                               work->mad_recv_wc->recv_buf.grh,
                                &cm_id_priv->av);
        cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv->
                                                            id.local_id);
@@ -2549,7 +2605,7 @@ static void cm_format_sidr_req(struct cm_sidr_req_msg *sidr_req_msg,
        cm_format_mad_hdr(&sidr_req_msg->hdr, CM_SIDR_REQ_ATTR_ID,
                          cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_SIDR));
        sidr_req_msg->request_id = cm_id_priv->id.local_id;
-       sidr_req_msg->pkey = cpu_to_be16(param->pkey);
+       sidr_req_msg->pkey = cpu_to_be16(param->path->pkey);
        sidr_req_msg->service_id = param->service_id;
 
        if (param->private_data && param->private_data_len)
@@ -2641,6 +2697,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
        cm_id_priv->av.dgid.global.subnet_prefix = cpu_to_be64(wc->slid);
        cm_id_priv->av.dgid.global.interface_id = 0;
        cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
+                               work->mad_recv_wc->recv_buf.grh,
                                &cm_id_priv->av);
        cm_id_priv->id.remote_id = sidr_req_msg->request_id;
        cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
@@ -2654,7 +2711,8 @@ static int cm_sidr_req_handler(struct cm_work *work)
                goto out; /* Duplicate message. */
        }
        cur_cm_id_priv = cm_find_listen(cm_id->device,
-                                       sidr_req_msg->service_id);
+                                       sidr_req_msg->service_id,
+                                       sidr_req_msg->private_data);
        if (!cur_cm_id_priv) {
                rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
                spin_unlock_irqrestore(&cm.lock, flags);
@@ -3291,7 +3349,6 @@ error:
 
 static void __exit ib_cm_cleanup(void)
 {
-       flush_workqueue(cm.wq);
        destroy_workqueue(cm.wq);
        ib_unregister_client(&cm_client);
        idr_destroy(&cm.local_id_table);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
new file mode 100644 (file)
index 0000000..a76834e
--- /dev/null
@@ -0,0 +1,1927 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
+ * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#include <linux/completion.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/mutex.h>
+#include <linux/random.h>
+#include <linux/idr.h>
+
+#include <net/tcp.h>
+
+#include <rdma/rdma_cm.h>
+#include <rdma/rdma_cm_ib.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_cm.h>
+#include <rdma/ib_sa.h>
+
+MODULE_AUTHOR("Sean Hefty");
+MODULE_DESCRIPTION("Generic RDMA CM Agent");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define CMA_CM_RESPONSE_TIMEOUT 20
+#define CMA_MAX_CM_RETRIES 3
+
+static void cma_add_one(struct ib_device *device);
+static void cma_remove_one(struct ib_device *device);
+
+static struct ib_client cma_client = {
+       .name   = "cma",
+       .add    = cma_add_one,
+       .remove = cma_remove_one
+};
+
+static LIST_HEAD(dev_list);
+static LIST_HEAD(listen_any_list);
+static DEFINE_MUTEX(lock);
+static struct workqueue_struct *cma_wq;
+static DEFINE_IDR(sdp_ps);
+static DEFINE_IDR(tcp_ps);
+
+struct cma_device {
+       struct list_head        list;
+       struct ib_device        *device;
+       __be64                  node_guid;
+       struct completion       comp;
+       atomic_t                refcount;
+       struct list_head        id_list;
+};
+
+enum cma_state {
+       CMA_IDLE,
+       CMA_ADDR_QUERY,
+       CMA_ADDR_RESOLVED,
+       CMA_ROUTE_QUERY,
+       CMA_ROUTE_RESOLVED,
+       CMA_CONNECT,
+       CMA_DISCONNECT,
+       CMA_ADDR_BOUND,
+       CMA_LISTEN,
+       CMA_DEVICE_REMOVAL,
+       CMA_DESTROYING
+};
+
+struct rdma_bind_list {
+       struct idr              *ps;
+       struct hlist_head       owners;
+       unsigned short          port;
+};
+
+/*
+ * Device removal can occur at anytime, so we need extra handling to
+ * serialize notifying the user of device removal with other callbacks.
+ * We do this by disabling removal notification while a callback is in process,
+ * and reporting it after the callback completes.
+ */
+struct rdma_id_private {
+       struct rdma_cm_id       id;
+
+       struct rdma_bind_list   *bind_list;
+       struct hlist_node       node;
+       struct list_head        list;
+       struct list_head        listen_list;
+       struct cma_device       *cma_dev;
+
+       enum cma_state          state;
+       spinlock_t              lock;
+       struct completion       comp;
+       atomic_t                refcount;
+       wait_queue_head_t       wait_remove;
+       atomic_t                dev_remove;
+
+       int                     backlog;
+       int                     timeout_ms;
+       struct ib_sa_query      *query;
+       int                     query_id;
+       union {
+               struct ib_cm_id *ib;
+       } cm_id;
+
+       u32                     seq_num;
+       u32                     qp_num;
+       enum ib_qp_type         qp_type;
+       u8                      srq;
+};
+
+struct cma_work {
+       struct work_struct      work;
+       struct rdma_id_private  *id;
+       enum cma_state          old_state;
+       enum cma_state          new_state;
+       struct rdma_cm_event    event;
+};
+
+union cma_ip_addr {
+       struct in6_addr ip6;
+       struct {
+               __u32 pad[3];
+               __u32 addr;
+       } ip4;
+};
+
+struct cma_hdr {
+       u8 cma_version;
+       u8 ip_version;  /* IP version: 7:4 */
+       __u16 port;
+       union cma_ip_addr src_addr;
+       union cma_ip_addr dst_addr;
+};
+
+struct sdp_hh {
+       u8 bsdh[16];
+       u8 sdp_version; /* Major version: 7:4 */
+       u8 ip_version;  /* IP version: 7:4 */
+       u8 sdp_specific1[10];
+       __u16 port;
+       __u16 sdp_specific2;
+       union cma_ip_addr src_addr;
+       union cma_ip_addr dst_addr;
+};
+
+struct sdp_hah {
+       u8 bsdh[16];
+       u8 sdp_version;
+};
+
+#define CMA_VERSION 0x00
+#define SDP_MAJ_VERSION 0x2
+
+static int cma_comp(struct rdma_id_private *id_priv, enum cma_state comp)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&id_priv->lock, flags);
+       ret = (id_priv->state == comp);
+       spin_unlock_irqrestore(&id_priv->lock, flags);
+       return ret;
+}
+
+static int cma_comp_exch(struct rdma_id_private *id_priv,
+                        enum cma_state comp, enum cma_state exch)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&id_priv->lock, flags);
+       if ((ret = (id_priv->state == comp)))
+               id_priv->state = exch;
+       spin_unlock_irqrestore(&id_priv->lock, flags);
+       return ret;
+}
+
+static enum cma_state cma_exch(struct rdma_id_private *id_priv,
+                              enum cma_state exch)
+{
+       unsigned long flags;
+       enum cma_state old;
+
+       spin_lock_irqsave(&id_priv->lock, flags);
+       old = id_priv->state;
+       id_priv->state = exch;
+       spin_unlock_irqrestore(&id_priv->lock, flags);
+       return old;
+}
+
+static inline u8 cma_get_ip_ver(struct cma_hdr *hdr)
+{
+       return hdr->ip_version >> 4;
+}
+
+static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver)
+{
+       hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF);
+}
+
+static inline u8 sdp_get_majv(u8 sdp_version)
+{
+       return sdp_version >> 4;
+}
+
+static inline u8 sdp_get_ip_ver(struct sdp_hh *hh)
+{
+       return hh->ip_version >> 4;
+}
+
+static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver)
+{
+       hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF);
+}
+
+static void cma_attach_to_dev(struct rdma_id_private *id_priv,
+                             struct cma_device *cma_dev)
+{
+       atomic_inc(&cma_dev->refcount);
+       id_priv->cma_dev = cma_dev;
+       id_priv->id.device = cma_dev->device;
+       list_add_tail(&id_priv->list, &cma_dev->id_list);
+}
+
+static inline void cma_deref_dev(struct cma_device *cma_dev)
+{
+       if (atomic_dec_and_test(&cma_dev->refcount))
+               complete(&cma_dev->comp);
+}
+
+static void cma_detach_from_dev(struct rdma_id_private *id_priv)
+{
+       list_del(&id_priv->list);
+       cma_deref_dev(id_priv->cma_dev);
+       id_priv->cma_dev = NULL;
+}
+
+static int cma_acquire_ib_dev(struct rdma_id_private *id_priv)
+{
+       struct cma_device *cma_dev;
+       union ib_gid *gid;
+       int ret = -ENODEV;
+
+       gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr);
+
+       mutex_lock(&lock);
+       list_for_each_entry(cma_dev, &dev_list, list) {
+               ret = ib_find_cached_gid(cma_dev->device, gid,
+                                        &id_priv->id.port_num, NULL);
+               if (!ret) {
+                       cma_attach_to_dev(id_priv, cma_dev);
+                       break;
+               }
+       }
+       mutex_unlock(&lock);
+       return ret;
+}
+
+static int cma_acquire_dev(struct rdma_id_private *id_priv)
+{
+       switch (id_priv->id.route.addr.dev_addr.dev_type) {
+       case IB_NODE_CA:
+               return cma_acquire_ib_dev(id_priv);
+       default:
+               return -ENODEV;
+       }
+}
+
+static void cma_deref_id(struct rdma_id_private *id_priv)
+{
+       if (atomic_dec_and_test(&id_priv->refcount))
+               complete(&id_priv->comp);
+}
+
+static void cma_release_remove(struct rdma_id_private *id_priv)
+{
+       if (atomic_dec_and_test(&id_priv->dev_remove))
+               wake_up(&id_priv->wait_remove);
+}
+
+struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
+                                 void *context, enum rdma_port_space ps)
+{
+       struct rdma_id_private *id_priv;
+
+       id_priv = kzalloc(sizeof *id_priv, GFP_KERNEL);
+       if (!id_priv)
+               return ERR_PTR(-ENOMEM);
+
+       id_priv->state = CMA_IDLE;
+       id_priv->id.context = context;
+       id_priv->id.event_handler = event_handler;
+       id_priv->id.ps = ps;
+       spin_lock_init(&id_priv->lock);
+       init_completion(&id_priv->comp);
+       atomic_set(&id_priv->refcount, 1);
+       init_waitqueue_head(&id_priv->wait_remove);
+       atomic_set(&id_priv->dev_remove, 0);
+       INIT_LIST_HEAD(&id_priv->listen_list);
+       get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
+
+       return &id_priv->id;
+}
+EXPORT_SYMBOL(rdma_create_id);
+
+static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
+{
+       struct ib_qp_attr qp_attr;
+       struct rdma_dev_addr *dev_addr;
+       int ret;
+
+       dev_addr = &id_priv->id.route.addr.dev_addr;
+       ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
+                                 ib_addr_get_pkey(dev_addr),
+                                 &qp_attr.pkey_index);
+       if (ret)
+               return ret;
+
+       qp_attr.qp_state = IB_QPS_INIT;
+       qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+       qp_attr.port_num = id_priv->id.port_num;
+       return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS |
+                                         IB_QP_PKEY_INDEX | IB_QP_PORT);
+}
+
+int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
+                  struct ib_qp_init_attr *qp_init_attr)
+{
+       struct rdma_id_private *id_priv;
+       struct ib_qp *qp;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (id->device != pd->device)
+               return -EINVAL;
+
+       qp = ib_create_qp(pd, qp_init_attr);
+       if (IS_ERR(qp))
+               return PTR_ERR(qp);
+
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               ret = cma_init_ib_qp(id_priv, qp);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+
+       if (ret)
+               goto err;
+
+       id->qp = qp;
+       id_priv->qp_num = qp->qp_num;
+       id_priv->qp_type = qp->qp_type;
+       id_priv->srq = (qp->srq != NULL);
+       return 0;
+err:
+       ib_destroy_qp(qp);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_create_qp);
+
+void rdma_destroy_qp(struct rdma_cm_id *id)
+{
+       ib_destroy_qp(id->qp);
+}
+EXPORT_SYMBOL(rdma_destroy_qp);
+
+static int cma_modify_qp_rtr(struct rdma_cm_id *id)
+{
+       struct ib_qp_attr qp_attr;
+       int qp_attr_mask, ret;
+
+       if (!id->qp)
+               return 0;
+
+       /* Need to update QP attributes from default values. */
+       qp_attr.qp_state = IB_QPS_INIT;
+       ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+       if (ret)
+               return ret;
+
+       ret = ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+       if (ret)
+               return ret;
+
+       qp_attr.qp_state = IB_QPS_RTR;
+       ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+       if (ret)
+               return ret;
+
+       return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+}
+
+static int cma_modify_qp_rts(struct rdma_cm_id *id)
+{
+       struct ib_qp_attr qp_attr;
+       int qp_attr_mask, ret;
+
+       if (!id->qp)
+               return 0;
+
+       qp_attr.qp_state = IB_QPS_RTS;
+       ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+       if (ret)
+               return ret;
+
+       return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+}
+
+static int cma_modify_qp_err(struct rdma_cm_id *id)
+{
+       struct ib_qp_attr qp_attr;
+
+       if (!id->qp)
+               return 0;
+
+       qp_attr.qp_state = IB_QPS_ERR;
+       return ib_modify_qp(id->qp, &qp_attr, IB_QP_STATE);
+}
+
+int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
+                      int *qp_attr_mask)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       switch (id_priv->id.device->node_type) {
+       case IB_NODE_CA:
+               ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
+                                        qp_attr_mask);
+               if (qp_attr->qp_state == IB_QPS_RTR)
+                       qp_attr->rq_psn = id_priv->seq_num;
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(rdma_init_qp_attr);
+
+static inline int cma_zero_addr(struct sockaddr *addr)
+{
+       struct in6_addr *ip6;
+
+       if (addr->sa_family == AF_INET)
+               return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr);
+       else {
+               ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
+               return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |
+                       ip6->s6_addr32[3] | ip6->s6_addr32[4]) == 0;
+       }
+}
+
+static inline int cma_loopback_addr(struct sockaddr *addr)
+{
+       return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr);
+}
+
+static inline int cma_any_addr(struct sockaddr *addr)
+{
+       return cma_zero_addr(addr) || cma_loopback_addr(addr);
+}
+
+static inline int cma_any_port(struct sockaddr *addr)
+{
+       return !((struct sockaddr_in *) addr)->sin_port;
+}
+
+static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
+                           u8 *ip_ver, __u16 *port,
+                           union cma_ip_addr **src, union cma_ip_addr **dst)
+{
+       switch (ps) {
+       case RDMA_PS_SDP:
+               if (sdp_get_majv(((struct sdp_hh *) hdr)->sdp_version) !=
+                   SDP_MAJ_VERSION)
+                       return -EINVAL;
+
+               *ip_ver = sdp_get_ip_ver(hdr);
+               *port   = ((struct sdp_hh *) hdr)->port;
+               *src    = &((struct sdp_hh *) hdr)->src_addr;
+               *dst    = &((struct sdp_hh *) hdr)->dst_addr;
+               break;
+       default:
+               if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION)
+                       return -EINVAL;
+
+               *ip_ver = cma_get_ip_ver(hdr);
+               *port   = ((struct cma_hdr *) hdr)->port;
+               *src    = &((struct cma_hdr *) hdr)->src_addr;
+               *dst    = &((struct cma_hdr *) hdr)->dst_addr;
+               break;
+       }
+
+       if (*ip_ver != 4 && *ip_ver != 6)
+               return -EINVAL;
+       return 0;
+}
+
+static void cma_save_net_info(struct rdma_addr *addr,
+                             struct rdma_addr *listen_addr,
+                             u8 ip_ver, __u16 port,
+                             union cma_ip_addr *src, union cma_ip_addr *dst)
+{
+       struct sockaddr_in *listen4, *ip4;
+       struct sockaddr_in6 *listen6, *ip6;
+
+       switch (ip_ver) {
+       case 4:
+               listen4 = (struct sockaddr_in *) &listen_addr->src_addr;
+               ip4 = (struct sockaddr_in *) &addr->src_addr;
+               ip4->sin_family = listen4->sin_family;
+               ip4->sin_addr.s_addr = dst->ip4.addr;
+               ip4->sin_port = listen4->sin_port;
+
+               ip4 = (struct sockaddr_in *) &addr->dst_addr;
+               ip4->sin_family = listen4->sin_family;
+               ip4->sin_addr.s_addr = src->ip4.addr;
+               ip4->sin_port = port;
+               break;
+       case 6:
+               listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr;
+               ip6 = (struct sockaddr_in6 *) &addr->src_addr;
+               ip6->sin6_family = listen6->sin6_family;
+               ip6->sin6_addr = dst->ip6;
+               ip6->sin6_port = listen6->sin6_port;
+
+               ip6 = (struct sockaddr_in6 *) &addr->dst_addr;
+               ip6->sin6_family = listen6->sin6_family;
+               ip6->sin6_addr = src->ip6;
+               ip6->sin6_port = port;
+               break;
+       default:
+               break;
+       }
+}
+
+static inline int cma_user_data_offset(enum rdma_port_space ps)
+{
+       switch (ps) {
+       case RDMA_PS_SDP:
+               return 0;
+       default:
+               return sizeof(struct cma_hdr);
+       }
+}
+
+static int cma_notify_user(struct rdma_id_private *id_priv,
+                          enum rdma_cm_event_type type, int status,
+                          void *data, u8 data_len)
+{
+       struct rdma_cm_event event;
+
+       event.event = type;
+       event.status = status;
+       event.private_data = data;
+       event.private_data_len = data_len;
+
+       return id_priv->id.event_handler(&id_priv->id, &event);
+}
+
+static void cma_cancel_route(struct rdma_id_private *id_priv)
+{
+       switch (id_priv->id.device->node_type) {
+       case IB_NODE_CA:
+               if (id_priv->query)
+                       ib_sa_cancel_query(id_priv->query_id, id_priv->query);
+               break;
+       default:
+               break;
+       }
+}
+
+static inline int cma_internal_listen(struct rdma_id_private *id_priv)
+{
+       return (id_priv->state == CMA_LISTEN) && id_priv->cma_dev &&
+              cma_any_addr(&id_priv->id.route.addr.src_addr);
+}
+
+static void cma_destroy_listen(struct rdma_id_private *id_priv)
+{
+       cma_exch(id_priv, CMA_DESTROYING);
+
+       if (id_priv->cma_dev) {
+               switch (id_priv->id.device->node_type) {
+               case IB_NODE_CA:
+                       if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
+                               ib_destroy_cm_id(id_priv->cm_id.ib);
+                       break;
+               default:
+                       break;
+               }
+               cma_detach_from_dev(id_priv);
+       }
+       list_del(&id_priv->listen_list);
+
+       cma_deref_id(id_priv);
+       wait_for_completion(&id_priv->comp);
+
+       kfree(id_priv);
+}
+
+static void cma_cancel_listens(struct rdma_id_private *id_priv)
+{
+       struct rdma_id_private *dev_id_priv;
+
+       mutex_lock(&lock);
+       list_del(&id_priv->list);
+
+       while (!list_empty(&id_priv->listen_list)) {
+               dev_id_priv = list_entry(id_priv->listen_list.next,
+                                        struct rdma_id_private, listen_list);
+               cma_destroy_listen(dev_id_priv);
+       }
+       mutex_unlock(&lock);
+}
+
+static void cma_cancel_operation(struct rdma_id_private *id_priv,
+                                enum cma_state state)
+{
+       switch (state) {
+       case CMA_ADDR_QUERY:
+               rdma_addr_cancel(&id_priv->id.route.addr.dev_addr);
+               break;
+       case CMA_ROUTE_QUERY:
+               cma_cancel_route(id_priv);
+               break;
+       case CMA_LISTEN:
+               if (cma_any_addr(&id_priv->id.route.addr.src_addr) &&
+                   !id_priv->cma_dev)
+                       cma_cancel_listens(id_priv);
+               break;
+       default:
+               break;
+       }
+}
+
+static void cma_release_port(struct rdma_id_private *id_priv)
+{
+       struct rdma_bind_list *bind_list = id_priv->bind_list;
+
+       if (!bind_list)
+               return;
+
+       mutex_lock(&lock);
+       hlist_del(&id_priv->node);
+       if (hlist_empty(&bind_list->owners)) {
+               idr_remove(bind_list->ps, bind_list->port);
+               kfree(bind_list);
+       }
+       mutex_unlock(&lock);
+}
+
+void rdma_destroy_id(struct rdma_cm_id *id)
+{
+       struct rdma_id_private *id_priv;
+       enum cma_state state;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       state = cma_exch(id_priv, CMA_DESTROYING);
+       cma_cancel_operation(id_priv, state);
+
+       if (id_priv->cma_dev) {
+               switch (id->device->node_type) {
+               case IB_NODE_CA:
+                       if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
+                               ib_destroy_cm_id(id_priv->cm_id.ib);
+                       break;
+               default:
+                       break;
+               }
+               mutex_lock(&lock);
+               cma_detach_from_dev(id_priv);
+               mutex_unlock(&lock);
+       }
+
+       cma_release_port(id_priv);
+       cma_deref_id(id_priv);
+       wait_for_completion(&id_priv->comp);
+
+       kfree(id_priv->id.route.path_rec);
+       kfree(id_priv);
+}
+EXPORT_SYMBOL(rdma_destroy_id);
+
+static int cma_rep_recv(struct rdma_id_private *id_priv)
+{
+       int ret;
+
+       ret = cma_modify_qp_rtr(&id_priv->id);
+       if (ret)
+               goto reject;
+
+       ret = cma_modify_qp_rts(&id_priv->id);
+       if (ret)
+               goto reject;
+
+       ret = ib_send_cm_rtu(id_priv->cm_id.ib, NULL, 0);
+       if (ret)
+               goto reject;
+
+       return 0;
+reject:
+       cma_modify_qp_err(&id_priv->id);
+       ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
+                      NULL, 0, NULL, 0);
+       return ret;
+}
+
+static int cma_verify_rep(struct rdma_id_private *id_priv, void *data)
+{
+       if (id_priv->id.ps == RDMA_PS_SDP &&
+           sdp_get_majv(((struct sdp_hah *) data)->sdp_version) !=
+           SDP_MAJ_VERSION)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int cma_rtu_recv(struct rdma_id_private *id_priv)
+{
+       int ret;
+
+       ret = cma_modify_qp_rts(&id_priv->id);
+       if (ret)
+               goto reject;
+
+       return 0;
+reject:
+       cma_modify_qp_err(&id_priv->id);
+       ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
+                      NULL, 0, NULL, 0);
+       return ret;
+}
+
+static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
+{
+       struct rdma_id_private *id_priv = cm_id->context;
+       enum rdma_cm_event_type event;
+       u8 private_data_len = 0;
+       int ret = 0, status = 0;
+
+       atomic_inc(&id_priv->dev_remove);
+       if (!cma_comp(id_priv, CMA_CONNECT))
+               goto out;
+
+       switch (ib_event->event) {
+       case IB_CM_REQ_ERROR:
+       case IB_CM_REP_ERROR:
+               event = RDMA_CM_EVENT_UNREACHABLE;
+               status = -ETIMEDOUT;
+               break;
+       case IB_CM_REP_RECEIVED:
+               status = cma_verify_rep(id_priv, ib_event->private_data);
+               if (status)
+                       event = RDMA_CM_EVENT_CONNECT_ERROR;
+               else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) {
+                       status = cma_rep_recv(id_priv);
+                       event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
+                                        RDMA_CM_EVENT_ESTABLISHED;
+               } else
+                       event = RDMA_CM_EVENT_CONNECT_RESPONSE;
+               private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
+               break;
+       case IB_CM_RTU_RECEIVED:
+               status = cma_rtu_recv(id_priv);
+               event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
+                                RDMA_CM_EVENT_ESTABLISHED;
+               break;
+       case IB_CM_DREQ_ERROR:
+               status = -ETIMEDOUT; /* fall through */
+       case IB_CM_DREQ_RECEIVED:
+       case IB_CM_DREP_RECEIVED:
+               if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT))
+                       goto out;
+               event = RDMA_CM_EVENT_DISCONNECTED;
+               break;
+       case IB_CM_TIMEWAIT_EXIT:
+       case IB_CM_MRA_RECEIVED:
+               /* ignore event */
+               goto out;
+       case IB_CM_REJ_RECEIVED:
+               cma_modify_qp_err(&id_priv->id);
+               status = ib_event->param.rej_rcvd.reason;
+               event = RDMA_CM_EVENT_REJECTED;
+               break;
+       default:
+               printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d",
+                      ib_event->event);
+               goto out;
+       }
+
+       ret = cma_notify_user(id_priv, event, status, ib_event->private_data,
+                             private_data_len);
+       if (ret) {
+               /* Destroy the CM ID by returning a non-zero value. */
+               id_priv->cm_id.ib = NULL;
+               cma_exch(id_priv, CMA_DESTROYING);
+               cma_release_remove(id_priv);
+               rdma_destroy_id(&id_priv->id);
+               return ret;
+       }
+out:
+       cma_release_remove(id_priv);
+       return ret;
+}
+
+static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id,
+                                         struct ib_cm_event *ib_event)
+{
+       struct rdma_id_private *id_priv;
+       struct rdma_cm_id *id;
+       struct rdma_route *rt;
+       union cma_ip_addr *src, *dst;
+       __u16 port;
+       u8 ip_ver;
+
+       id = rdma_create_id(listen_id->event_handler, listen_id->context,
+                           listen_id->ps);
+       if (IS_ERR(id))
+               return NULL;
+
+       rt = &id->route;
+       rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1;
+       rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, GFP_KERNEL);
+       if (!rt->path_rec)
+               goto err;
+
+       if (cma_get_net_info(ib_event->private_data, listen_id->ps,
+                            &ip_ver, &port, &src, &dst))
+               goto err;
+
+       cma_save_net_info(&id->route.addr, &listen_id->route.addr,
+                         ip_ver, port, src, dst);
+       rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;
+       if (rt->num_paths == 2)
+               rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
+
+       ib_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
+       ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
+       ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey));
+       rt->addr.dev_addr.dev_type = IB_NODE_CA;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       id_priv->state = CMA_CONNECT;
+       return id_priv;
+err:
+       rdma_destroy_id(id);
+       return NULL;
+}
+
+static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
+{
+       struct rdma_id_private *listen_id, *conn_id;
+       int offset, ret;
+
+       listen_id = cm_id->context;
+       atomic_inc(&listen_id->dev_remove);
+       if (!cma_comp(listen_id, CMA_LISTEN)) {
+               ret = -ECONNABORTED;
+               goto out;
+       }
+
+       conn_id = cma_new_id(&listen_id->id, ib_event);
+       if (!conn_id) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       atomic_inc(&conn_id->dev_remove);
+       ret = cma_acquire_ib_dev(conn_id);
+       if (ret) {
+               ret = -ENODEV;
+               cma_release_remove(conn_id);
+               rdma_destroy_id(&conn_id->id);
+               goto out;
+       }
+
+       conn_id->cm_id.ib = cm_id;
+       cm_id->context = conn_id;
+       cm_id->cm_handler = cma_ib_handler;
+
+       offset = cma_user_data_offset(listen_id->id.ps);
+       ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
+                             ib_event->private_data + offset,
+                             IB_CM_REQ_PRIVATE_DATA_SIZE - offset);
+       if (ret) {
+               /* Destroy the CM ID by returning a non-zero value. */
+               conn_id->cm_id.ib = NULL;
+               cma_exch(conn_id, CMA_DESTROYING);
+               cma_release_remove(conn_id);
+               rdma_destroy_id(&conn_id->id);
+       }
+out:
+       cma_release_remove(listen_id);
+       return ret;
+}
+
+static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr)
+{
+       return cpu_to_be64(((u64)ps << 16) +
+              be16_to_cpu(((struct sockaddr_in *) addr)->sin_port));
+}
+
+static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
+                                struct ib_cm_compare_data *compare)
+{
+       struct cma_hdr *cma_data, *cma_mask;
+       struct sdp_hh *sdp_data, *sdp_mask;
+       __u32 ip4_addr;
+       struct in6_addr ip6_addr;
+
+       memset(compare, 0, sizeof *compare);
+       cma_data = (void *) compare->data;
+       cma_mask = (void *) compare->mask;
+       sdp_data = (void *) compare->data;
+       sdp_mask = (void *) compare->mask;
+
+       switch (addr->sa_family) {
+       case AF_INET:
+               ip4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+               if (ps == RDMA_PS_SDP) {
+                       sdp_set_ip_ver(sdp_data, 4);
+                       sdp_set_ip_ver(sdp_mask, 0xF);
+                       sdp_data->dst_addr.ip4.addr = ip4_addr;
+                       sdp_mask->dst_addr.ip4.addr = ~0;
+               } else {
+                       cma_set_ip_ver(cma_data, 4);
+                       cma_set_ip_ver(cma_mask, 0xF);
+                       cma_data->dst_addr.ip4.addr = ip4_addr;
+                       cma_mask->dst_addr.ip4.addr = ~0;
+               }
+               break;
+       case AF_INET6:
+               ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr;
+               if (ps == RDMA_PS_SDP) {
+                       sdp_set_ip_ver(sdp_data, 6);
+                       sdp_set_ip_ver(sdp_mask, 0xF);
+                       sdp_data->dst_addr.ip6 = ip6_addr;
+                       memset(&sdp_mask->dst_addr.ip6, 0xFF,
+                              sizeof sdp_mask->dst_addr.ip6);
+               } else {
+                       cma_set_ip_ver(cma_data, 6);
+                       cma_set_ip_ver(cma_mask, 0xF);
+                       cma_data->dst_addr.ip6 = ip6_addr;
+                       memset(&cma_mask->dst_addr.ip6, 0xFF,
+                              sizeof cma_mask->dst_addr.ip6);
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+static int cma_ib_listen(struct rdma_id_private *id_priv)
+{
+       struct ib_cm_compare_data compare_data;
+       struct sockaddr *addr;
+       __be64 svc_id;
+       int ret;
+
+       id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler,
+                                           id_priv);
+       if (IS_ERR(id_priv->cm_id.ib))
+               return PTR_ERR(id_priv->cm_id.ib);
+
+       addr = &id_priv->id.route.addr.src_addr;
+       svc_id = cma_get_service_id(id_priv->id.ps, addr);
+       if (cma_any_addr(addr))
+               ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL);
+       else {
+               cma_set_compare_data(id_priv->id.ps, addr, &compare_data);
+               ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, &compare_data);
+       }
+
+       if (ret) {
+               ib_destroy_cm_id(id_priv->cm_id.ib);
+               id_priv->cm_id.ib = NULL;
+       }
+
+       return ret;
+}
+
+static int cma_listen_handler(struct rdma_cm_id *id,
+                             struct rdma_cm_event *event)
+{
+       struct rdma_id_private *id_priv = id->context;
+
+       id->context = id_priv->id.context;
+       id->event_handler = id_priv->id.event_handler;
+       return id_priv->id.event_handler(id, event);
+}
+
+static void cma_listen_on_dev(struct rdma_id_private *id_priv,
+                             struct cma_device *cma_dev)
+{
+       struct rdma_id_private *dev_id_priv;
+       struct rdma_cm_id *id;
+       int ret;
+
+       id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps);
+       if (IS_ERR(id))
+               return;
+
+       dev_id_priv = container_of(id, struct rdma_id_private, id);
+
+       dev_id_priv->state = CMA_ADDR_BOUND;
+       memcpy(&id->route.addr.src_addr, &id_priv->id.route.addr.src_addr,
+              ip_addr_size(&id_priv->id.route.addr.src_addr));
+
+       cma_attach_to_dev(dev_id_priv, cma_dev);
+       list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list);
+
+       ret = rdma_listen(id, id_priv->backlog);
+       if (ret)
+               goto err;
+
+       return;
+err:
+       cma_destroy_listen(dev_id_priv);
+}
+
+static void cma_listen_on_all(struct rdma_id_private *id_priv)
+{
+       struct cma_device *cma_dev;
+
+       mutex_lock(&lock);
+       list_add_tail(&id_priv->list, &listen_any_list);
+       list_for_each_entry(cma_dev, &dev_list, list)
+               cma_listen_on_dev(id_priv, cma_dev);
+       mutex_unlock(&lock);
+}
+
+static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af)
+{
+       struct sockaddr_in addr_in;
+
+       memset(&addr_in, 0, sizeof addr_in);
+       addr_in.sin_family = af;
+       return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
+}
+
+int rdma_listen(struct rdma_cm_id *id, int backlog)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (id_priv->state == CMA_IDLE) {
+               ret = cma_bind_any(id, AF_INET);
+               if (ret)
+                       return ret;
+       }
+
+       if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN))
+               return -EINVAL;
+
+       id_priv->backlog = backlog;
+       if (id->device) {
+               switch (id->device->node_type) {
+               case IB_NODE_CA:
+                       ret = cma_ib_listen(id_priv);
+                       if (ret)
+                               goto err;
+                       break;
+               default:
+                       ret = -ENOSYS;
+                       goto err;
+               }
+       } else
+               cma_listen_on_all(id_priv);
+
+       return 0;
+err:
+       id_priv->backlog = 0;
+       cma_comp_exch(id_priv, CMA_LISTEN, CMA_ADDR_BOUND);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_listen);
+
+static void cma_query_handler(int status, struct ib_sa_path_rec *path_rec,
+                             void *context)
+{
+       struct cma_work *work = context;
+       struct rdma_route *route;
+
+       route = &work->id->id.route;
+
+       if (!status) {
+               route->num_paths = 1;
+               *route->path_rec = *path_rec;
+       } else {
+               work->old_state = CMA_ROUTE_QUERY;
+               work->new_state = CMA_ADDR_RESOLVED;
+               work->event.event = RDMA_CM_EVENT_ROUTE_ERROR;
+       }
+
+       queue_work(cma_wq, &work->work);
+}
+
+static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
+                             struct cma_work *work)
+{
+       struct rdma_dev_addr *addr = &id_priv->id.route.addr.dev_addr;
+       struct ib_sa_path_rec path_rec;
+
+       memset(&path_rec, 0, sizeof path_rec);
+       path_rec.sgid = *ib_addr_get_sgid(addr);
+       path_rec.dgid = *ib_addr_get_dgid(addr);
+       path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr));
+       path_rec.numb_path = 1;
+
+       id_priv->query_id = ib_sa_path_rec_get(id_priv->id.device,
+                               id_priv->id.port_num, &path_rec,
+                               IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID |
+                               IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH,
+                               timeout_ms, GFP_KERNEL,
+                               cma_query_handler, work, &id_priv->query);
+
+       return (id_priv->query_id < 0) ? id_priv->query_id : 0;
+}
+
+static void cma_work_handler(void *data)
+{
+       struct cma_work *work = data;
+       struct rdma_id_private *id_priv = work->id;
+       int destroy = 0;
+
+       atomic_inc(&id_priv->dev_remove);
+       if (!cma_comp_exch(id_priv, work->old_state, work->new_state))
+               goto out;
+
+       if (id_priv->id.event_handler(&id_priv->id, &work->event)) {
+               cma_exch(id_priv, CMA_DESTROYING);
+               destroy = 1;
+       }
+out:
+       cma_release_remove(id_priv);
+       cma_deref_id(id_priv);
+       if (destroy)
+               rdma_destroy_id(&id_priv->id);
+       kfree(work);
+}
+
+static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
+{
+       struct rdma_route *route = &id_priv->id.route;
+       struct cma_work *work;
+       int ret;
+
+       work = kzalloc(sizeof *work, GFP_KERNEL);
+       if (!work)
+               return -ENOMEM;
+
+       work->id = id_priv;
+       INIT_WORK(&work->work, cma_work_handler, work);
+       work->old_state = CMA_ROUTE_QUERY;
+       work->new_state = CMA_ROUTE_RESOLVED;
+       work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
+
+       route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL);
+       if (!route->path_rec) {
+               ret = -ENOMEM;
+               goto err1;
+       }
+
+       ret = cma_query_ib_route(id_priv, timeout_ms, work);
+       if (ret)
+               goto err2;
+
+       return 0;
+err2:
+       kfree(route->path_rec);
+       route->path_rec = NULL;
+err1:
+       kfree(work);
+       return ret;
+}
+
+int rdma_set_ib_paths(struct rdma_cm_id *id,
+                     struct ib_sa_path_rec *path_rec, int num_paths)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_RESOLVED))
+               return -EINVAL;
+
+       id->route.path_rec = kmalloc(sizeof *path_rec * num_paths, GFP_KERNEL);
+       if (!id->route.path_rec) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       memcpy(id->route.path_rec, path_rec, sizeof *path_rec * num_paths);
+       return 0;
+err:
+       cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_ADDR_RESOLVED);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_set_ib_paths);
+
+int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_QUERY))
+               return -EINVAL;
+
+       atomic_inc(&id_priv->refcount);
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               ret = cma_resolve_ib_route(id_priv, timeout_ms);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       cma_comp_exch(id_priv, CMA_ROUTE_QUERY, CMA_ADDR_RESOLVED);
+       cma_deref_id(id_priv);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_resolve_route);
+
+static int cma_bind_loopback(struct rdma_id_private *id_priv)
+{
+       struct cma_device *cma_dev;
+       struct ib_port_attr port_attr;
+       union ib_gid *gid;
+       u16 pkey;
+       int ret;
+       u8 p;
+
+       mutex_lock(&lock);
+       list_for_each_entry(cma_dev, &dev_list, list)
+               for (p = 1; p <= cma_dev->device->phys_port_cnt; ++p)
+                       if (!ib_query_port (cma_dev->device, p, &port_attr) &&
+                           port_attr.state == IB_PORT_ACTIVE)
+                               goto port_found;
+
+       if (!list_empty(&dev_list)) {
+               p = 1;
+               cma_dev = list_entry(dev_list.next, struct cma_device, list);
+       } else {
+               ret = -ENODEV;
+               goto out;
+       }
+
+port_found:
+       gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr);
+       ret = ib_get_cached_gid(cma_dev->device, p, 0, gid);
+       if (ret)
+               goto out;
+
+       ret = ib_get_cached_pkey(cma_dev->device, p, 0, &pkey);
+       if (ret)
+               goto out;
+
+       ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey);
+       id_priv->id.port_num = p;
+       cma_attach_to_dev(id_priv, cma_dev);
+out:
+       mutex_unlock(&lock);
+       return ret;
+}
+
+static void addr_handler(int status, struct sockaddr *src_addr,
+                        struct rdma_dev_addr *dev_addr, void *context)
+{
+       struct rdma_id_private *id_priv = context;
+       enum rdma_cm_event_type event;
+
+       atomic_inc(&id_priv->dev_remove);
+       if (!id_priv->cma_dev && !status)
+               status = cma_acquire_dev(id_priv);
+
+       if (status) {
+               if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND))
+                       goto out;
+               event = RDMA_CM_EVENT_ADDR_ERROR;
+       } else {
+               if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
+                       goto out;
+               memcpy(&id_priv->id.route.addr.src_addr, src_addr,
+                      ip_addr_size(src_addr));
+               event = RDMA_CM_EVENT_ADDR_RESOLVED;
+       }
+
+       if (cma_notify_user(id_priv, event, status, NULL, 0)) {
+               cma_exch(id_priv, CMA_DESTROYING);
+               cma_release_remove(id_priv);
+               cma_deref_id(id_priv);
+               rdma_destroy_id(&id_priv->id);
+               return;
+       }
+out:
+       cma_release_remove(id_priv);
+       cma_deref_id(id_priv);
+}
+
+static int cma_resolve_loopback(struct rdma_id_private *id_priv)
+{
+       struct cma_work *work;
+       struct sockaddr_in *src_in, *dst_in;
+       int ret;
+
+       work = kzalloc(sizeof *work, GFP_KERNEL);
+       if (!work)
+               return -ENOMEM;
+
+       if (!id_priv->cma_dev) {
+               ret = cma_bind_loopback(id_priv);
+               if (ret)
+                       goto err;
+       }
+
+       ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr,
+                        ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr));
+
+       if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) {
+               src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr;
+               dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr;
+               src_in->sin_family = dst_in->sin_family;
+               src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr;
+       }
+
+       work->id = id_priv;
+       INIT_WORK(&work->work, cma_work_handler, work);
+       work->old_state = CMA_ADDR_QUERY;
+       work->new_state = CMA_ADDR_RESOLVED;
+       work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
+       queue_work(cma_wq, &work->work);
+       return 0;
+err:
+       kfree(work);
+       return ret;
+}
+
+static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+                        struct sockaddr *dst_addr)
+{
+       if (src_addr && src_addr->sa_family)
+               return rdma_bind_addr(id, src_addr);
+       else
+               return cma_bind_any(id, dst_addr->sa_family);
+}
+
+int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+                     struct sockaddr *dst_addr, int timeout_ms)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (id_priv->state == CMA_IDLE) {
+               ret = cma_bind_addr(id, src_addr, dst_addr);
+               if (ret)
+                       return ret;
+       }
+
+       if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_ADDR_QUERY))
+               return -EINVAL;
+
+       atomic_inc(&id_priv->refcount);
+       memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr));
+       if (cma_any_addr(dst_addr))
+               ret = cma_resolve_loopback(id_priv);
+       else
+               ret = rdma_resolve_ip(&id->route.addr.src_addr, dst_addr,
+                                     &id->route.addr.dev_addr,
+                                     timeout_ms, addr_handler, id_priv);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND);
+       cma_deref_id(id_priv);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_resolve_addr);
+
+static void cma_bind_port(struct rdma_bind_list *bind_list,
+                         struct rdma_id_private *id_priv)
+{
+       struct sockaddr_in *sin;
+
+       sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
+       sin->sin_port = htons(bind_list->port);
+       id_priv->bind_list = bind_list;
+       hlist_add_head(&id_priv->node, &bind_list->owners);
+}
+
+static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
+                         unsigned short snum)
+{
+       struct rdma_bind_list *bind_list;
+       int port, start, ret;
+
+       bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
+       if (!bind_list)
+               return -ENOMEM;
+
+       start = snum ? snum : sysctl_local_port_range[0];
+
+       do {
+               ret = idr_get_new_above(ps, bind_list, start, &port);
+       } while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
+
+       if (ret)
+               goto err;
+
+       if ((snum && port != snum) ||
+           (!snum && port > sysctl_local_port_range[1])) {
+               idr_remove(ps, port);
+               ret = -EADDRNOTAVAIL;
+               goto err;
+       }
+
+       bind_list->ps = ps;
+       bind_list->port = (unsigned short) port;
+       cma_bind_port(bind_list, id_priv);
+       return 0;
+err:
+       kfree(bind_list);
+       return ret;
+}
+
+static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
+{
+       struct rdma_id_private *cur_id;
+       struct sockaddr_in *sin, *cur_sin;
+       struct rdma_bind_list *bind_list;
+       struct hlist_node *node;
+       unsigned short snum;
+
+       sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
+       snum = ntohs(sin->sin_port);
+       if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+               return -EACCES;
+
+       bind_list = idr_find(ps, snum);
+       if (!bind_list)
+               return cma_alloc_port(ps, id_priv, snum);
+
+       /*
+        * We don't support binding to any address if anyone is bound to
+        * a specific address on the same port.
+        */
+       if (cma_any_addr(&id_priv->id.route.addr.src_addr))
+               return -EADDRNOTAVAIL;
+
+       hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
+               if (cma_any_addr(&cur_id->id.route.addr.src_addr))
+                       return -EADDRNOTAVAIL;
+               
+               cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr;
+               if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr)
+                       return -EADDRINUSE;
+       }
+
+       cma_bind_port(bind_list, id_priv);
+       return 0;
+}
+
+static int cma_get_port(struct rdma_id_private *id_priv)
+{
+       struct idr *ps;
+       int ret;
+
+       switch (id_priv->id.ps) {
+       case RDMA_PS_SDP:
+               ps = &sdp_ps;
+               break;
+       case RDMA_PS_TCP:
+               ps = &tcp_ps;
+               break;
+       default:
+               return -EPROTONOSUPPORT;
+       }
+
+       mutex_lock(&lock);
+       if (cma_any_port(&id_priv->id.route.addr.src_addr))
+               ret = cma_alloc_port(ps, id_priv, 0);
+       else
+               ret = cma_use_port(ps, id_priv);
+       mutex_unlock(&lock);
+
+       return ret;
+}
+
+int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       if (addr->sa_family != AF_INET)
+               return -EAFNOSUPPORT;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND))
+               return -EINVAL;
+
+       if (!cma_any_addr(addr)) {
+               ret = rdma_translate_ip(addr, &id->route.addr.dev_addr);
+               if (!ret)
+                       ret = cma_acquire_dev(id_priv);
+               if (ret)
+                       goto err;
+       }
+
+       memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr));
+       ret = cma_get_port(id_priv);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_bind_addr);
+
+static int cma_format_hdr(void *hdr, enum rdma_port_space ps,
+                         struct rdma_route *route)
+{
+       struct sockaddr_in *src4, *dst4;
+       struct cma_hdr *cma_hdr;
+       struct sdp_hh *sdp_hdr;
+
+       src4 = (struct sockaddr_in *) &route->addr.src_addr;
+       dst4 = (struct sockaddr_in *) &route->addr.dst_addr;
+
+       switch (ps) {
+       case RDMA_PS_SDP:
+               sdp_hdr = hdr;
+               if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION)
+                       return -EINVAL;
+               sdp_set_ip_ver(sdp_hdr, 4);
+               sdp_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
+               sdp_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
+               sdp_hdr->port = src4->sin_port;
+               break;
+       default:
+               cma_hdr = hdr;
+               cma_hdr->cma_version = CMA_VERSION;
+               cma_set_ip_ver(cma_hdr, 4);
+               cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
+               cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
+               cma_hdr->port = src4->sin_port;
+               break;
+       }
+       return 0;
+}
+
+static int cma_connect_ib(struct rdma_id_private *id_priv,
+                         struct rdma_conn_param *conn_param)
+{
+       struct ib_cm_req_param req;
+       struct rdma_route *route;
+       void *private_data;
+       int offset, ret;
+
+       memset(&req, 0, sizeof req);
+       offset = cma_user_data_offset(id_priv->id.ps);
+       req.private_data_len = offset + conn_param->private_data_len;
+       private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
+       if (!private_data)
+               return -ENOMEM;
+
+       if (conn_param->private_data && conn_param->private_data_len)
+               memcpy(private_data + offset, conn_param->private_data,
+                      conn_param->private_data_len);
+
+       id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
+                                           id_priv);
+       if (IS_ERR(id_priv->cm_id.ib)) {
+               ret = PTR_ERR(id_priv->cm_id.ib);
+               goto out;
+       }
+
+       route = &id_priv->id.route;
+       ret = cma_format_hdr(private_data, id_priv->id.ps, route);
+       if (ret)
+               goto out;
+       req.private_data = private_data;
+
+       req.primary_path = &route->path_rec[0];
+       if (route->num_paths == 2)
+               req.alternate_path = &route->path_rec[1];
+
+       req.service_id = cma_get_service_id(id_priv->id.ps,
+                                           &route->addr.dst_addr);
+       req.qp_num = id_priv->qp_num;
+       req.qp_type = id_priv->qp_type;
+       req.starting_psn = id_priv->seq_num;
+       req.responder_resources = conn_param->responder_resources;
+       req.initiator_depth = conn_param->initiator_depth;
+       req.flow_control = conn_param->flow_control;
+       req.retry_count = conn_param->retry_count;
+       req.rnr_retry_count = conn_param->rnr_retry_count;
+       req.remote_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
+       req.local_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
+       req.max_cm_retries = CMA_MAX_CM_RETRIES;
+       req.srq = id_priv->srq ? 1 : 0;
+
+       ret = ib_send_cm_req(id_priv->cm_id.ib, &req);
+out:
+       kfree(private_data);
+       return ret;
+}
+
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT))
+               return -EINVAL;
+
+       if (!id->qp) {
+               id_priv->qp_num = conn_param->qp_num;
+               id_priv->qp_type = conn_param->qp_type;
+               id_priv->srq = conn_param->srq;
+       }
+
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               ret = cma_connect_ib(id_priv, conn_param);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       cma_comp_exch(id_priv, CMA_CONNECT, CMA_ROUTE_RESOLVED);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_connect);
+
+static int cma_accept_ib(struct rdma_id_private *id_priv,
+                        struct rdma_conn_param *conn_param)
+{
+       struct ib_cm_rep_param rep;
+       int ret;
+
+       ret = cma_modify_qp_rtr(&id_priv->id);
+       if (ret)
+               return ret;
+
+       memset(&rep, 0, sizeof rep);
+       rep.qp_num = id_priv->qp_num;
+       rep.starting_psn = id_priv->seq_num;
+       rep.private_data = conn_param->private_data;
+       rep.private_data_len = conn_param->private_data_len;
+       rep.responder_resources = conn_param->responder_resources;
+       rep.initiator_depth = conn_param->initiator_depth;
+       rep.target_ack_delay = CMA_CM_RESPONSE_TIMEOUT;
+       rep.failover_accepted = 0;
+       rep.flow_control = conn_param->flow_control;
+       rep.rnr_retry_count = conn_param->rnr_retry_count;
+       rep.srq = id_priv->srq ? 1 : 0;
+
+       return ib_send_cm_rep(id_priv->cm_id.ib, &rep);
+}
+
+int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp(id_priv, CMA_CONNECT))
+               return -EINVAL;
+
+       if (!id->qp && conn_param) {
+               id_priv->qp_num = conn_param->qp_num;
+               id_priv->qp_type = conn_param->qp_type;
+               id_priv->srq = conn_param->srq;
+       }
+
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               if (conn_param)
+                       ret = cma_accept_ib(id_priv, conn_param);
+               else
+                       ret = cma_rep_recv(id_priv);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+
+       if (ret)
+               goto reject;
+
+       return 0;
+reject:
+       cma_modify_qp_err(id);
+       rdma_reject(id, NULL, 0);
+       return ret;
+}
+EXPORT_SYMBOL(rdma_accept);
+
+int rdma_reject(struct rdma_cm_id *id, const void *private_data,
+               u8 private_data_len)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp(id_priv, CMA_CONNECT))
+               return -EINVAL;
+
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               ret = ib_send_cm_rej(id_priv->cm_id.ib,
+                                    IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
+                                    private_data, private_data_len);
+               break;
+       default:
+               ret = -ENOSYS;
+               break;
+       }
+       return ret;
+}
+EXPORT_SYMBOL(rdma_reject);
+
+int rdma_disconnect(struct rdma_cm_id *id)
+{
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       id_priv = container_of(id, struct rdma_id_private, id);
+       if (!cma_comp(id_priv, CMA_CONNECT) &&
+           !cma_comp(id_priv, CMA_DISCONNECT))
+               return -EINVAL;
+
+       ret = cma_modify_qp_err(id);
+       if (ret)
+               goto out;
+
+       switch (id->device->node_type) {
+       case IB_NODE_CA:
+               /* Initiate or respond to a disconnect. */
+               if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0))
+                       ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0);
+               break;
+       default:
+               break;
+       }
+out:
+       return ret;
+}
+EXPORT_SYMBOL(rdma_disconnect);
+
+static void cma_add_one(struct ib_device *device)
+{
+       struct cma_device *cma_dev;
+       struct rdma_id_private *id_priv;
+
+       cma_dev = kmalloc(sizeof *cma_dev, GFP_KERNEL);
+       if (!cma_dev)
+               return;
+
+       cma_dev->device = device;
+       cma_dev->node_guid = device->node_guid;
+       if (!cma_dev->node_guid)
+               goto err;
+
+       init_completion(&cma_dev->comp);
+       atomic_set(&cma_dev->refcount, 1);
+       INIT_LIST_HEAD(&cma_dev->id_list);
+       ib_set_client_data(device, &cma_client, cma_dev);
+
+       mutex_lock(&lock);
+       list_add_tail(&cma_dev->list, &dev_list);
+       list_for_each_entry(id_priv, &listen_any_list, list)
+               cma_listen_on_dev(id_priv, cma_dev);
+       mutex_unlock(&lock);
+       return;
+err:
+       kfree(cma_dev);
+}
+
+static int cma_remove_id_dev(struct rdma_id_private *id_priv)
+{
+       enum cma_state state;
+
+       /* Record that we want to remove the device */
+       state = cma_exch(id_priv, CMA_DEVICE_REMOVAL);
+       if (state == CMA_DESTROYING)
+               return 0;
+
+       cma_cancel_operation(id_priv, state);
+       wait_event(id_priv->wait_remove, !atomic_read(&id_priv->dev_remove));
+
+       /* Check for destruction from another callback. */
+       if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL))
+               return 0;
+
+       return cma_notify_user(id_priv, RDMA_CM_EVENT_DEVICE_REMOVAL,
+                              0, NULL, 0);
+}
+
+static void cma_process_remove(struct cma_device *cma_dev)
+{
+       struct list_head remove_list;
+       struct rdma_id_private *id_priv;
+       int ret;
+
+       INIT_LIST_HEAD(&remove_list);
+
+       mutex_lock(&lock);
+       while (!list_empty(&cma_dev->id_list)) {
+               id_priv = list_entry(cma_dev->id_list.next,
+                                    struct rdma_id_private, list);
+
+               if (cma_internal_listen(id_priv)) {
+                       cma_destroy_listen(id_priv);
+                       continue;
+               }
+
+               list_del(&id_priv->list);
+               list_add_tail(&id_priv->list, &remove_list);
+               atomic_inc(&id_priv->refcount);
+               mutex_unlock(&lock);
+
+               ret = cma_remove_id_dev(id_priv);
+               cma_deref_id(id_priv);
+               if (ret)
+                       rdma_destroy_id(&id_priv->id);
+
+               mutex_lock(&lock);
+       }
+       mutex_unlock(&lock);
+
+       cma_deref_dev(cma_dev);
+       wait_for_completion(&cma_dev->comp);
+}
+
+static void cma_remove_one(struct ib_device *device)
+{
+       struct cma_device *cma_dev;
+
+       cma_dev = ib_get_client_data(device, &cma_client);
+       if (!cma_dev)
+               return;
+
+       mutex_lock(&lock);
+       list_del(&cma_dev->list);
+       mutex_unlock(&lock);
+
+       cma_process_remove(cma_dev);
+       kfree(cma_dev);
+}
+
+static int cma_init(void)
+{
+       int ret;
+
+       cma_wq = create_singlethread_workqueue("rdma_cm_wq");
+       if (!cma_wq)
+               return -ENOMEM;
+
+       ret = ib_register_client(&cma_client);
+       if (ret)
+               goto err;
+       return 0;
+
+err:
+       destroy_workqueue(cma_wq);
+       return ret;
+}
+
+static void cma_cleanup(void)
+{
+       ib_unregister_client(&cma_client);
+       destroy_workqueue(cma_wq);
+       idr_destroy(&sdp_ps);
+       idr_destroy(&tcp_ps);
+}
+
+module_init(cma_init);
+module_exit(cma_cleanup);
index 838bf54458d2d2ddda812583d1fb7273179d491a..615fe9cc6c568fe9b42dffdf007fda3254c81e1e 100644 (file)
@@ -54,7 +54,7 @@ enum {
 /*
  * If an FMR is not in use, then the list member will point to either
  * its pool's free_list (if the FMR can be mapped again; that is,
- * remap_count < IB_FMR_MAX_REMAPS) or its pool's dirty_list (if the
+ * remap_count < pool->max_remaps) or its pool's dirty_list (if the
  * FMR needs to be unmapped before being remapped).  In either of
  * these cases it is a bug if the ref_count is not 0.  In other words,
  * if ref_count is > 0, then the list member must not be linked into
@@ -84,6 +84,7 @@ struct ib_fmr_pool {
 
        int                       pool_size;
        int                       max_pages;
+       int                       max_remaps;
        int                       dirty_watermark;
        int                       dirty_len;
        struct list_head          free_list;
@@ -214,8 +215,10 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
 {
        struct ib_device   *device;
        struct ib_fmr_pool *pool;
+       struct ib_device_attr *attr;
        int i;
        int ret;
+       int max_remaps;
 
        if (!params)
                return ERR_PTR(-EINVAL);
@@ -228,6 +231,26 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
                return ERR_PTR(-ENOSYS);
        }
 
+       attr = kmalloc(sizeof *attr, GFP_KERNEL);
+       if (!attr) {
+               printk(KERN_WARNING "couldn't allocate device attr struct");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       ret = ib_query_device(device, attr);
+       if (ret) {
+               printk(KERN_WARNING "couldn't query device");
+               kfree(attr);
+               return ERR_PTR(ret);
+       }
+
+       if (!attr->max_map_per_fmr)
+               max_remaps = IB_FMR_MAX_REMAPS;
+       else
+               max_remaps = attr->max_map_per_fmr;
+
+       kfree(attr);
+
        pool = kmalloc(sizeof *pool, GFP_KERNEL);
        if (!pool) {
                printk(KERN_WARNING "couldn't allocate pool struct");
@@ -258,6 +281,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
 
        pool->pool_size       = 0;
        pool->max_pages       = params->max_pages_per_fmr;
+       pool->max_remaps      = max_remaps;
        pool->dirty_watermark = params->dirty_watermark;
        pool->dirty_len       = 0;
        spin_lock_init(&pool->pool_lock);
@@ -279,7 +303,7 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
                struct ib_pool_fmr *fmr;
                struct ib_fmr_attr attr = {
                        .max_pages  = params->max_pages_per_fmr,
-                       .max_maps   = IB_FMR_MAX_REMAPS,
+                       .max_maps   = pool->max_remaps,
                        .page_shift = params->page_shift
                };
 
@@ -489,7 +513,7 @@ int ib_fmr_pool_unmap(struct ib_pool_fmr *fmr)
 
        --fmr->ref_count;
        if (!fmr->ref_count) {
-               if (fmr->remap_count < IB_FMR_MAX_REMAPS) {
+               if (fmr->remap_count < pool->max_remaps) {
                        list_add_tail(&fmr->list, &pool->free_list);
                } else {
                        list_add_tail(&fmr->list, &pool->dirty_list);
index 5ad41a64314cd5b050f67dd4980c6ba0264419a4..b38e02a5db356c2b8dfdc612032e5fd73a860397 100644 (file)
@@ -34,6 +34,7 @@
  * $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $
  */
 #include <linux/dma-mapping.h>
+#include <rdma/ib_cache.h>
 
 #include "mad_priv.h"
 #include "mad_rmpp.h"
@@ -45,8 +46,7 @@ MODULE_DESCRIPTION("kernel IB MAD API");
 MODULE_AUTHOR("Hal Rosenstock");
 MODULE_AUTHOR("Sean Hefty");
 
-
-kmem_cache_t *ib_mad_cache;
+static kmem_cache_t *ib_mad_cache;
 
 static struct list_head ib_mad_port_list;
 static u32 ib_mad_client_id = 0;
@@ -1673,20 +1673,21 @@ static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr,
                rwc->recv_buf.mad->mad_hdr.mgmt_class;
 }
 
-static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr,
+static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv,
+                                  struct ib_mad_send_wr_private *wr,
                                   struct ib_mad_recv_wc *rwc )
 {
        struct ib_ah_attr attr;
        u8 send_resp, rcv_resp;
+       union ib_gid sgid;
+       struct ib_device *device = mad_agent_priv->agent.device;
+       u8 port_num = mad_agent_priv->agent.port_num;
+       u8 lmc;
 
        send_resp = ((struct ib_mad *)(wr->send_buf.mad))->
                     mad_hdr.method & IB_MGMT_METHOD_RESP;
        rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP;
 
-       if (!send_resp && rcv_resp)
-               /* is request/response. GID/LIDs are both local (same). */
-               return 1;
-
        if (send_resp == rcv_resp)
                /* both requests, or both responses. GIDs different */
                return 0;
@@ -1695,48 +1696,78 @@ static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr,
                /* Assume not equal, to avoid false positives. */
                return 0;
 
-       if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH))
-               return attr.dlid == rwc->wc->slid;
-       else if ((attr.ah_flags & IB_AH_GRH) &&
-                (rwc->wc->wc_flags & IB_WC_GRH))
-               return memcmp(attr.grh.dgid.raw,
-                             rwc->recv_buf.grh->sgid.raw, 16) == 0;
-       else
+       if (!!(attr.ah_flags & IB_AH_GRH) !=
+           !!(rwc->wc->wc_flags & IB_WC_GRH))
                /* one has GID, other does not.  Assume different */
                return 0;
+
+       if (!send_resp && rcv_resp) {
+               /* is request/response. */
+               if (!(attr.ah_flags & IB_AH_GRH)) {
+                       if (ib_get_cached_lmc(device, port_num, &lmc))
+                               return 0;
+                       return (!lmc || !((attr.src_path_bits ^
+                                          rwc->wc->dlid_path_bits) &
+                                         ((1 << lmc) - 1)));
+               } else {
+                       if (ib_get_cached_gid(device, port_num,
+                                             attr.grh.sgid_index, &sgid))
+                               return 0;
+                       return !memcmp(sgid.raw, rwc->recv_buf.grh->dgid.raw,
+                                      16);
+               }
+       }
+
+       if (!(attr.ah_flags & IB_AH_GRH))
+               return attr.dlid == rwc->wc->slid;
+       else
+               return !memcmp(attr.grh.dgid.raw, rwc->recv_buf.grh->sgid.raw,
+                              16);
+}
+
+static inline int is_direct(u8 class)
+{
+       return (class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE);
 }
+
 struct ib_mad_send_wr_private*
 ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv,
-                struct ib_mad_recv_wc *mad_recv_wc)
+                struct ib_mad_recv_wc *wc)
 {
-       struct ib_mad_send_wr_private *mad_send_wr;
+       struct ib_mad_send_wr_private *wr;
        struct ib_mad *mad;
 
-       mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad;
+       mad = (struct ib_mad *)wc->recv_buf.mad;
 
-       list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
-                           agent_list) {
-               if ((mad_send_wr->tid == mad->mad_hdr.tid) &&
-                   rcv_has_same_class(mad_send_wr, mad_recv_wc) &&
-                   rcv_has_same_gid(mad_send_wr, mad_recv_wc))
-                       return mad_send_wr;
+       list_for_each_entry(wr, &mad_agent_priv->wait_list, agent_list) {
+               if ((wr->tid == mad->mad_hdr.tid) &&
+                   rcv_has_same_class(wr, wc) &&
+                   /*
+                    * Don't check GID for direct routed MADs.
+                    * These might have permissive LIDs.
+                    */
+                   (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) ||
+                    rcv_has_same_gid(mad_agent_priv, wr, wc)))
+                       return wr;
        }
 
        /*
         * It's possible to receive the response before we've
         * been notified that the send has completed
         */
-       list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
-                           agent_list) {
-               if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
-                   mad_send_wr->tid == mad->mad_hdr.tid &&
-                   mad_send_wr->timeout &&
-                   rcv_has_same_class(mad_send_wr, mad_recv_wc) &&
-                   rcv_has_same_gid(mad_send_wr, mad_recv_wc)) {
+       list_for_each_entry(wr, &mad_agent_priv->send_list, agent_list) {
+               if (is_data_mad(mad_agent_priv, wr->send_buf.mad) &&
+                   wr->tid == mad->mad_hdr.tid &&
+                   wr->timeout &&
+                   rcv_has_same_class(wr, wc) &&
+                   /*
+                    * Don't check GID for direct routed MADs.
+                    * These might have permissive LIDs.
+                    */
+                   (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) ||
+                    rcv_has_same_gid(mad_agent_priv, wr, wc)))
                        /* Verify request has not been canceled */
-                       return (mad_send_wr->status == IB_WC_SUCCESS) ?
-                               mad_send_wr : NULL;
-               }
+                       return (wr->status == IB_WC_SUCCESS) ? wr : NULL;
        }
        return NULL;
 }
index b4fa28d3160fc5abd2dc076e92bfb2f81928fb62..d147f3bad2ce78f819525d5332b88212b0a452be 100644 (file)
@@ -212,8 +212,6 @@ struct ib_mad_port_private {
        struct ib_mad_qp_info qp_info[IB_MAD_QPS_CORE];
 };
 
-extern kmem_cache_t *ib_mad_cache;
-
 int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr);
 
 struct ib_mad_send_wr_private *
index 501cc054cb3b150d8af4bd3c1c6d0196560ffb65..e911c99ff8437987d0e12535a8f80bda02e8327f 100644 (file)
@@ -47,6 +47,7 @@
 
 #include <rdma/ib_pack.h>
 #include <rdma/ib_sa.h>
+#include <rdma/ib_cache.h>
 
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("InfiniBand subnet administration query support");
@@ -441,6 +442,36 @@ void ib_sa_cancel_query(int id, struct ib_sa_query *query)
 }
 EXPORT_SYMBOL(ib_sa_cancel_query);
 
+int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
+                        struct ib_sa_path_rec *rec, struct ib_ah_attr *ah_attr)
+{
+       int ret;
+       u16 gid_index;
+
+       memset(ah_attr, 0, sizeof *ah_attr);
+       ah_attr->dlid = be16_to_cpu(rec->dlid);
+       ah_attr->sl = rec->sl;
+       ah_attr->src_path_bits = be16_to_cpu(rec->slid) & 0x7f;
+       ah_attr->port_num = port_num;
+
+       if (rec->hop_limit > 1) {
+               ah_attr->ah_flags = IB_AH_GRH;
+               ah_attr->grh.dgid = rec->dgid;
+
+               ret = ib_find_cached_gid(device, &rec->sgid, &port_num,
+                                        &gid_index);
+               if (ret)
+                       return ret;
+
+               ah_attr->grh.sgid_index    = gid_index;
+               ah_attr->grh.flow_label    = be32_to_cpu(rec->flow_label);
+               ah_attr->grh.hop_limit     = rec->hop_limit;
+               ah_attr->grh.traffic_class = rec->traffic_class;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(ib_init_ah_from_path);
+
 static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
 {
        unsigned long flags;
index 9164a09b6ccd1d0aeea7153d29c8307e3c5903ca..c1c6fda9452cc44f6b44400e00eaa7f5e42ea43a 100644 (file)
@@ -30,7 +30,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: ucm.c 2594 2005-06-13 19:46:02Z libor $
+ * $Id: ucm.c 4311 2005-12-05 18:42:01Z sean.hefty $
  */
 
 #include <linux/completion.h>
@@ -50,6 +50,7 @@
 
 #include <rdma/ib_cm.h>
 #include <rdma/ib_user_cm.h>
+#include <rdma/ib_marshall.h>
 
 MODULE_AUTHOR("Libor Michalek");
 MODULE_DESCRIPTION("InfiniBand userspace Connection Manager access");
@@ -63,7 +64,7 @@ struct ib_ucm_device {
 };
 
 struct ib_ucm_file {
-       struct semaphore mutex;
+       struct mutex file_mutex;
        struct file *filp;
        struct ib_ucm_device *device;
 
@@ -152,7 +153,7 @@ static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx)
 {
        struct ib_ucm_event *uevent;
 
-       down(&ctx->file->mutex);
+       mutex_lock(&ctx->file->file_mutex);
        list_del(&ctx->file_list);
        while (!list_empty(&ctx->events)) {
 
@@ -167,7 +168,7 @@ static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx)
 
                kfree(uevent);
        }
-       up(&ctx->file->mutex);
+       mutex_unlock(&ctx->file->file_mutex);
 }
 
 static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
@@ -205,36 +206,6 @@ error:
        return NULL;
 }
 
-static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
-                                 struct ib_sa_path_rec  *kpath)
-{
-       if (!kpath || !upath)
-               return;
-
-       memcpy(upath->dgid, kpath->dgid.raw, sizeof *upath->dgid);
-       memcpy(upath->sgid, kpath->sgid.raw, sizeof *upath->sgid);
-
-       upath->dlid             = kpath->dlid;
-       upath->slid             = kpath->slid;
-       upath->raw_traffic      = kpath->raw_traffic;
-       upath->flow_label       = kpath->flow_label;
-       upath->hop_limit        = kpath->hop_limit;
-       upath->traffic_class    = kpath->traffic_class;
-       upath->reversible       = kpath->reversible;
-       upath->numb_path        = kpath->numb_path;
-       upath->pkey             = kpath->pkey;
-       upath->sl               = kpath->sl;
-       upath->mtu_selector     = kpath->mtu_selector;
-       upath->mtu              = kpath->mtu;
-       upath->rate_selector    = kpath->rate_selector;
-       upath->rate             = kpath->rate;
-       upath->packet_life_time = kpath->packet_life_time;
-       upath->preference       = kpath->preference;
-
-       upath->packet_life_time_selector =
-               kpath->packet_life_time_selector;
-}
-
 static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
                                 struct ib_cm_req_event_param *kreq)
 {
@@ -253,8 +224,10 @@ static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
        ureq->srq                        = kreq->srq;
        ureq->port                       = kreq->port;
 
-       ib_ucm_event_path_get(&ureq->primary_path, kreq->primary_path);
-       ib_ucm_event_path_get(&ureq->alternate_path, kreq->alternate_path);
+       ib_copy_path_rec_to_user(&ureq->primary_path, kreq->primary_path);
+       if (kreq->alternate_path)
+               ib_copy_path_rec_to_user(&ureq->alternate_path,
+                                        kreq->alternate_path);
 }
 
 static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
@@ -324,8 +297,8 @@ static int ib_ucm_event_process(struct ib_cm_event *evt,
                info          = evt->param.rej_rcvd.ari;
                break;
        case IB_CM_LAP_RECEIVED:
-               ib_ucm_event_path_get(&uvt->resp.u.lap_resp.path,
-                                     evt->param.lap_rcvd.alternate_path);
+               ib_copy_path_rec_to_user(&uvt->resp.u.lap_resp.path,
+                                        evt->param.lap_rcvd.alternate_path);
                uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE;
                uvt->resp.present = IB_UCM_PRES_ALTERNATE;
                break;
@@ -402,11 +375,11 @@ static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
        if (result)
                goto err2;
 
-       down(&ctx->file->mutex);
+       mutex_lock(&ctx->file->file_mutex);
        list_add_tail(&uevent->file_list, &ctx->file->events);
        list_add_tail(&uevent->ctx_list, &ctx->events);
        wake_up_interruptible(&ctx->file->poll_wait);
-       up(&ctx->file->mutex);
+       mutex_unlock(&ctx->file->file_mutex);
        return 0;
 
 err2:
@@ -432,7 +405,7 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
                return -EFAULT;
 
-       down(&file->mutex);
+       mutex_lock(&file->file_mutex);
        while (list_empty(&file->events)) {
 
                if (file->filp->f_flags & O_NONBLOCK) {
@@ -447,9 +420,9 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
 
                prepare_to_wait(&file->poll_wait, &wait, TASK_INTERRUPTIBLE);
 
-               up(&file->mutex);
+               mutex_unlock(&file->file_mutex);
                schedule();
-               down(&file->mutex);
+               mutex_lock(&file->file_mutex);
 
                finish_wait(&file->poll_wait, &wait);
        }
@@ -509,7 +482,7 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
        kfree(uevent->info);
        kfree(uevent);
 done:
-       up(&file->mutex);
+       mutex_unlock(&file->file_mutex);
        return result;
 }
 
@@ -528,9 +501,9 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
                return -EFAULT;
 
-       down(&file->mutex);
+       mutex_lock(&file->file_mutex);
        ctx = ib_ucm_ctx_alloc(file);
-       up(&file->mutex);
+       mutex_unlock(&file->file_mutex);
        if (!ctx)
                return -ENOMEM;
 
@@ -637,65 +610,11 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
        return result;
 }
 
-static void ib_ucm_copy_ah_attr(struct ib_ucm_ah_attr *dest_attr,
-                               struct ib_ah_attr *src_attr)
-{
-       memcpy(dest_attr->grh_dgid, src_attr->grh.dgid.raw,
-              sizeof src_attr->grh.dgid);
-       dest_attr->grh_flow_label = src_attr->grh.flow_label;
-       dest_attr->grh_sgid_index = src_attr->grh.sgid_index;
-       dest_attr->grh_hop_limit = src_attr->grh.hop_limit;
-       dest_attr->grh_traffic_class = src_attr->grh.traffic_class;
-
-       dest_attr->dlid = src_attr->dlid;
-       dest_attr->sl = src_attr->sl;
-       dest_attr->src_path_bits = src_attr->src_path_bits;
-       dest_attr->static_rate = src_attr->static_rate;
-       dest_attr->is_global = (src_attr->ah_flags & IB_AH_GRH);
-       dest_attr->port_num = src_attr->port_num;
-}
-
-static void ib_ucm_copy_qp_attr(struct ib_ucm_init_qp_attr_resp *dest_attr,
-                               struct ib_qp_attr *src_attr)
-{
-       dest_attr->cur_qp_state = src_attr->cur_qp_state;
-       dest_attr->path_mtu = src_attr->path_mtu;
-       dest_attr->path_mig_state = src_attr->path_mig_state;
-       dest_attr->qkey = src_attr->qkey;
-       dest_attr->rq_psn = src_attr->rq_psn;
-       dest_attr->sq_psn = src_attr->sq_psn;
-       dest_attr->dest_qp_num = src_attr->dest_qp_num;
-       dest_attr->qp_access_flags = src_attr->qp_access_flags;
-
-       dest_attr->max_send_wr = src_attr->cap.max_send_wr;
-       dest_attr->max_recv_wr = src_attr->cap.max_recv_wr;
-       dest_attr->max_send_sge = src_attr->cap.max_send_sge;
-       dest_attr->max_recv_sge = src_attr->cap.max_recv_sge;
-       dest_attr->max_inline_data = src_attr->cap.max_inline_data;
-
-       ib_ucm_copy_ah_attr(&dest_attr->ah_attr, &src_attr->ah_attr);
-       ib_ucm_copy_ah_attr(&dest_attr->alt_ah_attr, &src_attr->alt_ah_attr);
-
-       dest_attr->pkey_index = src_attr->pkey_index;
-       dest_attr->alt_pkey_index = src_attr->alt_pkey_index;
-       dest_attr->en_sqd_async_notify = src_attr->en_sqd_async_notify;
-       dest_attr->sq_draining = src_attr->sq_draining;
-       dest_attr->max_rd_atomic = src_attr->max_rd_atomic;
-       dest_attr->max_dest_rd_atomic = src_attr->max_dest_rd_atomic;
-       dest_attr->min_rnr_timer = src_attr->min_rnr_timer;
-       dest_attr->port_num = src_attr->port_num;
-       dest_attr->timeout = src_attr->timeout;
-       dest_attr->retry_cnt = src_attr->retry_cnt;
-       dest_attr->rnr_retry = src_attr->rnr_retry;
-       dest_attr->alt_port_num = src_attr->alt_port_num;
-       dest_attr->alt_timeout = src_attr->alt_timeout;
-}
-
 static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file,
                                   const char __user *inbuf,
                                   int in_len, int out_len)
 {
-       struct ib_ucm_init_qp_attr_resp resp;
+       struct ib_uverbs_qp_attr resp;
        struct ib_ucm_init_qp_attr cmd;
        struct ib_ucm_context *ctx;
        struct ib_qp_attr qp_attr;
@@ -718,7 +637,7 @@ static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file,
        if (result)
                goto out;
 
-       ib_ucm_copy_qp_attr(&resp, &qp_attr);
+       ib_copy_qp_attr_to_user(&resp, &qp_attr);
 
        if (copy_to_user((void __user *)(unsigned long)cmd.response,
                         &resp, sizeof(resp)))
@@ -729,6 +648,17 @@ out:
        return result;
 }
 
+static int ucm_validate_listen(__be64 service_id, __be64 service_mask)
+{
+       service_id &= service_mask;
+
+       if (((service_id & IB_CMA_SERVICE_ID_MASK) == IB_CMA_SERVICE_ID) ||
+           ((service_id & IB_SDP_SERVICE_ID_MASK) == IB_SDP_SERVICE_ID))
+               return -EINVAL;
+
+       return 0;
+}
+
 static ssize_t ib_ucm_listen(struct ib_ucm_file *file,
                             const char __user *inbuf,
                             int in_len, int out_len)
@@ -744,7 +674,13 @@ static ssize_t ib_ucm_listen(struct ib_ucm_file *file,
        if (IS_ERR(ctx))
                return PTR_ERR(ctx);
 
-       result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask);
+       result = ucm_validate_listen(cmd.service_id, cmd.service_mask);
+       if (result)
+               goto out;
+
+       result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask,
+                             NULL);
+out:
        ib_ucm_ctx_put(ctx);
        return result;
 }
@@ -793,7 +729,7 @@ static int ib_ucm_alloc_data(const void **dest, u64 src, u32 len)
 
 static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src)
 {
-       struct ib_ucm_path_rec ucm_path;
+       struct ib_user_path_rec upath;
        struct ib_sa_path_rec  *sa_path;
 
        *path = NULL;
@@ -805,36 +741,14 @@ static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src)
        if (!sa_path)
                return -ENOMEM;
 
-       if (copy_from_user(&ucm_path, (void __user *)(unsigned long)src,
-                          sizeof(ucm_path))) {
+       if (copy_from_user(&upath, (void __user *)(unsigned long)src,
+                          sizeof(upath))) {
 
                kfree(sa_path);
                return -EFAULT;
        }
 
-       memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid);
-       memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid);
-
-       sa_path->dlid             = ucm_path.dlid;
-       sa_path->slid             = ucm_path.slid;
-       sa_path->raw_traffic      = ucm_path.raw_traffic;
-       sa_path->flow_label       = ucm_path.flow_label;
-       sa_path->hop_limit        = ucm_path.hop_limit;
-       sa_path->traffic_class    = ucm_path.traffic_class;
-       sa_path->reversible       = ucm_path.reversible;
-       sa_path->numb_path        = ucm_path.numb_path;
-       sa_path->pkey             = ucm_path.pkey;
-       sa_path->sl               = ucm_path.sl;
-       sa_path->mtu_selector     = ucm_path.mtu_selector;
-       sa_path->mtu              = ucm_path.mtu;
-       sa_path->rate_selector    = ucm_path.rate_selector;
-       sa_path->rate             = ucm_path.rate;
-       sa_path->packet_life_time = ucm_path.packet_life_time;
-       sa_path->preference       = ucm_path.preference;
-
-       sa_path->packet_life_time_selector =
-               ucm_path.packet_life_time_selector;
-
+       ib_copy_path_rec_from_user(sa_path, &upath);
        *path = sa_path;
        return 0;
 }
@@ -1130,7 +1044,6 @@ static ssize_t ib_ucm_send_sidr_req(struct ib_ucm_file *file,
        param.service_id       = cmd.sid;
        param.timeout_ms       = cmd.timeout;
        param.max_cm_retries   = cmd.max_cm_retries;
-       param.pkey             = cmd.pkey;
 
        ctx = ib_ucm_ctx_get(file, cmd.id);
        if (!IS_ERR(ctx)) {
@@ -1263,7 +1176,7 @@ static int ib_ucm_open(struct inode *inode, struct file *filp)
        INIT_LIST_HEAD(&file->ctxs);
        init_waitqueue_head(&file->poll_wait);
 
-       init_MUTEX(&file->mutex);
+       mutex_init(&file->file_mutex);
 
        filp->private_data = file;
        file->filp = filp;
@@ -1277,11 +1190,11 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
        struct ib_ucm_file *file = filp->private_data;
        struct ib_ucm_context *ctx;
 
-       down(&file->mutex);
+       mutex_lock(&file->file_mutex);
        while (!list_empty(&file->ctxs)) {
                ctx = list_entry(file->ctxs.next,
                                 struct ib_ucm_context, file_list);
-               up(&file->mutex);
+               mutex_unlock(&file->file_mutex);
 
                mutex_lock(&ctx_id_mutex);
                idr_remove(&ctx_id_table, ctx->id);
@@ -1291,9 +1204,9 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
                ib_ucm_cleanup_events(ctx);
                kfree(ctx);
 
-               down(&file->mutex);
+               mutex_lock(&file->file_mutex);
        }
-       up(&file->mutex);
+       mutex_unlock(&file->file_mutex);
        kfree(file);
        return 0;
 }
index 3372d67ff139eb51232f96ad287e50608e5998ef..bb9bee56a824a9ea5b1da2417a882a12aab11f16 100644 (file)
@@ -132,7 +132,7 @@ struct ib_ucq_object {
        u32                     async_events_reported;
 };
 
-extern struct mutex ib_uverbs_idr_mutex;
+extern spinlock_t ib_uverbs_idr_lock;
 extern struct idr ib_uverbs_pd_idr;
 extern struct idr ib_uverbs_mr_idr;
 extern struct idr ib_uverbs_mw_idr;
@@ -141,6 +141,8 @@ extern struct idr ib_uverbs_cq_idr;
 extern struct idr ib_uverbs_qp_idr;
 extern struct idr ib_uverbs_srq_idr;
 
+void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
+
 struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
                                        int is_async, int *fd);
 void ib_uverbs_release_event_file(struct kref *ref);
index 9f69bd48eb1bee6ccf488f0e71a7777efd7f5f0d..76bf61e9b552424e37347b7cd52a3e92bff30ed5 100644 (file)
                (udata)->outlen = (olen);                               \
        } while (0)
 
+/*
+ * The ib_uobject locking scheme is as follows:
+ *
+ * - ib_uverbs_idr_lock protects the uverbs idrs themselves, so it
+ *   needs to be held during all idr operations.  When an object is
+ *   looked up, a reference must be taken on the object's kref before
+ *   dropping this lock.
+ *
+ * - Each object also has an rwsem.  This rwsem must be held for
+ *   reading while an operation that uses the object is performed.
+ *   For example, while registering an MR, the associated PD's
+ *   uobject.mutex must be held for reading.  The rwsem must be held
+ *   for writing while initializing or destroying an object.
+ *
+ * - In addition, each object has a "live" flag.  If this flag is not
+ *   set, then lookups of the object will fail even if it is found in
+ *   the idr.  This handles a reader that blocks and does not acquire
+ *   the rwsem until after the object is destroyed.  The destroy
+ *   operation will set the live flag to 0 and then drop the rwsem;
+ *   this will allow the reader to acquire the rwsem, see that the
+ *   live flag is 0, and then drop the rwsem and its reference to
+ *   object.  The underlying storage will not be freed until the last
+ *   reference to the object is dropped.
+ */
+
+static void init_uobj(struct ib_uobject *uobj, u64 user_handle,
+                     struct ib_ucontext *context)
+{
+       uobj->user_handle = user_handle;
+       uobj->context     = context;
+       kref_init(&uobj->ref);
+       init_rwsem(&uobj->mutex);
+       uobj->live        = 0;
+}
+
+static void release_uobj(struct kref *kref)
+{
+       kfree(container_of(kref, struct ib_uobject, ref));
+}
+
+static void put_uobj(struct ib_uobject *uobj)
+{
+       kref_put(&uobj->ref, release_uobj);
+}
+
+static void put_uobj_read(struct ib_uobject *uobj)
+{
+       up_read(&uobj->mutex);
+       put_uobj(uobj);
+}
+
+static void put_uobj_write(struct ib_uobject *uobj)
+{
+       up_write(&uobj->mutex);
+       put_uobj(uobj);
+}
+
+static int idr_add_uobj(struct idr *idr, struct ib_uobject *uobj)
+{
+       int ret;
+
+retry:
+       if (!idr_pre_get(idr, GFP_KERNEL))
+               return -ENOMEM;
+
+       spin_lock(&ib_uverbs_idr_lock);
+       ret = idr_get_new(idr, uobj, &uobj->id);
+       spin_unlock(&ib_uverbs_idr_lock);
+
+       if (ret == -EAGAIN)
+               goto retry;
+
+       return ret;
+}
+
+void idr_remove_uobj(struct idr *idr, struct ib_uobject *uobj)
+{
+       spin_lock(&ib_uverbs_idr_lock);
+       idr_remove(idr, uobj->id);
+       spin_unlock(&ib_uverbs_idr_lock);
+}
+
+static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
+                                        struct ib_ucontext *context)
+{
+       struct ib_uobject *uobj;
+
+       spin_lock(&ib_uverbs_idr_lock);
+       uobj = idr_find(idr, id);
+       if (uobj)
+               kref_get(&uobj->ref);
+       spin_unlock(&ib_uverbs_idr_lock);
+
+       return uobj;
+}
+
+static struct ib_uobject *idr_read_uobj(struct idr *idr, int id,
+                                       struct ib_ucontext *context)
+{
+       struct ib_uobject *uobj;
+
+       uobj = __idr_get_uobj(idr, id, context);
+       if (!uobj)
+               return NULL;
+
+       down_read(&uobj->mutex);
+       if (!uobj->live) {
+               put_uobj_read(uobj);
+               return NULL;
+       }
+
+       return uobj;
+}
+
+static struct ib_uobject *idr_write_uobj(struct idr *idr, int id,
+                                        struct ib_ucontext *context)
+{
+       struct ib_uobject *uobj;
+
+       uobj = __idr_get_uobj(idr, id, context);
+       if (!uobj)
+               return NULL;
+
+       down_write(&uobj->mutex);
+       if (!uobj->live) {
+               put_uobj_write(uobj);
+               return NULL;
+       }
+
+       return uobj;
+}
+
+static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context)
+{
+       struct ib_uobject *uobj;
+
+       uobj = idr_read_uobj(idr, id, context);
+       return uobj ? uobj->object : NULL;
+}
+
+static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context)
+{
+       return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context);
+}
+
+static void put_pd_read(struct ib_pd *pd)
+{
+       put_uobj_read(pd->uobject);
+}
+
+static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context)
+{
+       return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context);
+}
+
+static void put_cq_read(struct ib_cq *cq)
+{
+       put_uobj_read(cq->uobject);
+}
+
+static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context)
+{
+       return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context);
+}
+
+static void put_ah_read(struct ib_ah *ah)
+{
+       put_uobj_read(ah->uobject);
+}
+
+static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context)
+{
+       return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context);
+}
+
+static void put_qp_read(struct ib_qp *qp)
+{
+       put_uobj_read(qp->uobject);
+}
+
+static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context)
+{
+       return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context);
+}
+
+static void put_srq_read(struct ib_srq *srq)
+{
+       put_uobj_read(srq->uobject);
+}
+
 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
                              const char __user *buf,
                              int in_len, int out_len)
@@ -80,8 +270,10 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
                   in_len - sizeof cmd, out_len - sizeof resp);
 
        ucontext = ibdev->alloc_ucontext(ibdev, &udata);
-       if (IS_ERR(ucontext))
-               return PTR_ERR(file->ucontext);
+       if (IS_ERR(ucontext)) {
+               ret = PTR_ERR(file->ucontext);
+               goto err;
+       }
 
        ucontext->device = ibdev;
        INIT_LIST_HEAD(&ucontext->pd_list);
@@ -278,7 +470,8 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
        if (!uobj)
                return -ENOMEM;
 
-       uobj->context = file->ucontext;
+       init_uobj(uobj, 0, file->ucontext);
+       down_write(&uobj->mutex);
 
        pd = file->device->ib_dev->alloc_pd(file->device->ib_dev,
                                            file->ucontext, &udata);
@@ -291,20 +484,10 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
        pd->uobject = uobj;
        atomic_set(&pd->usecnt, 0);
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-retry:
-       if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
-               ret = -ENOMEM;
-               goto err_up;
-       }
-
-       ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id);
-
-       if (ret == -EAGAIN)
-               goto retry;
+       uobj->object = pd;
+       ret = idr_add_uobj(&ib_uverbs_pd_idr, uobj);
        if (ret)
-               goto err_up;
+               goto err_idr;
 
        memset(&resp, 0, sizeof resp);
        resp.pd_handle = uobj->id;
@@ -312,26 +495,27 @@ retry:
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_idr;
+               goto err_copy;
        }
 
        mutex_lock(&file->mutex);
        list_add_tail(&uobj->list, &file->ucontext->pd_list);
        mutex_unlock(&file->mutex);
 
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       uobj->live = 1;
+
+       up_write(&uobj->mutex);
 
        return in_len;
 
-err_idr:
-       idr_remove(&ib_uverbs_pd_idr, uobj->id);
+err_copy:
+       idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
 
-err_up:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+err_idr:
        ib_dealloc_pd(pd);
 
 err:
-       kfree(uobj);
+       put_uobj_write(uobj);
        return ret;
 }
 
@@ -340,37 +524,34 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
                             int in_len, int out_len)
 {
        struct ib_uverbs_dealloc_pd cmd;
-       struct ib_pd               *pd;
        struct ib_uobject          *uobj;
-       int                         ret = -EINVAL;
+       int                         ret;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
+       uobj = idr_write_uobj(&ib_uverbs_pd_idr, cmd.pd_handle, file->ucontext);
+       if (!uobj)
+               return -EINVAL;
 
-       pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
-       if (!pd || pd->uobject->context != file->ucontext)
-               goto out;
+       ret = ib_dealloc_pd(uobj->object);
+       if (!ret)
+               uobj->live = 0;
 
-       uobj = pd->uobject;
+       put_uobj_write(uobj);
 
-       ret = ib_dealloc_pd(pd);
        if (ret)
-               goto out;
+               return ret;
 
-       idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
+       idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
 
        mutex_lock(&file->mutex);
        list_del(&uobj->list);
        mutex_unlock(&file->mutex);
 
-       kfree(uobj);
-
-out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       put_uobj(uobj);
 
-       return ret ? ret : in_len;
+       return in_len;
 }
 
 ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
@@ -410,7 +591,8 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
        if (!obj)
                return -ENOMEM;
 
-       obj->uobject.context = file->ucontext;
+       init_uobj(&obj->uobject, 0, file->ucontext);
+       down_write(&obj->uobject.mutex);
 
        /*
         * We ask for writable memory if any access flags other than
@@ -427,23 +609,14 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
 
        obj->umem.virt_base = cmd.hca_va;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
-       if (!pd || pd->uobject->context != file->ucontext) {
-               ret = -EINVAL;
-               goto err_up;
-       }
-
-       if (!pd->device->reg_user_mr) {
-               ret = -ENOSYS;
-               goto err_up;
-       }
+       pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+       if (!pd)
+               goto err_release;
 
        mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata);
        if (IS_ERR(mr)) {
                ret = PTR_ERR(mr);
-               goto err_up;
+               goto err_put;
        }
 
        mr->device  = pd->device;
@@ -452,53 +625,48 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
        atomic_inc(&pd->usecnt);
        atomic_set(&mr->usecnt, 0);
 
-       memset(&resp, 0, sizeof resp);
-       resp.lkey = mr->lkey;
-       resp.rkey = mr->rkey;
-
-retry:
-       if (!idr_pre_get(&ib_uverbs_mr_idr, GFP_KERNEL)) {
-               ret = -ENOMEM;
-               goto err_unreg;
-       }
-
-       ret = idr_get_new(&ib_uverbs_mr_idr, mr, &obj->uobject.id);
-
-       if (ret == -EAGAIN)
-               goto retry;
+       obj->uobject.object = mr;
+       ret = idr_add_uobj(&ib_uverbs_mr_idr, &obj->uobject);
        if (ret)
                goto err_unreg;
 
+       memset(&resp, 0, sizeof resp);
+       resp.lkey      = mr->lkey;
+       resp.rkey      = mr->rkey;
        resp.mr_handle = obj->uobject.id;
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_idr;
+               goto err_copy;
        }
 
+       put_pd_read(pd);
+
        mutex_lock(&file->mutex);
        list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
        mutex_unlock(&file->mutex);
 
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       obj->uobject.live = 1;
+
+       up_write(&obj->uobject.mutex);
 
        return in_len;
 
-err_idr:
-       idr_remove(&ib_uverbs_mr_idr, obj->uobject.id);
+err_copy:
+       idr_remove_uobj(&ib_uverbs_mr_idr, &obj->uobject);
 
 err_unreg:
        ib_dereg_mr(mr);
-       atomic_dec(&pd->usecnt);
 
-err_up:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+err_put:
+       put_pd_read(pd);
 
+err_release:
        ib_umem_release(file->device->ib_dev, &obj->umem);
 
 err_free:
-       kfree(obj);
+       put_uobj_write(&obj->uobject);
        return ret;
 }
 
@@ -508,37 +676,40 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
 {
        struct ib_uverbs_dereg_mr cmd;
        struct ib_mr             *mr;
+       struct ib_uobject        *uobj;
        struct ib_umem_object    *memobj;
        int                       ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle);
-       if (!mr || mr->uobject->context != file->ucontext)
-               goto out;
+       uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle, file->ucontext);
+       if (!uobj)
+               return -EINVAL;
 
-       memobj = container_of(mr->uobject, struct ib_umem_object, uobject);
+       memobj = container_of(uobj, struct ib_umem_object, uobject);
+       mr     = uobj->object;
 
        ret = ib_dereg_mr(mr);
+       if (!ret)
+               uobj->live = 0;
+
+       put_uobj_write(uobj);
+
        if (ret)
-               goto out;
+               return ret;
 
-       idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
+       idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
 
        mutex_lock(&file->mutex);
-       list_del(&memobj->uobject.list);
+       list_del(&uobj->list);
        mutex_unlock(&file->mutex);
 
        ib_umem_release(file->device->ib_dev, &memobj->umem);
-       kfree(memobj);
 
-out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       put_uobj(uobj);
 
-       return ret ? ret : in_len;
+       return in_len;
 }
 
 ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
@@ -577,7 +748,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
        struct ib_uverbs_create_cq      cmd;
        struct ib_uverbs_create_cq_resp resp;
        struct ib_udata                 udata;
-       struct ib_ucq_object           *uobj;
+       struct ib_ucq_object           *obj;
        struct ib_uverbs_event_file    *ev_file = NULL;
        struct ib_cq                   *cq;
        int                             ret;
@@ -595,10 +766,13 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
        if (cmd.comp_vector >= file->device->num_comp_vectors)
                return -EINVAL;
 
-       uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
-       if (!uobj)
+       obj = kmalloc(sizeof *obj, GFP_KERNEL);
+       if (!obj)
                return -ENOMEM;
 
+       init_uobj(&obj->uobject, cmd.user_handle, file->ucontext);
+       down_write(&obj->uobject.mutex);
+
        if (cmd.comp_channel >= 0) {
                ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);
                if (!ev_file) {
@@ -607,72 +781,64 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
                }
        }
 
-       uobj->uobject.user_handle   = cmd.user_handle;
-       uobj->uobject.context       = file->ucontext;
-       uobj->uverbs_file           = file;
-       uobj->comp_events_reported  = 0;
-       uobj->async_events_reported = 0;
-       INIT_LIST_HEAD(&uobj->comp_list);
-       INIT_LIST_HEAD(&uobj->async_list);
+       obj->uverbs_file           = file;
+       obj->comp_events_reported  = 0;
+       obj->async_events_reported = 0;
+       INIT_LIST_HEAD(&obj->comp_list);
+       INIT_LIST_HEAD(&obj->async_list);
 
        cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
                                             file->ucontext, &udata);
        if (IS_ERR(cq)) {
                ret = PTR_ERR(cq);
-               goto err;
+               goto err_file;
        }
 
        cq->device        = file->device->ib_dev;
-       cq->uobject       = &uobj->uobject;
+       cq->uobject       = &obj->uobject;
        cq->comp_handler  = ib_uverbs_comp_handler;
        cq->event_handler = ib_uverbs_cq_event_handler;
        cq->cq_context    = ev_file;
        atomic_set(&cq->usecnt, 0);
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-retry:
-       if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
-               ret = -ENOMEM;
-               goto err_up;
-       }
-
-       ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
-
-       if (ret == -EAGAIN)
-               goto retry;
+       obj->uobject.object = cq;
+       ret = idr_add_uobj(&ib_uverbs_cq_idr, &obj->uobject);
        if (ret)
-               goto err_up;
+               goto err_free;
 
        memset(&resp, 0, sizeof resp);
-       resp.cq_handle = uobj->uobject.id;
+       resp.cq_handle = obj->uobject.id;
        resp.cqe       = cq->cqe;
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_idr;
+               goto err_copy;
        }
 
        mutex_lock(&file->mutex);
-       list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
+       list_add_tail(&obj->uobject.list, &file->ucontext->cq_list);
        mutex_unlock(&file->mutex);
 
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       obj->uobject.live = 1;
+
+       up_write(&obj->uobject.mutex);
 
        return in_len;
 
-err_idr:
-       idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
+err_copy:
+       idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject);
+
 
-err_up:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+err_free:
        ib_destroy_cq(cq);
 
-err:
+err_file:
        if (ev_file)
-               ib_uverbs_release_ucq(file, ev_file, uobj);
-       kfree(uobj);
+               ib_uverbs_release_ucq(file, ev_file, obj);
+
+err:
+       put_uobj_write(&obj->uobject);
        return ret;
 }
 
@@ -693,11 +859,9 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
                   (unsigned long) cmd.response + sizeof resp,
                   in_len - sizeof cmd, out_len - sizeof resp);
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
-       if (!cq || cq->uobject->context != file->ucontext || !cq->device->resize_cq)
-               goto out;
+       cq = idr_read_cq(cmd.cq_handle, file->ucontext);
+       if (!cq)
+               return -EINVAL;
 
        ret = cq->device->resize_cq(cq, cmd.cqe, &udata);
        if (ret)
@@ -711,7 +875,7 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file,
                ret = -EFAULT;
 
 out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       put_cq_read(cq);
 
        return ret ? ret : in_len;
 }
@@ -722,6 +886,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
 {
        struct ib_uverbs_poll_cq       cmd;
        struct ib_uverbs_poll_cq_resp *resp;
+       struct ib_uobject             *uobj;
        struct ib_cq                  *cq;
        struct ib_wc                  *wc;
        int                            ret = 0;
@@ -742,15 +907,17 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                goto out_wc;
        }
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-       cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
-       if (!cq || cq->uobject->context != file->ucontext) {
+       uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext);
+       if (!uobj) {
                ret = -EINVAL;
                goto out;
        }
+       cq = uobj->object;
 
        resp->count = ib_poll_cq(cq, cmd.ne, wc);
 
+       put_uobj_read(uobj);
+
        for (i = 0; i < resp->count; i++) {
                resp->wc[i].wr_id          = wc[i].wr_id;
                resp->wc[i].status         = wc[i].status;
@@ -772,7 +939,6 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                ret = -EFAULT;
 
 out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
        kfree(resp);
 
 out_wc:
@@ -785,22 +951,23 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
                                int out_len)
 {
        struct ib_uverbs_req_notify_cq cmd;
+       struct ib_uobject             *uobj;
        struct ib_cq                  *cq;
-       int                            ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-       cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
-       if (cq && cq->uobject->context == file->ucontext) {
-               ib_req_notify_cq(cq, cmd.solicited_only ?
-                                       IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
-               ret = in_len;
-       }
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext);
+       if (!uobj)
+               return -EINVAL;
+       cq = uobj->object;
 
-       return ret;
+       ib_req_notify_cq(cq, cmd.solicited_only ?
+                        IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
+
+       put_uobj_read(uobj);
+
+       return in_len;
 }
 
 ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
@@ -809,52 +976,50 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
 {
        struct ib_uverbs_destroy_cq      cmd;
        struct ib_uverbs_destroy_cq_resp resp;
+       struct ib_uobject               *uobj;
        struct ib_cq                    *cq;
-       struct ib_ucq_object            *uobj;
+       struct ib_ucq_object            *obj;
        struct ib_uverbs_event_file     *ev_file;
-       u64                              user_handle;
        int                              ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       memset(&resp, 0, sizeof resp);
-
-       mutex_lock(&ib_uverbs_idr_mutex);
+       uobj = idr_write_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext);
+       if (!uobj)
+               return -EINVAL;
+       cq      = uobj->object;
+       ev_file = cq->cq_context;
+       obj     = container_of(cq->uobject, struct ib_ucq_object, uobject);
 
-       cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
-       if (!cq || cq->uobject->context != file->ucontext)
-               goto out;
+       ret = ib_destroy_cq(cq);
+       if (!ret)
+               uobj->live = 0;
 
-       user_handle = cq->uobject->user_handle;
-       uobj        = container_of(cq->uobject, struct ib_ucq_object, uobject);
-       ev_file     = cq->cq_context;
+       put_uobj_write(uobj);
 
-       ret = ib_destroy_cq(cq);
        if (ret)
-               goto out;
+               return ret;
 
-       idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
+       idr_remove_uobj(&ib_uverbs_cq_idr, uobj);
 
        mutex_lock(&file->mutex);
-       list_del(&uobj->uobject.list);
+       list_del(&uobj->list);
        mutex_unlock(&file->mutex);
 
-       ib_uverbs_release_ucq(file, ev_file, uobj);
+       ib_uverbs_release_ucq(file, ev_file, obj);
 
-       resp.comp_events_reported  = uobj->comp_events_reported;
-       resp.async_events_reported = uobj->async_events_reported;
+       memset(&resp, 0, sizeof resp);
+       resp.comp_events_reported  = obj->comp_events_reported;
+       resp.async_events_reported = obj->async_events_reported;
 
-       kfree(uobj);
+       put_uobj(uobj);
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp))
-               ret = -EFAULT;
-
-out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+               return -EFAULT;
 
-       return ret ? ret : in_len;
+       return in_len;
 }
 
 ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
@@ -864,7 +1029,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        struct ib_uverbs_create_qp      cmd;
        struct ib_uverbs_create_qp_resp resp;
        struct ib_udata                 udata;
-       struct ib_uqp_object           *uobj;
+       struct ib_uqp_object           *obj;
        struct ib_pd                   *pd;
        struct ib_cq                   *scq, *rcq;
        struct ib_srq                  *srq;
@@ -882,23 +1047,21 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
                   (unsigned long) cmd.response + sizeof resp,
                   in_len - sizeof cmd, out_len - sizeof resp);
 
-       uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
-       if (!uobj)
+       obj = kmalloc(sizeof *obj, GFP_KERNEL);
+       if (!obj)
                return -ENOMEM;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
+       init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext);
+       down_write(&obj->uevent.uobject.mutex);
 
-       pd  = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
-       scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
-       rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle);
-       srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL;
+       pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+       scq = idr_read_cq(cmd.send_cq_handle, file->ucontext);
+       rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext);
+       srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
 
-       if (!pd  || pd->uobject->context  != file->ucontext ||
-           !scq || scq->uobject->context != file->ucontext ||
-           !rcq || rcq->uobject->context != file->ucontext ||
-           (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) {
+       if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
                ret = -EINVAL;
-               goto err_up;
+               goto err_put;
        }
 
        attr.event_handler = ib_uverbs_qp_event_handler;
@@ -915,16 +1078,14 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        attr.cap.max_recv_sge    = cmd.max_recv_sge;
        attr.cap.max_inline_data = cmd.max_inline_data;
 
-       uobj->uevent.uobject.user_handle = cmd.user_handle;
-       uobj->uevent.uobject.context     = file->ucontext;
-       uobj->uevent.events_reported     = 0;
-       INIT_LIST_HEAD(&uobj->uevent.event_list);
-       INIT_LIST_HEAD(&uobj->mcast_list);
+       obj->uevent.events_reported     = 0;
+       INIT_LIST_HEAD(&obj->uevent.event_list);
+       INIT_LIST_HEAD(&obj->mcast_list);
 
        qp = pd->device->create_qp(pd, &attr, &udata);
        if (IS_ERR(qp)) {
                ret = PTR_ERR(qp);
-               goto err_up;
+               goto err_put;
        }
 
        qp->device        = pd->device;
@@ -932,7 +1093,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        qp->send_cq       = attr.send_cq;
        qp->recv_cq       = attr.recv_cq;
        qp->srq           = attr.srq;
-       qp->uobject       = &uobj->uevent.uobject;
+       qp->uobject       = &obj->uevent.uobject;
        qp->event_handler = attr.event_handler;
        qp->qp_context    = attr.qp_context;
        qp->qp_type       = attr.qp_type;
@@ -942,23 +1103,14 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        if (attr.srq)
                atomic_inc(&attr.srq->usecnt);
 
-       memset(&resp, 0, sizeof resp);
-       resp.qpn = qp->qp_num;
-
-retry:
-       if (!idr_pre_get(&ib_uverbs_qp_idr, GFP_KERNEL)) {
-               ret = -ENOMEM;
-               goto err_destroy;
-       }
-
-       ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uevent.uobject.id);
-
-       if (ret == -EAGAIN)
-               goto retry;
+       obj->uevent.uobject.object = qp;
+       ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
        if (ret)
                goto err_destroy;
 
-       resp.qp_handle       = uobj->uevent.uobject.id;
+       memset(&resp, 0, sizeof resp);
+       resp.qpn             = qp->qp_num;
+       resp.qp_handle       = obj->uevent.uobject.id;
        resp.max_recv_sge    = attr.cap.max_recv_sge;
        resp.max_send_sge    = attr.cap.max_send_sge;
        resp.max_recv_wr     = attr.cap.max_recv_wr;
@@ -968,32 +1120,42 @@ retry:
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_idr;
+               goto err_copy;
        }
 
+       put_pd_read(pd);
+       put_cq_read(scq);
+       put_cq_read(rcq);
+       if (srq)
+               put_srq_read(srq);
+
        mutex_lock(&file->mutex);
-       list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list);
+       list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
        mutex_unlock(&file->mutex);
 
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       obj->uevent.uobject.live = 1;
+
+       up_write(&obj->uevent.uobject.mutex);
 
        return in_len;
 
-err_idr:
-       idr_remove(&ib_uverbs_qp_idr, uobj->uevent.uobject.id);
+err_copy:
+       idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
 
 err_destroy:
        ib_destroy_qp(qp);
-       atomic_dec(&pd->usecnt);
-       atomic_dec(&attr.send_cq->usecnt);
-       atomic_dec(&attr.recv_cq->usecnt);
-       if (attr.srq)
-               atomic_dec(&attr.srq->usecnt);
-
-err_up:
-       mutex_unlock(&ib_uverbs_idr_mutex);
 
-       kfree(uobj);
+err_put:
+       if (pd)
+               put_pd_read(pd);
+       if (scq)
+               put_cq_read(scq);
+       if (rcq)
+               put_cq_read(rcq);
+       if (srq)
+               put_srq_read(srq);
+
+       put_uobj_write(&obj->uevent.uobject);
        return ret;
 }
 
@@ -1018,15 +1180,15 @@ ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file,
                goto out;
        }
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-       if (qp && qp->uobject->context == file->ucontext)
-               ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr);
-       else
+       qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+       if (!qp) {
                ret = -EINVAL;
+               goto out;
+       }
 
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr);
+
+       put_qp_read(qp);
 
        if (ret)
                goto out;
@@ -1113,10 +1275,8 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
        if (!attr)
                return -ENOMEM;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-       if (!qp || qp->uobject->context != file->ucontext) {
+       qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+       if (!qp) {
                ret = -EINVAL;
                goto out;
        }
@@ -1168,13 +1328,15 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
        attr->alt_ah_attr.port_num          = cmd.alt_dest.port_num;
 
        ret = ib_modify_qp(qp, attr, cmd.attr_mask);
+
+       put_qp_read(qp);
+
        if (ret)
                goto out;
 
        ret = in_len;
 
 out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
        kfree(attr);
 
        return ret;
@@ -1186,8 +1348,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
 {
        struct ib_uverbs_destroy_qp      cmd;
        struct ib_uverbs_destroy_qp_resp resp;
+       struct ib_uobject               *uobj;
        struct ib_qp                    *qp;
-       struct ib_uqp_object            *uobj;
+       struct ib_uqp_object            *obj;
        int                              ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1195,43 +1358,43 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
 
        memset(&resp, 0, sizeof resp);
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-       if (!qp || qp->uobject->context != file->ucontext)
-               goto out;
-
-       uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
+       uobj = idr_write_uobj(&ib_uverbs_qp_idr, cmd.qp_handle, file->ucontext);
+       if (!uobj)
+               return -EINVAL;
+       qp  = uobj->object;
+       obj = container_of(uobj, struct ib_uqp_object, uevent.uobject);
 
-       if (!list_empty(&uobj->mcast_list)) {
-               ret = -EBUSY;
-               goto out;
+       if (!list_empty(&obj->mcast_list)) {
+               put_uobj_write(uobj);
+               return -EBUSY;
        }
 
        ret = ib_destroy_qp(qp);
+       if (!ret)
+               uobj->live = 0;
+
+       put_uobj_write(uobj);
+
        if (ret)
-               goto out;
+               return ret;
 
-       idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
+       idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
 
        mutex_lock(&file->mutex);
-       list_del(&uobj->uevent.uobject.list);
+       list_del(&uobj->list);
        mutex_unlock(&file->mutex);
 
-       ib_uverbs_release_uevent(file, &uobj->uevent);
+       ib_uverbs_release_uevent(file, &obj->uevent);
 
-       resp.events_reported = uobj->uevent.events_reported;
+       resp.events_reported = obj->uevent.events_reported;
 
-       kfree(uobj);
+       put_uobj(uobj);
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp))
-               ret = -EFAULT;
-
-out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+               return -EFAULT;
 
-       return ret ? ret : in_len;
+       return in_len;
 }
 
 ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
@@ -1244,6 +1407,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
        struct ib_send_wr              *wr = NULL, *last, *next, *bad_wr;
        struct ib_qp                   *qp;
        int                             i, sg_ind;
+       int                             is_ud;
        ssize_t                         ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1260,12 +1424,11 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
        if (!user_wr)
                return -ENOMEM;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-       if (!qp || qp->uobject->context != file->ucontext)
+       qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+       if (!qp)
                goto out;
 
+       is_ud = qp->qp_type == IB_QPT_UD;
        sg_ind = 0;
        last = NULL;
        for (i = 0; i < cmd.wr_count; ++i) {
@@ -1273,12 +1436,12 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                                   buf + sizeof cmd + i * cmd.wqe_size,
                                   cmd.wqe_size)) {
                        ret = -EFAULT;
-                       goto out;
+                       goto out_put;
                }
 
                if (user_wr->num_sge + sg_ind > cmd.sge_count) {
                        ret = -EINVAL;
-                       goto out;
+                       goto out_put;
                }
 
                next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
@@ -1286,7 +1449,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                               GFP_KERNEL);
                if (!next) {
                        ret = -ENOMEM;
-                       goto out;
+                       goto out_put;
                }
 
                if (!last)
@@ -1302,12 +1465,12 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                next->send_flags = user_wr->send_flags;
                next->imm_data   = (__be32 __force) user_wr->imm_data;
 
-               if (qp->qp_type == IB_QPT_UD) {
-                       next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr,
-                                                 user_wr->wr.ud.ah);
+               if (is_ud) {
+                       next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
+                                                    file->ucontext);
                        if (!next->wr.ud.ah) {
                                ret = -EINVAL;
-                               goto out;
+                               goto out_put;
                        }
                        next->wr.ud.remote_qpn  = user_wr->wr.ud.remote_qpn;
                        next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
@@ -1344,7 +1507,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                                           sg_ind * sizeof (struct ib_sge),
                                           next->num_sge * sizeof (struct ib_sge))) {
                                ret = -EFAULT;
-                               goto out;
+                               goto out_put;
                        }
                        sg_ind += next->num_sge;
                } else
@@ -1364,10 +1527,13 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                         &resp, sizeof resp))
                ret = -EFAULT;
 
-out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+out_put:
+       put_qp_read(qp);
 
+out:
        while (wr) {
+               if (is_ud && wr->wr.ud.ah)
+                       put_ah_read(wr->wr.ud.ah);
                next = wr->next;
                kfree(wr);
                wr = next;
@@ -1482,14 +1648,15 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
        if (IS_ERR(wr))
                return PTR_ERR(wr);
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-       if (!qp || qp->uobject->context != file->ucontext)
+       qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+       if (!qp)
                goto out;
 
        resp.bad_wr = 0;
        ret = qp->device->post_recv(qp, wr, &bad_wr);
+
+       put_qp_read(qp);
+
        if (ret)
                for (next = wr; next; next = next->next) {
                        ++resp.bad_wr;
@@ -1503,8 +1670,6 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
                ret = -EFAULT;
 
 out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
-
        while (wr) {
                next = wr->next;
                kfree(wr);
@@ -1533,14 +1698,15 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
        if (IS_ERR(wr))
                return PTR_ERR(wr);
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
-       if (!srq || srq->uobject->context != file->ucontext)
+       srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+       if (!srq)
                goto out;
 
        resp.bad_wr = 0;
        ret = srq->device->post_srq_recv(srq, wr, &bad_wr);
+
+       put_srq_read(srq);
+
        if (ret)
                for (next = wr; next; next = next->next) {
                        ++resp.bad_wr;
@@ -1554,8 +1720,6 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
                ret = -EFAULT;
 
 out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
-
        while (wr) {
                next = wr->next;
                kfree(wr);
@@ -1587,17 +1751,15 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
        if (!uobj)
                return -ENOMEM;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
+       init_uobj(uobj, cmd.user_handle, file->ucontext);
+       down_write(&uobj->mutex);
 
-       pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
-       if (!pd || pd->uobject->context != file->ucontext) {
+       pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+       if (!pd) {
                ret = -EINVAL;
-               goto err_up;
+               goto err;
        }
 
-       uobj->user_handle = cmd.user_handle;
-       uobj->context     = file->ucontext;
-
        attr.dlid              = cmd.attr.dlid;
        attr.sl                = cmd.attr.sl;
        attr.src_path_bits     = cmd.attr.src_path_bits;
@@ -1613,21 +1775,13 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
        ah = ib_create_ah(pd, &attr);
        if (IS_ERR(ah)) {
                ret = PTR_ERR(ah);
-               goto err_up;
-       }
-
-       ah->uobject = uobj;
-
-retry:
-       if (!idr_pre_get(&ib_uverbs_ah_idr, GFP_KERNEL)) {
-               ret = -ENOMEM;
-               goto err_destroy;
+               goto err;
        }
 
-       ret = idr_get_new(&ib_uverbs_ah_idr, ah, &uobj->id);
+       ah->uobject  = uobj;
+       uobj->object = ah;
 
-       if (ret == -EAGAIN)
-               goto retry;
+       ret = idr_add_uobj(&ib_uverbs_ah_idr, uobj);
        if (ret)
                goto err_destroy;
 
@@ -1636,27 +1790,29 @@ retry:
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_idr;
+               goto err_copy;
        }
 
+       put_pd_read(pd);
+
        mutex_lock(&file->mutex);
        list_add_tail(&uobj->list, &file->ucontext->ah_list);
        mutex_unlock(&file->mutex);
 
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       uobj->live = 1;
+
+       up_write(&uobj->mutex);
 
        return in_len;
 
-err_idr:
-       idr_remove(&ib_uverbs_ah_idr, uobj->id);
+err_copy:
+       idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
 
 err_destroy:
        ib_destroy_ah(ah);
 
-err_up:
-       mutex_unlock(&ib_uverbs_idr_mutex);
-
-       kfree(uobj);
+err:
+       put_uobj_write(uobj);
        return ret;
 }
 
@@ -1666,35 +1822,34 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
        struct ib_uverbs_destroy_ah cmd;
        struct ib_ah               *ah;
        struct ib_uobject          *uobj;
-       int                         ret = -EINVAL;
+       int                         ret;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
+       uobj = idr_write_uobj(&ib_uverbs_ah_idr, cmd.ah_handle, file->ucontext);
+       if (!uobj)
+               return -EINVAL;
+       ah = uobj->object;
 
-       ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle);
-       if (!ah || ah->uobject->context != file->ucontext)
-               goto out;
+       ret = ib_destroy_ah(ah);
+       if (!ret)
+               uobj->live = 0;
 
-       uobj = ah->uobject;
+       put_uobj_write(uobj);
 
-       ret = ib_destroy_ah(ah);
        if (ret)
-               goto out;
+               return ret;
 
-       idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle);
+       idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
 
        mutex_lock(&file->mutex);
        list_del(&uobj->list);
        mutex_unlock(&file->mutex);
 
-       kfree(uobj);
+       put_uobj(uobj);
 
-out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
-
-       return ret ? ret : in_len;
+       return in_len;
 }
 
 ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
@@ -1703,47 +1858,43 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
 {
        struct ib_uverbs_attach_mcast cmd;
        struct ib_qp                 *qp;
-       struct ib_uqp_object         *uobj;
+       struct ib_uqp_object         *obj;
        struct ib_uverbs_mcast_entry *mcast;
-       int                           ret = -EINVAL;
+       int                           ret;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-       if (!qp || qp->uobject->context != file->ucontext)
-               goto out;
+       qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+       if (!qp)
+               return -EINVAL;
 
-       uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
+       obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
 
-       list_for_each_entry(mcast, &uobj->mcast_list, list)
+       list_for_each_entry(mcast, &obj->mcast_list, list)
                if (cmd.mlid == mcast->lid &&
                    !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
                        ret = 0;
-                       goto out;
+                       goto out_put;
                }
 
        mcast = kmalloc(sizeof *mcast, GFP_KERNEL);
        if (!mcast) {
                ret = -ENOMEM;
-               goto out;
+               goto out_put;
        }
 
        mcast->lid = cmd.mlid;
        memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw);
 
        ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid);
-       if (!ret) {
-               uobj = container_of(qp->uobject, struct ib_uqp_object,
-                                   uevent.uobject);
-               list_add_tail(&mcast->list, &uobj->mcast_list);
-       } else
+       if (!ret)
+               list_add_tail(&mcast->list, &obj->mcast_list);
+       else
                kfree(mcast);
 
-out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+out_put:
+       put_qp_read(qp);
 
        return ret ? ret : in_len;
 }
@@ -1753,7 +1904,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
                               int out_len)
 {
        struct ib_uverbs_detach_mcast cmd;
-       struct ib_uqp_object         *uobj;
+       struct ib_uqp_object         *obj;
        struct ib_qp                 *qp;
        struct ib_uverbs_mcast_entry *mcast;
        int                           ret = -EINVAL;
@@ -1761,19 +1912,17 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-       if (!qp || qp->uobject->context != file->ucontext)
-               goto out;
+       qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+       if (!qp)
+               return -EINVAL;
 
        ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
        if (ret)
-               goto out;
+               goto out_put;
 
-       uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
+       obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
 
-       list_for_each_entry(mcast, &uobj->mcast_list, list)
+       list_for_each_entry(mcast, &obj->mcast_list, list)
                if (cmd.mlid == mcast->lid &&
                    !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
                        list_del(&mcast->list);
@@ -1781,8 +1930,8 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
                        break;
                }
 
-out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+out_put:
+       put_qp_read(qp);
 
        return ret ? ret : in_len;
 }
@@ -1794,7 +1943,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
        struct ib_uverbs_create_srq      cmd;
        struct ib_uverbs_create_srq_resp resp;
        struct ib_udata                  udata;
-       struct ib_uevent_object         *uobj;
+       struct ib_uevent_object         *obj;
        struct ib_pd                    *pd;
        struct ib_srq                   *srq;
        struct ib_srq_init_attr          attr;
@@ -1810,17 +1959,17 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
                   (unsigned long) cmd.response + sizeof resp,
                   in_len - sizeof cmd, out_len - sizeof resp);
 
-       uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
-       if (!uobj)
+       obj = kmalloc(sizeof *obj, GFP_KERNEL);
+       if (!obj)
                return -ENOMEM;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
+       init_uobj(&obj->uobject, 0, file->ucontext);
+       down_write(&obj->uobject.mutex);
 
-       pd  = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
-
-       if (!pd || pd->uobject->context != file->ucontext) {
+       pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+       if (!pd) {
                ret = -EINVAL;
-               goto err_up;
+               goto err;
        }
 
        attr.event_handler  = ib_uverbs_srq_event_handler;
@@ -1829,69 +1978,59 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
        attr.attr.max_sge   = cmd.max_sge;
        attr.attr.srq_limit = cmd.srq_limit;
 
-       uobj->uobject.user_handle = cmd.user_handle;
-       uobj->uobject.context     = file->ucontext;
-       uobj->events_reported     = 0;
-       INIT_LIST_HEAD(&uobj->event_list);
+       obj->events_reported     = 0;
+       INIT_LIST_HEAD(&obj->event_list);
 
        srq = pd->device->create_srq(pd, &attr, &udata);
        if (IS_ERR(srq)) {
                ret = PTR_ERR(srq);
-               goto err_up;
+               goto err;
        }
 
        srq->device        = pd->device;
        srq->pd            = pd;
-       srq->uobject       = &uobj->uobject;
+       srq->uobject       = &obj->uobject;
        srq->event_handler = attr.event_handler;
        srq->srq_context   = attr.srq_context;
        atomic_inc(&pd->usecnt);
        atomic_set(&srq->usecnt, 0);
 
-       memset(&resp, 0, sizeof resp);
-
-retry:
-       if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) {
-               ret = -ENOMEM;
-               goto err_destroy;
-       }
-
-       ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id);
-
-       if (ret == -EAGAIN)
-               goto retry;
+       obj->uobject.object = srq;
+       ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
        if (ret)
                goto err_destroy;
 
-       resp.srq_handle = uobj->uobject.id;
+       memset(&resp, 0, sizeof resp);
+       resp.srq_handle = obj->uobject.id;
        resp.max_wr     = attr.attr.max_wr;
        resp.max_sge    = attr.attr.max_sge;
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
-               goto err_idr;
+               goto err_copy;
        }
 
+       put_pd_read(pd);
+
        mutex_lock(&file->mutex);
-       list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
+       list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
        mutex_unlock(&file->mutex);
 
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       obj->uobject.live = 1;
+
+       up_write(&obj->uobject.mutex);
 
        return in_len;
 
-err_idr:
-       idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id);
+err_copy:
+       idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
 
 err_destroy:
        ib_destroy_srq(srq);
-       atomic_dec(&pd->usecnt);
-
-err_up:
-       mutex_unlock(&ib_uverbs_idr_mutex);
 
-       kfree(uobj);
+err:
+       put_uobj_write(&obj->uobject);
        return ret;
 }
 
@@ -1907,21 +2046,16 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
-       if (!srq || srq->uobject->context != file->ucontext) {
-               ret = -EINVAL;
-               goto out;
-       }
+       srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+       if (!srq)
+               return -EINVAL;
 
        attr.max_wr    = cmd.max_wr;
        attr.srq_limit = cmd.srq_limit;
 
        ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
 
-out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       put_srq_read(srq);
 
        return ret ? ret : in_len;
 }
@@ -1942,18 +2076,16 @@ ssize_t ib_uverbs_query_srq(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
+       srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+       if (!srq)
+               return -EINVAL;
 
-       srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
-       if (srq && srq->uobject->context == file->ucontext)
-               ret = ib_query_srq(srq, &attr);
-       else
-               ret = -EINVAL;
+       ret = ib_query_srq(srq, &attr);
 
-       mutex_unlock(&ib_uverbs_idr_mutex);
+       put_srq_read(srq);
 
        if (ret)
-               goto out;
+               return ret;
 
        memset(&resp, 0, sizeof resp);
 
@@ -1963,10 +2095,9 @@ ssize_t ib_uverbs_query_srq(struct ib_uverbs_file *file,
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp))
-               ret = -EFAULT;
+               return -EFAULT;
 
-out:
-       return ret ? ret : in_len;
+       return in_len;
 }
 
 ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
@@ -1975,45 +2106,45 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
 {
        struct ib_uverbs_destroy_srq      cmd;
        struct ib_uverbs_destroy_srq_resp resp;
+       struct ib_uobject                *uobj;
        struct ib_srq                    *srq;
-       struct ib_uevent_object          *uobj;
+       struct ib_uevent_object          *obj;
        int                               ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
-       memset(&resp, 0, sizeof resp);
+       uobj = idr_write_uobj(&ib_uverbs_srq_idr, cmd.srq_handle, file->ucontext);
+       if (!uobj)
+               return -EINVAL;
+       srq = uobj->object;
+       obj = container_of(uobj, struct ib_uevent_object, uobject);
 
-       srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
-       if (!srq || srq->uobject->context != file->ucontext)
-               goto out;
+       ret = ib_destroy_srq(srq);
+       if (!ret)
+               uobj->live = 0;
 
-       uobj = container_of(srq->uobject, struct ib_uevent_object, uobject);
+       put_uobj_write(uobj);
 
-       ret = ib_destroy_srq(srq);
        if (ret)
-               goto out;
+               return ret;
 
-       idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
+       idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
 
        mutex_lock(&file->mutex);
-       list_del(&uobj->uobject.list);
+       list_del(&uobj->list);
        mutex_unlock(&file->mutex);
 
-       ib_uverbs_release_uevent(file, uobj);
+       ib_uverbs_release_uevent(file, obj);
 
-       resp.events_reported = uobj->events_reported;
+       memset(&resp, 0, sizeof resp);
+       resp.events_reported = obj->events_reported;
 
-       kfree(uobj);
+       put_uobj(uobj);
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp))
                ret = -EFAULT;
 
-out:
-       mutex_unlock(&ib_uverbs_idr_mutex);
-
        return ret ? ret : in_len;
 }
index ff092a0a94da0ebf77967dbeef73da9d2943ec8c..5ec2d49e9bb6ebae15bd88da1206e94d7f6eb860 100644 (file)
@@ -66,7 +66,7 @@ enum {
 
 static struct class *uverbs_class;
 
-DEFINE_MUTEX(ib_uverbs_idr_mutex);
+DEFINE_SPINLOCK(ib_uverbs_idr_lock);
 DEFINE_IDR(ib_uverbs_pd_idr);
 DEFINE_IDR(ib_uverbs_mr_idr);
 DEFINE_IDR(ib_uverbs_mw_idr);
@@ -183,21 +183,21 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
        if (!context)
                return 0;
 
-       mutex_lock(&ib_uverbs_idr_mutex);
-
        list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
-               struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);
-               idr_remove(&ib_uverbs_ah_idr, uobj->id);
+               struct ib_ah *ah = uobj->object;
+
+               idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
                ib_destroy_ah(ah);
                list_del(&uobj->list);
                kfree(uobj);
        }
 
        list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
-               struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id);
+               struct ib_qp *qp = uobj->object;
                struct ib_uqp_object *uqp =
                        container_of(uobj, struct ib_uqp_object, uevent.uobject);
-               idr_remove(&ib_uverbs_qp_idr, uobj->id);
+
+               idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
                ib_uverbs_detach_umcast(qp, uqp);
                ib_destroy_qp(qp);
                list_del(&uobj->list);
@@ -206,11 +206,12 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
        }
 
        list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
-               struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id);
+               struct ib_cq *cq = uobj->object;
                struct ib_uverbs_event_file *ev_file = cq->cq_context;
                struct ib_ucq_object *ucq =
                        container_of(uobj, struct ib_ucq_object, uobject);
-               idr_remove(&ib_uverbs_cq_idr, uobj->id);
+
+               idr_remove_uobj(&ib_uverbs_cq_idr, uobj);
                ib_destroy_cq(cq);
                list_del(&uobj->list);
                ib_uverbs_release_ucq(file, ev_file, ucq);
@@ -218,10 +219,11 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
        }
 
        list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
-               struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
+               struct ib_srq *srq = uobj->object;
                struct ib_uevent_object *uevent =
                        container_of(uobj, struct ib_uevent_object, uobject);
-               idr_remove(&ib_uverbs_srq_idr, uobj->id);
+
+               idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
                ib_destroy_srq(srq);
                list_del(&uobj->list);
                ib_uverbs_release_uevent(file, uevent);
@@ -231,11 +233,11 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
        /* XXX Free MWs */
 
        list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
-               struct ib_mr *mr = idr_find(&ib_uverbs_mr_idr, uobj->id);
+               struct ib_mr *mr = uobj->object;
                struct ib_device *mrdev = mr->device;
                struct ib_umem_object *memobj;
 
-               idr_remove(&ib_uverbs_mr_idr, uobj->id);
+               idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
                ib_dereg_mr(mr);
 
                memobj = container_of(uobj, struct ib_umem_object, uobject);
@@ -246,15 +248,14 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
        }
 
        list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
-               struct ib_pd *pd = idr_find(&ib_uverbs_pd_idr, uobj->id);
-               idr_remove(&ib_uverbs_pd_idr, uobj->id);
+               struct ib_pd *pd = uobj->object;
+
+               idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
                ib_dealloc_pd(pd);
                list_del(&uobj->list);
                kfree(uobj);
        }
 
-       mutex_unlock(&ib_uverbs_idr_mutex);
-
        return context->device->dealloc_ucontext(context);
 }
 
diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c
new file mode 100644 (file)
index 0000000..ce46b13
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_marshall.h>
+
+static void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
+                                   struct ib_ah_attr *src)
+{
+       memcpy(dst->grh.dgid, src->grh.dgid.raw, sizeof src->grh.dgid);
+       dst->grh.flow_label        = src->grh.flow_label;
+       dst->grh.sgid_index        = src->grh.sgid_index;
+       dst->grh.hop_limit         = src->grh.hop_limit;
+       dst->grh.traffic_class     = src->grh.traffic_class;
+       dst->dlid                  = src->dlid;
+       dst->sl                    = src->sl;
+       dst->src_path_bits         = src->src_path_bits;
+       dst->static_rate           = src->static_rate;
+       dst->is_global             = src->ah_flags & IB_AH_GRH ? 1 : 0;
+       dst->port_num              = src->port_num;
+}
+
+void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
+                            struct ib_qp_attr *src)
+{
+       dst->cur_qp_state       = src->cur_qp_state;
+       dst->path_mtu           = src->path_mtu;
+       dst->path_mig_state     = src->path_mig_state;
+       dst->qkey               = src->qkey;
+       dst->rq_psn             = src->rq_psn;
+       dst->sq_psn             = src->sq_psn;
+       dst->dest_qp_num        = src->dest_qp_num;
+       dst->qp_access_flags    = src->qp_access_flags;
+
+       dst->max_send_wr        = src->cap.max_send_wr;
+       dst->max_recv_wr        = src->cap.max_recv_wr;
+       dst->max_send_sge       = src->cap.max_send_sge;
+       dst->max_recv_sge       = src->cap.max_recv_sge;
+       dst->max_inline_data    = src->cap.max_inline_data;
+
+       ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr);
+       ib_copy_ah_attr_to_user(&dst->alt_ah_attr, &src->alt_ah_attr);
+
+       dst->pkey_index         = src->pkey_index;
+       dst->alt_pkey_index     = src->alt_pkey_index;
+       dst->en_sqd_async_notify = src->en_sqd_async_notify;
+       dst->sq_draining        = src->sq_draining;
+       dst->max_rd_atomic      = src->max_rd_atomic;
+       dst->max_dest_rd_atomic = src->max_dest_rd_atomic;
+       dst->min_rnr_timer      = src->min_rnr_timer;
+       dst->port_num           = src->port_num;
+       dst->timeout            = src->timeout;
+       dst->retry_cnt          = src->retry_cnt;
+       dst->rnr_retry          = src->rnr_retry;
+       dst->alt_port_num       = src->alt_port_num;
+       dst->alt_timeout        = src->alt_timeout;
+}
+EXPORT_SYMBOL(ib_copy_qp_attr_to_user);
+
+void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
+                             struct ib_sa_path_rec *src)
+{
+       memcpy(dst->dgid, src->dgid.raw, sizeof src->dgid);
+       memcpy(dst->sgid, src->sgid.raw, sizeof src->sgid);
+
+       dst->dlid               = src->dlid;
+       dst->slid               = src->slid;
+       dst->raw_traffic        = src->raw_traffic;
+       dst->flow_label         = src->flow_label;
+       dst->hop_limit          = src->hop_limit;
+       dst->traffic_class      = src->traffic_class;
+       dst->reversible         = src->reversible;
+       dst->numb_path          = src->numb_path;
+       dst->pkey               = src->pkey;
+       dst->sl                 = src->sl;
+       dst->mtu_selector       = src->mtu_selector;
+       dst->mtu                = src->mtu;
+       dst->rate_selector      = src->rate_selector;
+       dst->rate               = src->rate;
+       dst->packet_life_time   = src->packet_life_time;
+       dst->preference         = src->preference;
+       dst->packet_life_time_selector = src->packet_life_time_selector;
+}
+EXPORT_SYMBOL(ib_copy_path_rec_to_user);
+
+void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst,
+                               struct ib_user_path_rec *src)
+{
+       memcpy(dst->dgid.raw, src->dgid, sizeof dst->dgid);
+       memcpy(dst->sgid.raw, src->sgid, sizeof dst->sgid);
+
+       dst->dlid               = src->dlid;
+       dst->slid               = src->slid;
+       dst->raw_traffic        = src->raw_traffic;
+       dst->flow_label         = src->flow_label;
+       dst->hop_limit          = src->hop_limit;
+       dst->traffic_class      = src->traffic_class;
+       dst->reversible         = src->reversible;
+       dst->numb_path          = src->numb_path;
+       dst->pkey               = src->pkey;
+       dst->sl                 = src->sl;
+       dst->mtu_selector       = src->mtu_selector;
+       dst->mtu                = src->mtu;
+       dst->rate_selector      = src->rate_selector;
+       dst->rate               = src->rate;
+       dst->packet_life_time   = src->packet_life_time;
+       dst->preference         = src->preference;
+       dst->packet_life_time_selector = src->packet_life_time_selector;
+}
+EXPORT_SYMBOL(ib_copy_path_rec_from_user);
index b78e7dc6933072c21f4bd943960a9b79f6e3393f..468999c388033e83f4668f4f43e187f911f7a3ec 100644 (file)
@@ -125,35 +125,47 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
 }
 EXPORT_SYMBOL(ib_create_ah);
 
-struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
-                                  struct ib_grh *grh, u8 port_num)
+int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
+                      struct ib_grh *grh, struct ib_ah_attr *ah_attr)
 {
-       struct ib_ah_attr ah_attr;
        u32 flow_class;
        u16 gid_index;
        int ret;
 
-       memset(&ah_attr, 0, sizeof ah_attr);
-       ah_attr.dlid = wc->slid;
-       ah_attr.sl = wc->sl;
-       ah_attr.src_path_bits = wc->dlid_path_bits;
-       ah_attr.port_num = port_num;
+       memset(ah_attr, 0, sizeof *ah_attr);
+       ah_attr->dlid = wc->slid;
+       ah_attr->sl = wc->sl;
+       ah_attr->src_path_bits = wc->dlid_path_bits;
+       ah_attr->port_num = port_num;
 
        if (wc->wc_flags & IB_WC_GRH) {
-               ah_attr.ah_flags = IB_AH_GRH;
-               ah_attr.grh.dgid = grh->sgid;
+               ah_attr->ah_flags = IB_AH_GRH;
+               ah_attr->grh.dgid = grh->sgid;
 
-               ret = ib_find_cached_gid(pd->device, &grh->dgid, &port_num,
+               ret = ib_find_cached_gid(device, &grh->dgid, &port_num,
                                         &gid_index);
                if (ret)
-                       return ERR_PTR(ret);
+                       return ret;
 
-               ah_attr.grh.sgid_index = (u8) gid_index;
+               ah_attr->grh.sgid_index = (u8) gid_index;
                flow_class = be32_to_cpu(grh->version_tclass_flow);
-               ah_attr.grh.flow_label = flow_class & 0xFFFFF;
-               ah_attr.grh.traffic_class = (flow_class >> 20) & 0xFF;
-               ah_attr.grh.hop_limit = grh->hop_limit;
+               ah_attr->grh.flow_label = flow_class & 0xFFFFF;
+               ah_attr->grh.hop_limit = grh->hop_limit;
+               ah_attr->grh.traffic_class = (flow_class >> 20) & 0xFF;
        }
+       return 0;
+}
+EXPORT_SYMBOL(ib_init_ah_from_wc);
+
+struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
+                                  struct ib_grh *grh, u8 port_num)
+{
+       struct ib_ah_attr ah_attr;
+       int ret;
+
+       ret = ib_init_ah_from_wc(pd->device, port_num, wc, grh, &ah_attr);
+       if (ret)
+               return ERR_PTR(ret);
 
        return ib_create_ah(pd, &ah_attr);
 }
index f7f8391fe43fc21d714144991c76dab31c2f20d1..1a9d0a2c33c37f6aa4d158f1505dc501548486ad 100644 (file)
@@ -137,47 +137,11 @@ static int recv_subn_get_guidinfo(struct ib_smp *smp,
        return reply(smp);
 }
 
-struct port_info {
-       __be64 mkey;
-       __be64 gid_prefix;
-       __be16 lid;
-       __be16 sm_lid;
-       __be32 cap_mask;
-       __be16 diag_code;
-       __be16 mkey_lease_period;
-       u8 local_port_num;
-       u8 link_width_enabled;
-       u8 link_width_supported;
-       u8 link_width_active;
-       u8 linkspeed_portstate;                 /* 4 bits, 4 bits */
-       u8 portphysstate_linkdown;              /* 4 bits, 4 bits */
-       u8 mkeyprot_resv_lmc;                   /* 2 bits, 3, 3 */
-       u8 linkspeedactive_enabled;             /* 4 bits, 4 bits */
-       u8 neighbormtu_mastersmsl;              /* 4 bits, 4 bits */
-       u8 vlcap_inittype;                      /* 4 bits, 4 bits */
-       u8 vl_high_limit;
-       u8 vl_arb_high_cap;
-       u8 vl_arb_low_cap;
-       u8 inittypereply_mtucap;                /* 4 bits, 4 bits */
-       u8 vlstallcnt_hoqlife;                  /* 3 bits, 5 bits */
-       u8 operationalvl_pei_peo_fpi_fpo;       /* 4 bits, 1, 1, 1, 1 */
-       __be16 mkey_violations;
-       __be16 pkey_violations;
-       __be16 qkey_violations;
-       u8 guid_cap;
-       u8 clientrereg_resv_subnetto;           /* 1 bit, 2 bits, 5 */
-       u8 resv_resptimevalue;                  /* 3 bits, 5 bits */
-       u8 localphyerrors_overrunerrors;        /* 4 bits, 4 bits */
-       __be16 max_credit_hint;
-       u8 resv;
-       u8 link_roundtrip_latency[3];
-} __attribute__ ((packed));
-
 static int recv_subn_get_portinfo(struct ib_smp *smp,
                                  struct ib_device *ibdev, u8 port)
 {
        struct ipath_ibdev *dev;
-       struct port_info *pip = (struct port_info *)smp->data;
+       struct ib_port_info *pip = (struct ib_port_info *)smp->data;
        u16 lid;
        u8 ibcstat;
        u8 mtu;
@@ -312,7 +276,7 @@ static int recv_subn_set_guidinfo(struct ib_smp *smp,
 static int recv_subn_set_portinfo(struct ib_smp *smp,
                                  struct ib_device *ibdev, u8 port)
 {
-       struct port_info *pip = (struct port_info *)smp->data;
+       struct ib_port_info *pip = (struct ib_port_info *)smp->data;
        struct ib_event event;
        struct ipath_ibdev *dev;
        u32 flags;
@@ -445,7 +409,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp,
 
        if (pip->clientrereg_resv_subnetto & 0x80) {
                clientrereg = 1;
-               event.event = IB_EVENT_LID_CHANGE;
+               event.event = IB_EVENT_CLIENT_REREGISTER;
                ib_dispatch_event(&event);
        }
 
index 798e13e14faf826695d8b64a0493a5580e24bd73..d0f7731802c9acede3b220e730ab31ba9873cc24 100644 (file)
@@ -174,7 +174,6 @@ enum {
 
 struct mthca_cmd_context {
        struct completion done;
-       struct timer_list timer;
        int               result;
        int               next;
        u64               out_param;
@@ -362,15 +361,6 @@ void mthca_cmd_event(struct mthca_dev *dev,
        complete(&context->done);
 }
 
-static void event_timeout(unsigned long context_ptr)
-{
-       struct mthca_cmd_context *context =
-               (struct mthca_cmd_context *) context_ptr;
-
-       context->result = -EBUSY;
-       complete(&context->done);
-}
-
 static int mthca_cmd_wait(struct mthca_dev *dev,
                          u64 in_param,
                          u64 *out_param,
@@ -401,11 +391,10 @@ static int mthca_cmd_wait(struct mthca_dev *dev,
        if (err)
                goto out;
 
-       context->timer.expires  = jiffies + timeout;
-       add_timer(&context->timer);
-
-       wait_for_completion(&context->done);
-       del_timer_sync(&context->timer);
+       if (!wait_for_completion_timeout(&context->done, timeout)) {
+               err = -EBUSY;
+               goto out;
+       }
 
        err = context->result;
        if (err)
@@ -535,10 +524,6 @@ int mthca_cmd_use_events(struct mthca_dev *dev)
        for (i = 0; i < dev->cmd.max_cmds; ++i) {
                dev->cmd.context[i].token = i;
                dev->cmd.context[i].next = i + 1;
-               init_timer(&dev->cmd.context[i].timer);
-               dev->cmd.context[i].timer.data     =
-                       (unsigned long) &dev->cmd.context[i];
-               dev->cmd.context[i].timer.function = event_timeout;
        }
 
        dev->cmd.context[dev->cmd.max_cmds - 1].next = -1;
index 205854e9c662809b49576b1ea8c3eb213e44ce72..3e27a084257e9f23b7a4fba49561e15cfddf5b91 100644 (file)
@@ -540,8 +540,17 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
                entry->wr_id = srq->wrid[wqe_index];
                mthca_free_srq_wqe(srq, wqe);
        } else {
+               s32 wqe;
                wq = &(*cur_qp)->rq;
-               wqe_index = be32_to_cpu(cqe->wqe) >> wq->wqe_shift;
+               wqe = be32_to_cpu(cqe->wqe);
+               wqe_index = wqe >> wq->wqe_shift;
+               /*
+               * WQE addr == base - 1 might be reported in receive completion
+               * with error instead of (rq size - 1) by Sinai FW 1.0.800 and
+               * Arbel FW 5.1.400.  This bug should be fixed in later FW revs.
+               */
+               if (unlikely(wqe_index < 0))
+                       wqe_index = wq->max - 1;
                entry->wr_id = (*cur_qp)->wrid[wqe_index];
        }
 
@@ -813,6 +822,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
        spin_lock_init(&cq->lock);
        cq->refcount = 1;
        init_waitqueue_head(&cq->wait);
+       mutex_init(&cq->mutex);
 
        memset(cq_context, 0, sizeof *cq_context);
        cq_context->flags           = cpu_to_be32(MTHCA_CQ_STATUS_OK      |
index 99f109c3815d86255d0e6c607ebb742aec1c287e..d536217e700ea46f8acec32f2830fbd965b25af2 100644 (file)
@@ -695,10 +695,6 @@ static void mthca_unmap_reg(struct mthca_dev *dev, unsigned long offset,
 
 static int __devinit mthca_map_eq_regs(struct mthca_dev *dev)
 {
-       unsigned long mthca_base;
-
-       mthca_base = pci_resource_start(dev->pdev, 0);
-
        if (mthca_is_memfree(dev)) {
                /*
                 * We assume that the EQ arm and EQ set CI registers
index 4730863ece9a398c89e62c366d2f112d81b509f4..d9bc030bcccc78627f434a226f199110dafefa15 100644 (file)
@@ -114,14 +114,22 @@ static void smp_snoop(struct ib_device *ibdev,
             mad->mad_hdr.mgmt_class  == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) &&
            mad->mad_hdr.method     == IB_MGMT_METHOD_SET) {
                if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) {
+                       struct ib_port_info *pinfo =
+                               (struct ib_port_info *) ((struct ib_smp *) mad)->data;
+
                        mthca_update_rate(to_mdev(ibdev), port_num);
                        update_sm_ah(to_mdev(ibdev), port_num,
-                                    be16_to_cpup((__be16 *) (mad->data + 58)),
-                                    (*(u8 *) (mad->data + 76)) & 0xf);
+                                    be16_to_cpu(pinfo->lid),
+                                    pinfo->neighbormtu_mastersmsl & 0xf);
 
                        event.device           = ibdev;
-                       event.event            = IB_EVENT_LID_CHANGE;
                        event.element.port_num = port_num;
+
+                       if(pinfo->clientrereg_resv_subnetto & 0x80)
+                               event.event    = IB_EVENT_CLIENT_REREGISTER;
+                       else
+                               event.event    = IB_EVENT_LID_CHANGE;
+
                        ib_dispatch_event(&event);
                }
 
index a2eae8a30167e3d9cc076b6885028c54485a8285..230ae21db8fd3c15a2c8664443987efec352912e 100644 (file)
@@ -115,6 +115,16 @@ static int mthca_query_device(struct ib_device *ibdev,
        props->max_mcast_qp_attach = MTHCA_QP_PER_MGM;
        props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
                                           props->max_mcast_grp;
+       /*
+        * If Sinai memory key optimization is being used, then only
+        * the 8-bit key portion will change.  For other HCAs, the
+        * unused index bits will also be used for FMR remapping.
+        */
+       if (mdev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
+               props->max_map_per_fmr = 255;
+       else
+               props->max_map_per_fmr =
+                       (1 << (32 - long_log2(mdev->limits.num_mpts))) - 1;
 
        err = 0;
  out:
@@ -783,18 +793,24 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
        if (entries < 1 || entries > dev->limits.max_cqes)
                return -EINVAL;
 
+       mutex_lock(&cq->mutex);
+
        entries = roundup_pow_of_two(entries + 1);
-       if (entries == ibcq->cqe + 1)
-               return 0;
+       if (entries == ibcq->cqe + 1) {
+               ret = 0;
+               goto out;
+       }
 
        if (cq->is_kernel) {
                ret = mthca_alloc_resize_buf(dev, cq, entries);
                if (ret)
-                       return ret;
+                       goto out;
                lkey = cq->resize_buf->buf.mr.ibmr.lkey;
        } else {
-               if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
-                       return -EFAULT;
+               if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
                lkey = ucmd.lkey;
        }
 
@@ -811,7 +827,7 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
                        cq->resize_buf = NULL;
                        spin_unlock_irq(&cq->lock);
                }
-               return ret;
+               goto out;
        }
 
        if (cq->is_kernel) {
@@ -838,7 +854,10 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda
        } else
                ibcq->cqe = entries - 1;
 
-       return 0;
+out:
+       mutex_unlock(&cq->mutex);
+
+       return ret;
 }
 
 static int mthca_destroy_cq(struct ib_cq *cq)
index 179a8f610d0f00ded795bfa0b07310a9ac1fc986..8de2887ba15ce090ef9ea4297a634c5067244aaf 100644 (file)
@@ -214,6 +214,7 @@ struct mthca_cq {
        int                     arm_sn;
 
        wait_queue_head_t       wait;
+       struct mutex            mutex;
 };
 
 struct mthca_srq {
@@ -237,6 +238,7 @@ struct mthca_srq {
        struct mthca_mr         mr;
 
        wait_queue_head_t       wait;
+       struct mutex            mutex;
 };
 
 struct mthca_wq {
@@ -278,6 +280,7 @@ struct mthca_qp {
        union mthca_buf        queue;
 
        wait_queue_head_t      wait;
+       struct mutex           mutex;
 };
 
 struct mthca_sqp {
index 07c13be07a4a5da858a975fe6d11059b0da3a35b..16c387d8170cc599b8b2b16aa8d0275672bbe920 100644 (file)
@@ -534,7 +534,9 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
        struct mthca_qp_context *qp_context;
        u32 sqd_event = 0;
        u8 status;
-       int err;
+       int err = -EINVAL;
+
+       mutex_lock(&qp->mutex);
 
        if (attr_mask & IB_QP_CUR_STATE) {
                cur_state = attr->cur_qp_state;
@@ -553,39 +555,41 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
                          "%d->%d with attr 0x%08x\n",
                          qp->transport, cur_state, new_state,
                          attr_mask);
-               return -EINVAL;
+               goto out;
        }
 
        if ((attr_mask & IB_QP_PKEY_INDEX) &&
             attr->pkey_index >= dev->limits.pkey_table_len) {
                mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
                          attr->pkey_index, dev->limits.pkey_table_len-1);
-               return -EINVAL;
+               goto out;
        }
 
        if ((attr_mask & IB_QP_PORT) &&
            (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) {
                mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num);
-               return -EINVAL;
+               goto out;
        }
 
        if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
            attr->max_rd_atomic > dev->limits.max_qp_init_rdma) {
                mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n",
                          attr->max_rd_atomic, dev->limits.max_qp_init_rdma);
-               return -EINVAL;
+               goto out;
        }
 
        if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
            attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) {
                mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n",
                          attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift);
-               return -EINVAL;
+               goto out;
        }
 
        mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
-       if (IS_ERR(mailbox))
-               return PTR_ERR(mailbox);
+       if (IS_ERR(mailbox)) {
+               err = PTR_ERR(mailbox);
+               goto out;
+       }
        qp_param = mailbox->buf;
        qp_context = &qp_param->context;
        memset(qp_param, 0, sizeof *qp_param);
@@ -618,7 +622,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
                if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_2048) {
                        mthca_dbg(dev, "path MTU (%u) is invalid\n",
                                  attr->path_mtu);
-                       return -EINVAL;
+                       goto out_mailbox;
                }
                qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31;
        }
@@ -672,7 +676,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
        if (attr_mask & IB_QP_AV) {
                if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path,
                                   attr_mask & IB_QP_PORT ? attr->port_num : qp->port))
-                       return -EINVAL;
+                       goto out_mailbox;
 
                qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
        }
@@ -686,18 +690,18 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
                if (attr->alt_pkey_index >= dev->limits.pkey_table_len) {
                        mthca_dbg(dev, "Alternate P_Key index (%u) too large. max is %d\n",
                                  attr->alt_pkey_index, dev->limits.pkey_table_len-1);
-                       return -EINVAL;
+                       goto out_mailbox;
                }
 
                if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) {
                        mthca_dbg(dev, "Alternate port number (%u) is invalid\n",
                                attr->alt_port_num);
-                       return -EINVAL;
+                       goto out_mailbox;
                }
 
                if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path,
                                   attr->alt_ah_attr.port_num))
-                       return -EINVAL;
+                       goto out_mailbox;
 
                qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
                                                              attr->alt_port_num << 24);
@@ -793,12 +797,12 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
        err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0,
                              mailbox, sqd_event, &status);
        if (err)
-               goto out;
+               goto out_mailbox;
        if (status) {
                mthca_warn(dev, "modify QP %d->%d returned status %02x.\n",
                           cur_state, new_state, status);
                err = -EINVAL;
-               goto out;
+               goto out_mailbox;
        }
 
        qp->state = new_state;
@@ -853,8 +857,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
                }
        }
 
-out:
+out_mailbox:
        mthca_free_mailbox(dev, mailbox);
+
+out:
+       mutex_unlock(&qp->mutex);
        return err;
 }
 
@@ -1100,6 +1107,7 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
 
        qp->refcount = 1;
        init_waitqueue_head(&qp->wait);
+       mutex_init(&qp->mutex);
        qp->state        = IB_QPS_RESET;
        qp->atomic_rd_en = 0;
        qp->resp_depth   = 0;
index df5e494a9d3887ca9b71c9cd8721c7ffdaea0d54..f4fddd5327f534039bd0de8b6e0c5cce91ea4c3d 100644 (file)
@@ -49,6 +49,12 @@ int mthca_reset(struct mthca_dev *mdev)
        u32 *hca_header    = NULL;
        u32 *bridge_header = NULL;
        struct pci_dev *bridge = NULL;
+       int bridge_pcix_cap = 0;
+       int hca_pcie_cap = 0;
+       int hca_pcix_cap = 0;
+
+       u16 devctl;
+       u16 linkctl;
 
 #define MTHCA_RESET_OFFSET 0xf0010
 #define MTHCA_RESET_VALUE  swab32(1)
@@ -110,6 +116,9 @@ int mthca_reset(struct mthca_dev *mdev)
                }
        }
 
+       hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);
+       hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP);
+
        if (bridge) {
                bridge_header = kmalloc(256, GFP_KERNEL);
                if (!bridge_header) {
@@ -129,6 +138,13 @@ int mthca_reset(struct mthca_dev *mdev)
                                goto out;
                        }
                }
+               bridge_pcix_cap = pci_find_capability(bridge, PCI_CAP_ID_PCIX);
+               if (!bridge_pcix_cap) {
+                               err = -ENODEV;
+                               mthca_err(mdev, "Couldn't locate HCA bridge "
+                                         "PCI-X capability, aborting.\n");
+                               goto out;
+               }
        }
 
        /* actually hit reset */
@@ -178,6 +194,20 @@ int mthca_reset(struct mthca_dev *mdev)
 good:
        /* Now restore the PCI headers */
        if (bridge) {
+               if (pci_write_config_dword(bridge, bridge_pcix_cap + 0x8,
+                                bridge_header[(bridge_pcix_cap + 0x8) / 4])) {
+                       err = -ENODEV;
+                       mthca_err(mdev, "Couldn't restore HCA bridge Upstream "
+                                 "split transaction control, aborting.\n");
+                       goto out;
+               }
+               if (pci_write_config_dword(bridge, bridge_pcix_cap + 0xc,
+                                bridge_header[(bridge_pcix_cap + 0xc) / 4])) {
+                       err = -ENODEV;
+                       mthca_err(mdev, "Couldn't restore HCA bridge Downstream "
+                                 "split transaction control, aborting.\n");
+                       goto out;
+               }
                /*
                 * Bridge control register is at 0x3e, so we'll
                 * naturally restore it last in this loop.
@@ -203,6 +233,35 @@ good:
                }
        }
 
+       if (hca_pcix_cap) {
+               if (pci_write_config_dword(mdev->pdev, hca_pcix_cap,
+                                hca_header[hca_pcix_cap / 4])) {
+                       err = -ENODEV;
+                       mthca_err(mdev, "Couldn't restore HCA PCI-X "
+                                 "command register, aborting.\n");
+                       goto out;
+               }
+       }
+
+       if (hca_pcie_cap) {
+               devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4];
+               if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL,
+                                          devctl)) {
+                       err = -ENODEV;
+                       mthca_err(mdev, "Couldn't restore HCA PCI Express "
+                                 "Device Control register, aborting.\n");
+                       goto out;
+               }
+               linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4];
+               if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL,
+                                          linkctl)) {
+                       err = -ENODEV;
+                       mthca_err(mdev, "Couldn't restore HCA PCI Express "
+                                 "Link control register, aborting.\n");
+                       goto out;
+               }
+       }
+
        for (i = 0; i < 16; ++i) {
                if (i * 4 == PCI_COMMAND)
                        continue;
index 1ea433291fa71883e06fa0743c3f9fd443fe55bd..fab417c5cf43671f329b9b8c26dddc87bd9345ad 100644 (file)
@@ -243,6 +243,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
        spin_lock_init(&srq->lock);
        srq->refcount = 1;
        init_waitqueue_head(&srq->wait);
+       mutex_init(&srq->mutex);
 
        if (mthca_is_memfree(dev))
                mthca_arbel_init_srq_context(dev, pd, srq, mailbox->buf);
@@ -371,7 +372,11 @@ int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
        if (attr_mask & IB_SRQ_LIMIT) {
                if (attr->srq_limit > srq->max)
                        return -EINVAL;
+
+               mutex_lock(&srq->mutex);
                ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status);
+               mutex_unlock(&srq->mutex);
+
                if (ret)
                        return ret;
                if (status)
@@ -490,26 +495,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
 
        first_ind = srq->first_free;
 
-       for (nreq = 0; wr; ++nreq, wr = wr->next) {
-               if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
-                       nreq = 0;
-
-                       doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
-                       doorbell[1] = cpu_to_be32(srq->srqn << 8);
-
-                       /*
-                        * Make sure that descriptors are written
-                        * before doorbell is rung.
-                        */
-                       wmb();
-
-                       mthca_write64(doorbell,
-                                     dev->kar + MTHCA_RECEIVE_DOORBELL,
-                                     MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
-
-                       first_ind = srq->first_free;
-               }
-
+       for (nreq = 0; wr; wr = wr->next) {
                ind = srq->first_free;
 
                if (ind < 0) {
@@ -569,6 +555,26 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
 
                srq->wrid[ind]  = wr->wr_id;
                srq->first_free = next_ind;
+
+               ++nreq;
+               if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
+                       nreq = 0;
+
+                       doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
+                       doorbell[1] = cpu_to_be32(srq->srqn << 8);
+
+                       /*
+                        * Make sure that descriptors are written
+                        * before doorbell is rung.
+                        */
+                       wmb();
+
+                       mthca_write64(doorbell,
+                                     dev->kar + MTHCA_RECEIVE_DOORBELL,
+                                     MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+
+                       first_ind = srq->first_free;
+               }
        }
 
        if (likely(nreq)) {
index 12a1e0572ef208fd341aad093aa45d4a29f0fce0..491d2afaf5b499cc8089cd9f81d25a49d6001f1e 100644 (file)
@@ -272,8 +272,7 @@ 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_send(struct net_device *dev, union ib_gid *mgid,
-                     struct sk_buff *skb);
+void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb);
 
 void ipoib_mcast_restart_task(void *dev_ptr);
 int ipoib_mcast_start_thread(struct net_device *dev);
@@ -369,15 +368,26 @@ extern int ipoib_debug_level;
 #endif /* CONFIG_INFINIBAND_IPOIB_DEBUG_DATA */
 
 
-#define IPOIB_GID_FMT          "%x:%x:%x:%x:%x:%x:%x:%x"
-
-#define IPOIB_GID_ARG(gid)     be16_to_cpup((__be16 *) ((gid).raw +  0)), \
-                               be16_to_cpup((__be16 *) ((gid).raw +  2)), \
-                               be16_to_cpup((__be16 *) ((gid).raw +  4)), \
-                               be16_to_cpup((__be16 *) ((gid).raw +  6)), \
-                               be16_to_cpup((__be16 *) ((gid).raw +  8)), \
-                               be16_to_cpup((__be16 *) ((gid).raw + 10)), \
-                               be16_to_cpup((__be16 *) ((gid).raw + 12)), \
-                               be16_to_cpup((__be16 *) ((gid).raw + 14))
+#define IPOIB_GID_FMT          "%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:" \
+                               "%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x"
+
+#define IPOIB_GID_RAW_ARG(gid) ((u8 *)(gid))[0], \
+                               ((u8 *)(gid))[1], \
+                               ((u8 *)(gid))[2], \
+                               ((u8 *)(gid))[3], \
+                               ((u8 *)(gid))[4], \
+                               ((u8 *)(gid))[5], \
+                               ((u8 *)(gid))[6], \
+                               ((u8 *)(gid))[7], \
+                               ((u8 *)(gid))[8], \
+                               ((u8 *)(gid))[9], \
+                               ((u8 *)(gid))[10],\
+                               ((u8 *)(gid))[11],\
+                               ((u8 *)(gid))[12],\
+                               ((u8 *)(gid))[13],\
+                               ((u8 *)(gid))[14],\
+                               ((u8 *)(gid))[15]
+
+#define IPOIB_GID_ARG(gid)     IPOIB_GID_RAW_ARG((gid).raw)
 
 #endif /* _IPOIB_H */
index a54da42849ae1e9e19d3335326be70fe3c44880b..5033666b14817e75488b1859e7b217d41f653f8b 100644 (file)
@@ -84,15 +84,9 @@ void ipoib_free_ah(struct kref *kref)
 
        unsigned long flags;
 
-       if ((int) priv->tx_tail - (int) ah->last_send >= 0) {
-               ipoib_dbg(priv, "Freeing ah %p\n", ah->ah);
-               ib_destroy_ah(ah->ah);
-               kfree(ah);
-       } else {
-               spin_lock_irqsave(&priv->lock, flags);
-               list_add_tail(&ah->list, &priv->dead_ahs);
-               spin_unlock_irqrestore(&priv->lock, flags);
-       }
+       spin_lock_irqsave(&priv->lock, flags);
+       list_add_tail(&ah->list, &priv->dead_ahs);
+       spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 static int ipoib_ib_post_receive(struct net_device *dev, int id)
@@ -275,6 +269,7 @@ static void ipoib_ib_handle_wc(struct net_device *dev,
                spin_lock_irqsave(&priv->tx_lock, flags);
                ++priv->tx_tail;
                if (netif_queue_stopped(dev) &&
+                   test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags) &&
                    priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1)
                        netif_wake_queue(dev);
                spin_unlock_irqrestore(&priv->tx_lock, flags);
@@ -376,19 +371,16 @@ static void __ipoib_reap_ah(struct net_device *dev)
        struct ipoib_ah *ah, *tah;
        LIST_HEAD(remove_list);
 
-       spin_lock_irq(&priv->lock);
+       spin_lock_irq(&priv->tx_lock);
+       spin_lock(&priv->lock);
        list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list)
                if ((int) priv->tx_tail - (int) ah->last_send >= 0) {
                        list_del(&ah->list);
-                       list_add_tail(&ah->list, &remove_list);
+                       ib_destroy_ah(ah->ah);
+                       kfree(ah);
                }
-       spin_unlock_irq(&priv->lock);
-
-       list_for_each_entry_safe(ah, tah, &remove_list, list) {
-               ipoib_dbg(priv, "Reaping ah %p\n", ah->ah);
-               ib_destroy_ah(ah->ah);
-               kfree(ah);
-       }
+       spin_unlock(&priv->lock);
+       spin_unlock_irq(&priv->tx_lock);
 }
 
 void ipoib_reap_ah(void *dev_ptr)
index cb078a7d0bf5b86551adf812fbc93724883616f8..1c6ea1c682a5dc7c4bd5bed14f67307ef27aa1a1 100644 (file)
@@ -185,8 +185,7 @@ static int ipoib_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
-static struct ipoib_path *__path_find(struct net_device *dev,
-                                     union ib_gid *gid)
+static struct ipoib_path *__path_find(struct net_device *dev, void *gid)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct rb_node *n = priv->path_tree.rb_node;
@@ -196,7 +195,7 @@ static struct ipoib_path *__path_find(struct net_device *dev,
        while (n) {
                path = rb_entry(n, struct ipoib_path, rb_node);
 
-               ret = memcmp(gid->raw, path->pathrec.dgid.raw,
+               ret = memcmp(gid, path->pathrec.dgid.raw,
                             sizeof (union ib_gid));
 
                if (ret < 0)
@@ -424,8 +423,7 @@ static void path_rec_completion(int status,
        }
 }
 
-static struct ipoib_path *path_rec_create(struct net_device *dev,
-                                         union ib_gid *gid)
+static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_path *path;
@@ -440,7 +438,7 @@ static struct ipoib_path *path_rec_create(struct net_device *dev,
 
        INIT_LIST_HEAD(&path->neigh_list);
 
-       memcpy(path->pathrec.dgid.raw, gid->raw, sizeof (union ib_gid));
+       memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid));
        path->pathrec.sgid      = priv->local_gid;
        path->pathrec.pkey      = cpu_to_be16(priv->pkey);
        path->pathrec.numb_path = 1;
@@ -498,10 +496,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
         */
        spin_lock(&priv->lock);
 
-       path = __path_find(dev, (union ib_gid *) (skb->dst->neighbour->ha + 4));
+       path = __path_find(dev, skb->dst->neighbour->ha + 4);
        if (!path) {
-               path = path_rec_create(dev,
-                                      (union ib_gid *) (skb->dst->neighbour->ha + 4));
+               path = path_rec_create(dev, skb->dst->neighbour->ha + 4);
                if (!path)
                        goto err_path;
 
@@ -551,7 +548,7 @@ static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
        /* Add in the P_Key for multicasts */
        skb->dst->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
        skb->dst->neighbour->ha[9] = priv->pkey & 0xff;
-       ipoib_mcast_send(dev, (union ib_gid *) (skb->dst->neighbour->ha + 4), skb);
+       ipoib_mcast_send(dev, skb->dst->neighbour->ha + 4, skb);
 }
 
 static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
@@ -566,10 +563,9 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
         */
        spin_lock(&priv->lock);
 
-       path = __path_find(dev, (union ib_gid *) (phdr->hwaddr + 4));
+       path = __path_find(dev, phdr->hwaddr + 4);
        if (!path) {
-               path = path_rec_create(dev,
-                                      (union ib_gid *) (phdr->hwaddr + 4));
+               path = path_rec_create(dev, phdr->hwaddr + 4);
                if (path) {
                        /* put pseudoheader back on for next time */
                        skb_push(skb, sizeof *phdr);
@@ -660,7 +656,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff;
                        phdr->hwaddr[9] = priv->pkey & 0xff;
 
-                       ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb);
+                       ipoib_mcast_send(dev, phdr->hwaddr + 4, skb);
                } else {
                        /* unicast GID -- should be ARP or RARP reply */
 
@@ -671,7 +667,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                           skb->dst ? "neigh" : "dst",
                                           be16_to_cpup((__be16 *) skb->data),
                                           be32_to_cpup((__be32 *) phdr->hwaddr),
-                                          IPOIB_GID_ARG(*(union ib_gid *) (phdr->hwaddr + 4)));
+                                          IPOIB_GID_RAW_ARG(phdr->hwaddr + 4));
                                dev_kfree_skb_any(skb);
                                ++priv->stats.tx_dropped;
                                goto out;
@@ -754,7 +750,7 @@ static void ipoib_neigh_destructor(struct neighbour *n)
        ipoib_dbg(priv,
                  "neigh_destructor for %06x " IPOIB_GID_FMT "\n",
                  be32_to_cpup((__be32 *) n->ha),
-                 IPOIB_GID_ARG(*((union ib_gid *) (n->ha + 4))));
+                 IPOIB_GID_RAW_ARG(n->ha + 4));
 
        spin_lock_irqsave(&priv->lock, flags);
 
index 1dae4b238252d3b204d68570bc4fa73f9e73959c..216471fa01cc48fed536e16acf817d9b88383886 100644 (file)
@@ -154,7 +154,7 @@ static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev,
        return mcast;
 }
 
-static struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, union ib_gid *mgid)
+static struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, void *mgid)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct rb_node *n = priv->multicast_tree.rb_node;
@@ -165,7 +165,7 @@ static struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, union ib_g
 
                mcast = rb_entry(n, struct ipoib_mcast, rb_node);
 
-               ret = memcmp(mgid->raw, mcast->mcmember.mgid.raw,
+               ret = memcmp(mgid, mcast->mcmember.mgid.raw,
                             sizeof (union ib_gid));
                if (ret < 0)
                        n = n->rb_left;
@@ -694,8 +694,7 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
        return 0;
 }
 
-void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
-                     struct sk_buff *skb)
+void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_mcast *mcast;
@@ -718,7 +717,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
        if (!mcast) {
                /* Let's create a new send only group now */
                ipoib_dbg_mcast(priv, "setting up send only multicast group for "
-                               IPOIB_GID_FMT "\n", IPOIB_GID_ARG(*mgid));
+                               IPOIB_GID_FMT "\n", IPOIB_GID_RAW_ARG(mgid));
 
                mcast = ipoib_mcast_alloc(dev, 0);
                if (!mcast) {
@@ -730,7 +729,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
                }
 
                set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags);
-               mcast->mcmember.mgid = *mgid;
+               memcpy(mcast->mcmember.mgid.raw, mgid, sizeof (union ib_gid));
                __ipoib_mcast_add(dev, mcast);
                list_add_tail(&mcast->list, &priv->multicast_list);
        }
@@ -821,7 +820,8 @@ void ipoib_mcast_restart_task(void *dev_ptr)
 
        ipoib_mcast_stop_thread(dev, 0);
 
-       spin_lock_irqsave(&dev->xmit_lock, flags);
+       local_irq_save(flags);
+       netif_tx_lock(dev);
        spin_lock(&priv->lock);
 
        /*
@@ -896,7 +896,8 @@ void ipoib_mcast_restart_task(void *dev_ptr)
        }
 
        spin_unlock(&priv->lock);
-       spin_unlock_irqrestore(&dev->xmit_lock, flags);
+       netif_tx_unlock(dev);
+       local_irq_restore(flags);
 
        /* We have to cancel outside of the spinlock */
        list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
index 1d49d1643c5943246961a02c60b5acce7d8cd8f3..7b717c648f727bb52ac8d33fcb5bcb6de9cefe5e 100644 (file)
@@ -255,7 +255,8 @@ void ipoib_event(struct ib_event_handler *handler,
            record->event == IB_EVENT_PKEY_CHANGE ||
            record->event == IB_EVENT_PORT_ACTIVE ||
            record->event == IB_EVENT_LID_CHANGE  ||
-           record->event == IB_EVENT_SM_CHANGE) {
+           record->event == IB_EVENT_SM_CHANGE   ||
+           record->event == IB_EVENT_CLIENT_REREGISTER) {
                ipoib_dbg(priv, "Port state change event\n");
                queue_work(ipoib_workqueue, &priv->flush_task);
        }
index 9cbdffa08dc2bca6da821638efc0078b24792374..4e22afef72062571c12b3489bc9e26fa998fce43 100644 (file)
@@ -62,6 +62,13 @@ MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol initiator "
                   "v" DRV_VERSION " (" DRV_RELDATE ")");
 MODULE_LICENSE("Dual BSD/GPL");
 
+static int srp_sg_tablesize = SRP_DEF_SG_TABLESIZE;
+static int srp_max_iu_len;
+
+module_param(srp_sg_tablesize, int, 0444);
+MODULE_PARM_DESC(srp_sg_tablesize,
+                "Max number of gather/scatter entries per I/O (default is 12)");
+
 static int topspin_workarounds = 1;
 
 module_param(topspin_workarounds, int, 0444);
@@ -105,7 +112,8 @@ static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
        if (!iu->buf)
                goto out_free_iu;
 
-       iu->dma = dma_map_single(host->dev->dma_device, iu->buf, size, direction);
+       iu->dma = dma_map_single(host->dev->dev->dma_device,
+                                iu->buf, size, direction);
        if (dma_mapping_error(iu->dma))
                goto out_free_buf;
 
@@ -127,7 +135,8 @@ static void srp_free_iu(struct srp_host *host, struct srp_iu *iu)
        if (!iu)
                return;
 
-       dma_unmap_single(host->dev->dma_device, iu->dma, iu->size, iu->direction);
+       dma_unmap_single(host->dev->dev->dma_device,
+                        iu->dma, iu->size, iu->direction);
        kfree(iu->buf);
        kfree(iu);
 }
@@ -147,7 +156,7 @@ static int srp_init_qp(struct srp_target_port *target,
        if (!attr)
                return -ENOMEM;
 
-       ret = ib_find_cached_pkey(target->srp_host->dev,
+       ret = ib_find_cached_pkey(target->srp_host->dev->dev,
                                  target->srp_host->port,
                                  be16_to_cpu(target->path.pkey),
                                  &attr->pkey_index);
@@ -179,7 +188,7 @@ static int srp_create_target_ib(struct srp_target_port *target)
        if (!init_attr)
                return -ENOMEM;
 
-       target->cq = ib_create_cq(target->srp_host->dev, srp_completion,
+       target->cq = ib_create_cq(target->srp_host->dev->dev, srp_completion,
                                  NULL, target, SRP_CQ_SIZE);
        if (IS_ERR(target->cq)) {
                ret = PTR_ERR(target->cq);
@@ -198,7 +207,7 @@ static int srp_create_target_ib(struct srp_target_port *target)
        init_attr->send_cq             = target->cq;
        init_attr->recv_cq             = target->cq;
 
-       target->qp = ib_create_qp(target->srp_host->pd, init_attr);
+       target->qp = ib_create_qp(target->srp_host->dev->pd, init_attr);
        if (IS_ERR(target->qp)) {
                ret = PTR_ERR(target->qp);
                ib_destroy_cq(target->cq);
@@ -250,7 +259,7 @@ static int srp_lookup_path(struct srp_target_port *target)
 
        init_completion(&target->done);
 
-       target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev,
+       target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev->dev,
                                                   target->srp_host->port,
                                                   &target->path,
                                                   IB_SA_PATH_REC_DGID          |
@@ -309,10 +318,32 @@ static int srp_send_req(struct srp_target_port *target)
 
        req->priv.opcode        = SRP_LOGIN_REQ;
        req->priv.tag           = 0;
-       req->priv.req_it_iu_len = cpu_to_be32(SRP_MAX_IU_LEN);
+       req->priv.req_it_iu_len = cpu_to_be32(srp_max_iu_len);
        req->priv.req_buf_fmt   = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
                                              SRP_BUF_FORMAT_INDIRECT);
-       memcpy(req->priv.initiator_port_id, target->srp_host->initiator_port_id, 16);
+       /*
+        * In the published SRP specification (draft rev. 16a), the 
+        * port identifier format is 8 bytes of ID extension followed
+        * by 8 bytes of GUID.  Older drafts put the two halves in the
+        * opposite order, so that the GUID comes first.
+        *
+        * Targets conforming to these obsolete drafts can be
+        * recognized by the I/O Class they report.
+        */
+       if (target->io_class == SRP_REV10_IB_IO_CLASS) {
+               memcpy(req->priv.initiator_port_id,
+                      target->srp_host->initiator_port_id + 8, 8);
+               memcpy(req->priv.initiator_port_id + 8,
+                      target->srp_host->initiator_port_id, 8);
+               memcpy(req->priv.target_port_id,     &target->ioc_guid, 8);
+               memcpy(req->priv.target_port_id + 8, &target->id_ext, 8);
+       } else {
+               memcpy(req->priv.initiator_port_id,
+                      target->srp_host->initiator_port_id, 16);
+               memcpy(req->priv.target_port_id,     &target->id_ext, 8);
+               memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8);
+       }
+
        /*
         * Topspin/Cisco SRP targets will reject our login unless we
         * zero out the first 8 bytes of our initiator port ID.  The
@@ -325,8 +356,6 @@ static int srp_send_req(struct srp_target_port *target)
                       (unsigned long long) be64_to_cpu(target->ioc_guid));
                memset(req->priv.initiator_port_id, 0, 8);
        }
-       memcpy(req->priv.target_port_id,     &target->id_ext, 8);
-       memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8);
 
        status = ib_send_cm_req(target->cm_id, &req->param);
 
@@ -359,9 +388,9 @@ static void srp_remove_work(void *target_ptr)
        target->state = SRP_TARGET_REMOVED;
        spin_unlock_irq(target->scsi_host->host_lock);
 
-       mutex_lock(&target->srp_host->target_mutex);
+       spin_lock(&target->srp_host->target_lock);
        list_del(&target->list);
-       mutex_unlock(&target->srp_host->target_mutex);
+       spin_unlock(&target->srp_host->target_lock);
 
        scsi_remove_host(target->scsi_host);
        ib_destroy_cm_id(target->cm_id);
@@ -421,6 +450,11 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
             scmnd->sc_data_direction != DMA_FROM_DEVICE))
                return;
 
+       if (req->fmr) {
+               ib_fmr_pool_unmap(req->fmr);
+               req->fmr = NULL;
+       }
+
        /*
         * This handling of non-SG commands can be killed when the
         * SCSI midlayer no longer generates non-SG commands.
@@ -433,18 +467,30 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
                scat  = &req->fake_sg;
        }
 
-       dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents,
+       dma_unmap_sg(target->srp_host->dev->dev->dma_device, scat, nents,
                     scmnd->sc_data_direction);
 }
 
+static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
+{
+       srp_unmap_data(req->scmnd, target, req);
+       list_move_tail(&req->list, &target->free_reqs);
+}
+
+static void srp_reset_req(struct srp_target_port *target, struct srp_request *req)
+{
+       req->scmnd->result = DID_RESET << 16;
+       req->scmnd->scsi_done(req->scmnd);
+       srp_remove_req(target, req);
+}
+
 static int srp_reconnect_target(struct srp_target_port *target)
 {
        struct ib_cm_id *new_cm_id;
        struct ib_qp_attr qp_attr;
-       struct srp_request *req;
+       struct srp_request *req, *tmp;
        struct ib_wc wc;
        int ret;
-       int i;
 
        spin_lock_irq(target->scsi_host->host_lock);
        if (target->state != SRP_TARGET_LIVE) {
@@ -459,7 +505,7 @@ static int srp_reconnect_target(struct srp_target_port *target)
         * Now get a new local CM ID so that we avoid confusing the
         * target in case things are really fouled up.
         */
-       new_cm_id = ib_create_cm_id(target->srp_host->dev,
+       new_cm_id = ib_create_cm_id(target->srp_host->dev->dev,
                                    srp_cm_handler, target);
        if (IS_ERR(new_cm_id)) {
                ret = PTR_ERR(new_cm_id);
@@ -480,19 +526,12 @@ static int srp_reconnect_target(struct srp_target_port *target)
        while (ib_poll_cq(target->cq, 1, &wc) > 0)
                ; /* nothing */
 
-       list_for_each_entry(req, &target->req_queue, list) {
-               req->scmnd->result = DID_RESET << 16;
-               req->scmnd->scsi_done(req->scmnd);
-               srp_unmap_data(req->scmnd, target, req);
-       }
+       list_for_each_entry_safe(req, tmp, &target->req_queue, list)
+               srp_reset_req(target, req);
 
        target->rx_head  = 0;
        target->tx_head  = 0;
        target->tx_tail  = 0;
-       INIT_LIST_HEAD(&target->free_reqs);
-       INIT_LIST_HEAD(&target->req_queue);
-       for (i = 0; i < SRP_SQ_SIZE; ++i)
-               list_add_tail(&target->req_ring[i].list, &target->free_reqs);
 
        ret = srp_connect_target(target);
        if (ret)
@@ -528,14 +567,79 @@ err:
        return ret;
 }
 
+static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat,
+                      int sg_cnt, struct srp_request *req,
+                      struct srp_direct_buf *buf)
+{
+       u64 io_addr = 0;
+       u64 *dma_pages;
+       u32 len;
+       int page_cnt;
+       int i, j;
+       int ret;
+
+       if (!dev->fmr_pool)
+               return -ENODEV;
+
+       len = page_cnt = 0;
+       for (i = 0; i < sg_cnt; ++i) {
+               if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) {
+                       if (i > 0)
+                               return -EINVAL;
+                       else
+                               ++page_cnt;
+               }
+               if ((sg_dma_address(&scat[i]) + sg_dma_len(&scat[i])) &
+                   ~dev->fmr_page_mask) {
+                       if (i < sg_cnt - 1)
+                               return -EINVAL;
+                       else
+                               ++page_cnt;
+               }
+
+               len += sg_dma_len(&scat[i]);
+       }
+
+       page_cnt += len >> dev->fmr_page_shift;
+       if (page_cnt > SRP_FMR_SIZE)
+               return -ENOMEM;
+
+       dma_pages = kmalloc(sizeof (u64) * page_cnt, GFP_ATOMIC);
+       if (!dma_pages)
+               return -ENOMEM;
+
+       page_cnt = 0;
+       for (i = 0; i < sg_cnt; ++i)
+               for (j = 0; j < sg_dma_len(&scat[i]); j += dev->fmr_page_size)
+                       dma_pages[page_cnt++] =
+                               (sg_dma_address(&scat[i]) & dev->fmr_page_mask) + j;
+
+       req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool,
+                                       dma_pages, page_cnt, &io_addr);
+       if (IS_ERR(req->fmr)) {
+               ret = PTR_ERR(req->fmr);
+               goto out;
+       }
+
+       buf->va  = cpu_to_be64(sg_dma_address(&scat[0]) & ~dev->fmr_page_mask);
+       buf->key = cpu_to_be32(req->fmr->fmr->rkey);
+       buf->len = cpu_to_be32(len);
+
+       ret = 0;
+
+out:
+       kfree(dma_pages);
+
+       return ret;
+}
+
 static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
                        struct srp_request *req)
 {
        struct scatterlist *scat;
        struct srp_cmd *cmd = req->cmd->buf;
        int len, nents, count;
-       int i;
-       u8 fmt;
+       u8 fmt = SRP_DATA_DESC_DIRECT;
 
        if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE)
                return sizeof (struct srp_cmd);
@@ -560,53 +664,63 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
                sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen);
        }
 
-       count = dma_map_sg(target->srp_host->dev->dma_device, scat, nents,
-                          scmnd->sc_data_direction);
+       count = dma_map_sg(target->srp_host->dev->dev->dma_device,
+                          scat, nents, scmnd->sc_data_direction);
+
+       fmt = SRP_DATA_DESC_DIRECT;
+       len = sizeof (struct srp_cmd) + sizeof (struct srp_direct_buf);
 
        if (count == 1) {
+               /*
+                * The midlayer only generated a single gather/scatter
+                * entry, or DMA mapping coalesced everything to a
+                * single entry.  So a direct descriptor along with
+                * the DMA MR suffices.
+                */
                struct srp_direct_buf *buf = (void *) cmd->add_data;
 
-               fmt = SRP_DATA_DESC_DIRECT;
-
                buf->va  = cpu_to_be64(sg_dma_address(scat));
-               buf->key = cpu_to_be32(target->srp_host->mr->rkey);
+               buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey);
                buf->len = cpu_to_be32(sg_dma_len(scat));
-
-               len = sizeof (struct srp_cmd) +
-                       sizeof (struct srp_direct_buf);
-       } else {
+       } else if (srp_map_fmr(target->srp_host->dev, scat, count, req,
+                              (void *) cmd->add_data)) {
+               /*
+                * FMR mapping failed, and the scatterlist has more
+                * than one entry.  Generate an indirect memory
+                * descriptor.
+                */
                struct srp_indirect_buf *buf = (void *) cmd->add_data;
                u32 datalen = 0;
+               int i;
 
                fmt = SRP_DATA_DESC_INDIRECT;
+               len = sizeof (struct srp_cmd) +
+                       sizeof (struct srp_indirect_buf) +
+                       count * sizeof (struct srp_direct_buf);
+
+               for (i = 0; i < count; ++i) {
+                       buf->desc_list[i].va  =
+                               cpu_to_be64(sg_dma_address(&scat[i]));
+                       buf->desc_list[i].key =
+                               cpu_to_be32(target->srp_host->dev->mr->rkey);
+                       buf->desc_list[i].len =
+                               cpu_to_be32(sg_dma_len(&scat[i]));
+                       datalen += sg_dma_len(&scat[i]);
+               }
 
                if (scmnd->sc_data_direction == DMA_TO_DEVICE)
                        cmd->data_out_desc_cnt = count;
                else
                        cmd->data_in_desc_cnt = count;
 
-               buf->table_desc.va  = cpu_to_be64(req->cmd->dma +
-                                                 sizeof *cmd +
-                                                 sizeof *buf);
+               buf->table_desc.va  =
+                       cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf);
                buf->table_desc.key =
-                       cpu_to_be32(target->srp_host->mr->rkey);
+                       cpu_to_be32(target->srp_host->dev->mr->rkey);
                buf->table_desc.len =
                        cpu_to_be32(count * sizeof (struct srp_direct_buf));
 
-               for (i = 0; i < count; ++i) {
-                       buf->desc_list[i].va  = cpu_to_be64(sg_dma_address(&scat[i]));
-                       buf->desc_list[i].key =
-                               cpu_to_be32(target->srp_host->mr->rkey);
-                       buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i]));
-
-                       datalen += sg_dma_len(&scat[i]);
-               }
-
                buf->len = cpu_to_be32(datalen);
-
-               len = sizeof (struct srp_cmd) +
-                       sizeof (struct srp_indirect_buf) +
-                       count * sizeof (struct srp_direct_buf);
        }
 
        if (scmnd->sc_data_direction == DMA_TO_DEVICE)
@@ -617,12 +731,6 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
        return len;
 }
 
-static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
-{
-       srp_unmap_data(req->scmnd, target, req);
-       list_move_tail(&req->list, &target->free_reqs);
-}
-
 static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 {
        struct srp_request *req;
@@ -689,7 +797,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 
        iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV];
 
-       dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma,
+       dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma,
                                target->max_ti_iu_len, DMA_FROM_DEVICE);
 
        opcode = *(u8 *) iu->buf;
@@ -726,7 +834,7 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
                break;
        }
 
-       dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma,
+       dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma,
                                   target->max_ti_iu_len, DMA_FROM_DEVICE);
 }
 
@@ -770,7 +878,7 @@ static int __srp_post_recv(struct srp_target_port *target)
 
        list.addr   = iu->dma;
        list.length = iu->size;
-       list.lkey   = target->srp_host->mr->lkey;
+       list.lkey   = target->srp_host->dev->mr->lkey;
 
        wr.next     = NULL;
        wr.sg_list  = &list;
@@ -805,12 +913,8 @@ static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target)
        if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
                return NULL;
 
-       if (unlikely(target->req_lim < 1)) {
-               if (printk_ratelimit())
-                       printk(KERN_DEBUG PFX "Target has req_lim %d\n",
-                              target->req_lim);
-               return NULL;
-       }
+       if (unlikely(target->req_lim < 1))
+               ++target->zero_req_lim;
 
        return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
 }
@@ -828,7 +932,7 @@ static int __srp_post_send(struct srp_target_port *target,
 
        list.addr   = iu->dma;
        list.length = len;
-       list.lkey   = target->srp_host->mr->lkey;
+       list.lkey   = target->srp_host->dev->mr->lkey;
 
        wr.next       = NULL;
        wr.wr_id      = target->tx_head & SRP_SQ_SIZE;
@@ -870,8 +974,8 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
        if (!iu)
                goto err;
 
-       dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma,
-                               SRP_MAX_IU_LEN, DMA_TO_DEVICE);
+       dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma,
+                               srp_max_iu_len, DMA_TO_DEVICE);
 
        req = list_entry(target->free_reqs.next, struct srp_request, list);
 
@@ -903,8 +1007,8 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
                goto err_unmap;
        }
 
-       dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma,
-                                  SRP_MAX_IU_LEN, DMA_TO_DEVICE);
+       dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma,
+                                  srp_max_iu_len, DMA_TO_DEVICE);
 
        if (__srp_post_send(target, iu, len)) {
                printk(KERN_ERR PFX "Send failed\n");
@@ -936,7 +1040,7 @@ static int srp_alloc_iu_bufs(struct srp_target_port *target)
 
        for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
                target->tx_ring[i] = srp_alloc_iu(target->srp_host,
-                                                 SRP_MAX_IU_LEN,
+                                                 srp_max_iu_len,
                                                  GFP_KERNEL, DMA_TO_DEVICE);
                if (!target->tx_ring[i])
                        goto err;
@@ -1107,11 +1211,10 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
                srp_cm_rej_handler(cm_id, event, target);
                break;
 
-       case IB_CM_MRA_RECEIVED:
-               printk(KERN_ERR PFX "MRA received\n");
-               break;
-
-       case IB_CM_DREP_RECEIVED:
+       case IB_CM_DREQ_RECEIVED:
+               printk(KERN_WARNING PFX "DREQ received - connection closed\n");
+               if (ib_send_cm_drep(cm_id, NULL, 0))
+                       printk(KERN_ERR PFX "Sending CM DREP failed\n");
                break;
 
        case IB_CM_TIMEWAIT_EXIT:
@@ -1121,6 +1224,11 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
                target->status = 0;
                break;
 
+       case IB_CM_MRA_RECEIVED:
+       case IB_CM_DREQ_ERROR:
+       case IB_CM_DREP_RECEIVED:
+               break;
+
        default:
                printk(KERN_WARNING PFX "Unhandled CM event %d\n", event->event);
                break;
@@ -1239,11 +1347,8 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
        spin_lock_irq(target->scsi_host->host_lock);
 
        list_for_each_entry_safe(req, tmp, &target->req_queue, list)
-               if (req->scmnd->device == scmnd->device) {
-                       req->scmnd->result = DID_RESET << 16;
-                       req->scmnd->scsi_done(req->scmnd);
-                       srp_remove_req(target, req);
-               }
+               if (req->scmnd->device == scmnd->device)
+                       srp_reset_req(target, req);
 
        spin_unlock_irq(target->scsi_host->host_lock);
 
@@ -1329,11 +1434,23 @@ static ssize_t show_dgid(struct class_device *cdev, char *buf)
                       be16_to_cpu(((__be16 *) target->path.dgid.raw)[7]));
 }
 
+static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf)
+{
+       struct srp_target_port *target = host_to_target(class_to_shost(cdev));
+
+       if (target->state == SRP_TARGET_DEAD ||
+           target->state == SRP_TARGET_REMOVED)
+               return -ENODEV;
+
+       return sprintf(buf, "%d\n", target->zero_req_lim);
+}
+
 static CLASS_DEVICE_ATTR(id_ext,       S_IRUGO, show_id_ext,           NULL);
 static CLASS_DEVICE_ATTR(ioc_guid,     S_IRUGO, show_ioc_guid,         NULL);
 static CLASS_DEVICE_ATTR(service_id,   S_IRUGO, show_service_id,       NULL);
 static CLASS_DEVICE_ATTR(pkey,         S_IRUGO, show_pkey,             NULL);
 static CLASS_DEVICE_ATTR(dgid,         S_IRUGO, show_dgid,             NULL);
+static CLASS_DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim,     NULL);
 
 static struct class_device_attribute *srp_host_attrs[] = {
        &class_device_attr_id_ext,
@@ -1341,6 +1458,7 @@ static struct class_device_attribute *srp_host_attrs[] = {
        &class_device_attr_service_id,
        &class_device_attr_pkey,
        &class_device_attr_dgid,
+       &class_device_attr_zero_req_lim,
        NULL
 };
 
@@ -1354,7 +1472,6 @@ static struct scsi_host_template srp_template = {
        .eh_host_reset_handler          = srp_reset_host,
        .can_queue                      = SRP_SQ_SIZE,
        .this_id                        = -1,
-       .sg_tablesize                   = SRP_MAX_INDIRECT,
        .cmd_per_lun                    = SRP_SQ_SIZE,
        .use_clustering                 = ENABLE_CLUSTERING,
        .shost_attrs                    = srp_host_attrs
@@ -1365,18 +1482,17 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
        sprintf(target->target_name, "SRP.T10:%016llX",
                 (unsigned long long) be64_to_cpu(target->id_ext));
 
-       if (scsi_add_host(target->scsi_host, host->dev->dma_device))
+       if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device))
                return -ENODEV;
 
-       mutex_lock(&host->target_mutex);
+       spin_lock(&host->target_lock);
        list_add_tail(&target->list, &host->target_list);
-       mutex_unlock(&host->target_mutex);
+       spin_unlock(&host->target_lock);
 
        target->state = SRP_TARGET_LIVE;
 
-       /* XXX: are we supposed to have a definition of SCAN_WILD_CARD ?? */
        scsi_scan_target(&target->scsi_host->shost_gendev,
-                        0, target->scsi_id, ~0, 0);
+                        0, target->scsi_id, SCAN_WILD_CARD, 0);
 
        return 0;
 }
@@ -1410,6 +1526,8 @@ enum {
        SRP_OPT_PKEY            = 1 << 3,
        SRP_OPT_SERVICE_ID      = 1 << 4,
        SRP_OPT_MAX_SECT        = 1 << 5,
+       SRP_OPT_MAX_CMD_PER_LUN = 1 << 6,
+       SRP_OPT_IO_CLASS        = 1 << 7,
        SRP_OPT_ALL             = (SRP_OPT_ID_EXT       |
                                   SRP_OPT_IOC_GUID     |
                                   SRP_OPT_DGID         |
@@ -1418,13 +1536,15 @@ enum {
 };
 
 static match_table_t srp_opt_tokens = {
-       { SRP_OPT_ID_EXT,       "id_ext=%s"     },
-       { SRP_OPT_IOC_GUID,     "ioc_guid=%s"   },
-       { SRP_OPT_DGID,         "dgid=%s"       },
-       { SRP_OPT_PKEY,         "pkey=%x"       },
-       { SRP_OPT_SERVICE_ID,   "service_id=%s" },
-       { SRP_OPT_MAX_SECT,     "max_sect=%d"   },
-       { SRP_OPT_ERR,          NULL            }
+       { SRP_OPT_ID_EXT,               "id_ext=%s"             },
+       { SRP_OPT_IOC_GUID,             "ioc_guid=%s"           },
+       { SRP_OPT_DGID,                 "dgid=%s"               },
+       { SRP_OPT_PKEY,                 "pkey=%x"               },
+       { SRP_OPT_SERVICE_ID,           "service_id=%s"         },
+       { SRP_OPT_MAX_SECT,             "max_sect=%d"           },
+       { SRP_OPT_MAX_CMD_PER_LUN,      "max_cmd_per_lun=%d"    },
+       { SRP_OPT_IO_CLASS,             "io_class=%x"           },
+       { SRP_OPT_ERR,                  NULL                    }
 };
 
 static int srp_parse_options(const char *buf, struct srp_target_port *target)
@@ -1500,6 +1620,29 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
                        target->scsi_host->max_sectors = token;
                        break;
 
+               case SRP_OPT_MAX_CMD_PER_LUN:
+                       if (match_int(args, &token)) {
+                               printk(KERN_WARNING PFX "bad max cmd_per_lun parameter '%s'\n", p);
+                               goto out;
+                       }
+                       target->scsi_host->cmd_per_lun = min(token, SRP_SQ_SIZE);
+                       break;
+
+               case SRP_OPT_IO_CLASS:
+                       if (match_hex(args, &token)) {
+                               printk(KERN_WARNING PFX "bad  IO class parameter '%s' \n", p);
+                               goto out;
+                       }
+                       if (token != SRP_REV10_IB_IO_CLASS &&
+                           token != SRP_REV16A_IB_IO_CLASS) {
+                               printk(KERN_WARNING PFX "unknown IO class parameter value"
+                                      " %x specified (use %x or %x).\n",
+                                      token, SRP_REV10_IB_IO_CLASS, SRP_REV16A_IB_IO_CLASS);
+                               goto out;
+                       }
+                       target->io_class = token;
+                       break;
+
                default:
                        printk(KERN_WARNING PFX "unknown parameter or missing value "
                               "'%s' in target creation request\n", p);
@@ -1542,6 +1685,7 @@ static ssize_t srp_create_target(struct class_device *class_dev,
        target = host_to_target(target_host);
        memset(target, 0, sizeof *target);
 
+       target->io_class   = SRP_REV16A_IB_IO_CLASS;
        target->scsi_host  = target_host;
        target->srp_host   = host;
 
@@ -1558,7 +1702,7 @@ static ssize_t srp_create_target(struct class_device *class_dev,
        if (ret)
                goto err;
 
-       ib_get_cached_gid(host->dev, host->port, 0, &target->path.sgid);
+       ib_get_cached_gid(host->dev->dev, host->port, 0, &target->path.sgid);
 
        printk(KERN_DEBUG PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
               "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
@@ -1579,7 +1723,7 @@ static ssize_t srp_create_target(struct class_device *class_dev,
        if (ret)
                goto err;
 
-       target->cm_id = ib_create_cm_id(host->dev, srp_cm_handler, target);
+       target->cm_id = ib_create_cm_id(host->dev->dev, srp_cm_handler, target);
        if (IS_ERR(target->cm_id)) {
                ret = PTR_ERR(target->cm_id);
                goto err_free;
@@ -1619,7 +1763,7 @@ static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
        struct srp_host *host =
                container_of(class_dev, struct srp_host, class_dev);
 
-       return sprintf(buf, "%s\n", host->dev->name);
+       return sprintf(buf, "%s\n", host->dev->dev->name);
 }
 
 static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
@@ -1634,7 +1778,7 @@ static ssize_t show_port(struct class_device *class_dev, char *buf)
 
 static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
 
-static struct srp_host *srp_add_port(struct ib_device *device, u8 port)
+static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
 {
        struct srp_host *host;
 
@@ -1643,32 +1787,21 @@ static struct srp_host *srp_add_port(struct ib_device *device, u8 port)
                return NULL;
 
        INIT_LIST_HEAD(&host->target_list);
-       mutex_init(&host->target_mutex);
+       spin_lock_init(&host->target_lock);
        init_completion(&host->released);
        host->dev  = device;
        host->port = port;
 
        host->initiator_port_id[7] = port;
-       memcpy(host->initiator_port_id + 8, &device->node_guid, 8);
-
-       host->pd   = ib_alloc_pd(device);
-       if (IS_ERR(host->pd))
-               goto err_free;
-
-       host->mr   = ib_get_dma_mr(host->pd,
-                                  IB_ACCESS_LOCAL_WRITE |
-                                  IB_ACCESS_REMOTE_READ |
-                                  IB_ACCESS_REMOTE_WRITE);
-       if (IS_ERR(host->mr))
-               goto err_pd;
+       memcpy(host->initiator_port_id + 8, &device->dev->node_guid, 8);
 
        host->class_dev.class = &srp_class;
-       host->class_dev.dev   = device->dma_device;
+       host->class_dev.dev   = device->dev->dma_device;
        snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d",
-                device->name, port);
+                device->dev->name, port);
 
        if (class_device_register(&host->class_dev))
-               goto err_mr;
+               goto free_host;
        if (class_device_create_file(&host->class_dev, &class_device_attr_add_target))
                goto err_class;
        if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev))
@@ -1681,13 +1814,7 @@ static struct srp_host *srp_add_port(struct ib_device *device, u8 port)
 err_class:
        class_device_unregister(&host->class_dev);
 
-err_mr:
-       ib_dereg_mr(host->mr);
-
-err_pd:
-       ib_dealloc_pd(host->pd);
-
-err_free:
+free_host:
        kfree(host);
 
        return NULL;
@@ -1695,15 +1822,62 @@ err_free:
 
 static void srp_add_one(struct ib_device *device)
 {
-       struct list_head *dev_list;
+       struct srp_device *srp_dev;
+       struct ib_device_attr *dev_attr;
+       struct ib_fmr_pool_param fmr_param;
        struct srp_host *host;
        int s, e, p;
 
-       dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
-       if (!dev_list)
+       dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);
+       if (!dev_attr)
                return;
 
-       INIT_LIST_HEAD(dev_list);
+       if (ib_query_device(device, dev_attr)) {
+               printk(KERN_WARNING PFX "Query device failed for %s\n",
+                      device->name);
+               goto free_attr;
+       }
+
+       srp_dev = kmalloc(sizeof *srp_dev, GFP_KERNEL);
+       if (!srp_dev)
+               goto free_attr;
+
+       /*
+        * Use the smallest page size supported by the HCA, down to a
+        * minimum of 512 bytes (which is the smallest sector that a
+        * SCSI command will ever carry).
+        */
+       srp_dev->fmr_page_shift = max(9, ffs(dev_attr->page_size_cap) - 1);
+       srp_dev->fmr_page_size  = 1 << srp_dev->fmr_page_shift;
+       srp_dev->fmr_page_mask  = ~((unsigned long) srp_dev->fmr_page_size - 1);
+
+       INIT_LIST_HEAD(&srp_dev->dev_list);
+
+       srp_dev->dev = device;
+       srp_dev->pd  = ib_alloc_pd(device);
+       if (IS_ERR(srp_dev->pd))
+               goto free_dev;
+
+       srp_dev->mr = ib_get_dma_mr(srp_dev->pd,
+                                   IB_ACCESS_LOCAL_WRITE |
+                                   IB_ACCESS_REMOTE_READ |
+                                   IB_ACCESS_REMOTE_WRITE);
+       if (IS_ERR(srp_dev->mr))
+               goto err_pd;
+
+       memset(&fmr_param, 0, sizeof fmr_param);
+       fmr_param.pool_size         = SRP_FMR_POOL_SIZE;
+       fmr_param.dirty_watermark   = SRP_FMR_DIRTY_SIZE;
+       fmr_param.cache             = 1;
+       fmr_param.max_pages_per_fmr = SRP_FMR_SIZE;
+       fmr_param.page_shift        = srp_dev->fmr_page_shift;
+       fmr_param.access            = (IB_ACCESS_LOCAL_WRITE |
+                                      IB_ACCESS_REMOTE_WRITE |
+                                      IB_ACCESS_REMOTE_READ);
+
+       srp_dev->fmr_pool = ib_create_fmr_pool(srp_dev->pd, &fmr_param);
+       if (IS_ERR(srp_dev->fmr_pool))
+               srp_dev->fmr_pool = NULL;
 
        if (device->node_type == IB_NODE_SWITCH) {
                s = 0;
@@ -1714,25 +1888,35 @@ static void srp_add_one(struct ib_device *device)
        }
 
        for (p = s; p <= e; ++p) {
-               host = srp_add_port(device, p);
+               host = srp_add_port(srp_dev, p);
                if (host)
-                       list_add_tail(&host->list, dev_list);
+                       list_add_tail(&host->list, &srp_dev->dev_list);
        }
 
-       ib_set_client_data(device, &srp_client, dev_list);
+       ib_set_client_data(device, &srp_client, srp_dev);
+
+       goto free_attr;
+
+err_pd:
+       ib_dealloc_pd(srp_dev->pd);
+
+free_dev:
+       kfree(srp_dev);
+
+free_attr:
+       kfree(dev_attr);
 }
 
 static void srp_remove_one(struct ib_device *device)
 {
-       struct list_head *dev_list;
+       struct srp_device *srp_dev;
        struct srp_host *host, *tmp_host;
        LIST_HEAD(target_list);
        struct srp_target_port *target, *tmp_target;
-       unsigned long flags;
 
-       dev_list = ib_get_client_data(device, &srp_client);
+       srp_dev = ib_get_client_data(device, &srp_client);
 
-       list_for_each_entry_safe(host, tmp_host, dev_list, list) {
+       list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
                class_device_unregister(&host->class_dev);
                /*
                 * Wait for the sysfs entry to go away, so that no new
@@ -1744,15 +1928,13 @@ static void srp_remove_one(struct ib_device *device)
                 * Mark all target ports as removed, so we stop queueing
                 * commands and don't try to reconnect.
                 */
-               mutex_lock(&host->target_mutex);
-               list_for_each_entry_safe(target, tmp_target,
-                                        &host->target_list, list) {
-                       spin_lock_irqsave(target->scsi_host->host_lock, flags);
-                       if (target->state != SRP_TARGET_REMOVED)
-                               target->state = SRP_TARGET_REMOVED;
-                       spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+               spin_lock(&host->target_lock);
+               list_for_each_entry(target, &host->target_list, list) {
+                       spin_lock_irq(target->scsi_host->host_lock);
+                       target->state = SRP_TARGET_REMOVED;
+                       spin_unlock_irq(target->scsi_host->host_lock);
                }
-               mutex_unlock(&host->target_mutex);
+               spin_unlock(&host->target_lock);
 
                /*
                 * Wait for any reconnection tasks that may have
@@ -1770,18 +1952,26 @@ static void srp_remove_one(struct ib_device *device)
                        scsi_host_put(target->scsi_host);
                }
 
-               ib_dereg_mr(host->mr);
-               ib_dealloc_pd(host->pd);
                kfree(host);
        }
 
-       kfree(dev_list);
+       if (srp_dev->fmr_pool)
+               ib_destroy_fmr_pool(srp_dev->fmr_pool);
+       ib_dereg_mr(srp_dev->mr);
+       ib_dealloc_pd(srp_dev->pd);
+
+       kfree(srp_dev);
 }
 
 static int __init srp_init_module(void)
 {
        int ret;
 
+       srp_template.sg_tablesize = srp_sg_tablesize;
+       srp_max_iu_len = (sizeof (struct srp_cmd) +
+                         sizeof (struct srp_indirect_buf) +
+                         srp_sg_tablesize * 16);
+
        ret = class_register(&srp_class);
        if (ret) {
                printk(KERN_ERR PFX "couldn't register class infiniband_srp\n");
index c5cd43aae8604af42fb349b160e608a10a84c16d..5b581fb8eb0d08addeea3f9a5fff4763592f1ed6 100644 (file)
@@ -46,6 +46,7 @@
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_sa.h>
 #include <rdma/ib_cm.h>
+#include <rdma/ib_fmr_pool.h>
 
 enum {
        SRP_PATH_REC_TIMEOUT_MS = 1000,
@@ -55,20 +56,21 @@ enum {
        SRP_DLID_REDIRECT       = 2,
 
        SRP_MAX_LUN             = 512,
-       SRP_MAX_IU_LEN          = 256,
+       SRP_DEF_SG_TABLESIZE    = 12,
 
        SRP_RQ_SHIFT            = 6,
        SRP_RQ_SIZE             = 1 << SRP_RQ_SHIFT,
        SRP_SQ_SIZE             = SRP_RQ_SIZE - 1,
        SRP_CQ_SIZE             = SRP_SQ_SIZE + SRP_RQ_SIZE,
 
-       SRP_TAG_TSK_MGMT        = 1 << (SRP_RQ_SHIFT + 1)
+       SRP_TAG_TSK_MGMT        = 1 << (SRP_RQ_SHIFT + 1),
+
+       SRP_FMR_SIZE            = 256,
+       SRP_FMR_POOL_SIZE       = 1024,
+       SRP_FMR_DIRTY_SIZE      = SRP_FMR_POOL_SIZE / 4
 };
 
 #define SRP_OP_RECV            (1 << 31)
-#define SRP_MAX_INDIRECT       ((SRP_MAX_IU_LEN -                      \
-                                 sizeof (struct srp_cmd) -             \
-                                 sizeof (struct srp_indirect_buf)) / 16)
 
 enum srp_target_state {
        SRP_TARGET_LIVE,
@@ -77,15 +79,24 @@ enum srp_target_state {
        SRP_TARGET_REMOVED
 };
 
-struct srp_host {
-       u8                      initiator_port_id[16];
+struct srp_device {
+       struct list_head        dev_list;
        struct ib_device       *dev;
-       u8                      port;
        struct ib_pd           *pd;
        struct ib_mr           *mr;
+       struct ib_fmr_pool     *fmr_pool;
+       int                     fmr_page_shift;
+       int                     fmr_page_size;
+       unsigned long           fmr_page_mask;
+};
+
+struct srp_host {
+       u8                      initiator_port_id[16];
+       struct srp_device      *dev;
+       u8                      port;
        struct class_device     class_dev;
        struct list_head        target_list;
-       struct mutex            target_mutex;
+       spinlock_t              target_lock;
        struct completion       released;
        struct list_head        list;
 };
@@ -95,6 +106,7 @@ struct srp_request {
        struct scsi_cmnd       *scmnd;
        struct srp_iu          *cmd;
        struct srp_iu          *tsk_mgmt;
+       struct ib_pool_fmr     *fmr;
        /*
         * Fake scatterlist used when scmnd->use_sg==0.  Can be killed
         * when the SCSI midlayer no longer generates non-SG commands.
@@ -110,6 +122,7 @@ struct srp_target_port {
        __be64                  id_ext;
        __be64                  ioc_guid;
        __be64                  service_id;
+       u16                     io_class;
        struct srp_host        *srp_host;
        struct Scsi_Host       *scsi_host;
        char                    target_name[32];
@@ -126,6 +139,8 @@ struct srp_target_port {
        int                     max_ti_iu_len;
        s32                     req_lim;
 
+       int                     zero_req_lim;
+
        unsigned                rx_head;
        struct srp_iu          *rx_ring[SRP_RQ_SIZE];
 
index 2b2ec1057deeff1c9fc40f963da81cbbd7267de5..95c0de7964a0803f788764a7426cb66b75f79867 100644 (file)
@@ -589,7 +589,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
        struct sw *sw;
        struct input_dev *input_dev;
        int i, j, k, l;
-       int err;
+       int err = 0;
        unsigned char *buf = NULL;      /* [SW_LENGTH] */
        unsigned char *idbuf = NULL;    /* [SW_LENGTH] */
        unsigned char m = 1;
@@ -776,7 +776,10 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
                        goto fail4;
        }
 
-       return 0;
+ out:  kfree(buf);
+       kfree(idbuf);
+
+       return err;
 
  fail4:        input_free_device(sw->dev[i]);
  fail3:        while (--i >= 0)
@@ -784,9 +787,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
  fail2:        gameport_close(gameport);
  fail1:        gameport_set_drvdata(gameport, NULL);
        kfree(sw);
-       kfree(buf);
-       kfree(idbuf);
-       return err;
+       goto out;
 }
 
 static void sw_disconnect(struct gameport *gameport)
index 96c6bf77248ae7a67dc134ccfffb7f8465ffd974..1f0e720267d75312c0a52eaa44b5e5764eaf53ce 100644 (file)
@@ -245,9 +245,9 @@ static void corgikbd_hinge_timer(unsigned long data)
                if (hinge_count >= HINGE_STABLE_COUNT) {
                        spin_lock_irqsave(&corgikbd_data->lock, flags);
 
-                       input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
-                       input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
-                       input_report_switch(corgikbd_data->input, SW_2, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0));
+                       input_report_switch(corgikbd_data->input, SW_LID, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0));
+                       input_report_switch(corgikbd_data->input, SW_TABLET_MODE, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0));
+                       input_report_switch(corgikbd_data->input, SW_HEADPHONE_INSERT, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0));
                        input_sync(corgikbd_data->input);
 
                        spin_unlock_irqrestore(&corgikbd_data->lock, flags);
@@ -340,9 +340,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
        for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
                set_bit(corgikbd->keycode[i], input_dev->keybit);
        clear_bit(0, input_dev->keybit);
-       set_bit(SW_0, input_dev->swbit);
-       set_bit(SW_1, input_dev->swbit);
-       set_bit(SW_2, input_dev->swbit);
+       set_bit(SW_LID, input_dev->swbit);
+       set_bit(SW_TABLET_MODE, input_dev->swbit);
+       set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
 
        input_register_device(corgikbd->input);
 
index 1d238a9d52d68532d4d29e31f00d6e2be9ab6539..c5d03fb77bcb9a364ca16ea075d469425c671950 100644 (file)
@@ -299,9 +299,9 @@ static void spitzkbd_hinge_timer(unsigned long data)
        if (hinge_count >= HINGE_STABLE_COUNT) {
                spin_lock_irqsave(&spitzkbd_data->lock, flags);
 
-               input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
-               input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
-               input_report_switch(spitzkbd_data->input, SW_2, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0));
+               input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
+               input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+               input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0));
                input_sync(spitzkbd_data->input);
 
                spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
@@ -398,9 +398,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
        for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
                set_bit(spitzkbd->keycode[i], input_dev->keybit);
        clear_bit(0, input_dev->keybit);
-       set_bit(SW_0, input_dev->swbit);
-       set_bit(SW_1, input_dev->swbit);
-       set_bit(SW_2, input_dev->swbit);
+       set_bit(SW_LID, input_dev->swbit);
+       set_bit(SW_TABLET_MODE, input_dev->swbit);
+       set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
 
        input_register_device(input_dev);
 
index 36cd2e07fce8bf6be22b476a462ac375d698a1b5..e4e5be111c960b67834e2742a9475bbd73b2d42f 100644 (file)
@@ -318,6 +318,16 @@ static struct key_entry keymap_acer_travelmate_240[] = {
        { KE_END, 0 }
 };
 
+static struct key_entry keymap_aopen_1559as[] = {
+       { KE_KEY,  0x01, KEY_HELP },
+       { KE_KEY,  0x06, KEY_PROG3 },
+       { KE_KEY,  0x11, KEY_PROG1 },
+       { KE_KEY,  0x12, KEY_PROG2 },
+       { KE_WIFI, 0x30, 0 },
+       { KE_KEY,  0x31, KEY_MAIL },
+       { KE_KEY,  0x36, KEY_WWW },
+};
+
 /*
  * If your machine is not here (which is currently rather likely), please send
  * a list of buttons and their key codes (reported when loading this module
@@ -369,6 +379,15 @@ static struct dmi_system_id dmi_ids[] = {
                },
                .driver_data = keymap_acer_travelmate_240
        },
+        {
+               .callback = dmi_matched,
+               .ident = "AOpen 1559AS",
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "E2U"),
+                       DMI_MATCH(DMI_BOARD_NAME, "E2U"),
+               },
+               .driver_data = keymap_aopen_1559as
+       },
        { NULL, }
 };
 
index 2141501e9f2e498246df66233623490ade12494a..a0e2e797c6d5a6c9e3cceeb6659a9299630c5af5 100644 (file)
@@ -100,8 +100,8 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
        }
 
        if (priv->i->flags & ALPS_OLDPROTO) {
-               left = packet[2] & 0x08;
-               right = packet[2] & 0x10;
+               left = packet[2] & 0x10;
+               right = packet[2] & 0x08;
                middle = 0;
                x = packet[1] | ((packet[0] & 0x07) << 7);
                y = packet[4] | ((packet[3] & 0x07) << 7);
index 5ccc3ef3b89e84fe4d246a7a3fc6fd6d0b943394..c14395ba798005d31a14b7c3c0e135548ed4c03d 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 = {
index 40333d61093c805383ed3f7ae245dfdd12a51f95..2f0d28840810aad3c4811d276aa1a0cb6ffb17b8 100644 (file)
@@ -19,6 +19,7 @@
 #define PS2PP_KIND_WHEEL       1
 #define PS2PP_KIND_MX          2
 #define PS2PP_KIND_TP3         3
+#define PS2PP_KIND_TRACKMAN    4
 
 /* Logitech mouse features */
 #define PS2PP_WHEEL            0x01
@@ -223,6 +224,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
                { 73,   0,                      PS2PP_SIDE_BTN },
                { 75,   PS2PP_KIND_WHEEL,       PS2PP_WHEEL },
                { 76,   PS2PP_KIND_WHEEL,       PS2PP_WHEEL },
+               { 79,   PS2PP_KIND_TRACKMAN,    PS2PP_WHEEL },          /* TrackMan with wheel */
                { 80,   PS2PP_KIND_WHEEL,       PS2PP_SIDE_BTN | PS2PP_WHEEL },
                { 81,   PS2PP_KIND_WHEEL,       PS2PP_WHEEL },
                { 83,   PS2PP_KIND_WHEEL,       PS2PP_WHEEL },
@@ -298,6 +300,10 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse, struct ps2pp_inf
                        psmouse->name = "TouchPad 3";
                        break;
 
+               case PS2PP_KIND_TRACKMAN:
+                       psmouse->name = "TrackMan";
+                       break;
+
                default:
                        /*
                         * Set name to "Mouse" only when using PS2++,
index 1494175ac6fe43d0666e3cfed2426cfb0e622ed5..161afddd0f44396da88402f0af5bb2b9445f1a74 100644 (file)
 
 
 /*
- * This code has been tested on an ads7846 / N770 device.
+ * This code has been heavily tested on a Nokia 770, and lightly
+ * tested on other ads7846 devices (OSK/Mistral, Lubbock).
  * Support for ads7843 and ads7845 has only been stubbed in.
  *
- * Not yet done:  How accurate are the temperature and voltage
- * readings? (System-specific calibration should support
- * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.)
- *
  * IRQ handling needs a workaround because of a shortcoming in handling
  * edge triggered IRQs on some platforms like the OMAP1/2. These
  * platforms don't handle the ARM lazy IRQ disabling properly, thus we
@@ -248,10 +245,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
 
        if (req->msg.status)
                status = req->msg.status;
+
+       /* on-wire is a must-ignore bit, a BE12 value, then padding */
        sample = be16_to_cpu(req->sample);
-       sample = sample >> 4;
-       kfree(req);
+       sample = sample >> 3;
+       sample &= 0x0fff;
 
+       kfree(req);
        return status ? status : sample;
 }
 
@@ -336,13 +336,13 @@ static void ads7846_rx(void *ads)
        u16                     x, y, z1, z2;
        unsigned long           flags;
 
-       /* adjust:  12 bit samples (left aligned), built from
-        * two 8 bit values writen msb-first.
+       /* adjust:  on-wire is a must-ignore bit, a BE12 value, then padding;
+        * built from two 8 bit values written msb-first.
         */
-       x = be16_to_cpu(ts->tc.x) >> 4;
-       y = be16_to_cpu(ts->tc.y) >> 4;
-       z1 = be16_to_cpu(ts->tc.z1) >> 4;
-       z2 = be16_to_cpu(ts->tc.z2) >> 4;
+       x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff;
+       y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff;
+       z1 = (be16_to_cpu(ts->tc.z1) >> 3) & 0x0fff;
+       z2 = (be16_to_cpu(ts->tc.z2) >> 3) & 0x0fff;
 
        /* range filtering */
        if (x == MAX_12BIT)
@@ -420,7 +420,7 @@ static void ads7846_debounce(void *ads)
 
        m = &ts->msg[ts->msg_idx];
        t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
-       val = (*(u16 *)t->rx_buf) >> 3;
+       val = (be16_to_cpu(*(__be16 *)t->rx_buf) >> 3) & 0x0fff;
        if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) {
                /* Repeat it, if this was the first read or the read
                 * wasn't consistent enough. */
@@ -469,7 +469,7 @@ static void ads7846_timer(unsigned long handle)
        spin_lock_irq(&ts->lock);
 
        if (unlikely(ts->msg_idx && !ts->pendown)) {
-               /* measurment cycle ended */
+               /* measurement cycle ended */
                if (!device_suspended(&ts->spi->dev)) {
                        ts->irq_disabled = 0;
                        enable_irq(ts->spi->irq);
@@ -495,11 +495,10 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
        spin_lock_irqsave(&ts->lock, flags);
        if (likely(ts->get_pendown_state())) {
                if (!ts->irq_disabled) {
-                       /* REVISIT irq logic for many ARM chips has cloned a
-                        * bug wherein disabling an irq in its handler won't
-                        * work;(it's disabled lazily, and too late to work.
-                        * until all their irq logic is fixed, we must shadow
-                        * that state here.
+                       /* The ARM do_simple_IRQ() dispatcher doesn't act
+                        * like the other dispatchers:  it will report IRQs
+                        * even after they've been disabled.  We work around
+                        * that here.  (The "generic irq" framework may help...)
                         */
                        ts->irq_disabled = 1;
                        disable_irq(ts->spi->irq);
@@ -609,16 +608,20 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                return -EINVAL;
        }
 
+       /* REVISIT when the irq can be triggered active-low, or if for some
+        * reason the touchscreen isn't hooked up, we don't need to access
+        * the pendown state.
+        */
        if (pdata->get_pendown_state == NULL) {
                dev_dbg(&spi->dev, "no get_pendown_state function?\n");
                return -EINVAL;
        }
 
-       /* We'd set the wordsize to 12 bits ... except that some controllers
-        * will then treat the 8 bit command words as 12 bits (and drop the
-        * four MSBs of the 12 bit result).  Result: inputs must be shifted
-        * to discard the four garbage LSBs.
+       /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
+        * that even if the hardware can do that, the SPI controller driver
+        * may not.  So we stick to very-portable 8 bit words, both RX and TX.
         */
+       spi->bits_per_word = 8;
 
        ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
        input_dev = input_allocate_device();
@@ -772,7 +775,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 
        if (request_irq(spi->irq, ads7846_irq,
                        SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
-                       spi->dev.bus_id, ts)) {
+                       spi->dev.driver->name, ts)) {
                dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
                err = -EBUSY;
                goto err_free_mem;
index 3ca3cfb03a7e28078e125509ed858587f403d00f..f19b874753a9c4aec3802b557ab05100f387ff61 100644 (file)
@@ -167,6 +167,15 @@ void md_new_event(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(md_new_event);
 
+/* Alternate version that can be called from interrupts
+ * when calling sysfs_notify isn't needed.
+ */
+void md_new_event_inintr(mddev_t *mddev)
+{
+       atomic_inc(&md_event_count);
+       wake_up(&md_event_waiters);
+}
+
 /*
  * Enables to iterate over all existing md arrays
  * all_mddevs_lock protects this list.
@@ -4149,7 +4158,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
        set_bit(MD_RECOVERY_INTR, &mddev->recovery);
        set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
        md_wakeup_thread(mddev->thread);
-       md_new_event(mddev);
+       md_new_event_inintr(mddev);
 }
 
 /* seq_file implementation /proc/mdstat */
@@ -5028,8 +5037,10 @@ static int md_notify_reboot(struct notifier_block *this,
                printk(KERN_INFO "md: stopping all md devices.\n");
 
                ITERATE_MDDEV(mddev,tmp)
-                       if (mddev_trylock(mddev))
+                       if (mddev_trylock(mddev)) {
                                do_md_stop (mddev, 1);
+                               mddev_unlock(mddev);
+                       }
                /*
                 * certain more exotic SCSI devices are known to be
                 * volatile wrt too early system reboots. While the
index 2f0f35811bf7710c2a95e63bbeaa37c2900be0af..9fd87521a1639bd3dae51dcdce48545614d41a85 100644 (file)
@@ -1052,7 +1052,7 @@ static void wq_set_multicast_list (void *data)
 
        dvb_net_feed_stop(dev);
        priv->rx_mode = RX_MODE_UNI;
-       spin_lock_bh(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
 
        if (dev->flags & IFF_PROMISC) {
                dprintk("%s: promiscuous mode\n", dev->name);
@@ -1077,7 +1077,7 @@ static void wq_set_multicast_list (void *data)
                }
        }
 
-       spin_unlock_bh(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
        dvb_net_feed_start(dev);
 }
 
index 9080853fe283554c986f6636b34ee3bc42008b43..a30084076ac8884168c444d04d9377a32238507d 100644 (file)
@@ -1605,6 +1605,21 @@ mpt_resume(struct pci_dev *pdev)
 }
 #endif
 
+static int
+mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase)
+{
+       if ((MptDriverClass[index] == MPTSPI_DRIVER &&
+            ioc->bus_type != SPI) ||
+           (MptDriverClass[index] == MPTFC_DRIVER &&
+            ioc->bus_type != FC) ||
+           (MptDriverClass[index] == MPTSAS_DRIVER &&
+            ioc->bus_type != SAS))
+               /* make sure we only call the relevant reset handler
+                * for the bus */
+               return 0;
+       return (MptResetHandlers[index])(ioc, reset_phase);
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *     mpt_do_ioc_recovery - Initialize or recover MPT adapter.
@@ -1885,14 +1900,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                        if ((ret == 0) && MptResetHandlers[ii]) {
                                dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
                                                ioc->name, ii));
-                               rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
+                               rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET);
                                handlers++;
                        }
 
                        if (alt_ioc_ready && MptResetHandlers[ii]) {
                                drsprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
                                                ioc->name, ioc->alt_ioc->name, ii));
-                               rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
+                               rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET);
                                handlers++;
                        }
                }
@@ -3267,11 +3282,11 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
                                if (MptResetHandlers[ii]) {
                                        dprintk((MYIOC_s_INFO_FMT "Calling IOC pre_reset handler #%d\n",
                                                        ioc->name, ii));
-                                       r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_PRE_RESET);
+                                       r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET);
                                        if (ioc->alt_ioc) {
                                                dprintk((MYIOC_s_INFO_FMT "Calling alt-%s pre_reset handler #%d\n",
                                                                ioc->name, ioc->alt_ioc->name, ii));
-                                               r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_PRE_RESET);
+                                               r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET);
                                        }
                                }
                        }
@@ -5706,11 +5721,11 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
                        if (MptResetHandlers[ii]) {
                                dtmprintk((MYIOC_s_INFO_FMT "Calling IOC reset_setup handler #%d\n",
                                                ioc->name, ii));
-                               r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_SETUP_RESET);
+                               r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET);
                                if (ioc->alt_ioc) {
                                        dtmprintk((MYIOC_s_INFO_FMT "Calling alt-%s setup reset handler #%d\n",
                                                        ioc->name, ioc->alt_ioc->name, ii));
-                                       r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_SETUP_RESET);
+                                       r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET);
                                }
                        }
                }
index f2a4d382ea19e5403b2d2643b5a301476ae3f718..3201de053943c5c278d50e2164419e95b9a02bcf 100644 (file)
@@ -831,6 +831,7 @@ mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
        return rc;
 }
 
+#ifdef CONFIG_PM
 /*
  * spi module resume handler
  */
@@ -846,6 +847,7 @@ mptspi_resume(struct pci_dev *pdev)
 
        return rc;
 }
+#endif
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
index 5ea133c59afb3e7ab2788c2d68c1512723ddf5c6..7bd4d85d0b42db6af28def4072cbd11fbadbec86 100644 (file)
@@ -55,6 +55,7 @@ struct i2o_exec_wait {
        u32 m;                  /* message id */
        struct i2o_message *msg;        /* pointer to the reply message */
        struct list_head list;  /* node in global wait list */
+       spinlock_t lock;        /* lock before modifying */
 };
 
 /* Work struct needed to handle LCT NOTIFY replies */
@@ -87,6 +88,7 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void)
                return NULL;
 
        INIT_LIST_HEAD(&wait->list);
+       spin_lock_init(&wait->lock);
 
        return wait;
 };
@@ -125,6 +127,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
        DECLARE_WAIT_QUEUE_HEAD(wq);
        struct i2o_exec_wait *wait;
        static u32 tcntxt = 0x80000000;
+       long flags;
        int rc = 0;
 
        wait = i2o_exec_wait_alloc();
@@ -146,33 +149,28 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
        wait->tcntxt = tcntxt++;
        msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt);
 
+       wait->wq = &wq;
+       /*
+        * we add elements to the head, because if a entry in the list will
+        * never be removed, we have to iterate over it every time
+        */
+       list_add(&wait->list, &i2o_exec_wait_list);
+
        /*
         * Post the message to the controller. At some point later it will
         * return. If we time out before it returns then complete will be zero.
         */
        i2o_msg_post(c, msg);
 
-       if (!wait->complete) {
-               wait->wq = &wq;
-               /*
-                * we add elements add the head, because if a entry in the list
-                * will never be removed, we have to iterate over it every time
-                */
-               list_add(&wait->list, &i2o_exec_wait_list);
-
-               wait_event_interruptible_timeout(wq, wait->complete,
-                                                timeout * HZ);
+       wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ);
 
-               wait->wq = NULL;
-       }
+       spin_lock_irqsave(&wait->lock, flags);
 
-       barrier();
+       wait->wq = NULL;
 
-       if (wait->complete) {
+       if (wait->complete)
                rc = le32_to_cpu(wait->msg->body[0]) >> 24;
-               i2o_flush_reply(c, wait->m);
-               i2o_exec_wait_free(wait);
-       } else {
+       else {
                /*
                 * We cannot remove it now. This is important. When it does
                 * terminate (which it must do if the controller has not
@@ -186,6 +184,13 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
                rc = -ETIMEDOUT;
        }
 
+       spin_unlock_irqrestore(&wait->lock, flags);
+
+       if (rc != -ETIMEDOUT) {
+               i2o_flush_reply(c, wait->m);
+               i2o_exec_wait_free(wait);
+       }
+
        return rc;
 };
 
@@ -213,7 +218,6 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
 {
        struct i2o_exec_wait *wait, *tmp;
        unsigned long flags;
-       static spinlock_t lock = SPIN_LOCK_UNLOCKED;
        int rc = 1;
 
        /*
@@ -223,23 +227,24 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
         * already expired. Not much we can do about that except log it for
         * debug purposes, increase timeout, and recompile.
         */
-       spin_lock_irqsave(&lock, flags);
        list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
                if (wait->tcntxt == context) {
-                       list_del(&wait->list);
+                       spin_lock_irqsave(&wait->lock, flags);
 
-                       spin_unlock_irqrestore(&lock, flags);
+                       list_del(&wait->list);
 
                        wait->m = m;
                        wait->msg = msg;
                        wait->complete = 1;
 
-                       barrier();
-
-                       if (wait->wq) {
-                               wake_up_interruptible(wait->wq);
+                       if (wait->wq)
                                rc = 0;
-                       } else {
+                       else
+                               rc = -1;
+
+                       spin_unlock_irqrestore(&wait->lock, flags);
+
+                       if (rc) {
                                struct device *dev;
 
                                dev = &c->pdev->dev;
@@ -248,15 +253,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
                                         c->name);
                                i2o_dma_free(dev, &wait->dma);
                                i2o_exec_wait_free(wait);
-                               rc = -1;
-                       }
+                       } else
+                               wake_up_interruptible(wait->wq);
 
                        return rc;
                }
        }
 
-       spin_unlock_irqrestore(&lock, flags);
-
        osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
                 context);
 
@@ -322,14 +325,9 @@ static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL);
 static int i2o_exec_probe(struct device *dev)
 {
        struct i2o_device *i2o_dev = to_i2o_device(dev);
-       struct i2o_controller *c = i2o_dev->iop;
 
        i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
 
-       c->exec = i2o_dev;
-
-       i2o_exec_lct_notify(c, c->lct->change_ind + 1);
-
        device_create_file(dev, &dev_attr_vendor_id);
        device_create_file(dev, &dev_attr_product_id);
 
@@ -523,6 +521,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
        struct device *dev;
        struct i2o_message *msg;
 
+       down(&c->lct_lock);
+
        dev = &c->pdev->dev;
 
        if (i2o_dma_realloc
@@ -545,6 +545,8 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
 
        i2o_msg_post(c, msg);
 
+       up(&c->lct_lock);
+
        return 0;
 };
 
index 49216744693651f41480872faf8cfeb339dc7ab8..febbdd4e0605ddeed250f534ebeda84ac77682ac 100644 (file)
@@ -804,8 +804,6 @@ void i2o_iop_remove(struct i2o_controller *c)
 
        /* Ask the IOP to switch to RESET state */
        i2o_iop_reset(c);
-
-       put_device(&c->device);
 }
 
 /**
@@ -1059,7 +1057,7 @@ struct i2o_controller *i2o_iop_alloc(void)
 
        snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name);
        if (i2o_pool_alloc
-           (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4,
+           (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32),
             I2O_MSG_INPOOL_MIN)) {
                kfree(c);
                return ERR_PTR(-ENOMEM);
index 003b077c2324c26861694ad5d22de06ede24faf2..45bcf098e762c500e3777facb3a85c8f841ab385 100644 (file)
@@ -84,7 +84,7 @@ config MMC_WBSD
 
 config MMC_AU1X
        tristate "Alchemy AU1XX0 MMC Card Interface support"
-       depends on SOC_AU1X00 && MMC
+       depends on MMC && SOC_AU1200
        help
          This selects the AMD Alchemy(R) Multimedia card interface.
          If you have a Alchemy platform with a MMC slot, say Y or M here.
index b0053280ff2db61725a7bddba23287e36907428f..6bfcdbc7491e9ac01a601cd364016dcdc05b18cf 100644 (file)
@@ -1073,7 +1073,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        tasklet_init(&host->finish_tasklet,
                sdhci_tasklet_finish, (unsigned long)host);
 
-       setup_timer(&host->timer, sdhci_timeout_timer, (int)host);
+       setup_timer(&host->timer, sdhci_timeout_timer, (long)host);
 
        ret = request_irq(host->irq, sdhci_irq, SA_SHIRQ,
                host->slot_descr, host);
index f6b775e63ac8f07499767ae828f52cad418a067c..5ac265dde4235da928e1e7e598e2b235ea5a0901 100644 (file)
@@ -78,7 +78,7 @@ config MTD_REDBOOT_DIRECTORY_BLOCK
          option.
 
          The option specifies which Flash sectors holds the RedBoot
-         partition table.  A zero or positive value gives an absolete
+         partition table.  A zero or positive value gives an absolute
          erase block number. A negative value specifies a number of
          sectors before the end of the device.
 
@@ -103,7 +103,7 @@ config MTD_CMDLINE_PARTS
        bool "Command line partition table parsing"
        depends on MTD_PARTITIONS = "y"
        ---help---
-         Allow generic configuration of the MTD paritition tables via the kernel
+         Allow generic configuration of the MTD partition tables via the kernel
          command line. Multiple flash resources are supported for hardware where
          different kinds of flash memory are available.
 
index a7ec5954caf54bcf88d7582c929ab55a2be02263..6d8f30deb8689e14a5a7d385bc45abc888b8777e 100644 (file)
@@ -30,7 +30,6 @@ config MTD_JEDECPROBE
 
 config MTD_GEN_PROBE
        tristate
-       select OBSOLETE_INTERMODULE
 
 config MTD_CFI_ADV_OPTIONS
        bool "Flash chip driver advanced configuration options"
index 8afe3092c4e38ba73214c3f255006c3bced97a3a..75bc1c2a0f431b9954447921f03b7246ed2fb395 100644 (file)
@@ -3,13 +3,6 @@
 #
 # $Id: Makefile.common,v 1.5 2005/11/07 11:14:22 gleixner Exp $
 
-#                       *** BIG UGLY NOTE ***
-#
-# The removal of get_module_symbol() and replacement with
-# inter_module_register() et al has introduced a link order dependency
-# here where previously there was none.  We now have to ensure that
-# the CFI command set drivers are linked before gen_probe.o
-
 obj-$(CONFIG_MTD)              += chipreg.o
 obj-$(CONFIG_MTD_AMDSTD)       += amd_flash.o
 obj-$(CONFIG_MTD_CFI)          += cfi_probe.o
index 57115618c4968903e0a4d70052bc6d54c6e64e3b..16eaca69fb5aff52137560149b4409217463f47b 100644 (file)
@@ -97,7 +97,6 @@ struct amd_flash_private {
        int interleave;
        int numchips;
        unsigned long chipshift;
-//     const char *im_name;
        struct flchip chips[0];
 };
 
@@ -131,12 +130,6 @@ static struct mtd_chip_driver amd_flash_chipdrv = {
        .module = THIS_MODULE
 };
 
-
-
-static const char im_name[] = "amd_flash";
-
-
-
 static inline __u32 wide_read(struct map_info *map, __u32 addr)
 {
        if (map->buswidth == 1) {
@@ -737,6 +730,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
                offset += dev_size;
        }
        mtd->type = MTD_NORFLASH;
+       mtd->writesize = 1;
        mtd->flags = MTD_CAP_NORFLASH;
        mtd->name = map->name;
        mtd->erase = amd_flash_erase;
index 1c074d63ff3af865d52acf29d59aa1be824c41bf..0d435814aaa137aba3274696c0a118515f155fa4 100644 (file)
@@ -331,13 +331,6 @@ read_pri_intelext(struct map_info *map, __u16 adr)
        return extp;
 }
 
-/* This routine is made available to other mtd code via
- * inter_module_register.  It must only be accessed through
- * inter_module_get which will bump the use count of this module.  The
- * addresses passed back in cfi are valid as long as the use count of
- * this module is non-zero, i.e. between inter_module_get and
- * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
- */
 struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
 {
        struct cfi_private *cfi = map->fldrv_priv;
@@ -406,7 +399,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
        for (i=0; i< cfi->numchips; i++) {
                cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
                cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
-               cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
+               cfi->chips[i].erase_time = 1000<<cfi->cfiq->BlockEraseTimeoutTyp;
                cfi->chips[i].ref_point_counter = 0;
                init_waitqueue_head(&(cfi->chips[i].wq));
        }
@@ -415,6 +408,11 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
 
        return cfi_intelext_setup(mtd);
 }
+struct mtd_info *cfi_cmdset_0003(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0001")));
+struct mtd_info *cfi_cmdset_0200(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0001")));
+EXPORT_SYMBOL_GPL(cfi_cmdset_0001);
+EXPORT_SYMBOL_GPL(cfi_cmdset_0003);
+EXPORT_SYMBOL_GPL(cfi_cmdset_0200);
 
 static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
 {
@@ -547,12 +545,12 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
                if (extp->MinorVersion >= '4') {
                        struct cfi_intelext_programming_regioninfo *prinfo;
                        prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];
-                       MTD_PROGREGION_SIZE(mtd) = cfi->interleave << prinfo->ProgRegShift;
+                       mtd->writesize = cfi->interleave << prinfo->ProgRegShift;
                        MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid;
                        MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid;
-                       mtd->flags |= MTD_PROGRAM_REGIONS;
+                       mtd->flags &= ~MTD_BIT_WRITEABLE;
                        printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",
-                              map->name, MTD_PROGREGION_SIZE(mtd),
+                              map->name, mtd->writesize,
                               MTD_PROGREGION_CTRLMODE_VALID(mtd),
                               MTD_PROGREGION_CTRLMODE_INVALID(mtd));
                }
@@ -896,26 +894,33 @@ static void __xipram xip_enable(struct map_info *map, struct flchip *chip,
 
 /*
  * When a delay is required for the flash operation to complete, the
- * xip_udelay() function is polling for both the given timeout and pending
- * (but still masked) hardware interrupts.  Whenever there is an interrupt
- * pending then the flash erase or write operation is suspended, array mode
- * restored and interrupts unmasked.  Task scheduling might also happen at that
- * point.  The CPU eventually returns from the interrupt or the call to
- * schedule() and the suspended flash operation is resumed for the remaining
- * of the delay period.
+ * xip_wait_for_operation() function is polling for both the given timeout
+ * and pending (but still masked) hardware interrupts.  Whenever there is an
+ * interrupt pending then the flash erase or write operation is suspended,
+ * array mode restored and interrupts unmasked.  Task scheduling might also
+ * happen at that point.  The CPU eventually returns from the interrupt or
+ * the call to schedule() and the suspended flash operation is resumed for
+ * the remaining of the delay period.
  *
  * Warning: this function _will_ fool interrupt latency tracing tools.
  */
 
-static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
-                               unsigned long adr, int usec)
+static int __xipram xip_wait_for_operation(
+               struct map_info *map, struct flchip *chip,
+               unsigned long adr, int *chip_op_time )
 {
        struct cfi_private *cfi = map->fldrv_priv;
        struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
        map_word status, OK = CMD(0x80);
-       unsigned long suspended, start = xip_currtime();
+       unsigned long usec, suspended, start, done;
        flstate_t oldstate, newstate;
 
+               start = xip_currtime();
+       usec = *chip_op_time * 8;
+       if (usec == 0)
+               usec = 500000;
+       done = 0;
+
        do {
                cpu_relax();
                if (xip_irqpending() && cfip &&
@@ -932,9 +937,9 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
                         * we resume the whole thing at once).  Yes, it
                         * can happen!
                         */
+                       usec -= done;
                        map_write(map, CMD(0xb0), adr);
                        map_write(map, CMD(0x70), adr);
-                       usec -= xip_elapsed_since(start);
                        suspended = xip_currtime();
                        do {
                                if (xip_elapsed_since(suspended) > 100000) {
@@ -944,7 +949,7 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
                                         * This is a critical error but there
                                         * is not much we can do here.
                                         */
-                                       return;
+                                       return -EIO;
                                }
                                status = map_read(map, adr);
                        } while (!map_word_andequal(map, status, OK, OK));
@@ -1004,65 +1009,107 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
                        xip_cpu_idle();
                }
                status = map_read(map, adr);
+               done = xip_elapsed_since(start);
        } while (!map_word_andequal(map, status, OK, OK)
-                && xip_elapsed_since(start) < usec);
-}
+                && done < usec);
 
-#define UDELAY(map, chip, adr, usec)  xip_udelay(map, chip, adr, usec)
+       return (done >= usec) ? -ETIME : 0;
+}
 
 /*
  * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while
  * the flash is actively programming or erasing since we have to poll for
  * the operation to complete anyway.  We can't do that in a generic way with
  * a XIP setup so do it before the actual flash operation in this case
- * and stub it out from INVALIDATE_CACHE_UDELAY.
+ * and stub it out from INVAL_CACHE_AND_WAIT.
  */
 #define XIP_INVAL_CACHED_RANGE(map, from, size)  \
        INVALIDATE_CACHED_RANGE(map, from, size)
 
-#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec)  \
-       UDELAY(map, chip, cmd_adr, usec)
-
-/*
- * Extra notes:
- *
- * Activating this XIP support changes the way the code works a bit.  For
- * example the code to suspend the current process when concurrent access
- * happens is never executed because xip_udelay() will always return with the
- * same chip state as it was entered with.  This is why there is no care for
- * the presence of add_wait_queue() or schedule() calls from within a couple
- * xip_disable()'d  areas of code, like in do_erase_oneblock for example.
- * The queueing and scheduling are always happening within xip_udelay().
- *
- * Similarly, get_chip() and put_chip() just happen to always be executed
- * with chip->state set to FL_READY (or FL_XIP_WHILE_*) where flash state
- * is in array mode, therefore never executing many cases therein and not
- * causing any problem with XIP.
- */
+#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \
+       xip_wait_for_operation(map, chip, cmd_adr, p_usec)
 
 #else
 
 #define xip_disable(map, chip, adr)
 #define xip_enable(map, chip, adr)
 #define XIP_INVAL_CACHED_RANGE(x...)
+#define INVAL_CACHE_AND_WAIT inval_cache_and_wait_for_operation
+
+static int inval_cache_and_wait_for_operation(
+               struct map_info *map, struct flchip *chip,
+               unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
+               int *chip_op_time )
+{
+       struct cfi_private *cfi = map->fldrv_priv;
+       map_word status, status_OK = CMD(0x80);
+       int z, chip_state = chip->state;
+       unsigned long timeo;
+
+       spin_unlock(chip->mutex);
+       if (inval_len)
+               INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
+       if (*chip_op_time)
+               cfi_udelay(*chip_op_time);
+       spin_lock(chip->mutex);
+
+       timeo = *chip_op_time * 8 * HZ / 1000000;
+       if (timeo < HZ/2)
+               timeo = HZ/2;
+       timeo += jiffies;
+
+       z = 0;
+       for (;;) {
+               if (chip->state != chip_state) {
+                       /* Someone's suspended the operation: sleep */
+                       DECLARE_WAITQUEUE(wait, current);
+
+                       set_current_state(TASK_UNINTERRUPTIBLE);
+                       add_wait_queue(&chip->wq, &wait);
+                       spin_unlock(chip->mutex);
+                       schedule();
+                       remove_wait_queue(&chip->wq, &wait);
+                       timeo = jiffies + (HZ / 2); /* FIXME */
+                       spin_lock(chip->mutex);
+                       continue;
+               }
 
-#define UDELAY(map, chip, adr, usec)  \
-do {  \
-       spin_unlock(chip->mutex);  \
-       cfi_udelay(usec);  \
-       spin_lock(chip->mutex);  \
-} while (0)
-
-#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec)  \
-do {  \
-       spin_unlock(chip->mutex);  \
-       INVALIDATE_CACHED_RANGE(map, adr, len);  \
-       cfi_udelay(usec);  \
-       spin_lock(chip->mutex);  \
-} while (0)
+               status = map_read(map, cmd_adr);
+               if (map_word_andequal(map, status, status_OK, status_OK))
+                       break;
+
+               /* OK Still waiting */
+               if (time_after(jiffies, timeo)) {
+                       map_write(map, CMD(0x70), cmd_adr);
+                       chip->state = FL_STATUS;
+                       return -ETIME;
+               }
+
+               /* Latency issues. Drop the lock, wait a while and retry */
+               z++;
+               spin_unlock(chip->mutex);
+               cfi_udelay(1);
+               spin_lock(chip->mutex);
+       }
+
+       if (!z) {
+               if (!--(*chip_op_time))
+                       *chip_op_time = 1;
+       } else if (z > 1)
+               ++(*chip_op_time);
+
+       /* Done and happy. */
+       chip->state = FL_STATUS;
+       return 0;
+}
 
 #endif
 
+#define WAIT_TIMEOUT(map, chip, adr, udelay) \
+       ({ int __udelay = (udelay); \
+          INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); })
+
+
 static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
 {
        unsigned long cmd_addr;
@@ -1252,14 +1299,11 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
                                     unsigned long adr, map_word datum, int mode)
 {
        struct cfi_private *cfi = map->fldrv_priv;
-       map_word status, status_OK, write_cmd;
-       unsigned long timeo;
-       int z, ret=0;
+       map_word status, write_cmd;
+       int ret=0;
 
        adr += chip->start;
 
-       /* Let's determine those according to the interleave only once */
-       status_OK = CMD(0x80);
        switch (mode) {
        case FL_WRITING:
                write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41);
@@ -1285,57 +1329,17 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
        map_write(map, datum, adr);
        chip->state = mode;
 
-       INVALIDATE_CACHE_UDELAY(map, chip, adr,
-                               adr, map_bankwidth(map),
-                               chip->word_write_time);
-
-       timeo = jiffies + (HZ/2);
-       z = 0;
-       for (;;) {
-               if (chip->state != mode) {
-                       /* Someone's suspended the write. Sleep */
-                       DECLARE_WAITQUEUE(wait, current);
-
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       add_wait_queue(&chip->wq, &wait);
-                       spin_unlock(chip->mutex);
-                       schedule();
-                       remove_wait_queue(&chip->wq, &wait);
-                       timeo = jiffies + (HZ / 2); /* FIXME */
-                       spin_lock(chip->mutex);
-                       continue;
-               }
-
-               status = map_read(map, adr);
-               if (map_word_andequal(map, status, status_OK, status_OK))
-                       break;
-
-               /* OK Still waiting */
-               if (time_after(jiffies, timeo)) {
-                       map_write(map, CMD(0x70), adr);
-                       chip->state = FL_STATUS;
-                       xip_enable(map, chip, adr);
-                       printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
-                       ret = -EIO;
-                       goto out;
-               }
-
-               /* Latency issues. Drop the lock, wait a while and retry */
-               z++;
-               UDELAY(map, chip, adr, 1);
-       }
-       if (!z) {
-               chip->word_write_time--;
-               if (!chip->word_write_time)
-                       chip->word_write_time = 1;
+       ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
+                                  adr, map_bankwidth(map),
+                                  &chip->word_write_time);
+       if (ret) {
+               xip_enable(map, chip, adr);
+               printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
+               goto out;
        }
-       if (z > 1)
-               chip->word_write_time++;
-
-       /* Done and happy. */
-       chip->state = FL_STATUS;
 
        /* check for errors */
+       status = map_read(map, adr);
        if (map_word_bitsset(map, status, CMD(0x1a))) {
                unsigned long chipstatus = MERGESTATUS(status);
 
@@ -1452,9 +1456,9 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
                                    unsigned long *pvec_seek, int len)
 {
        struct cfi_private *cfi = map->fldrv_priv;
-       map_word status, status_OK, write_cmd, datum;
-       unsigned long cmd_adr, timeo;
-       int wbufsize, z, ret=0, word_gap, words;
+       map_word status, write_cmd, datum;
+       unsigned long cmd_adr;
+       int ret, wbufsize, word_gap, words;
        const struct kvec *vec;
        unsigned long vec_seek;
 
@@ -1463,7 +1467,6 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
        cmd_adr = adr & ~(wbufsize-1);
 
        /* Let's determine this according to the interleave only once */
-       status_OK = CMD(0x80);
        write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9);
 
        spin_lock(chip->mutex);
@@ -1477,12 +1480,14 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
        ENABLE_VPP(map);
        xip_disable(map, chip, cmd_adr);
 
-       /* Â§4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set
+       /* Ã‚§4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set
           [...], the device will not accept any more Write to Buffer commands".
           So we must check here and reset those bits if they're set. Otherwise
           we're just pissing in the wind */
-       if (chip->state != FL_STATUS)
+       if (chip->state != FL_STATUS) {
                map_write(map, CMD(0x70), cmd_adr);
+               chip->state = FL_STATUS;
+       }
        status = map_read(map, cmd_adr);
        if (map_word_bitsset(map, status, CMD(0x30))) {
                xip_enable(map, chip, cmd_adr);
@@ -1493,32 +1498,20 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
        }
 
        chip->state = FL_WRITING_TO_BUFFER;
-
-       z = 0;
-       for (;;) {
-               map_write(map, write_cmd, cmd_adr);
-
+       map_write(map, write_cmd, cmd_adr);
+       ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0);
+       if (ret) {
+               /* Argh. Not ready for write to buffer */
+               map_word Xstatus = map_read(map, cmd_adr);
+               map_write(map, CMD(0x70), cmd_adr);
+               chip->state = FL_STATUS;
                status = map_read(map, cmd_adr);
-               if (map_word_andequal(map, status, status_OK, status_OK))
-                       break;
-
-               UDELAY(map, chip, cmd_adr, 1);
-
-               if (++z > 20) {
-                       /* Argh. Not ready for write to buffer */
-                       map_word Xstatus;
-                       map_write(map, CMD(0x70), cmd_adr);
-                       chip->state = FL_STATUS;
-                       Xstatus = map_read(map, cmd_adr);
-                       /* Odd. Clear status bits */
-                       map_write(map, CMD(0x50), cmd_adr);
-                       map_write(map, CMD(0x70), cmd_adr);
-                       xip_enable(map, chip, cmd_adr);
-                       printk(KERN_ERR "%s: Chip not ready for buffer write. status = %lx, Xstatus = %lx\n",
-                              map->name, status.x[0], Xstatus.x[0]);
-                       ret = -EIO;
-                       goto out;
-               }
+               map_write(map, CMD(0x50), cmd_adr);
+               map_write(map, CMD(0x70), cmd_adr);
+               xip_enable(map, chip, cmd_adr);
+               printk(KERN_ERR "%s: Chip not ready for buffer write. Xstatus = %lx, status = %lx\n",
+                               map->name, Xstatus.x[0], status.x[0]);
+               goto out;
        }
 
        /* Figure out the number of words to write */
@@ -1573,56 +1566,19 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
        map_write(map, CMD(0xd0), cmd_adr);
        chip->state = FL_WRITING;
 
-       INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr,
-                               adr, len,
-                               chip->buffer_write_time);
-
-       timeo = jiffies + (HZ/2);
-       z = 0;
-       for (;;) {
-               if (chip->state != FL_WRITING) {
-                       /* Someone's suspended the write. Sleep */
-                       DECLARE_WAITQUEUE(wait, current);
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       add_wait_queue(&chip->wq, &wait);
-                       spin_unlock(chip->mutex);
-                       schedule();
-                       remove_wait_queue(&chip->wq, &wait);
-                       timeo = jiffies + (HZ / 2); /* FIXME */
-                       spin_lock(chip->mutex);
-                       continue;
-               }
-
-               status = map_read(map, cmd_adr);
-               if (map_word_andequal(map, status, status_OK, status_OK))
-                       break;
-
-               /* OK Still waiting */
-               if (time_after(jiffies, timeo)) {
-                       map_write(map, CMD(0x70), cmd_adr);
-                       chip->state = FL_STATUS;
-                       xip_enable(map, chip, cmd_adr);
-                       printk(KERN_ERR "%s: buffer write error (status timeout)\n", map->name);
-                       ret = -EIO;
-                       goto out;
-               }
-
-               /* Latency issues. Drop the lock, wait a while and retry */
-               z++;
-               UDELAY(map, chip, cmd_adr, 1);
-       }
-       if (!z) {
-               chip->buffer_write_time--;
-               if (!chip->buffer_write_time)
-                       chip->buffer_write_time = 1;
+       ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
+                                  adr, len,
+                                  &chip->buffer_write_time);
+       if (ret) {
+               map_write(map, CMD(0x70), cmd_adr);
+               chip->state = FL_STATUS;
+               xip_enable(map, chip, cmd_adr);
+               printk(KERN_ERR "%s: buffer write error (status timeout)\n", map->name);
+               goto out;
        }
-       if (z > 1)
-               chip->buffer_write_time++;
-
-       /* Done and happy. */
-       chip->state = FL_STATUS;
 
        /* check for errors */
+       status = map_read(map, cmd_adr);
        if (map_word_bitsset(map, status, CMD(0x1a))) {
                unsigned long chipstatus = MERGESTATUS(status);
 
@@ -1693,6 +1649,11 @@ static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs,
                        if (chipnum == cfi->numchips)
                                return 0;
                }
+
+               /* Be nice and reschedule with the chip in a usable state for other
+                  processes. */
+               cond_resched();
+
        } while (len);
 
        return 0;
@@ -1713,17 +1674,12 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
                                      unsigned long adr, int len, void *thunk)
 {
        struct cfi_private *cfi = map->fldrv_priv;
-       map_word status, status_OK;
-       unsigned long timeo;
+       map_word status;
        int retries = 3;
-       DECLARE_WAITQUEUE(wait, current);
-       int ret = 0;
+       int ret;
 
        adr += chip->start;
 
-       /* Let's determine this according to the interleave only once */
-       status_OK = CMD(0x80);
-
  retry:
        spin_lock(chip->mutex);
        ret = get_chip(map, chip, adr, FL_ERASING);
@@ -1745,48 +1701,15 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
        chip->state = FL_ERASING;
        chip->erase_suspended = 0;
 
-       INVALIDATE_CACHE_UDELAY(map, chip, adr,
-                               adr, len,
-                               chip->erase_time*1000/2);
-
-       /* FIXME. Use a timer to check this, and return immediately. */
-       /* Once the state machine's known to be working I'll do that */
-
-       timeo = jiffies + (HZ*20);
-       for (;;) {
-               if (chip->state != FL_ERASING) {
-                       /* Someone's suspended the erase. Sleep */
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       add_wait_queue(&chip->wq, &wait);
-                       spin_unlock(chip->mutex);
-                       schedule();
-                       remove_wait_queue(&chip->wq, &wait);
-                       spin_lock(chip->mutex);
-                       continue;
-               }
-               if (chip->erase_suspended) {
-                       /* This erase was suspended and resumed.
-                          Adjust the timeout */
-                       timeo = jiffies + (HZ*20); /* FIXME */
-                       chip->erase_suspended = 0;
-               }
-
-               status = map_read(map, adr);
-               if (map_word_andequal(map, status, status_OK, status_OK))
-                       break;
-
-               /* OK Still waiting */
-               if (time_after(jiffies, timeo)) {
-                       map_write(map, CMD(0x70), adr);
-                       chip->state = FL_STATUS;
-                       xip_enable(map, chip, adr);
-                       printk(KERN_ERR "%s: block erase error: (status timeout)\n", map->name);
-                       ret = -EIO;
-                       goto out;
-               }
-
-               /* Latency issues. Drop the lock, wait a while and retry */
-               UDELAY(map, chip, adr, 1000000/HZ);
+       ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
+                                  adr, len,
+                                  &chip->erase_time);
+       if (ret) {
+               map_write(map, CMD(0x70), adr);
+               chip->state = FL_STATUS;
+               xip_enable(map, chip, adr);
+               printk(KERN_ERR "%s: block erase error: (status timeout)\n", map->name);
+               goto out;
        }
 
        /* We've broken this before. It doesn't hurt to be safe */
@@ -1815,7 +1738,6 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
                        ret = -EIO;
                } else if (chipstatus & 0x20 && retries--) {
                        printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus);
-                       timeo = jiffies + HZ;
                        put_chip(map, chip, adr);
                        spin_unlock(chip->mutex);
                        goto retry;
@@ -1921,15 +1843,11 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
 {
        struct cfi_private *cfi = map->fldrv_priv;
        struct cfi_pri_intelext *extp = cfi->cmdset_priv;
-       map_word status, status_OK;
-       unsigned long timeo = jiffies + HZ;
+       int udelay;
        int ret;
 
        adr += chip->start;
 
-       /* Let's determine this according to the interleave only once */
-       status_OK = CMD(0x80);
-
        spin_lock(chip->mutex);
        ret = get_chip(map, chip, adr, FL_LOCKING);
        if (ret) {
@@ -1954,41 +1872,21 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
         * If Instant Individual Block Locking supported then no need
         * to delay.
         */
+       udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0;
 
-       if (!extp || !(extp->FeatureSupport & (1 << 5)))
-               UDELAY(map, chip, adr, 1000000/HZ);
-
-       /* FIXME. Use a timer to check this, and return immediately. */
-       /* Once the state machine's known to be working I'll do that */
-
-       timeo = jiffies + (HZ*20);
-       for (;;) {
-
-               status = map_read(map, adr);
-               if (map_word_andequal(map, status, status_OK, status_OK))
-                       break;
-
-               /* OK Still waiting */
-               if (time_after(jiffies, timeo)) {
-                       map_write(map, CMD(0x70), adr);
-                       chip->state = FL_STATUS;
-                       xip_enable(map, chip, adr);
-                       printk(KERN_ERR "%s: block unlock error: (status timeout)\n", map->name);
-                       put_chip(map, chip, adr);
-                       spin_unlock(chip->mutex);
-                       return -EIO;
-               }
-
-               /* Latency issues. Drop the lock, wait a while and retry */
-               UDELAY(map, chip, adr, 1);
+       ret = WAIT_TIMEOUT(map, chip, adr, udelay);
+       if (ret) {
+               map_write(map, CMD(0x70), adr);
+               chip->state = FL_STATUS;
+               xip_enable(map, chip, adr);
+               printk(KERN_ERR "%s: block unlock error: (status timeout)\n", map->name);
+               goto out;
        }
 
-       /* Done and happy. */
-       chip->state = FL_STATUS;
        xip_enable(map, chip, adr);
-       put_chip(map, chip, adr);
+out:   put_chip(map, chip, adr);
        spin_unlock(chip->mutex);
-       return 0;
+       return ret;
 }
 
 static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
@@ -2445,28 +2343,8 @@ static void cfi_intelext_destroy(struct mtd_info *mtd)
        kfree(mtd->eraseregions);
 }
 
-static char im_name_0001[] = "cfi_cmdset_0001";
-static char im_name_0003[] = "cfi_cmdset_0003";
-static char im_name_0200[] = "cfi_cmdset_0200";
-
-static int __init cfi_intelext_init(void)
-{
-       inter_module_register(im_name_0001, THIS_MODULE, &cfi_cmdset_0001);
-       inter_module_register(im_name_0003, THIS_MODULE, &cfi_cmdset_0001);
-       inter_module_register(im_name_0200, THIS_MODULE, &cfi_cmdset_0001);
-       return 0;
-}
-
-static void __exit cfi_intelext_exit(void)
-{
-       inter_module_unregister(im_name_0001);
-       inter_module_unregister(im_name_0003);
-       inter_module_unregister(im_name_0200);
-}
-
-module_init(cfi_intelext_init);
-module_exit(cfi_intelext_exit);
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
 MODULE_DESCRIPTION("MTD chip driver for Intel/Sharp flash chips");
+MODULE_ALIAS("cfi_cmdset_0003");
+MODULE_ALIAS("cfi_cmdset_0200");
index aed10bd5c3c3869cb52732d764004753a30aa319..1e01ad38b26e91d0f17c60e74d6987c6833afba1 100644 (file)
@@ -236,6 +236,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
        mtd->resume  = cfi_amdstd_resume;
        mtd->flags   = MTD_CAP_NORFLASH;
        mtd->name    = map->name;
+       mtd->writesize = 1;
 
        if (cfi->cfi_mode==CFI_MODE_CFI){
                unsigned char bootloc;
@@ -326,7 +327,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
 
        return cfi_amdstd_setup(mtd);
 }
-
+EXPORT_SYMBOL_GPL(cfi_cmdset_0002);
 
 static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
 {
@@ -1758,25 +1759,6 @@ static void cfi_amdstd_destroy(struct mtd_info *mtd)
        kfree(mtd->eraseregions);
 }
 
-static char im_name[]="cfi_cmdset_0002";
-
-
-static int __init cfi_amdstd_init(void)
-{
-       inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002);
-       return 0;
-}
-
-
-static void __exit cfi_amdstd_exit(void)
-{
-       inter_module_unregister(im_name);
-}
-
-
-module_init(cfi_amdstd_init);
-module_exit(cfi_amdstd_exit);
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Crossnet Co. <info@crossnet.co.jp> et al.");
 MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips");
index 0807c1c91e5544695df9f4ca76df1e4c6d1c2d77..fae70a5db5409f65307a6f851edfaafda6bb039e 100644 (file)
@@ -162,6 +162,7 @@ struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary)
 
        return cfi_staa_setup(map);
 }
+EXPORT_SYMBOL_GPL(cfi_cmdset_0020);
 
 static struct mtd_info *cfi_staa_setup(struct map_info *map)
 {
@@ -237,9 +238,8 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
        mtd->unlock = cfi_staa_unlock;
        mtd->suspend = cfi_staa_suspend;
        mtd->resume = cfi_staa_resume;
-       mtd->flags = MTD_CAP_NORFLASH;
-       mtd->flags |= MTD_ECC; /* FIXME: Not all STMicro flashes have this */
-       mtd->eccsize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
+       mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE;
+       mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
        map->fldrv = &cfi_staa_chipdrv;
        __module_get(THIS_MODULE);
        mtd->name = map->name;
@@ -1410,20 +1410,4 @@ static void cfi_staa_destroy(struct mtd_info *mtd)
        kfree(cfi);
 }
 
-static char im_name[]="cfi_cmdset_0020";
-
-static int __init cfi_staa_init(void)
-{
-       inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0020);
-       return 0;
-}
-
-static void __exit cfi_staa_exit(void)
-{
-       inter_module_unregister(im_name);
-}
-
-module_init(cfi_staa_init);
-module_exit(cfi_staa_exit);
-
 MODULE_LICENSE("GPL");
index e636aa86bc24825dca9278511e5c38e82a00f4fb..4bf9f8cac0dd96746a6c1a9cca9afa4d8161449d 100644 (file)
@@ -349,12 +349,12 @@ static void print_cfi_ident(struct cfi_ident *cfip)
        else
                printk("No Vpp line\n");
 
-       printk("Typical byte/word write timeout: %d Âµs\n", 1<<cfip->WordWriteTimeoutTyp);
-       printk("Maximum byte/word write timeout: %d Âµs\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
+       printk("Typical byte/word write timeout: %d Ã‚µs\n", 1<<cfip->WordWriteTimeoutTyp);
+       printk("Maximum byte/word write timeout: %d Ã‚µs\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
 
        if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
-               printk("Typical full buffer write timeout: %d Âµs\n", 1<<cfip->BufWriteTimeoutTyp);
-               printk("Maximum full buffer write timeout: %d Âµs\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
+               printk("Typical full buffer write timeout: %d Ã‚µs\n", 1<<cfip->BufWriteTimeoutTyp);
+               printk("Maximum full buffer write timeout: %d Ã‚µs\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
        }
        else
                printk("Full buffer write not supported\n");
index 41bd59d20d85f38229e1b9056e9e87d4598474c2..cdb0f590b40c117ba246f23e2351528608476df2 100644 (file)
@@ -37,8 +37,15 @@ struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
        if (!mtd)
                mtd = check_cmd_set(map, 0); /* Then the secondary */
 
-       if (mtd)
+       if (mtd) {
+               if (mtd->size > map->size) {
+                       printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n",
+                              (unsigned long)mtd->size >> 10, 
+                              (unsigned long)map->size >> 10);
+                       mtd->size = map->size;
+               }
                return mtd;
+       }
 
        printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n");
 
@@ -100,7 +107,12 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
         * Align bitmap storage size to full byte.
         */
        max_chips = map->size >> cfi.chipshift;
-       mapsize = (max_chips / 8) + ((max_chips % 8) ? 1 : 0);
+       if (!max_chips) {
+               printk(KERN_WARNING "NOR chip too large to fit in mapping. Attempting to cope...\n");
+               max_chips = 1;
+       }
+
+       mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG;
        chip_map = kmalloc(mapsize, GFP_KERNEL);
        if (!chip_map) {
                printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
@@ -194,25 +206,28 @@ static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map,
 {
        struct cfi_private *cfi = map->fldrv_priv;
        __u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
-#if defined(CONFIG_MODULES) && defined(HAVE_INTER_MODULE)
-       char probename[32];
+#ifdef CONFIG_MODULES
+       char probename[16+sizeof(MODULE_SYMBOL_PREFIX)];
        cfi_cmdset_fn_t *probe_function;
 
-       sprintf(probename, "cfi_cmdset_%4.4X", type);
+       sprintf(probename, MODULE_SYMBOL_PREFIX "cfi_cmdset_%4.4X", type);
 
-       probe_function = inter_module_get_request(probename, probename);
+       probe_function = __symbol_get(probename);
+       if (!probe_function) {
+               request_module(probename + sizeof(MODULE_SYMBOL_PREFIX) - 1);
+               probe_function = __symbol_get(probename);
+       }
 
        if (probe_function) {
                struct mtd_info *mtd;
 
                mtd = (*probe_function)(map, primary);
                /* If it was happy, it'll have increased its own use count */
-               inter_module_put(probename);
+               symbol_put_addr(probe_function);
                return mtd;
        }
 #endif
-       printk(KERN_NOTICE "Support for command set %04X not present\n",
-              type);
+       printk(KERN_NOTICE "Support for command set %04X not present\n", type);
 
        return NULL;
 }
@@ -226,12 +241,8 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
                return NULL;
 
        switch(type){
-               /* Urgh. Ifdefs. The version with weak symbols was
-                * _much_ nicer. Shame it didn't seem to work on
-                * anything but x86, really.
-                * But we can't rely in inter_module_get() because
-                * that'd mean we depend on link order.
-                */
+               /* We need these for the !CONFIG_MODULES case,
+                  because symbol_get() doesn't work there */
 #ifdef CONFIG_MTD_CFI_INTELEXT
        case 0x0001:
        case 0x0003:
@@ -246,9 +257,9 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
         case 0x0020:
                return cfi_cmdset_0020(map, primary);
 #endif
+       default:
+               return cfi_cmdset_unknown(map, primary);
        }
-
-       return cfi_cmdset_unknown(map, primary);
 }
 
 MODULE_LICENSE("GPL");
index bd2e876a814bfc6374660379b83503c64be2841e..763925747db6f60a6701aad1b68e2fdecb801457 100644 (file)
@@ -70,7 +70,7 @@ static struct mtd_info *map_ram_probe(struct map_info *map)
        mtd->read = mapram_read;
        mtd->write = mapram_write;
        mtd->sync = mapram_nop;
-       mtd->flags = MTD_CAP_RAM | MTD_VOLATILE;
+       mtd->flags = MTD_CAP_RAM;
 
        mtd->erasesize = PAGE_SIZE;
        while(mtd->size & (mtd->erasesize - 1))
index 624c12c232c8b2989319fadc66236ec9026e81a3..bc6ee9ef8a31ac8d6a44ef054d9d0a33d9dc9a23 100644 (file)
@@ -46,9 +46,7 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
        mtd->write = maprom_write;
        mtd->sync = maprom_nop;
        mtd->flags = MTD_CAP_ROM;
-       mtd->erasesize = 131072;
-       while(mtd->size & (mtd->erasesize - 1))
-               mtd->erasesize >>= 1;
+       mtd->erasesize = map->size;
 
        __module_get(THIS_MODULE);
        return mtd;
index 3cc0b23c5865cd3cd3fb1ffe5ad4496e7b5aeb59..967abbecdff9bb450aab9852e28c5ee84d39dcc7 100644 (file)
@@ -140,6 +140,7 @@ static struct mtd_info *sharp_probe(struct map_info *map)
        mtd->suspend = sharp_suspend;
        mtd->resume = sharp_resume;
        mtd->flags = MTD_CAP_NORFLASH;
+       mtd->writesize = 1;
        mtd->name = map->name;
 
        memset(sharp, 0, sizeof(*sharp));
index 7fac438b5c32cbc376a9dc4945247a767a42fc55..16c02b5ccf7ec30c994a7fb5a938e4fcb2d8278b 100644 (file)
@@ -47,6 +47,11 @@ config MTD_MS02NV
          accelerator.  Say Y here if you have a DECstation 5000/2x0 or a
          DECsystem 5900 equipped with such a module.
 
+         If you want to compile this driver as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want),
+         say M here and read <file:Documentation/modules.txt>.  The module will
+         be called ms02-nv.o.
+
 config MTD_DATAFLASH
        tristate "Support for AT45xxx DataFlash"
        depends on MTD && SPI_MASTER && EXPERIMENTAL
@@ -209,7 +214,6 @@ config MTD_DOC2001PLUS
 config MTD_DOCPROBE
        tristate
        select MTD_DOCECC
-       select OBSOLETE_INTERMODULE
 
 config MTD_DOCECC
        tristate
index b6573670316f198e02b3df9d0eafc12fc5e96d48..0f788d5c4bf8307b9b609891338bc4469b755534 100644 (file)
@@ -3,13 +3,6 @@
 #
 # $Id: Makefile.common,v 1.7 2004/12/22 17:51:15 joern Exp $
 
-#                       *** BIG UGLY NOTE ***
-#
-# The removal of get_module_symbol() and replacement with
-# inter_module_register() et al has introduced a link order dependency
-# here where previously there was none.  We now have to ensure that
-# doc200[01].o are linked before docprobe.o
-
 obj-$(CONFIG_MTD_DOC2000)      += doc2000.o
 obj-$(CONFIG_MTD_DOC2001)      += doc2001.o
 obj-$(CONFIG_MTD_DOC2001PLUS)  += doc2001plus.o
index 4160b8334c53e0881cdc12c1f7d3d54fff883772..0d98c223c5fc2e188d1f1e58ad0ea53ca0d1a506 100644 (file)
@@ -4,7 +4,7 @@
  * block2mtd.c - create an mtd from a block device
  *
  * Copyright (C) 2001,2002     Simon Evans <spse@secret.org.uk>
- * Copyright (C) 2004,2005     Jörn Engel <joern@wh.fh-wedel.de>
+ * Copyright (C) 2004-2006     Jörn Engel <joern@wh.fh-wedel.de>
  *
  * Licence: GPL
  */
@@ -331,7 +331,6 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
        dev->mtd.writev = default_mtd_writev;
        dev->mtd.sync = block2mtd_sync;
        dev->mtd.read = block2mtd_read;
-       dev->mtd.readv = default_mtd_readv;
        dev->mtd.priv = dev;
        dev->mtd.owner = THIS_MODULE;
 
@@ -351,6 +350,12 @@ devinit_err:
 }
 
 
+/* This function works similar to reguler strtoul.  In addition, it
+ * allows some suffixes for a more human-readable number format:
+ * ki, Ki, kiB, KiB    - multiply result with 1024
+ * Mi, MiB             - multiply result with 1024^2
+ * Gi, GiB             - multiply result with 1024^3
+ */
 static int ustrtoul(const char *cp, char **endp, unsigned int base)
 {
        unsigned long result = simple_strtoul(cp, endp, base);
@@ -359,11 +364,16 @@ static int ustrtoul(const char *cp, char **endp, unsigned int base)
                result *= 1024;
        case 'M':
                result *= 1024;
+       case 'K':
        case 'k':
                result *= 1024;
        /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
-               if ((*endp)[1] == 'i')
-                       (*endp) += 2;
+               if ((*endp)[1] == 'i') {
+                       if ((*endp)[2] == 'B')
+                               (*endp) += 3;
+                       else
+                               (*endp) += 2;
+               }
        }
        return result;
 }
@@ -418,7 +428,8 @@ static inline void kill_final_newline(char *str)
 
 static int block2mtd_setup(const char *val, struct kernel_param *kp)
 {
-       char buf[80+12], *str=buf; /* 80 for device, 12 for erase size */
+       char buf[80+12]; /* 80 for device, 12 for erase size */
+       char *str = buf;
        char *token[2];
        char *name;
        size_t erase_size = PAGE_SIZE;
@@ -430,7 +441,7 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp)
        strcpy(str, val);
        kill_final_newline(str);
 
-       for (i=0; i<2; i++)
+       for (i = 0; i < 2; i++)
                token[i] = strsep(&str, ",");
 
        if (str)
@@ -449,8 +460,10 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp)
 
        if (token[1]) {
                ret = parse_num(&erase_size, token[1]);
-               if (ret)
+               if (ret) {
+                       kfree(name);
                        parse_err("illegal erase size");
+               }
        }
 
        add_device(name, erase_size);
index 23e7a5c7d2c13d98524b69f54378d887e1962fc8..c54e40464d8283eb3a0de099e0ef27a481faeed2 100644 (file)
@@ -59,13 +59,10 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
                        size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
 static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
                         size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
-static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
-                         unsigned long count, loff_t to, size_t *retlen,
-                         u_char *eccbuf, struct nand_oobinfo *oobsel);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-                       size_t *retlen, u_char *buf);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-                        size_t *retlen, const u_char *buf);
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+                       struct mtd_oob_ops *ops);
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+                        struct mtd_oob_ops *ops);
 static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len,
                         size_t *retlen, const u_char *buf);
 static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
@@ -517,16 +514,9 @@ static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
        return retval;
 }
 
-static const char im_name[] = "DoC2k_init";
-
-/* This routine is made available to other mtd code via
- * inter_module_register.  It must only be accessed through
- * inter_module_get which will bump the use count of this module.  The
- * addresses passed back in mtd are valid as long as the use count of
- * this module is non-zero, i.e. between inter_module_get and
- * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
- */
-static void DoC2k_init(struct mtd_info *mtd)
+/* This routine is found from the docprobe code by symbol_get(),
+ * which will bump the use count of this module. */
+void DoC2k_init(struct mtd_info *mtd)
 {
        struct DiskOnChip *this = mtd->priv;
        struct DiskOnChip *old = NULL;
@@ -586,7 +576,7 @@ static void DoC2k_init(struct mtd_info *mtd)
        mtd->ecctype = MTD_ECC_RS_DiskOnChip;
        mtd->size = 0;
        mtd->erasesize = 0;
-       mtd->oobblock = 512;
+       mtd->writesize = 512;
        mtd->oobsize = 16;
        mtd->owner = THIS_MODULE;
        mtd->erase = doc_erase;
@@ -594,9 +584,6 @@ static void DoC2k_init(struct mtd_info *mtd)
        mtd->unpoint = NULL;
        mtd->read = doc_read;
        mtd->write = doc_write;
-       mtd->read_ecc = doc_read_ecc;
-       mtd->write_ecc = doc_write_ecc;
-       mtd->writev_ecc = doc_writev_ecc;
        mtd->read_oob = doc_read_oob;
        mtd->write_oob = doc_write_oob;
        mtd->sync = NULL;
@@ -623,6 +610,7 @@ static void DoC2k_init(struct mtd_info *mtd)
                return;
        }
 }
+EXPORT_SYMBOL_GPL(DoC2k_init);
 
 static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
                    size_t * retlen, u_char * buf)
@@ -971,72 +959,18 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
        return 0;
 }
 
-static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
-                         unsigned long count, loff_t to, size_t *retlen,
-                         u_char *eccbuf, struct nand_oobinfo *oobsel)
-{
-       static char static_buf[512];
-       static DEFINE_MUTEX(writev_buf_mutex);
-
-       size_t totretlen = 0;
-       size_t thisvecofs = 0;
-       int ret= 0;
-
-       mutex_lock(&writev_buf_mutex);
-
-       while(count) {
-               size_t thislen, thisretlen;
-               unsigned char *buf;
-
-               buf = vecs->iov_base + thisvecofs;
-               thislen = vecs->iov_len - thisvecofs;
-
-
-               if (thislen >= 512) {
-                       thislen = thislen & ~(512-1);
-                       thisvecofs += thislen;
-               } else {
-                       /* Not enough to fill a page. Copy into buf */
-                       memcpy(static_buf, buf, thislen);
-                       buf = &static_buf[thislen];
-
-                       while(count && thislen < 512) {
-                               vecs++;
-                               count--;
-                               thisvecofs = min((512-thislen), vecs->iov_len);
-                               memcpy(buf, vecs->iov_base, thisvecofs);
-                               thislen += thisvecofs;
-                               buf += thisvecofs;
-                       }
-                       buf = static_buf;
-               }
-               if (count && thisvecofs == vecs->iov_len) {
-                       thisvecofs = 0;
-                       vecs++;
-                       count--;
-               }
-               ret = doc_write_ecc(mtd, to, thislen, &thisretlen, buf, eccbuf, oobsel);
-
-               totretlen += thisretlen;
-
-               if (ret || thisretlen != thislen)
-                       break;
-
-               to += thislen;
-       }
-
-       mutex_unlock(&writev_buf_mutex);
-       *retlen = totretlen;
-       return ret;
-}
-
-
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-                       size_t * retlen, u_char * buf)
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+                       struct mtd_oob_ops *ops)
 {
        struct DiskOnChip *this = mtd->priv;
        int len256 = 0, ret;
        struct Nand *mychip;
+       uint8_t *buf = ops->oobbuf;
+       size_t len = ops->len;
+
+       BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+       ofs += ops->ooboffs;
 
        mutex_lock(&this->lock);
 
@@ -1077,7 +1011,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
 
        DoC_ReadBuf(this, &buf[len256], len - len256);
 
-       *retlen = len;
+       ops->retlen = len;
        /* Reading the full OOB data drops us off of the end of the page,
          * causing the flash device to go into busy mode, so we need
          * to wait until ready 11.4.1 and Toshiba TC58256FT docs */
@@ -1192,17 +1126,20 @@ static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len,
 
 }
 
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-                        size_t * retlen, const u_char * buf)
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+                        struct mtd_oob_ops *ops)
 {
-       struct DiskOnChip *this = mtd->priv;
-       int ret;
+       struct DiskOnChip *this = mtd->priv;
+       int ret;
 
-       mutex_lock(&this->lock);
-       ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf);
+       BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+       mutex_lock(&this->lock);
+       ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len,
+                                  &ops->retlen, ops->oobbuf);
 
-       mutex_unlock(&this->lock);
-       return ret;
+       mutex_unlock(&this->lock);
+       return ret;
 }
 
 static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
@@ -1277,12 +1214,6 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
  *
  ****************************************************************************/
 
-static int __init init_doc2000(void)
-{
-       inter_module_register(im_name, THIS_MODULE, &DoC2k_init);
-       return 0;
-}
-
 static void __exit cleanup_doc2000(void)
 {
        struct mtd_info *mtd;
@@ -1298,11 +1229,9 @@ static void __exit cleanup_doc2000(void)
                kfree(this->chips);
                kfree(mtd);
        }
-       inter_module_unregister(im_name);
 }
 
 module_exit(cleanup_doc2000);
-module_init(init_doc2000);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
index 681a9c73a2a321850404d4856f4738be47e17d15..0cf022a69e653433e9a5f941fd739fd4a712a13e 100644 (file)
@@ -43,10 +43,10 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
 static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
                         size_t *retlen, const u_char *buf, u_char *eccbuf,
                         struct nand_oobinfo *oobsel);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-                       size_t *retlen, u_char *buf);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-                        size_t *retlen, const u_char *buf);
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+                       struct mtd_oob_ops *ops);
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+                        struct mtd_oob_ops *ops);
 static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
 
 static struct mtd_info *docmillist = NULL;
@@ -324,16 +324,9 @@ static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
        return retval;
 }
 
-static const char im_name[] = "DoCMil_init";
-
-/* This routine is made available to other mtd code via
- * inter_module_register.  It must only be accessed through
- * inter_module_get which will bump the use count of this module.  The
- * addresses passed back in mtd are valid as long as the use count of
- * this module is non-zero, i.e. between inter_module_get and
- * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
- */
-static void DoCMil_init(struct mtd_info *mtd)
+/* This routine is found from the docprobe code by symbol_get(),
+ * which will bump the use count of this module. */
+void DoCMil_init(struct mtd_info *mtd)
 {
        struct DiskOnChip *this = mtd->priv;
        struct DiskOnChip *old = NULL;
@@ -368,7 +361,7 @@ static void DoCMil_init(struct mtd_info *mtd)
        /* FIXME: erase size is not always 8KiB */
        mtd->erasesize = 0x2000;
 
-       mtd->oobblock = 512;
+       mtd->writesize = 512;
        mtd->oobsize = 16;
        mtd->owner = THIS_MODULE;
        mtd->erase = doc_erase;
@@ -376,8 +369,6 @@ static void DoCMil_init(struct mtd_info *mtd)
        mtd->unpoint = NULL;
        mtd->read = doc_read;
        mtd->write = doc_write;
-       mtd->read_ecc = doc_read_ecc;
-       mtd->write_ecc = doc_write_ecc;
        mtd->read_oob = doc_read_oob;
        mtd->write_oob = doc_write_oob;
        mtd->sync = NULL;
@@ -401,6 +392,7 @@ static void DoCMil_init(struct mtd_info *mtd)
                return;
        }
 }
+EXPORT_SYMBOL_GPL(DoCMil_init);
 
 static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
                     size_t *retlen, u_char *buf)
@@ -670,8 +662,8 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
        return ret;
 }
 
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-                       size_t *retlen, u_char *buf)
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+                       struct mtd_oob_ops *ops)
 {
 #ifndef USE_MEMCPY
        int i;
@@ -680,6 +672,12 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
        struct DiskOnChip *this = mtd->priv;
        void __iomem *docptr = this->virtadr;
        struct Nand *mychip = &this->chips[ofs >> this->chipshift];
+       uint8_t *buf = ops->oobbuf;
+       size_t len = ops->len;
+
+       BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+       ofs += ops->ooboffs;
 
        /* Find the chip which is to be used and select it */
        if (this->curfloor != mychip->floor) {
@@ -716,13 +714,13 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
 #endif
        buf[len - 1] = ReadDOC(docptr, LastDataRead);
 
-       *retlen = len;
+       ops->retlen = len;
 
        return 0;
 }
 
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-                        size_t *retlen, const u_char *buf)
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+                        struct mtd_oob_ops *ops)
 {
 #ifndef USE_MEMCPY
        int i;
@@ -732,6 +730,12 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
        struct DiskOnChip *this = mtd->priv;
        void __iomem *docptr = this->virtadr;
        struct Nand *mychip = &this->chips[ofs >> this->chipshift];
+       uint8_t *buf = ops->oobbuf;
+       size_t len = ops->len;
+
+       BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+       ofs += ops->ooboffs;
 
        /* Find the chip which is to be used and select it */
        if (this->curfloor != mychip->floor) {
@@ -783,12 +787,12 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
        if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
                printk("Error programming oob data\n");
                /* FIXME: implement Bad Block Replacement (in nftl.c ??) */
-               *retlen = 0;
+               ops->retlen = 0;
                ret = -EIO;
        }
        dummy = ReadDOC(docptr, LastDataRead);
 
-       *retlen = len;
+       ops->retlen = len;
 
        return ret;
 }
@@ -856,12 +860,6 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
  *
  ****************************************************************************/
 
-static int __init init_doc2001(void)
-{
-       inter_module_register(im_name, THIS_MODULE, &DoCMil_init);
-       return 0;
-}
-
 static void __exit cleanup_doc2001(void)
 {
        struct mtd_info *mtd;
@@ -877,11 +875,9 @@ static void __exit cleanup_doc2001(void)
                kfree(this->chips);
                kfree(mtd);
        }
-       inter_module_unregister(im_name);
 }
 
 module_exit(cleanup_doc2001);
-module_init(init_doc2001);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
index 5f57f29efee48d84e235a8ff75a35e7e354227a7..66cb1e50469a1df22f0c409f90a2786ebe3e929c 100644 (file)
@@ -47,10 +47,10 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
 static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
                size_t *retlen, const u_char *buf, u_char *eccbuf,
                struct nand_oobinfo *oobsel);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-               size_t *retlen, u_char *buf);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-               size_t *retlen, const u_char *buf);
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+                       struct mtd_oob_ops *ops);
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+                        struct mtd_oob_ops *ops);
 static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
 
 static struct mtd_info *docmilpluslist = NULL;
@@ -447,16 +447,9 @@ static int DoCMilPlus_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
        return retval;
 }
 
-static const char im_name[] = "DoCMilPlus_init";
-
-/* This routine is made available to other mtd code via
- * inter_module_register.  It must only be accessed through
- * inter_module_get which will bump the use count of this module.  The
- * addresses passed back in mtd are valid as long as the use count of
- * this module is non-zero, i.e. between inter_module_get and
- * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
- */
-static void DoCMilPlus_init(struct mtd_info *mtd)
+/* This routine is found from the docprobe code by symbol_get(),
+ * which will bump the use count of this module. */
+void DoCMilPlus_init(struct mtd_info *mtd)
 {
        struct DiskOnChip *this = mtd->priv;
        struct DiskOnChip *old = NULL;
@@ -490,7 +483,7 @@ static void DoCMilPlus_init(struct mtd_info *mtd)
        mtd->size = 0;
 
        mtd->erasesize = 0;
-       mtd->oobblock = 512;
+       mtd->writesize = 512;
        mtd->oobsize = 16;
        mtd->owner = THIS_MODULE;
        mtd->erase = doc_erase;
@@ -498,8 +491,6 @@ static void DoCMilPlus_init(struct mtd_info *mtd)
        mtd->unpoint = NULL;
        mtd->read = doc_read;
        mtd->write = doc_write;
-       mtd->read_ecc = doc_read_ecc;
-       mtd->write_ecc = doc_write_ecc;
        mtd->read_oob = doc_read_oob;
        mtd->write_oob = doc_write_oob;
        mtd->sync = NULL;
@@ -524,6 +515,7 @@ static void DoCMilPlus_init(struct mtd_info *mtd)
                return;
        }
 }
+EXPORT_SYMBOL_GPL(DoCMilPlus_init);
 
 #if 0
 static int doc_dumpblk(struct mtd_info *mtd, loff_t from)
@@ -876,14 +868,20 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
        return ret;
 }
 
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-                       size_t *retlen, u_char *buf)
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+                       struct mtd_oob_ops *ops)
 {
        loff_t fofs, base;
        struct DiskOnChip *this = mtd->priv;
        void __iomem * docptr = this->virtadr;
        struct Nand *mychip = &this->chips[ofs >> this->chipshift];
        size_t i, size, got, want;
+       uint8_t *buf = ops->oobbuf;
+       size_t len = ops->len;
+
+       BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+       ofs += ops->ooboffs;
 
        DoC_CheckASIC(docptr);
 
@@ -949,12 +947,12 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
        /* Disable flash internally */
        WriteDOC(0, docptr, Mplus_FlashSelect);
 
-       *retlen = len;
+       ops->retlen = len;
        return 0;
 }
 
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-                        size_t *retlen, const u_char *buf)
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+                        struct mtd_oob_ops *ops)
 {
        volatile char dummy;
        loff_t fofs, base;
@@ -963,6 +961,12 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
        struct Nand *mychip = &this->chips[ofs >> this->chipshift];
        size_t i, size, got, want;
        int ret = 0;
+       uint8_t *buf = ops->oobbuf;
+       size_t len = ops->len;
+
+       BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+       ofs += ops->ooboffs;
 
        DoC_CheckASIC(docptr);
 
@@ -1038,7 +1042,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
                        printk("MTD: Error 0x%x programming oob at 0x%x\n",
                                dummy, (int)ofs);
                        /* FIXME: implement Bad Block Replacement */
-                       *retlen = 0;
+                       ops->retlen = 0;
                        ret = -EIO;
                }
                dummy = ReadDOC(docptr, Mplus_LastDataRead);
@@ -1051,7 +1055,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
        /* Disable flash internally */
        WriteDOC(0, docptr, Mplus_FlashSelect);
 
-       *retlen = len;
+       ops->retlen = len;
        return ret;
 }
 
@@ -1122,12 +1126,6 @@ int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
  *
  ****************************************************************************/
 
-static int __init init_doc2001plus(void)
-{
-       inter_module_register(im_name, THIS_MODULE, &DoCMilPlus_init);
-       return 0;
-}
-
 static void __exit cleanup_doc2001plus(void)
 {
        struct mtd_info *mtd;
@@ -1143,11 +1141,9 @@ static void __exit cleanup_doc2001plus(void)
                kfree(this->chips);
                kfree(mtd);
        }
-       inter_module_unregister(im_name);
 }
 
 module_exit(cleanup_doc2001plus);
-module_init(init_doc2001plus);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com> et al.");
index 13178b9dd00aa1db3a72a3a9a87100efff547029..593bb033a3fafac6b40cc5b5369b7299264900ae 100644 (file)
@@ -231,6 +231,10 @@ static inline int __init doccheck(void __iomem *potential, unsigned long physadr
 
 static int docfound;
 
+extern void DoC2k_init(struct mtd_info *);
+extern void DoCMil_init(struct mtd_info *);
+extern void DoCMilPlus_init(struct mtd_info *);
+
 static void __init DoC_Probe(unsigned long physadr)
 {
        void __iomem *docptr;
@@ -239,8 +243,6 @@ static void __init DoC_Probe(unsigned long physadr)
        int ChipID;
        char namebuf[15];
        char *name = namebuf;
-       char *im_funcname = NULL;
-       char *im_modname = NULL;
        void (*initroutine)(struct mtd_info *) = NULL;
 
        docptr = ioremap(physadr, DOC_IOREMAP_LEN);
@@ -278,41 +280,33 @@ static void __init DoC_Probe(unsigned long physadr)
                switch(ChipID) {
                case DOC_ChipID_Doc2kTSOP:
                        name="2000 TSOP";
-                       im_funcname = "DoC2k_init";
-                       im_modname = "doc2000";
+                       initroutine = symbol_request(DoC2k_init);
                        break;
 
                case DOC_ChipID_Doc2k:
                        name="2000";
-                       im_funcname = "DoC2k_init";
-                       im_modname = "doc2000";
+                       initroutine = symbol_request(DoC2k_init);
                        break;
 
                case DOC_ChipID_DocMil:
                        name="Millennium";
 #ifdef DOC_SINGLE_DRIVER
-                       im_funcname = "DoC2k_init";
-                       im_modname = "doc2000";
+                       initroutine = symbol_request(DoC2k_init);
 #else
-                       im_funcname = "DoCMil_init";
-                       im_modname = "doc2001";
+                       initroutine = symbol_request(DoCMil_init);
 #endif /* DOC_SINGLE_DRIVER */
                        break;
 
                case DOC_ChipID_DocMilPlus16:
                case DOC_ChipID_DocMilPlus32:
                        name="MillenniumPlus";
-                       im_funcname = "DoCMilPlus_init";
-                       im_modname = "doc2001plus";
+                       initroutine = symbol_request(DoCMilPlus_init);
                        break;
                }
 
-               if (im_funcname)
-                       initroutine = inter_module_get_request(im_funcname, im_modname);
-
                if (initroutine) {
                        (*initroutine)(mtd);
-                       inter_module_put(im_funcname);
+                       symbol_put_addr(initroutine);
                        return;
                }
                printk(KERN_NOTICE "Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr);
index 29b0ddaa324e417abf153460d7d94fb67823a6ef..4ea50a1dda8570a1606abbbd623c93f011df2bb7 100644 (file)
@@ -635,6 +635,7 @@ int __init lart_flash_init (void)
    printk ("%s: This looks like a LART board to me.\n",module_name);
    mtd.name = module_name;
    mtd.type = MTD_NORFLASH;
+   mtd.writesize = 1;
    mtd.flags = MTD_CAP_NORFLASH;
    mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
    mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
index 04e65d5dae000f9b3d4f0c94c114da26169d2548..a8466141e914d3f5f94c0adec075b4a4f0099cef 100644 (file)
@@ -465,6 +465,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
                flash->mtd.name = spi->dev.bus_id;
 
        flash->mtd.type = MTD_NORFLASH;
+       flash->mtd.writesize = 1;
        flash->mtd.flags = MTD_CAP_NORFLASH;
        flash->mtd.size = info->sector_size * info->n_sectors;
        flash->mtd.erasesize = info->sector_size;
index 485f663493d295fc7e796507af7c774ddfba503c..4ab7670770e43ff1cc9a0d855b872e1c22656f1e 100644 (file)
@@ -219,7 +219,7 @@ static int __init ms02nv_init_one(ulong addr)
        mp->uaddr = phys_to_virt(fixaddr);
 
        mtd->type = MTD_RAM;
-       mtd->flags = MTD_CAP_RAM | MTD_XIP;
+       mtd->flags = MTD_CAP_RAM;
        mtd->size = fixsize;
        mtd->name = (char *)ms02nv_name;
        mtd->owner = THIS_MODULE;
index 1443117fd8f4afb988becd36beb1d14a084c5646..b4438eacfd80d47c7dfc7e59146f9b806e8ae6e6 100644 (file)
@@ -106,6 +106,7 @@ int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
        mtd->type = MTD_RAM;
        mtd->flags = MTD_CAP_RAM;
        mtd->size = size;
+       mtd->writesize = 1;
        mtd->erasesize = MTDRAM_ERASE_SIZE;
        mtd->priv = mapped_address;
 
index e8685ee6c1e425f202b8ca2b91ea6de05dc8c8ae..e09e416667d38daea36e24b8034daa86597adb79 100644 (file)
@@ -1,8 +1,8 @@
 /**
  * $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $
  *
- * Copyright (c) ????          Jochen Schäuble <psionic@psionic.de>
- * Copyright (c) 2003-2004     Jörn Engel <joern@wh.fh-wedel.de>
+ * Copyright (c) ????          Jochen Schäuble <psionic@psionic.de>
+ * Copyright (c) 2003-2004     Jörn Engel <joern@wh.fh-wedel.de>
  *
  * Usage:
  *
@@ -142,7 +142,7 @@ static int register_device(char *name, unsigned long start, unsigned long len)
 
        new->mtd.name = name;
        new->mtd.size = len;
-       new->mtd.flags = MTD_CAP_RAM | MTD_ERASEABLE | MTD_VOLATILE;
+       new->mtd.flags = MTD_CAP_RAM;
         new->mtd.erase = phram_erase;
        new->mtd.point = phram_point;
        new->mtd.unpoint = phram_unpoint;
@@ -266,12 +266,16 @@ static int phram_setup(const char *val, struct kernel_param *kp)
                return 0;
 
        ret = parse_num32(&start, token[1]);
-       if (ret)
+       if (ret) {
+               kfree(name);
                parse_err("illegal start address\n");
+       }
 
        ret = parse_num32(&len, token[2]);
-       if (ret)
+       if (ret) {
+               kfree(name);
                parse_err("illegal device length\n");
+       }
 
        register_device(name, start, len);
 
@@ -296,5 +300,5 @@ module_init(init_phram);
 module_exit(cleanup_phram);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jörn Engel <joern@wh.fh-wedel.de>");
+MODULE_AUTHOR("Jörn Engel <joern@wh.fh-wedel.de>");
 MODULE_DESCRIPTION("MTD driver for physical RAM");
index 6faee6c6958c2a7bc709b53df6cf61ff6c507369..b3f665e3c38bfeec5fade51e3c4fb77ee61bc7b4 100644 (file)
@@ -200,8 +200,7 @@ static int register_device(char *name, unsigned long start, unsigned long length
 
        (*curmtd)->mtdinfo->name = name;
        (*curmtd)->mtdinfo->size = length;
-       (*curmtd)->mtdinfo->flags = MTD_CLEAR_BITS | MTD_SET_BITS |
-                                       MTD_WRITEB_WRITEABLE | MTD_VOLATILE | MTD_CAP_RAM;
+       (*curmtd)->mtdinfo->flags = MTD_CAP_RAM;
         (*curmtd)->mtdinfo->erase = slram_erase;
        (*curmtd)->mtdinfo->point = slram_point;
        (*curmtd)->mtdinfo->unpoint = slram_unpoint;
index a3b92479719db14e52d1d716952403ac9d218aa0..1e21a2c3dd29eba442cd621deed1cf8f57788a8a 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nftl.h>
 #include <linux/mtd/inftl.h>
+#include <linux/mtd/nand.h>
 #include <asm/uaccess.h>
 #include <asm/errno.h>
 #include <asm/io.h>
@@ -79,14 +80,12 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
        inftl->mbd.devnum = -1;
        inftl->mbd.blksize = 512;
        inftl->mbd.tr = tr;
-       memcpy(&inftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
-       inftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
 
-        if (INFTL_mount(inftl) < 0) {
+       if (INFTL_mount(inftl) < 0) {
                printk(KERN_WARNING "INFTL: could not mount device\n");
                kfree(inftl);
                return;
-        }
+       }
 
        /* OK, it's a new one. Set up all the data structures. */
 
@@ -151,6 +150,69 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev)
  * Actual INFTL access routines.
  */
 
+/*
+ * Read oob data from flash
+ */
+int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                  size_t *retlen, uint8_t *buf)
+{
+       struct mtd_oob_ops ops;
+       int res;
+
+       ops.mode = MTD_OOB_PLACE;
+       ops.ooboffs = offs & (mtd->writesize - 1);
+       ops.ooblen = len;
+       ops.oobbuf = buf;
+       ops.datbuf = NULL;
+       ops.len = len;
+
+       res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+       *retlen = ops.retlen;
+       return res;
+}
+
+/*
+ * Write oob data to flash
+ */
+int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                   size_t *retlen, uint8_t *buf)
+{
+       struct mtd_oob_ops ops;
+       int res;
+
+       ops.mode = MTD_OOB_PLACE;
+       ops.ooboffs = offs & (mtd->writesize - 1);
+       ops.ooblen = len;
+       ops.oobbuf = buf;
+       ops.datbuf = NULL;
+       ops.len = len;
+
+       res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+       *retlen = ops.retlen;
+       return res;
+}
+
+/*
+ * Write data and oob to flash
+ */
+static int inftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
+                      size_t *retlen, uint8_t *buf, uint8_t *oob)
+{
+       struct mtd_oob_ops ops;
+       int res;
+
+       ops.mode = MTD_OOB_PLACE;
+       ops.ooboffs = offs;
+       ops.ooblen = mtd->oobsize;
+       ops.oobbuf = oob;
+       ops.datbuf = buf;
+       ops.len = len;
+
+       res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+       *retlen = ops.retlen;
+       return res;
+}
+
 /*
  * INFTL_findfreeblock: Find a free Erase Unit on the INFTL partition.
  *     This function is used when the give Virtual Unit Chain.
@@ -198,10 +260,11 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
        u16 BlockMap[MAX_SECTORS_PER_UNIT];
        unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT];
        unsigned int thisEUN, prevEUN, status;
+       struct mtd_info *mtd = inftl->mbd.mtd;
        int block, silly;
        unsigned int targetEUN;
        struct inftl_oob oob;
-        size_t retlen;
+       size_t retlen;
 
        DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,"
                "pending=%d)\n", inftl, thisVUC, pendingblock);
@@ -221,18 +284,18 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
         * Scan to find the Erase Unit which holds the actual data for each
         * 512-byte block within the Chain.
         */
-        silly = MAX_LOOPS;
+       silly = MAX_LOOPS;
        while (thisEUN < inftl->nb_blocks) {
                for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) {
                        if ((BlockMap[block] != 0xffff) || BlockDeleted[block])
                                continue;
 
-                       if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize)
-                            + (block * SECTORSIZE), 16 , &retlen,
-                            (char *)&oob) < 0)
+                       if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize)
+                                          + (block * SECTORSIZE), 16, &retlen,
+                                          (char *)&oob) < 0)
                                status = SECTOR_IGNORE;
                        else
-                               status = oob.b.Status | oob.b.Status1;
+                               status = oob.b.Status | oob.b.Status1;
 
                        switch(status) {
                        case SECTOR_FREE:
@@ -282,29 +345,31 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
                        continue;
                }
 
-                /*
+               /*
                 * Copy only in non free block (free blocks can only
                  * happen in case of media errors or deleted blocks).
                 */
-                if (BlockMap[block] == BLOCK_NIL)
-                        continue;
-
-                ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
-                       BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE,
-                       &retlen, movebuf);
-                if (ret < 0) {
-                       ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
-                               BlockMap[block]) + (block * SECTORSIZE),
-                               SECTORSIZE, &retlen, movebuf);
+               if (BlockMap[block] == BLOCK_NIL)
+                       continue;
+
+               ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) +
+                               (block * SECTORSIZE), SECTORSIZE, &retlen,
+                               movebuf);
+               if (ret < 0 && ret != -EUCLEAN) {
+                       ret = mtd->read(mtd,
+                                       (inftl->EraseSize * BlockMap[block]) +
+                                       (block * SECTORSIZE), SECTORSIZE,
+                                       &retlen, movebuf);
                        if (ret != -EIO)
-                               DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
-                                       "away on retry?\n");
-                }
-                memset(&oob, 0xff, sizeof(struct inftl_oob));
-                oob.b.Status = oob.b.Status1 = SECTOR_USED;
-                MTD_WRITEECC(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) +
-                       (block * SECTORSIZE), SECTORSIZE, &retlen,
-                       movebuf, (char *)&oob, &inftl->oobinfo);
+                               DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
+                                     "away on retry?\n");
+               }
+               memset(&oob, 0xff, sizeof(struct inftl_oob));
+               oob.b.Status = oob.b.Status1 = SECTOR_USED;
+
+               inftl_write(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) +
+                           (block * SECTORSIZE), SECTORSIZE, &retlen,
+                           movebuf, (char *)&oob);
        }
 
        /*
@@ -329,17 +394,17 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
                if (thisEUN == targetEUN)
                        break;
 
-                if (INFTL_formatblock(inftl, thisEUN) < 0) {
+               if (INFTL_formatblock(inftl, thisEUN) < 0) {
                        /*
                         * Could not erase : mark block as reserved.
                         */
                        inftl->PUtable[thisEUN] = BLOCK_RESERVED;
-                } else {
+               } else {
                        /* Correctly erased : mark it as free */
                        inftl->PUtable[thisEUN] = BLOCK_FREE;
                        inftl->PUtable[prevEUN] = BLOCK_NIL;
                        inftl->numfreeEUNs++;
-                }
+               }
        }
 
        return targetEUN;
@@ -415,6 +480,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
        unsigned int thisVUC = block / (inftl->EraseSize / SECTORSIZE);
        unsigned int thisEUN, writeEUN, prev_block, status;
        unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize -1);
+       struct mtd_info *mtd = inftl->mbd.mtd;
        struct inftl_oob oob;
        struct inftl_bci bci;
        unsigned char anac, nacs, parity;
@@ -434,10 +500,10 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
                silly = MAX_LOOPS;
 
                while (thisEUN <= inftl->lastEUN) {
-                       MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
-                               blockofs, 8, &retlen, (char *)&bci);
+                       inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
+                                      blockofs, 8, &retlen, (char *)&bci);
 
-                        status = bci.Status | bci.Status1;
+                       status = bci.Status | bci.Status1;
                        DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in "
                                "EUN %d is %x\n", block , writeEUN, status);
 
@@ -522,8 +588,8 @@ hitused:
                nacs = 0;
                thisEUN = inftl->VUtable[thisVUC];
                if (thisEUN != BLOCK_NIL) {
-                       MTD_READOOB(inftl->mbd.mtd, thisEUN * inftl->EraseSize
-                               + 8, 8, &retlen, (char *)&oob.u);
+                       inftl_read_oob(mtd, thisEUN * inftl->EraseSize
+                                      + 8, 8, &retlen, (char *)&oob.u);
                        anac = oob.u.a.ANAC + 1;
                        nacs = oob.u.a.NACs + 1;
                }
@@ -544,8 +610,8 @@ hitused:
                oob.u.a.parityPerField = parity;
                oob.u.a.discarded = 0xaa;
 
-               MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + 8, 8,
-                       &retlen, (char *)&oob.u);
+               inftl_write_oob(mtd, writeEUN * inftl->EraseSize + 8, 8,
+                               &retlen, (char *)&oob.u);
 
                /* Also back up header... */
                oob.u.b.virtualUnitNo = cpu_to_le16(thisVUC);
@@ -555,8 +621,8 @@ hitused:
                oob.u.b.parityPerField = parity;
                oob.u.b.discarded = 0xaa;
 
-               MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize +
-                       SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u);
+               inftl_write_oob(mtd, writeEUN * inftl->EraseSize +
+                               SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u);
 
                inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC];
                inftl->VUtable[thisVUC] = writeEUN;
@@ -576,6 +642,7 @@ hitused:
  */
 static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
 {
+       struct mtd_info *mtd = inftl->mbd.mtd;
        unsigned char BlockUsed[MAX_SECTORS_PER_UNIT];
        unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT];
        unsigned int thisEUN, status;
@@ -606,9 +673,9 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
                        if (BlockUsed[block] || BlockDeleted[block])
                                continue;
 
-                       if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize)
-                           + (block * SECTORSIZE), 8 , &retlen,
-                           (char *)&bci) < 0)
+                       if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize)
+                                          + (block * SECTORSIZE), 8 , &retlen,
+                                         (char *)&bci) < 0)
                                status = SECTOR_IGNORE;
                        else
                                status = bci.Status | bci.Status1;
@@ -670,12 +737,12 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
                DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n",
                      thisEUN, thisVUC);
 
-                if (INFTL_formatblock(inftl, thisEUN) < 0) {
+               if (INFTL_formatblock(inftl, thisEUN) < 0) {
                        /*
                         * Could not erase : mark block as reserved.
                         */
                        inftl->PUtable[thisEUN] = BLOCK_RESERVED;
-                } else {
+               } else {
                        /* Correctly erased : mark it as free */
                        inftl->PUtable[thisEUN] = BLOCK_FREE;
                        inftl->numfreeEUNs++;
@@ -697,6 +764,7 @@ static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block)
 {
        unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)];
        unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
+       struct mtd_info *mtd = inftl->mbd.mtd;
        unsigned int status;
        int silly = MAX_LOOPS;
        size_t retlen;
@@ -706,8 +774,8 @@ static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block)
                "block=%d)\n", inftl, block);
 
        while (thisEUN < inftl->nb_blocks) {
-               if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
-                   blockofs, 8, &retlen, (char *)&bci) < 0)
+               if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
+                                  blockofs, 8, &retlen, (char *)&bci) < 0)
                        status = SECTOR_IGNORE;
                else
                        status = bci.Status | bci.Status1;
@@ -741,10 +809,10 @@ foundit:
        if (thisEUN != BLOCK_NIL) {
                loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
 
-               if (MTD_READOOB(inftl->mbd.mtd, ptr, 8, &retlen, (char *)&bci) < 0)
+               if (inftl_read_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0)
                        return -EIO;
                bci.Status = bci.Status1 = SECTOR_DELETED;
-               if (MTD_WRITEOOB(inftl->mbd.mtd, ptr, 8, &retlen, (char *)&bci) < 0)
+               if (inftl_write_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0)
                        return -EIO;
                INFTL_trydeletechain(inftl, block / (inftl->EraseSize / SECTORSIZE));
        }
@@ -784,9 +852,10 @@ static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
 
                memset(&oob, 0xff, sizeof(struct inftl_oob));
                oob.b.Status = oob.b.Status1 = SECTOR_USED;
-               MTD_WRITEECC(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) +
-                       blockofs, SECTORSIZE, &retlen, (char *)buffer,
-                       (char *)&oob, &inftl->oobinfo);
+
+               inftl_write(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) +
+                           blockofs, SECTORSIZE, &retlen, (char *)buffer,
+                           (char *)&oob);
                /*
                 * need to write SECTOR_USED flags since they are not written
                 * in mtd_writeecc
@@ -804,17 +873,18 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
        struct INFTLrecord *inftl = (void *)mbd;
        unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)];
        unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
-        unsigned int status;
+       struct mtd_info *mtd = inftl->mbd.mtd;
+       unsigned int status;
        int silly = MAX_LOOPS;
-        struct inftl_bci bci;
+       struct inftl_bci bci;
        size_t retlen;
 
        DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld,"
                "buffer=%p)\n", inftl, block, buffer);
 
        while (thisEUN < inftl->nb_blocks) {
-               if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
-                    blockofs, 8, &retlen, (char *)&bci) < 0)
+               if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
+                                 blockofs, 8, &retlen, (char *)&bci) < 0)
                        status = SECTOR_IGNORE;
                else
                        status = bci.Status | bci.Status1;
@@ -850,10 +920,12 @@ foundit:
                /* The requested block is not on the media, return all 0x00 */
                memset(buffer, 0, SECTORSIZE);
        } else {
-               size_t retlen;
+               size_t retlen;
                loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
-               if (MTD_READ(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen,
-                   buffer))
+               int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer);
+
+               /* Handle corrected bit flips gracefully */
+               if (ret < 0 && ret != -EUCLEAN)
                        return -EIO;
        }
        return 0;
index 43fdc943388241bcceeacd66b410ec15612699d2..8f6006f1a519480c3fbba9581294b901bc2571b9 100644 (file)
 
 char inftlmountrev[]="$Revision: 1.18 $";
 
+extern int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                         size_t *retlen, uint8_t *buf);
+extern int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                          size_t *retlen, uint8_t *buf);
+
 /*
  * find_boot_record: Find the INFTL Media Header and its Spare copy which
  *     contains the various device information of the INFTL partition and
@@ -57,6 +62,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
        unsigned int i, block;
        u8 buf[SECTORSIZE];
        struct INFTLMediaHeader *mh = &inftl->MediaHdr;
+       struct mtd_info *mtd = inftl->mbd.mtd;
        struct INFTLPartition *ip;
        size_t retlen;
 
@@ -80,8 +86,8 @@ static int find_boot_record(struct INFTLrecord *inftl)
                 * Check for BNAND header first. Then whinge if it's found
                 * but later checks fail.
                 */
-               ret = MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize,
-                   SECTORSIZE, &retlen, buf);
+               ret = mtd->read(mtd, block * inftl->EraseSize,
+                               SECTORSIZE, &retlen, buf);
                /* We ignore ret in case the ECC of the MediaHeader is invalid
                   (which is apparently acceptable) */
                if (retlen != SECTORSIZE) {
@@ -106,8 +112,9 @@ static int find_boot_record(struct INFTLrecord *inftl)
                }
 
                /* To be safer with BIOS, also use erase mark as discriminant */
-               if ((ret = MTD_READOOB(inftl->mbd.mtd, block * inftl->EraseSize +
-                   SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0)) {
+               if ((ret = inftl_read_oob(mtd, block * inftl->EraseSize +
+                                         SECTORSIZE + 8, 8, &retlen,
+                                         (char *)&h1) < 0)) {
                        printk(KERN_WARNING "INFTL: ANAND header found at "
                                "0x%x in mtd%d, but OOB data read failed "
                                "(err %d)\n", block * inftl->EraseSize,
@@ -123,8 +130,8 @@ static int find_boot_record(struct INFTLrecord *inftl)
                memcpy(mh, buf, sizeof(struct INFTLMediaHeader));
 
                /* Read the spare media header at offset 4096 */
-               MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize + 4096,
-                   SECTORSIZE, &retlen, buf);
+               mtd->read(mtd, block * inftl->EraseSize + 4096,
+                         SECTORSIZE, &retlen, buf);
                if (retlen != SECTORSIZE) {
                        printk(KERN_WARNING "INFTL: Unable to read spare "
                               "Media Header\n");
@@ -233,7 +240,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
                                 */
                                instr->addr = ip->Reserved0 * inftl->EraseSize;
                                instr->len = inftl->EraseSize;
-                               MTD_ERASE(inftl->mbd.mtd, instr);
+                               mtd->erase(mtd, instr);
                        }
                        if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) {
                                printk(KERN_WARNING "INFTL: Media Header "
@@ -350,21 +357,21 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
        int len, int check_oob)
 {
        u8 buf[SECTORSIZE + inftl->mbd.mtd->oobsize];
+       struct mtd_info *mtd = inftl->mbd.mtd;
        size_t retlen;
        int i;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=%p,"
-               "address=0x%x,len=%d,check_oob=%d)\n", inftl,
-               address, len, check_oob);
-
        for (i = 0; i < len; i += SECTORSIZE) {
-               if (MTD_READECC(inftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &inftl->oobinfo) < 0)
+               if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf))
                        return -1;
                if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
                        return -1;
 
                if (check_oob) {
-                       if (memcmpb(buf + SECTORSIZE, 0xff, inftl->mbd.mtd->oobsize) != 0)
+                       if(inftl_read_oob(mtd, address, mtd->oobsize,
+                                         &retlen, &buf[SECTORSIZE]) < 0)
+                               return -1;
+                       if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
                                return -1;
                }
                address += SECTORSIZE;
@@ -387,6 +394,7 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
        size_t retlen;
        struct inftl_unittail uci;
        struct erase_info *instr = &inftl->instr;
+       struct mtd_info *mtd = inftl->mbd.mtd;
        int physblock;
 
        DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p,"
@@ -404,8 +412,9 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
        /* Erase one physical eraseblock at a time, even though the NAND api
           allows us to group them.  This way we if we have a failure, we can
           mark only the failed block in the bbt. */
-       for (physblock = 0; physblock < inftl->EraseSize; physblock += instr->len, instr->addr += instr->len) {
-               MTD_ERASE(inftl->mbd.mtd, instr);
+       for (physblock = 0; physblock < inftl->EraseSize;
+            physblock += instr->len, instr->addr += instr->len) {
+               mtd->erase(inftl->mbd.mtd, instr);
 
                if (instr->state == MTD_ERASE_FAILED) {
                        printk(KERN_WARNING "INFTL: error while formatting block %d\n",
@@ -414,10 +423,10 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
                }
 
                /*
-               * Check the "freeness" of Erase Unit before updating metadata.
-               * FixMe: is this check really necessary? Since we have check the
-               *        return code after the erase operation.
-               */
+                * Check the "freeness" of Erase Unit before updating metadata.
+                * FixMe: is this check really necessary? Since we have check
+                * the return code after the erase operation.
+                */
                if (check_free_sectors(inftl, instr->addr, instr->len, 1) != 0)
                        goto fail;
        }
@@ -429,8 +438,7 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
        uci.Reserved[2] = 0;
        uci.Reserved[3] = 0;
        instr->addr = block * inftl->EraseSize + SECTORSIZE * 2;
-       if (MTD_WRITEOOB(inftl->mbd.mtd, instr->addr +
-           8, 8, &retlen, (char *)&uci) < 0)
+       if (inftl_write_oob(mtd, instr->addr + 8, 8, &retlen, (char *)&uci) < 0)
                goto fail;
        return 0;
 fail:
@@ -549,6 +557,7 @@ void INFTL_dumpVUchains(struct INFTLrecord *s)
 
 int INFTL_mount(struct INFTLrecord *s)
 {
+       struct mtd_info *mtd = s->mbd.mtd;
        unsigned int block, first_block, prev_block, last_block;
        unsigned int first_logical_block, logical_block, erase_mark;
        int chain_length, do_format_chain;
@@ -607,10 +616,11 @@ int INFTL_mount(struct INFTLrecord *s)
                                break;
                        }
 
-                       if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8,
-                           8, &retlen, (char *)&h0) < 0 ||
-                           MTD_READOOB(s->mbd.mtd, block * s->EraseSize +
-                           2 * SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0) {
+                       if (inftl_read_oob(mtd, block * s->EraseSize + 8,
+                                          8, &retlen, (char *)&h0) < 0 ||
+                           inftl_read_oob(mtd, block * s->EraseSize +
+                                          2 * SECTORSIZE + 8, 8, &retlen,
+                                          (char *)&h1) < 0) {
                                /* Should never happen? */
                                do_format_chain++;
                                break;
index 7abd7fee0ddaa669b64f167e587c6e3a8ab7aacf..6bdaacc6d6f9157c2353fd391dce37c4484b8eb5 100644 (file)
@@ -37,7 +37,7 @@ config MTD_PHYSMAP_START
 config MTD_PHYSMAP_LEN
        hex "Physical length of flash mapping"
        depends on MTD_PHYSMAP
-       default "0x4000000"
+       default "0"
        help
          This is the total length of the mapping of the flash chips on
          your particular board. If there is space, or aliases, in the
@@ -78,7 +78,7 @@ config MTD_PNC2000
 
 config MTD_SC520CDP
        tristate "CFI Flash device mapped on AMD SC520 CDP"
-       depends on X86 && MTD_CFI
+       depends on X86 && MTD_CFI && MTD_CONCAT
        help
          The SC520 CDP board has two banks of CFI-compliant chips and one
          Dual-in-line JEDEC chip. This 'mapping' driver supports that
@@ -109,7 +109,7 @@ config MTD_TS5500
          mtd1 allows you to reprogram your BIOS. BE VERY CAREFUL.
 
          Note that jumper 3 ("Write Enable Drive A") must be set
-         otherwise detection won't succeeed.
+         otherwise detection won't succeed.
 
 config MTD_SBC_GXX
        tristate "CFI Flash device mapped on Arcom SBC-GXx boards"
@@ -200,8 +200,8 @@ config MTD_TSUNAMI
          Support for the flash chip on Tsunami TIG bus.
 
 config MTD_LASAT
-       tristate "Flash chips on LASAT board"
-       depends on LASAT
+       tristate "LASAT flash device"
+       depends on LASAT && MTD_CFI
        help
          Support for the flash chips on the Lasat 100 and 200 boards.
 
@@ -561,7 +561,6 @@ config MTD_PCMCIA
 config MTD_PCMCIA_ANONYMOUS
        bool "Use PCMCIA MTD drivers for anonymous PCMCIA cards"
        depends on MTD_PCMCIA
-       default N
        help
          If this option is enabled, PCMCIA cards which do not report
          anything about themselves are assumed to be MTD cards.
index fd0f0d3187de3bb7efad5400b1d6dbc82e55b35b..92b5d883d7b0e4f8b4ad978a6fac2a9c44c2bfc4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright Â© 2001 Flaga hf. Medical Devices, Kári Davíðsson <kd@flaga.is>
+ *  Copyright Â© 2001 Flaga hf. Medical Devices, Kári Davíðsson <kd@flaga.is>
  *
  *  $Id: cfi_flagadm.c,v 1.15 2005/11/07 11:14:26 gleixner Exp $
  *
@@ -135,5 +135,5 @@ module_exit(cleanup_flagadm);
 
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>");
+MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>");
 MODULE_DESCRIPTION("MTD map driver for Flaga digital module");
index 652813cd6c2d47f0dbb92113f912fd2cde2bf7ab..85c2a9e22b1e28ee6186da35ae51ae3ac9301278 100644 (file)
@@ -122,5 +122,5 @@ module_exit(cleanup_dbox2_flash);
 
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>, Bastian Blank <waldi@tuxbox.org>, Alexander Wild <wild@te-elektronik.com>");
+MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>, Bastian Blank <waldi@tuxbox.org>, Alexander Wild <wild@te-elektronik.com>");
 MODULE_DESCRIPTION("MTD map driver for D-Box 2 board");
index d1e66e186746bf4116476ae2a8fb17b95660600c..5c25d4e552c61053cc11daf0d32fcda1144f1cb6 100644 (file)
@@ -4,7 +4,7 @@
  * $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $
  *
  * (C) 2005 Bruno Randolf <bruno.randolf@4g-systems.biz>
- * (C) 2005 Jörn Engel <joern@wohnheim.fh-wedel.de>
+ * (C) 2005 Jörn Engel <joern@wohnheim.fh-wedel.de>
  *
  */
 
index 54a3102ab19a8868cbd18c2d1ce5cf9c92111ea6..0994b5b2e3313f87b8a581f896d315306b87d310 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/cfi.h>
 #include <linux/reboot.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
 #include <asm/io.h>
 
 /****************************************************************************/
@@ -188,7 +190,7 @@ int nettel_eraseconfig(void)
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&wait_q, &wait);
 
-               ret = MTD_ERASE(mtd, &nettel_erase);
+               ret = mtd->erase(mtd, &nettel_erase);
                if (ret) {
                        set_current_state(TASK_RUNNING);
                        remove_wait_queue(&wait_q, &wait);
index d27f4129afd3c952b5e5f33d85cec2e73d41584a..c861134cbc48d253ccc3530568402b0de0665441 100644 (file)
@@ -713,6 +713,7 @@ static void pcmciamtd_detach(struct pcmcia_device *link)
 
        if(dev->mtd_info) {
                del_mtd_device(dev->mtd_info);
+               map_destroy(dev->mtd_info);
                info("mtd%d: Removed", dev->mtd_info->index);
        }
 
index f49ebc3c4606c89dbc60605cbbf31dd33a6bf93f..433c3cac3ca959285e0cd87e33829e2540c53acc 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <asm/io.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/config.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#include <asm/io.h>
 
-static struct mtd_info *mymtd;
-
-struct map_info physmap_map = {
-       .name = "phys_mapped_flash",
-       .phys = CONFIG_MTD_PHYSMAP_START,
-       .size = CONFIG_MTD_PHYSMAP_LEN,
-       .bankwidth = CONFIG_MTD_PHYSMAP_BANKWIDTH,
+struct physmap_flash_info {
+       struct mtd_info         *mtd;
+       struct map_info         map;
+       struct resource         *res;
+#ifdef CONFIG_MTD_PARTITIONS
+       int                     nr_parts;
+       struct mtd_partition    *parts;
+#endif
 };
 
+
+static int physmap_flash_remove(struct platform_device *dev)
+{
+       struct physmap_flash_info *info;
+       struct physmap_flash_data *physmap_data;
+
+       info = platform_get_drvdata(dev);
+       if (info == NULL)
+               return 0;
+       platform_set_drvdata(dev, NULL);
+
+       physmap_data = dev->dev.platform_data;
+
+       if (info->mtd != NULL) {
 #ifdef CONFIG_MTD_PARTITIONS
-static struct mtd_partition *mtd_parts;
-static int                   mtd_parts_nb;
+               if (info->nr_parts) {
+                       del_mtd_partitions(info->mtd);
+                       kfree(info->parts);
+               } else if (physmap_data->nr_parts) {
+                       del_mtd_partitions(info->mtd);
+               } else {
+                       del_mtd_device(info->mtd);
+               }
+#else
+               del_mtd_device(info->mtd);
+#endif
+               map_destroy(info->mtd);
+       }
 
-static int num_physmap_partitions;
-static struct mtd_partition *physmap_partitions;
+       if (info->map.virt != NULL)
+               iounmap((void *)info->map.virt);
 
-static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
+       if (info->res != NULL) {
+               release_resource(info->res);
+               kfree(info->res);
+       }
 
-void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
-{
-       physmap_partitions=parts;
-       num_physmap_partitions=num_parts;
+       return 0;
 }
-#endif /* CONFIG_MTD_PARTITIONS */
 
-static int __init init_physmap(void)
+static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+#endif
+
+static int physmap_flash_probe(struct platform_device *dev)
 {
-       static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
-       const char **type;
+       struct physmap_flash_data *physmap_data;
+       struct physmap_flash_info *info;
+       const char **probe_type;
+       int err;
+
+       physmap_data = dev->dev.platform_data;
+       if (physmap_data == NULL)
+               return -ENODEV;
+
+               printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
+           (unsigned long long)dev->resource->end - dev->resource->start + 1,
+           (unsigned long long)dev->resource->start);
+
+       info = kmalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
+       if (info == NULL) {
+               err = -ENOMEM;
+               goto err_out;
+       }
+       memset(info, 0, sizeof(*info));
 
-               printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys);
-       physmap_map.virt = ioremap(physmap_map.phys, physmap_map.size);
+       platform_set_drvdata(dev, info);
 
-       if (!physmap_map.virt) {
-               printk("Failed to ioremap\n");
-               return -EIO;
+       info->res = request_mem_region(dev->resource->start,
+                       dev->resource->end - dev->resource->start + 1,
+                       dev->dev.bus_id);
+       if (info->res == NULL) {
+               dev_err(&dev->dev, "Could not reserve memory region\n");
+               err = -ENOMEM;
+               goto err_out;
        }
 
-       simple_map_init(&physmap_map);
+       info->map.name = dev->dev.bus_id;
+       info->map.phys = dev->resource->start;
+       info->map.size = dev->resource->end - dev->resource->start + 1;
+       info->map.bankwidth = physmap_data->width;
+       info->map.set_vpp = physmap_data->set_vpp;
+
+       info->map.virt = ioremap(info->map.phys, info->map.size);
+       if (info->map.virt == NULL) {
+               dev_err(&dev->dev, "Failed to ioremap flash region\n");
+               err = EIO;
+               goto err_out;
+       }
 
-       mymtd = NULL;
-       type = rom_probe_types;
-       for(; !mymtd && *type; type++) {
-               mymtd = do_map_probe(*type, &physmap_map);
+       simple_map_init(&info->map);
+
+       probe_type = rom_probe_types;
+       for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
+               info->mtd = do_map_probe(*probe_type, &info->map);
+       if (info->mtd == NULL) {
+               dev_err(&dev->dev, "map_probe failed\n");
+               err = -ENXIO;
+               goto err_out;
        }
-       if (mymtd) {
-               mymtd->owner = THIS_MODULE;
+       info->mtd->owner = THIS_MODULE;
 
 #ifdef CONFIG_MTD_PARTITIONS
-               mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes,
-                                                   &mtd_parts, 0);
+       err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
+       if (err > 0) {
+               add_mtd_partitions(info->mtd, info->parts, err);
+               return 0;
+       }
 
-               if (mtd_parts_nb > 0)
-               {
-                       add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);
-                       return 0;
-               }
+       if (physmap_data->nr_parts) {
+               printk(KERN_NOTICE "Using physmap partition information\n");
+               add_mtd_partitions(info->mtd, physmap_data->parts,
+                                               physmap_data->nr_parts);
+               return 0;
+       }
+#endif
+
+       add_mtd_device(info->mtd);
+       return 0;
+
+err_out:
+       physmap_flash_remove(dev);
+       return err;
+}
+
+static struct platform_driver physmap_flash_driver = {
+       .probe          = physmap_flash_probe,
+       .remove         = physmap_flash_remove,
+       .driver         = {
+               .name   = "physmap-flash",
+       },
+};
 
-               if (num_physmap_partitions != 0)
-               {
-                       printk(KERN_NOTICE
-                              "Using physmap partition definition\n");
-                       add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions);
-                       return 0;
-               }
 
+#ifdef CONFIG_MTD_PHYSMAP_LEN
+#if CONFIG_MTD_PHYSMAP_LEN != 0
+#warning using PHYSMAP compat code
+#define PHYSMAP_COMPAT
+#endif
 #endif
-               add_mtd_device(mymtd);
 
-               return 0;
-       }
+#ifdef PHYSMAP_COMPAT
+static struct physmap_flash_data physmap_flash_data = {
+       .width          = CONFIG_MTD_PHYSMAP_BANKWIDTH,
+};
 
-       iounmap(physmap_map.virt);
-       return -ENXIO;
-}
+static struct resource physmap_flash_resource = {
+       .start          = CONFIG_MTD_PHYSMAP_START,
+       .end            = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN,
+       .flags          = IORESOURCE_MEM,
+};
 
-static void __exit cleanup_physmap(void)
+static struct platform_device physmap_flash = {
+       .name           = "physmap-flash",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &physmap_flash_data,
+       },
+       .num_resources  = 1,
+       .resource       = &physmap_flash_resource,
+};
+
+void physmap_configure(unsigned long addr, unsigned long size,
+               int bankwidth, void (*set_vpp)(struct map_info *, int))
 {
+       physmap_flash_resource.start = addr;
+       physmap_flash_resource.end = addr + size - 1;
+       physmap_flash_data.width = bankwidth;
+       physmap_flash_data.set_vpp = set_vpp;
+}
+
 #ifdef CONFIG_MTD_PARTITIONS
-       if (mtd_parts_nb) {
-               del_mtd_partitions(mymtd);
-               kfree(mtd_parts);
-       } else if (num_physmap_partitions) {
-               del_mtd_partitions(mymtd);
-       } else {
-               del_mtd_device(mymtd);
-       }
-#else
-       del_mtd_device(mymtd);
+void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
+{
+       physmap_flash_data.nr_parts = num_parts;
+       physmap_flash_data.parts = parts;
+}
+#endif
 #endif
-       map_destroy(mymtd);
 
-       iounmap(physmap_map.virt);
-       physmap_map.virt = NULL;
+static int __init physmap_init(void)
+{
+       int err;
+
+       err = platform_driver_register(&physmap_flash_driver);
+#ifdef PHYSMAP_COMPAT
+       if (err == 0)
+               platform_device_register(&physmap_flash);
+#endif
+
+       return err;
 }
 
-module_init(init_physmap);
-module_exit(cleanup_physmap);
+static void __exit physmap_exit(void)
+{
+#ifdef PHYSMAP_COMPAT
+       platform_device_unregister(&physmap_flash);
+#endif
+       platform_driver_unregister(&physmap_flash_driver);
+}
 
+module_init(physmap_init);
+module_exit(physmap_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
index 2cef280e388c76aaf455fe49f3232596f8d40308..e5c78463ebfd5361c38429c171720b0f1cef281b 100644 (file)
@@ -71,7 +71,7 @@ static int erase_write (struct mtd_info *mtd, unsigned long pos,
        set_current_state(TASK_INTERRUPTIBLE);
        add_wait_queue(&wait_q, &wait);
 
-       ret = MTD_ERASE(mtd, &erase);
+       ret = mtd->erase(mtd, &erase);
        if (ret) {
                set_current_state(TASK_RUNNING);
                remove_wait_queue(&wait_q, &wait);
@@ -88,7 +88,7 @@ static int erase_write (struct mtd_info *mtd, unsigned long pos,
         * Next, writhe data to flash.
         */
 
-       ret = MTD_WRITE (mtd, pos, len, &retlen, buf);
+       ret = mtd->write(mtd, pos, len, &retlen, buf);
        if (ret)
                return ret;
        if (retlen != len)
@@ -138,7 +138,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
                mtd->name, pos, len);
 
        if (!sect_size)
-               return MTD_WRITE (mtd, pos, len, &retlen, buf);
+               return mtd->write(mtd, pos, len, &retlen, buf);
 
        while (len > 0) {
                unsigned long sect_start = (pos/sect_size)*sect_size;
@@ -170,7 +170,8 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
                            mtdblk->cache_offset != sect_start) {
                                /* fill the cache with the current sector */
                                mtdblk->cache_state = STATE_EMPTY;
-                               ret = MTD_READ(mtd, sect_start, sect_size, &retlen, mtdblk->cache_data);
+                               ret = mtd->read(mtd, sect_start, sect_size,
+                                               &retlen, mtdblk->cache_data);
                                if (ret)
                                        return ret;
                                if (retlen != sect_size)
@@ -207,7 +208,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
                        mtd->name, pos, len);
 
        if (!sect_size)
-               return MTD_READ (mtd, pos, len, &retlen, buf);
+               return mtd->read(mtd, pos, len, &retlen, buf);
 
        while (len > 0) {
                unsigned long sect_start = (pos/sect_size)*sect_size;
@@ -226,7 +227,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
                    mtdblk->cache_offset == sect_start) {
                        memcpy (buf, mtdblk->cache_data + offset, size);
                } else {
-                       ret = MTD_READ (mtd, pos, size, &retlen, buf);
+                       ret = mtd->read(mtd, pos, size, &retlen, buf);
                        if (ret)
                                return ret;
                        if (retlen != size)
@@ -288,8 +289,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
 
        mutex_init(&mtdblk->cache_mutex);
        mtdblk->cache_state = STATE_EMPTY;
-       if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM &&
-           mtdblk->mtd->erasesize) {
+       if ( !(mtdblk->mtd->flags & MTD_NO_ERASE) && mtdblk->mtd->erasesize) {
                mtdblk->cache_size = mtdblk->mtd->erasesize;
                mtdblk->cache_data = NULL;
        }
index 0c830ba41ef05b3e93c39f316b1217149645b672..29563ed258a4788bf86eb03341b4fad0440ed2d0 100644 (file)
@@ -45,9 +45,7 @@ static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
        dev->blksize = 512;
        dev->size = mtd->size >> 9;
        dev->tr = tr;
-       if ((mtd->flags & (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE)) !=
-           (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE))
-               dev->readonly = 1;
+       dev->readonly = 1;
 
        add_mtd_blktrans_dev(dev);
 }
index 6f044584bdc6ac3b38c4a20949bfcbabb5f292ae..aa18d45b264bb2d3aef9c71792401ac1d7ccece5 100644 (file)
@@ -49,24 +49,18 @@ static struct mtd_notifier notifier = {
 };
 
 /*
- * We use file->private_data to store a pointer to the MTDdevice.
- * Since alighment is at least 32 bits, we have 2 bits free for OTP
- * modes as well.
+ * Data structure to hold the pointer to the mtd device as well
+ * as mode information ofr various use cases.
  */
-
-#define TO_MTD(file) (struct mtd_info *)((long)((file)->private_data) & ~3L)
-
-#define MTD_MODE_OTP_FACT      1
-#define MTD_MODE_OTP_USER      2
-#define MTD_MODE(file)         ((long)((file)->private_data) & 3)
-
-#define SET_MTD_MODE(file, mode) \
-       do { long __p = (long)((file)->private_data); \
-            (file)->private_data = (void *)((__p & ~3L) | mode); } while (0)
+struct mtd_file_info {
+       struct mtd_info *mtd;
+       enum mtd_file_modes mode;
+};
 
 static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
 {
-       struct mtd_info *mtd = TO_MTD(file);
+       struct mtd_file_info *mfi = file->private_data;
+       struct mtd_info *mtd = mfi->mtd;
 
        switch (orig) {
        case 0:
@@ -97,6 +91,7 @@ static int mtd_open(struct inode *inode, struct file *file)
        int minor = iminor(inode);
        int devnum = minor >> 1;
        struct mtd_info *mtd;
+       struct mtd_file_info *mfi;
 
        DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n");
 
@@ -117,14 +112,20 @@ static int mtd_open(struct inode *inode, struct file *file)
                return -ENODEV;
        }
 
-       file->private_data = mtd;
-
        /* You can't open it RW if it's not a writeable device */
        if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) {
                put_mtd_device(mtd);
                return -EACCES;
        }
 
+       mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
+       if (!mfi) {
+               put_mtd_device(mtd);
+               return -ENOMEM;
+       }
+       mfi->mtd = mtd;
+       file->private_data = mfi;
+
        return 0;
 } /* mtd_open */
 
@@ -132,16 +133,17 @@ static int mtd_open(struct inode *inode, struct file *file)
 
 static int mtd_close(struct inode *inode, struct file *file)
 {
-       struct mtd_info *mtd;
+       struct mtd_file_info *mfi = file->private_data;
+       struct mtd_info *mtd = mfi->mtd;
 
        DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
 
-       mtd = TO_MTD(file);
-
        if (mtd->sync)
                mtd->sync(mtd);
 
        put_mtd_device(mtd);
+       file->private_data = NULL;
+       kfree(mfi);
 
        return 0;
 } /* mtd_close */
@@ -153,7 +155,8 @@ static int mtd_close(struct inode *inode, struct file *file)
 
 static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)
 {
-       struct mtd_info *mtd = TO_MTD(file);
+       struct mtd_file_info *mfi = file->private_data;
+       struct mtd_info *mtd = mfi->mtd;
        size_t retlen=0;
        size_t total_retlen=0;
        int ret=0;
@@ -170,36 +173,58 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
 
        /* FIXME: Use kiovec in 2.5 to lock down the user's buffers
           and pass them directly to the MTD functions */
+
+       if (count > MAX_KMALLOC_SIZE)
+               kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
+       else
+               kbuf=kmalloc(count, GFP_KERNEL);
+
+       if (!kbuf)
+               return -ENOMEM;
+
        while (count) {
+
                if (count > MAX_KMALLOC_SIZE)
                        len = MAX_KMALLOC_SIZE;
                else
                        len = count;
 
-               kbuf=kmalloc(len,GFP_KERNEL);
-               if (!kbuf)
-                       return -ENOMEM;
-
-               switch (MTD_MODE(file)) {
-               case MTD_MODE_OTP_FACT:
+               switch (mfi->mode) {
+               case MTD_MODE_OTP_FACTORY:
                        ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf);
                        break;
                case MTD_MODE_OTP_USER:
                        ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
                        break;
+               case MTD_MODE_RAW:
+               {
+                       struct mtd_oob_ops ops;
+
+                       ops.mode = MTD_OOB_RAW;
+                       ops.datbuf = kbuf;
+                       ops.oobbuf = NULL;
+                       ops.len = len;
+
+                       ret = mtd->read_oob(mtd, *ppos, &ops);
+                       retlen = ops.retlen;
+                       break;
+               }
                default:
-                       ret = MTD_READ(mtd, *ppos, len, &retlen, kbuf);
+                       ret = mtd->read(mtd, *ppos, len, &retlen, kbuf);
                }
                /* Nand returns -EBADMSG on ecc errors, but it returns
                 * the data. For our userspace tools it is important
                 * to dump areas with ecc errors !
+                * For kernel internal usage it also might return -EUCLEAN
+                * to signal the caller that a bitflip has occured and has
+                * been corrected by the ECC algorithm.
                 * Userspace software which accesses NAND this way
                 * must be aware of the fact that it deals with NAND
                 */
-               if (!ret || (ret == -EBADMSG)) {
+               if (!ret || (ret == -EUCLEAN) || (ret == -EBADMSG)) {
                        *ppos += retlen;
                        if (copy_to_user(buf, kbuf, retlen)) {
-                               kfree(kbuf);
+                               kfree(kbuf);
                                return -EFAULT;
                        }
                        else
@@ -215,15 +240,16 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
                        return ret;
                }
 
-               kfree(kbuf);
        }
 
+       kfree(kbuf);
        return total_retlen;
 } /* mtd_read */
 
 static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos)
 {
-       struct mtd_info *mtd = TO_MTD(file);
+       struct mtd_file_info *mfi = file->private_data;
+       struct mtd_info *mtd = mfi->mtd;
        char *kbuf;
        size_t retlen;
        size_t total_retlen=0;
@@ -241,25 +267,28 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
        if (!count)
                return 0;
 
+       if (count > MAX_KMALLOC_SIZE)
+               kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
+       else
+               kbuf=kmalloc(count, GFP_KERNEL);
+
+       if (!kbuf)
+               return -ENOMEM;
+
        while (count) {
+
                if (count > MAX_KMALLOC_SIZE)
                        len = MAX_KMALLOC_SIZE;
                else
                        len = count;
 
-               kbuf=kmalloc(len,GFP_KERNEL);
-               if (!kbuf) {
-                       printk("kmalloc is null\n");
-                       return -ENOMEM;
-               }
-
                if (copy_from_user(kbuf, buf, len)) {
                        kfree(kbuf);
                        return -EFAULT;
                }
 
-               switch (MTD_MODE(file)) {
-               case MTD_MODE_OTP_FACT:
+               switch (mfi->mode) {
+               case MTD_MODE_OTP_FACTORY:
                        ret = -EROFS;
                        break;
                case MTD_MODE_OTP_USER:
@@ -269,6 +298,21 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
                        }
                        ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
                        break;
+
+               case MTD_MODE_RAW:
+               {
+                       struct mtd_oob_ops ops;
+
+                       ops.mode = MTD_OOB_RAW;
+                       ops.datbuf = kbuf;
+                       ops.oobbuf = NULL;
+                       ops.len = len;
+
+                       ret = mtd->write_oob(mtd, *ppos, &ops);
+                       retlen = ops.retlen;
+                       break;
+               }
+
                default:
                        ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf);
                }
@@ -282,10 +326,9 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
                        kfree(kbuf);
                        return ret;
                }
-
-               kfree(kbuf);
        }
 
+       kfree(kbuf);
        return total_retlen;
 } /* mtd_write */
 
@@ -299,13 +342,45 @@ static void mtdchar_erase_callback (struct erase_info *instr)
        wake_up((wait_queue_head_t *)instr->priv);
 }
 
+#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
+static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
+{
+       struct mtd_info *mtd = mfi->mtd;
+       int ret = 0;
+
+       switch (mode) {
+       case MTD_OTP_FACTORY:
+               if (!mtd->read_fact_prot_reg)
+                       ret = -EOPNOTSUPP;
+               else
+                       mfi->mode = MTD_MODE_OTP_FACTORY;
+               break;
+       case MTD_OTP_USER:
+               if (!mtd->read_fact_prot_reg)
+                       ret = -EOPNOTSUPP;
+               else
+                       mfi->mode = MTD_MODE_OTP_USER;
+               break;
+       default:
+               ret = -EINVAL;
+       case MTD_OTP_OFF:
+               break;
+       }
+       return ret;
+}
+#else
+# define otp_select_filemode(f,m)      -EOPNOTSUPP
+#endif
+
 static int mtd_ioctl(struct inode *inode, struct file *file,
                     u_int cmd, u_long arg)
 {
-       struct mtd_info *mtd = TO_MTD(file);
+       struct mtd_file_info *mfi = file->private_data;
+       struct mtd_info *mtd = mfi->mtd;
        void __user *argp = (void __user *)arg;
        int ret = 0;
        u_long size;
+       struct mtd_info_user info;
 
        DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
 
@@ -341,7 +416,15 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
        }
 
        case MEMGETINFO:
-               if (copy_to_user(argp, mtd, sizeof(struct mtd_info_user)))
+               info.type       = mtd->type;
+               info.flags      = mtd->flags;
+               info.size       = mtd->size;
+               info.erasesize  = mtd->erasesize;
+               info.writesize  = mtd->writesize;
+               info.oobsize    = mtd->oobsize;
+               info.ecctype    = mtd->ecctype;
+               info.eccsize    = mtd->eccsize;
+               if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
                        return -EFAULT;
                break;
 
@@ -400,8 +483,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
        case MEMWRITEOOB:
        {
                struct mtd_oob_buf buf;
-               void *databuf;
-               ssize_t retlen;
+               struct mtd_oob_ops ops;
 
                if(!(file->f_mode & 2))
                        return -EPERM;
@@ -409,7 +491,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
                        return -EFAULT;
 
-               if (buf.length > 0x4096)
+               if (buf.length > 4096)
                        return -EINVAL;
 
                if (!mtd->write_oob)
@@ -421,21 +503,32 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                if (ret)
                        return ret;
 
-               databuf = kmalloc(buf.length, GFP_KERNEL);
-               if (!databuf)
+               ops.len = buf.length;
+               ops.ooblen = buf.length;
+               ops.ooboffs = buf.start & (mtd->oobsize - 1);
+               ops.datbuf = NULL;
+               ops.mode = MTD_OOB_PLACE;
+
+               if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs))
+                       return -EINVAL;
+
+               ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
+               if (!ops.oobbuf)
                        return -ENOMEM;
 
-               if (copy_from_user(databuf, buf.ptr, buf.length)) {
-                       kfree(databuf);
+               if (copy_from_user(ops.oobbuf, buf.ptr, buf.length)) {
+                       kfree(ops.oobbuf);
                        return -EFAULT;
                }
 
-               ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf);
+               buf.start &= ~(mtd->oobsize - 1);
+               ret = mtd->write_oob(mtd, buf.start, &ops);
 
-               if (copy_to_user(argp + sizeof(uint32_t), &retlen, sizeof(uint32_t)))
+               if (copy_to_user(argp + sizeof(uint32_t), &ops.retlen,
+                                sizeof(uint32_t)))
                        ret = -EFAULT;
 
-               kfree(databuf);
+               kfree(ops.oobbuf);
                break;
 
        }
@@ -443,13 +536,12 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
        case MEMREADOOB:
        {
                struct mtd_oob_buf buf;
-               void *databuf;
-               ssize_t retlen;
+               struct mtd_oob_ops ops;
 
                if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
                        return -EFAULT;
 
-               if (buf.length > 0x4096)
+               if (buf.length > 4096)
                        return -EINVAL;
 
                if (!mtd->read_oob)
@@ -457,22 +549,32 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                else
                        ret = access_ok(VERIFY_WRITE, buf.ptr,
                                        buf.length) ? 0 : -EFAULT;
-
                if (ret)
                        return ret;
 
-               databuf = kmalloc(buf.length, GFP_KERNEL);
-               if (!databuf)
+               ops.len = buf.length;
+               ops.ooblen = buf.length;
+               ops.ooboffs = buf.start & (mtd->oobsize - 1);
+               ops.datbuf = NULL;
+               ops.mode = MTD_OOB_PLACE;
+
+               if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs))
+                       return -EINVAL;
+
+               ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
+               if (!ops.oobbuf)
                        return -ENOMEM;
 
-               ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf);
+               buf.start &= ~(mtd->oobsize - 1);
+               ret = mtd->read_oob(mtd, buf.start, &ops);
 
-               if (put_user(retlen, (uint32_t __user *)argp))
+               if (put_user(ops.retlen, (uint32_t __user *)argp))
                        ret = -EFAULT;
-               else if (retlen && copy_to_user(buf.ptr, databuf, retlen))
+               else if (ops.retlen && copy_to_user(buf.ptr, ops.oobbuf,
+                                                   ops.retlen))
                        ret = -EFAULT;
 
-               kfree(databuf);
+               kfree(ops.oobbuf);
                break;
        }
 
@@ -504,16 +606,22 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                break;
        }
 
-       case MEMSETOOBSEL:
-       {
-               if (copy_from_user(&mtd->oobinfo, argp, sizeof(struct nand_oobinfo)))
-                       return -EFAULT;
-               break;
-       }
-
+       /* Legacy interface */
        case MEMGETOOBSEL:
        {
-               if (copy_to_user(argp, &(mtd->oobinfo), sizeof(struct nand_oobinfo)))
+               struct nand_oobinfo oi;
+
+               if (!mtd->ecclayout)
+                       return -EOPNOTSUPP;
+               if (mtd->ecclayout->eccbytes > ARRAY_SIZE(oi.eccpos))
+                       return -EINVAL;
+
+               oi.useecc = MTD_NANDECC_AUTOPLACE;
+               memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos));
+               memcpy(&oi.oobfree, mtd->ecclayout->oobfree,
+                      sizeof(oi.oobfree));
+
+               if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
                        return -EFAULT;
                break;
        }
@@ -544,31 +652,17 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                break;
        }
 
-#ifdef CONFIG_MTD_OTP
+#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
        case OTPSELECT:
        {
                int mode;
                if (copy_from_user(&mode, argp, sizeof(int)))
                        return -EFAULT;
-               SET_MTD_MODE(file, 0);
-               switch (mode) {
-               case MTD_OTP_FACTORY:
-                       if (!mtd->read_fact_prot_reg)
-                               ret = -EOPNOTSUPP;
-                       else
-                               SET_MTD_MODE(file, MTD_MODE_OTP_FACT);
-                       break;
-               case MTD_OTP_USER:
-                       if (!mtd->read_fact_prot_reg)
-                               ret = -EOPNOTSUPP;
-                       else
-                               SET_MTD_MODE(file, MTD_MODE_OTP_USER);
-                       break;
-               default:
-                       ret = -EINVAL;
-               case MTD_OTP_OFF:
-                       break;
-               }
+
+               mfi->mode = MTD_MODE_NORMAL;
+
+               ret = otp_select_filemode(mfi, mode);
+
                file->f_pos = 0;
                break;
        }
@@ -580,8 +674,8 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                if (!buf)
                        return -ENOMEM;
                ret = -EOPNOTSUPP;
-               switch (MTD_MODE(file)) {
-               case MTD_MODE_OTP_FACT:
+               switch (mfi->mode) {
+               case MTD_MODE_OTP_FACTORY:
                        if (mtd->get_fact_prot_info)
                                ret = mtd->get_fact_prot_info(mtd, buf, 4096);
                        break;
@@ -589,6 +683,8 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                        if (mtd->get_user_prot_info)
                                ret = mtd->get_user_prot_info(mtd, buf, 4096);
                        break;
+               default:
+                       break;
                }
                if (ret >= 0) {
                        if (cmd == OTPGETREGIONCOUNT) {
@@ -607,7 +703,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
        {
                struct otp_info info;
 
-               if (MTD_MODE(file) != MTD_MODE_OTP_USER)
+               if (mfi->mode != MTD_MODE_OTP_USER)
                        return -EINVAL;
                if (copy_from_user(&info, argp, sizeof(info)))
                        return -EFAULT;
@@ -618,6 +714,49 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
        }
 #endif
 
+       case ECCGETLAYOUT:
+       {
+               if (!mtd->ecclayout)
+                       return -EOPNOTSUPP;
+
+               if (copy_to_user(argp, &mtd->ecclayout,
+                                sizeof(struct nand_ecclayout)))
+                       return -EFAULT;
+               break;
+       }
+
+       case ECCGETSTATS:
+       {
+               if (copy_to_user(argp, &mtd->ecc_stats,
+                                sizeof(struct mtd_ecc_stats)))
+                       return -EFAULT;
+               break;
+       }
+
+       case MTDFILEMODE:
+       {
+               mfi->mode = 0;
+
+               switch(arg) {
+               case MTD_MODE_OTP_FACTORY:
+               case MTD_MODE_OTP_USER:
+                       ret = otp_select_filemode(mfi, arg);
+                       break;
+
+               case MTD_MODE_RAW:
+                       if (!mtd->read_oob || !mtd->write_oob)
+                               return -EOPNOTSUPP;
+                       mfi->mode = arg;
+
+               case MTD_MODE_NORMAL:
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               file->f_pos = 0;
+               break;
+       }
+
        default:
                ret = -ENOTTY;
        }
index 9af840364a74ff849c2aa283b25c0dc6038565a1..1fea631b58520aef095c356730709722f6b38248 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/concat.h>
 
+#include <asm/div64.h>
+
 /*
  * Our storage structure:
  * Subdev points to an array of pointers to struct mtd_info objects
@@ -54,7 +56,7 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,
            size_t * retlen, u_char * buf)
 {
        struct mtd_concat *concat = CONCAT(mtd);
-       int err = -EINVAL;
+       int ret = 0, err;
        int i;
 
        *retlen = 0;
@@ -78,19 +80,29 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,
 
                err = subdev->read(subdev, from, size, &retsize, buf);
 
-               if (err)
-                       break;
+               /* Save information about bitflips! */
+               if (unlikely(err)) {
+                       if (err == -EBADMSG) {
+                               mtd->ecc_stats.failed++;
+                               ret = err;
+                       } else if (err == -EUCLEAN) {
+                               mtd->ecc_stats.corrected++;
+                               /* Do not overwrite -EBADMSG !! */
+                               if (!ret)
+                                       ret = err;
+                       } else
+                               return err;
+               }
 
                *retlen += retsize;
                len -= size;
                if (len == 0)
-                       break;
+                       return ret;
 
-               err = -EINVAL;
                buf += size;
                from = 0;
        }
-       return err;
+       return -EINVAL;
 }
 
 static int
@@ -141,211 +153,185 @@ concat_write(struct mtd_info *mtd, loff_t to, size_t len,
 }
 
 static int
-concat_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
-               size_t * retlen, u_char * buf, u_char * eccbuf,
-               struct nand_oobinfo *oobsel)
+concat_writev(struct mtd_info *mtd, const struct kvec *vecs,
+               unsigned long count, loff_t to, size_t * retlen)
 {
        struct mtd_concat *concat = CONCAT(mtd);
-       int err = -EINVAL;
+       struct kvec *vecs_copy;
+       unsigned long entry_low, entry_high;
+       size_t total_len = 0;
        int i;
+       int err = -EINVAL;
 
-       *retlen = 0;
-
-       for (i = 0; i < concat->num_subdev; i++) {
-               struct mtd_info *subdev = concat->subdev[i];
-               size_t size, retsize;
-
-               if (from >= subdev->size) {
-                       /* Not destined for this subdev */
-                       size = 0;
-                       from -= subdev->size;
-                       continue;
-               }
-
-               if (from + len > subdev->size)
-                       /* First part goes into this subdev */
-                       size = subdev->size - from;
-               else
-                       /* Entire transaction goes into this subdev */
-                       size = len;
+       if (!(mtd->flags & MTD_WRITEABLE))
+               return -EROFS;
 
-               if (subdev->read_ecc)
-                       err = subdev->read_ecc(subdev, from, size,
-                                              &retsize, buf, eccbuf, oobsel);
-               else
-                       err = -EINVAL;
+       *retlen = 0;
 
-               if (err)
-                       break;
+       /* Calculate total length of data */
+       for (i = 0; i < count; i++)
+               total_len += vecs[i].iov_len;
 
-               *retlen += retsize;
-               len -= size;
-               if (len == 0)
-                       break;
+       /* Do not allow write past end of device */
+       if ((to + total_len) > mtd->size)
+               return -EINVAL;
 
-               err = -EINVAL;
-               buf += size;
-               if (eccbuf) {
-                       eccbuf += subdev->oobsize;
-                       /* in nand.c at least, eccbufs are
-                          tagged with 2 (int)eccstatus'; we
-                          must account for these */
-                       eccbuf += 2 * (sizeof (int));
-               }
-               from = 0;
+       /* Check alignment */
+       if (mtd->writesize > 1) {
+               loff_t __to = to;
+               if (do_div(__to, mtd->writesize) || (total_len % mtd->writesize))
+                       return -EINVAL;
        }
-       return err;
-}
 
-static int
-concat_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
-                size_t * retlen, const u_char * buf, u_char * eccbuf,
-                struct nand_oobinfo *oobsel)
-{
-       struct mtd_concat *concat = CONCAT(mtd);
-       int err = -EINVAL;
-       int i;
-
-       if (!(mtd->flags & MTD_WRITEABLE))
-               return -EROFS;
-
-       *retlen = 0;
+       /* make a copy of vecs */
+       vecs_copy = kmalloc(sizeof(struct kvec) * count, GFP_KERNEL);
+       if (!vecs_copy)
+               return -ENOMEM;
+       memcpy(vecs_copy, vecs, sizeof(struct kvec) * count);
 
+       entry_low = 0;
        for (i = 0; i < concat->num_subdev; i++) {
                struct mtd_info *subdev = concat->subdev[i];
-               size_t size, retsize;
+               size_t size, wsize, retsize, old_iov_len;
 
                if (to >= subdev->size) {
-                       size = 0;
                        to -= subdev->size;
                        continue;
                }
-               if (to + len > subdev->size)
-                       size = subdev->size - to;
-               else
-                       size = len;
+
+               size = min(total_len, (size_t)(subdev->size - to));
+               wsize = size; /* store for future use */
+
+               entry_high = entry_low;
+               while (entry_high < count) {
+                       if (size <= vecs_copy[entry_high].iov_len)
+                               break;
+                       size -= vecs_copy[entry_high++].iov_len;
+               }
+
+               old_iov_len = vecs_copy[entry_high].iov_len;
+               vecs_copy[entry_high].iov_len = size;
 
                if (!(subdev->flags & MTD_WRITEABLE))
                        err = -EROFS;
-               else if (subdev->write_ecc)
-                       err = subdev->write_ecc(subdev, to, size,
-                                               &retsize, buf, eccbuf, oobsel);
                else
-                       err = -EINVAL;
+                       err = subdev->writev(subdev, &vecs_copy[entry_low],
+                               entry_high - entry_low + 1, to, &retsize);
+
+               vecs_copy[entry_high].iov_len = old_iov_len - size;
+               vecs_copy[entry_high].iov_base += size;
+
+               entry_low = entry_high;
 
                if (err)
                        break;
 
                *retlen += retsize;
-               len -= size;
-               if (len == 0)
+               total_len -= wsize;
+
+               if (total_len == 0)
                        break;
 
                err = -EINVAL;
-               buf += size;
-               if (eccbuf)
-                       eccbuf += subdev->oobsize;
                to = 0;
        }
+
+       kfree(vecs_copy);
        return err;
 }
 
 static int
-concat_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
-               size_t * retlen, u_char * buf)
+concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 {
        struct mtd_concat *concat = CONCAT(mtd);
-       int err = -EINVAL;
-       int i;
+       struct mtd_oob_ops devops = *ops;
+       int i, err, ret = 0;
 
-       *retlen = 0;
+       ops->retlen = 0;
 
        for (i = 0; i < concat->num_subdev; i++) {
                struct mtd_info *subdev = concat->subdev[i];
-               size_t size, retsize;
 
                if (from >= subdev->size) {
-                       /* Not destined for this subdev */
-                       size = 0;
                        from -= subdev->size;
                        continue;
                }
-               if (from + len > subdev->size)
-                       /* First part goes into this subdev */
-                       size = subdev->size - from;
-               else
-                       /* Entire transaction goes into this subdev */
-                       size = len;
 
-               if (subdev->read_oob)
-                       err = subdev->read_oob(subdev, from, size,
-                                              &retsize, buf);
-               else
-                       err = -EINVAL;
+               /* partial read ? */
+               if (from + devops.len > subdev->size)
+                       devops.len = subdev->size - from;
+
+               err = subdev->read_oob(subdev, from, &devops);
+               ops->retlen += devops.retlen;
+
+               /* Save information about bitflips! */
+               if (unlikely(err)) {
+                       if (err == -EBADMSG) {
+                               mtd->ecc_stats.failed++;
+                               ret = err;
+                       } else if (err == -EUCLEAN) {
+                               mtd->ecc_stats.corrected++;
+                               /* Do not overwrite -EBADMSG !! */
+                               if (!ret)
+                                       ret = err;
+                       } else
+                               return err;
+               }
 
-               if (err)
-                       break;
+               devops.len = ops->len - ops->retlen;
+               if (!devops.len)
+                       return ret;
 
-               *retlen += retsize;
-               len -= size;
-               if (len == 0)
-                       break;
+               if (devops.datbuf)
+                       devops.datbuf += devops.retlen;
+               if (devops.oobbuf)
+                       devops.oobbuf += devops.ooblen;
 
-               err = -EINVAL;
-               buf += size;
                from = 0;
        }
-       return err;
+       return -EINVAL;
 }
 
 static int
-concat_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
-                size_t * retlen, const u_char * buf)
+concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
 {
        struct mtd_concat *concat = CONCAT(mtd);
-       int err = -EINVAL;
-       int i;
+       struct mtd_oob_ops devops = *ops;
+       int i, err;
 
        if (!(mtd->flags & MTD_WRITEABLE))
                return -EROFS;
 
-       *retlen = 0;
+       ops->retlen = 0;
 
        for (i = 0; i < concat->num_subdev; i++) {
                struct mtd_info *subdev = concat->subdev[i];
-               size_t size, retsize;
 
                if (to >= subdev->size) {
-                       size = 0;
                        to -= subdev->size;
                        continue;
                }
-               if (to + len > subdev->size)
-                       size = subdev->size - to;
-               else
-                       size = len;
 
-               if (!(subdev->flags & MTD_WRITEABLE))
-                       err = -EROFS;
-               else if (subdev->write_oob)
-                       err = subdev->write_oob(subdev, to, size, &retsize,
-                                               buf);
-               else
-                       err = -EINVAL;
+               /* partial write ? */
+               if (to + devops.len > subdev->size)
+                       devops.len = subdev->size - to;
 
+               err = subdev->write_oob(subdev, to, &devops);
+               ops->retlen += devops.retlen;
                if (err)
-                       break;
+                       return err;
 
-               *retlen += retsize;
-               len -= size;
-               if (len == 0)
-                       break;
+               devops.len = ops->len - ops->retlen;
+               if (!devops.len)
+                       return 0;
 
-               err = -EINVAL;
-               buf += size;
+               if (devops.datbuf)
+                       devops.datbuf += devops.retlen;
+               if (devops.oobbuf)
+                       devops.oobbuf += devops.ooblen;
                to = 0;
        }
-       return err;
+       return -EINVAL;
 }
 
 static void concat_erase_callback(struct erase_info *instr)
@@ -636,6 +622,60 @@ static void concat_resume(struct mtd_info *mtd)
        }
 }
 
+static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
+       struct mtd_concat *concat = CONCAT(mtd);
+       int i, res = 0;
+
+       if (!concat->subdev[0]->block_isbad)
+               return res;
+
+       if (ofs > mtd->size)
+               return -EINVAL;
+
+       for (i = 0; i < concat->num_subdev; i++) {
+               struct mtd_info *subdev = concat->subdev[i];
+
+               if (ofs >= subdev->size) {
+                       ofs -= subdev->size;
+                       continue;
+               }
+
+               res = subdev->block_isbad(subdev, ofs);
+               break;
+       }
+
+       return res;
+}
+
+static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+       struct mtd_concat *concat = CONCAT(mtd);
+       int i, err = -EINVAL;
+
+       if (!concat->subdev[0]->block_markbad)
+               return 0;
+
+       if (ofs > mtd->size)
+               return -EINVAL;
+
+       for (i = 0; i < concat->num_subdev; i++) {
+               struct mtd_info *subdev = concat->subdev[i];
+
+               if (ofs >= subdev->size) {
+                       ofs -= subdev->size;
+                       continue;
+               }
+
+               err = subdev->block_markbad(subdev, ofs);
+               if (!err)
+                       mtd->ecc_stats.badblocks++;
+               break;
+       }
+
+       return err;
+}
+
 /*
  * This function constructs a virtual MTD device by concatenating
  * num_devs MTD devices. A pointer to the new device object is
@@ -677,18 +717,22 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],     /* subdevices to c
        concat->mtd.flags = subdev[0]->flags;
        concat->mtd.size = subdev[0]->size;
        concat->mtd.erasesize = subdev[0]->erasesize;
-       concat->mtd.oobblock = subdev[0]->oobblock;
+       concat->mtd.writesize = subdev[0]->writesize;
        concat->mtd.oobsize = subdev[0]->oobsize;
        concat->mtd.ecctype = subdev[0]->ecctype;
        concat->mtd.eccsize = subdev[0]->eccsize;
-       if (subdev[0]->read_ecc)
-               concat->mtd.read_ecc = concat_read_ecc;
-       if (subdev[0]->write_ecc)
-               concat->mtd.write_ecc = concat_write_ecc;
+       if (subdev[0]->writev)
+               concat->mtd.writev = concat_writev;
        if (subdev[0]->read_oob)
                concat->mtd.read_oob = concat_read_oob;
        if (subdev[0]->write_oob)
                concat->mtd.write_oob = concat_write_oob;
+       if (subdev[0]->block_isbad)
+               concat->mtd.block_isbad = concat_block_isbad;
+       if (subdev[0]->block_markbad)
+               concat->mtd.block_markbad = concat_block_markbad;
+
+       concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
 
        concat->subdev[0] = subdev[0];
 
@@ -717,12 +761,12 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],     /* subdevices to c
                                    subdev[i]->flags & MTD_WRITEABLE;
                }
                concat->mtd.size += subdev[i]->size;
-               if (concat->mtd.oobblock   !=  subdev[i]->oobblock ||
+               concat->mtd.ecc_stats.badblocks +=
+                       subdev[i]->ecc_stats.badblocks;
+               if (concat->mtd.writesize   !=  subdev[i]->writesize ||
                    concat->mtd.oobsize    !=  subdev[i]->oobsize ||
                    concat->mtd.ecctype    !=  subdev[i]->ecctype ||
                    concat->mtd.eccsize    !=  subdev[i]->eccsize ||
-                   !concat->mtd.read_ecc  != !subdev[i]->read_ecc ||
-                   !concat->mtd.write_ecc != !subdev[i]->write_ecc ||
                    !concat->mtd.read_oob  != !subdev[i]->read_oob ||
                    !concat->mtd.write_oob != !subdev[i]->write_oob) {
                        kfree(concat);
@@ -734,14 +778,11 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[],     /* subdevices to c
 
        }
 
+       concat->mtd.ecclayout = subdev[0]->ecclayout;
+
        concat->num_subdev = num_devs;
        concat->mtd.name = name;
 
-       /*
-        * NOTE: for now, we do not provide any readv()/writev() methods
-        *       because they are messy to implement and they are not
-        *       used to a great extent anyway.
-        */
        concat->mtd.erase = concat_erase;
        concat->mtd.read = concat_read;
        concat->mtd.write = concat_write;
index 9905870f56e5e0c6ced0dcb53c5f0d6f8128ee47..16a952dd486a90277580d0eb30493a7bb5fda458 100644 (file)
@@ -47,6 +47,7 @@ int add_mtd_device(struct mtd_info *mtd)
 {
        int i;
 
+       BUG_ON(mtd->writesize == 0);
        mutex_lock(&mtd_table_mutex);
 
        for (i=0; i < MAX_MTD_DEVICES; i++)
@@ -254,37 +255,6 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
        return ret;
 }
 
-
-/* default_mtd_readv - default mtd readv method for MTD devices that dont
- *                    implement their own
- */
-
-int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
-                     unsigned long count, loff_t from, size_t *retlen)
-{
-       unsigned long i;
-       size_t totlen = 0, thislen;
-       int ret = 0;
-
-       if(!mtd->read) {
-               ret = -EIO;
-       } else {
-               for (i=0; i<count; i++) {
-                       if (!vecs[i].iov_len)
-                               continue;
-                       ret = mtd->read(mtd, from, vecs[i].iov_len, &thislen, vecs[i].iov_base);
-                       totlen += thislen;
-                       if (ret || thislen != vecs[i].iov_len)
-                               break;
-                       from += vecs[i].iov_len;
-               }
-       }
-       if (retlen)
-               *retlen = totlen;
-       return ret;
-}
-
-
 EXPORT_SYMBOL(add_mtd_device);
 EXPORT_SYMBOL(del_mtd_device);
 EXPORT_SYMBOL(get_mtd_device);
@@ -292,7 +262,6 @@ EXPORT_SYMBOL(put_mtd_device);
 EXPORT_SYMBOL(register_mtd_user);
 EXPORT_SYMBOL(unregister_mtd_user);
 EXPORT_SYMBOL(default_mtd_writev);
-EXPORT_SYMBOL(default_mtd_readv);
 
 #ifdef CONFIG_PROC_FS
 
index 99395911d26f73577999a62b3808e4456529bb92..77a7123a5c56514b75de1e519a22916add1dd228 100644 (file)
@@ -51,16 +51,21 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
                        size_t *retlen, u_char *buf)
 {
        struct mtd_part *part = PART(mtd);
+       int res;
+
        if (from >= mtd->size)
                len = 0;
        else if (from + len > mtd->size)
                len = mtd->size - from;
-       if (part->master->read_ecc == NULL)
-               return part->master->read (part->master, from + part->offset,
-                                       len, retlen, buf);
-       else
-               return part->master->read_ecc (part->master, from + part->offset,
-                                       len, retlen, buf, NULL, &mtd->oobinfo);
+       res = part->master->read (part->master, from + part->offset,
+                                  len, retlen, buf);
+       if (unlikely(res)) {
+               if (res == -EUCLEAN)
+                       mtd->ecc_stats.corrected++;
+               if (res == -EBADMSG)
+                       mtd->ecc_stats.failed++;
+       }
+       return res;
 }
 
 static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
@@ -74,6 +79,7 @@ static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
        return part->master->point (part->master, from + part->offset,
                                    len, retlen, buf);
 }
+
 static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
 {
        struct mtd_part *part = PART(mtd);
@@ -81,31 +87,25 @@ static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_
        part->master->unpoint (part->master, addr, from + part->offset, len);
 }
 
-
-static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-                       size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel)
+static int part_read_oob(struct mtd_info *mtd, loff_t from,
+                        struct mtd_oob_ops *ops)
 {
        struct mtd_part *part = PART(mtd);
-       if (oobsel == NULL)
-               oobsel = &mtd->oobinfo;
-       if (from >= mtd->size)
-               len = 0;
-       else if (from + len > mtd->size)
-               len = mtd->size - from;
-       return part->master->read_ecc (part->master, from + part->offset,
-                                       len, retlen, buf, eccbuf, oobsel);
-}
+       int res;
 
-static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
-                       size_t *retlen, u_char *buf)
-{
-       struct mtd_part *part = PART(mtd);
        if (from >= mtd->size)
-               len = 0;
-       else if (from + len > mtd->size)
-               len = mtd->size - from;
-       return part->master->read_oob (part->master, from + part->offset,
-                                       len, retlen, buf);
+               return -EINVAL;
+       if (from + ops->len > mtd->size)
+               return -EINVAL;
+       res = part->master->read_oob(part->master, from + part->offset, ops);
+
+       if (unlikely(res)) {
+               if (res == -EUCLEAN)
+                       mtd->ecc_stats.corrected++;
+               if (res == -EBADMSG)
+                       mtd->ecc_stats.failed++;
+       }
+       return res;
 }
 
 static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
@@ -148,44 +148,23 @@ static int part_write (struct mtd_info *mtd, loff_t to, size_t len,
                len = 0;
        else if (to + len > mtd->size)
                len = mtd->size - to;
-       if (part->master->write_ecc == NULL)
-               return part->master->write (part->master, to + part->offset,
-                                       len, retlen, buf);
-       else
-               return part->master->write_ecc (part->master, to + part->offset,
-                                       len, retlen, buf, NULL, &mtd->oobinfo);
-
+       return part->master->write (part->master, to + part->offset,
+                                   len, retlen, buf);
 }
 
-static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
-                       size_t *retlen, const u_char *buf,
-                        u_char *eccbuf, struct nand_oobinfo *oobsel)
+static int part_write_oob(struct mtd_info *mtd, loff_t to,
+                        struct mtd_oob_ops *ops)
 {
        struct mtd_part *part = PART(mtd);
-       if (!(mtd->flags & MTD_WRITEABLE))
-               return -EROFS;
-       if (oobsel == NULL)
-               oobsel = &mtd->oobinfo;
-       if (to >= mtd->size)
-               len = 0;
-       else if (to + len > mtd->size)
-               len = mtd->size - to;
-       return part->master->write_ecc (part->master, to + part->offset,
-                                       len, retlen, buf, eccbuf, oobsel);
-}
 
-static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
-                       size_t *retlen, const u_char *buf)
-{
-       struct mtd_part *part = PART(mtd);
        if (!(mtd->flags & MTD_WRITEABLE))
                return -EROFS;
+
        if (to >= mtd->size)
-               len = 0;
-       else if (to + len > mtd->size)
-               len = mtd->size - to;
-       return part->master->write_oob (part->master, to + part->offset,
-                                       len, retlen, buf);
+               return -EINVAL;
+       if (to + ops->len > mtd->size)
+               return -EINVAL;
+       return part->master->write_oob(part->master, to + part->offset, ops);
 }
 
 static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
@@ -208,52 +187,8 @@ static int part_writev (struct mtd_info *mtd,  const struct kvec *vecs,
        struct mtd_part *part = PART(mtd);
        if (!(mtd->flags & MTD_WRITEABLE))
                return -EROFS;
-       if (part->master->writev_ecc == NULL)
-               return part->master->writev (part->master, vecs, count,
+       return part->master->writev (part->master, vecs, count,
                                        to + part->offset, retlen);
-       else
-               return part->master->writev_ecc (part->master, vecs, count,
-                                       to + part->offset, retlen,
-                                       NULL, &mtd->oobinfo);
-}
-
-static int part_readv (struct mtd_info *mtd,  struct kvec *vecs,
-                        unsigned long count, loff_t from, size_t *retlen)
-{
-       struct mtd_part *part = PART(mtd);
-       if (part->master->readv_ecc == NULL)
-               return part->master->readv (part->master, vecs, count,
-                                       from + part->offset, retlen);
-       else
-               return part->master->readv_ecc (part->master, vecs, count,
-                                       from + part->offset, retlen,
-                                       NULL, &mtd->oobinfo);
-}
-
-static int part_writev_ecc (struct mtd_info *mtd,  const struct kvec *vecs,
-                        unsigned long count, loff_t to, size_t *retlen,
-                        u_char *eccbuf,  struct nand_oobinfo *oobsel)
-{
-       struct mtd_part *part = PART(mtd);
-       if (!(mtd->flags & MTD_WRITEABLE))
-               return -EROFS;
-       if (oobsel == NULL)
-               oobsel = &mtd->oobinfo;
-       return part->master->writev_ecc (part->master, vecs, count,
-                                       to + part->offset, retlen,
-                                       eccbuf, oobsel);
-}
-
-static int part_readv_ecc (struct mtd_info *mtd,  struct kvec *vecs,
-                        unsigned long count, loff_t from, size_t *retlen,
-                        u_char *eccbuf,  struct nand_oobinfo *oobsel)
-{
-       struct mtd_part *part = PART(mtd);
-       if (oobsel == NULL)
-               oobsel = &mtd->oobinfo;
-       return part->master->readv_ecc (part->master, vecs, count,
-                                       from + part->offset, retlen,
-                                       eccbuf, oobsel);
 }
 
 static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
@@ -329,12 +264,17 @@ static int part_block_isbad (struct mtd_info *mtd, loff_t ofs)
 static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
 {
        struct mtd_part *part = PART(mtd);
+       int res;
+
        if (!(mtd->flags & MTD_WRITEABLE))
                return -EROFS;
        if (ofs >= mtd->size)
                return -EINVAL;
        ofs += part->offset;
-       return part->master->block_markbad(part->master, ofs);
+       res = part->master->block_markbad(part->master, ofs);
+       if (!res)
+               mtd->ecc_stats.badblocks++;
+       return res;
 }
 
 /*
@@ -398,7 +338,7 @@ int add_mtd_partitions(struct mtd_info *master,
                slave->mtd.type = master->type;
                slave->mtd.flags = master->flags & ~parts[i].mask_flags;
                slave->mtd.size = parts[i].size;
-               slave->mtd.oobblock = master->oobblock;
+               slave->mtd.writesize = master->writesize;
                slave->mtd.oobsize = master->oobsize;
                slave->mtd.ecctype = master->ecctype;
                slave->mtd.eccsize = master->eccsize;
@@ -415,10 +355,6 @@ int add_mtd_partitions(struct mtd_info *master,
                        slave->mtd.unpoint = part_unpoint;
                }
 
-               if (master->read_ecc)
-                       slave->mtd.read_ecc = part_read_ecc;
-               if (master->write_ecc)
-                       slave->mtd.write_ecc = part_write_ecc;
                if (master->read_oob)
                        slave->mtd.read_oob = part_read_oob;
                if (master->write_oob)
@@ -443,12 +379,6 @@ int add_mtd_partitions(struct mtd_info *master,
                }
                if (master->writev)
                        slave->mtd.writev = part_writev;
-               if (master->readv)
-                       slave->mtd.readv = part_readv;
-               if (master->writev_ecc)
-                       slave->mtd.writev_ecc = part_writev_ecc;
-               if (master->readv_ecc)
-                       slave->mtd.readv_ecc = part_readv_ecc;
                if (master->lock)
                        slave->mtd.lock = part_lock;
                if (master->unlock)
@@ -528,8 +458,17 @@ int add_mtd_partitions(struct mtd_info *master,
                                parts[i].name);
                }
 
-               /* copy oobinfo from master */
-               memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo));
+               slave->mtd.ecclayout = master->ecclayout;
+               if (master->block_isbad) {
+                       uint32_t offs = 0;
+
+                       while(offs < slave->mtd.size) {
+                               if (master->block_isbad(master,
+                                                       offs + slave->offset))
+                                       slave->mtd.ecc_stats.badblocks++;
+                               offs += slave->mtd.erasesize;
+                       }
+               }
 
                if(parts[i].mtdp)
                {       /* store the object pointer (caller may or may not register it */
index cfe288a6e85358b2a639e779aef1dc0f84928c79..3db77eec0ed2539031c807732858dda2a21c39fc 100644 (file)
@@ -23,6 +23,14 @@ config MTD_NAND_VERIFY_WRITE
          device thinks the write was successful, a bit could have been
          flipped accidentaly due to device wear or something else.
 
+config MTD_NAND_ECC_SMC
+       bool "NAND ECC Smart Media byte order"
+       depends on MTD_NAND
+       default n
+       help
+         Software ECC according to the Smart Media Specification.
+         The original Linux implementation had byte 0 and 1 swapped.
+
 config MTD_NAND_AUTCPU12
        tristate "SmartMediaCard on autronix autcpu12 board"
        depends on MTD_NAND && ARCH_AUTCPU12
@@ -49,12 +57,24 @@ config MTD_NAND_SPIA
        help
          If you had to ask, you don't have one. Say 'N'.
 
+config MTD_NAND_AMS_DELTA
+       tristate "NAND Flash device on Amstrad E3"
+       depends on MACH_AMS_DELTA && MTD_NAND
+       help
+         Support for NAND flash on Amstrad E3 (Delta).
+
 config MTD_NAND_TOTO
        tristate "NAND Flash device on TOTO board"
-       depends on ARCH_OMAP && MTD_NAND
+       depends on ARCH_OMAP && MTD_NAND && BROKEN
        help
          Support for NAND flash on Texas Instruments Toto platform.
 
+config MTD_NAND_TS7250
+       tristate "NAND Flash device on TS-7250 board"
+       depends on MACH_TS72XX && MTD_NAND
+       help
+         Support for NAND flash on Technologic Systems TS-7250 platform.
+
 config MTD_NAND_IDS
        tristate
 
@@ -76,7 +96,7 @@ config MTD_NAND_RTC_FROM4
 
 config MTD_NAND_PPCHAMELEONEVB
        tristate "NAND Flash device on PPChameleonEVB board"
-       depends on PPCHAMELEONEVB && MTD_NAND
+       depends on PPCHAMELEONEVB && MTD_NAND && BROKEN
        help
          This enables the NAND flash driver on the PPChameleon EVB Board.
 
@@ -87,7 +107,7 @@ config MTD_NAND_S3C2410
          This enables the NAND flash controller on the S3C2410 and S3C2440
          SoCs
 
-         No board specfic support is done by this driver, each board
+         No board specific support is done by this driver, each board
          must advertise a platform_device for the driver to attach.
 
 config MTD_NAND_S3C2410_DEBUG
@@ -109,6 +129,22 @@ config MTD_NAND_S3C2410_HWECC
          currently not be able to switch to software, as there is no
          implementation for ECC method used by the S3C2410
 
+config MTD_NAND_NDFC
+       tristate "NDFC NanD Flash Controller"
+       depends on MTD_NAND && 44x
+       help
+        NDFC Nand Flash Controllers are integrated in EP44x SoCs
+
+config MTD_NAND_S3C2410_CLKSTOP
+       bool "S3C2410 NAND IDLE clock stop"
+       depends on MTD_NAND_S3C2410
+       default n
+       help
+         Stop the clock to the NAND controller when there is no chip
+         selected to save power. This will mean there is a small delay
+         when the is NAND chip selected or released, but will save
+         approximately 5mA of power when there is nothing happening.
+
 config MTD_NAND_DISKONCHIP
        tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
        depends on MTD_NAND && EXPERIMENTAL
@@ -183,11 +219,24 @@ config MTD_NAND_SHARPSL
        tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
        depends on MTD_NAND && ARCH_PXA
 
+config MTD_NAND_CS553X
+       tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
+       depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH)
+       help
+         The CS553x companion chips for the AMD Geode processor
+         include NAND flash controllers with built-in hardware ECC
+         capabilities; enabling this option will allow you to use
+         these. The driver will check the MSRs to verify that the
+         controller is enabled for NAND, and currently requires that
+         the controller be in MMIO mode.
+
+         If you say "m", the module will be called "cs553x_nand.ko".
+
 config MTD_NAND_NANDSIM
        tristate "Support for NAND Flash Simulator"
        depends on MTD_NAND && MTD_PARTITIONS
        help
-         The simulator may simulate verious NAND flash chips for the
+         The simulator may simulate various NAND flash chips for the
          MTD nand layer.
 
 endmenu
index 41742026a52e7e45033f8a37ef57d7b0222c55df..f74759351c912a2fd3d7d4cb840e44f428e5fd5f 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_MTD_NAND)                  += nand.o nand_ecc.o
 obj-$(CONFIG_MTD_NAND_IDS)             += nand_ids.o
 
 obj-$(CONFIG_MTD_NAND_SPIA)            += spia.o
+obj-$(CONFIG_MTD_NAND_AMS_DELTA)       += ams-delta.o
 obj-$(CONFIG_MTD_NAND_TOTO)            += toto.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)                += autcpu12.o
 obj-$(CONFIG_MTD_NAND_EDB7312)         += edb7312.o
@@ -17,6 +18,9 @@ obj-$(CONFIG_MTD_NAND_DISKONCHIP)     += diskonchip.o
 obj-$(CONFIG_MTD_NAND_H1900)           += h1910.o
 obj-$(CONFIG_MTD_NAND_RTC_FROM4)       += rtc_from4.o
 obj-$(CONFIG_MTD_NAND_SHARPSL)         += sharpsl.o
+obj-$(CONFIG_MTD_NAND_TS7250)          += ts7250.o
 obj-$(CONFIG_MTD_NAND_NANDSIM)         += nandsim.o
+obj-$(CONFIG_MTD_NAND_CS553X)          += cs553x_nand.o
+obj-$(CONFIG_MTD_NAND_NDFC)            += ndfc.o
 
 nand-objs = nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
new file mode 100644 (file)
index 0000000..d7897dc
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ *  drivers/mtd/nand/ams-delta.c
+ *
+ *  Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ *  Derived from drivers/mtd/toto.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.
+ *
+ *  Overview:
+ *   This is a device driver for the NAND flash device found on the
+ *   Amstrad E3 (Delta).
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/sizes.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/board-ams-delta.h>
+
+/*
+ * MTD structure for E3 (Delta)
+ */
+static struct mtd_info *ams_delta_mtd = NULL;
+
+#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP)
+
+/*
+ * Define partitions for flash devices
+ */
+
+static struct mtd_partition partition_info[] = {
+       { .name         = "Kernel",
+         .offset       = 0,
+         .size         = 3 * SZ_1M + SZ_512K },
+       { .name         = "u-boot",
+         .offset       = 3 * SZ_1M + SZ_512K,
+         .size         = SZ_256K },
+       { .name         = "u-boot params",
+         .offset       = 3 * SZ_1M + SZ_512K + SZ_256K,
+         .size         = SZ_256K },
+       { .name         = "Amstrad LDR",
+         .offset       = 4 * SZ_1M,
+         .size         = SZ_256K },
+       { .name         = "File system",
+         .offset       = 4 * SZ_1M + 1 * SZ_256K,
+         .size         = 27 * SZ_1M },
+       { .name         = "PBL reserved",
+         .offset       = 32 * SZ_1M - 3 * SZ_256K,
+         .size         =  3 * SZ_256K },
+};
+
+static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
+{
+       struct nand_chip *this = mtd->priv;
+
+       omap_writew(0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
+       omap_writew(byte, this->IO_ADDR_W);
+       ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0);
+       ndelay(40);
+       ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE,
+                              AMS_DELTA_LATCH2_NAND_NWE);
+}
+
+static u_char ams_delta_read_byte(struct mtd_info *mtd)
+{
+       u_char res;
+       struct nand_chip *this = mtd->priv;
+
+       ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0);
+       ndelay(40);
+       omap_writew(~0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
+       res = omap_readw(this->IO_ADDR_R);
+       ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE,
+                              AMS_DELTA_LATCH2_NAND_NRE);
+
+       return res;
+}
+
+static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
+                               int len)
+{
+       int i;
+
+       for (i=0; i<len; i++)
+               ams_delta_write_byte(mtd, buf[i]);
+}
+
+static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+       int i;
+
+       for (i=0; i<len; i++)
+               buf[i] = ams_delta_read_byte(mtd);
+}
+
+static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf,
+                               int len)
+{
+       int i;
+
+       for (i=0; i<len; i++)
+               if (buf[i] != ams_delta_read_byte(mtd))
+                       return -EFAULT;
+
+       return 0;
+}
+
+/*
+ * Command control function
+ *
+ * ctrl:
+ * NAND_NCE: bit 0 -> bit 2
+ * NAND_CLE: bit 1 -> bit 7
+ * NAND_ALE: bit 2 -> bit 6
+ */
+static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
+                               unsigned int ctrl)
+{
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               unsigned long bits;
+
+               bits = (~ctrl & NAND_NCE) << 2;
+               bits |= (ctrl & NAND_CLE) << 7;
+               bits |= (ctrl & NAND_ALE) << 6;
+
+               ams_delta_latch2_write(0xC2, bits);
+       }
+
+       if (cmd != NAND_CMD_NONE)
+               ams_delta_write_byte(mtd, cmd);
+}
+
+static int ams_delta_nand_ready(struct mtd_info *mtd)
+{
+       return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB);
+}
+
+/*
+ * Main initialization routine
+ */
+static int __init ams_delta_init(void)
+{
+       struct nand_chip *this;
+       int err = 0;
+
+       /* Allocate memory for MTD device structure and private data */
+       ams_delta_mtd = kmalloc(sizeof(struct mtd_info) +
+                               sizeof(struct nand_chip), GFP_KERNEL);
+       if (!ams_delta_mtd) {
+               printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n");
+               err = -ENOMEM;
+               goto out;
+       }
+
+       ams_delta_mtd->owner = THIS_MODULE;
+
+       /* Get pointer to private data */
+       this = (struct nand_chip *) (&ams_delta_mtd[1]);
+
+       /* Initialize structures */
+       memset(ams_delta_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
+
+       /* Link the private data with the MTD structure */
+       ams_delta_mtd->priv = this;
+
+       /* Set address of NAND IO lines */
+       this->IO_ADDR_R = (OMAP_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH);
+       this->IO_ADDR_W = (OMAP_MPUIO_BASE + OMAP_MPUIO_OUTPUT);
+       this->read_byte = ams_delta_read_byte;
+       this->write_buf = ams_delta_write_buf;
+       this->read_buf = ams_delta_read_buf;
+       this->verify_buf = ams_delta_verify_buf;
+       this->cmd_ctrl = ams_delta_hwcontrol;
+       if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) {
+               this->dev_ready = ams_delta_nand_ready;
+       } else {
+               this->dev_ready = NULL;
+               printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n");
+       }
+       /* 25 us command delay time */
+       this->chip_delay = 30;
+       this->ecc.mode = NAND_ECC_SOFT;
+
+       /* Set chip enabled, but  */
+       ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |
+                                         AMS_DELTA_LATCH2_NAND_NWE |
+                                         AMS_DELTA_LATCH2_NAND_NCE |
+                                         AMS_DELTA_LATCH2_NAND_NWP);
+
+       /* Scan to find existance of the device */
+       if (nand_scan(ams_delta_mtd, 1)) {
+               err = -ENXIO;
+               goto out_mtd;
+       }
+
+       /* Register the partitions */
+       add_mtd_partitions(ams_delta_mtd, partition_info,
+                          ARRAY_SIZE(partition_info));
+
+       goto out;
+
+ out_mtd:
+       kfree(ams_delta_mtd);
+ out:
+       return err;
+}
+
+module_init(ams_delta_init);
+
+/*
+ * Clean up routine
+ */
+static void __exit ams_delta_cleanup(void)
+{
+       /* Release resources, unregister device */
+       nand_release(ams_delta_mtd);
+
+       /* Free the MTD device structure */
+       kfree(ams_delta_mtd);
+}
+module_exit(ams_delta_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
+MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)");
index bde3550910a2e12626b7255e23a92982776a8668..31228334da12425dbfe18f2cc3155894aaaf34a5 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/interrupt.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
  */
 static struct mtd_info *au1550_mtd = NULL;
 static void __iomem *p_nand;
-static int nand_width = 1; /* default x8*/
+static int nand_width = 1;     /* default x8 */
+static void (*au1550_write_byte)(struct mtd_info *, u_char);
 
 /*
  * Define partitions for flash device
  */
 static const struct mtd_partition partition_info[] = {
        {
-               .name   = "NAND FS 0",
-               .offset = 0,
-               .size   = 8*1024*1024
-       },
+        .name = "NAND FS 0",
+        .offset = 0,
+        .size = 8 * 1024 * 1024},
        {
-               .name   = "NAND FS 1",
-               .offset =  MTDPART_OFS_APPEND,
-               .size   =    MTDPART_SIZ_FULL
-       }
+        .name = "NAND FS 1",
+        .offset = MTDPART_OFS_APPEND,
+        .size = MTDPART_SIZ_FULL}
 };
 
 /**
@@ -129,21 +129,6 @@ static u16 au_read_word(struct mtd_info *mtd)
        return ret;
 }
 
-/**
- * au_write_word -  write one word to the chip
- * @mtd:       MTD device structure
- * @word:      data word to write
- *
- *  write function for 16bit buswith without
- * endianess conversion
- */
-static void au_write_word(struct mtd_info *mtd, u16 word)
-{
-       struct nand_chip *this = mtd->priv;
-       writew(word, this->IO_ADDR_W);
-       au_sync();
-}
-
 /**
  * au_write_buf -  write buffer to chip
  * @mtd:       MTD device structure
@@ -157,7 +142,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
        int i;
        struct nand_chip *this = mtd->priv;
 
-       for (i=0; i<len; i++) {
+       for (i = 0; i < len; i++) {
                writeb(buf[i], this->IO_ADDR_W);
                au_sync();
        }
@@ -176,7 +161,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
        int i;
        struct nand_chip *this = mtd->priv;
 
-       for (i=0; i<len; i++) {
+       for (i = 0; i < len; i++) {
                buf[i] = readb(this->IO_ADDR_R);
                au_sync();
        }
@@ -195,7 +180,7 @@ static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
        int i;
        struct nand_chip *this = mtd->priv;
 
-       for (i=0; i<len; i++) {
+       for (i = 0; i < len; i++) {
                if (buf[i] != readb(this->IO_ADDR_R))
                        return -EFAULT;
                au_sync();
@@ -219,7 +204,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
        u16 *p = (u16 *) buf;
        len >>= 1;
 
-       for (i=0; i<len; i++) {
+       for (i = 0; i < len; i++) {
                writew(p[i], this->IO_ADDR_W);
                au_sync();
        }
@@ -241,7 +226,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
        u16 *p = (u16 *) buf;
        len >>= 1;
 
-       for (i=0; i<len; i++) {
+       for (i = 0; i < len; i++) {
                p[i] = readw(this->IO_ADDR_R);
                au_sync();
        }
@@ -262,7 +247,7 @@ static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
        u16 *p = (u16 *) buf;
        len >>= 1;
 
-       for (i=0; i<len; i++) {
+       for (i = 0; i < len; i++) {
                if (p[i] != readw(this->IO_ADDR_R))
                        return -EFAULT;
                au_sync();
@@ -270,32 +255,52 @@ static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
        return 0;
 }
 
+/* Select the chip by setting nCE to low */
+#define NAND_CTL_SETNCE                1
+/* Deselect the chip by setting nCE to high */
+#define NAND_CTL_CLRNCE                2
+/* Select the command latch by setting CLE to high */
+#define NAND_CTL_SETCLE                3
+/* Deselect the command latch by setting CLE to low */
+#define NAND_CTL_CLRCLE                4
+/* Select the address latch by setting ALE to high */
+#define NAND_CTL_SETALE                5
+/* Deselect the address latch by setting ALE to low */
+#define NAND_CTL_CLRALE                6
 
 static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
 {
        register struct nand_chip *this = mtd->priv;
 
-       switch(cmd){
+       switch (cmd) {
 
-       case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break;
-       case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break;
+       case NAND_CTL_SETCLE:
+               this->IO_ADDR_W = p_nand + MEM_STNAND_CMD;
+               break;
+
+       case NAND_CTL_CLRCLE:
+               this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
+               break;
+
+       case NAND_CTL_SETALE:
+               this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR;
+               break;
 
-       case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break;
        case NAND_CTL_CLRALE:
                this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
-               /* FIXME: Nobody knows why this is neccecary,
+               /* FIXME: Nobody knows why this is necessary,
                 * but it works only that way */
                udelay(1);
                break;
 
        case NAND_CTL_SETNCE:
                /* assert (force assert) chip enable */
-               au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break;
+               au_writel((1 << (4 + NAND_CS)), MEM_STNDCTL);
                break;
 
        case NAND_CTL_CLRNCE:
-               /* deassert chip enable */
-               au_writel(0, MEM_STNDCTL); break;
+               /* deassert chip enable */
+               au_writel(0, MEM_STNDCTL);
                break;
        }
 
@@ -312,69 +317,200 @@ int au1550_device_ready(struct mtd_info *mtd)
        return ret;
 }
 
+/**
+ * au1550_select_chip - control -CE line
+ *     Forbid driving -CE manually permitting the NAND controller to do this.
+ *     Keeping -CE asserted during the whole sector reads interferes with the
+ *     NOR flash and PCMCIA drivers as it causes contention on the static bus.
+ *     We only have to hold -CE low for the NAND read commands since the flash
+ *     chip needs it to be asserted during chip not ready time but the NAND
+ *     controller keeps it released.
+ *
+ * @mtd:       MTD device structure
+ * @chip:      chipnumber to select, -1 for deselect
+ */
+static void au1550_select_chip(struct mtd_info *mtd, int chip)
+{
+}
+
+/**
+ * au1550_command - Send command to NAND device
+ * @mtd:       MTD device structure
+ * @command:   the command to be sent
+ * @column:    the column address for this command, -1 if none
+ * @page_addr: the page address for this command, -1 if none
+ */
+static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
+{
+       register struct nand_chip *this = mtd->priv;
+       int ce_override = 0, i;
+       ulong flags;
+
+       /* Begin command latch cycle */
+       au1550_hwcontrol(mtd, NAND_CTL_SETCLE);
+       /*
+        * Write out the command to the device.
+        */
+       if (command == NAND_CMD_SEQIN) {
+               int readcmd;
+
+               if (column >= mtd->writesize) {
+                       /* OOB area */
+                       column -= mtd->writesize;
+                       readcmd = NAND_CMD_READOOB;
+               } else if (column < 256) {
+                       /* First 256 bytes --> READ0 */
+                       readcmd = NAND_CMD_READ0;
+               } else {
+                       column -= 256;
+                       readcmd = NAND_CMD_READ1;
+               }
+               au1550_write_byte(mtd, readcmd);
+       }
+       au1550_write_byte(mtd, command);
+
+       /* Set ALE and clear CLE to start address cycle */
+       au1550_hwcontrol(mtd, NAND_CTL_CLRCLE);
+
+       if (column != -1 || page_addr != -1) {
+               au1550_hwcontrol(mtd, NAND_CTL_SETALE);
+
+               /* Serially input address */
+               if (column != -1) {
+                       /* Adjust columns for 16 bit buswidth */
+                       if (this->options & NAND_BUSWIDTH_16)
+                               column >>= 1;
+                       au1550_write_byte(mtd, column);
+               }
+               if (page_addr != -1) {
+                       au1550_write_byte(mtd, (u8)(page_addr & 0xff));
+
+                       if (command == NAND_CMD_READ0 ||
+                           command == NAND_CMD_READ1 ||
+                           command == NAND_CMD_READOOB) {
+                               /*
+                                * NAND controller will release -CE after
+                                * the last address byte is written, so we'll
+                                * have to forcibly assert it. No interrupts
+                                * are allowed while we do this as we don't
+                                * want the NOR flash or PCMCIA drivers to
+                                * steal our precious bytes of data...
+                                */
+                               ce_override = 1;
+                               local_irq_save(flags);
+                               au1550_hwcontrol(mtd, NAND_CTL_SETNCE);
+                       }
+
+                       au1550_write_byte(mtd, (u8)(page_addr >> 8));
+
+                       /* One more address cycle for devices > 32MiB */
+                       if (this->chipsize > (32 << 20))
+                               au1550_write_byte(mtd, (u8)((page_addr >> 16) & 0x0f));
+               }
+               /* Latch in address */
+               au1550_hwcontrol(mtd, NAND_CTL_CLRALE);
+       }
+
+       /*
+        * Program and erase have their own busy handlers.
+        * Status and sequential in need no delay.
+        */
+       switch (command) {
+
+       case NAND_CMD_PAGEPROG:
+       case NAND_CMD_ERASE1:
+       case NAND_CMD_ERASE2:
+       case NAND_CMD_SEQIN:
+       case NAND_CMD_STATUS:
+               return;
+
+       case NAND_CMD_RESET:
+               break;
+
+       case NAND_CMD_READ0:
+       case NAND_CMD_READ1:
+       case NAND_CMD_READOOB:
+               /* Check if we're really driving -CE low (just in case) */
+               if (unlikely(!ce_override))
+                       break;
+
+               /* Apply a short delay always to ensure that we do wait tWB. */
+               ndelay(100);
+               /* Wait for a chip to become ready... */
+               for (i = this->chip_delay; !this->dev_ready(mtd) && i > 0; --i)
+                       udelay(1);
+
+               /* Release -CE and re-enable interrupts. */
+               au1550_hwcontrol(mtd, NAND_CTL_CLRNCE);
+               local_irq_restore(flags);
+               return;
+       }
+       /* Apply this short delay always to ensure that we do wait tWB. */
+       ndelay(100);
+
+       while(!this->dev_ready(mtd));
+}
+
+
 /*
  * Main initialization routine
  */
-int __init au1xxx_nand_init (void)
+static int __init au1xxx_nand_init(void)
 {
        struct nand_chip *this;
-       u16 boot_swapboot = 0; /* default value */
+       u16 boot_swapboot = 0;  /* default value */
        int retval;
        u32 mem_staddr;
        u32 nand_phys;
 
        /* Allocate memory for MTD device structure and private data */
-       au1550_mtd = kmalloc (sizeof(struct mtd_info) +
-                       sizeof (struct nand_chip), GFP_KERNEL);
+       au1550_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!au1550_mtd) {
-               printk ("Unable to allocate NAND MTD dev structure.\n");
+               printk("Unable to allocate NAND MTD dev structure.\n");
                return -ENOMEM;
        }
 
        /* Get pointer to private data */
-       this = (struct nand_chip *) (&au1550_mtd[1]);
+       this = (struct nand_chip *)(&au1550_mtd[1]);
 
        /* Initialize structures */
-       memset((char *) au1550_mtd, 0, sizeof(struct mtd_info));
-       memset((char *) this, 0, sizeof(struct nand_chip));
+       memset(au1550_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
 
        /* Link the private data with the MTD structure */
        au1550_mtd->priv = this;
+       au1550_mtd->owner = THIS_MODULE;
 
 
-       /* disable interrupts */
-       au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL);
-
-       /* disable NAND boot */
-       au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL);
+       /* MEM_STNDCTL: disable ints, disable nand boot */
+       au_writel(0, MEM_STNDCTL);
 
 #ifdef CONFIG_MIPS_PB1550
        /* set gpio206 high */
-       au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR);
+       au_writel(au_readl(GPIO2_DIR) & ~(1 << 6), GPIO2_DIR);
 
-       boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
-               ((bcsr->status >> 6)  & 0x1);
+       boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr->status >> 6) & 0x1);
        switch (boot_swapboot) {
-               case 0:
-               case 2:
-               case 8:
-               case 0xC:
-               case 0xD:
-                       /* x16 NAND Flash */
-                       nand_width = 0;
-                       break;
-               case 1:
-               case 9:
-               case 3:
-               case 0xE:
-               case 0xF:
-                       /* x8 NAND Flash */
-                       nand_width = 1;
-                       break;
-               default:
-                       printk("Pb1550 NAND: bad boot:swap\n");
-                       retval = -EINVAL;
-                       goto outmem;
+       case 0:
+       case 2:
+       case 8:
+       case 0xC:
+       case 0xD:
+               /* x16 NAND Flash */
+               nand_width = 0;
+               break;
+       case 1:
+       case 9:
+       case 3:
+       case 0xE:
+       case 0xF:
+               /* x8 NAND Flash */
+               nand_width = 1;
+               break;
+       default:
+               printk("Pb1550 NAND: bad boot:swap\n");
+               retval = -EINVAL;
+               goto outmem;
        }
 #endif
 
@@ -424,21 +560,22 @@ int __init au1xxx_nand_init (void)
 
        /* make controller and MTD agree */
        if (NAND_CS == 0)
-               nand_width = au_readl(MEM_STCFG0) & (1<<22);
+               nand_width = au_readl(MEM_STCFG0) & (1 << 22);
        if (NAND_CS == 1)
-               nand_width = au_readl(MEM_STCFG1) & (1<<22);
+               nand_width = au_readl(MEM_STCFG1) & (1 << 22);
        if (NAND_CS == 2)
-               nand_width = au_readl(MEM_STCFG2) & (1<<22);
+               nand_width = au_readl(MEM_STCFG2) & (1 << 22);
        if (NAND_CS == 3)
-               nand_width = au_readl(MEM_STCFG3) & (1<<22);
-
+               nand_width = au_readl(MEM_STCFG3) & (1 << 22);
 
        /* Set address of hardware control function */
-       this->hwcontrol = au1550_hwcontrol;
        this->dev_ready = au1550_device_ready;
+       this->select_chip = au1550_select_chip;
+       this->cmdfunc = au1550_command;
+
        /* 30 us command delay time */
        this->chip_delay = 30;
-       this->eccmode = NAND_ECC_SOFT;
+       this->ecc.mode = NAND_ECC_SOFT;
 
        this->options = NAND_NO_AUTOINCR;
 
@@ -446,15 +583,14 @@ int __init au1xxx_nand_init (void)
                this->options |= NAND_BUSWIDTH_16;
 
        this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte;
-       this->write_byte = (!nand_width) ? au_write_byte16 : au_write_byte;
-       this->write_word = au_write_word;
+       au1550_write_byte = (!nand_width) ? au_write_byte16 : au_write_byte;
        this->read_word = au_read_word;
        this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf;
        this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf;
        this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf;
 
        /* Scan to find existence of the device */
-       if (nand_scan (au1550_mtd, 1)) {
+       if (nand_scan(au1550_mtd, 1)) {
                retval = -ENXIO;
                goto outio;
        }
@@ -465,10 +601,10 @@ int __init au1xxx_nand_init (void)
        return 0;
 
  outio:
-       iounmap ((void *)p_nand);
+       iounmap((void *)p_nand);
 
  outmem:
-       kfree (au1550_mtd);
+       kfree(au1550_mtd);
        return retval;
 }
 
@@ -477,22 +613,21 @@ module_init(au1xxx_nand_init);
 /*
  * Clean up routine
  */
-#ifdef MODULE
-static void __exit au1550_cleanup (void)
+static void __exit au1550_cleanup(void)
 {
-       struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1];
+       struct nand_chip *this = (struct nand_chip *)&au1550_mtd[1];
 
        /* Release resources, unregister device */
-       nand_release (au1550_mtd);
+       nand_release(au1550_mtd);
 
        /* Free the MTD device structure */
-       kfree (au1550_mtd);
+       kfree(au1550_mtd);
 
        /* Unmap */
-       iounmap ((void *)p_nand);
+       iounmap((void *)p_nand);
 }
+
 module_exit(au1550_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Embedded Edge, LLC");
index a3c7fea404d096d84a9cbcdecce88ebfac2ebadf..fe94ae9ae1f22d4feb409100726a4d8dadca5cb7 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
  *
  *  Derived from drivers/mtd/spia.c
- *      Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
+ *      Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
  *
  * $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $
  *
  * MTD structure for AUTCPU12 board
  */
 static struct mtd_info *autcpu12_mtd = NULL;
-
-static int autcpu12_io_base = CS89712_VIRT_BASE;
-static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC;
-static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET;
-static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET;
-static void __iomem * autcpu12_fio_base;
+static void __iomem *autcpu12_fio_base;
 
 /*
  * Define partitions for flash devices
@@ -94,108 +89,131 @@ static struct mtd_partition partition_info128k[] = {
 #define NUM_PARTITIONS128K 2
 /*
  *     hardware specific access to control-lines
-*/
-static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd)
+ *
+ *     ALE bit 4 autcpu12_pedr
+ *     CLE bit 5 autcpu12_pedr
+ *     NCE bit 0 fio_ctrl
+ *
+ */
+static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd,
+                              unsigned int ctrl)
 {
+       struct nand_chip *chip = mtd->priv;
 
-       switch(cmd){
-
-               case NAND_CTL_SETCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |=  AUTCPU12_SMC_CLE; break;
-               case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_CLE; break;
+       if (ctrl & NAND_CTRL_CHANGE) {
+               void __iomem *addr
+               unsigned char bits;
 
-               case NAND_CTL_SETALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |=  AUTCPU12_SMC_ALE; break;
-               case NAND_CTL_CLRALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_ALE; break;
+               addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
+               bits = (ctrl & NAND_CLE) << 4;
+               bits |= (ctrl & NAND_ALE) << 2;
+               writeb((readb(addr) & ~0x30) | bits, addr);
 
-               case NAND_CTL_SETNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x01; break;
-               case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x00; break;
+               addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET;
+               writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr);
        }
+
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, chip->IO_ADDR_W);
 }
 
 /*
-     read device ready pin
-*/
+ *     read device ready pin
+ */
 int autcpu12_device_ready(struct mtd_info *mtd)
 {
+       void __iomem *addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
 
-       return ( (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0;
-
+       return readb(addr) & AUTCPU12_SMC_RDY;
 }
 
 /*
  * Main initialization routine
  */
-int __init autcpu12_init (void)
+static int __init autcpu12_init(void)
 {
        struct nand_chip *this;
        int err = 0;
 
        /* Allocate memory for MTD device structure and private data */
-       autcpu12_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
-                               GFP_KERNEL);
+       autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
+                              GFP_KERNEL);
        if (!autcpu12_mtd) {
-               printk ("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
+               printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
                err = -ENOMEM;
                goto out;
        }
 
        /* map physical adress */
-       autcpu12_fio_base = ioremap(autcpu12_fio_pbase,SZ_1K);
-       if(!autcpu12_fio_base){
+       autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K);
+       if (!autcpu12_fio_base) {
                printk("Ioremap autcpu12 SmartMedia Card failed\n");
                err = -EIO;
                goto out_mtd;
        }
 
        /* Get pointer to private data */
-       this = (struct nand_chip *) (&autcpu12_mtd[1]);
+       this = (struct nand_chip *)(&autcpu12_mtd[1]);
 
        /* Initialize structures */
-       memset((char *) autcpu12_mtd, 0, sizeof(struct mtd_info));
-       memset((char *) this, 0, sizeof(struct nand_chip));
+       memset(autcpu12_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
 
        /* Link the private data with the MTD structure */
        autcpu12_mtd->priv = this;
+       autcpu12_mtd->owner = THIS_MODULE;
 
        /* Set address of NAND IO lines */
        this->IO_ADDR_R = autcpu12_fio_base;
        this->IO_ADDR_W = autcpu12_fio_base;
-       this->hwcontrol = autcpu12_hwcontrol;
+       this->cmd_ctrl = autcpu12_hwcontrol;
        this->dev_ready = autcpu12_device_ready;
        /* 20 us command delay time */
        this->chip_delay = 20;
-       this->eccmode = NAND_ECC_SOFT;
+       this->ecc.mode = NAND_ECC_SOFT;
 
        /* Enable the following for a flash based bad block table */
        /*
-       this->options = NAND_USE_FLASH_BBT;
-       */
+          this->options = NAND_USE_FLASH_BBT;
+        */
        this->options = NAND_USE_FLASH_BBT;
 
        /* Scan to find existance of the device */
-       if (nand_scan (autcpu12_mtd, 1)) {
+       if (nand_scan(autcpu12_mtd, 1)) {
                err = -ENXIO;
                goto out_ior;
        }
 
        /* Register the partitions */
-       switch(autcpu12_mtd->size){
-               case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break;
-               case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break;
-               case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break;
-               case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break;
-               default: {
-                       printk ("Unsupported SmartMedia device\n");
+       switch (autcpu12_mtd->size) {
+               case SZ_16M:
+                       add_mtd_partitions(autcpu12_mtd, partition_info16k,
+                                          NUM_PARTITIONS16K);
+                       break;
+               case SZ_32M:
+                       add_mtd_partitions(autcpu12_mtd, partition_info32k,
+                                          NUM_PARTITIONS32K);
+                       break;
+               case SZ_64M:
+                       add_mtd_partitions(autcpu12_mtd, partition_info64k,
+                                          NUM_PARTITIONS64K);
+                       break;
+               case SZ_128M:
+                       add_mtd_partitions(autcpu12_mtd, partition_info128k,
+                                          NUM_PARTITIONS128K);
+                       break;
+               default:
+                       printk("Unsupported SmartMedia device\n");
                        err = -ENXIO;
                        goto out_ior;
-               }
        }
        goto out;
 
-out_ior:
-       iounmap((void *)autcpu12_fio_base);
-out_mtd:
-       kfree (autcpu12_mtd);
-out:
+ out_ior:
+       iounmap(autcpu12_fio_base);
+ out_mtd:
+       kfree(autcpu12_mtd);
+ out:
        return err;
 }
 
@@ -204,20 +222,19 @@ module_init(autcpu12_init);
 /*
  * Clean up routine
  */
-#ifdef MODULE
-static void __exit autcpu12_cleanup (void)
+static void __exit autcpu12_cleanup(void)
 {
        /* Release resources, unregister device */
-       nand_release (autcpu12_mtd);
+       nand_release(autcpu12_mtd);
 
        /* unmap physical adress */
-       iounmap((void *)autcpu12_fio_base);
+       iounmap(autcpu12_fio_base);
 
        /* Free the MTD device structure */
-       kfree (autcpu12_mtd);
+       kfree(autcpu12_mtd);
 }
+
 module_exit(autcpu12_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
new file mode 100644 (file)
index 0000000..e0a1d38
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * drivers/mtd/nand/cs553x_nand.c
+ *
+ * (C) 2005, 2006 Red Hat Inc.
+ *
+ * Author: David Woodhouse <dwmw2@infradead.org>
+ *        Tom Sylla <tom.sylla@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Overview:
+ *   This is a device driver for the NAND flash controller found on 
+ *   the AMD CS5535/CS5536 companion chipsets for the Geode processor.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/msr.h>
+#include <asm/io.h>
+
+#define NR_CS553X_CONTROLLERS  4
+
+#define MSR_DIVIL_GLD_CAP      0x51400000      /* DIVIL capabilitiies */
+#define CAP_CS5535             0x2df000ULL
+#define CAP_CS5536             0x5df500ULL
+
+/* NAND Timing MSRs */
+#define MSR_NANDF_DATA         0x5140001b      /* NAND Flash Data Timing MSR */
+#define MSR_NANDF_CTL          0x5140001c      /* NAND Flash Control Timing */
+#define MSR_NANDF_RSVD         0x5140001d      /* Reserved */
+
+/* NAND BAR MSRs */
+#define MSR_DIVIL_LBAR_FLSH0   0x51400010      /* Flash Chip Select 0 */
+#define MSR_DIVIL_LBAR_FLSH1   0x51400011      /* Flash Chip Select 1 */
+#define MSR_DIVIL_LBAR_FLSH2   0x51400012      /* Flash Chip Select 2 */
+#define MSR_DIVIL_LBAR_FLSH3   0x51400013      /* Flash Chip Select 3 */
+       /* Each made up of... */
+#define FLSH_LBAR_EN           (1ULL<<32)
+#define FLSH_NOR_NAND          (1ULL<<33)      /* 1 for NAND */
+#define FLSH_MEM_IO            (1ULL<<34)      /* 1 for MMIO */
+       /* I/O BARs have BASE_ADDR in bits 15:4, IO_MASK in 47:36 */
+       /* MMIO BARs have BASE_ADDR in bits 31:12, MEM_MASK in 63:44 */
+
+/* Pin function selection MSR (IDE vs. flash on the IDE pins) */
+#define MSR_DIVIL_BALL_OPTS    0x51400015
+#define PIN_OPT_IDE            (1<<0)  /* 0 for flash, 1 for IDE */
+
+/* Registers within the NAND flash controller BAR -- memory mapped */
+#define MM_NAND_DATA           0x00    /* 0 to 0x7ff, in fact */
+#define MM_NAND_CTL            0x800   /* Any even address 0x800-0x80e */
+#define MM_NAND_IO             0x801   /* Any odd address 0x801-0x80f */
+#define MM_NAND_STS            0x810
+#define MM_NAND_ECC_LSB                0x811
+#define MM_NAND_ECC_MSB                0x812
+#define MM_NAND_ECC_COL                0x813
+#define MM_NAND_LAC            0x814
+#define MM_NAND_ECC_CTL                0x815
+
+/* Registers within the NAND flash controller BAR -- I/O mapped */
+#define IO_NAND_DATA           0x00    /* 0 to 3, in fact */
+#define IO_NAND_CTL            0x04
+#define IO_NAND_IO             0x05
+#define IO_NAND_STS            0x06
+#define IO_NAND_ECC_CTL                0x08
+#define IO_NAND_ECC_LSB                0x09
+#define IO_NAND_ECC_MSB                0x0a
+#define IO_NAND_ECC_COL                0x0b
+#define IO_NAND_LAC            0x0c
+
+#define CS_NAND_CTL_DIST_EN    (1<<4)  /* Enable NAND Distract interrupt */
+#define CS_NAND_CTL_RDY_INT_MASK       (1<<3)  /* Enable RDY/BUSY# interrupt */
+#define CS_NAND_CTL_ALE                (1<<2)
+#define CS_NAND_CTL_CLE                (1<<1)
+#define CS_NAND_CTL_CE         (1<<0)  /* Keep low; 1 to reset */
+
+#define CS_NAND_STS_FLASH_RDY  (1<<3)
+#define CS_NAND_CTLR_BUSY      (1<<2)
+#define CS_NAND_CMD_COMP       (1<<1)
+#define CS_NAND_DIST_ST                (1<<0)
+
+#define CS_NAND_ECC_PARITY     (1<<2)
+#define CS_NAND_ECC_CLRECC     (1<<1)
+#define CS_NAND_ECC_ENECC      (1<<0)
+
+static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+       struct nand_chip *this = mtd->priv;
+
+       while (unlikely(len > 0x800)) {
+               memcpy_fromio(buf, this->IO_ADDR_R, 0x800);
+               buf += 0x800;
+               len -= 0x800;
+       }
+       memcpy_fromio(buf, this->IO_ADDR_R, len);
+}
+
+static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+       struct nand_chip *this = mtd->priv;
+
+       while (unlikely(len > 0x800)) {
+               memcpy_toio(this->IO_ADDR_R, buf, 0x800);
+               buf += 0x800;
+               len -= 0x800;
+       }
+       memcpy_toio(this->IO_ADDR_R, buf, len);
+}
+
+static unsigned char cs553x_read_byte(struct mtd_info *mtd)
+{
+       struct nand_chip *this = mtd->priv;
+       return readb(this->IO_ADDR_R);
+}
+
+static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
+{
+       struct nand_chip *this = mtd->priv;
+       int i = 100000;
+
+       while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) {
+               udelay(1);
+               i--;
+       }
+       writeb(byte, this->IO_ADDR_W + 0x801);
+}
+
+static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
+                            unsigned int ctrl)
+{
+       struct nand_chip *this = mtd->priv;
+       void __iomem *mmio_base = this->IO_ADDR_R;
+       if (ctrl & NAND_CTRL_CHANGE) {
+               unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01;
+               writeb(ctl, mmio_base + MM_NAND_CTL);
+       }
+       if (cmd != NAND_CMD_NONE)
+               cs553x_write_byte(mtd, cmd);
+}
+
+static int cs553x_device_ready(struct mtd_info *mtd)
+{
+       struct nand_chip *this = mtd->priv;
+       void __iomem *mmio_base = this->IO_ADDR_R;
+       unsigned char foo = readb(mmio_base + MM_NAND_STS);
+
+       return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY);
+}
+
+static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+       struct nand_chip *this = mtd->priv;
+       void __iomem *mmio_base = this->IO_ADDR_R;
+
+       writeb(0x07, mmio_base + MM_NAND_ECC_CTL);
+}
+
+static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+{
+       uint32_t ecc;
+       struct nand_chip *this = mtd->priv;
+       void __iomem *mmio_base = this->IO_ADDR_R;
+
+       ecc = readl(mmio_base + MM_NAND_STS);
+
+       ecc_code[1] = ecc >> 8;
+       ecc_code[0] = ecc >> 16;
+       ecc_code[2] = ecc >> 24;
+       return 0;
+}
+
+static struct mtd_info *cs553x_mtd[4];
+
+static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
+{
+       int err = 0;
+       struct nand_chip *this;
+       struct mtd_info *new_mtd;
+
+       printk(KERN_NOTICE "Probing CS553x NAND controller CS#%d at %sIO 0x%08lx\n", cs, mmio?"MM":"P", adr);
+
+       if (!mmio) {
+               printk(KERN_NOTICE "PIO mode not yet implemented for CS553X NAND controller\n");
+               return -ENXIO;
+       }
+
+       /* Allocate memory for MTD device structure and private data */
+       new_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
+       if (!new_mtd) {
+               printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n");
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /* Get pointer to private data */
+       this = (struct nand_chip *)(&new_mtd[1]);
+
+       /* Initialize structures */
+       memset(new_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
+
+       /* Link the private data with the MTD structure */
+       new_mtd->priv = this;
+       new_mtd->owner = THIS_MODULE;
+
+       /* map physical address */
+       this->IO_ADDR_R = this->IO_ADDR_W = ioremap(adr, 4096);
+       if (!this->IO_ADDR_R) {
+               printk(KERN_WARNING "ioremap cs553x NAND @0x%08lx failed\n", adr);
+               err = -EIO;
+               goto out_mtd;
+       }
+
+       this->cmd_ctrl = cs553x_hwcontrol;
+       this->dev_ready = cs553x_device_ready;
+       this->read_byte = cs553x_read_byte;
+       this->read_buf = cs553x_read_buf;
+       this->write_buf = cs553x_write_buf;
+
+       this->chip_delay = 0;
+
+       this->ecc.mode = NAND_ECC_HW;
+       this->ecc.size = 256;
+       this->ecc.bytes = 3;
+       this->ecc.hwctl  = cs_enable_hwecc;
+       this->ecc.calculate = cs_calculate_ecc;
+       this->ecc.correct  = nand_correct_data;
+
+       /* Enable the following for a flash based bad block table */
+       this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
+
+       /* Scan to find existance of the device */
+       if (nand_scan(new_mtd, 1)) {
+               err = -ENXIO;
+               goto out_ior;
+       }
+
+       cs553x_mtd[cs] = new_mtd;
+       goto out;
+
+out_ior:
+       iounmap((void *)this->IO_ADDR_R);
+out_mtd:
+       kfree(new_mtd);
+out:
+       return err;
+}
+
+static int is_geode(void)
+{
+       /* These are the CPUs which will have a CS553[56] companion chip */
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+           boot_cpu_data.x86 == 5 &&
+           boot_cpu_data.x86_model == 10)
+               return 1; /* Geode LX */
+
+       if ((boot_cpu_data.x86_vendor == X86_VENDOR_NSC ||
+            boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX) &&
+           boot_cpu_data.x86 == 5 &&
+           boot_cpu_data.x86_model == 5)
+               return 1; /* Geode GX (née GX2) */
+
+       return 0;
+}
+
+static int __init cs553x_init(void)
+{
+       int err = -ENXIO;
+       int i;
+       uint64_t val;
+
+       /* If the CPU isn't a Geode GX or LX, abort */
+       if (!is_geode())
+               return -ENXIO;
+
+       /* If it doesn't have the CS553[56], abort */
+       rdmsrl(MSR_DIVIL_GLD_CAP, val);
+       val &= ~0xFFULL;
+       if (val != CAP_CS5535 && val != CAP_CS5536)
+               return -ENXIO;
+
+       /* If it doesn't have the NAND controller enabled, abort */
+       rdmsrl(MSR_DIVIL_BALL_OPTS, val);
+       if (val & 1) {
+               printk(KERN_INFO "CS553x NAND controller: Flash I/O not enabled in MSR_DIVIL_BALL_OPTS.\n");
+               return -ENXIO;
+       }
+
+       for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
+               rdmsrl(MSR_DIVIL_LBAR_FLSH0 + i, val);
+
+               if ((val & (FLSH_LBAR_EN|FLSH_NOR_NAND)) == (FLSH_LBAR_EN|FLSH_NOR_NAND))
+                       err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF);
+       }
+
+       /* Register all devices together here. This means we can easily hack it to 
+          do mtdconcat etc. if we want to. */
+       for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
+               if (cs553x_mtd[i]) {
+                       add_mtd_device(cs553x_mtd[i]);
+
+                       /* If any devices registered, return success. Else the last error. */
+                       err = 0;
+               }
+       }
+
+       return err;
+}
+
+module_init(cs553x_init);
+
+static void __exit cs553x_cleanup(void)
+{
+       int i;
+
+       for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
+               struct mtd_info *mtd = cs553x_mtd[i];
+               struct nand_chip *this;
+               void __iomem *mmio_base;
+
+               if (!mtd)
+                       break;
+
+               this = cs553x_mtd[i]->priv;
+               mmio_base = this->IO_ADDR_R;
+
+               /* Release resources, unregister device */
+               nand_release(cs553x_mtd[i]);
+               cs553x_mtd[i] = NULL;
+
+               /* unmap physical adress */
+               iounmap(mmio_base);
+
+               /* Free the MTD device structure */
+               kfree(mtd);
+       }
+}
+
+module_exit(cs553x_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_DESCRIPTION("NAND controller driver for AMD CS5535/CS5536 companion chip");
index ec5e45e4e4efcfe9214e0076ed59c470cf2b90e7..6107f532855b8d4dbb901ff83c721e76a0b59af2 100644 (file)
@@ -58,10 +58,10 @@ static unsigned long __initdata doc_locations[] = {
        0xe4000000,
 #elif defined(CONFIG_MOMENCO_OCELOT)
        0x2f000000,
-        0xff000000,
+       0xff000000,
 #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
-        0xff000000,
-##else
+       0xff000000,
+#else
 #warning Unknown architecture for DiskOnChip. No default probe locations defined
 #endif
        0xffffffff };
@@ -73,7 +73,7 @@ struct doc_priv {
        unsigned long physadr;
        u_char ChipID;
        u_char CDSNControl;
-       int chips_per_floor; /* The number of chips detected on each floor */
+       int chips_per_floor;    /* The number of chips detected on each floor */
        int curfloor;
        int curchip;
        int mh0_page;
@@ -84,6 +84,7 @@ struct doc_priv {
 /* This is the syndrome computed by the HW ecc generator upon reading an empty
    page, one with all 0xff for data and stored ecc code. */
 static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a };
+
 /* This is the ecc value computed by the HW ecc generator upon writing an empty
    page, one with all 0xff for data. */
 static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
@@ -94,28 +95,29 @@ static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
 #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
 #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
 
-static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd);
+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
+                             unsigned int bitmask);
 static void doc200x_select_chip(struct mtd_info *mtd, int chip);
 
-static int debug=0;
+static int debug = 0;
 module_param(debug, int, 0);
 
-static int try_dword=1;
+static int try_dword = 1;
 module_param(try_dword, int, 0);
 
-static int no_ecc_failures=0;
+static int no_ecc_failures = 0;
 module_param(no_ecc_failures, int, 0);
 
-static int no_autopart=0;
+static int no_autopart = 0;
 module_param(no_autopart, int, 0);
 
-static int show_firmware_partition=0;
+static int show_firmware_partition = 0;
 module_param(show_firmware_partition, int, 0);
 
 #ifdef MTD_NAND_DISKONCHIP_BBTWRITE
-static int inftl_bbt_write=1;
+static int inftl_bbt_write = 1;
 #else
-static int inftl_bbt_write=0;
+static int inftl_bbt_write = 0;
 #endif
 module_param(inftl_bbt_write, int, 0);
 
@@ -123,7 +125,6 @@ static unsigned long doc_config_location = CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDR
 module_param(doc_config_location, ulong, 0);
 MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
 
-
 /* Sector size for HW ECC */
 #define SECTOR_SIZE 512
 /* The sector bytes are packed into NB_DATA 10 bit words */
@@ -147,7 +148,7 @@ static struct rs_control *rs_decoder;
  * some comments, improved a minor bit and converted it to make use
  * of the generic Reed-Solomon libary. tglx
  */
-static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
+static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 {
        int i, j, nerr, errpos[8];
        uint8_t parity;
@@ -168,18 +169,18 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
         *  s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0]
         *  where x = alpha^(FCR + i)
         */
-       for(j = 1; j < NROOTS; j++) {
-               if(ds[j] == 0)
+       for (j = 1; j < NROOTS; j++) {
+               if (ds[j] == 0)
                        continue;
                tmp = rs->index_of[ds[j]];
-               for(i = 0; i < NROOTS; i++)
+               for (i = 0; i < NROOTS; i++)
                        s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)];
        }
 
        /* Calc s[i] = s[i] / alpha^(v + i) */
        for (i = 0; i < NROOTS; i++) {
                if (syn[i])
-                       syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
+                       syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
        }
        /* Call the decoder library */
        nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval);
@@ -193,7 +194,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
         * but they are given by the design of the de/encoder circuit
         * in the DoC ASIC's.
         */
-       for(i = 0;i < nerr; i++) {
+       for (i = 0; i < nerr; i++) {
                int index, bitpos, pos = 1015 - errpos[i];
                uint8_t val;
                if (pos >= NB_DATA && pos < 1019)
@@ -205,8 +206,7 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
                           can be modified since pos is even */
                        index = (pos >> 3) ^ 1;
                        bitpos = pos & 7;
-                       if ((index >= 0 && index < SECTOR_SIZE) ||
-                           index == (SECTOR_SIZE + 1)) {
+                       if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) {
                                val = (uint8_t) (errval[i] >> (2 + bitpos));
                                parity ^= val;
                                if (index < SECTOR_SIZE)
@@ -216,9 +216,8 @@ static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
                        bitpos = (bitpos + 10) & 7;
                        if (bitpos == 0)
                                bitpos = 8;
-                       if ((index >= 0 && index < SECTOR_SIZE) ||
-                           index == (SECTOR_SIZE + 1)) {
-                               val = (uint8_t)(errval[i] << (8 - bitpos));
+                       if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) {
+                               val = (uint8_t) (errval[i] << (8 - bitpos));
                                parity ^= val;
                                if (index < SECTOR_SIZE)
                                        data[index] ^= val;
@@ -250,10 +249,11 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
 /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
 static int _DoC_WaitReady(struct doc_priv *doc)
 {
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        unsigned long timeo = jiffies + (HZ * 10);
 
-       if(debug) printk("_DoC_WaitReady...\n");
+       if (debug)
+               printk("_DoC_WaitReady...\n");
        /* Out-of-line routine to wait for chip response */
        if (DoC_is_MillenniumPlus(doc)) {
                while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) {
@@ -280,7 +280,7 @@ static int _DoC_WaitReady(struct doc_priv *doc)
 
 static inline int DoC_WaitReady(struct doc_priv *doc)
 {
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int ret = 0;
 
        if (DoC_is_MillenniumPlus(doc)) {
@@ -298,7 +298,8 @@ static inline int DoC_WaitReady(struct doc_priv *doc)
                DoC_Delay(doc, 2);
        }
 
-       if(debug) printk("DoC_WaitReady OK\n");
+       if (debug)
+               printk("DoC_WaitReady OK\n");
        return ret;
 }
 
@@ -306,9 +307,10 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
 
-       if(debug)printk("write_byte %02x\n", datum);
+       if (debug)
+               printk("write_byte %02x\n", datum);
        WriteDOC(datum, docptr, CDSNSlowIO);
        WriteDOC(datum, docptr, 2k_CDSN_IO);
 }
@@ -317,77 +319,78 @@ static u_char doc2000_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        u_char ret;
 
        ReadDOC(docptr, CDSNSlowIO);
        DoC_Delay(doc, 2);
        ret = ReadDOC(docptr, 2k_CDSN_IO);
-       if (debug) printk("read_byte returns %02x\n", ret);
+       if (debug)
+               printk("read_byte returns %02x\n", ret);
        return ret;
 }
 
-static void doc2000_writebuf(struct mtd_info *mtd,
-                            const u_char *buf, int len)
+static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int i;
-       if (debug)printk("writebuf of %d bytes: ", len);
-       for (i=0; i < len; i++) {
+       if (debug)
+               printk("writebuf of %d bytes: ", len);
+       for (i = 0; i < len; i++) {
                WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i);
                if (debug && i < 16)
                        printk("%02x ", buf[i]);
        }
-       if (debug) printk("\n");
+       if (debug)
+               printk("\n");
 }
 
-static void doc2000_readbuf(struct mtd_info *mtd,
-                           u_char *buf, int len)
+static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
-       int i;
+       void __iomem *docptr = doc->virtadr;
+       int i;
 
-       if (debug)printk("readbuf of %d bytes: ", len);
+       if (debug)
+               printk("readbuf of %d bytes: ", len);
 
-       for (i=0; i < len; i++) {
+       for (i = 0; i < len; i++) {
                buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i);
        }
 }
 
-static void doc2000_readbuf_dword(struct mtd_info *mtd,
-                           u_char *buf, int len)
+static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
-       int i;
+       void __iomem *docptr = doc->virtadr;
+       int i;
 
-       if (debug) printk("readbuf_dword of %d bytes: ", len);
+       if (debug)
+               printk("readbuf_dword of %d bytes: ", len);
 
-       if (unlikely((((unsigned long)buf)|len) & 3)) {
-               for (i=0; i < len; i++) {
-                       *(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i);
+       if (unlikely((((unsigned long)buf) | len) & 3)) {
+               for (i = 0; i < len; i++) {
+                       *(uint8_t *) (&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i);
                }
        } else {
-               for (i=0; i < len; i+=4) {
-                       *(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i);
+               for (i = 0; i < len; i += 4) {
+                       *(uint32_t *) (&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i);
                }
        }
 }
 
-static int doc2000_verifybuf(struct mtd_info *mtd,
-                             const u_char *buf, int len)
+static int doc2000_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int i;
 
-       for (i=0; i < len; i++)
+       for (i = 0; i < len; i++)
                if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO))
                        return -EFAULT;
        return 0;
@@ -400,12 +403,10 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
        uint16_t ret;
 
        doc200x_select_chip(mtd, nr);
-       doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
-       this->write_byte(mtd, NAND_CMD_READID);
-       doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
-       doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
-       this->write_byte(mtd, 0);
-       doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
+       doc200x_hwcontrol(mtd, NAND_CMD_READID,
+                         NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+       doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+       doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
        /* We cant' use dev_ready here, but at least we wait for the
         * command to complete
@@ -423,12 +424,11 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
                } ident;
                void __iomem *docptr = doc->virtadr;
 
-               doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
-               doc2000_write_byte(mtd, NAND_CMD_READID);
-               doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
-               doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
-               doc2000_write_byte(mtd, 0);
-               doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
+               doc200x_hwcontrol(mtd, NAND_CMD_READID,
+                                 NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+               doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+               doc200x_hwcontrol(mtd, NAND_CMD_NONE,
+                                 NAND_NCE | NAND_CTRL_CHANGE);
 
                udelay(50);
 
@@ -464,7 +464,7 @@ static void __init doc2000_count_chips(struct mtd_info *mtd)
        printk(KERN_DEBUG "Detected %d chips per floor.\n", i);
 }
 
-static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
+static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
 {
        struct doc_priv *doc = this->priv;
 
@@ -482,7 +482,7 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
 
        WriteDOC(datum, docptr, CDSNSlowIO);
        WriteDOC(datum, docptr, Mil_CDSN_IO);
@@ -493,7 +493,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
 
        //ReadDOC(docptr, CDSNSlowIO);
        /* 11.4.5 -- delay twice to allow extended length cycle */
@@ -503,50 +503,47 @@ static u_char doc2001_read_byte(struct mtd_info *mtd)
        return ReadDOC(docptr, LastDataRead);
 }
 
-static void doc2001_writebuf(struct mtd_info *mtd,
-                            const u_char *buf, int len)
+static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int i;
 
-       for (i=0; i < len; i++)
+       for (i = 0; i < len; i++)
                WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);
        /* Terminate write pipeline */
        WriteDOC(0x00, docptr, WritePipeTerm);
 }
 
-static void doc2001_readbuf(struct mtd_info *mtd,
-                           u_char *buf, int len)
+static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int i;
 
        /* Start read pipeline */
        ReadDOC(docptr, ReadPipeInit);
 
-       for (i=0; i < len-1; i++)
+       for (i = 0; i < len - 1; i++)
                buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff));
 
        /* Terminate read pipeline */
        buf[i] = ReadDOC(docptr, LastDataRead);
 }
 
-static int doc2001_verifybuf(struct mtd_info *mtd,
-                            const u_char *buf, int len)
+static int doc2001_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int i;
 
        /* Start read pipeline */
        ReadDOC(docptr, ReadPipeInit);
 
-       for (i=0; i < len-1; i++)
+       for (i = 0; i < len - 1; i++)
                if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
                        ReadDOC(docptr, LastDataRead);
                        return i;
@@ -560,87 +557,90 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        u_char ret;
 
-        ReadDOC(docptr, Mplus_ReadPipeInit);
-        ReadDOC(docptr, Mplus_ReadPipeInit);
-        ret = ReadDOC(docptr, Mplus_LastDataRead);
-       if (debug) printk("read_byte returns %02x\n", ret);
+       ReadDOC(docptr, Mplus_ReadPipeInit);
+       ReadDOC(docptr, Mplus_ReadPipeInit);
+       ret = ReadDOC(docptr, Mplus_LastDataRead);
+       if (debug)
+               printk("read_byte returns %02x\n", ret);
        return ret;
 }
 
-static void doc2001plus_writebuf(struct mtd_info *mtd,
-                            const u_char *buf, int len)
+static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int i;
 
-       if (debug)printk("writebuf of %d bytes: ", len);
-       for (i=0; i < len; i++) {
+       if (debug)
+               printk("writebuf of %d bytes: ", len);
+       for (i = 0; i < len; i++) {
                WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);
                if (debug && i < 16)
                        printk("%02x ", buf[i]);
        }
-       if (debug) printk("\n");
+       if (debug)
+               printk("\n");
 }
 
-static void doc2001plus_readbuf(struct mtd_info *mtd,
-                           u_char *buf, int len)
+static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int i;
 
-       if (debug)printk("readbuf of %d bytes: ", len);
+       if (debug)
+               printk("readbuf of %d bytes: ", len);
 
        /* Start read pipeline */
        ReadDOC(docptr, Mplus_ReadPipeInit);
        ReadDOC(docptr, Mplus_ReadPipeInit);
 
-       for (i=0; i < len-2; i++) {
+       for (i = 0; i < len - 2; i++) {
                buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
                if (debug && i < 16)
                        printk("%02x ", buf[i]);
        }
 
        /* Terminate read pipeline */
-       buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead);
+       buf[len - 2] = ReadDOC(docptr, Mplus_LastDataRead);
        if (debug && i < 16)
-               printk("%02x ", buf[len-2]);
-       buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead);
+               printk("%02x ", buf[len - 2]);
+       buf[len - 1] = ReadDOC(docptr, Mplus_LastDataRead);
        if (debug && i < 16)
-               printk("%02x ", buf[len-1]);
-       if (debug) printk("\n");
+               printk("%02x ", buf[len - 1]);
+       if (debug)
+               printk("\n");
 }
 
-static int doc2001plus_verifybuf(struct mtd_info *mtd,
-                            const u_char *buf, int len)
+static int doc2001plus_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int i;
 
-       if (debug)printk("verifybuf of %d bytes: ", len);
+       if (debug)
+               printk("verifybuf of %d bytes: ", len);
 
        /* Start read pipeline */
        ReadDOC(docptr, Mplus_ReadPipeInit);
        ReadDOC(docptr, Mplus_ReadPipeInit);
 
-       for (i=0; i < len-2; i++)
+       for (i = 0; i < len - 2; i++)
                if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
                        ReadDOC(docptr, Mplus_LastDataRead);
                        ReadDOC(docptr, Mplus_LastDataRead);
                        return i;
                }
-       if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead))
-               return len-2;
-       if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead))
-               return len-1;
+       if (buf[len - 2] != ReadDOC(docptr, Mplus_LastDataRead))
+               return len - 2;
+       if (buf[len - 1] != ReadDOC(docptr, Mplus_LastDataRead))
+               return len - 1;
        return 0;
 }
 
@@ -648,10 +648,11 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int floor = 0;
 
-       if(debug)printk("select chip (%d)\n", chip);
+       if (debug)
+               printk("select chip (%d)\n", chip);
 
        if (chip == -1) {
                /* Disable flash internally */
@@ -660,7 +661,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
        }
 
        floor = chip / doc->chips_per_floor;
-       chip -= (floor *  doc->chips_per_floor);
+       chip -= (floor * doc->chips_per_floor);
 
        /* Assert ChipEnable and deassert WriteProtect */
        WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect);
@@ -674,72 +675,61 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int floor = 0;
 
-       if(debug)printk("select chip (%d)\n", chip);
+       if (debug)
+               printk("select chip (%d)\n", chip);
 
        if (chip == -1)
                return;
 
        floor = chip / doc->chips_per_floor;
-       chip -= (floor *  doc->chips_per_floor);
+       chip -= (floor * doc->chips_per_floor);
 
        /* 11.4.4 -- deassert CE before changing chip */
-       doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE);
+       doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
 
        WriteDOC(floor, docptr, FloorSelect);
        WriteDOC(chip, docptr, CDSNDeviceSelect);
 
-       doc200x_hwcontrol(mtd, NAND_CTL_SETNCE);
+       doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
        doc->curchip = chip;
        doc->curfloor = floor;
 }
 
-static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd)
+#define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE)
+
+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
+                             unsigned int ctrl)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
 
-       switch(cmd) {
-       case NAND_CTL_SETNCE:
-               doc->CDSNControl |= CDSN_CTRL_CE;
-               break;
-       case NAND_CTL_CLRNCE:
-               doc->CDSNControl &= ~CDSN_CTRL_CE;
-               break;
-       case NAND_CTL_SETCLE:
-               doc->CDSNControl |= CDSN_CTRL_CLE;
-               break;
-       case NAND_CTL_CLRCLE:
-               doc->CDSNControl &= ~CDSN_CTRL_CLE;
-               break;
-       case NAND_CTL_SETALE:
-               doc->CDSNControl |= CDSN_CTRL_ALE;
-               break;
-       case NAND_CTL_CLRALE:
-               doc->CDSNControl &= ~CDSN_CTRL_ALE;
-               break;
-       case NAND_CTL_SETWP:
-               doc->CDSNControl |= CDSN_CTRL_WP;
-               break;
-       case NAND_CTL_CLRWP:
-               doc->CDSNControl &= ~CDSN_CTRL_WP;
-               break;
+       if (ctrl & NAND_CTRL_CHANGE) {
+               doc->CDSNControl &= ~CDSN_CTRL_MSK;
+               doc->CDSNControl |= ctrl & CDSN_CTRL_MSK;
+               if (debug)
+                       printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
+               WriteDOC(doc->CDSNControl, docptr, CDSNControl);
+               /* 11.4.3 -- 4 NOPs after CSDNControl write */
+               DoC_Delay(doc, 4);
+       }
+       if (cmd != NAND_CMD_NONE) {
+               if (DoC_is_2000(doc))
+                       doc2000_write_byte(mtd, cmd);
+               else
+                       doc2001_write_byte(mtd, cmd);
        }
-       if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
-       WriteDOC(doc->CDSNControl, docptr, CDSNControl);
-       /* 11.4.3 -- 4 NOPs after CSDNControl write */
-       DoC_Delay(doc, 4);
 }
 
-static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
+static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
 
        /*
         * Must terminate write pipeline before sending any commands
@@ -756,9 +746,9 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col
        if (command == NAND_CMD_SEQIN) {
                int readcmd;
 
-               if (column >= mtd->oobblock) {
+               if (column >= mtd->writesize) {
                        /* OOB area */
-                       column -= mtd->oobblock;
+                       column -= mtd->writesize;
                        readcmd = NAND_CMD_READOOB;
                } else if (column < 256) {
                        /* First 256 bytes --> READ0 */
@@ -782,25 +772,26 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col
                        WriteDOC(column, docptr, Mplus_FlashAddress);
                }
                if (page_addr != -1) {
-                       WriteDOC((unsigned char) (page_addr & 0xff), docptr, Mplus_FlashAddress);
-                       WriteDOC((unsigned char) ((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress);
+                       WriteDOC((unsigned char)(page_addr & 0xff), docptr, Mplus_FlashAddress);
+                       WriteDOC((unsigned char)((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress);
                        /* One more address cycle for higher density devices */
                        if (this->chipsize & 0x0c000000) {
-                               WriteDOC((unsigned char) ((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress);
+                               WriteDOC((unsigned char)((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress);
                                printk("high density\n");
                        }
                }
                WriteDOC(0, docptr, Mplus_WritePipeTerm);
                WriteDOC(0, docptr, Mplus_WritePipeTerm);
                /* deassert ALE */
-               if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || command == NAND_CMD_READOOB || command == NAND_CMD_READID)
+               if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 ||
+                   command == NAND_CMD_READOOB || command == NAND_CMD_READID)
                        WriteDOC(0, docptr, Mplus_FlashControl);
        }
 
        /*
         * program and erase have their own busy handlers
         * status and sequential in needs no delay
-       */
+        */
        switch (command) {
 
        case NAND_CMD_PAGEPROG:
@@ -817,55 +808,57 @@ static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int col
                WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd);
                WriteDOC(0, docptr, Mplus_WritePipeTerm);
                WriteDOC(0, docptr, Mplus_WritePipeTerm);
-               while ( !(this->read_byte(mtd) & 0x40));
+               while (!(this->read_byte(mtd) & 0x40)) ;
                return;
 
-       /* This applies to read commands */
+               /* This applies to read commands */
        default:
                /*
                 * If we don't have access to the busy pin, we apply the given
                 * command delay
-               */
+                */
                if (!this->dev_ready) {
-                       udelay (this->chip_delay);
+                       udelay(this->chip_delay);
                        return;
                }
        }
 
        /* Apply this short delay always to ensure that we do wait tWB in
         * any case on any machine. */
-       ndelay (100);
+       ndelay(100);
        /* wait until command is processed */
-       while (!this->dev_ready(mtd));
+       while (!this->dev_ready(mtd)) ;
 }
 
 static int doc200x_dev_ready(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
 
        if (DoC_is_MillenniumPlus(doc)) {
                /* 11.4.2 -- must NOP four times before checking FR/B# */
                DoC_Delay(doc, 4);
                if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) {
-                       if(debug)
+                       if (debug)
                                printk("not ready\n");
                        return 0;
                }
-               if (debug)printk("was ready\n");
+               if (debug)
+                       printk("was ready\n");
                return 1;
        } else {
                /* 11.4.2 -- must NOP four times before checking FR/B# */
                DoC_Delay(doc, 4);
                if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
-                       if(debug)
+                       if (debug)
                                printk("not ready\n");
                        return 0;
                }
                /* 11.4.2 -- Must NOP twice if it's ready */
                DoC_Delay(doc, 2);
-               if (debug)printk("was ready\n");
+               if (debug)
+                       printk("was ready\n");
                return 1;
        }
 }
@@ -881,10 +874,10 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
 
        /* Prime the ECC engine */
-       switch(mode) {
+       switch (mode) {
        case NAND_ECC_READ:
                WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
                WriteDOC(DOC_ECC_EN, docptr, ECCConf);
@@ -900,10 +893,10 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
 
        /* Prime the ECC engine */
-       switch(mode) {
+       switch (mode) {
        case NAND_ECC_READ:
                WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
                WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
@@ -916,12 +909,11 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
 }
 
 /* This code is only called on write */
-static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
-                                unsigned char *ecc_code)
+static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
        int i;
        int emptymatch = 1;
 
@@ -961,7 +953,8 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
                   often.  It could be optimized away by examining the data in
                   the writebuf routine, and remembering the result. */
                for (i = 0; i < 512; i++) {
-                       if (dat[i] == 0xff) continue;
+                       if (dat[i] == 0xff)
+                               continue;
                        emptymatch = 0;
                        break;
                }
@@ -969,17 +962,20 @@ static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
        /* If emptymatch still =1, we do have an all-0xff data buffer.
           Return all-0xff ecc value instead of the computed one, so
           it'll look just like a freshly-erased page. */
-       if (emptymatch) memset(ecc_code, 0xff, 6);
+       if (emptymatch)
+               memset(ecc_code, 0xff, 6);
 #endif
        return 0;
 }
 
-static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
+                               u_char *read_ecc, u_char *isnull)
 {
        int i, ret = 0;
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+       void __iomem *docptr = doc->virtadr;
+       uint8_t calc_ecc[6];
        volatile u_char dummy;
        int emptymatch = 1;
 
@@ -1012,18 +1008,20 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
                   all-0xff data and stored ecc block.  Check the stored ecc. */
                if (emptymatch) {
                        for (i = 0; i < 6; i++) {
-                               if (read_ecc[i] == 0xff) continue;
+                               if (read_ecc[i] == 0xff)
+                                       continue;
                                emptymatch = 0;
                                break;
                        }
                }
                /* If emptymatch still =1, check the data block. */
                if (emptymatch) {
-               /* Note: this somewhat expensive test should not be triggered
-                  often.  It could be optimized away by examining the data in
-                  the readbuf routine, and remembering the result. */
+                       /* Note: this somewhat expensive test should not be triggered
+                          often.  It could be optimized away by examining the data in
+                          the readbuf routine, and remembering the result. */
                        for (i = 0; i < 512; i++) {
-                               if (dat[i] == 0xff) continue;
+                               if (dat[i] == 0xff)
+                                       continue;
                                emptymatch = 0;
                                break;
                        }
@@ -1032,7 +1030,8 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
                   erased block, in which case the ECC will not come out right.
                   We'll suppress the error and tell the caller everything's
                   OK.  Because it is. */
-               if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc);
+               if (!emptymatch)
+                       ret = doc_ecc_decode(rs_decoder, dat, calc_ecc);
                if (ret > 0)
                        printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
        }
@@ -1059,11 +1058,10 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_
  * safer.  The only problem with it is that any code that parses oobfree must
  * be able to handle out-of-order segments.
  */
-static struct nand_oobinfo doc200x_oobinfo = {
-        .useecc = MTD_NANDECC_AUTOPLACE,
-        .eccbytes = 6,
-        .eccpos = {0, 1, 2, 3, 4, 5},
-        .oobfree = { {8, 8}, {6, 2} }
+static struct nand_ecclayout doc200x_oobinfo = {
+       .eccbytes = 6,
+       .eccpos = {0, 1, 2, 3, 4, 5},
+       .oobfree = {{8, 8}, {6, 2}}
 };
 
 /* Find the (I)NFTL Media Header, and optionally also the mirror media header.
@@ -1072,8 +1070,7 @@ static struct nand_oobinfo doc200x_oobinfo = {
    either "ANAND" or "BNAND".  If findmirror=1, also look for the mirror media
    header.  The page #s of the found media headers are placed in mh0_page and
    mh1_page in the DOC private structure. */
-static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
-                                    const char *id, int findmirror)
+static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
@@ -1082,17 +1079,19 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
        size_t retlen;
 
        for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
-               ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
-               if (retlen != mtd->oobblock) continue;
+               ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf);
+               if (retlen != mtd->writesize)
+                       continue;
                if (ret) {
-                       printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n",
-                               offs);
+                       printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", offs);
                }
-               if (memcmp(buf, id, 6)) continue;
+               if (memcmp(buf, id, 6))
+                       continue;
                printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs);
                if (doc->mh0_page == -1) {
                        doc->mh0_page = offs >> this->page_shift;
-                       if (!findmirror) return 1;
+                       if (!findmirror)
+                               return 1;
                        continue;
                }
                doc->mh1_page = offs >> this->page_shift;
@@ -1105,8 +1104,8 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
        /* Only one mediaheader was found.  We want buf to contain a
           mediaheader on return, so we'll have to re-read the one we found. */
        offs = doc->mh0_page << this->page_shift;
-       ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
-       if (retlen != mtd->oobblock) {
+       ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf);
+       if (retlen != mtd->writesize) {
                /* Insanity.  Give up. */
                printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n");
                return 0;
@@ -1114,8 +1113,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
        return 1;
 }
 
-static inline int __init nftl_partscan(struct mtd_info *mtd,
-                               struct mtd_partition *parts)
+static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
@@ -1127,13 +1125,14 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
        unsigned blocks, maxblocks;
        int offs, numheaders;
 
-       buf = kmalloc(mtd->oobblock, GFP_KERNEL);
+       buf = kmalloc(mtd->writesize, GFP_KERNEL);
        if (!buf) {
                printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
                return 0;
        }
-       if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out;
-       mh = (struct NFTLMediaHeader *) buf;
+       if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1)))
+               goto out;
+       mh = (struct NFTLMediaHeader *)buf;
 
        mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits);
        mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN);
@@ -1155,8 +1154,8 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
                /* Auto-determine UnitSizeFactor.  The constraints are:
                   - There can be at most 32768 virtual blocks.
                   - There can be at most (virtual block size - page size)
-                    virtual blocks (because MediaHeader+BBT must fit in 1).
-               */
+                  virtual blocks (because MediaHeader+BBT must fit in 1).
+                */
                mh->UnitSizeFactor = 0xff;
                while (blocks > maxblocks) {
                        blocks >>= 1;
@@ -1211,14 +1210,13 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
        }
 
        ret = numparts;
-out:
+ out:
        kfree(buf);
        return ret;
 }
 
 /* This is a stripped-down copy of the code in inftlmount.c */
-static inline int __init inftl_partscan(struct mtd_info *mtd,
-                                struct mtd_partition *parts)
+static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
 {
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
@@ -1235,15 +1233,16 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
        if (inftl_bbt_write)
                end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift);
 
-       buf = kmalloc(mtd->oobblock, GFP_KERNEL);
+       buf = kmalloc(mtd->writesize, GFP_KERNEL);
        if (!buf) {
                printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
                return 0;
        }
 
-       if (!find_media_headers(mtd, buf, "BNAND", 0)) goto out;
+       if (!find_media_headers(mtd, buf, "BNAND", 0))
+               goto out;
        doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift);
-       mh = (struct INFTLMediaHeader *) buf;
+       mh = (struct INFTLMediaHeader *)buf;
 
        mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
        mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
@@ -1319,8 +1318,10 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
                parts[numparts].offset = ip->firstUnit << vshift;
                parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift;
                numparts++;
-               if (ip->lastUnit > lastvunit) lastvunit = ip->lastUnit;
-               if (ip->flags & INFTL_LAST) break;
+               if (ip->lastUnit > lastvunit)
+                       lastvunit = ip->lastUnit;
+               if (ip->flags & INFTL_LAST)
+                       break;
        }
        lastvunit++;
        if ((lastvunit << vshift) < end) {
@@ -1330,7 +1331,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,
                numparts++;
        }
        ret = numparts;
-out:
+ out:
        kfree(buf);
        return ret;
 }
@@ -1342,11 +1343,12 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd)
        struct doc_priv *doc = this->priv;
        struct mtd_partition parts[2];
 
-       memset((char *) parts, 0, sizeof(parts));
+       memset((char *)parts, 0, sizeof(parts));
        /* On NFTL, we have to find the media headers before we can read the
           BBTs, since they're stored in the media header eraseblocks. */
        numparts = nftl_partscan(mtd, parts);
-       if (!numparts) return -EIO;
+       if (!numparts)
+               return -EIO;
        this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT |
                                NAND_BBT_SAVECONTENT | NAND_BBT_WRITE |
                                NAND_BBT_VERSION;
@@ -1393,8 +1395,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd)
                this->bbt_td->pages[0] = 2;
                this->bbt_md = NULL;
        } else {
-               this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT |
-                                       NAND_BBT_VERSION;
+               this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION;
                if (inftl_bbt_write)
                        this->bbt_td->options |= NAND_BBT_WRITE;
                this->bbt_td->offs = 8;
@@ -1404,8 +1405,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd)
                this->bbt_td->reserved_block_code = 0x01;
                this->bbt_td->pattern = "MSYS_BBT";
 
-               this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT |
-                                       NAND_BBT_VERSION;
+               this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION;
                if (inftl_bbt_write)
                        this->bbt_md->options |= NAND_BBT_WRITE;
                this->bbt_md->offs = 8;
@@ -1420,12 +1420,13 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd)
           At least as nand_bbt.c is currently written. */
        if ((ret = nand_scan_bbt(mtd, NULL)))
                return ret;
-       memset((char *) parts, 0, sizeof(parts));
+       memset((char *)parts, 0, sizeof(parts));
        numparts = inftl_partscan(mtd, parts);
        /* At least for now, require the INFTL Media Header.  We could probably
           do without it for non-INFTL use, since all it gives us is
           autopartitioning, but I want to give it more thought. */
-       if (!numparts) return -EIO;
+       if (!numparts)
+               return -EIO;
        add_mtd_device(mtd);
 #ifdef CONFIG_MTD_PARTITIONS
        if (!no_autopart)
@@ -1439,7 +1440,6 @@ static inline int __init doc2000_init(struct mtd_info *mtd)
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
 
-       this->write_byte = doc2000_write_byte;
        this->read_byte = doc2000_read_byte;
        this->write_buf = doc2000_writebuf;
        this->read_buf = doc2000_readbuf;
@@ -1457,7 +1457,6 @@ static inline int __init doc2001_init(struct mtd_info *mtd)
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
 
-       this->write_byte = doc2001_write_byte;
        this->read_byte = doc2001_read_byte;
        this->write_buf = doc2001_writebuf;
        this->read_buf = doc2001_readbuf;
@@ -1489,16 +1488,15 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
        struct nand_chip *this = mtd->priv;
        struct doc_priv *doc = this->priv;
 
-       this->write_byte = NULL;
        this->read_byte = doc2001plus_read_byte;
        this->write_buf = doc2001plus_writebuf;
        this->read_buf = doc2001plus_readbuf;
        this->verify_buf = doc2001plus_verifybuf;
        this->scan_bbt = inftl_scan_bbt;
-       this->hwcontrol = NULL;
+       this->cmd_ctrl = NULL;
        this->select_chip = doc2001plus_select_chip;
        this->cmdfunc = doc2001plus_command;
-       this->enable_hwecc = doc2001plus_enable_hwecc;
+       this->ecc.hwctl = doc2001plus_enable_hwecc;
 
        doc->chips_per_floor = 1;
        mtd->name = "DiskOnChip Millennium Plus";
@@ -1535,20 +1533,16 @@ static int __init doc_probe(unsigned long physadr)
        save_control = ReadDOC(virtadr, DOCControl);
 
        /* Reset the DiskOnChip ASIC */
-       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
-                virtadr, DOCControl);
-       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
-                virtadr, DOCControl);
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl);
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl);
 
        /* Enable the DiskOnChip ASIC */
-       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
-                virtadr, DOCControl);
-       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
-                virtadr, DOCControl);
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl);
+       WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl);
 
        ChipID = ReadDOC(virtadr, ChipID);
 
-       switch(ChipID) {
+       switch (ChipID) {
        case DOC_ChipID_Doc2k:
                reg = DoC_2k_ECCStatus;
                break;
@@ -1564,15 +1558,13 @@ static int __init doc_probe(unsigned long physadr)
                        ReadDOC(virtadr, Mplus_Power);
 
                /* Reset the Millennium Plus ASIC */
-               tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
-                       DOC_MODE_BDECT;
+               tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT;
                WriteDOC(tmp, virtadr, Mplus_DOCControl);
                WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
 
                mdelay(1);
                /* Enable the Millennium Plus ASIC */
-               tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
-                       DOC_MODE_BDECT;
+               tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT;
                WriteDOC(tmp, virtadr, Mplus_DOCControl);
                WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
                mdelay(1);
@@ -1596,7 +1588,7 @@ static int __init doc_probe(unsigned long physadr)
                goto notfound;
        }
        /* Check the TOGGLE bit in the ECC register */
-       tmp  = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
+       tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
        tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
        tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
        if ((tmp == tmpb) || (tmp != tmpc)) {
@@ -1626,11 +1618,11 @@ static int __init doc_probe(unsigned long physadr)
                if (ChipID == DOC_ChipID_DocMilPlus16) {
                        WriteDOC(~newval, virtadr, Mplus_AliasResolution);
                        oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution);
-                       WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it
+                       WriteDOC(newval, virtadr, Mplus_AliasResolution);       // restore it
                } else {
                        WriteDOC(~newval, virtadr, AliasResolution);
                        oldval = ReadDOC(doc->virtadr, AliasResolution);
-                       WriteDOC(newval, virtadr, AliasResolution); // restore it
+                       WriteDOC(newval, virtadr, AliasResolution);     // restore it
                }
                newval = ~newval;
                if (oldval == newval) {
@@ -1642,10 +1634,8 @@ static int __init doc_probe(unsigned long physadr)
        printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr);
 
        len = sizeof(struct mtd_info) +
-             sizeof(struct nand_chip) +
-             sizeof(struct doc_priv) +
-             (2 * sizeof(struct nand_bbt_descr));
-       mtd =  kmalloc(len, GFP_KERNEL);
+           sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr));
+       mtd = kmalloc(len, GFP_KERNEL);
        if (!mtd) {
                printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
                ret = -ENOMEM;
@@ -1663,17 +1653,19 @@ static int __init doc_probe(unsigned long physadr)
 
        nand->priv              = doc;
        nand->select_chip       = doc200x_select_chip;
-       nand->hwcontrol         = doc200x_hwcontrol;
+       nand->cmd_ctrl          = doc200x_hwcontrol;
        nand->dev_ready         = doc200x_dev_ready;
        nand->waitfunc          = doc200x_wait;
        nand->block_bad         = doc200x_block_bad;
-       nand->enable_hwecc      = doc200x_enable_hwecc;
-       nand->calculate_ecc     = doc200x_calculate_ecc;
-       nand->correct_data      = doc200x_correct_data;
+       nand->ecc.hwctl         = doc200x_enable_hwecc;
+       nand->ecc.calculate     = doc200x_calculate_ecc;
+       nand->ecc.correct       = doc200x_correct_data;
 
-       nand->autooob           = &doc200x_oobinfo;
-       nand->eccmode           = NAND_ECC_HW6_512;
-       nand->options           = NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME;
+       nand->ecc.layout        = &doc200x_oobinfo;
+       nand->ecc.mode          = NAND_ECC_HW_SYNDROME;
+       nand->ecc.size          = 512;
+       nand->ecc.bytes         = 6;
+       nand->options           = NAND_USE_FLASH_BBT;
 
        doc->physadr            = physadr;
        doc->virtadr            = virtadr;
@@ -1707,18 +1699,18 @@ static int __init doc_probe(unsigned long physadr)
        doclist = mtd;
        return 0;
 
-notfound:
+ notfound:
        /* Put back the contents of the DOCControl register, in case it's not
           actually a DiskOnChip.  */
        WriteDOC(save_control, virtadr, DOCControl);
-fail:
+ fail:
        iounmap(virtadr);
        return ret;
 }
 
 static void release_nanddoc(void)
 {
-       struct mtd_info *mtd, *nextmtd;
+       struct mtd_info *mtd, *nextmtd;
        struct nand_chip *nand;
        struct doc_priv *doc;
 
@@ -1747,8 +1739,8 @@ static int __init init_nanddoc(void)
         * generator polinomial degree = 4
         */
        rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS);
-       if (!rs_decoder) {
-               printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n");
+       if (!rs_decoder) {
+               printk(KERN_ERR "DiskOnChip: Could not create a RS decoder\n");
                return -ENOMEM;
        }
 
@@ -1758,7 +1750,7 @@ static int __init init_nanddoc(void)
                if (ret < 0)
                        goto outerr;
        } else {
-               for (i=0; (doc_locations[i] != 0xffffffff); i++) {
+               for (i = 0; (doc_locations[i] != 0xffffffff); i++) {
                        doc_probe(doc_locations[i]);
                }
        }
@@ -1770,7 +1762,7 @@ static int __init init_nanddoc(void)
                goto outerr;
        }
        return 0;
-outerr:
+ outerr:
        free_rs(rs_decoder);
        return ret;
 }
index 9b1fd2f387faf59444378adc5b966ff948673477..516c0e5e564cb2b03a8a02a73e0c58a90798ced8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/mtd/nand/edb7312.c
  *
- *  Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
+ *  Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
  *
  *  Derived from drivers/mtd/nand/autcpu12.c
  *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
@@ -25,7 +25,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <asm/io.h>
-#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
+#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
 #include <asm/sizes.h>
 #include <asm/hardware/clps7111.h>
 
@@ -54,51 +54,45 @@ static struct mtd_info *ep7312_mtd = NULL;
  */
 
 static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE;
-static void __iomem * ep7312_pxdr = (void __iomem *) EP7312_PXDR;
-static void __iomem * ep7312_pxddr = (void __iomem *) EP7312_PXDDR;
+static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR;
+static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR;
 
 #ifdef CONFIG_MTD_PARTITIONS
 /*
  * Define static partitions for flash device
  */
 static struct mtd_partition partition_info[] = {
-       { .name = "EP7312 Nand Flash",
-                 .offset = 0,
-                 .size = 8*1024*1024 }
+       {.name = "EP7312 Nand Flash",
+        .offset = 0,
+        .size = 8 * 1024 * 1024}
 };
+
 #define NUM_PARTITIONS 1
 
 #endif
 
-
 /*
  *     hardware specific access to control-lines
+ *
+ *     NAND_NCE: bit 0 -> bit 7
+ *     NAND_CLE: bit 1 -> bit 4
+ *     NAND_ALE: bit 2 -> bit 5
  */
-static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd)
+static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-       switch(cmd) {
-
-       case NAND_CTL_SETCLE:
-               clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr);
-               break;
-       case NAND_CTL_CLRCLE:
-               clps_writeb(clps_readb(ep7312_pxdr) & ~0x10, ep7312_pxdr);
-               break;
-
-       case NAND_CTL_SETALE:
-               clps_writeb(clps_readb(ep7312_pxdr) | 0x20, ep7312_pxdr);
-               break;
-       case NAND_CTL_CLRALE:
-               clps_writeb(clps_readb(ep7312_pxdr) & ~0x20, ep7312_pxdr);
-               break;
-
-       case NAND_CTL_SETNCE:
-               clps_writeb((clps_readb(ep7312_pxdr) | 0x80) & ~0x40, ep7312_pxdr);
-               break;
-       case NAND_CTL_CLRNCE:
-               clps_writeb((clps_readb(ep7312_pxdr) | 0x80) | 0x40, ep7312_pxdr);
-               break;
+       struct nand_chip *chip = mtd->priv;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               unsigned char bits;
+
+               bits = (ctrl & (NAND_CLE | NAND_ALE)) << 3;
+               bits = (ctrl & NAND_NCE) << 7;
+
+               clps_writeb((clps_readb(ep7312_pxdr)  & 0xB0) | 0x10,
+                           ep7312_pxdr);
        }
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, chip->IO_ADDR_W);
 }
 
 /*
@@ -108,6 +102,7 @@ static int ep7312_device_ready(struct mtd_info *mtd)
 {
        return 1;
 }
+
 #ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
@@ -115,18 +110,16 @@ const char *part_probes[] = { "cmdlinepart", NULL };
 /*
  * Main initialization routine
  */
-static int __init ep7312_init (void)
+static int __init ep7312_init(void)
 {
        struct nand_chip *this;
        const char *part_type = 0;
        int mtd_parts_nb = 0;
        struct mtd_partition *mtd_parts = 0;
-       void __iomem * ep7312_fio_base;
+       void __iomem *ep7312_fio_base;
 
        /* Allocate memory for MTD device structure and private data */
-       ep7312_mtd = kmalloc(sizeof(struct mtd_info) +
-                            sizeof(struct nand_chip),
-                            GFP_KERNEL);
+       ep7312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!ep7312_mtd) {
                printk("Unable to allocate EDB7312 NAND MTD device structure.\n");
                return -ENOMEM;
@@ -134,21 +127,22 @@ static int __init ep7312_init (void)
 
        /* map physical adress */
        ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K);
-       if(!ep7312_fio_base) {
+       if (!ep7312_fio_base) {
                printk("ioremap EDB7312 NAND flash failed\n");
                kfree(ep7312_mtd);
                return -EIO;
        }
 
        /* Get pointer to private data */
-       this = (struct nand_chip *) (&ep7312_mtd[1]);
+       this = (struct nand_chip *)(&ep7312_mtd[1]);
 
        /* Initialize structures */
-       memset((char *) ep7312_mtd, 0, sizeof(struct mtd_info));
-       memset((char *) this, 0, sizeof(struct nand_chip));
+       memset(ep7312_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
 
        /* Link the private data with the MTD structure */
        ep7312_mtd->priv = this;
+       ep7312_mtd->owner = THIS_MODULE;
 
        /*
         * Set GPIO Port B control register so that the pins are configured
@@ -159,22 +153,20 @@ static int __init ep7312_init (void)
        /* insert callbacks */
        this->IO_ADDR_R = ep7312_fio_base;
        this->IO_ADDR_W = ep7312_fio_base;
-       this->hwcontrol = ep7312_hwcontrol;
+       this->cmd_ctrl = ep7312_hwcontrol;
        this->dev_ready = ep7312_device_ready;
        /* 15 us command delay time */
        this->chip_delay = 15;
 
        /* Scan to find existence of the device */
-       if (nand_scan (ep7312_mtd, 1)) {
+       if (nand_scan(ep7312_mtd, 1)) {
                iounmap((void *)ep7312_fio_base);
-               kfree (ep7312_mtd);
+               kfree(ep7312_mtd);
                return -ENXIO;
        }
-
 #ifdef CONFIG_MTD_PARTITIONS
        ep7312_mtd->name = "edb7312-nand";
-       mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes,
-                                           &mtd_parts, 0);
+       mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0);
        if (mtd_parts_nb > 0)
                part_type = "command line";
        else
@@ -193,24 +185,23 @@ static int __init ep7312_init (void)
        /* Return happy */
        return 0;
 }
+
 module_init(ep7312_init);
 
 /*
  * Clean up routine
  */
-static void __exit ep7312_cleanup (void)
+static void __exit ep7312_cleanup(void)
 {
-       struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1];
+       struct nand_chip *this = (struct nand_chip *)&ep7312_mtd[1];
 
        /* Release resources, unregister device */
-       nand_release (ap7312_mtd);
-
-       /* Free internal data buffer */
-       kfree (this->data_buf);
+       nand_release(ap7312_mtd);
 
        /* Free the MTD device structure */
-       kfree (ep7312_mtd);
+       kfree(ep7312_mtd);
 }
+
 module_exit(ep7312_cleanup);
 
 MODULE_LICENSE("GPL");
index f68f7a99a6309bafb051d76b634654f52c0bbe7e..2d585d2d090c97e58efc831ec988159ee1a3fb22 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) 2003 Joshua Wise (joshua@joshuawise.com)
  *
  *  Derived from drivers/mtd/nand/edb7312.c
- *       Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
+ *       Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
  *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
  *
  * $Id: h1910.c,v 1.6 2005/11/07 11:14:30 gleixner Exp $
@@ -26,7 +26,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <asm/io.h>
-#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
+#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
 #include <asm/sizes.h>
 #include <asm/arch/h1900-gpio.h>
 #include <asm/arch/ipaq.h>
@@ -45,47 +45,29 @@ static struct mtd_info *h1910_nand_mtd = NULL;
  * Define static partitions for flash device
  */
 static struct mtd_partition partition_info[] = {
-       { name: "h1910 NAND Flash",
-                 offset: 0,
-                 size: 16*1024*1024 }
+      {name:"h1910 NAND Flash",
+             offset:0,
+      size:16 * 1024 * 1024}
 };
+
 #define NUM_PARTITIONS 1
 
 #endif
 
-
 /*
  *     hardware specific access to control-lines
+ *
+ *     NAND_NCE: bit 0 - don't care
+ *     NAND_CLE: bit 1 - address bit 2
+ *     NAND_ALE: bit 2 - address bit 3
  */
-static void h1910_hwcontrol(struct mtd_info *mtd, int cmd)
+static void h1910_hwcontrol(struct mtd_info *mtd, int cmd,
+                           unsigned int ctrl)
 {
-       struct nand_chip* this = (struct nand_chip *) (mtd->priv);
-
-       switch(cmd) {
-
-       case NAND_CTL_SETCLE:
-               this->IO_ADDR_R |= (1 << 2);
-               this->IO_ADDR_W |= (1 << 2);
-               break;
-       case NAND_CTL_CLRCLE:
-               this->IO_ADDR_R &= ~(1 << 2);
-               this->IO_ADDR_W &= ~(1 << 2);
-               break;
-
-       case NAND_CTL_SETALE:
-               this->IO_ADDR_R |= (1 << 3);
-               this->IO_ADDR_W |= (1 << 3);
-               break;
-       case NAND_CTL_CLRALE:
-               this->IO_ADDR_R &= ~(1 << 3);
-               this->IO_ADDR_W &= ~(1 << 3);
-               break;
-
-       case NAND_CTL_SETNCE:
-               break;
-       case NAND_CTL_CLRNCE:
-               break;
-       }
+       struct nand_chip *chip = mtd->priv;
+
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, chip->IO_ADDR_W | ((ctrl & 0x6) << 1));
 }
 
 /*
@@ -101,7 +83,7 @@ static int h1910_device_ready(struct mtd_info *mtd)
 /*
  * Main initialization routine
  */
-static int __init h1910_init (void)
+static int __init h1910_init(void)
 {
        struct nand_chip *this;
        const char *part_type = 0;
@@ -119,24 +101,23 @@ static int __init h1910_init (void)
        }
 
        /* Allocate memory for MTD device structure and private data */
-       h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) +
-                            sizeof(struct nand_chip),
-                            GFP_KERNEL);
+       h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!h1910_nand_mtd) {
                printk("Unable to allocate h1910 NAND MTD device structure.\n");
-               iounmap ((void *) nandaddr);
+               iounmap((void *)nandaddr);
                return -ENOMEM;
        }
 
        /* Get pointer to private data */
-       this = (struct nand_chip *) (&h1910_nand_mtd[1]);
+       this = (struct nand_chip *)(&h1910_nand_mtd[1]);
 
        /* Initialize structures */
-       memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info));
-       memset((char *) this, 0, sizeof(struct nand_chip));
+       memset(h1910_nand_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
 
        /* Link the private data with the MTD structure */
        h1910_nand_mtd->priv = this;
+       h1910_nand_mtd->owner = THIS_MODULE;
 
        /*
         * Enable VPEN
@@ -146,31 +127,28 @@ static int __init h1910_init (void)
        /* insert callbacks */
        this->IO_ADDR_R = nandaddr;
        this->IO_ADDR_W = nandaddr;
-       this->hwcontrol = h1910_hwcontrol;
+       this->cmd_ctrl = h1910_hwcontrol;
        this->dev_ready = NULL; /* unknown whether that was correct or not so we will just do it like this */
        /* 15 us command delay time */
        this->chip_delay = 50;
-       this->eccmode = NAND_ECC_SOFT;
+       this->ecc.mode = NAND_ECC_SOFT;
        this->options = NAND_NO_AUTOINCR;
 
        /* Scan to find existence of the device */
-       if (nand_scan (h1910_nand_mtd, 1)) {
+       if (nand_scan(h1910_nand_mtd, 1)) {
                printk(KERN_NOTICE "No NAND device - returning -ENXIO\n");
-               kfree (h1910_nand_mtd);
-               iounmap ((void *) nandaddr);
+               kfree(h1910_nand_mtd);
+               iounmap((void *)nandaddr);
                return -ENXIO;
        }
-
 #ifdef CONFIG_MTD_CMDLINE_PARTS
-       mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts,
-                                               "h1910-nand");
+       mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand");
        if (mtd_parts_nb > 0)
-         part_type = "command line";
+               part_type = "command line";
        else
-         mtd_parts_nb = 0;
+               mtd_parts_nb = 0;
 #endif
-       if (mtd_parts_nb == 0)
-       {
+       if (mtd_parts_nb == 0) {
                mtd_parts = partition_info;
                mtd_parts_nb = NUM_PARTITIONS;
                part_type = "static";
@@ -183,24 +161,26 @@ static int __init h1910_init (void)
        /* Return happy */
        return 0;
 }
+
 module_init(h1910_init);
 
 /*
  * Clean up routine
  */
-static void __exit h1910_cleanup (void)
+static void __exit h1910_cleanup(void)
 {
-       struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1];
+       struct nand_chip *this = (struct nand_chip *)&h1910_nand_mtd[1];
 
        /* Release resources, unregister device */
-       nand_release (h1910_nand_mtd);
+       nand_release(h1910_nand_mtd);
 
        /* Release io resource */
-       iounmap ((void *) this->IO_ADDR_W);
+       iounmap((void *)this->IO_ADDR_W);
 
        /* Free the MTD device structure */
-       kfree (h1910_nand_mtd);
+       kfree(h1910_nand_mtd);
 }
+
 module_exit(h1910_cleanup);
 
 MODULE_LICENSE("GPL");
index 95e96fa1fcebb61522ebf342952b23d30acb9623..27083ed0a017a6af2da8d41ad48d466e7b98a86d 100644 (file)
  *     http://www.linux-mtd.infradead.org/tech/nand.html
  *
  *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- *               2002 Thomas Gleixner (tglx@linutronix.de)
+ *               2002-2006 Thomas Gleixner (tglx@linutronix.de)
  *
- *  02-08-2004  tglx: support for strange chips, which cannot auto increment
- *             pages on read / read_oob
- *
- *  03-17-2004  tglx: Check ready before auto increment check. Simon Bayes
- *             pointed this out, as he marked an auto increment capable chip
- *             as NOAUTOINCR in the board driver.
- *             Make reads over block boundaries work too
- *
- *  04-14-2004 tglx: first working version for 2k page size chips
- *
- *  05-19-2004  tglx: Basic support for Renesas AG-AND chips
- *
- *  09-24-2004  tglx: add support for hardware controllers (e.g. ECC) shared
- *             among multiple independend devices. Suggestions and initial patch
- *             from Ben Dooks <ben-mtd@fluff.org>
- *
- *  12-05-2004 dmarlin: add workaround for Renesas AG-AND chips "disturb" issue.
- *             Basically, any block not rewritten may lose data when surrounding blocks
- *             are rewritten many times.  JFFS2 ensures this doesn't happen for blocks
- *             it uses, but the Bad Block Table(s) may not be rewritten.  To ensure they
- *             do not lose data, force them to be rewritten when some of the surrounding
- *             blocks are erased.  Rather than tracking a specific nearby block (which
- *             could itself go bad), use a page address 'mask' to select several blocks
- *             in the same area, and rewrite the BBT when any of them are erased.
- *
- *  01-03-2005 dmarlin: added support for the device recovery command sequence for Renesas
- *             AG-AND chips.  If there was a sudden loss of power during an erase operation,
- *             a "device recovery" operation must be performed when power is restored
- *             to ensure correct operation.
- *
- *  01-20-2005 dmarlin: added support for optional hardware specific callback routine to
- *             perform extra error status checks on erase and write failures.  This required
- *             adding a wrapper function for nand_read_ecc.
- *
- * 08-20-2005  vwool: suspend/resume added
- *
- * Credits:
+ *  Credits:
  *     David Woodhouse for adding multichip support
  *
  *     Aleph One Ltd. and Toby Churchill Ltd. for supporting the
  *     rework for 2K page size chips
  *
- * TODO:
+ *  TODO:
  *     Enable cached programming for 2k page size chips
  *     Check, if mtd->ecctype should be set to MTD_ECC_HW
  *     if we have HW ecc support.
  *     The AG-AND chips have nice features for speed improvement,
  *     which are not supported yet. Read / program 4 pages in one go.
  *
- * $Id: nand_base.c,v 1.150 2005/09/15 13:58:48 vwool Exp $
- *
  * 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/delay.h>
 #include <linux/errno.h>
+#include <linux/err.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #endif
 
 /* Define default oob placement schemes for large and small page devices */
-static struct nand_oobinfo nand_oob_8 = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_8 = {
        .eccbytes = 3,
        .eccpos = {0, 1, 2},
-       .oobfree = { {3, 2}, {6, 2} }
+       .oobfree = {
+               {.offset = 3,
+                .length = 2},
+               {.offset = 6,
+                .length = 2}}
 };
 
-static struct nand_oobinfo nand_oob_16 = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_16 = {
        .eccbytes = 6,
        .eccpos = {0, 1, 2, 3, 6, 7},
-       .oobfree = { {8, 8} }
+       .oobfree = {
+               {.offset = 8,
+                . length = 8}}
 };
 
-static struct nand_oobinfo nand_oob_64 = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_64 = {
        .eccbytes = 24,
        .eccpos = {
-               40, 41, 42, 43, 44, 45, 46, 47,
-               48, 49, 50, 51, 52, 53, 54, 55,
-               56, 57, 58, 59, 60, 61, 62, 63},
-       .oobfree = { {2, 38} }
+                  40, 41, 42, 43, 44, 45, 46, 47,
+                  48, 49, 50, 51, 52, 53, 54, 55,
+                  56, 57, 58, 59, 60, 61, 62, 63},
+       .oobfree = {
+               {.offset = 2,
+                .length = 38}}
 };
 
-/* This is used for padding purposes in nand_write_oob */
-static u_char ffchars[] = {
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-};
+static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
+                          int new_state);
+
+static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
+                            struct mtd_oob_ops *ops);
 
 /*
- * NAND low-level MTD interface functions
+ * For devices which display every fart in the system on a seperate LED. Is
+ * compiled away when LED support is disabled.
  */
-static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
-static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
-
-static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
-static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-                         size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
-static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
-static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf);
-static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
-                          size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
-static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf);
-static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
-                       unsigned long count, loff_t to, size_t * retlen);
-static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs,
-                       unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
-static int nand_erase (struct mtd_info *mtd, struct erase_info *instr);
-static void nand_sync (struct mtd_info *mtd);
-
-/* Some internal functions */
-static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,
-               struct nand_oobinfo *oobsel, int mode);
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
-       u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode);
-#else
-#define nand_verify_pages(...) (0)
-#endif
-
-static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state);
+DEFINE_LED_TRIGGER(nand_led_trigger);
 
 /**
  * nand_release_device - [GENERIC] release chip
@@ -164,27 +99,19 @@ static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int ne
  *
  * Deselect, release chip lock and wake up anyone waiting on the device
  */
-static void nand_release_device (struct mtd_info *mtd)
+static void nand_release_device(struct mtd_info *mtd)
 {
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
 
        /* De-select the NAND device */
-       this->select_chip(mtd, -1);
-
-       if (this->controller) {
-               /* Release the controller and the chip */
-               spin_lock(&this->controller->lock);
-               this->controller->active = NULL;
-               this->state = FL_READY;
-               wake_up(&this->controller->wq);
-               spin_unlock(&this->controller->lock);
-       } else {
-               /* Release the chip */
-               spin_lock(&this->chip_lock);
-               this->state = FL_READY;
-               wake_up(&this->wq);
-               spin_unlock(&this->chip_lock);
-       }
+       chip->select_chip(mtd, -1);
+
+       /* Release the controller and the chip */
+       spin_lock(&chip->controller->lock);
+       chip->controller->active = NULL;
+       chip->state = FL_READY;
+       wake_up(&chip->controller->wq);
+       spin_unlock(&chip->controller->lock);
 }
 
 /**
@@ -193,23 +120,10 @@ static void nand_release_device (struct mtd_info *mtd)
  *
  * Default read function for 8bit buswith
  */
-static u_char nand_read_byte(struct mtd_info *mtd)
-{
-       struct nand_chip *this = mtd->priv;
-       return readb(this->IO_ADDR_R);
-}
-
-/**
- * nand_write_byte - [DEFAULT] write one byte to the chip
- * @mtd:       MTD device structure
- * @byte:      pointer to data byte to write
- *
- * Default write function for 8it buswith
- */
-static void nand_write_byte(struct mtd_info *mtd, u_char byte)
+static uint8_t nand_read_byte(struct mtd_info *mtd)
 {
-       struct nand_chip *this = mtd->priv;
-       writeb(byte, this->IO_ADDR_W);
+       struct nand_chip *chip = mtd->priv;
+       return readb(chip->IO_ADDR_R);
 }
 
 /**
@@ -219,24 +133,10 @@ static void nand_write_byte(struct mtd_info *mtd, u_char byte)
  * Default read function for 16bit buswith with
  * endianess conversion
  */
-static u_char nand_read_byte16(struct mtd_info *mtd)
-{
-       struct nand_chip *this = mtd->priv;
-       return (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
-}
-
-/**
- * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip
- * @mtd:       MTD device structure
- * @byte:      pointer to data byte to write
- *
- * Default write function for 16bit buswith with
- * endianess conversion
- */
-static void nand_write_byte16(struct mtd_info *mtd, u_char byte)
+static uint8_t nand_read_byte16(struct mtd_info *mtd)
 {
-       struct nand_chip *this = mtd->priv;
-       writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
+       struct nand_chip *chip = mtd->priv;
+       return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
 }
 
 /**
@@ -248,22 +148,8 @@ static void nand_write_byte16(struct mtd_info *mtd, u_char byte)
  */
 static u16 nand_read_word(struct mtd_info *mtd)
 {
-       struct nand_chip *this = mtd->priv;
-       return readw(this->IO_ADDR_R);
-}
-
-/**
- * nand_write_word - [DEFAULT] write one word to the chip
- * @mtd:       MTD device structure
- * @word:      data word to write
- *
- * Default write function for 16bit buswith without
- * endianess conversion
- */
-static void nand_write_word(struct mtd_info *mtd, u16 word)
-{
-       struct nand_chip *this = mtd->priv;
-       writew(word, this->IO_ADDR_W);
+       struct nand_chip *chip = mtd->priv;
+       return readw(chip->IO_ADDR_R);
 }
 
 /**
@@ -273,15 +159,15 @@ static void nand_write_word(struct mtd_info *mtd, u16 word)
  *
  * Default select function for 1 chip devices.
  */
-static void nand_select_chip(struct mtd_info *mtd, int chip)
+static void nand_select_chip(struct mtd_info *mtd, int chipnr)
 {
-       struct nand_chip *this = mtd->priv;
-       switch(chip) {
+       struct nand_chip *chip = mtd->priv;
+
+       switch (chipnr) {
        case -1:
-               this->hwcontrol(mtd, NAND_CTL_CLRNCE);
+               chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
                break;
        case 0:
-               this->hwcontrol(mtd, NAND_CTL_SETNCE);
                break;
 
        default:
@@ -297,13 +183,13 @@ static void nand_select_chip(struct mtd_info *mtd, int chip)
  *
  * Default write function for 8bit buswith
  */
-static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
        int i;
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
 
-       for (i=0; i<len; i++)
-               writeb(buf[i], this->IO_ADDR_W);
+       for (i = 0; i < len; i++)
+               writeb(buf[i], chip->IO_ADDR_W);
 }
 
 /**
@@ -314,13 +200,13 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
  *
  * Default read function for 8bit buswith
  */
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
        int i;
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
 
-       for (i=0; i<len; i++)
-               buf[i] = readb(this->IO_ADDR_R);
+       for (i = 0; i < len; i++)
+               buf[i] = readb(chip->IO_ADDR_R);
 }
 
 /**
@@ -331,15 +217,14 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
  *
  * Default verify function for 8bit buswith
  */
-static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
        int i;
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
 
-       for (i=0; i<len; i++)
-               if (buf[i] != readb(this->IO_ADDR_R))
+       for (i = 0; i < len; i++)
+               if (buf[i] != readb(chip->IO_ADDR_R))
                        return -EFAULT;
-
        return 0;
 }
 
@@ -351,15 +236,15 @@ static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
  *
  * Default write function for 16bit buswith
  */
-static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
+static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
        int i;
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
        u16 *p = (u16 *) buf;
        len >>= 1;
 
-       for (i=0; i<len; i++)
-               writew(p[i], this->IO_ADDR_W);
+       for (i = 0; i < len; i++)
+               writew(p[i], chip->IO_ADDR_W);
 
 }
 
@@ -371,15 +256,15 @@ static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
  *
  * Default read function for 16bit buswith
  */
-static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
+static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 {
        int i;
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
        u16 *p = (u16 *) buf;
        len >>= 1;
 
-       for (i=0; i<len; i++)
-               p[i] = readw(this->IO_ADDR_R);
+       for (i = 0; i < len; i++)
+               p[i] = readw(chip->IO_ADDR_R);
 }
 
 /**
@@ -390,15 +275,15 @@ static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
  *
  * Default verify function for 16bit buswith
  */
-static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
+static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
        int i;
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
        u16 *p = (u16 *) buf;
        len >>= 1;
 
-       for (i=0; i<len; i++)
-               if (p[i] != readw(this->IO_ADDR_R))
+       for (i = 0; i < len; i++)
+               if (p[i] != readw(chip->IO_ADDR_R))
                        return -EFAULT;
 
        return 0;
@@ -415,38 +300,37 @@ static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
 static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 {
        int page, chipnr, res = 0;
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
        u16 bad;
 
        if (getchip) {
-               page = (int)(ofs >> this->page_shift);
-               chipnr = (int)(ofs >> this->chip_shift);
+               page = (int)(ofs >> chip->page_shift);
+               chipnr = (int)(ofs >> chip->chip_shift);
 
-               /* Grab the lock and see if the device is available */
-               nand_get_device (this, mtd, FL_READING);
+               nand_get_device(chip, mtd, FL_READING);
 
                /* Select the NAND device */
-               this->select_chip(mtd, chipnr);
+               chip->select_chip(mtd, chipnr);
        } else
-               page = (int) ofs;
+               page = (int)ofs;
 
-       if (this->options & NAND_BUSWIDTH_16) {
-               this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask);
-               bad = cpu_to_le16(this->read_word(mtd));
-               if (this->badblockpos & 0x1)
+       if (chip->options & NAND_BUSWIDTH_16) {
+               chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
+                             page & chip->pagemask);
+               bad = cpu_to_le16(chip->read_word(mtd));
+               if (chip->badblockpos & 0x1)
                        bad >>= 8;
                if ((bad & 0xFF) != 0xff)
                        res = 1;
        } else {
-               this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask);
-               if (this->read_byte(mtd) != 0xff)
+               chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
+                             page & chip->pagemask);
+               if (chip->read_byte(mtd) != 0xff)
                        res = 1;
        }
 
-       if (getchip) {
-               /* Deselect and wake up anyone waiting on the device */
+       if (getchip)
                nand_release_device(mtd);
-       }
 
        return res;
 }
@@ -461,23 +345,33 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 */
 static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-       struct nand_chip *this = mtd->priv;
-       u_char buf[2] = {0, 0};
-       size_t  retlen;
-       int block;
+       struct nand_chip *chip = mtd->priv;
+       uint8_t buf[2] = { 0, 0 };
+       int block, ret;
 
        /* Get block number */
-       block = ((int) ofs) >> this->bbt_erase_shift;
-       if (this->bbt)
-               this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
+       block = ((int)ofs) >> chip->bbt_erase_shift;
+       if (chip->bbt)
+               chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
 
        /* Do we have a flash based bad block table ? */
-       if (this->options & NAND_USE_FLASH_BBT)
-               return nand_update_bbt (mtd, ofs);
+       if (chip->options & NAND_USE_FLASH_BBT)
+               ret = nand_update_bbt(mtd, ofs);
+       else {
+               /* We write two bytes, so we dont have to mess with 16 bit
+                * access
+                */
+               ofs += mtd->oobsize;
+               chip->ops.len = 2;
+               chip->ops.datbuf = NULL;
+               chip->ops.oobbuf = buf;
+               chip->ops.ooboffs = chip->badblockpos & ~0x01;
 
-       /* We write two bytes, so we dont have to mess with 16 bit access */
-       ofs += mtd->oobsize + (this->badblockpos & ~0x01);
-       return nand_write_oob (mtd, ofs , 2, &retlen, buf);
+               ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+       }
+       if (!ret)
+               mtd->ecc_stats.badblocks++;
+       return ret;
 }
 
 /**
@@ -487,12 +381,12 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
  *
  * The function expects, that the device is already selected
  */
-static int nand_check_wp (struct mtd_info *mtd)
+static int nand_check_wp(struct mtd_info *mtd)
 {
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
        /* Check the WP bit */
-       this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);
-       return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
+       chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+       return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
 }
 
 /**
@@ -505,32 +399,31 @@ static int nand_check_wp (struct mtd_info *mtd)
  * Check, if the block is bad. Either by reading the bad block table or
  * calling of the scan function.
  */
-static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt)
+static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
+                              int allowbbt)
 {
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
 
-       if (!this->bbt)
-               return this->block_bad(mtd, ofs, getchip);
+       if (!chip->bbt)
+               return chip->block_bad(mtd, ofs, getchip);
 
        /* Return info from the table */
-       return nand_isbad_bbt (mtd, ofs, allowbbt);
+       return nand_isbad_bbt(mtd, ofs, allowbbt);
 }
 
-DEFINE_LED_TRIGGER(nand_led_trigger);
-
 /*
  * Wait for the ready pin, after a command
  * The timeout is catched later.
  */
 static void nand_wait_ready(struct mtd_info *mtd)
 {
-       struct nand_chip *this = mtd->priv;
-       unsigned long   timeo = jiffies + 2;
+       struct nand_chip *chip = mtd->priv;
+       unsigned long timeo = jiffies + 2;
 
        led_trigger_event(nand_led_trigger, LED_FULL);
        /* wait until command is processed or timeout occures */
        do {
-               if (this->dev_ready(mtd))
+               if (chip->dev_ready(mtd))
                        break;
                touch_softlockup_watchdog();
        } while (time_before(jiffies, timeo));
@@ -547,21 +440,21 @@ static void nand_wait_ready(struct mtd_info *mtd)
  * Send command to NAND device. This function is used for small page
  * devices (256/512 Bytes per page)
  */
-static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
+static void nand_command(struct mtd_info *mtd, unsigned int command,
+                        int column, int page_addr)
 {
-       register struct nand_chip *this = mtd->priv;
+       register struct nand_chip *chip = mtd->priv;
+       int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
 
-       /* Begin command latch cycle */
-       this->hwcontrol(mtd, NAND_CTL_SETCLE);
        /*
         * Write out the command to the device.
         */
        if (command == NAND_CMD_SEQIN) {
                int readcmd;
 
-               if (column >= mtd->oobblock) {
+               if (column >= mtd->writesize) {
                        /* OOB area */
-                       column -= mtd->oobblock;
+                       column -= mtd->writesize;
                        readcmd = NAND_CMD_READOOB;
                } else if (column < 256) {
                        /* First 256 bytes --> READ0 */
@@ -570,38 +463,37 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in
                        column -= 256;
                        readcmd = NAND_CMD_READ1;
                }
-               this->write_byte(mtd, readcmd);
+               chip->cmd_ctrl(mtd, readcmd, ctrl);
+               ctrl &= ~NAND_CTRL_CHANGE;
        }
-       this->write_byte(mtd, command);
+       chip->cmd_ctrl(mtd, command, ctrl);
 
-       /* Set ALE and clear CLE to start address cycle */
-       this->hwcontrol(mtd, NAND_CTL_CLRCLE);
-
-       if (column != -1 || page_addr != -1) {
-               this->hwcontrol(mtd, NAND_CTL_SETALE);
-
-               /* Serially input address */
-               if (column != -1) {
-                       /* Adjust columns for 16 bit buswidth */
-                       if (this->options & NAND_BUSWIDTH_16)
-                               column >>= 1;
-                       this->write_byte(mtd, column);
-               }
-               if (page_addr != -1) {
-                       this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
-                       this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
-                       /* One more address cycle for devices > 32MiB */
-                       if (this->chipsize > (32 << 20))
-                               this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));
-               }
-               /* Latch in address */
-               this->hwcontrol(mtd, NAND_CTL_CLRALE);
+       /*
+        * Address cycle, when necessary
+        */
+       ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
+       /* Serially input address */
+       if (column != -1) {
+               /* Adjust columns for 16 bit buswidth */
+               if (chip->options & NAND_BUSWIDTH_16)
+                       column >>= 1;
+               chip->cmd_ctrl(mtd, column, ctrl);
+               ctrl &= ~NAND_CTRL_CHANGE;
        }
+       if (page_addr != -1) {
+               chip->cmd_ctrl(mtd, page_addr, ctrl);
+               ctrl &= ~NAND_CTRL_CHANGE;
+               chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
+               /* One more address cycle for devices > 32MiB */
+               if (chip->chipsize > (32 << 20))
+                       chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
+       }
+       chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
        /*
         * program and erase have their own busy handlers
         * status and sequential in needs no delay
-       */
+        */
        switch (command) {
 
        case NAND_CMD_PAGEPROG:
@@ -612,29 +504,30 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in
                return;
 
        case NAND_CMD_RESET:
-               if (this->dev_ready)
+               if (chip->dev_ready)
                        break;
-               udelay(this->chip_delay);
-               this->hwcontrol(mtd, NAND_CTL_SETCLE);
-               this->write_byte(mtd, NAND_CMD_STATUS);
-               this->hwcontrol(mtd, NAND_CTL_CLRCLE);
-               while ( !(this->read_byte(mtd) & NAND_STATUS_READY));
+               udelay(chip->chip_delay);
+               chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
+                              NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+               chip->cmd_ctrl(mtd,
+                              NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+               while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
                return;
 
-       /* This applies to read commands */
+               /* This applies to read commands */
        default:
                /*
                 * If we don't have access to the busy pin, we apply the given
                 * command delay
-               */
-               if (!this->dev_ready) {
-                       udelay (this->chip_delay);
+                */
+               if (!chip->dev_ready) {
+                       udelay(chip->chip_delay);
                        return;
                }
        }
        /* Apply this short delay always to ensure that we do wait tWB in
         * any case on any machine. */
-       ndelay (100);
+       ndelay(100);
 
        nand_wait_ready(mtd);
 }
@@ -646,50 +539,49 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in
  * @column:    the column address for this command, -1 if none
  * @page_addr: the page address for this command, -1 if none
  *
- * Send command to NAND device. This is the version for the new large page devices
- * We dont have the seperate regions as we have in the small page devices.
- * We must emulate NAND_CMD_READOOB to keep the code compatible.
+ * Send command to NAND device. This is the version for the new large page
+ * devices We dont have the separate regions as we have in the small page
+ * devices.  We must emulate NAND_CMD_READOOB to keep the code compatible.
  *
  */
-static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, int page_addr)
+static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
+                           int column, int page_addr)
 {
-       register struct nand_chip *this = mtd->priv;
+       register struct nand_chip *chip = mtd->priv;
 
        /* Emulate NAND_CMD_READOOB */
        if (command == NAND_CMD_READOOB) {
-               column += mtd->oobblock;
+               column += mtd->writesize;
                command = NAND_CMD_READ0;
        }
 
-
-       /* Begin command latch cycle */
-       this->hwcontrol(mtd, NAND_CTL_SETCLE);
-       /* Write out the command to the device. */
-       this->write_byte(mtd, (command & 0xff));
-       /* End command latch cycle */
-       this->hwcontrol(mtd, NAND_CTL_CLRCLE);
+       /* Command latch cycle */
+       chip->cmd_ctrl(mtd, command & 0xff,
+                      NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
 
        if (column != -1 || page_addr != -1) {
-               this->hwcontrol(mtd, NAND_CTL_SETALE);
+               int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
 
                /* Serially input address */
                if (column != -1) {
                        /* Adjust columns for 16 bit buswidth */
-                       if (this->options & NAND_BUSWIDTH_16)
+                       if (chip->options & NAND_BUSWIDTH_16)
                                column >>= 1;
-                       this->write_byte(mtd, column & 0xff);
-                       this->write_byte(mtd, column >> 8);
+                       chip->cmd_ctrl(mtd, column, ctrl);
+                       ctrl &= ~NAND_CTRL_CHANGE;
+                       chip->cmd_ctrl(mtd, column >> 8, ctrl);
                }
                if (page_addr != -1) {
-                       this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
-                       this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
+                       chip->cmd_ctrl(mtd, page_addr, ctrl);
+                       chip->cmd_ctrl(mtd, page_addr >> 8,
+                                      NAND_NCE | NAND_ALE);
                        /* One more address cycle for devices > 128MiB */
-                       if (this->chipsize > (128 << 20))
-                               this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0xff));
+                       if (chip->chipsize > (128 << 20))
+                               chip->cmd_ctrl(mtd, page_addr >> 16,
+                                              NAND_NCE | NAND_ALE);
                }
-               /* Latch in address */
-               this->hwcontrol(mtd, NAND_CTL_CLRALE);
        }
+       chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
        /*
         * program and erase have their own busy handlers
@@ -702,55 +594,62 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column,
        case NAND_CMD_ERASE1:
        case NAND_CMD_ERASE2:
        case NAND_CMD_SEQIN:
+       case NAND_CMD_RNDIN:
        case NAND_CMD_STATUS:
        case NAND_CMD_DEPLETE1:
                return;
 
-       /*
-        * read error status commands require only a short delay
-        */
+               /*
+                * read error status commands require only a short delay
+                */
        case NAND_CMD_STATUS_ERROR:
        case NAND_CMD_STATUS_ERROR0:
        case NAND_CMD_STATUS_ERROR1:
        case NAND_CMD_STATUS_ERROR2:
        case NAND_CMD_STATUS_ERROR3:
-               udelay(this->chip_delay);
+               udelay(chip->chip_delay);
                return;
 
        case NAND_CMD_RESET:
-               if (this->dev_ready)
+               if (chip->dev_ready)
                        break;
-               udelay(this->chip_delay);
-               this->hwcontrol(mtd, NAND_CTL_SETCLE);
-               this->write_byte(mtd, NAND_CMD_STATUS);
-               this->hwcontrol(mtd, NAND_CTL_CLRCLE);
-               while ( !(this->read_byte(mtd) & NAND_STATUS_READY));
+               udelay(chip->chip_delay);
+               chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
+                              NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+               chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+                              NAND_NCE | NAND_CTRL_CHANGE);
+               while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
+               return;
+
+       case NAND_CMD_RNDOUT:
+               /* No ready / busy check necessary */
+               chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART,
+                              NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+               chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+                              NAND_NCE | NAND_CTRL_CHANGE);
                return;
 
        case NAND_CMD_READ0:
-               /* Begin command latch cycle */
-               this->hwcontrol(mtd, NAND_CTL_SETCLE);
-               /* Write out the start read command */
-               this->write_byte(mtd, NAND_CMD_READSTART);
-               /* End command latch cycle */
-               this->hwcontrol(mtd, NAND_CTL_CLRCLE);
-               /* Fall through into ready check */
-
-       /* This applies to read commands */
+               chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
+                              NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+               chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+                              NAND_NCE | NAND_CTRL_CHANGE);
+
+               /* This applies to read commands */
        default:
                /*
                 * If we don't have access to the busy pin, we apply the given
                 * command delay
-               */
-               if (!this->dev_ready) {
-                       udelay (this->chip_delay);
+                */
+               if (!chip->dev_ready) {
+                       udelay(chip->chip_delay);
                        return;
                }
        }
 
        /* Apply this short delay always to ensure that we do wait tWB in
         * any case on any machine. */
-       ndelay (100);
+       ndelay(100);
 
        nand_wait_ready(mtd);
 }
@@ -763,34 +662,28 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column,
  *
  * Get the device and lock it for exclusive access
  */
-static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state)
+static int
+nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
 {
-       struct nand_chip *active;
-       spinlock_t *lock;
-       wait_queue_head_t *wq;
-       DECLARE_WAITQUEUE (wait, current);
-
-       lock = (this->controller) ? &this->controller->lock : &this->chip_lock;
-       wq = (this->controller) ? &this->controller->wq : &this->wq;
-retry:
-       active = this;
+       spinlock_t *lock = &chip->controller->lock;
+       wait_queue_head_t *wq = &chip->controller->wq;
+       DECLARE_WAITQUEUE(wait, current);
+ retry:
        spin_lock(lock);
 
        /* Hardware controller shared among independend devices */
-       if (this->controller) {
-               if (this->controller->active)
-                       active = this->controller->active;
-               else
-                       this->controller->active = this;
-       }
-       if (active == this && this->state == FL_READY) {
-               this->state = new_state;
+       /* Hardware controller shared among independend devices */
+       if (!chip->controller->active)
+               chip->controller->active = chip;
+
+       if (chip->controller->active == chip && chip->state == FL_READY) {
+               chip->state = new_state;
                spin_unlock(lock);
                return 0;
        }
        if (new_state == FL_PM_SUSPENDED) {
                spin_unlock(lock);
-               return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
+               return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
        }
        set_current_state(TASK_UNINTERRUPTIBLE);
        add_wait_queue(wq, &wait);
@@ -804,540 +697,339 @@ retry:
  * nand_wait - [DEFAULT]  wait until the command is done
  * @mtd:       MTD device structure
  * @this:      NAND chip structure
- * @state:     state to select the max. timeout value
  *
  * Wait for command done. This applies to erase and program only
  * Erase can take up to 400ms and program up to 20ms according to
  * general NAND and SmartMedia specs
  *
 */
-static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
+static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
 
-       unsigned long   timeo = jiffies;
-       int     status;
+       unsigned long timeo = jiffies;
+       int status, state = chip->state;
 
        if (state == FL_ERASING)
-                timeo += (HZ * 400) / 1000;
+               timeo += (HZ * 400) / 1000;
        else
-                timeo += (HZ * 20) / 1000;
+               timeo += (HZ * 20) / 1000;
 
        led_trigger_event(nand_led_trigger, LED_FULL);
 
        /* Apply this short delay always to ensure that we do wait tWB in
         * any case on any machine. */
-       ndelay (100);
+       ndelay(100);
 
-       if ((state == FL_ERASING) && (this->options & NAND_IS_AND))
-               this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1);
+       if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
+               chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
        else
-               this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);
+               chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
 
        while (time_before(jiffies, timeo)) {
-               /* Check, if we were interrupted */
-               if (this->state != state)
-                       return 0;
-
-               if (this->dev_ready) {
-                       if (this->dev_ready(mtd))
+               if (chip->dev_ready) {
+                       if (chip->dev_ready(mtd))
                                break;
                } else {
-                       if (this->read_byte(mtd) & NAND_STATUS_READY)
+                       if (chip->read_byte(mtd) & NAND_STATUS_READY)
                                break;
                }
                cond_resched();
        }
        led_trigger_event(nand_led_trigger, LED_OFF);
 
-       status = (int) this->read_byte(mtd);
+       status = (int)chip->read_byte(mtd);
        return status;
 }
 
 /**
- * nand_write_page - [GENERIC] write one page
- * @mtd:       MTD device structure
- * @this:      NAND chip structure
- * @page:      startpage inside the chip, must be called with (page & this->pagemask)
- * @oob_buf:   out of band data buffer
- * @oobsel:    out of band selecttion structre
- * @cached:    1 = enable cached programming if supported by chip
- *
- * Nand_page_program function is used for write and writev !
- * This function will always program a full page of data
- * If you call it with a non page aligned buffer, you're lost :)
- *
- * Cached programming is not supported yet.
+ * nand_read_page_raw - [Intern] read raw page data without ecc
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       buffer to store read data
  */
-static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page,
-       u_char *oob_buf,  struct nand_oobinfo *oobsel, int cached)
+static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+                             uint8_t *buf)
 {
-       int     i, status;
-       u_char  ecc_code[32];
-       int     eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
-       int     *oob_config = oobsel->eccpos;
-       int     datidx = 0, eccidx = 0, eccsteps = this->eccsteps;
-       int     eccbytes = 0;
-
-       /* FIXME: Enable cached programming */
-       cached = 0;
-
-       /* Send command to begin auto page programming */
-       this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page);
+       chip->read_buf(mtd, buf, mtd->writesize);
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+       return 0;
+}
 
-       /* Write out complete page of data, take care of eccmode */
-       switch (eccmode) {
-       /* No ecc, write all */
-       case NAND_ECC_NONE:
-               printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
-               this->write_buf(mtd, this->data_poi, mtd->oobblock);
-               break;
+/**
+ * nand_read_page_swecc - {REPLACABLE] software ecc based page read function
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       buffer to store read data
+ */
+static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
+                               uint8_t *buf)
+{
+       int i, eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       int eccsteps = chip->ecc.steps;
+       uint8_t *p = buf;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
+       uint8_t *ecc_code = chip->buffers.ecccode;
+       int *eccpos = chip->ecc.layout->eccpos;
 
-       /* Software ecc 3/256, write all */
-       case NAND_ECC_SOFT:
-               for (; eccsteps; eccsteps--) {
-                       this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
-                       for (i = 0; i < 3; i++, eccidx++)
-                               oob_buf[oob_config[eccidx]] = ecc_code[i];
-                       datidx += this->eccsize;
-               }
-               this->write_buf(mtd, this->data_poi, mtd->oobblock);
-               break;
-       default:
-               eccbytes = this->eccbytes;
-               for (; eccsteps; eccsteps--) {
-                       /* enable hardware ecc logic for write */
-                       this->enable_hwecc(mtd, NAND_ECC_WRITE);
-                       this->write_buf(mtd, &this->data_poi[datidx], this->eccsize);
-                       this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
-                       for (i = 0; i < eccbytes; i++, eccidx++)
-                               oob_buf[oob_config[eccidx]] = ecc_code[i];
-                       /* If the hardware ecc provides syndromes then
-                        * the ecc code must be written immidiately after
-                        * the data bytes (words) */
-                       if (this->options & NAND_HWECC_SYNDROME)
-                               this->write_buf(mtd, ecc_code, eccbytes);
-                       datidx += this->eccsize;
-               }
-               break;
-       }
+       nand_read_page_raw(mtd, chip, buf);
 
-       /* Write out OOB data */
-       if (this->options & NAND_HWECC_SYNDROME)
-               this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
-       else
-               this->write_buf(mtd, oob_buf, mtd->oobsize);
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+               chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 
-       /* Send command to actually program the data */
-       this->cmdfunc (mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
+       for (i = 0; i < chip->ecc.total; i++)
+               ecc_code[i] = chip->oob_poi[eccpos[i]];
 
-       if (!cached) {
-               /* call wait ready function */
-               status = this->waitfunc (mtd, this, FL_WRITING);
+       eccsteps = chip->ecc.steps;
+       p = buf;
 
-               /* See if operation failed and additional status checks are available */
-               if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
-                       status = this->errstat(mtd, this, FL_WRITING, status, page);
-               }
+       for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+               int stat;
 
-               /* See if device thinks it succeeded */
-               if (status & NAND_STATUS_FAIL) {
-                       DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
-                       return -EIO;
-               }
-       } else {
-               /* FIXME: Implement cached programming ! */
-               /* wait until cache is ready*/
-               // status = this->waitfunc (mtd, this, FL_CACHEDRPG);
+               stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
+               if (stat == -1)
+                       mtd->ecc_stats.failed++;
+               else
+                       mtd->ecc_stats.corrected += stat;
        }
        return 0;
 }
 
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
 /**
- * nand_verify_pages - [GENERIC] verify the chip contents after a write
- * @mtd:       MTD device structure
- * @this:      NAND chip structure
- * @page:      startpage inside the chip, must be called with (page & this->pagemask)
- * @numpages:  number of pages to verify
- * @oob_buf:   out of band data buffer
- * @oobsel:    out of band selecttion structre
- * @chipnr:    number of the current chip
- * @oobmode:   1 = full buffer verify, 0 = ecc only
+ * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       buffer to store read data
  *
- * The NAND device assumes that it is always writing to a cleanly erased page.
- * Hence, it performs its internal write verification only on bits that
- * transitioned from 1 to 0. The device does NOT verify the whole page on a
- * byte by byte basis. It is possible that the page was not completely erased
- * or the page is becoming unusable due to wear. The read with ECC would catch
- * the error later when the ECC page check fails, but we would rather catch
- * it early in the page write stage. Better to write no data than invalid data.
+ * Not for syndrome calculating ecc controllers which need a special oob layout
  */
-static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
-       u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
+static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+                               uint8_t *buf)
 {
-       int     i, j, datidx = 0, oobofs = 0, res = -EIO;
-       int     eccsteps = this->eccsteps;
-       int     hweccbytes;
-       u_char  oobdata[64];
-
-       hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
-
-       /* Send command to read back the first page */
-       this->cmdfunc (mtd, NAND_CMD_READ0, 0, page);
-
-       for(;;) {
-               for (j = 0; j < eccsteps; j++) {
-                       /* Loop through and verify the data */
-                       if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) {
-                               DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-                               goto out;
-                       }
-                       datidx += mtd->eccsize;
-                       /* Have we a hw generator layout ? */
-                       if (!hweccbytes)
-                               continue;
-                       if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) {
-                               DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-                               goto out;
-                       }
-                       oobofs += hweccbytes;
-               }
+       int i, eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       int eccsteps = chip->ecc.steps;
+       uint8_t *p = buf;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
+       uint8_t *ecc_code = chip->buffers.ecccode;
+       int *eccpos = chip->ecc.layout->eccpos;
+
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+               chip->ecc.hwctl(mtd, NAND_ECC_READ);
+               chip->read_buf(mtd, p, eccsize);
+               chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+       }
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 
-               /* check, if we must compare all data or if we just have to
-                * compare the ecc bytes
-                */
-               if (oobmode) {
-                       if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) {
-                               DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-                               goto out;
-                       }
-               } else {
-                       /* Read always, else autoincrement fails */
-                       this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
-
-                       if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
-                               int ecccnt = oobsel->eccbytes;
-
-                               for (i = 0; i < ecccnt; i++) {
-                                       int idx = oobsel->eccpos[i];
-                                       if (oobdata[idx] != oob_buf[oobofs + idx] ) {
-                                               DEBUG (MTD_DEBUG_LEVEL0,
-                                               "%s: Failed ECC write "
-                                               "verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i);
-                                               goto out;
-                                       }
-                               }
-                       }
-               }
-               oobofs += mtd->oobsize - hweccbytes * eccsteps;
-               page++;
-               numpages--;
-
-               /* Apply delay or wait for ready/busy pin
-                * Do this before the AUTOINCR check, so no problems
-                * arise if a chip which does auto increment
-                * is marked as NOAUTOINCR by the board driver.
-                * Do this also before returning, so the chip is
-                * ready for the next command.
-               */
-               if (!this->dev_ready)
-                       udelay (this->chip_delay);
-               else
-                       nand_wait_ready(mtd);
+       for (i = 0; i < chip->ecc.total; i++)
+               ecc_code[i] = chip->oob_poi[eccpos[i]];
 
-               /* All done, return happy */
-               if (!numpages)
-                       return 0;
+       eccsteps = chip->ecc.steps;
+       p = buf;
 
+       for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+               int stat;
 
-               /* Check, if the chip supports auto page increment */
-               if (!NAND_CANAUTOINCR(this))
-                       this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
+               stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
+               if (stat == -1)
+                       mtd->ecc_stats.failed++;
+               else
+                       mtd->ecc_stats.corrected += stat;
        }
-       /*
-        * Terminate the read command. We come here in case of an error
-        * So we must issue a reset command.
-        */
-out:
-       this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1);
-       return res;
+       return 0;
 }
-#endif
 
 /**
- * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
- * @mtd:       MTD device structure
- * @from:      offset to read from
- * @len:       number of bytes to read
- * @retlen:    pointer to variable to store the number of read bytes
- * @buf:       the databuffer to put data
+ * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       buffer to store read data
  *
- * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL
- * and flags = 0xff
+ * The hw generator calculates the error syndrome automatically. Therefor
+ * we need a special oob layout and handling.
  */
-static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
+static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+                                  uint8_t *buf)
 {
-       return nand_do_read_ecc (mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff);
-}
+       int i, eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       int eccsteps = chip->ecc.steps;
+       uint8_t *p = buf;
+       uint8_t *oob = chip->oob_poi;
+
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+               int stat;
+
+               chip->ecc.hwctl(mtd, NAND_ECC_READ);
+               chip->read_buf(mtd, p, eccsize);
+
+               if (chip->ecc.prepad) {
+                       chip->read_buf(mtd, oob, chip->ecc.prepad);
+                       oob += chip->ecc.prepad;
+               }
+
+               chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
+               chip->read_buf(mtd, oob, eccbytes);
+               stat = chip->ecc.correct(mtd, p, oob, NULL);
+
+               if (stat == -1)
+                       mtd->ecc_stats.failed++;
+               else
+                       mtd->ecc_stats.corrected += stat;
 
+               oob += eccbytes;
+
+               if (chip->ecc.postpad) {
+                       chip->read_buf(mtd, oob, chip->ecc.postpad);
+                       oob += chip->ecc.postpad;
+               }
+       }
+
+       /* Calculate remaining oob bytes */
+       i = mtd->oobsize - (oob - chip->oob_poi);
+       if (i)
+               chip->read_buf(mtd, oob, i);
+
+       return 0;
+}
 
 /**
- * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc
- * @mtd:       MTD device structure
- * @from:      offset to read from
- * @len:       number of bytes to read
- * @retlen:    pointer to variable to store the number of read bytes
- * @buf:       the databuffer to put data
- * @oob_buf:   filesystem supplied oob data buffer
- * @oobsel:    oob selection structure
- *
- * This function simply calls nand_do_read_ecc with flags = 0xff
+ * nand_transfer_oob - [Internal] Transfer oob to client buffer
+ * @chip:      nand chip structure
+ * @ops:       oob ops structure
  */
-static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-                         size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel)
+static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
+                                 struct mtd_oob_ops *ops)
 {
-       /* use userspace supplied oobinfo, if zero */
-       if (oobsel == NULL)
-               oobsel = &mtd->oobinfo;
-       return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff);
+       size_t len = ops->ooblen;
+
+       switch(ops->mode) {
+
+       case MTD_OOB_PLACE:
+       case MTD_OOB_RAW:
+               memcpy(oob, chip->oob_poi + ops->ooboffs, len);
+               return oob + len;
+
+       case MTD_OOB_AUTO: {
+               struct nand_oobfree *free = chip->ecc.layout->oobfree;
+               uint32_t boffs = 0, roffs = ops->ooboffs;
+               size_t bytes = 0;
+
+               for(; free->length && len; free++, len -= bytes) {
+                       /* Read request not from offset 0 ? */
+                       if (unlikely(roffs)) {
+                               if (roffs >= free->length) {
+                                       roffs -= free->length;
+                                       continue;
+                               }
+                               boffs = free->offset + roffs;
+                               bytes = min_t(size_t, len,
+                                             (free->length - roffs));
+                               roffs = 0;
+                       } else {
+                               bytes = min_t(size_t, len, free->length);
+                               boffs = free->offset;
+                       }
+                       memcpy(oob, chip->oob_poi + boffs, bytes);
+                       oob += bytes;
+               }
+               return oob;
+       }
+       default:
+               BUG();
+       }
+       return NULL;
 }
 
-
 /**
- * nand_do_read_ecc - [MTD Interface] Read data with ECC
+ * nand_do_read_ops - [Internal] Read data with ECC
+ *
  * @mtd:       MTD device structure
  * @from:      offset to read from
- * @len:       number of bytes to read
- * @retlen:    pointer to variable to store the number of read bytes
- * @buf:       the databuffer to put data
- * @oob_buf:   filesystem supplied oob data buffer (can be NULL)
- * @oobsel:    oob selection structure
- * @flags:     flag to indicate if nand_get_device/nand_release_device should be preformed
- *             and how many corrected error bits are acceptable:
- *               bits 0..7 - number of tolerable errors
- *               bit  8    - 0 == do not get/release chip, 1 == get/release chip
  *
- * NAND read with ECC
+ * Internal function. Called with chip held.
  */
-int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-                            size_t * retlen, u_char * buf, u_char * oob_buf,
-                            struct nand_oobinfo *oobsel, int flags)
+static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
+                           struct mtd_oob_ops *ops)
 {
+       int chipnr, page, realpage, col, bytes, aligned;
+       struct nand_chip *chip = mtd->priv;
+       struct mtd_ecc_stats stats;
+       int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
+       int sndcmd = 1;
+       int ret = 0;
+       uint32_t readlen = ops->len;
+       uint8_t *bufpoi, *oob, *buf;
 
-       int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
-       int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
-       struct nand_chip *this = mtd->priv;
-       u_char *data_poi, *oob_data = oob_buf;
-       u_char ecc_calc[32];
-       u_char ecc_code[32];
-        int eccmode, eccsteps;
-       int     *oob_config, datidx;
-       int     blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
-       int     eccbytes;
-       int     compareecc = 1;
-       int     oobreadlen;
-
-
-       DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
-
-       /* Do not allow reads past end of device */
-       if ((from + len) > mtd->size) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
-               *retlen = 0;
-               return -EINVAL;
-       }
-
-       /* Grab the lock and see if the device is available */
-       if (flags & NAND_GET_DEVICE)
-               nand_get_device (this, mtd, FL_READING);
-
-       /* Autoplace of oob data ? Use the default placement scheme */
-       if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
-               oobsel = this->autooob;
-
-       eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
-       oob_config = oobsel->eccpos;
-
-       /* Select the NAND device */
-       chipnr = (int)(from >> this->chip_shift);
-       this->select_chip(mtd, chipnr);
-
-       /* First we calculate the starting page */
-       realpage = (int) (from >> this->page_shift);
-       page = realpage & this->pagemask;
-
-       /* Get raw starting column */
-       col = from & (mtd->oobblock - 1);
-
-       end = mtd->oobblock;
-       ecc = this->eccsize;
-       eccbytes = this->eccbytes;
-
-       if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))
-               compareecc = 0;
-
-       oobreadlen = mtd->oobsize;
-       if (this->options & NAND_HWECC_SYNDROME)
-               oobreadlen -= oobsel->eccbytes;
+       stats = mtd->ecc_stats;
 
-       /* Loop until all data read */
-       while (read < len) {
+       chipnr = (int)(from >> chip->chip_shift);
+       chip->select_chip(mtd, chipnr);
 
-               int aligned = (!col && (len - read) >= end);
-               /*
-                * If the read is not page aligned, we have to read into data buffer
-                * due to ecc, else we read into return buffer direct
-                */
-               if (aligned)
-                       data_poi = &buf[read];
-               else
-                       data_poi = this->data_buf;
+       realpage = (int)(from >> chip->page_shift);
+       page = realpage & chip->pagemask;
 
-               /* Check, if we have this page in the buffer
-                *
-                * FIXME: Make it work when we must provide oob data too,
-                * check the usage of data_buf oob field
-                */
-               if (realpage == this->pagebuf && !oob_buf) {
-                       /* aligned read ? */
-                       if (aligned)
-                               memcpy (data_poi, this->data_buf, end);
-                       goto readdata;
-               }
+       col = (int)(from & (mtd->writesize - 1));
+       chip->oob_poi = chip->buffers.oobrbuf;
 
-               /* Check, if we must send the read command */
-               if (sndcmd) {
-                       this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
-                       sndcmd = 0;
-               }
+       buf = ops->datbuf;
+       oob = ops->oobbuf;
 
-               /* get oob area, if we have no oob buffer from fs-driver */
-               if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE ||
-                       oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
-                       oob_data = &this->data_buf[end];
+       while(1) {
+               bytes = min(mtd->writesize - col, readlen);
+               aligned = (bytes == mtd->writesize);
 
-               eccsteps = this->eccsteps;
+               /* Is the current page in the buffer ? */
+               if (realpage != chip->pagebuf || oob) {
+                       bufpoi = aligned ? buf : chip->buffers.databuf;
 
-               switch (eccmode) {
-               case NAND_ECC_NONE: {   /* No ECC, Read in a page */
-                       static unsigned long lastwhinge = 0;
-                       if ((lastwhinge / HZ) != (jiffies / HZ)) {
-                               printk (KERN_WARNING "Reading data from NAND FLASH without ECC is not recommended\n");
-                               lastwhinge = jiffies;
+                       if (likely(sndcmd)) {
+                               chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+                               sndcmd = 0;
                        }
-                       this->read_buf(mtd, data_poi, end);
-                       break;
-               }
 
-               case NAND_ECC_SOFT:     /* Software ECC 3/256: Read in a page + oob data */
-                       this->read_buf(mtd, data_poi, end);
-                       for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc)
-                               this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
-                       break;
+                       /* Now read the page into the buffer */
+                       ret = chip->ecc.read_page(mtd, chip, bufpoi);
+                       if (ret < 0)
+                               break;
 
-               default:
-                       for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) {
-                               this->enable_hwecc(mtd, NAND_ECC_READ);
-                               this->read_buf(mtd, &data_poi[datidx], ecc);
-
-                               /* HW ecc with syndrome calculation must read the
-                                * syndrome from flash immidiately after the data */
-                               if (!compareecc) {
-                                       /* Some hw ecc generators need to know when the
-                                        * syndrome is read from flash */
-                                       this->enable_hwecc(mtd, NAND_ECC_READSYN);
-                                       this->read_buf(mtd, &oob_data[i], eccbytes);
-                                       /* We calc error correction directly, it checks the hw
-                                        * generator for an error, reads back the syndrome and
-                                        * does the error correction on the fly */
-                                       ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
-                                       if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
-                                               DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: "
-                                                       "Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
-                                               ecc_failed++;
-                                       }
-                               } else {
-                                       this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
-                               }
+                       /* Transfer not aligned data */
+                       if (!aligned) {
+                               chip->pagebuf = realpage;
+                               memcpy(buf, chip->buffers.databuf + col, bytes);
                        }
-                       break;
-               }
-
-               /* read oobdata */
-               this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
-
-               /* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
-               if (!compareecc)
-                       goto readoob;
 
-               /* Pick the ECC bytes out of the oob data */
-               for (j = 0; j < oobsel->eccbytes; j++)
-                       ecc_code[j] = oob_data[oob_config[j]];
+                       buf += bytes;
 
-               /* correct data, if neccecary */
-               for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) {
-                       ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
-
-                       /* Get next chunk of ecc bytes */
-                       j += eccbytes;
-
-                       /* Check, if we have a fs supplied oob-buffer,
-                        * This is the legacy mode. Used by YAFFS1
-                        * Should go away some day
-                        */
-                       if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {
-                               int *p = (int *)(&oob_data[mtd->oobsize]);
-                               p[i] = ecc_status;
+                       if (unlikely(oob)) {
+                               /* Raw mode does data:oob:data:oob */
+                               if (ops->mode != MTD_OOB_RAW)
+                                       oob = nand_transfer_oob(chip, oob, ops);
+                               else
+                                       buf = nand_transfer_oob(chip, buf, ops);
                        }
 
-                       if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
-                               DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);
-                               ecc_failed++;
+                       if (!(chip->options & NAND_NO_READRDY)) {
+                               /*
+                                * Apply delay or wait for ready/busy pin. Do
+                                * this before the AUTOINCR check, so no
+                                * problems arise if a chip which does auto
+                                * increment is marked as NOAUTOINCR by the
+                                * board driver.
+                                */
+                               if (!chip->dev_ready)
+                                       udelay(chip->chip_delay);
+                               else
+                                       nand_wait_ready(mtd);
                        }
+               } else {
+                       memcpy(buf, chip->buffers.databuf + col, bytes);
+                       buf += bytes;
                }
 
-       readoob:
-               /* check, if we have a fs supplied oob-buffer */
-               if (oob_buf) {
-                       /* without autoplace. Legacy mode used by YAFFS1 */
-                       switch(oobsel->useecc) {
-                       case MTD_NANDECC_AUTOPLACE:
-                       case MTD_NANDECC_AUTOPL_USR:
-                               /* Walk through the autoplace chunks */
-                               for (i = 0; oobsel->oobfree[i][1]; i++) {
-                                       int from = oobsel->oobfree[i][0];
-                                       int num = oobsel->oobfree[i][1];
-                                       memcpy(&oob_buf[oob], &oob_data[from], num);
-                                       oob += num;
-                               }
-                               break;
-                       case MTD_NANDECC_PLACE:
-                               /* YAFFS1 legacy mode */
-                               oob_data += this->eccsteps * sizeof (int);
-                       default:
-                               oob_data += mtd->oobsize;
-                       }
-               }
-       readdata:
-               /* Partial page read, transfer data into fs buffer */
-               if (!aligned) {
-                       for (j = col; j < end && read < len; j++)
-                               buf[read++] = data_poi[j];
-                       this->pagebuf = realpage;
-               } else
-                       read += mtd->oobblock;
-
-               /* Apply delay or wait for ready/busy pin
-                * Do this before the AUTOINCR check, so no problems
-                * arise if a chip which does auto increment
-                * is marked as NOAUTOINCR by the board driver.
-               */
-               if (!this->dev_ready)
-                       udelay (this->chip_delay);
-               else
-                       nand_wait_ready(mtd);
+               readlen -= bytes;
 
-               if (read == len)
+               if (!readlen)
                        break;
 
                /* For subsequent reads align to page boundary. */
@@ -1345,701 +1037,775 @@ int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
                /* Increment page address */
                realpage++;
 
-               page = realpage & this->pagemask;
+               page = realpage & chip->pagemask;
                /* Check, if we cross a chip boundary */
                if (!page) {
                        chipnr++;
-                       this->select_chip(mtd, -1);
-                       this->select_chip(mtd, chipnr);
+                       chip->select_chip(mtd, -1);
+                       chip->select_chip(mtd, chipnr);
                }
+
                /* Check, if the chip supports auto page increment
                 * or if we have hit a block boundary.
-               */
-               if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
+                */
+               if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
                        sndcmd = 1;
        }
 
-       /* Deselect and wake up anyone waiting on the device */
-       if (flags & NAND_GET_DEVICE)
-               nand_release_device(mtd);
+       ops->retlen = ops->len - (size_t) readlen;
 
-       /*
-        * Return success, if no ECC failures, else -EBADMSG
-        * fs driver will take care of that, because
-        * retlen == desired len and result == -EBADMSG
-        */
-       *retlen = read;
-       return ecc_failed ? -EBADMSG : 0;
+       if (ret)
+               return ret;
+
+       if (mtd->ecc_stats.failed - stats.failed)
+               return -EBADMSG;
+
+       return  mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
 }
 
 /**
- * nand_read_oob - [MTD Interface] NAND read out-of-band
+ * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
  * @mtd:       MTD device structure
  * @from:      offset to read from
  * @len:       number of bytes to read
  * @retlen:    pointer to variable to store the number of read bytes
  * @buf:       the databuffer to put data
  *
- * NAND read out-of-band data from the spare area
+ * Get hold of the chip and call nand_do_read
  */
-static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
+static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
+                    size_t *retlen, uint8_t *buf)
 {
-       int i, col, page, chipnr;
-       struct nand_chip *this = mtd->priv;
-       int     blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
-
-       DEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
-
-       /* Shift to get page */
-       page = (int)(from >> this->page_shift);
-       chipnr = (int)(from >> this->chip_shift);
-
-       /* Mask to get column */
-       col = from & (mtd->oobsize - 1);
-
-       /* Initialize return length value */
-       *retlen = 0;
+       struct nand_chip *chip = mtd->priv;
+       int ret;
 
        /* Do not allow reads past end of device */
-       if ((from + len) > mtd->size) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n");
-               *retlen = 0;
+       if ((from + len) > mtd->size)
                return -EINVAL;
-       }
-
-       /* Grab the lock and see if the device is available */
-       nand_get_device (this, mtd , FL_READING);
-
-       /* Select the NAND device */
-       this->select_chip(mtd, chipnr);
+       if (!len)
+               return 0;
 
-       /* Send the read command */
-       this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask);
-       /*
-        * Read the data, if we read more than one page
-        * oob data, let the device transfer the data !
-        */
-       i = 0;
-       while (i < len) {
-               int thislen = mtd->oobsize - col;
-               thislen = min_t(int, thislen, len);
-               this->read_buf(mtd, &buf[i], thislen);
-               i += thislen;
-
-               /* Read more ? */
-               if (i < len) {
-                       page++;
-                       col = 0;
-
-                       /* Check, if we cross a chip boundary */
-                       if (!(page & this->pagemask)) {
-                               chipnr++;
-                               this->select_chip(mtd, -1);
-                               this->select_chip(mtd, chipnr);
-                       }
+       nand_get_device(chip, mtd, FL_READING);
 
-                       /* Apply delay or wait for ready/busy pin
-                        * Do this before the AUTOINCR check, so no problems
-                        * arise if a chip which does auto increment
-                        * is marked as NOAUTOINCR by the board driver.
-                        */
-                       if (!this->dev_ready)
-                               udelay (this->chip_delay);
-                       else
-                               nand_wait_ready(mtd);
+       chip->ops.len = len;
+       chip->ops.datbuf = buf;
+       chip->ops.oobbuf = NULL;
 
-                       /* Check, if the chip supports auto page increment
-                        * or if we have hit a block boundary.
-                       */
-                       if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) {
-                               /* For subsequent page reads set offset to 0 */
-                               this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);
-                       }
-               }
-       }
+       ret = nand_do_read_ops(mtd, from, &chip->ops);
 
-       /* Deselect and wake up anyone waiting on the device */
        nand_release_device(mtd);
 
-       /* Return happy */
-       *retlen = len;
-       return 0;
+       *retlen = chip->ops.retlen;
+       return ret;
 }
 
 /**
- * nand_read_raw - [GENERIC] Read raw data including oob into buffer
- * @mtd:       MTD device structure
- * @buf:       temporary buffer
- * @from:      offset to read from
- * @len:       number of bytes to read
- * @ooblen:    number of oob data bytes to read
- *
- * Read raw data including oob into buffer
+ * nand_read_oob_std - [REPLACABLE] the most common OOB data read function
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @page:      page number to read
+ * @sndcmd:    flag whether to issue read command or not
  */
-int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen)
+static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
+                            int page, int sndcmd)
 {
-       struct nand_chip *this = mtd->priv;
-       int page = (int) (from >> this->page_shift);
-       int chip = (int) (from >> this->chip_shift);
-       int sndcmd = 1;
-       int cnt = 0;
-       int pagesize = mtd->oobblock + mtd->oobsize;
-       int     blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
-
-       /* Do not allow reads past end of device */
-       if ((from + len) > mtd->size) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt read beyond end of device\n");
-               return -EINVAL;
+       if (sndcmd) {
+               chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+               sndcmd = 0;
        }
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+       return sndcmd;
+}
 
-       /* Grab the lock and see if the device is available */
-       nand_get_device (this, mtd , FL_READING);
+/**
+ * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC
+ *                         with syndromes
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @page:      page number to read
+ * @sndcmd:    flag whether to issue read command or not
+ */
+static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+                                 int page, int sndcmd)
+{
+       uint8_t *buf = chip->oob_poi;
+       int length = mtd->oobsize;
+       int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
+       int eccsize = chip->ecc.size;
+       uint8_t *bufpoi = buf;
+       int i, toread, sndrnd = 0, pos;
+
+       chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page);
+       for (i = 0; i < chip->ecc.steps; i++) {
+               if (sndrnd) {
+                       pos = eccsize + i * (eccsize + chunk);
+                       if (mtd->writesize > 512)
+                               chip->cmdfunc(mtd, NAND_CMD_RNDOUT, pos, -1);
+                       else
+                               chip->cmdfunc(mtd, NAND_CMD_READ0, pos, page);
+               } else
+                       sndrnd = 1;
+               toread = min_t(int, length, chunk);
+               chip->read_buf(mtd, bufpoi, toread);
+               bufpoi += toread;
+               length -= toread;
+       }
+       if (length > 0)
+               chip->read_buf(mtd, bufpoi, length);
 
-       this->select_chip (mtd, chip);
+       return 1;
+}
+
+/**
+ * nand_write_oob_std - [REPLACABLE] the most common OOB data write function
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @page:      page number to write
+ */
+static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
+                             int page)
+{
+       int status = 0;
+       const uint8_t *buf = chip->oob_poi;
+       int length = mtd->oobsize;
 
-       /* Add requested oob length */
-       len += ooblen;
+       chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+       chip->write_buf(mtd, buf, length);
+       /* Send command to program the OOB data */
+       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
 
-       while (len) {
-               if (sndcmd)
-                       this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask);
-               sndcmd = 0;
+       status = chip->waitfunc(mtd, chip);
 
-               this->read_buf (mtd, &buf[cnt], pagesize);
+       return status;
+}
 
-               len -= pagesize;
-               cnt += pagesize;
-               page++;
+/**
+ * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC
+ *                          with syndrome - only for large page flash !
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @page:      page number to write
+ */
+static int nand_write_oob_syndrome(struct mtd_info *mtd,
+                                  struct nand_chip *chip, int page)
+{
+       int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
+       int eccsize = chip->ecc.size, length = mtd->oobsize;
+       int i, len, pos, status = 0, sndcmd = 0, steps = chip->ecc.steps;
+       const uint8_t *bufpoi = chip->oob_poi;
 
-               if (!this->dev_ready)
-                       udelay (this->chip_delay);
-               else
-                       nand_wait_ready(mtd);
+       /*
+        * data-ecc-data-ecc ... ecc-oob
+        * or
+        * data-pad-ecc-pad-data-pad .... ecc-pad-oob
+        */
+       if (!chip->ecc.prepad && !chip->ecc.postpad) {
+               pos = steps * (eccsize + chunk);
+               steps = 0;
+       } else
+               pos = eccsize + chunk;
 
-               /* Check, if the chip supports auto page increment */
-               if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
+       chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
+       for (i = 0; i < steps; i++) {
+               if (sndcmd) {
+                       if (mtd->writesize <= 512) {
+                               uint32_t fill = 0xFFFFFFFF;
+
+                               len = eccsize;
+                               while (len > 0) {
+                                       int num = min_t(int, len, 4);
+                                       chip->write_buf(mtd, (uint8_t *)&fill,
+                                                       num);
+                                       len -= num;
+                               }
+                       } else {
+                               pos = eccsize + i * (eccsize + chunk);
+                               chip->cmdfunc(mtd, NAND_CMD_RNDIN, pos, -1);
+                       }
+               } else
                        sndcmd = 1;
+               len = min_t(int, length, chunk);
+               chip->write_buf(mtd, bufpoi, len);
+               bufpoi += len;
+               length -= len;
        }
+       if (length > 0)
+               chip->write_buf(mtd, bufpoi, length);
 
-       /* Deselect and wake up anyone waiting on the device */
-       nand_release_device(mtd);
-       return 0;
-}
+       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+       status = chip->waitfunc(mtd, chip);
 
+       return status & NAND_STATUS_FAIL ? -EIO : 0;
+}
 
 /**
- * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
+ * nand_do_read_oob - [Intern] NAND read out-of-band
  * @mtd:       MTD device structure
- * @fsbuf:     buffer given by fs driver
- * @oobsel:    out of band selection structre
- * @autoplace: 1 = place given buffer into the oob bytes
- * @numpages:  number of pages to prepare
- *
- * Return:
- * 1. Filesystem buffer available and autoplacement is off,
- *    return filesystem buffer
- * 2. No filesystem buffer or autoplace is off, return internal
- *    buffer
- * 3. Filesystem buffer is given and autoplace selected
- *    put data from fs buffer into internal buffer and
- *    retrun internal buffer
- *
- * Note: The internal buffer is filled with 0xff. This must
- * be done only once, when no autoplacement happens
- * Autoplacement sets the buffer dirty flag, which
- * forces the 0xff fill before using the buffer again.
+ * @from:      offset to read from
+ * @ops:       oob operations description structure
  *
-*/
-static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct nand_oobinfo *oobsel,
-               int autoplace, int numpages)
+ * NAND read out-of-band data from the spare area
+ */
+static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
+                           struct mtd_oob_ops *ops)
 {
-       struct nand_chip *this = mtd->priv;
-       int i, len, ofs;
-
-       /* Zero copy fs supplied buffer */
-       if (fsbuf && !autoplace)
-               return fsbuf;
-
-       /* Check, if the buffer must be filled with ff again */
-       if (this->oobdirty) {
-               memset (this->oob_buf, 0xff,
-                       mtd->oobsize << (this->phys_erase_shift - this->page_shift));
-               this->oobdirty = 0;
-       }
+       int page, realpage, chipnr, sndcmd = 1;
+       struct nand_chip *chip = mtd->priv;
+       int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
+       int readlen = ops->len;
+       uint8_t *buf = ops->oobbuf;
+
+       DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n",
+             (unsigned long long)from, readlen);
+
+       chipnr = (int)(from >> chip->chip_shift);
+       chip->select_chip(mtd, chipnr);
+
+       /* Shift to get page */
+       realpage = (int)(from >> chip->page_shift);
+       page = realpage & chip->pagemask;
+
+       chip->oob_poi = chip->buffers.oobrbuf;
+
+       while(1) {
+               sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
+               buf = nand_transfer_oob(chip, buf, ops);
 
-       /* If we have no autoplacement or no fs buffer use the internal one */
-       if (!autoplace || !fsbuf)
-               return this->oob_buf;
-
-       /* Walk through the pages and place the data */
-       this->oobdirty = 1;
-       ofs = 0;
-       while (numpages--) {
-               for (i = 0, len = 0; len < mtd->oobavail; i++) {
-                       int to = ofs + oobsel->oobfree[i][0];
-                       int num = oobsel->oobfree[i][1];
-                       memcpy (&this->oob_buf[to], fsbuf, num);
-                       len += num;
-                       fsbuf += num;
+               readlen -= ops->ooblen;
+               if (!readlen)
+                       break;
+
+               if (!(chip->options & NAND_NO_READRDY)) {
+                       /*
+                        * Apply delay or wait for ready/busy pin. Do this
+                        * before the AUTOINCR check, so no problems arise if a
+                        * chip which does auto increment is marked as
+                        * NOAUTOINCR by the board driver.
+                        */
+                       if (!chip->dev_ready)
+                               udelay(chip->chip_delay);
+                       else
+                               nand_wait_ready(mtd);
                }
-               ofs += mtd->oobavail;
+
+               /* Increment page address */
+               realpage++;
+
+               page = realpage & chip->pagemask;
+               /* Check, if we cross a chip boundary */
+               if (!page) {
+                       chipnr++;
+                       chip->select_chip(mtd, -1);
+                       chip->select_chip(mtd, chipnr);
+               }
+
+               /* Check, if the chip supports auto page increment
+                * or if we have hit a block boundary.
+                */
+               if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
+                       sndcmd = 1;
        }
-       return this->oob_buf;
-}
 
-#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0
+       ops->retlen = ops->len;
+       return 0;
+}
 
 /**
- * nand_write - [MTD Interface] compability function for nand_write_ecc
+ * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band
  * @mtd:       MTD device structure
- * @to:                offset to write to
- * @len:       number of bytes to write
- * @retlen:    pointer to variable to store the number of written bytes
- * @buf:       the data to write
- *
- * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
+ * @from:      offset to read from
+ * @ops:       oob operation description structure
  *
-*/
-static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
+ * NAND read data and/or out-of-band data
+ */
+static int nand_read_oob(struct mtd_info *mtd, loff_t from,
+                        struct mtd_oob_ops *ops)
 {
-       return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL));
+       int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
+                        uint8_t *buf) = NULL;
+       struct nand_chip *chip = mtd->priv;
+       int ret = -ENOTSUPP;
+
+       ops->retlen = 0;
+
+       /* Do not allow reads past end of device */
+       if ((from + ops->len) > mtd->size) {
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+                     "Attempt read beyond end of device\n");
+               return -EINVAL;
+       }
+
+       nand_get_device(chip, mtd, FL_READING);
+
+       switch(ops->mode) {
+       case MTD_OOB_PLACE:
+       case MTD_OOB_AUTO:
+               break;
+
+       case MTD_OOB_RAW:
+               /* Replace the read_page algorithm temporary */
+               read_page = chip->ecc.read_page;
+               chip->ecc.read_page = nand_read_page_raw;
+               break;
+
+       default:
+               goto out;
+       }
+
+       if (!ops->datbuf)
+               ret = nand_do_read_oob(mtd, from, ops);
+       else
+               ret = nand_do_read_ops(mtd, from, ops);
+
+       if (unlikely(ops->mode == MTD_OOB_RAW))
+               chip->ecc.read_page = read_page;
+ out:
+       nand_release_device(mtd);
+       return ret;
 }
 
+
 /**
- * nand_write_ecc - [MTD Interface] NAND write with ECC
- * @mtd:       MTD device structure
- * @to:                offset to write to
- * @len:       number of bytes to write
- * @retlen:    pointer to variable to store the number of written bytes
- * @buf:       the data to write
- * @eccbuf:    filesystem supplied oob data buffer
- * @oobsel:    oob selection structure
- *
- * NAND write with ECC
+ * nand_write_page_raw - [Intern] raw page write function
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       data buffer
  */
-static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
-                          size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel)
+static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+                               const uint8_t *buf)
 {
-       int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
-       int autoplace = 0, numpages, totalpages;
-       struct nand_chip *this = mtd->priv;
-       u_char *oobbuf, *bufstart;
-       int     ppblock = (1 << (this->phys_erase_shift - this->page_shift));
+       chip->write_buf(mtd, buf, mtd->writesize);
+       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
 
-       DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+/**
+ * nand_write_page_swecc - {REPLACABLE] software ecc based page write function
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       data buffer
+ */
+static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
+                                 const uint8_t *buf)
+{
+       int i, eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       int eccsteps = chip->ecc.steps;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
+       const uint8_t *p = buf;
+       int *eccpos = chip->ecc.layout->eccpos;
 
-       /* Initialize retlen, in case of early exit */
-       *retlen = 0;
+       /* Software ecc calculation */
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+               chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 
-       /* Do not allow write past end of device */
-       if ((to + len) > mtd->size) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n");
-               return -EINVAL;
-       }
+       for (i = 0; i < chip->ecc.total; i++)
+               chip->oob_poi[eccpos[i]] = ecc_calc[i];
 
-       /* reject writes, which are not page aligned */
-       if (NOTALIGNED (to) || NOTALIGNED(len)) {
-               printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
-               return -EINVAL;
+       nand_write_page_raw(mtd, chip, buf);
+}
+
+/**
+ * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       data buffer
+ */
+static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+                                 const uint8_t *buf)
+{
+       int i, eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       int eccsteps = chip->ecc.steps;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
+       const uint8_t *p = buf;
+       int *eccpos = chip->ecc.layout->eccpos;
+
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+               chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+               chip->write_buf(mtd, p, eccsize);
+               chip->ecc.calculate(mtd, p, &ecc_calc[i]);
        }
 
-       /* Grab the lock and see if the device is available */
-       nand_get_device (this, mtd, FL_WRITING);
+       for (i = 0; i < chip->ecc.total; i++)
+               chip->oob_poi[eccpos[i]] = ecc_calc[i];
 
-       /* Calculate chipnr */
-       chipnr = (int)(to >> this->chip_shift);
-       /* Select the NAND device */
-       this->select_chip(mtd, chipnr);
+       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
 
-       /* Check, if it is write protected */
-       if (nand_check_wp(mtd))
-               goto out;
+/**
+ * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       data buffer
+ *
+ * The hw generator calculates the error syndrome automatically. Therefor
+ * we need a special oob layout and handling.
+ */
+static void nand_write_page_syndrome(struct mtd_info *mtd,
+                                   struct nand_chip *chip, const uint8_t *buf)
+{
+       int i, eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       int eccsteps = chip->ecc.steps;
+       const uint8_t *p = buf;
+       uint8_t *oob = chip->oob_poi;
 
-       /* if oobsel is NULL, use chip defaults */
-       if (oobsel == NULL)
-               oobsel = &mtd->oobinfo;
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 
-       /* Autoplace of oob data ? Use the default placement scheme */
-       if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
-               oobsel = this->autooob;
-               autoplace = 1;
-       }
-       if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
-               autoplace = 1;
+               chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+               chip->write_buf(mtd, p, eccsize);
 
-       /* Setup variables and oob buffer */
-       totalpages = len >> this->page_shift;
-       page = (int) (to >> this->page_shift);
-       /* Invalidate the page cache, if we write to the cached page */
-       if (page <= this->pagebuf && this->pagebuf < (page + totalpages))
-               this->pagebuf = -1;
-
-       /* Set it relative to chip */
-       page &= this->pagemask;
-       startpage = page;
-       /* Calc number of pages we can write in one go */
-       numpages = min (ppblock - (startpage  & (ppblock - 1)), totalpages);
-       oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, autoplace, numpages);
-       bufstart = (u_char *)buf;
-
-       /* Loop until all data is written */
-       while (written < len) {
-
-               this->data_poi = (u_char*) &buf[written];
-               /* Write one page. If this is the last page to write
-                * or the last page in this block, then use the
-                * real pageprogram command, else select cached programming
-                * if supported by the chip.
-                */
-               ret = nand_write_page (mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
-               if (ret) {
-                       DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret);
-                       goto out;
+               if (chip->ecc.prepad) {
+                       chip->write_buf(mtd, oob, chip->ecc.prepad);
+                       oob += chip->ecc.prepad;
                }
-               /* Next oob page */
-               oob += mtd->oobsize;
-               /* Update written bytes count */
-               written += mtd->oobblock;
-               if (written == len)
-                       goto cmp;
 
-               /* Increment page address */
-               page++;
-
-               /* Have we hit a block boundary ? Then we have to verify and
-                * if verify is ok, we have to setup the oob buffer for
-                * the next pages.
-               */
-               if (!(page & (ppblock - 1))){
-                       int ofs;
-                       this->data_poi = bufstart;
-                       ret = nand_verify_pages (mtd, this, startpage,
-                               page - startpage,
-                               oobbuf, oobsel, chipnr, (eccbuf != NULL));
-                       if (ret) {
-                               DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
-                               goto out;
-                       }
-                       *retlen = written;
-
-                       ofs = autoplace ? mtd->oobavail : mtd->oobsize;
-                       if (eccbuf)
-                               eccbuf += (page - startpage) * ofs;
-                       totalpages -= page - startpage;
-                       numpages = min (totalpages, ppblock);
-                       page &= this->pagemask;
-                       startpage = page;
-                       oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel,
-                                       autoplace, numpages);
-                       oob = 0;
-                       /* Check, if we cross a chip boundary */
-                       if (!page) {
-                               chipnr++;
-                               this->select_chip(mtd, -1);
-                               this->select_chip(mtd, chipnr);
-                       }
+               chip->ecc.calculate(mtd, p, oob);
+               chip->write_buf(mtd, oob, eccbytes);
+               oob += eccbytes;
+
+               if (chip->ecc.postpad) {
+                       chip->write_buf(mtd, oob, chip->ecc.postpad);
+                       oob += chip->ecc.postpad;
                }
        }
-       /* Verify the remaining pages */
-cmp:
-       this->data_poi = bufstart;
-       ret = nand_verify_pages (mtd, this, startpage, totalpages,
-               oobbuf, oobsel, chipnr, (eccbuf != NULL));
-       if (!ret)
-               *retlen = written;
-       else
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
-
-out:
-       /* Deselect and wake up anyone waiting on the device */
-       nand_release_device(mtd);
 
-       return ret;
+       /* Calculate remaining oob bytes */
+       i = mtd->oobsize - (oob - chip->oob_poi);
+       if (i)
+               chip->write_buf(mtd, oob, i);
 }
 
-
 /**
- * nand_write_oob - [MTD Interface] NAND write out-of-band
+ * nand_write_page - [INTERNAL] write one page
  * @mtd:       MTD device structure
- * @to:                offset to write to
- * @len:       number of bytes to write
- * @retlen:    pointer to variable to store the number of written bytes
+ * @chip:      NAND chip descriptor
  * @buf:       the data to write
- *
- * NAND write out-of-band
+ * @page:      page number to write
+ * @cached:    cached programming
  */
-static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
+static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+                          const uint8_t *buf, int page, int cached)
 {
-       int column, page, status, ret = -EIO, chipnr;
-       struct nand_chip *this = mtd->priv;
+       int status;
 
-       DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+       chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
 
-       /* Shift to get page */
-       page = (int) (to >> this->page_shift);
-       chipnr = (int) (to >> this->chip_shift);
+       chip->ecc.write_page(mtd, chip, buf);
 
-       /* Mask to get column */
-       column = to & (mtd->oobsize - 1);
+       /*
+        * Cached progamming disabled for now, Not sure if its worth the
+        * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
+        */
+       cached = 0;
 
-       /* Initialize return length value */
-       *retlen = 0;
+       if (!cached || !(chip->options & NAND_CACHEPRG)) {
 
-       /* Do not allow write past end of page */
-       if ((column + len) > mtd->oobsize) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
-               return -EINVAL;
+               chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+               status = chip->waitfunc(mtd, chip);
+               /*
+                * See if operation failed and additional status checks are
+                * available
+                */
+               if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+                       status = chip->errstat(mtd, chip, FL_WRITING, status,
+                                              page);
+
+               if (status & NAND_STATUS_FAIL)
+                       return -EIO;
+       } else {
+               chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
+               status = chip->waitfunc(mtd, chip);
        }
 
-       /* Grab the lock and see if the device is available */
-       nand_get_device (this, mtd, FL_WRITING);
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+       /* Send command to read back the data */
+       chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
 
-       /* Select the NAND device */
-       this->select_chip(mtd, chipnr);
+       if (chip->verify_buf(mtd, buf, mtd->writesize))
+               return -EIO;
+#endif
+       return 0;
+}
+
+/**
+ * nand_fill_oob - [Internal] Transfer client buffer to oob
+ * @chip:      nand chip structure
+ * @oob:       oob data buffer
+ * @ops:       oob ops structure
+ */
+static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
+                                 struct mtd_oob_ops *ops)
+{
+       size_t len = ops->ooblen;
+
+       switch(ops->mode) {
+
+       case MTD_OOB_PLACE:
+       case MTD_OOB_RAW:
+               memcpy(chip->oob_poi + ops->ooboffs, oob, len);
+               return oob + len;
+
+       case MTD_OOB_AUTO: {
+               struct nand_oobfree *free = chip->ecc.layout->oobfree;
+               uint32_t boffs = 0, woffs = ops->ooboffs;
+               size_t bytes = 0;
+
+               for(; free->length && len; free++, len -= bytes) {
+                       /* Write request not from offset 0 ? */
+                       if (unlikely(woffs)) {
+                               if (woffs >= free->length) {
+                                       woffs -= free->length;
+                                       continue;
+                               }
+                               boffs = free->offset + woffs;
+                               bytes = min_t(size_t, len,
+                                             (free->length - woffs));
+                               woffs = 0;
+                       } else {
+                               bytes = min_t(size_t, len, free->length);
+                               boffs = free->offset;
+                       }
+                       memcpy(chip->oob_poi + woffs, oob, bytes);
+                       oob += bytes;
+               }
+               return oob;
+       }
+       default:
+               BUG();
+       }
+       return NULL;
+}
+
+#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
+
+/**
+ * nand_do_write_ops - [Internal] NAND write with ECC
+ * @mtd:       MTD device structure
+ * @to:                offset to write to
+ * @ops:       oob operations description structure
+ *
+ * NAND write with ECC
+ */
+static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
+                            struct mtd_oob_ops *ops)
+{
+       int chipnr, realpage, page, blockmask;
+       struct nand_chip *chip = mtd->priv;
+       uint32_t writelen = ops->len;
+       uint8_t *oob = ops->oobbuf;
+       uint8_t *buf = ops->datbuf;
+       int bytes = mtd->writesize;
+       int ret;
+
+       ops->retlen = 0;
 
-       /* Reset the chip. Some chips (like the Toshiba TC5832DC found
-          in one of my DiskOnChip 2000 test units) will clear the whole
-          data page too if we don't do this. I have no clue why, but
-          I seem to have 'fixed' it in the doc2000 driver in
-          August 1999.  dwmw2. */
-       this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+       /* reject writes, which are not page aligned */
+       if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
+               printk(KERN_NOTICE "nand_write: "
+                      "Attempt to write not page aligned data\n");
+               return -EINVAL;
+       }
+
+       if (!writelen)
+               return 0;
 
        /* Check, if it is write protected */
        if (nand_check_wp(mtd))
-               goto out;
+               return -EIO;
 
-       /* Invalidate the page cache, if we write to the cached page */
-       if (page == this->pagebuf)
-               this->pagebuf = -1;
-
-       if (NAND_MUST_PAD(this)) {
-               /* Write out desired data */
-               this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page & this->pagemask);
-               /* prepad 0xff for partial programming */
-               this->write_buf(mtd, ffchars, column);
-               /* write data */
-               this->write_buf(mtd, buf, len);
-               /* postpad 0xff for partial programming */
-               this->write_buf(mtd, ffchars, mtd->oobsize - (len+column));
-       } else {
-               /* Write out desired data */
-               this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock + column, page & this->pagemask);
-               /* write data */
-               this->write_buf(mtd, buf, len);
-       }
-       /* Send command to program the OOB data */
-       this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1);
+       chipnr = (int)(to >> chip->chip_shift);
+       chip->select_chip(mtd, chipnr);
 
-       status = this->waitfunc (mtd, this, FL_WRITING);
+       realpage = (int)(to >> chip->page_shift);
+       page = realpage & chip->pagemask;
+       blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
 
-       /* See if device thinks it succeeded */
-       if (status & NAND_STATUS_FAIL) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
-               ret = -EIO;
-               goto out;
-       }
-       /* Return happy */
-       *retlen = len;
+       /* Invalidate the page cache, when we write to the cached page */
+       if (to <= (chip->pagebuf << chip->page_shift) &&
+           (chip->pagebuf << chip->page_shift) < (to + ops->len))
+               chip->pagebuf = -1;
 
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-       /* Send command to read back the data */
-       this->cmdfunc (mtd, NAND_CMD_READOOB, column, page & this->pagemask);
+       chip->oob_poi = chip->buffers.oobwbuf;
 
-       if (this->verify_buf(mtd, buf, len)) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page);
-               ret = -EIO;
-               goto out;
+       while(1) {
+               int cached = writelen > bytes && page != blockmask;
+
+               if (unlikely(oob))
+                       oob = nand_fill_oob(chip, oob, ops);
+
+               ret = nand_write_page(mtd, chip, buf, page, cached);
+               if (ret)
+                       break;
+
+               writelen -= bytes;
+               if (!writelen)
+                       break;
+
+               buf += bytes;
+               realpage++;
+
+               page = realpage & chip->pagemask;
+               /* Check, if we cross a chip boundary */
+               if (!page) {
+                       chipnr++;
+                       chip->select_chip(mtd, -1);
+                       chip->select_chip(mtd, chipnr);
+               }
        }
-#endif
-       ret = 0;
-out:
-       /* Deselect and wake up anyone waiting on the device */
-       nand_release_device(mtd);
 
+       if (unlikely(oob))
+               memset(chip->oob_poi, 0xff, mtd->oobsize);
+
+       ops->retlen = ops->len - writelen;
        return ret;
 }
 
-
 /**
- * nand_writev - [MTD Interface] compabilty function for nand_writev_ecc
+ * nand_write - [MTD Interface] NAND write with ECC
  * @mtd:       MTD device structure
- * @vecs:      the iovectors to write
- * @count:     number of vectors
  * @to:                offset to write to
+ * @len:       number of bytes to write
  * @retlen:    pointer to variable to store the number of written bytes
+ * @buf:       the data to write
  *
- * NAND write with kvec. This just calls the ecc function
+ * NAND write with ECC
  */
-static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
-               loff_t to, size_t * retlen)
+static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
+                         size_t *retlen, const uint8_t *buf)
 {
-       return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL));
+       struct nand_chip *chip = mtd->priv;
+       int ret;
+
+       /* Do not allow reads past end of device */
+       if ((to + len) > mtd->size)
+               return -EINVAL;
+       if (!len)
+               return 0;
+
+       nand_get_device(chip, mtd, FL_WRITING);
+
+       chip->ops.len = len;
+       chip->ops.datbuf = (uint8_t *)buf;
+       chip->ops.oobbuf = NULL;
+
+       ret = nand_do_write_ops(mtd, to, &chip->ops);
+
+       nand_release_device(mtd);
+
+       *retlen = chip->ops.retlen;
+       return ret;
 }
 
 /**
- * nand_writev_ecc - [MTD Interface] write with iovec with ecc
+ * nand_do_write_oob - [MTD Interface] NAND write out-of-band
  * @mtd:       MTD device structure
- * @vecs:      the iovectors to write
- * @count:     number of vectors
  * @to:                offset to write to
- * @retlen:    pointer to variable to store the number of written bytes
- * @eccbuf:    filesystem supplied oob data buffer
- * @oobsel:    oob selection structure
+ * @ops:       oob operation description structure
  *
- * NAND write with iovec with ecc
+ * NAND write out-of-band
  */
-static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
-               loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel)
+static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
+                            struct mtd_oob_ops *ops)
 {
-       int i, page, len, total_len, ret = -EIO, written = 0, chipnr;
-       int oob, numpages, autoplace = 0, startpage;
-       struct nand_chip *this = mtd->priv;
-       int     ppblock = (1 << (this->phys_erase_shift - this->page_shift));
-       u_char *oobbuf, *bufstart;
+       int chipnr, page, status;
+       struct nand_chip *chip = mtd->priv;
 
-       /* Preset written len for early exit */
-       *retlen = 0;
-
-       /* Calculate total length of data */
-       total_len = 0;
-       for (i = 0; i < count; i++)
-               total_len += (int) vecs[i].iov_len;
-
-       DEBUG (MTD_DEBUG_LEVEL3,
-              "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count);
+       DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
+             (unsigned int)to, (int)ops->len);
 
        /* Do not allow write past end of page */
-       if ((to + total_len) > mtd->size) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n");
+       if ((ops->ooboffs + ops->len) > mtd->oobsize) {
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
+                     "Attempt to write past end of page\n");
                return -EINVAL;
        }
 
-       /* reject writes, which are not page aligned */
-       if (NOTALIGNED (to) || NOTALIGNED(total_len)) {
-               printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
-               return -EINVAL;
-       }
+       chipnr = (int)(to >> chip->chip_shift);
+       chip->select_chip(mtd, chipnr);
 
-       /* Grab the lock and see if the device is available */
-       nand_get_device (this, mtd, FL_WRITING);
+       /* Shift to get page */
+       page = (int)(to >> chip->page_shift);
 
-       /* Get the current chip-nr */
-       chipnr = (int) (to >> this->chip_shift);
-       /* Select the NAND device */
-       this->select_chip(mtd, chipnr);
+       /*
+        * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
+        * of my DiskOnChip 2000 test units) will clear the whole data page too
+        * if we don't do this. I have no clue why, but I seem to have 'fixed'
+        * it in the doc2000 driver in August 1999.  dwmw2.
+        */
+       chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 
        /* Check, if it is write protected */
        if (nand_check_wp(mtd))
-               goto out;
+               return -EROFS;
 
-       /* if oobsel is NULL, use chip defaults */
-       if (oobsel == NULL)
-               oobsel = &mtd->oobinfo;
+       /* Invalidate the page cache, if we write to the cached page */
+       if (page == chip->pagebuf)
+               chip->pagebuf = -1;
 
-       /* Autoplace of oob data ? Use the default placement scheme */
-       if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
-               oobsel = this->autooob;
-               autoplace = 1;
-       }
-       if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
-               autoplace = 1;
+       chip->oob_poi = chip->buffers.oobwbuf;
+       memset(chip->oob_poi, 0xff, mtd->oobsize);
+       nand_fill_oob(chip, ops->oobbuf, ops);
+       status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
+       memset(chip->oob_poi, 0xff, mtd->oobsize);
 
-       /* Setup start page */
-       page = (int) (to >> this->page_shift);
-       /* Invalidate the page cache, if we write to the cached page */
-       if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift))
-               this->pagebuf = -1;
+       if (status)
+               return status;
 
-       startpage = page & this->pagemask;
+       ops->retlen = ops->len;
 
-       /* Loop until all kvec' data has been written */
-       len = 0;
-       while (count) {
-               /* If the given tuple is >= pagesize then
-                * write it out from the iov
-                */
-               if ((vecs->iov_len - len) >= mtd->oobblock) {
-                       /* Calc number of pages we can write
-                        * out of this iov in one go */
-                       numpages = (vecs->iov_len - len) >> this->page_shift;
-                       /* Do not cross block boundaries */
-                       numpages = min (ppblock - (startpage & (ppblock - 1)), numpages);
-                       oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);
-                       bufstart = (u_char *)vecs->iov_base;
-                       bufstart += len;
-                       this->data_poi = bufstart;
-                       oob = 0;
-                       for (i = 1; i <= numpages; i++) {
-                               /* Write one page. If this is the last page to write
-                                * then use the real pageprogram command, else select
-                                * cached programming if supported by the chip.
-                                */
-                               ret = nand_write_page (mtd, this, page & this->pagemask,
-                                       &oobbuf[oob], oobsel, i != numpages);
-                               if (ret)
-                                       goto out;
-                               this->data_poi += mtd->oobblock;
-                               len += mtd->oobblock;
-                               oob += mtd->oobsize;
-                               page++;
-                       }
-                       /* Check, if we have to switch to the next tuple */
-                       if (len >= (int) vecs->iov_len) {
-                               vecs++;
-                               len = 0;
-                               count--;
-                       }
-               } else {
-                       /* We must use the internal buffer, read data out of each
-                        * tuple until we have a full page to write
-                        */
-                       int cnt = 0;
-                       while (cnt < mtd->oobblock) {
-                               if (vecs->iov_base != NULL && vecs->iov_len)
-                                       this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++];
-                               /* Check, if we have to switch to the next tuple */
-                               if (len >= (int) vecs->iov_len) {
-                                       vecs++;
-                                       len = 0;
-                                       count--;
-                               }
-                       }
-                       this->pagebuf = page;
-                       this->data_poi = this->data_buf;
-                       bufstart = this->data_poi;
-                       numpages = 1;
-                       oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);
-                       ret = nand_write_page (mtd, this, page & this->pagemask,
-                               oobbuf, oobsel, 0);
-                       if (ret)
-                               goto out;
-                       page++;
-               }
+       return 0;
+}
 
-               this->data_poi = bufstart;
-               ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0);
-               if (ret)
-                       goto out;
+/**
+ * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
+ * @mtd:       MTD device structure
+ * @from:      offset to read from
+ * @ops:       oob operation description structure
+ */
+static int nand_write_oob(struct mtd_info *mtd, loff_t to,
+                         struct mtd_oob_ops *ops)
+{
+       void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
+                         const uint8_t *buf) = NULL;
+       struct nand_chip *chip = mtd->priv;
+       int ret = -ENOTSUPP;
 
-               written += mtd->oobblock * numpages;
-               /* All done ? */
-               if (!count)
-                       break;
+       ops->retlen = 0;
 
-               startpage = page & this->pagemask;
-               /* Check, if we cross a chip boundary */
-               if (!startpage) {
-                       chipnr++;
-                       this->select_chip(mtd, -1);
-                       this->select_chip(mtd, chipnr);
-               }
+       /* Do not allow writes past end of device */
+       if ((to + ops->len) > mtd->size) {
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+                     "Attempt read beyond end of device\n");
+               return -EINVAL;
        }
-       ret = 0;
-out:
-       /* Deselect and wake up anyone waiting on the device */
-       nand_release_device(mtd);
 
-       *retlen = written;
+       nand_get_device(chip, mtd, FL_WRITING);
+
+       switch(ops->mode) {
+       case MTD_OOB_PLACE:
+       case MTD_OOB_AUTO:
+               break;
+
+       case MTD_OOB_RAW:
+               /* Replace the write_page algorithm temporary */
+               write_page = chip->ecc.write_page;
+               chip->ecc.write_page = nand_write_page_raw;
+               break;
+
+       default:
+               goto out;
+       }
+
+       if (!ops->datbuf)
+               ret = nand_do_write_oob(mtd, to, ops);
+       else
+               ret = nand_do_write_ops(mtd, to, ops);
+
+       if (unlikely(ops->mode == MTD_OOB_RAW))
+               chip->ecc.write_page = write_page;
+ out:
+       nand_release_device(mtd);
        return ret;
 }
 
@@ -2050,12 +1816,12 @@ out:
  *
  * Standard erase command for NAND chips
  */
-static void single_erase_cmd (struct mtd_info *mtd, int page)
+static void single_erase_cmd(struct mtd_info *mtd, int page)
 {
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
        /* Send commands to erase a block */
-       this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page);
-       this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1);
+       chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+       chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
 }
 
 /**
@@ -2066,15 +1832,15 @@ static void single_erase_cmd (struct mtd_info *mtd, int page)
  * AND multi block erase command function
  * Erase 4 consecutive blocks
  */
-static void multi_erase_cmd (struct mtd_info *mtd, int page)
+static void multi_erase_cmd(struct mtd_info *mtd, int page)
 {
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
        /* Send commands to erase a block */
-       this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
-       this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
-       this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
-       this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page);
-       this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1);
+       chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
+       chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
+       chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
+       chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+       chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
 }
 
 /**
@@ -2084,79 +1850,82 @@ static void multi_erase_cmd (struct mtd_info *mtd, int page)
  *
  * Erase one ore more blocks
  */
-static int nand_erase (struct mtd_info *mtd, struct erase_info *instr)
+static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
-       return nand_erase_nand (mtd, instr, 0);
+       return nand_erase_nand(mtd, instr, 0);
 }
 
 #define BBT_PAGE_MASK  0xffffff3f
 /**
- * nand_erase_intern - [NAND Interface] erase block(s)
+ * nand_erase_nand - [Internal] erase block(s)
  * @mtd:       MTD device structure
  * @instr:     erase instruction
  * @allowbbt:  allow erasing the bbt area
  *
  * Erase one ore more blocks
  */
-int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
+int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
+                   int allowbbt)
 {
        int page, len, status, pages_per_block, ret, chipnr;
-       struct nand_chip *this = mtd->priv;
-       int rewrite_bbt[NAND_MAX_CHIPS]={0};    /* flags to indicate the page, if bbt needs to be rewritten. */
-       unsigned int bbt_masked_page;           /* bbt mask to compare to page being erased. */
-                                               /* It is used to see if the current page is in the same */
-                                               /*   256 block group and the same bank as the bbt. */
+       struct nand_chip *chip = mtd->priv;
+       int rewrite_bbt[NAND_MAX_CHIPS]={0};
+       unsigned int bbt_masked_page = 0xffffffff;
 
-       DEBUG (MTD_DEBUG_LEVEL3,
-              "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len);
+       DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
+             (unsigned int)instr->addr, (unsigned int)instr->len);
 
        /* Start address must align on block boundary */
-       if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
+       if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
                return -EINVAL;
        }
 
        /* Length must align on block boundary */
-       if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n");
+       if (instr->len & ((1 << chip->phys_erase_shift) - 1)) {
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
+                     "Length not block aligned\n");
                return -EINVAL;
        }
 
        /* Do not allow erase past end of device */
        if ((instr->len + instr->addr) > mtd->size) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n");
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
+                     "Erase past end of device\n");
                return -EINVAL;
        }
 
        instr->fail_addr = 0xffffffff;
 
        /* Grab the lock and see if the device is available */
-       nand_get_device (this, mtd, FL_ERASING);
+       nand_get_device(chip, mtd, FL_ERASING);
 
        /* Shift to get first page */
-       page = (int) (instr->addr >> this->page_shift);
-       chipnr = (int) (instr->addr >> this->chip_shift);
+       page = (int)(instr->addr >> chip->page_shift);
+       chipnr = (int)(instr->addr >> chip->chip_shift);
 
        /* Calculate pages in each block */
-       pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
+       pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
 
        /* Select the NAND device */
-       this->select_chip(mtd, chipnr);
+       chip->select_chip(mtd, chipnr);
 
-       /* Check the WP bit */
        /* Check, if it is write protected */
        if (nand_check_wp(mtd)) {
-               DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n");
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
+                     "Device is write protected!!!\n");
                instr->state = MTD_ERASE_FAILED;
                goto erase_exit;
        }
 
-       /* if BBT requires refresh, set the BBT page mask to see if the BBT should be rewritten */
-       if (this->options & BBT_AUTO_REFRESH) {
-               bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
-       } else {
-               bbt_masked_page = 0xffffffff;   /* should not match anything */
-       }
+       /*
+        * If BBT requires refresh, set the BBT page mask to see if the BBT
+        * should be rewritten. Otherwise the mask is set to 0xffffffff which
+        * can not be matched. This is also done when the bbt is actually
+        * erased to avoid recusrsive updates
+        */
+       if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
+               bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
 
        /* Loop through the pages */
        len = instr->len;
@@ -2164,64 +1933,77 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb
        instr->state = MTD_ERASING;
 
        while (len) {
-               /* Check if we have a bad block, we do not erase bad blocks ! */
-               if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) {
-                       printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
+               /*
+                * heck if we have a bad block, we do not erase bad blocks !
+                */
+               if (nand_block_checkbad(mtd, ((loff_t) page) <<
+                                       chip->page_shift, 0, allowbbt)) {
+                       printk(KERN_WARNING "nand_erase: attempt to erase a "
+                              "bad block at page 0x%08x\n", page);
                        instr->state = MTD_ERASE_FAILED;
                        goto erase_exit;
                }
 
-               /* Invalidate the page cache, if we erase the block which contains
-                  the current cached page */
-               if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
-                       this->pagebuf = -1;
+               /*
+                * Invalidate the page cache, if we erase the block which
+                * contains the current cached page
+                */
+               if (page <= chip->pagebuf && chip->pagebuf <
+                   (page + pages_per_block))
+                       chip->pagebuf = -1;
 
-               this->erase_cmd (mtd, page & this->pagemask);
+               chip->erase_cmd(mtd, page & chip->pagemask);
 
-               status = this->waitfunc (mtd, this, FL_ERASING);
+               status = chip->waitfunc(mtd, chip);
 
-               /* See if operation failed and additional status checks are available */
-               if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
-                       status = this->errstat(mtd, this, FL_ERASING, status, page);
-               }
+               /*
+                * See if operation failed and additional status checks are
+                * available
+                */
+               if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+                       status = chip->errstat(mtd, chip, FL_ERASING,
+                                              status, page);
 
                /* See if block erase succeeded */
                if (status & NAND_STATUS_FAIL) {
-                       DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);
+                       DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
+                             "Failed erase, page 0x%08x\n", page);
                        instr->state = MTD_ERASE_FAILED;
-                       instr->fail_addr = (page << this->page_shift);
+                       instr->fail_addr = (page << chip->page_shift);
                        goto erase_exit;
                }
 
-               /* if BBT requires refresh, set the BBT rewrite flag to the page being erased */
-               if (this->options & BBT_AUTO_REFRESH) {
-                       if (((page & BBT_PAGE_MASK) == bbt_masked_page) &&
-                            (page != this->bbt_td->pages[chipnr])) {
-                               rewrite_bbt[chipnr] = (page << this->page_shift);
-                       }
-               }
+               /*
+                * If BBT requires refresh, set the BBT rewrite flag to the
+                * page being erased
+                */
+               if (bbt_masked_page != 0xffffffff &&
+                   (page & BBT_PAGE_MASK) == bbt_masked_page)
+                           rewrite_bbt[chipnr] = (page << chip->page_shift);
 
                /* Increment page address and decrement length */
-               len -= (1 << this->phys_erase_shift);
+               len -= (1 << chip->phys_erase_shift);
                page += pages_per_block;
 
                /* Check, if we cross a chip boundary */
-               if (len && !(page & this->pagemask)) {
+               if (len && !(page & chip->pagemask)) {
                        chipnr++;
-                       this->select_chip(mtd, -1);
-                       this->select_chip(mtd, chipnr);
-
-                       /* if BBT requires refresh and BBT-PERCHIP,
-                        *   set the BBT page mask to see if this BBT should be rewritten */
-                       if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) {
-                               bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
-                       }
+                       chip->select_chip(mtd, -1);
+                       chip->select_chip(mtd, chipnr);
 
+                       /*
+                        * If BBT requires refresh and BBT-PERCHIP, set the BBT
+                        * page mask to see if this BBT should be rewritten
+                        */
+                       if (bbt_masked_page != 0xffffffff &&
+                           (chip->bbt_td->options & NAND_BBT_PERCHIP))
+                               bbt_masked_page = chip->bbt_td->pages[chipnr] &
+                                       BBT_PAGE_MASK;
                }
        }
        instr->state = MTD_ERASE_DONE;
 
-erase_exit:
+ erase_exit:
 
        ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
        /* Do call back function */
@@ -2231,16 +2013,21 @@ erase_exit:
        /* Deselect and wake up anyone waiting on the device */
        nand_release_device(mtd);
 
-       /* if BBT requires refresh and erase was successful, rewrite any selected bad block tables */
-       if ((this->options & BBT_AUTO_REFRESH) && (!ret)) {
-               for (chipnr = 0; chipnr < this->numchips; chipnr++) {
-                       if (rewrite_bbt[chipnr]) {
-                               /* update the BBT for chip */
-                               DEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n",
-                                       chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]);
-                               nand_update_bbt (mtd, rewrite_bbt[chipnr]);
-                       }
-               }
+       /*
+        * If BBT requires refresh and erase was successful, rewrite any
+        * selected bad block tables
+        */
+       if (bbt_masked_page == 0xffffffff || ret)
+               return ret;
+
+       for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
+               if (!rewrite_bbt[chipnr])
+                       continue;
+               /* update the BBT for chip */
+               DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
+                     "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
+                     chip->bbt_td->pages[chipnr]);
+               nand_update_bbt(mtd, rewrite_bbt[chipnr]);
        }
 
        /* Return more or less happy */
@@ -2253,51 +2040,50 @@ erase_exit:
  *
  * Sync is actually a wait for chip ready function
  */
-static void nand_sync (struct mtd_info *mtd)
+static void nand_sync(struct mtd_info *mtd)
 {
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
 
-       DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n");
+       DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
 
        /* Grab the lock and see if the device is available */
-       nand_get_device (this, mtd, FL_SYNCING);
+       nand_get_device(chip, mtd, FL_SYNCING);
        /* Release it and go back */
-       nand_release_device (mtd);
+       nand_release_device(mtd);
 }
 
-
 /**
- * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
+ * nand_block_isbad - [MTD Interface] Check if block at offset is bad
  * @mtd:       MTD device structure
  * @ofs:       offset relative to mtd start
  */
-static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs)
+static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 {
        /* Check for invalid offset */
-       if (ofs > mtd->size)
+       if (offs > mtd->size)
                return -EINVAL;
 
-       return nand_block_checkbad (mtd, ofs, 1, 0);
+       return nand_block_checkbad(mtd, offs, 1, 0);
 }
 
 /**
- * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
+ * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
  * @mtd:       MTD device structure
  * @ofs:       offset relative to mtd start
  */
-static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs)
+static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
        int ret;
 
-        if ((ret = nand_block_isbad(mtd, ofs))) {
-               /* If it was bad already, return success and do nothing. */
+       if ((ret = nand_block_isbad(mtd, ofs))) {
+               /* If it was bad already, return success and do nothing. */
                if (ret > 0)
                        return 0;
-               return ret;
-        }
+               return ret;
+       }
 
-       return this->block_markbad(mtd, ofs);
+       return chip->block_markbad(mtd, ofs);
 }
 
 /**
@@ -2306,9 +2092,9 @@ static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs)
  */
 static int nand_suspend(struct mtd_info *mtd)
 {
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
 
-       return nand_get_device (this, mtd, FL_PM_SUSPENDED);
+       return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
 }
 
 /**
@@ -2317,373 +2103,385 @@ static int nand_suspend(struct mtd_info *mtd)
  */
 static void nand_resume(struct mtd_info *mtd)
 {
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
 
-       if (this->state == FL_PM_SUSPENDED)
+       if (chip->state == FL_PM_SUSPENDED)
                nand_release_device(mtd);
        else
-               printk(KERN_ERR "resume() called for the chip which is not "
-                               "in suspended state\n");
-
+               printk(KERN_ERR "nand_resume() called for a chip which is not "
+                      "in suspended state\n");
 }
 
-
-/**
- * nand_scan - [NAND Interface] Scan for the NAND device
- * @mtd:       MTD device structure
- * @maxchips:  Number of chips to scan for
- *
- * This fills out all the not initialized function pointers
- * with the defaults.
- * The flash ID is read and the mtd/chip structures are
- * filled with the appropriate values. Buffers are allocated if
- * they are not provided by the board driver
- *
+/*
+ * Set default functions
  */
-int nand_scan (struct mtd_info *mtd, int maxchips)
+static void nand_set_defaults(struct nand_chip *chip, int busw)
 {
-       int i, nand_maf_id, nand_dev_id, busw, maf_id;
-       struct nand_chip *this = mtd->priv;
-
-       /* Get buswidth to select the correct functions*/
-       busw = this->options & NAND_BUSWIDTH_16;
-
        /* check for proper chip_delay setup, set 20us if not */
-       if (!this->chip_delay)
-               this->chip_delay = 20;
+       if (!chip->chip_delay)
+               chip->chip_delay = 20;
 
        /* check, if a user supplied command function given */
-       if (this->cmdfunc == NULL)
-               this->cmdfunc = nand_command;
+       if (chip->cmdfunc == NULL)
+               chip->cmdfunc = nand_command;
 
        /* check, if a user supplied wait function given */
-       if (this->waitfunc == NULL)
-               this->waitfunc = nand_wait;
-
-       if (!this->select_chip)
-               this->select_chip = nand_select_chip;
-       if (!this->write_byte)
-               this->write_byte = busw ? nand_write_byte16 : nand_write_byte;
-       if (!this->read_byte)
-               this->read_byte = busw ? nand_read_byte16 : nand_read_byte;
-       if (!this->write_word)
-               this->write_word = nand_write_word;
-       if (!this->read_word)
-               this->read_word = nand_read_word;
-       if (!this->block_bad)
-               this->block_bad = nand_block_bad;
-       if (!this->block_markbad)
-               this->block_markbad = nand_default_block_markbad;
-       if (!this->write_buf)
-               this->write_buf = busw ? nand_write_buf16 : nand_write_buf;
-       if (!this->read_buf)
-               this->read_buf = busw ? nand_read_buf16 : nand_read_buf;
-       if (!this->verify_buf)
-               this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
-       if (!this->scan_bbt)
-               this->scan_bbt = nand_default_bbt;
+       if (chip->waitfunc == NULL)
+               chip->waitfunc = nand_wait;
+
+       if (!chip->select_chip)
+               chip->select_chip = nand_select_chip;
+       if (!chip->read_byte)
+               chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
+       if (!chip->read_word)
+               chip->read_word = nand_read_word;
+       if (!chip->block_bad)
+               chip->block_bad = nand_block_bad;
+       if (!chip->block_markbad)
+               chip->block_markbad = nand_default_block_markbad;
+       if (!chip->write_buf)
+               chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
+       if (!chip->read_buf)
+               chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
+       if (!chip->verify_buf)
+               chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
+       if (!chip->scan_bbt)
+               chip->scan_bbt = nand_default_bbt;
+
+       if (!chip->controller) {
+               chip->controller = &chip->hwcontrol;
+               spin_lock_init(&chip->controller->lock);
+               init_waitqueue_head(&chip->controller->wq);
+       }
+
+}
+
+/*
+ * Get the flash and manufacturer id and lookup if the type is supported
+ */
+static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
+                                                 struct nand_chip *chip,
+                                                 int busw, int *maf_id)
+{
+       struct nand_flash_dev *type = NULL;
+       int i, dev_id, maf_idx;
 
        /* Select the device */
-       this->select_chip(mtd, 0);
+       chip->select_chip(mtd, 0);
 
        /* Send the command for reading device ID */
-       this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
+       chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
 
        /* Read manufacturer and device IDs */
-       nand_maf_id = this->read_byte(mtd);
-       nand_dev_id = this->read_byte(mtd);
+       *maf_id = chip->read_byte(mtd);
+       dev_id = chip->read_byte(mtd);
 
-       /* Print and store flash device information */
+       /* Lookup the flash id */
        for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+               if (dev_id == nand_flash_ids[i].id) {
+                       type =  &nand_flash_ids[i];
+                       break;
+               }
+       }
 
-               if (nand_dev_id != nand_flash_ids[i].id)
-                       continue;
+       if (!type)
+               return ERR_PTR(-ENODEV);
+
+       if (!mtd->name)
+               mtd->name = type->name;
+
+       chip->chipsize = type->chipsize << 20;
+
+       /* Newer devices have all the information in additional id bytes */
+       if (!type->pagesize) {
+               int extid;
+               /* The 3rd id byte contains non relevant data ATM */
+               extid = chip->read_byte(mtd);
+               /* The 4th id byte is the important one */
+               extid = chip->read_byte(mtd);
+               /* Calc pagesize */
+               mtd->writesize = 1024 << (extid & 0x3);
+               extid >>= 2;
+               /* Calc oobsize */
+               mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
+               extid >>= 2;
+               /* Calc blocksize. Blocksize is multiples of 64KiB */
+               mtd->erasesize = (64 * 1024) << (extid & 0x03);
+               extid >>= 2;
+               /* Get buswidth information */
+               busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
 
-               if (!mtd->name) mtd->name = nand_flash_ids[i].name;
-               this->chipsize = nand_flash_ids[i].chipsize << 20;
-
-               /* New devices have all the information in additional id bytes */
-               if (!nand_flash_ids[i].pagesize) {
-                       int extid;
-                       /* The 3rd id byte contains non relevant data ATM */
-                       extid = this->read_byte(mtd);
-                       /* The 4th id byte is the important one */
-                       extid = this->read_byte(mtd);
-                       /* Calc pagesize */
-                       mtd->oobblock = 1024 << (extid & 0x3);
-                       extid >>= 2;
-                       /* Calc oobsize */
-                       mtd->oobsize = (8 << (extid & 0x01)) * (mtd->oobblock >> 9);
-                       extid >>= 2;
-                       /* Calc blocksize. Blocksize is multiples of 64KiB */
-                       mtd->erasesize = (64 * 1024)  << (extid & 0x03);
-                       extid >>= 2;
-                       /* Get buswidth information */
-                       busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+       } else {
+               /*
+                * Old devices have chip data hardcoded in the device id table
+                */
+               mtd->erasesize = type->erasesize;
+               mtd->writesize = type->pagesize;
+               mtd->oobsize = mtd->writesize / 32;
+               busw = type->options & NAND_BUSWIDTH_16;
+       }
 
-               } else {
-                       /* Old devices have this data hardcoded in the
-                        * device id table */
-                       mtd->erasesize = nand_flash_ids[i].erasesize;
-                       mtd->oobblock = nand_flash_ids[i].pagesize;
-                       mtd->oobsize = mtd->oobblock / 32;
-                       busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
-               }
+       /* Try to identify manufacturer */
+       for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) {
+               if (nand_manuf_ids[maf_idx].id == *maf_id)
+                       break;
+       }
 
-               /* Try to identify manufacturer */
-               for (maf_id = 0; nand_manuf_ids[maf_id].id != 0x0; maf_id++) {
-                       if (nand_manuf_ids[maf_id].id == nand_maf_id)
-                               break;
-               }
+       /*
+        * Check, if buswidth is correct. Hardware drivers should set
+        * chip correct !
+        */
+       if (busw != (chip->options & NAND_BUSWIDTH_16)) {
+               printk(KERN_INFO "NAND device: Manufacturer ID:"
+                      " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
+                      dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
+               printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
+                      (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
+                      busw ? 16 : 8);
+               return ERR_PTR(-EINVAL);
+       }
 
-               /* Check, if buswidth is correct. Hardware drivers should set
-                * this correct ! */
-               if (busw != (this->options & NAND_BUSWIDTH_16)) {
-                       printk (KERN_INFO "NAND device: Manufacturer ID:"
-                               " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
-                               nand_manuf_ids[maf_id].name , mtd->name);
-                       printk (KERN_WARNING
-                               "NAND bus width %d instead %d bit\n",
-                                       (this->options & NAND_BUSWIDTH_16) ? 16 : 8,
-                                       busw ? 16 : 8);
-                       this->select_chip(mtd, -1);
-                       return 1;
-               }
+       /* Calculate the address shift from the page size */
+       chip->page_shift = ffs(mtd->writesize) - 1;
+       /* Convert chipsize to number of pages per chip -1. */
+       chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
 
-               /* Calculate the address shift from the page size */
-               this->page_shift = ffs(mtd->oobblock) - 1;
-               this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;
-               this->chip_shift = ffs(this->chipsize) - 1;
-
-               /* Set the bad block position */
-               this->badblockpos = mtd->oobblock > 512 ?
-                       NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
-
-               /* Get chip options, preserve non chip based options */
-               this->options &= ~NAND_CHIPOPTIONS_MSK;
-               this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
-               /* Set this as a default. Board drivers can override it, if neccecary */
-               this->options |= NAND_NO_AUTOINCR;
-               /* Check if this is a not a samsung device. Do not clear the options
-                * for chips which are not having an extended id.
-                */
-               if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
-                       this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
+       chip->bbt_erase_shift = chip->phys_erase_shift =
+               ffs(mtd->erasesize) - 1;
+       chip->chip_shift = ffs(chip->chipsize) - 1;
 
-               /* Check for AND chips with 4 page planes */
-               if (this->options & NAND_4PAGE_ARRAY)
-                       this->erase_cmd = multi_erase_cmd;
-               else
-                       this->erase_cmd = single_erase_cmd;
+       /* Set the bad block position */
+       chip->badblockpos = mtd->writesize > 512 ?
+               NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
 
-               /* Do not replace user supplied command function ! */
-               if (mtd->oobblock > 512 && this->cmdfunc == nand_command)
-                       this->cmdfunc = nand_command_lp;
+       /* Get chip options, preserve non chip based options */
+       chip->options &= ~NAND_CHIPOPTIONS_MSK;
+       chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
 
-               printk (KERN_INFO "NAND device: Manufacturer ID:"
-                       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
-                       nand_manuf_ids[maf_id].name , nand_flash_ids[i].name);
-               break;
-       }
+       /*
+        * Set chip as a default. Board drivers can override it, if necessary
+        */
+       chip->options |= NAND_NO_AUTOINCR;
+
+       /* Check if chip is a not a samsung device. Do not clear the
+        * options for chips which are not having an extended id.
+        */
+       if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
+               chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
+
+       /* Check for AND chips with 4 page planes */
+       if (chip->options & NAND_4PAGE_ARRAY)
+               chip->erase_cmd = multi_erase_cmd;
+       else
+               chip->erase_cmd = single_erase_cmd;
+
+       /* Do not replace user supplied command function ! */
+       if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
+               chip->cmdfunc = nand_command_lp;
+
+       printk(KERN_INFO "NAND device: Manufacturer ID:"
+              " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
+              nand_manuf_ids[maf_idx].name, type->name);
+
+       return type;
+}
+
+/* module_text_address() isn't exported, and it's mostly a pointless
+   test if this is a module _anyway_ -- they'd have to try _really_ hard
+   to call us from in-kernel code if the core NAND support is modular. */
+#ifdef MODULE
+#define caller_is_module() (1)
+#else
+#define caller_is_module() \
+       module_text_address((unsigned long)__builtin_return_address(0))
+#endif
+
+/**
+ * nand_scan - [NAND Interface] Scan for the NAND device
+ * @mtd:       MTD device structure
+ * @maxchips:  Number of chips to scan for
+ *
+ * This fills out all the uninitialized function pointers
+ * with the defaults.
+ * The flash ID is read and the mtd/chip structures are
+ * filled with the appropriate values.
+ * The mtd->owner field must be set to the module of the caller
+ *
+ */
+int nand_scan(struct mtd_info *mtd, int maxchips)
+{
+       int i, busw, nand_maf_id;
+       struct nand_chip *chip = mtd->priv;
+       struct nand_flash_dev *type;
 
-       if (!nand_flash_ids[i].name) {
-               printk (KERN_WARNING "No NAND device found!!!\n");
-               this->select_chip(mtd, -1);
-               return 1;
+       /* Many callers got this wrong, so check for it for a while... */
+       if (!mtd->owner && caller_is_module()) {
+               printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
+               BUG();
        }
 
-       for (i=1; i < maxchips; i++) {
-               this->select_chip(mtd, i);
+       /* Get buswidth to select the correct functions */
+       busw = chip->options & NAND_BUSWIDTH_16;
+       /* Set the default functions */
+       nand_set_defaults(chip, busw);
 
-               /* Send the command for reading device ID */
-               this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
+       /* Read the flash type */
+       type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
+
+       if (IS_ERR(type)) {
+               printk(KERN_WARNING "No NAND device found!!!\n");
+               chip->select_chip(mtd, -1);
+               return PTR_ERR(type);
+       }
 
+       /* Check for a chip array */
+       for (i = 1; i < maxchips; i++) {
+               chip->select_chip(mtd, i);
+               /* Send the command for reading device ID */
+               chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
                /* Read manufacturer and device IDs */
-               if (nand_maf_id != this->read_byte(mtd) ||
-                   nand_dev_id != this->read_byte(mtd))
+               if (nand_maf_id != chip->read_byte(mtd) ||
+                   type->id != chip->read_byte(mtd))
                        break;
        }
        if (i > 1)
                printk(KERN_INFO "%d NAND chips detected\n", i);
 
-       /* Allocate buffers, if neccecary */
-       if (!this->oob_buf) {
-               size_t len;
-               len = mtd->oobsize << (this->phys_erase_shift - this->page_shift);
-               this->oob_buf = kmalloc (len, GFP_KERNEL);
-               if (!this->oob_buf) {
-                       printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n");
-                       return -ENOMEM;
-               }
-               this->options |= NAND_OOBBUF_ALLOC;
-       }
+       /* Store the number of chips and calc total size for mtd */
+       chip->numchips = i;
+       mtd->size = i * chip->chipsize;
 
-       if (!this->data_buf) {
-               size_t len;
-               len = mtd->oobblock + mtd->oobsize;
-               this->data_buf = kmalloc (len, GFP_KERNEL);
-               if (!this->data_buf) {
-                       if (this->options & NAND_OOBBUF_ALLOC)
-                               kfree (this->oob_buf);
-                       printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n");
-                       return -ENOMEM;
-               }
-               this->options |= NAND_DATABUF_ALLOC;
-       }
+       /* Preset the internal oob write buffer */
+       memset(chip->buffers.oobwbuf, 0xff, mtd->oobsize);
 
-       /* Store the number of chips and calc total size for mtd */
-       this->numchips = i;
-       mtd->size = i * this->chipsize;
-       /* Convert chipsize to number of pages per chip -1. */
-       this->pagemask = (this->chipsize >> this->page_shift) - 1;
-       /* Preset the internal oob buffer */
-       memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
-
-       /* If no default placement scheme is given, select an
-        * appropriate one */
-       if (!this->autooob) {
-               /* Select the appropriate default oob placement scheme for
-                * placement agnostic filesystems */
+       /*
+        * If no default placement scheme is given, select an appropriate one
+        */
+       if (!chip->ecc.layout) {
                switch (mtd->oobsize) {
                case 8:
-                       this->autooob = &nand_oob_8;
+                       chip->ecc.layout = &nand_oob_8;
                        break;
                case 16:
-                       this->autooob = &nand_oob_16;
+                       chip->ecc.layout = &nand_oob_16;
                        break;
                case 64:
-                       this->autooob = &nand_oob_64;
+                       chip->ecc.layout = &nand_oob_64;
                        break;
                default:
-                       printk (KERN_WARNING "No oob scheme defined for oobsize %d\n",
-                               mtd->oobsize);
+                       printk(KERN_WARNING "No oob scheme defined for "
+                              "oobsize %d\n", mtd->oobsize);
                        BUG();
                }
        }
 
-       /* The number of bytes available for the filesystem to place fs dependend
-        * oob data */
-       mtd->oobavail = 0;
-       for (i = 0; this->autooob->oobfree[i][1]; i++)
-               mtd->oobavail += this->autooob->oobfree[i][1];
-
        /*
-        * check ECC mode, default to software
-        * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize
-        * fallback to software ECC
-       */
-       this->eccsize = 256;    /* set default eccsize */
-       this->eccbytes = 3;
-
-       switch (this->eccmode) {
-       case NAND_ECC_HW12_2048:
-               if (mtd->oobblock < 2048) {
-                       printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n",
-                              mtd->oobblock);
-                       this->eccmode = NAND_ECC_SOFT;
-                       this->calculate_ecc = nand_calculate_ecc;
-                       this->correct_data = nand_correct_data;
-               } else
-                       this->eccsize = 2048;
-               break;
-
-       case NAND_ECC_HW3_512:
-       case NAND_ECC_HW6_512:
-       case NAND_ECC_HW8_512:
-               if (mtd->oobblock == 256) {
-                       printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");
-                       this->eccmode = NAND_ECC_SOFT;
-                       this->calculate_ecc = nand_calculate_ecc;
-                       this->correct_data = nand_correct_data;
-               } else
-                       this->eccsize = 512; /* set eccsize to 512 */
-               break;
+        * check ECC mode, default to software if 3byte/512byte hardware ECC is
+        * selected and we have 256 byte pagesize fallback to software ECC
+        */
+       switch (chip->ecc.mode) {
+       case NAND_ECC_HW:
+               /* Use standard hwecc read page function ? */
+               if (!chip->ecc.read_page)
+                       chip->ecc.read_page = nand_read_page_hwecc;
+               if (!chip->ecc.write_page)
+                       chip->ecc.write_page = nand_write_page_hwecc;
+               if (!chip->ecc.read_oob)
+                       chip->ecc.read_oob = nand_read_oob_std;
+               if (!chip->ecc.write_oob)
+                       chip->ecc.write_oob = nand_write_oob_std;
+
+       case NAND_ECC_HW_SYNDROME:
+               if (!chip->ecc.calculate || !chip->ecc.correct ||
+                   !chip->ecc.hwctl) {
+                       printk(KERN_WARNING "No ECC functions supplied, "
+                              "Hardware ECC not possible\n");
+                       BUG();
+               }
+               /* Use standard syndrome read/write page function ? */
+               if (!chip->ecc.read_page)
+                       chip->ecc.read_page = nand_read_page_syndrome;
+               if (!chip->ecc.write_page)
+                       chip->ecc.write_page = nand_write_page_syndrome;
+               if (!chip->ecc.read_oob)
+                       chip->ecc.read_oob = nand_read_oob_syndrome;
+               if (!chip->ecc.write_oob)
+                       chip->ecc.write_oob = nand_write_oob_syndrome;
+
+               if (mtd->writesize >= chip->ecc.size)
+                       break;
+               printk(KERN_WARNING "%d byte HW ECC not possible on "
+                      "%d byte page size, fallback to SW ECC\n",
+                      chip->ecc.size, mtd->writesize);
+               chip->ecc.mode = NAND_ECC_SOFT;
 
-       case NAND_ECC_HW3_256:
+       case NAND_ECC_SOFT:
+               chip->ecc.calculate = nand_calculate_ecc;
+               chip->ecc.correct = nand_correct_data;
+               chip->ecc.read_page = nand_read_page_swecc;
+               chip->ecc.write_page = nand_write_page_swecc;
+               chip->ecc.read_oob = nand_read_oob_std;
+               chip->ecc.write_oob = nand_write_oob_std;
+               chip->ecc.size = 256;
+               chip->ecc.bytes = 3;
                break;
 
        case NAND_ECC_NONE:
-               printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n");
-               this->eccmode = NAND_ECC_NONE;
-               break;
-
-       case NAND_ECC_SOFT:
-               this->calculate_ecc = nand_calculate_ecc;
-               this->correct_data = nand_correct_data;
+               printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
+                      "This is not recommended !!\n");
+               chip->ecc.read_page = nand_read_page_raw;
+               chip->ecc.write_page = nand_write_page_raw;
+               chip->ecc.read_oob = nand_read_oob_std;
+               chip->ecc.write_oob = nand_write_oob_std;
+               chip->ecc.size = mtd->writesize;
+               chip->ecc.bytes = 0;
                break;
-
        default:
-               printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
+               printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
+                      chip->ecc.mode);
                BUG();
        }
 
-       /* Check hardware ecc function availability and adjust number of ecc bytes per
-        * calculation step
-       */
-       switch (this->eccmode) {
-       case NAND_ECC_HW12_2048:
-               this->eccbytes += 4;
-       case NAND_ECC_HW8_512:
-               this->eccbytes += 2;
-       case NAND_ECC_HW6_512:
-               this->eccbytes += 3;
-       case NAND_ECC_HW3_512:
-       case NAND_ECC_HW3_256:
-               if (this->calculate_ecc && this->correct_data && this->enable_hwecc)
-                       break;
-               printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n");
-               BUG();
-       }
-
-       mtd->eccsize = this->eccsize;
-
-       /* Set the number of read / write steps for one page to ensure ECC generation */
-       switch (this->eccmode) {
-       case NAND_ECC_HW12_2048:
-               this->eccsteps = mtd->oobblock / 2048;
-               break;
-       case NAND_ECC_HW3_512:
-       case NAND_ECC_HW6_512:
-       case NAND_ECC_HW8_512:
-               this->eccsteps = mtd->oobblock / 512;
-               break;
-       case NAND_ECC_HW3_256:
-       case NAND_ECC_SOFT:
-               this->eccsteps = mtd->oobblock / 256;
-               break;
+       /*
+        * The number of bytes available for a client to place data into
+        * the out of band area
+        */
+       chip->ecc.layout->oobavail = 0;
+       for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
+               chip->ecc.layout->oobavail +=
+                       chip->ecc.layout->oobfree[i].length;
 
-       case NAND_ECC_NONE:
-               this->eccsteps = 1;
-               break;
+       /*
+        * Set the number of read / write steps for one page depending on ECC
+        * mode
+        */
+       chip->ecc.steps = mtd->writesize / chip->ecc.size;
+       if(chip->ecc.steps * chip->ecc.size != mtd->writesize) {
+               printk(KERN_WARNING "Invalid ecc parameters\n");
+               BUG();
        }
+       chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
 
-       /* Initialize state, waitqueue and spinlock */
-       this->state = FL_READY;
-       init_waitqueue_head (&this->wq);
-       spin_lock_init (&this->chip_lock);
+       /* Initialize state */
+       chip->state = FL_READY;
 
        /* De-select the device */
-       this->select_chip(mtd, -1);
+       chip->select_chip(mtd, -1);
 
        /* Invalidate the pagebuffer reference */
-       this->pagebuf = -1;
+       chip->pagebuf = -1;
 
        /* Fill in remaining MTD driver data */
        mtd->type = MTD_NANDFLASH;
-       mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
+       mtd->flags = MTD_CAP_NANDFLASH;
        mtd->ecctype = MTD_ECC_SW;
        mtd->erase = nand_erase;
        mtd->point = NULL;
        mtd->unpoint = NULL;
        mtd->read = nand_read;
        mtd->write = nand_write;
-       mtd->read_ecc = nand_read_ecc;
-       mtd->write_ecc = nand_write_ecc;
        mtd->read_oob = nand_read_oob;
        mtd->write_oob = nand_write_oob;
-       mtd->readv = NULL;
-       mtd->writev = nand_writev;
-       mtd->writev_ecc = nand_writev_ecc;
        mtd->sync = nand_sync;
        mtd->lock = NULL;
        mtd->unlock = NULL;
@@ -2692,47 +2490,38 @@ int nand_scan (struct mtd_info *mtd, int maxchips)
        mtd->block_isbad = nand_block_isbad;
        mtd->block_markbad = nand_block_markbad;
 
-       /* and make the autooob the default one */
-       memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
-
-       mtd->owner = THIS_MODULE;
+       /* propagate ecc.layout to mtd_info */
+       mtd->ecclayout = chip->ecc.layout;
 
        /* Check, if we should skip the bad block table scan */
-       if (this->options & NAND_SKIP_BBTSCAN)
+       if (chip->options & NAND_SKIP_BBTSCAN)
                return 0;
 
        /* Build bad block table */
-       return this->scan_bbt (mtd);
+       return chip->scan_bbt(mtd);
 }
 
 /**
  * nand_release - [NAND Interface] Free resources held by the NAND device
  * @mtd:       MTD device structure
 */
-void nand_release (struct mtd_info *mtd)
+void nand_release(struct mtd_info *mtd)
 {
-       struct nand_chip *this = mtd->priv;
+       struct nand_chip *chip = mtd->priv;
 
 #ifdef CONFIG_MTD_PARTITIONS
        /* Deregister partitions */
-       del_mtd_partitions (mtd);
+       del_mtd_partitions(mtd);
 #endif
        /* Deregister the device */
-       del_mtd_device (mtd);
+       del_mtd_device(mtd);
 
        /* Free bad block table memory */
-       kfree (this->bbt);
-       /* Buffer allocated by nand_scan ? */
-       if (this->options & NAND_OOBBUF_ALLOC)
-               kfree (this->oob_buf);
-       /* Buffer allocated by nand_scan ? */
-       if (this->options & NAND_DATABUF_ALLOC)
-               kfree (this->data_buf);
+       kfree(chip->bbt);
 }
 
-EXPORT_SYMBOL_GPL (nand_scan);
-EXPORT_SYMBOL_GPL (nand_release);
-
+EXPORT_SYMBOL_GPL(nand_scan);
+EXPORT_SYMBOL_GPL(nand_release);
 
 static int __init nand_base_init(void)
 {
@@ -2748,6 +2537,6 @@ static void __exit nand_base_exit(void)
 module_init(nand_base_init);
 module_exit(nand_base_exit);
 
-MODULE_LICENSE ("GPL");
-MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION ("Generic NAND flash driver code");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
+MODULE_DESCRIPTION("Generic NAND flash driver code");
index ca286999fe08ab3b39e89f6f2963bc708b440569..a612c4ea8194d86750c39d0aac18784cbfe20606 100644 (file)
@@ -48,7 +48,7 @@
  *
  * Following assumptions are made:
  * - bbts start at a page boundary, if autolocated on a block boundary
- * - the space neccecary for a bbt in FLASH does not exceed a block boundary
+ * - the space necessary for a bbt in FLASH does not exceed a block boundary
  *
  */
 
@@ -60,7 +60,7 @@
 #include <linux/mtd/compatmac.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
-
+#include <linux/vmalloc.h>
 
 /**
  * check_pattern - [GENERIC] check if a pattern is in the buffer
@@ -75,7 +75,7 @@
  * pattern area contain 0xff
  *
 */
-static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
+static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
 {
        int i, end = 0;
        uint8_t *p = buf;
@@ -116,7 +116,7 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des
  * no optional empty check
  *
 */
-static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td)
+static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
 {
        int i;
        uint8_t *p = buf;
@@ -142,8 +142,8 @@ static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td)
  * Read the bad block table starting from page.
  *
  */
-static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
-       int bits, int offs, int reserved_block_code)
+static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
+                   int bits, int offs, int reserved_block_code)
 {
        int res, i, j, act = 0;
        struct nand_chip *this = mtd->priv;
@@ -152,17 +152,17 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
        uint8_t msk = (uint8_t) ((1 << bits) - 1);
 
        totlen = (num * bits) >> 3;
-       from = ((loff_t)page) << this->page_shift;
+       from = ((loff_t) page) << this->page_shift;
 
        while (totlen) {
-               len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
-               res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
+               len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
+               res = mtd->read(mtd, from, len, &retlen, buf);
                if (res < 0) {
                        if (retlen != len) {
-                               printk (KERN_INFO "nand_bbt: Error reading bad block table\n");
+                               printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
                                return res;
                        }
-                       printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
+                       printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
                }
 
                /* Analyse data */
@@ -172,22 +172,23 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
                                uint8_t tmp = (dat >> j) & msk;
                                if (tmp == msk)
                                        continue;
-                               if (reserved_block_code &&
-                                   (tmp == reserved_block_code)) {
-                                       printk (KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
-                                               ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+                               if (reserved_block_code && (tmp == reserved_block_code)) {
+                                       printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
+                                              ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
                                        this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
+                                       mtd->ecc_stats.bbtblocks++;
                                        continue;
                                }
                                /* Leave it for now, if its matured we can move this
                                 * message to MTD_DEBUG_LEVEL0 */
-                               printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
-                                       ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+                               printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
+                                      ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
                                /* Factory marked bad or worn out ? */
                                if (tmp == 0)
                                        this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
                                else
                                        this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
+                               mtd->ecc_stats.badblocks++;
                        }
                }
                totlen -= len;
@@ -207,7 +208,7 @@ static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
  * Read the bad block table for all chips starting at a given page
  * We assume that the bbt bits are in consecutive order.
 */
-static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
+static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
 {
        struct nand_chip *this = mtd->priv;
        int res = 0, i;
@@ -231,6 +232,42 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
        return 0;
 }
 
+/*
+ * Scan read raw data from flash
+ */
+static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
+                        size_t len)
+{
+       struct mtd_oob_ops ops;
+
+       ops.mode = MTD_OOB_RAW;
+       ops.ooboffs = 0;
+       ops.ooblen = mtd->oobsize;
+       ops.oobbuf = buf;
+       ops.datbuf = buf;
+       ops.len = len;
+
+       return mtd->read_oob(mtd, offs, &ops);
+}
+
+/*
+ * Scan write data with oob to flash
+ */
+static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
+                         uint8_t *buf, uint8_t *oob)
+{
+       struct mtd_oob_ops ops;
+
+       ops.mode = MTD_OOB_PLACE;
+       ops.ooboffs = 0;
+       ops.ooblen = mtd->oobsize;
+       ops.datbuf = buf;
+       ops.oobbuf = oob;
+       ops.len = len;
+
+       return mtd->write_oob(mtd, offs, &ops);
+}
+
 /**
  * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
  * @mtd:       MTD device structure
@@ -242,28 +279,85 @@ static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
  * We assume that the bbt bits are in consecutive order.
  *
 */
-static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td,
-       struct nand_bbt_descr *md)
+static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
+                        struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
        struct nand_chip *this = mtd->priv;
 
        /* Read the primary version, if available */
        if (td->options & NAND_BBT_VERSION) {
-               nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
-               td->version[0] = buf[mtd->oobblock + td->veroffs];
-               printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
+               scan_read_raw(mtd, buf, td->pages[0] << this->page_shift,
+                             mtd->writesize);
+               td->version[0] = buf[mtd->writesize + td->veroffs];
+               printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
+                      td->pages[0], td->version[0]);
        }
 
        /* Read the mirror version, if available */
        if (md && (md->options & NAND_BBT_VERSION)) {
-               nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
-               md->version[0] = buf[mtd->oobblock + md->veroffs];
-               printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
+               scan_read_raw(mtd, buf, md->pages[0] << this->page_shift,
+                             mtd->writesize);
+               md->version[0] = buf[mtd->writesize + md->veroffs];
+               printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
+                      md->pages[0], md->version[0]);
        }
-
        return 1;
 }
 
+/*
+ * Scan a given block full
+ */
+static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
+                          loff_t offs, uint8_t *buf, size_t readlen,
+                          int scanlen, int len)
+{
+       int ret, j;
+
+       ret = scan_read_raw(mtd, buf, offs, readlen);
+       if (ret)
+               return ret;
+
+       for (j = 0; j < len; j++, buf += scanlen) {
+               if (check_pattern(buf, scanlen, mtd->writesize, bd))
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ * Scan a given block partially
+ */
+static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
+                          loff_t offs, uint8_t *buf, int len)
+{
+       struct mtd_oob_ops ops;
+       int j, ret;
+
+       ops.len = mtd->oobsize;
+       ops.ooblen = mtd->oobsize;
+       ops.oobbuf = buf;
+       ops.ooboffs = 0;
+       ops.datbuf = NULL;
+       ops.mode = MTD_OOB_PLACE;
+
+       for (j = 0; j < len; j++) {
+               /*
+                * Read the full oob until read_oob is fixed to
+                * handle single byte reads for 16 bit
+                * buswidth
+                */
+               ret = mtd->read_oob(mtd, offs, &ops);
+               if (ret)
+                       return ret;
+
+               if (check_short_pattern(buf, bd))
+                       return 1;
+
+               offs += mtd->writesize;
+       }
+       return 0;
+}
+
 /**
  * create_bbt - [GENERIC] Create a bad block table by scanning the device
  * @mtd:       MTD device structure
@@ -275,15 +369,16 @@ static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_de
  * Create a bad block table by scanning the device
  * for the given good/bad block identify pattern
  */
-static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
+static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
+       struct nand_bbt_descr *bd, int chip)
 {
        struct nand_chip *this = mtd->priv;
-       int i, j, numblocks, len, scanlen;
+       int i, numblocks, len, scanlen;
        int startblock;
        loff_t from;
-       size_t readlen, ooblen;
+       size_t readlen;
 
-       printk (KERN_INFO "Scanning device for bad blocks\n");
+       printk(KERN_INFO "Scanning device for bad blocks\n");
 
        if (bd->options & NAND_BBT_SCANALLPAGES)
                len = 1 << (this->bbt_erase_shift - this->page_shift);
@@ -296,25 +391,24 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 
        if (!(bd->options & NAND_BBT_SCANEMPTY)) {
                /* We need only read few bytes from the OOB area */
-               scanlen = ooblen = 0;
+               scanlen = 0;
                readlen = bd->len;
        } else {
                /* Full page content should be read */
-               scanlen = mtd->oobblock + mtd->oobsize;
-               readlen = len * mtd->oobblock;
-               ooblen = len * mtd->oobsize;
+               scanlen = mtd->writesize + mtd->oobsize;
+               readlen = len * mtd->writesize;
        }
 
        if (chip == -1) {
-               /* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it
-                * makes shifting and masking less painful */
+               /* Note that numblocks is 2 * (real numblocks) here, see i+=2
+                * below as it makes shifting and masking less painful */
                numblocks = mtd->size >> (this->bbt_erase_shift - 1);
                startblock = 0;
                from = 0;
        } else {
                if (chip >= this->numchips) {
-                       printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
-                               chip + 1, this->numchips);
+                       printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
+                              chip + 1, this->numchips);
                        return -EINVAL;
                }
                numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
@@ -326,36 +420,22 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
        for (i = startblock; i < numblocks;) {
                int ret;
 
-               if (bd->options & NAND_BBT_SCANEMPTY)
-                       if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen)))
-                               return ret;
-
-               for (j = 0; j < len; j++) {
-                       if (!(bd->options & NAND_BBT_SCANEMPTY)) {
-                               size_t retlen;
-
-                               /* Read the full oob until read_oob is fixed to
-                                * handle single byte reads for 16 bit buswidth */
-                               ret = mtd->read_oob(mtd, from + j * mtd->oobblock,
-                                                       mtd->oobsize, &retlen, buf);
-                               if (ret)
-                                       return ret;
-
-                               if (check_short_pattern (buf, bd)) {
-                                       this->bbt[i >> 3] |= 0x03 << (i & 0x6);
-                                       printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
-                                               i >> 1, (unsigned int) from);
-                                       break;
-                               }
-                       } else {
-                               if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
-                                       this->bbt[i >> 3] |= 0x03 << (i & 0x6);
-                                       printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
-                                               i >> 1, (unsigned int) from);
-                                       break;
-                               }
-                       }
+               if (bd->options & NAND_BBT_SCANALLPAGES)
+                       ret = scan_block_full(mtd, bd, from, buf, readlen,
+                                             scanlen, len);
+               else
+                       ret = scan_block_fast(mtd, bd, from, buf, len);
+
+               if (ret < 0)
+                       return ret;
+
+               if (ret) {
+                       this->bbt[i >> 3] |= 0x03 << (i & 0x6);
+                       printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
+                              i >> 1, (unsigned int)from);
+                       mtd->ecc_stats.badblocks++;
                }
+
                i += 2;
                from += (1 << this->bbt_erase_shift);
        }
@@ -374,22 +454,23 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
  * block.
  * If the option NAND_BBT_PERCHIP is given, each chip is searched
  * for a bbt, which contains the bad block information of this chip.
- * This is neccecary to provide support for certain DOC devices.
+ * This is necessary to provide support for certain DOC devices.
  *
  * The bbt ident pattern resides in the oob area of the first page
  * in a block.
  */
-static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
+static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
 {
        struct nand_chip *this = mtd->priv;
        int i, chips;
        int bits, startblock, block, dir;
-       int scanlen = mtd->oobblock + mtd->oobsize;
+       int scanlen = mtd->writesize + mtd->oobsize;
        int bbtblocks;
+       int blocktopage = this->bbt_erase_shift - this->page_shift;
 
        /* Search direction top -> down ? */
        if (td->options & NAND_BBT_LASTBLOCK) {
-               startblock = (mtd->size >> this->bbt_erase_shift) -1;
+               startblock = (mtd->size >> this->bbt_erase_shift) - 1;
                dir = -1;
        } else {
                startblock = 0;
@@ -415,13 +496,16 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
                td->pages[i] = -1;
                /* Scan the maximum number of blocks */
                for (block = 0; block < td->maxblocks; block++) {
+
                        int actblock = startblock + dir * block;
+                       loff_t offs = actblock << this->bbt_erase_shift;
+
                        /* Read first page */
-                       nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
-                       if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
-                               td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
+                       scan_read_raw(mtd, buf, offs, mtd->writesize);
+                       if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
+                               td->pages[i] = actblock << blocktopage;
                                if (td->options & NAND_BBT_VERSION) {
-                                       td->version[i] = buf[mtd->oobblock + td->veroffs];
+                                       td->version[i] = buf[mtd->writesize + td->veroffs];
                                }
                                break;
                        }
@@ -431,9 +515,10 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
        /* Check, if we found a bbt for each requested chip */
        for (i = 0; i < chips; i++) {
                if (td->pages[i] == -1)
-                       printk (KERN_WARNING "Bad block table not found for chip %d\n", i);
+                       printk(KERN_WARNING "Bad block table not found for chip %d\n", i);
                else
-                       printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]);
+                       printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i],
+                              td->version[i]);
        }
        return 0;
 }
@@ -447,21 +532,19 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
  *
  * Search and read the bad block table(s)
 */
-static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
-       struct nand_bbt_descr *td, struct nand_bbt_descr *md)
+static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
        /* Search the primary table */
-       search_bbt (mtd, buf, td);
+       search_bbt(mtd, buf, td);
 
        /* Search the mirror table */
        if (md)
-               search_bbt (mtd, buf, md);
+               search_bbt(mtd, buf, md);
 
        /* Force result check */
        return 1;
 }
 
-
 /**
  * write_bbt - [GENERIC] (Re)write the bad block table
  *
@@ -474,25 +557,31 @@ static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
  * (Re)write the bad block table
  *
 */
-static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
-       struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
+static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
+                    struct nand_bbt_descr *td, struct nand_bbt_descr *md,
+                    int chipsel)
 {
        struct nand_chip *this = mtd->priv;
-       struct nand_oobinfo oobinfo;
        struct erase_info einfo;
        int i, j, res, chip = 0;
        int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
-       int nrchips, bbtoffs, pageoffs;
+       int nrchips, bbtoffs, pageoffs, ooboffs;
        uint8_t msk[4];
        uint8_t rcode = td->reserved_block_code;
        size_t retlen, len = 0;
        loff_t to;
+       struct mtd_oob_ops ops;
+
+       ops.ooblen = mtd->oobsize;
+       ops.ooboffs = 0;
+       ops.datbuf = NULL;
+       ops.mode = MTD_OOB_PLACE;
 
        if (!rcode)
                rcode = 0xff;
        /* Write bad block table per chip rather than per device ? */
        if (td->options & NAND_BBT_PERCHIP) {
-               numblocks = (int) (this->chipsize >> this->bbt_erase_shift);
+               numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
                /* Full device write or specific chip ? */
                if (chipsel == -1) {
                        nrchips = this->numchips;
@@ -501,7 +590,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
                        chip = chipsel;
                }
        } else {
-               numblocks = (int) (mtd->size >> this->bbt_erase_shift);
+               numblocks = (int)(mtd->size >> this->bbt_erase_shift);
                nrchips = 1;
        }
 
@@ -530,27 +619,38 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
                for (i = 0; i < td->maxblocks; i++) {
                        int block = startblock + dir * i;
                        /* Check, if the block is bad */
-                       switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) {
+                       switch ((this->bbt[block >> 2] >>
+                                (2 * (block & 0x03))) & 0x03) {
                        case 0x01:
                        case 0x03:
                                continue;
                        }
-                       page = block << (this->bbt_erase_shift - this->page_shift);
+                       page = block <<
+                               (this->bbt_erase_shift - this->page_shift);
                        /* Check, if the block is used by the mirror table */
                        if (!md || md->pages[chip] != page)
                                goto write;
                }
-               printk (KERN_ERR "No space left to write bad block table\n");
+               printk(KERN_ERR "No space left to write bad block table\n");
                return -ENOSPC;
-write:
+       write:
 
                /* Set up shift count and masks for the flash table */
                bits = td->options & NAND_BBT_NRBITS_MSK;
+               msk[2] = ~rcode;
                switch (bits) {
-               case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break;
-               case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break;
-               case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break;
-               case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break;
+               case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
+                       msk[3] = 0x01;
+                       break;
+               case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
+                       msk[3] = 0x03;
+                       break;
+               case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
+                       msk[3] = 0x0f;
+                       break;
+               case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
+                       msk[3] = 0xff;
+                       break;
                default: return -EINVAL;
                }
 
@@ -558,82 +658,92 @@ write:
 
                to = ((loff_t) page) << this->page_shift;
 
-               memcpy (&oobinfo, this->autooob, sizeof(oobinfo));
-               oobinfo.useecc = MTD_NANDECC_PLACEONLY;
-
                /* Must we save the block contents ? */
                if (td->options & NAND_BBT_SAVECONTENT) {
                        /* Make it block aligned */
                        to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
                        len = 1 << this->bbt_erase_shift;
-                       res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
+                       res = mtd->read(mtd, to, len, &retlen, buf);
                        if (res < 0) {
                                if (retlen != len) {
-                                       printk (KERN_INFO "nand_bbt: Error reading block for writing the bad block table\n");
+                                       printk(KERN_INFO "nand_bbt: Error "
+                                              "reading block for writing "
+                                              "the bad block table\n");
                                        return res;
                                }
-                               printk (KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n");
+                               printk(KERN_WARNING "nand_bbt: ECC error "
+                                      "while reading block for writing "
+                                      "bad block table\n");
                        }
+                       /* Read oob data */
+                       ops.len = (len >> this->page_shift) * mtd->oobsize;
+                       ops.oobbuf = &buf[len];
+                       res = mtd->read_oob(mtd, to + mtd->writesize, &ops);
+                       if (res < 0 || ops.retlen != ops.len)
+                               goto outerr;
+
                        /* Calc the byte offset in the buffer */
                        pageoffs = page - (int)(to >> this->page_shift);
                        offs = pageoffs << this->page_shift;
                        /* Preset the bbt area with 0xff */
-                       memset (&buf[offs], 0xff, (size_t)(numblocks >> sft));
-                       /* Preset the bbt's oob area with 0xff */
-                       memset (&buf[len + pageoffs * mtd->oobsize], 0xff,
-                               ((len >> this->page_shift) - pageoffs) * mtd->oobsize);
-                       if (td->options & NAND_BBT_VERSION) {
-                               buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
-                       }
+                       memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
+                       ooboffs = len + (pageoffs * mtd->oobsize);
+
                } else {
                        /* Calc length */
                        len = (size_t) (numblocks >> sft);
                        /* Make it page aligned ! */
-                       len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1);
+                       len = (len + (mtd->writesize - 1)) &
+                               ~(mtd->writesize - 1);
                        /* Preset the buffer with 0xff */
-                       memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
+                       memset(buf, 0xff, len +
+                              (len >> this->page_shift)* mtd->oobsize);
                        offs = 0;
+                       ooboffs = len;
                        /* Pattern is located in oob area of first page */
-                       memcpy (&buf[len + td->offs], td->pattern, td->len);
-                       if (td->options & NAND_BBT_VERSION) {
-                               buf[len + td->veroffs] = td->version[chip];
-                       }
+                       memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
                }
 
+               if (td->options & NAND_BBT_VERSION)
+                       buf[ooboffs + td->veroffs] = td->version[chip];
+
                /* walk through the memory table */
-               for (i = 0; i < numblocks; ) {
+               for (i = 0; i < numblocks;) {
                        uint8_t dat;
                        dat = this->bbt[bbtoffs + (i >> 2)];
-                       for (j = 0; j < 4; j++ , i++) {
+                       for (j = 0; j < 4; j++, i++) {
                                int sftcnt = (i << (3 - sft)) & sftmsk;
                                /* Do not store the reserved bbt blocks ! */
-                               buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt);
+                               buf[offs + (i >> sft)] &=
+                                       ~(msk[dat & 0x03] << sftcnt);
                                dat >>= 2;
                        }
                }
 
-               memset (&einfo, 0, sizeof (einfo));
+               memset(&einfo, 0, sizeof(einfo));
                einfo.mtd = mtd;
-               einfo.addr = (unsigned long) to;
+               einfo.addr = (unsigned long)to;
                einfo.len = 1 << this->bbt_erase_shift;
-               res = nand_erase_nand (mtd, &einfo, 1);
-               if (res < 0) {
-                       printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
-                       return res;
-               }
+               res = nand_erase_nand(mtd, &einfo, 1);
+               if (res < 0)
+                       goto outerr;
 
-               res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
-               if (res < 0) {
-                       printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
-                       return res;
-               }
-               printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n",
-                       (unsigned int) to, td->version[chip]);
+               res = scan_write_bbt(mtd, to, len, buf, &buf[len]);
+               if (res < 0)
+                       goto outerr;
+
+               printk(KERN_DEBUG "Bad block table written to 0x%08x, version "
+                      "0x%02X\n", (unsigned int)to, td->version[chip]);
 
                /* Mark it as used */
                td->pages[chip] = page;
        }
        return 0;
+
+ outerr:
+       printk(KERN_WARNING
+              "nand_bbt: Error while writing bad block table %d\n", res);
+       return res;
 }
 
 /**
@@ -644,27 +754,27 @@ write:
  * The function creates a memory based bbt by scanning the device
  * for manufacturer / software marked good / bad blocks
 */
-static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
+static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
        struct nand_chip *this = mtd->priv;
 
        bd->options &= ~NAND_BBT_SCANEMPTY;
-       return create_bbt (mtd, this->data_buf, bd, -1);
+       return create_bbt(mtd, this->buffers.databuf, bd, -1);
 }
 
 /**
- * check_create - [GENERIC] create and write bbt(s) if neccecary
+ * check_create - [GENERIC] create and write bbt(s) if necessary
  * @mtd:       MTD device structure
  * @buf:       temporary buffer
  * @bd:                descriptor for the good/bad block search pattern
  *
  * The function checks the results of the previous call to read_bbt
- * and creates / updates the bbt(s) if neccecary
- * Creation is neccecary if no bbt was found for the chip/device
- * Update is neccecary if one of the tables is missing or the
+ * and creates / updates the bbt(s) if necessary
+ * Creation is necessary if no bbt was found for the chip/device
+ * Update is necessary if one of the tables is missing or the
  * version nr. of one table is less than the other
 */
-static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
+static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
 {
        int i, chips, writeops, chipsel, res;
        struct nand_chip *this = mtd->priv;
@@ -732,35 +842,35 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des
                        rd = td;
                        goto writecheck;
                }
-create:
+       create:
                /* Create the bad block table by scanning the device ? */
                if (!(td->options & NAND_BBT_CREATE))
                        continue;
 
                /* Create the table in memory by scanning the chip(s) */
-               create_bbt (mtd, buf, bd, chipsel);
+               create_bbt(mtd, buf, bd, chipsel);
 
                td->version[i] = 1;
                if (md)
                        md->version[i] = 1;
-writecheck:
+       writecheck:
                /* read back first ? */
                if (rd)
-                       read_abs_bbt (mtd, buf, rd, chipsel);
+                       read_abs_bbt(mtd, buf, rd, chipsel);
                /* If they weren't versioned, read both. */
                if (rd2)
-                       read_abs_bbt (mtd, buf, rd2, chipsel);
+                       read_abs_bbt(mtd, buf, rd2, chipsel);
 
                /* Write the bad block table to the device ? */
                if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
-                       res = write_bbt (mtd, buf, td, md, chipsel);
+                       res = write_bbt(mtd, buf, td, md, chipsel);
                        if (res < 0)
                                return res;
                }
 
                /* Write the mirror bad block table to the device ? */
                if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
-                       res = write_bbt (mtd, buf, md, td, chipsel);
+                       res = write_bbt(mtd, buf, md, td, chipsel);
                        if (res < 0)
                                return res;
                }
@@ -777,7 +887,7 @@ writecheck:
  * accidental erasures / writes. The regions are identified by
  * the mark 0x02.
 */
-static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
+static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 {
        struct nand_chip *this = mtd->priv;
        int i, j, chips, block, nrblocks, update;
@@ -795,7 +905,8 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
        for (i = 0; i < chips; i++) {
                if ((td->options & NAND_BBT_ABSPAGE) ||
                    !(td->options & NAND_BBT_WRITE)) {
-                       if (td->pages[i] == -1) continue;
+                       if (td->pages[i] == -1)
+                               continue;
                        block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
                        block <<= 1;
                        oldval = this->bbt[(block >> 3)];
@@ -815,7 +926,8 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
                        oldval = this->bbt[(block >> 3)];
                        newval = oldval | (0x2 << (block & 0x06));
                        this->bbt[(block >> 3)] = newval;
-                       if (oldval != newval) update = 1;
+                       if (oldval != newval)
+                               update = 1;
                        block += 2;
                }
                /* If we want reserved blocks to be recorded to flash, and some
@@ -840,7 +952,7 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
  * by calling the nand_free_bbt function.
  *
 */
-int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
+int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
        struct nand_chip *this = mtd->priv;
        int len, res = 0;
@@ -850,21 +962,21 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
 
        len = mtd->size >> (this->bbt_erase_shift + 2);
        /* Allocate memory (2bit per block) */
-       this->bbt = kmalloc (len, GFP_KERNEL);
+       this->bbt = kmalloc(len, GFP_KERNEL);
        if (!this->bbt) {
-               printk (KERN_ERR "nand_scan_bbt: Out of memory\n");
+               printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
                return -ENOMEM;
        }
        /* Clear the memory bad block table */
-       memset (this->bbt, 0x00, len);
+       memset(this->bbt, 0x00, len);
 
        /* If no primary table decriptor is given, scan the device
         * to build a memory based bad block table
         */
        if (!td) {
                if ((res = nand_memory_bbt(mtd, bd))) {
-                       printk (KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
-                       kfree (this->bbt);
+                       printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
+                       kfree(this->bbt);
                        this->bbt = NULL;
                }
                return res;
@@ -873,35 +985,34 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
        /* Allocate a temporary buffer for one eraseblock incl. oob */
        len = (1 << this->bbt_erase_shift);
        len += (len >> this->page_shift) * mtd->oobsize;
-       buf = kmalloc (len, GFP_KERNEL);
+       buf = vmalloc(len);
        if (!buf) {
-               printk (KERN_ERR "nand_bbt: Out of memory\n");
-               kfree (this->bbt);
+               printk(KERN_ERR "nand_bbt: Out of memory\n");
+               kfree(this->bbt);
                this->bbt = NULL;
                return -ENOMEM;
        }
 
        /* Is the bbt at a given page ? */
        if (td->options & NAND_BBT_ABSPAGE) {
-               res = read_abs_bbts (mtd, buf, td, md);
+               res = read_abs_bbts(mtd, buf, td, md);
        } else {
                /* Search the bad block table using a pattern in oob */
-               res = search_read_bbts (mtd, buf, td, md);
+               res = search_read_bbts(mtd, buf, td, md);
        }
 
        if (res)
-               res = check_create (mtd, buf, bd);
+               res = check_create(mtd, buf, bd);
 
        /* Prevent the bbt regions from erasing / writing */
-       mark_bbt_region (mtd, td);
+       mark_bbt_region(mtd, td);
        if (md)
-               mark_bbt_region (mtd, md);
+               mark_bbt_region(mtd, md);
 
-       kfree (buf);
+       vfree(buf);
        return res;
 }
 
-
 /**
  * nand_update_bbt - [NAND Interface] update bad block table(s)
  * @mtd:       MTD device structure
@@ -909,7 +1020,7 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
  *
  * The function updates the bad block table(s)
 */
-int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
+int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 {
        struct nand_chip *this = mtd->priv;
        int len, res = 0, writeops = 0;
@@ -925,9 +1036,9 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
        /* Allocate a temporary buffer for one eraseblock incl. oob */
        len = (1 << this->bbt_erase_shift);
        len += (len >> this->page_shift) * mtd->oobsize;
-       buf = kmalloc (len, GFP_KERNEL);
+       buf = kmalloc(len, GFP_KERNEL);
        if (!buf) {
-               printk (KERN_ERR "nand_update_bbt: Out of memory\n");
+               printk(KERN_ERR "nand_update_bbt: Out of memory\n");
                return -ENOMEM;
        }
 
@@ -935,7 +1046,7 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
 
        /* Do we have a bbt per chip ? */
        if (td->options & NAND_BBT_PERCHIP) {
-               chip = (int) (offs >> this->chip_shift);
+               chip = (int)(offs >> this->chip_shift);
                chipsel = chip;
        } else {
                chip = 0;
@@ -948,17 +1059,17 @@ int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
 
        /* Write the bad block table to the device ? */
        if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
-               res = write_bbt (mtd, buf, td, md, chipsel);
+               res = write_bbt(mtd, buf, td, md, chipsel);
                if (res < 0)
                        goto out;
        }
        /* Write the mirror bad block table to the device ? */
        if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
-               res = write_bbt (mtd, buf, md, td, chipsel);
+               res = write_bbt(mtd, buf, md, td, chipsel);
        }
 
-out:
-       kfree (buf);
+ out:
+       kfree(buf);
        return res;
 }
 
@@ -981,14 +1092,14 @@ static struct nand_bbt_descr largepage_memorybased = {
 };
 
 static struct nand_bbt_descr smallpage_flashbased = {
-       .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+       .options = NAND_BBT_SCAN2NDPAGE,
        .offs = 5,
        .len = 1,
        .pattern = scan_ff_pattern
 };
 
 static struct nand_bbt_descr largepage_flashbased = {
-       .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+       .options = NAND_BBT_SCAN2NDPAGE,
        .offs = 0,
        .len = 2,
        .pattern = scan_ff_pattern
@@ -1036,7 +1147,7 @@ static struct nand_bbt_descr bbt_mirror_descr = {
  * support for the device and calls the nand_scan_bbt function
  *
 */
-int nand_default_bbt (struct mtd_info *mtd)
+int nand_default_bbt(struct mtd_info *mtd)
 {
        struct nand_chip *this = mtd->priv;
 
@@ -1046,7 +1157,7 @@ int nand_default_bbt (struct mtd_info *mtd)
         * of the good / bad information, so we _must_ store
         * this information in a good / bad table during
         * startup
-       */
+        */
        if (this->options & NAND_IS_AND) {
                /* Use the default pattern descriptors */
                if (!this->bbt_td) {
@@ -1054,10 +1165,9 @@ int nand_default_bbt (struct mtd_info *mtd)
                        this->bbt_md = &bbt_mirror_descr;
                }
                this->options |= NAND_USE_FLASH_BBT;
-               return nand_scan_bbt (mtd, &agand_flashbased);
+               return nand_scan_bbt(mtd, &agand_flashbased);
        }
 
-
        /* Is a flash based bad block table requested ? */
        if (this->options & NAND_USE_FLASH_BBT) {
                /* Use the default pattern descriptors */
@@ -1066,18 +1176,17 @@ int nand_default_bbt (struct mtd_info *mtd)
                        this->bbt_md = &bbt_mirror_descr;
                }
                if (!this->badblock_pattern) {
-                       this->badblock_pattern = (mtd->oobblock > 512) ?
-                               &largepage_flashbased : &smallpage_flashbased;
+                       this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased;
                }
        } else {
                this->bbt_td = NULL;
                this->bbt_md = NULL;
                if (!this->badblock_pattern) {
-                       this->badblock_pattern = (mtd->oobblock > 512) ?
-                               &largepage_memorybased : &smallpage_memorybased;
+                       this->badblock_pattern = (mtd->writesize > 512) ?
+                           &largepage_memorybased : &smallpage_memorybased;
                }
        }
-       return nand_scan_bbt (mtd, this->badblock_pattern);
+       return nand_scan_bbt(mtd, this->badblock_pattern);
 }
 
 /**
@@ -1087,26 +1196,29 @@ int nand_default_bbt (struct mtd_info *mtd)
  * @allowbbt:  allow access to bad block table region
  *
 */
-int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
+int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 {
        struct nand_chip *this = mtd->priv;
        int block;
-       uint8_t res;
+       uint8_t res;
 
        /* Get block number * 2 */
-       block = (int) (offs >> (this->bbt_erase_shift - 1));
+       block = (int)(offs >> (this->bbt_erase_shift - 1));
        res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
-       DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
-               (unsigned int)offs, block >> 1, res);
+       DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
+             (unsigned int)offs, block >> 1, res);
 
        switch ((int)res) {
-       case 0x00:      return 0;
-       case 0x01:      return 1;
-       case 0x02:      return allowbbt ? 0 : 1;
+       case 0x00:
+               return 0;
+       case 0x01:
+               return 1;
+       case 0x02:
+               return allowbbt ? 0 : 1;
        }
        return 1;
 }
 
-EXPORT_SYMBOL (nand_scan_bbt);
-EXPORT_SYMBOL (nand_default_bbt);
+EXPORT_SYMBOL(nand_scan_bbt);
+EXPORT_SYMBOL(nand_default_bbt);
index 40ac909150a3db5701c572fe536b9e1e6a5c766b..2a163e4084df0dde8a3ada36357b58b60f11ce50 100644 (file)
@@ -7,6 +7,8 @@
  * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
  *                         Toshiba America Electronics Components, Inc.
  *
+ * Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+ *
  * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $
  *
  * This file is free software; you can redistribute it and/or modify it
@@ -62,90 +64,76 @@ static const u_char nand_ecc_precalc_table[] = {
        0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
 };
 
-
 /**
- * nand_trans_result - [GENERIC] create non-inverted ECC
- * @reg2:      line parity reg 2
- * @reg3:      line parity reg 3
- * @ecc_code:  ecc
- *
- * Creates non-inverted ECC code from line parity
- */
-static void nand_trans_result(u_char reg2, u_char reg3,
-       u_char *ecc_code)
-{
-       u_char a, b, i, tmp1, tmp2;
-
-       /* Initialize variables */
-       a = b = 0x80;
-       tmp1 = tmp2 = 0;
-
-       /* Calculate first ECC byte */
-       for (i = 0; i < 4; i++) {
-               if (reg3 & a)           /* LP15,13,11,9 --> ecc_code[0] */
-                       tmp1 |= b;
-               b >>= 1;
-               if (reg2 & a)           /* LP14,12,10,8 --> ecc_code[0] */
-                       tmp1 |= b;
-               b >>= 1;
-               a >>= 1;
-       }
-
-       /* Calculate second ECC byte */
-       b = 0x80;
-       for (i = 0; i < 4; i++) {
-               if (reg3 & a)           /* LP7,5,3,1 --> ecc_code[1] */
-                       tmp2 |= b;
-               b >>= 1;
-               if (reg2 & a)           /* LP6,4,2,0 --> ecc_code[1] */
-                       tmp2 |= b;
-               b >>= 1;
-               a >>= 1;
-       }
-
-       /* Store two of the ECC bytes */
-       ecc_code[0] = tmp1;
-       ecc_code[1] = tmp2;
-}
-
-/**
- * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block
+ * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code
+ *                     for 256 byte block
  * @mtd:       MTD block structure
  * @dat:       raw data
  * @ecc_code:  buffer for ECC
  */
-int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+                      u_char *ecc_code)
 {
-       u_char idx, reg1, reg2, reg3;
-       int j;
+       uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
+       int i;
 
        /* Initialize variables */
        reg1 = reg2 = reg3 = 0;
-       ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
 
        /* Build up column parity */
-       for(j = 0; j < 256; j++) {
-
+       for(i = 0; i < 256; i++) {
                /* Get CP0 - CP5 from table */
-               idx = nand_ecc_precalc_table[dat[j]];
+               idx = nand_ecc_precalc_table[*dat++];
                reg1 ^= (idx & 0x3f);
 
                /* All bit XOR = 1 ? */
                if (idx & 0x40) {
-                       reg3 ^= (u_char) j;
-                       reg2 ^= ~((u_char) j);
+                       reg3 ^= (uint8_t) i;
+                       reg2 ^= ~((uint8_t) i);
                }
        }
 
        /* Create non-inverted ECC code from line parity */
-       nand_trans_result(reg2, reg3, ecc_code);
+       tmp1  = (reg3 & 0x80) >> 0; /* B7 -> B7 */
+       tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
+       tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
+       tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
+       tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
+       tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
+       tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
+       tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
+
+       tmp2  = (reg3 & 0x08) << 4; /* B3 -> B7 */
+       tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
+       tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
+       tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
+       tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
+       tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
+       tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
+       tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
 
        /* Calculate final ECC code */
-       ecc_code[0] = ~ecc_code[0];
-       ecc_code[1] = ~ecc_code[1];
+#ifdef CONFIG_NAND_ECC_SMC
+       ecc_code[0] = ~tmp2;
+       ecc_code[1] = ~tmp1;
+#else
+       ecc_code[0] = ~tmp1;
+       ecc_code[1] = ~tmp2;
+#endif
        ecc_code[2] = ((~reg1) << 2) | 0x03;
+
        return 0;
 }
+EXPORT_SYMBOL(nand_calculate_ecc);
+
+static inline int countbits(uint32_t byte)
+{
+       int res = 0;
+
+       for (;byte; byte >>= 1)
+               res += byte & 0x01;
+       return res;
+}
 
 /**
  * nand_correct_data - [NAND Interface] Detect and correct bit error(s)
@@ -156,93 +144,54 @@ int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code
  *
  * Detect and correct a 1 bit error for 256 byte block
  */
-int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+int nand_correct_data(struct mtd_info *mtd, u_char *dat,
+                     u_char *read_ecc, u_char *calc_ecc)
 {
-       u_char a, b, c, d1, d2, d3, add, bit, i;
+       uint8_t s0, s1, s2;
+
+#ifdef CONFIG_NAND_ECC_SMC
+       s0 = calc_ecc[0] ^ read_ecc[0];
+       s1 = calc_ecc[1] ^ read_ecc[1];
+       s2 = calc_ecc[2] ^ read_ecc[2];
+#else
+       s1 = calc_ecc[0] ^ read_ecc[0];
+       s0 = calc_ecc[1] ^ read_ecc[1];
+       s2 = calc_ecc[2] ^ read_ecc[2];
+#endif
+       if ((s0 | s1 | s2) == 0)
+               return 0;
 
-       /* Do error detection */
-       d1 = calc_ecc[0] ^ read_ecc[0];
-       d2 = calc_ecc[1] ^ read_ecc[1];
-       d3 = calc_ecc[2] ^ read_ecc[2];
+       /* Check for a single bit error */
+       if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
+           ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
+           ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
 
-       if ((d1 | d2 | d3) == 0) {
-               /* No errors */
-               return 0;
-       }
-       else {
-               a = (d1 ^ (d1 >> 1)) & 0x55;
-               b = (d2 ^ (d2 >> 1)) & 0x55;
-               c = (d3 ^ (d3 >> 1)) & 0x54;
-
-               /* Found and will correct single bit error in the data */
-               if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
-                       c = 0x80;
-                       add = 0;
-                       a = 0x80;
-                       for (i=0; i<4; i++) {
-                               if (d1 & c)
-                                       add |= a;
-                               c >>= 2;
-                               a >>= 1;
-                       }
-                       c = 0x80;
-                       for (i=0; i<4; i++) {
-                               if (d2 & c)
-                                       add |= a;
-                               c >>= 2;
-                               a >>= 1;
-                       }
-                       bit = 0;
-                       b = 0x04;
-                       c = 0x80;
-                       for (i=0; i<3; i++) {
-                               if (d3 & c)
-                                       bit |= b;
-                               c >>= 2;
-                               b >>= 1;
-                       }
-                       b = 0x01;
-                       a = dat[add];
-                       a ^= (b << bit);
-                       dat[add] = a;
-                       return 1;
-               }
-               else {
-                       i = 0;
-                       while (d1) {
-                               if (d1 & 0x01)
-                                       ++i;
-                               d1 >>= 1;
-                       }
-                       while (d2) {
-                               if (d2 & 0x01)
-                                       ++i;
-                               d2 >>= 1;
-                       }
-                       while (d3) {
-                               if (d3 & 0x01)
-                                       ++i;
-                               d3 >>= 1;
-                       }
-                       if (i == 1) {
-                               /* ECC Code Error Correction */
-                               read_ecc[0] = calc_ecc[0];
-                               read_ecc[1] = calc_ecc[1];
-                               read_ecc[2] = calc_ecc[2];
-                               return 2;
-                       }
-                       else {
-                               /* Uncorrectable Error */
-                               return -1;
-                       }
-               }
+               uint32_t byteoffs, bitnum;
+
+               byteoffs = (s1 << 0) & 0x80;
+               byteoffs |= (s1 << 1) & 0x40;
+               byteoffs |= (s1 << 2) & 0x20;
+               byteoffs |= (s1 << 3) & 0x10;
+
+               byteoffs |= (s0 >> 4) & 0x08;
+               byteoffs |= (s0 >> 3) & 0x04;
+               byteoffs |= (s0 >> 2) & 0x02;
+               byteoffs |= (s0 >> 1) & 0x01;
+
+               bitnum = (s2 >> 5) & 0x04;
+               bitnum |= (s2 >> 4) & 0x02;
+               bitnum |= (s2 >> 3) & 0x01;
+
+               dat[byteoffs] ^= (1 << bitnum);
+
+               return 1;
        }
 
-       /* Should never happen */
+       if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
+               return 1;
+
        return -1;
 }
-
-EXPORT_SYMBOL(nand_calculate_ecc);
 EXPORT_SYMBOL(nand_correct_data);
 
 MODULE_LICENSE("GPL");
index dbc7e55a4247a215cf1097c1ea289be0d51bd357..2e2cdf2fc91d686e84de0f5cf00451a9d58808c3 100644 (file)
 *      Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
 *      options
 *
-*      Pagesize; 0, 256, 512
-*      0       get this information from the extended chip ID
+*      Pagesize; 0, 256, 512
+*      0       get this information from the extended chip ID
 +      256     256 Byte page size
 *      512     512 Byte page size
 */
 struct nand_flash_dev nand_flash_ids[] = {
-       {"NAND 1MiB 5V 8-bit",          0x6e, 256, 1, 0x1000, 0},
-       {"NAND 2MiB 5V 8-bit",          0x64, 256, 2, 0x1000, 0},
-       {"NAND 4MiB 5V 8-bit",          0x6b, 512, 4, 0x2000, 0},
-       {"NAND 1MiB 3,3V 8-bit",        0xe8, 256, 1, 0x1000, 0},
-       {"NAND 1MiB 3,3V 8-bit",        0xec, 256, 1, 0x1000, 0},
-       {"NAND 2MiB 3,3V 8-bit",        0xea, 256, 2, 0x1000, 0},
-       {"NAND 4MiB 3,3V 8-bit",        0xd5, 512, 4, 0x2000, 0},
-       {"NAND 4MiB 3,3V 8-bit",        0xe3, 512, 4, 0x2000, 0},
-       {"NAND 4MiB 3,3V 8-bit",        0xe5, 512, 4, 0x2000, 0},
-       {"NAND 8MiB 3,3V 8-bit",        0xd6, 512, 8, 0x2000, 0},
-
-       {"NAND 8MiB 1,8V 8-bit",        0x39, 512, 8, 0x2000, 0},
-       {"NAND 8MiB 3,3V 8-bit",        0xe6, 512, 8, 0x2000, 0},
-       {"NAND 8MiB 1,8V 16-bit",       0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
-       {"NAND 8MiB 3,3V 16-bit",       0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
-
-       {"NAND 16MiB 1,8V 8-bit",       0x33, 512, 16, 0x4000, 0},
-       {"NAND 16MiB 3,3V 8-bit",       0x73, 512, 16, 0x4000, 0},
-       {"NAND 16MiB 1,8V 16-bit",      0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 16MiB 3,3V 16-bit",      0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
-
-       {"NAND 32MiB 1,8V 8-bit",       0x35, 512, 32, 0x4000, 0},
-       {"NAND 32MiB 3,3V 8-bit",       0x75, 512, 32, 0x4000, 0},
-       {"NAND 32MiB 1,8V 16-bit",      0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 32MiB 3,3V 16-bit",      0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
-
-       {"NAND 64MiB 1,8V 8-bit",       0x36, 512, 64, 0x4000, 0},
-       {"NAND 64MiB 3,3V 8-bit",       0x76, 512, 64, 0x4000, 0},
-       {"NAND 64MiB 1,8V 16-bit",      0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 64MiB 3,3V 16-bit",      0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
-
-       {"NAND 128MiB 1,8V 8-bit",      0x78, 512, 128, 0x4000, 0},
-       {"NAND 128MiB 1,8V 8-bit",      0x39, 512, 128, 0x4000, 0},
-       {"NAND 128MiB 3,3V 8-bit",      0x79, 512, 128, 0x4000, 0},
-       {"NAND 128MiB 1,8V 16-bit",     0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 128MiB 1,8V 16-bit",     0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 128MiB 3,3V 16-bit",     0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 128MiB 3,3V 16-bit",     0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-
-       {"NAND 256MiB 3,3V 8-bit",      0x71, 512, 256, 0x4000, 0},
-
-       /* These are the new chips with large page size. The pagesize
-       * and the erasesize is determined from the extended id bytes
-       */
+       {"NAND 1MiB 5V 8-bit",          0x6e, 256, 1, 0x1000, 0},
+       {"NAND 2MiB 5V 8-bit",          0x64, 256, 2, 0x1000, 0},
+       {"NAND 4MiB 5V 8-bit",          0x6b, 512, 4, 0x2000, 0},
+       {"NAND 1MiB 3,3V 8-bit",        0xe8, 256, 1, 0x1000, 0},
+       {"NAND 1MiB 3,3V 8-bit",        0xec, 256, 1, 0x1000, 0},
+       {"NAND 2MiB 3,3V 8-bit",        0xea, 256, 2, 0x1000, 0},
+       {"NAND 4MiB 3,3V 8-bit",        0xd5, 512, 4, 0x2000, 0},
+       {"NAND 4MiB 3,3V 8-bit",        0xe3, 512, 4, 0x2000, 0},
+       {"NAND 4MiB 3,3V 8-bit",        0xe5, 512, 4, 0x2000, 0},
+       {"NAND 8MiB 3,3V 8-bit",        0xd6, 512, 8, 0x2000, 0},
+
+       {"NAND 8MiB 1,8V 8-bit",        0x39, 512, 8, 0x2000, 0},
+       {"NAND 8MiB 3,3V 8-bit",        0xe6, 512, 8, 0x2000, 0},
+       {"NAND 8MiB 1,8V 16-bit",       0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
+       {"NAND 8MiB 3,3V 16-bit",       0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
+
+       {"NAND 16MiB 1,8V 8-bit",       0x33, 512, 16, 0x4000, 0},
+       {"NAND 16MiB 3,3V 8-bit",       0x73, 512, 16, 0x4000, 0},
+       {"NAND 16MiB 1,8V 16-bit",      0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
+       {"NAND 16MiB 3,3V 16-bit",      0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
+
+       {"NAND 32MiB 1,8V 8-bit",       0x35, 512, 32, 0x4000, 0},
+       {"NAND 32MiB 3,3V 8-bit",       0x75, 512, 32, 0x4000, 0},
+       {"NAND 32MiB 1,8V 16-bit",      0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
+       {"NAND 32MiB 3,3V 16-bit",      0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
+
+       {"NAND 64MiB 1,8V 8-bit",       0x36, 512, 64, 0x4000, 0},
+       {"NAND 64MiB 3,3V 8-bit",       0x76, 512, 64, 0x4000, 0},
+       {"NAND 64MiB 1,8V 16-bit",      0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
+       {"NAND 64MiB 3,3V 16-bit",      0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
+
+       {"NAND 128MiB 1,8V 8-bit",      0x78, 512, 128, 0x4000, 0},
+       {"NAND 128MiB 1,8V 8-bit",      0x39, 512, 128, 0x4000, 0},
+       {"NAND 128MiB 3,3V 8-bit",      0x79, 512, 128, 0x4000, 0},
+       {"NAND 128MiB 1,8V 16-bit",     0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+       {"NAND 128MiB 1,8V 16-bit",     0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+       {"NAND 128MiB 3,3V 16-bit",     0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+       {"NAND 128MiB 3,3V 16-bit",     0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+
+       {"NAND 256MiB 3,3V 8-bit",      0x71, 512, 256, 0x4000, 0},
+
+       /*
+        * These are the new chips with large page size. The pagesize and the
+        * erasesize is determined from the extended id bytes
+        */
+#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR)
+#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
+
        /*512 Megabit */
-       {"NAND 64MiB 1,8V 8-bit",       0xA2, 0,  64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 64MiB 3,3V 8-bit",       0xF2, 0,  64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 64MiB 1,8V 16-bit",      0xB2, 0,  64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-       {"NAND 64MiB 3,3V 16-bit",      0xC2, 0,  64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+       {"NAND 64MiB 1,8V 8-bit",       0xA2, 0,  64, 0, LP_OPTIONS},
+       {"NAND 64MiB 3,3V 8-bit",       0xF2, 0,  64, 0, LP_OPTIONS},
+       {"NAND 64MiB 1,8V 16-bit",      0xB2, 0,  64, 0, LP_OPTIONS16},
+       {"NAND 64MiB 3,3V 16-bit",      0xC2, 0,  64, 0, LP_OPTIONS16},
 
        /* 1 Gigabit */
-       {"NAND 128MiB 1,8V 8-bit",      0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 128MiB 3,3V 8-bit",      0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 128MiB 1,8V 16-bit",     0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-       {"NAND 128MiB 3,3V 16-bit",     0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+       {"NAND 128MiB 1,8V 8-bit",      0xA1, 0, 128, 0, LP_OPTIONS},
+       {"NAND 128MiB 3,3V 8-bit",      0xF1, 0, 128, 0, LP_OPTIONS},
+       {"NAND 128MiB 1,8V 16-bit",     0xB1, 0, 128, 0, LP_OPTIONS16},
+       {"NAND 128MiB 3,3V 16-bit",     0xC1, 0, 128, 0, LP_OPTIONS16},
 
        /* 2 Gigabit */
-       {"NAND 256MiB 1,8V 8-bit",      0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 256MiB 3,3V 8-bit",      0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 256MiB 1,8V 16-bit",     0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-       {"NAND 256MiB 3,3V 16-bit",     0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+       {"NAND 256MiB 1,8V 8-bit",      0xAA, 0, 256, 0, LP_OPTIONS},
+       {"NAND 256MiB 3,3V 8-bit",      0xDA, 0, 256, 0, LP_OPTIONS},
+       {"NAND 256MiB 1,8V 16-bit",     0xBA, 0, 256, 0, LP_OPTIONS16},
+       {"NAND 256MiB 3,3V 16-bit",     0xCA, 0, 256, 0, LP_OPTIONS16},
 
        /* 4 Gigabit */
-       {"NAND 512MiB 1,8V 8-bit",      0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 512MiB 3,3V 8-bit",      0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 512MiB 1,8V 16-bit",     0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-       {"NAND 512MiB 3,3V 16-bit",     0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+       {"NAND 512MiB 1,8V 8-bit",      0xAC, 0, 512, 0, LP_OPTIONS},
+       {"NAND 512MiB 3,3V 8-bit",      0xDC, 0, 512, 0, LP_OPTIONS},
+       {"NAND 512MiB 1,8V 16-bit",     0xBC, 0, 512, 0, LP_OPTIONS16},
+       {"NAND 512MiB 3,3V 16-bit",     0xCC, 0, 512, 0, LP_OPTIONS16},
 
        /* 8 Gigabit */
-       {"NAND 1GiB 1,8V 8-bit",        0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 1GiB 3,3V 8-bit",        0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 1GiB 1,8V 16-bit",       0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-       {"NAND 1GiB 3,3V 16-bit",       0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+       {"NAND 1GiB 1,8V 8-bit",        0xA3, 0, 1024, 0, LP_OPTIONS},
+       {"NAND 1GiB 3,3V 8-bit",        0xD3, 0, 1024, 0, LP_OPTIONS},
+       {"NAND 1GiB 1,8V 16-bit",       0xB3, 0, 1024, 0, LP_OPTIONS16},
+       {"NAND 1GiB 3,3V 16-bit",       0xC3, 0, 1024, 0, LP_OPTIONS16},
 
        /* 16 Gigabit */
-       {"NAND 2GiB 1,8V 8-bit",        0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 2GiB 3,3V 8-bit",        0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-       {"NAND 2GiB 1,8V 16-bit",       0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-       {"NAND 2GiB 3,3V 16-bit",       0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-
-       /* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout !
-        * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes
-        * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7
-        * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
-        * There are more speed improvements for reads and writes possible, but not implemented now
+       {"NAND 2GiB 1,8V 8-bit",        0xA5, 0, 2048, 0, LP_OPTIONS},
+       {"NAND 2GiB 3,3V 8-bit",        0xD5, 0, 2048, 0, LP_OPTIONS},
+       {"NAND 2GiB 1,8V 16-bit",       0xB5, 0, 2048, 0, LP_OPTIONS16},
+       {"NAND 2GiB 3,3V 16-bit",       0xC5, 0, 2048, 0, LP_OPTIONS16},
+
+       /*
+        * Renesas AND 1 Gigabit. Those chips do not support extended id and
+        * have a strange page/block layout !  The chosen minimum erasesize is
+        * 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page
+        * planes 1 block = 2 pages, but due to plane arrangement the blocks
+        * 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 Anyway JFFS2 would
+        * increase the eraseblock size so we chose a combined one which can be
+        * erased in one go There are more speed improvements for reads and
+        * writes possible, but not implemented now
         */
-       {"AND 128MiB 3,3V 8-bit",       0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH},
+       {"AND 128MiB 3,3V 8-bit",       0x01, 2048, 128, 0x4000,
+        NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY |
+        BBT_AUTO_REFRESH
+       },
 
        {NULL,}
 };
@@ -125,13 +136,13 @@ struct nand_manufacturers nand_manuf_ids[] = {
        {NAND_MFR_NATIONAL, "National"},
        {NAND_MFR_RENESAS, "Renesas"},
        {NAND_MFR_STMICRO, "ST Micro"},
-        {NAND_MFR_HYNIX, "Hynix"},
+       {NAND_MFR_HYNIX, "Hynix"},
        {0x0, "Unknown"}
 };
 
-EXPORT_SYMBOL (nand_manuf_ids);
-EXPORT_SYMBOL (nand_flash_ids);
+EXPORT_SYMBOL(nand_manuf_ids);
+EXPORT_SYMBOL(nand_flash_ids);
 
-MODULE_LICENSE ("GPL");
-MODULE_AUTHOR ("Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION ("Nand device & manufacturer ID's");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
+MODULE_DESCRIPTION("Nand device & manufacturer IDs");
index a0af92cc7efd787624f6848d93d618eca898ce84..ebd64abc8be809ead329761205798c3a48fb60da 100644 (file)
@@ -369,7 +369,7 @@ init_nandsim(struct mtd_info *mtd)
        /* Initialize the NAND flash parameters */
        ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8;
        ns->geom.totsz    = mtd->size;
-       ns->geom.pgsz     = mtd->oobblock;
+       ns->geom.pgsz     = mtd->writesize;
        ns->geom.oobsz    = mtd->oobsize;
        ns->geom.secsz    = mtd->erasesize;
        ns->geom.pgszoob  = ns->geom.pgsz + ns->geom.oobsz;
@@ -1071,68 +1071,6 @@ switch_state(struct nandsim *ns)
        }
 }
 
-static void
-ns_hwcontrol(struct mtd_info *mtd, int cmd)
-{
-       struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
-
-       switch (cmd) {
-
-       /* set CLE line high */
-       case NAND_CTL_SETCLE:
-               NS_DBG("ns_hwcontrol: start command latch cycles\n");
-               ns->lines.cle  = 1;
-               break;
-
-       /* set CLE line low */
-       case NAND_CTL_CLRCLE:
-               NS_DBG("ns_hwcontrol: stop command latch cycles\n");
-               ns->lines.cle  = 0;
-               break;
-
-       /* set ALE line high */
-       case NAND_CTL_SETALE:
-               NS_DBG("ns_hwcontrol: start address latch cycles\n");
-               ns->lines.ale   = 1;
-               break;
-
-       /* set ALE line low */
-       case NAND_CTL_CLRALE:
-               NS_DBG("ns_hwcontrol: stop address latch cycles\n");
-               ns->lines.ale  = 0;
-               break;
-
-       /* set WP line high */
-       case NAND_CTL_SETWP:
-               NS_DBG("ns_hwcontrol: enable write protection\n");
-               ns->lines.wp = 1;
-               break;
-
-       /* set WP line low */
-       case NAND_CTL_CLRWP:
-               NS_DBG("ns_hwcontrol: disable write protection\n");
-               ns->lines.wp = 0;
-               break;
-
-       /* set CE line low */
-       case NAND_CTL_SETNCE:
-               NS_DBG("ns_hwcontrol: enable chip\n");
-               ns->lines.ce = 1;
-               break;
-
-       /* set CE line high */
-       case NAND_CTL_CLRNCE:
-               NS_DBG("ns_hwcontrol: disable chip\n");
-               ns->lines.ce = 0;
-               break;
-
-       default:
-               NS_ERR("hwcontrol: unknown command\n");
-        }
-
-       return;
-}
-
 static u_char
 ns_nand_read_byte(struct mtd_info *mtd)
 {
@@ -1359,6 +1297,18 @@ ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
        return;
 }
 
+static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
+{
+       struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
+
+       ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
+       ns->lines.ale = bitmask & NAND_ALE ? 1 : 0;
+       ns->lines.ce = bitmask & NAND_NCE ? 1 : 0;
+
+       if (cmd != NAND_CMD_NONE)
+               ns_nand_write_byte(mtd, cmd);
+}
+
 static int
 ns_device_ready(struct mtd_info *mtd)
 {
@@ -1376,17 +1326,6 @@ ns_nand_read_word(struct mtd_info *mtd)
        return chip->read_byte(mtd) | (chip->read_byte(mtd) << 8);
 }
 
-static void
-ns_nand_write_word(struct mtd_info *mtd, uint16_t word)
-{
-       struct nand_chip *chip = (struct nand_chip *)mtd->priv;
-
-       NS_DBG("write_word\n");
-
-       chip->write_byte(mtd, word & 0xFF);
-       chip->write_byte(mtd, word >> 8);
-}
-
 static void
 ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
@@ -1514,16 +1453,14 @@ static int __init ns_init_module(void)
        /*
         * Register simulator's callbacks.
         */
-       chip->hwcontrol  = ns_hwcontrol;
+       chip->cmd_ctrl   = ns_hwcontrol;
        chip->read_byte  = ns_nand_read_byte;
        chip->dev_ready  = ns_device_ready;
-       chip->write_byte = ns_nand_write_byte;
        chip->write_buf  = ns_nand_write_buf;
        chip->read_buf   = ns_nand_read_buf;
        chip->verify_buf = ns_nand_verify_buf;
-       chip->write_word = ns_nand_write_word;
        chip->read_word  = ns_nand_read_word;
-       chip->eccmode    = NAND_ECC_SOFT;
+       chip->ecc.mode   = NAND_ECC_SOFT;
        chip->options   |= NAND_SKIP_BBTSCAN;
 
        /*
@@ -1546,6 +1483,8 @@ static int __init ns_init_module(void)
                chip->options |= NAND_BUSWIDTH_16;
        }
 
+       nsmtd->owner = THIS_MODULE;
+
        if ((retval = nand_scan(nsmtd, 1)) != 0) {
                NS_ERR("can't register NAND Simulator\n");
                if (retval > 0)
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
new file mode 100644 (file)
index 0000000..fe8d385
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ *  drivers/mtd/ndfc.c
+ *
+ *  Overview:
+ *   Platform independend driver for NDFC (NanD Flash Controller)
+ *   integrated into EP440 cores
+ *
+ *  Author: Thomas Gleixner
+ *
+ *  Copyright 2006 IBM
+ *
+ *  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/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/ndfc.h>
+#include <linux/mtd/mtd.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/ibm44x.h>
+
+struct ndfc_nand_mtd {
+       struct mtd_info                 mtd;
+       struct nand_chip                chip;
+       struct platform_nand_chip       *pl_chip;
+};
+
+static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS];
+
+struct ndfc_controller {
+       void __iomem            *ndfcbase;
+       struct nand_hw_control  ndfc_control;
+       atomic_t                childs_active;
+};
+
+static struct ndfc_controller ndfc_ctrl;
+
+static void ndfc_select_chip(struct mtd_info *mtd, int chip)
+{
+       uint32_t ccr;
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       struct nand_chip *nandchip = mtd->priv;
+       struct ndfc_nand_mtd *nandmtd = nandchip->priv;
+       struct platform_nand_chip *pchip = nandmtd->pl_chip;
+
+       ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+       if (chip >= 0) {
+               ccr &= ~NDFC_CCR_BS_MASK;
+               ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
+       } else
+               ccr |= NDFC_CCR_RESET_CE;
+       writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+}
+
+static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+       struct nand_chip *chip = mtd->priv;
+
+       if (cmd == NAND_CMD_NONE)
+               return;
+
+       if (ctrl & NAND_CLE)
+               writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_CMD);
+       else
+               writel(cmd & 0xFF, chip->IO_ADDR_W + NDFC_ALE);
+}
+
+static int ndfc_ready(struct mtd_info *mtd)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+
+       return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
+}
+
+static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+       uint32_t ccr;
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+
+       ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+       ccr |= NDFC_CCR_RESET_ECC;
+       __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+       wmb();
+}
+
+static int ndfc_calculate_ecc(struct mtd_info *mtd,
+                             const u_char *dat, u_char *ecc_code)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       uint32_t ecc;
+       uint8_t *p = (uint8_t *)&ecc;
+
+       wmb();
+       ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC);
+       ecc_code[0] = p[1];
+       ecc_code[1] = p[2];
+       ecc_code[2] = p[3];
+
+       return 0;
+}
+
+/*
+ * Speedups for buffer read/write/verify
+ *
+ * NDFC allows 32bit read/write of data. So we can speed up the buffer
+ * functions. No further checking, as nand_base will always read/write
+ * page aligned.
+ */
+static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       uint32_t *p = (uint32_t *) buf;
+
+       for(;len > 0; len -= 4)
+               *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA);
+}
+
+static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       uint32_t *p = (uint32_t *) buf;
+
+       for(;len > 0; len -= 4)
+               __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA);
+}
+
+static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       uint32_t *p = (uint32_t *) buf;
+
+       for(;len > 0; len -= 4)
+               if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA))
+                       return -EFAULT;
+       return 0;
+}
+
+/*
+ * Initialize chip structure
+ */
+static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
+{
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       struct nand_chip *chip = &mtd->chip;
+
+       chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
+       chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
+       chip->cmd_ctrl = ndfc_hwcontrol;
+       chip->dev_ready = ndfc_ready;
+       chip->select_chip = ndfc_select_chip;
+       chip->chip_delay = 50;
+       chip->priv = mtd;
+       chip->options = mtd->pl_chip->options;
+       chip->controller = &ndfc->ndfc_control;
+       chip->read_buf = ndfc_read_buf;
+       chip->write_buf = ndfc_write_buf;
+       chip->verify_buf = ndfc_verify_buf;
+       chip->ecc.correct = nand_correct_data;
+       chip->ecc.hwctl = ndfc_enable_hwecc;
+       chip->ecc.calculate = ndfc_calculate_ecc;
+       chip->ecc.mode = NAND_ECC_HW;
+       chip->ecc.size = 256;
+       chip->ecc.bytes = 3;
+       chip->ecclayout = mtd->pl_chip->ecclayout;
+       mtd->mtd.priv = chip;
+       mtd->mtd.owner = THIS_MODULE;
+}
+
+static int ndfc_chip_probe(struct platform_device *pdev)
+{
+       struct platform_nand_chip *nc = pdev->dev.platform_data;
+       struct ndfc_chip_settings *settings = nc->priv;
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       struct ndfc_nand_mtd *nandmtd;
+
+       if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS)
+               return -EINVAL;
+
+       /* Set the bank settings */
+       __raw_writel(settings->bank_settings,
+                    ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2));
+
+       nandmtd = &ndfc_mtd[pdev->id];
+       if (nandmtd->pl_chip)
+               return -EBUSY;
+
+       nandmtd->pl_chip = nc;
+       ndfc_chip_init(nandmtd);
+
+       /* Scan for chips */
+       if (nand_scan(&nandmtd->mtd, nc->nr_chips)) {
+               nandmtd->pl_chip = NULL;
+               return -ENODEV;
+       }
+
+#ifdef CONFIG_MTD_PARTITIONS
+       printk("Number of partitions %d\n", nc->nr_partitions);
+       if (nc->nr_partitions) {
+               /* Add the full device, so complete dumps can be made */
+               add_mtd_device(&nandmtd->mtd);
+               add_mtd_partitions(&nandmtd->mtd, nc->partitions,
+                                  nc->nr_partitions);
+
+       } else
+#else
+               add_mtd_device(&nandmtd->mtd);
+#endif
+
+       atomic_inc(&ndfc->childs_active);
+       return 0;
+}
+
+static int ndfc_chip_remove(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static int ndfc_nand_probe(struct platform_device *pdev)
+{
+       struct platform_nand_ctrl *nc = pdev->dev.platform_data;
+       struct ndfc_controller_settings *settings = nc->priv;
+       struct resource *res = pdev->resource;
+       struct ndfc_controller *ndfc = &ndfc_ctrl;
+       unsigned long long phys = settings->ndfc_erpn | res->start;
+
+       ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
+       if (!ndfc->ndfcbase) {
+               printk(KERN_ERR "NDFC: ioremap failed\n");
+               return -EIO;
+       }
+
+       __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR);
+
+       spin_lock_init(&ndfc->ndfc_control.lock);
+       init_waitqueue_head(&ndfc->ndfc_control.wq);
+
+       platform_set_drvdata(pdev, ndfc);
+
+       printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n",
+              __raw_readl(ndfc->ndfcbase + NDFC_REVID));
+
+       return 0;
+}
+
+static int ndfc_nand_remove(struct platform_device *pdev)
+{
+       struct ndfc_controller *ndfc = platform_get_drvdata(pdev);
+
+       if (atomic_read(&ndfc->childs_active))
+               return -EBUSY;
+
+       if (ndfc) {
+               platform_set_drvdata(pdev, NULL);
+               iounmap(ndfc_ctrl.ndfcbase);
+               ndfc_ctrl.ndfcbase = NULL;
+       }
+       return 0;
+}
+
+/* driver device registration */
+
+static struct platform_driver ndfc_chip_driver = {
+       .probe          = ndfc_chip_probe,
+       .remove         = ndfc_chip_remove,
+       .driver         = {
+               .name   = "ndfc-chip",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static struct platform_driver ndfc_nand_driver = {
+       .probe          = ndfc_nand_probe,
+       .remove         = ndfc_nand_remove,
+       .driver         = {
+               .name   = "ndfc-nand",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init ndfc_nand_init(void)
+{
+       int ret;
+
+       spin_lock_init(&ndfc_ctrl.ndfc_control.lock);
+       init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq);
+
+       ret = platform_driver_register(&ndfc_nand_driver);
+       if (!ret)
+               ret = platform_driver_register(&ndfc_chip_driver);
+       return ret;
+}
+
+static void __exit ndfc_nand_exit(void)
+{
+       platform_driver_unregister(&ndfc_chip_driver);
+       platform_driver_unregister(&ndfc_nand_driver);
+}
+
+module_init(ndfc_nand_init);
+module_exit(ndfc_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
+MODULE_DESCRIPTION("Platform driver for NDFC");
index 91a95f34a6eed2c6763ec849cadcb490e6a0e21d..22fa65c12ab9f270a1176616c6874028e06716a9 100644 (file)
 /*
  * MTD structure for PPChameleonEVB board
  */
-static struct mtd_info *ppchameleon_mtd        = NULL;
+static struct mtd_info *ppchameleon_mtd = NULL;
 static struct mtd_info *ppchameleonevb_mtd = NULL;
 
 /*
  * Module stuff
  */
-static unsigned long ppchameleon_fio_pbase     = CFG_NAND0_PADDR;
+static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR;
 static unsigned long ppchameleonevb_fio_pbase = CFG_NAND1_PADDR;
 
 #ifdef MODULE
 module_param(ppchameleon_fio_pbase, ulong, 0);
 module_param(ppchameleonevb_fio_pbase, ulong, 0);
 #else
-__setup("ppchameleon_fio_pbase=",ppchameleon_fio_pbase);
-__setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase);
+__setup("ppchameleon_fio_pbase=", ppchameleon_fio_pbase);
+__setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase);
 #endif
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -80,82 +80,96 @@ __setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase);
  * Define static partitions for flash devices
  */
 static struct mtd_partition partition_info_hi[] = {
-       { name: "PPChameleon HI Nand Flash",
-                 offset: 0,
-                 size: 128*1024*1024 }
+      { .name = "PPChameleon HI Nand Flash",
+       offset = 0,
+       .size = 128 * 1024 * 1024
+      }
 };
 
 static struct mtd_partition partition_info_me[] = {
-       { name: "PPChameleon ME Nand Flash",
-                 offset: 0,
-                 size: 32*1024*1024 }
+      { .name = "PPChameleon ME Nand Flash",
+       .offset = 0,
+       .size = 32 * 1024 * 1024
+      }
 };
 
 static struct mtd_partition partition_info_evb[] = {
-       { name: "PPChameleonEVB Nand Flash",
-                 offset: 0,
-                 size: 32*1024*1024 }
+      { .name = "PPChameleonEVB Nand Flash",
+       .offset = 0,
+       .size = 32 * 1024 * 1024
+      }
 };
 
 #define NUM_PARTITIONS 1
 
-extern int parse_cmdline_partitions(struct mtd_info *master,
-                                   struct mtd_partition **pparts,
-                                   const char *mtd_id);
+extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id);
 #endif
 
-
 /*
  *     hardware specific access to control-lines
  */
-static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd,
+                                 unsigned int ctrl)
 {
-       switch(cmd) {
-
-       case NAND_CTL_SETCLE:
-               MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
-               break;
-       case NAND_CTL_CLRCLE:
-               MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
-               break;
-       case NAND_CTL_SETALE:
-               MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
-               break;
-       case NAND_CTL_CLRALE:
-               MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
-               break;
-       case NAND_CTL_SETNCE:
+       struct nand_chip *chip = mtd->priv;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+#error Missing headerfiles. No way to fix this. -tglx
+               switch (cmd) {
+               case NAND_CTL_SETCLE:
+                       MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
+                       break;
+               case NAND_CTL_CLRCLE:
+                       MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
+                       break;
+               case NAND_CTL_SETALE:
+                       MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
+                       break;
+               case NAND_CTL_CLRALE:
+                       MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
+                       break;
+               case NAND_CTL_SETNCE:
                        MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
-               break;
-       case NAND_CTL_CLRNCE:
+                       break;
+               case NAND_CTL_CLRNCE:
                        MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
-               break;
+                       break;
+               }
        }
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, chip->IO_ADDR_W);
 }
 
-static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd,
+                                    unsigned int ctrl)
 {
-       switch(cmd) {
-
-       case NAND_CTL_SETCLE:
-               MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
-               break;
-       case NAND_CTL_CLRCLE:
-               MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
-               break;
-       case NAND_CTL_SETALE:
-               MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
-               break;
-       case NAND_CTL_CLRALE:
-               MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
-               break;
-       case NAND_CTL_SETNCE:
-               MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
-               break;
-       case NAND_CTL_CLRNCE:
-               MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
-               break;
+       struct nand_chip *chip = mtd->priv;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+#error Missing headerfiles. No way to fix this. -tglx
+               switch (cmd) {
+               case NAND_CTL_SETCLE:
+                       MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
+                       break;
+               case NAND_CTL_CLRCLE:
+                       MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
+                       break;
+               case NAND_CTL_SETALE:
+                       MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
+                       break;
+               case NAND_CTL_CLRALE:
+                       MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
+                       break;
+               case NAND_CTL_SETNCE:
+                       MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
+                       break;
+               case NAND_CTL_CLRNCE:
+                       MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
+                       break;
+               }
        }
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, chip->IO_ADDR_W);
 }
 
 #ifdef USE_READY_BUSY_PIN
@@ -164,15 +178,15 @@ static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
  */
 static int ppchameleon_device_ready(struct mtd_info *minfo)
 {
-       if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_RB_GPIO_PIN)
+       if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_RB_GPIO_PIN)
                return 1;
        return 0;
 }
 
 static int ppchameleonevb_device_ready(struct mtd_info *minfo)
 {
-       if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
-       return 1;
+       if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
+               return 1;
        return 0;
 }
 #endif
@@ -185,7 +199,7 @@ const char *part_probes_evb[] = { "cmdlinepart", NULL };
 /*
  * Main initialization routine
  */
-static int __init ppchameleonevb_init (void)
+static int __init ppchameleonevb_init(void)
 {
        struct nand_chip *this;
        const char *part_type = 0;
@@ -194,13 +208,11 @@ static int __init ppchameleonevb_init (void)
        void __iomem *ppchameleon_fio_base;
        void __iomem *ppchameleonevb_fio_base;
 
-
        /*********************************
        * Processor module NAND (if any) *
        *********************************/
        /* Allocate memory for MTD device structure and private data */
-       ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) +
-                                                     sizeof(struct nand_chip), GFP_KERNEL);
+       ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!ppchameleon_mtd) {
                printk("Unable to allocate PPChameleon NAND MTD device structure.\n");
                return -ENOMEM;
@@ -208,63 +220,65 @@ static int __init ppchameleonevb_init (void)
 
        /* map physical address */
        ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M);
-       if(!ppchameleon_fio_base) {
+       if (!ppchameleon_fio_base) {
                printk("ioremap PPChameleon NAND flash failed\n");
                kfree(ppchameleon_mtd);
                return -EIO;
        }
 
        /* Get pointer to private data */
-       this = (struct nand_chip *) (&ppchameleon_mtd[1]);
+       this = (struct nand_chip *)(&ppchameleon_mtd[1]);
 
        /* Initialize structures */
-       memset((char *) ppchameleon_mtd, 0, sizeof(struct mtd_info));
-       memset((char *) this, 0, sizeof(struct nand_chip));
+       memset(ppchameleon_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
 
        /* Link the private data with the MTD structure */
        ppchameleon_mtd->priv = this;
+       ppchameleon_mtd->owner = THIS_MODULE;
 
-        /* Initialize GPIOs */
+       /* Initialize GPIOs */
        /* Pin mapping for NAND chip */
        /*
-               CE      GPIO_01
-               CLE     GPIO_02
-               ALE     GPIO_03
-               R/B     GPIO_04
-       */
+          CE   GPIO_01
+          CLE  GPIO_02
+          ALE  GPIO_03
+          R/B  GPIO_04
+        */
        /* output select */
-       out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xC0FFFFFF);
+       out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xC0FFFFFF);
        /* three-state select */
-       out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xC0FFFFFF);
+       out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xC0FFFFFF);
        /* enable output driver */
-       out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
+       out_be32((volatile unsigned *)GPIO0_TCR,
+                in_be32((volatile unsigned *)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
 #ifdef USE_READY_BUSY_PIN
        /* three-state select */
-       out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFF3FFFFF);
+       out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFF3FFFFF);
        /* high-impedecence */
-       out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
+       out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
        /* input select */
-       out_be32((volatile unsigned*)GPIO0_ISR1H, (in_be32((volatile unsigned*)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
+       out_be32((volatile unsigned *)GPIO0_ISR1H,
+                (in_be32((volatile unsigned *)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
 #endif
 
        /* insert callbacks */
        this->IO_ADDR_R = ppchameleon_fio_base;
        this->IO_ADDR_W = ppchameleon_fio_base;
-       this->hwcontrol = ppchameleon_hwcontrol;
+       this->cmd_ctrl = ppchameleon_hwcontrol;
 #ifdef USE_READY_BUSY_PIN
        this->dev_ready = ppchameleon_device_ready;
 #endif
        this->chip_delay = NAND_BIG_DELAY_US;
        /* ECC mode */
-       this->eccmode = NAND_ECC_SOFT;
+       this->ecc.mode = NAND_ECC_SOFT;
 
        /* Scan to find existence of the device (it could not be mounted) */
-       if (nand_scan (ppchameleon_mtd, 1)) {
+       if (nand_scan(ppchameleon_mtd, 1)) {
                iounmap((void *)ppchameleon_fio_base);
-               kfree (ppchameleon_mtd);
+               kfree(ppchameleon_mtd);
                goto nand_evb_init;
        }
-
 #ifndef USE_READY_BUSY_PIN
        /* Adjust delay if necessary */
        if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
@@ -275,12 +289,11 @@ static int __init ppchameleonevb_init (void)
        ppchameleon_mtd->name = "ppchameleon-nand";
        mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0);
        if (mtd_parts_nb > 0)
-         part_type = "command line";
+               part_type = "command line";
        else
-         mtd_parts_nb = 0;
+               mtd_parts_nb = 0;
 #endif
-       if (mtd_parts_nb == 0)
-       {
+       if (mtd_parts_nb == 0) {
                if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
                        mtd_parts = partition_info_me;
                else
@@ -293,13 +306,12 @@ static int __init ppchameleonevb_init (void)
        printk(KERN_NOTICE "Using %s partition definition\n", part_type);
        add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
 
-nand_evb_init:
+ nand_evb_init:
        /****************************
        * EVB NAND (always present) *
        ****************************/
        /* Allocate memory for MTD device structure and private data */
-       ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) +
-                                                        sizeof(struct nand_chip), GFP_KERNEL);
+       ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!ppchameleonevb_mtd) {
                printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n");
                return -ENOMEM;
@@ -307,77 +319,76 @@ nand_evb_init:
 
        /* map physical address */
        ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M);
-       if(!ppchameleonevb_fio_base) {
+       if (!ppchameleonevb_fio_base) {
                printk("ioremap PPChameleonEVB NAND flash failed\n");
                kfree(ppchameleonevb_mtd);
                return -EIO;
        }
 
        /* Get pointer to private data */
-       this = (struct nand_chip *) (&ppchameleonevb_mtd[1]);
+       this = (struct nand_chip *)(&ppchameleonevb_mtd[1]);
 
        /* Initialize structures */
-       memset((char *) ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
-       memset((char *) this, 0, sizeof(struct nand_chip));
+       memset(ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
 
        /* Link the private data with the MTD structure */
        ppchameleonevb_mtd->priv = this;
 
-        /* Initialize GPIOs */
+       /* Initialize GPIOs */
        /* Pin mapping for NAND chip */
        /*
-               CE      GPIO_14
-               CLE     GPIO_15
-               ALE     GPIO_16
-               R/B     GPIO_31
-       */
+          CE   GPIO_14
+          CLE  GPIO_15
+          ALE  GPIO_16
+          R/B  GPIO_31
+        */
        /* output select */
-       out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xFFFFFFF0);
-       out_be32((volatile unsigned*)GPIO0_OSRL, in_be32((volatile unsigned*)GPIO0_OSRL) & 0x3FFFFFFF);
+       out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xFFFFFFF0);
+       out_be32((volatile unsigned *)GPIO0_OSRL, in_be32((volatile unsigned *)GPIO0_OSRL) & 0x3FFFFFFF);
        /* three-state select */
-       out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0);
-       out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF);
+       out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFFFFFFF0);
+       out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0x3FFFFFFF);
        /* enable output driver */
-       out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
+       out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
                 NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN);
 #ifdef USE_READY_BUSY_PIN
        /* three-state select */
-       out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC);
+       out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0xFFFFFFFC);
        /* high-impedecence */
-       out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
+       out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
        /* input select */
-       out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
+       out_be32((volatile unsigned *)GPIO0_ISR1L,
+                (in_be32((volatile unsigned *)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
 #endif
 
        /* insert callbacks */
        this->IO_ADDR_R = ppchameleonevb_fio_base;
        this->IO_ADDR_W = ppchameleonevb_fio_base;
-       this->hwcontrol = ppchameleonevb_hwcontrol;
+       this->cmd_ctrl = ppchameleonevb_hwcontrol;
 #ifdef USE_READY_BUSY_PIN
        this->dev_ready = ppchameleonevb_device_ready;
 #endif
        this->chip_delay = NAND_SMALL_DELAY_US;
 
        /* ECC mode */
-       this->eccmode = NAND_ECC_SOFT;
+       this->ecc.mode = NAND_ECC_SOFT;
 
        /* Scan to find existence of the device */
-       if (nand_scan (ppchameleonevb_mtd, 1)) {
+       if (nand_scan(ppchameleonevb_mtd, 1)) {
                iounmap((void *)ppchameleonevb_fio_base);
-               kfree (ppchameleonevb_mtd);
+               kfree(ppchameleonevb_mtd);
                return -ENXIO;
        }
-
 #ifdef CONFIG_MTD_PARTITIONS
        ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
        mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0);
        if (mtd_parts_nb > 0)
-         part_type = "command line";
+               part_type = "command line";
        else
-         mtd_parts_nb = 0;
+               mtd_parts_nb = 0;
 #endif
-       if (mtd_parts_nb == 0)
-       {
+       if (mtd_parts_nb == 0) {
                mtd_parts = partition_info_evb;
                mtd_parts_nb = NUM_PARTITIONS;
                part_type = "static";
@@ -390,18 +401,19 @@ nand_evb_init:
        /* Return happy */
        return 0;
 }
+
 module_init(ppchameleonevb_init);
 
 /*
  * Clean up routine
  */
-static void __exit ppchameleonevb_cleanup (void)
+static void __exit ppchameleonevb_cleanup(void)
 {
        struct nand_chip *this;
 
        /* Release resources, unregister device(s) */
-       nand_release (ppchameleon_mtd);
-       nand_release (ppchameleonevb_mtd);
+       nand_release(ppchameleon_mtd);
+       nand_release(ppchameleonevb_mtd);
 
        /* Release iomaps */
        this = (struct nand_chip *) &ppchameleon_mtd[1];
index 4129c03dfd9090b4962212e5a03207f598da1f8e..f8c49645324d7b5e458b08824beaabb535e42cd3 100644 (file)
@@ -97,12 +97,12 @@ static struct mtd_info *rtc_from4_mtd = NULL;
 static void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE);
 
 static const struct mtd_partition partition_info[] = {
-        {
-                .name   = "Renesas flash partition 1",
-                .offset = 0,
-                .size   = MTDPART_SIZ_FULL
-        },
+       {
+        .name = "Renesas flash partition 1",
+        .offset = 0,
+        .size = MTDPART_SIZ_FULL},
 };
+
 #define NUM_PARTITIONS 1
 
 /*
@@ -111,8 +111,8 @@ static const struct mtd_partition partition_info[] = {
  *             NAND_BBT_CREATE and/or NAND_BBT_WRITE
  *
  */
-static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
-static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
+static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
 
 static struct nand_bbt_descr rtc_from4_bbt_main_descr = {
        .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
@@ -134,8 +134,6 @@ static struct nand_bbt_descr rtc_from4_bbt_mirror_descr = {
        .pattern = mirror_pattern
 };
 
-
-
 #ifdef RTC_FROM4_HWECC
 
 /* the Reed Solomon control structure */
@@ -144,15 +142,14 @@ static struct rs_control *rs_decoder;
 /*
  *      hardware specific Out Of Band information
  */
-static struct nand_oobinfo rtc_from4_nand_oobinfo = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout rtc_from4_nand_oobinfo = {
        .eccbytes = 32,
        .eccpos = {
-                0,  1,  2,  3,  4,  5,  6,  7,
-                8,  9, 10, 11, 12, 13, 14, 15,
-               16, 17, 18, 19, 20, 21, 22, 23,
-               24, 25, 26, 27, 28, 29, 30, 31},
-       .oobfree = { {32, 32} }
+                  0, 1, 2, 3, 4, 5, 6, 7,
+                  8, 9, 10, 11, 12, 13, 14, 15,
+                  16, 17, 18, 19, 20, 21, 22, 23,
+                  24, 25, 26, 27, 28, 29, 30, 31},
+       .oobfree = {{32, 32}}
 };
 
 /* Aargh. I missed the reversed bit order, when I
@@ -162,44 +159,42 @@ static struct nand_oobinfo rtc_from4_nand_oobinfo = {
  * of the ecc byte which we get from the FPGA
  */
 static uint8_t revbits[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,
+       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,
 };
 
 #endif
 
-
-
 /*
  * rtc_from4_hwcontrol - hardware specific access to control-lines
  * @mtd:       MTD device structure
@@ -212,35 +207,20 @@ static uint8_t revbits[256] = {
  * Address lines (A24-A22), so no action is required here.
  *
  */
-static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
+static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd,
+                               unsigned int ctrl)
 {
-       struct nand_chip* this = (struct nand_chip *) (mtd->priv);
-
-       switch(cmd) {
+       struct nand_chip *chip = (mtd->priv);
 
-       case NAND_CTL_SETCLE:
-               this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE);
-               break;
-       case NAND_CTL_CLRCLE:
-               this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE);
-               break;
-
-       case NAND_CTL_SETALE:
-               this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE);
-               break;
-       case NAND_CTL_CLRALE:
-               this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE);
-               break;
+       if (cmd == NAND_CMD_NONE)
+               return;
 
-       case NAND_CTL_SETNCE:
-               break;
-       case NAND_CTL_CLRNCE:
-               break;
-
-       }
+       if (ctrl & NAND_CLE)
+               writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_CLE);
+       else
+               writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_ALE);
 }
 
-
 /*
  * rtc_from4_nand_select_chip - hardware specific chip select
  * @mtd:       MTD device structure
@@ -252,26 +232,25 @@ static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
  */
 static void rtc_from4_nand_select_chip(struct mtd_info *mtd, int chip)
 {
-        struct nand_chip *this = mtd->priv;
+       struct nand_chip *this = mtd->priv;
 
        this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R & ~RTC_FROM4_NAND_ADDR_MASK);
        this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_NAND_ADDR_MASK);
 
-        switch(chip) {
+       switch (chip) {
 
-        case 0:                /* select slot 3 chip */
+       case 0:         /* select slot 3 chip */
                this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT3);
                this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT3);
-                break;
-        case 1:                /* select slot 4 chip */
+               break;
+       case 1:         /* select slot 4 chip */
                this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT4);
                this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT4);
-                break;
+               break;
 
-        }
+       }
 }
 
-
 /*
  * rtc_from4_nand_device_ready - hardware specific ready/busy check
  * @mtd:       MTD device structure
@@ -290,7 +269,6 @@ static int rtc_from4_nand_device_ready(struct mtd_info *mtd)
 
 }
 
-
 /*
  * deplete - code to perform device recovery in case there was a power loss
  * @mtd:       MTD device structure
@@ -306,24 +284,23 @@ static int rtc_from4_nand_device_ready(struct mtd_info *mtd)
  */
 static void deplete(struct mtd_info *mtd, int chip)
 {
-        struct nand_chip *this = mtd->priv;
+       struct nand_chip *this = mtd->priv;
 
-        /* wait until device is ready */
-        while (!this->dev_ready(mtd));
+       /* wait until device is ready */
+       while (!this->dev_ready(mtd)) ;
 
        this->select_chip(mtd, chip);
 
        /* Send the commands for device recovery, phase 1 */
-       this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000);
-       this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1);
+       this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000);
+       this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1);
 
        /* Send the commands for device recovery, phase 2 */
-       this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004);
-       this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1);
+       this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004);
+       this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1);
 
 }
 
-
 #ifdef RTC_FROM4_HWECC
 /*
  * rtc_from4_enable_hwecc - hardware specific hardware ECC enable function
@@ -335,39 +312,35 @@ static void deplete(struct mtd_info *mtd, int chip)
  */
 static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode)
 {
-       volatile unsigned short * rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL);
+       volatile unsigned short *rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL);
        unsigned short status;
 
        switch (mode) {
-           case NAND_ECC_READ :
-               status =  RTC_FROM4_RS_ECC_CTL_CLR
-                       | RTC_FROM4_RS_ECC_CTL_FD_E;
+       case NAND_ECC_READ:
+               status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_FD_E;
 
                *rs_ecc_ctl = status;
                break;
 
-           case NAND_ECC_READSYN :
-               status =  0x00;
+       case NAND_ECC_READSYN:
+               status = 0x00;
 
                *rs_ecc_ctl = status;
                break;
 
-           case NAND_ECC_WRITE :
-               status =  RTC_FROM4_RS_ECC_CTL_CLR
-                       | RTC_FROM4_RS_ECC_CTL_GEN
-                       | RTC_FROM4_RS_ECC_CTL_FD_E;
+       case NAND_ECC_WRITE:
+               status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_GEN | RTC_FROM4_RS_ECC_CTL_FD_E;
 
                *rs_ecc_ctl = status;
                break;
 
-           default:
+       default:
                BUG();
                break;
        }
 
 }
 
-
 /*
  * rtc_from4_calculate_ecc - hardware specific code to read ECC code
  * @mtd:       MTD device structure
@@ -383,7 +356,7 @@ static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode)
  */
 static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
 {
-       volatile unsigned short * rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN);
+       volatile unsigned short *rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN);
        unsigned short value;
        int i;
 
@@ -395,7 +368,6 @@ static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_c
        ecc_code[7] |= 0x0f;    /* set the last four bits (not used) */
 }
 
-
 /*
  * rtc_from4_correct_data - hardware specific code to correct data using ECC code
  * @mtd:       MTD device structure
@@ -414,7 +386,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
        unsigned short status;
        uint16_t par[6], syn[6];
        uint8_t ecc[8];
-        volatile unsigned short *rs_ecc;
+       volatile unsigned short *rs_ecc;
 
        status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CHK));
 
@@ -424,23 +396,18 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
 
        /* Read the syndrom pattern from the FPGA and correct the bitorder */
        rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
-        for (i = 0; i < 8; i++) {
-                ecc[i] = revbits[(*rs_ecc) & 0xFF];
-                rs_ecc++;
-        }
+       for (i = 0; i < 8; i++) {
+               ecc[i] = revbits[(*rs_ecc) & 0xFF];
+               rs_ecc++;
+       }
 
        /* convert into 6 10bit syndrome fields */
-       par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) |
-                                     (((uint16_t)ecc[1] << 8) & 0x300)];
-       par[4] = rs_decoder->index_of[(((uint16_t)ecc[1] >> 2) & 0x03f) |
-                                     (((uint16_t)ecc[2] << 6) & 0x3c0)];
-       par[3] = rs_decoder->index_of[(((uint16_t)ecc[2] >> 4) & 0x00f) |
-                                     (((uint16_t)ecc[3] << 4) & 0x3f0)];
-       par[2] = rs_decoder->index_of[(((uint16_t)ecc[3] >> 6) & 0x003) |
-                                     (((uint16_t)ecc[4] << 2) & 0x3fc)];
-       par[1] = rs_decoder->index_of[(((uint16_t)ecc[5] >> 0) & 0x0ff) |
-                                     (((uint16_t)ecc[6] << 8) & 0x300)];
-       par[0] = (((uint16_t)ecc[6] >> 2) & 0x03f) | (((uint16_t)ecc[7] << 6) & 0x3c0);
+       par[5] = rs_decoder->index_of[(((uint16_t) ecc[0] >> 0) & 0x0ff) | (((uint16_t) ecc[1] << 8) & 0x300)];
+       par[4] = rs_decoder->index_of[(((uint16_t) ecc[1] >> 2) & 0x03f) | (((uint16_t) ecc[2] << 6) & 0x3c0)];
+       par[3] = rs_decoder->index_of[(((uint16_t) ecc[2] >> 4) & 0x00f) | (((uint16_t) ecc[3] << 4) & 0x3f0)];
+       par[2] = rs_decoder->index_of[(((uint16_t) ecc[3] >> 6) & 0x003) | (((uint16_t) ecc[4] << 2) & 0x3fc)];
+       par[1] = rs_decoder->index_of[(((uint16_t) ecc[5] >> 0) & 0x0ff) | (((uint16_t) ecc[6] << 8) & 0x300)];
+       par[0] = (((uint16_t) ecc[6] >> 2) & 0x03f) | (((uint16_t) ecc[7] << 6) & 0x3c0);
 
        /* Convert to computable syndrome */
        for (i = 0; i < 6; i++) {
@@ -453,16 +420,14 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
                syn[i] = rs_decoder->index_of[syn[i]];
        }
 
-       /* Let the library code do its magic.*/
-       res = decode_rs8(rs_decoder, (uint8_t *)buf, par, 512, syn, 0, NULL, 0xff, NULL);
+       /* Let the library code do its magic. */
+       res = decode_rs8(rs_decoder, (uint8_t *) buf, par, 512, syn, 0, NULL, 0xff, NULL);
        if (res > 0) {
-               DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: "
-                       "ECC corrected %d errors on read\n", res);
+               DEBUG(MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res);
        }
        return res;
 }
 
-
 /**
  * rtc_from4_errstat - perform additional error status checks
  * @mtd:       MTD device structure
@@ -478,54 +443,66 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
  * note: see pages 34..37 of data sheet for details.
  *
  */
-static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page)
+static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
+                            int state, int status, int page)
 {
-       int     er_stat=0;
-       int     rtn, retlen;
-       size_t  len;
+       int er_stat = 0;
+       int rtn, retlen;
+       size_t len;
        uint8_t *buf;
-       int     i;
-
-       this->cmdfunc (mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
-
-        if (state == FL_ERASING) {
-               for (i=0; i<4; i++) {
-                       if (status & 1<<(i+1)) {
-                               this->cmdfunc (mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1);
-                               rtn = this->read_byte(mtd);
-                               this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);
-                               if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
-                                       er_stat |= 1<<(i+1);    /* err_ecc_not_avail */
-                               }
-                       }
+       int i;
+
+       this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
+
+       if (state == FL_ERASING) {
+
+               for (i = 0; i < 4; i++) {
+                       if (!(status & 1 << (i + 1)))
+                               continue;
+                       this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1),
+                                     -1, -1);
+                       rtn = this->read_byte(mtd);
+                       this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
+
+                       /* err_ecc_not_avail */
+                       if (!(rtn & ERR_STAT_ECC_AVAILABLE))
+                               er_stat |= 1 << (i + 1);
                }
+
        } else if (state == FL_WRITING) {
+
+               unsigned long corrected = mtd->ecc_stats.corrected;
+
                /* single bank write logic */
-               this->cmdfunc (mtd, NAND_CMD_STATUS_ERROR, -1, -1);
+               this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1);
                rtn = this->read_byte(mtd);
-               this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);
+               this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
+
                if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
-                       er_stat |= 1<<1;        /* err_ecc_not_avail */
-               } else {
-                       len = mtd->oobblock;
-                       buf = kmalloc (len, GFP_KERNEL);
-                       if (!buf) {
-                               printk (KERN_ERR "rtc_from4_errstat: Out of memory!\n");
-                               er_stat = 1;                    /* if we can't check, assume failed */
-                       } else {
-                               /* recovery read */
-                               /* page read */
-                               rtn = nand_do_read_ecc (mtd, page, len, &retlen, buf, NULL, this->autooob, 1);
-                               if (rtn) {      /* if read failed or > 1-bit error corrected */
-                                       er_stat |= 1<<1;        /* ECC read failed */
-                               }
-                               kfree(buf);
-                       }
+                       /* err_ecc_not_avail */
+                       er_stat |= 1 << 1;
+                       goto out;
+               }
+
+               len = mtd->writesize;
+               buf = kmalloc(len, GFP_KERNEL);
+               if (!buf) {
+                       printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
+                       er_stat = 1;
+                       goto out;
                }
+
+               /* recovery read */
+               rtn = nand_do_read(mtd, page, len, &retlen, buf);
+
+               /* if read failed or > 1-bit error corrected */
+               if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) {
+                       er_stat |= 1 << 1;
+               kfree(buf);
        }
 
        rtn = status;
-       if (er_stat == 0) {                             /* if ECC is available   */
+       if (er_stat == 0) {     /* if ECC is available   */
                rtn = (status & ~NAND_STATUS_FAIL);     /*   clear the error bit */
        }
 
@@ -533,33 +510,32 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int s
 }
 #endif
 
-
 /*
  * Main initialization routine
  */
-int __init rtc_from4_init (void)
+static int __init rtc_from4_init(void)
 {
        struct nand_chip *this;
        unsigned short bcr1, bcr2, wcr2;
        int i;
 
        /* Allocate memory for MTD device structure and private data */
-       rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip),
-                               GFP_KERNEL);
+       rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!rtc_from4_mtd) {
-               printk ("Unable to allocate Renesas NAND MTD device structure.\n");
+               printk("Unable to allocate Renesas NAND MTD device structure.\n");
                return -ENOMEM;
        }
 
        /* Get pointer to private data */
-       this = (struct nand_chip *) (&rtc_from4_mtd[1]);
+       this = (struct nand_chip *)(&rtc_from4_mtd[1]);
 
        /* Initialize structures */
-       memset((char *) rtc_from4_mtd, 0, sizeof(struct mtd_info));
-       memset((char *) this, 0, sizeof(struct nand_chip));
+       memset(rtc_from4_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
 
        /* Link the private data with the MTD structure */
        rtc_from4_mtd->priv = this;
+       rtc_from4_mtd->owner = THIS_MODULE;
 
        /* set area 5 as PCMCIA mode to clear the spec of tDH(Data hold time;9ns min) */
        bcr1 = *SH77X9_BCR1 & ~0x0002;
@@ -580,9 +556,9 @@ int __init rtc_from4_init (void)
        this->IO_ADDR_R = rtc_from4_fio_base;
        this->IO_ADDR_W = rtc_from4_fio_base;
        /* Set address of hardware control function */
-       this->hwcontrol = rtc_from4_hwcontrol;
+       this->cmd_ctrl = rtc_from4_hwcontrol;
        /* Set address of chip select function */
-        this->select_chip = rtc_from4_nand_select_chip;
+       this->select_chip = rtc_from4_nand_select_chip;
        /* command delay time (in us) */
        this->chip_delay = 100;
        /* return the status of the Ready/Busy line */
@@ -591,19 +567,20 @@ int __init rtc_from4_init (void)
 #ifdef RTC_FROM4_HWECC
        printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n");
 
-        this->eccmode = NAND_ECC_HW8_512;
-       this->options |= NAND_HWECC_SYNDROME;
+       this->ecc.mode = NAND_ECC_HW_SYNDROME;
+       this->ecc.size = 512;
+       this->ecc.bytes = 8;
        /* return the status of extra status and ECC checks */
        this->errstat = rtc_from4_errstat;
        /* set the nand_oobinfo to support FPGA H/W error detection */
-       this->autooob = &rtc_from4_nand_oobinfo;
-       this->enable_hwecc = rtc_from4_enable_hwecc;
-       this->calculate_ecc = rtc_from4_calculate_ecc;
-       this->correct_data = rtc_from4_correct_data;
+       this->ecc.layout = &rtc_from4_nand_oobinfo;
+       this->ecc.hwctl = rtc_from4_enable_hwecc;
+       this->ecc.calculate = rtc_from4_calculate_ecc;
+       this->ecc.correct = rtc_from4_correct_data;
 #else
        printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
 
-       this->eccmode = NAND_ECC_SOFT;
+       this->ecc.mode = NAND_ECC_SOFT;
 #endif
 
        /* set the bad block tables to support debugging */
@@ -617,7 +594,7 @@ int __init rtc_from4_init (void)
        }
 
        /* Perform 'device recovery' for each chip in case there was a power loss. */
-       for (i=0; i < this->numchips; i++) {
+       for (i = 0; i < this->numchips; i++) {
                deplete(rtc_from4_mtd, i);
        }
 
@@ -643,7 +620,7 @@ int __init rtc_from4_init (void)
         */
        rs_decoder = init_rs(10, 0x409, 0, 1, 6);
        if (!rs_decoder) {
-               printk (KERN_ERR "Could not create a RS decoder\n");
+               printk(KERN_ERR "Could not create a RS decoder\n");
                nand_release(rtc_from4_mtd);
                kfree(rtc_from4_mtd);
                return -ENOMEM;
@@ -652,20 +629,19 @@ int __init rtc_from4_init (void)
        /* Return happy */
        return 0;
 }
-module_init(rtc_from4_init);
 
+module_init(rtc_from4_init);
 
 /*
  * Clean up routine
  */
-#ifdef MODULE
-static void __exit rtc_from4_cleanup (void)
+static void __exit rtc_from4_cleanup(void)
 {
        /* Release resource, unregister partitions */
        nand_release(rtc_from4_mtd);
 
        /* Free the MTD device structure */
-       kfree (rtc_from4_mtd);
+       kfree(rtc_from4_mtd);
 
 #ifdef RTC_FROM4_HWECC
        /* Free the reed solomon resources */
@@ -674,10 +650,9 @@ static void __exit rtc_from4_cleanup (void)
        }
 #endif
 }
+
 module_exit(rtc_from4_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("d.marlin <dmarlin@redhat.com");
 MODULE_DESCRIPTION("Board-specific glue layer for AG-AND flash on Renesas FROM_BOARD4");
-
index 5b55599739f3d3557e84bef104c209f3fc35ef8a..2c262fe03d8af60a93bd6cda681246bf4b7d9ce6 100644 (file)
@@ -18,8 +18,9 @@
  *     20-Jun-2005  BJD  Updated s3c2440 support, fixed timing bug
  *     08-Jul-2005  BJD  Fix OOPS when no platform data supplied
  *     20-Oct-2005  BJD  Fix timing calculation bug
+ *     14-Jan-2006  BJD  Allow clock to be stopped when idle
  *
- * $Id: s3c2410.c,v 1.20 2005/11/07 11:14:31 gleixner Exp $
+ * $Id: s3c2410.c,v 1.23 2006/04/01 18:06:29 bjd Exp $
  *
  * 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
@@ -36,9 +37,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-#include <config/mtd/nand/s3c2410/hwecc.h>
-#include <config/mtd/nand/s3c2410/debug.h>
-
 #ifdef CONFIG_MTD_NAND_S3C2410_DEBUG
 #define DEBUG
 #endif
@@ -73,14 +71,20 @@ static int hardware_ecc = 1;
 static int hardware_ecc = 0;
 #endif
 
+#ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
+static int clock_stop = 1;
+#else
+static const int clock_stop = 0;
+#endif
+
+
 /* new oob placement block for use with hardware ecc generation
  */
 
-static struct nand_oobinfo nand_hw_eccoob = {
-       .useecc         = MTD_NANDECC_AUTOPLACE,
-       .eccbytes       = 3,
-       .eccpos         = {0, 1, 2 },
-       .oobfree        = { {8, 8} }
+static struct nand_ecclayout nand_hw_eccoob = {
+       .eccbytes = 3,
+       .eccpos = {0, 1, 2},
+       .oobfree = {{8, 8}}
 };
 
 /* controller and mtd information */
@@ -135,6 +139,11 @@ static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
        return dev->dev.platform_data;
 }
 
+static inline int allow_clk_stop(struct s3c2410_nand_info *info)
+{
+       return clock_stop;
+}
+
 /* timing calculations */
 
 #define NS_IN_KHZ 1000000
@@ -149,8 +158,7 @@ static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max)
        pr_debug("result %d from %ld, %d\n", result, clk, wanted);
 
        if (result > max) {
-               printk("%d ns is too big for current clock rate %ld\n",
-                      wanted, clk);
+               printk("%d ns is too big for current clock rate %ld\n", wanted, clk);
                return -1;
        }
 
@@ -164,8 +172,7 @@ static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max)
 
 /* controller setup */
 
-static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
-                              struct platform_device *pdev)
+static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, struct platform_device *pdev)
 {
        struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
        unsigned long clkrate = clk_get_rate(info->clk);
@@ -177,7 +184,7 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
        clkrate /= 1000;        /* turn clock into kHz for ease of use */
 
        if (plat != NULL) {
-               tacls  = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4);
+               tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4);
                twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8);
                twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8);
        } else {
@@ -193,19 +200,22 @@ static int s3c2410_nand_inithw(struct s3c2410_nand_info *info,
        }
 
        printk(KERN_INFO PFX "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
-              tacls, to_ns(tacls, clkrate),
-              twrph0, to_ns(twrph0, clkrate),
-              twrph1, to_ns(twrph1, clkrate));
+              tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));
 
        if (!info->is_s3c2440) {
-               cfg  = S3C2410_NFCONF_EN;
-               cfg |= S3C2410_NFCONF_TACLS(tacls-1);
-               cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1);
-               cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1);
+               cfg = S3C2410_NFCONF_EN;
+               cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
+               cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
+               cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
        } else {
-               cfg   = S3C2440_NFCONF_TACLS(tacls-1);
-               cfg  |= S3C2440_NFCONF_TWRPH0(twrph0-1);
-               cfg  |= S3C2440_NFCONF_TWRPH1(twrph1-1);
+               cfg = S3C2440_NFCONF_TACLS(tacls - 1);
+               cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
+               cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
+
+               /* enable the controller and de-assert nFCE */
+
+               writel(S3C2440_NFCONT_ENABLE | S3C2440_NFCONT_ENABLE,
+                      info->regs + S3C2440_NFCONT);
        }
 
        pr_debug(PFX "NF_CONF is 0x%lx\n", cfg);
@@ -229,7 +239,10 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
        info = nmtd->info;
 
        bit = (info->is_s3c2440) ? S3C2440_NFCONT_nFCE : S3C2410_NFCONF_nFCE;
-       reg = info->regs+((info->is_s3c2440) ? S3C2440_NFCONT:S3C2410_NFCONF);
+       reg = info->regs + ((info->is_s3c2440) ? S3C2440_NFCONT : S3C2410_NFCONF);
+
+       if (chip != -1 && allow_clk_stop(info))
+               clk_enable(info->clk);
 
        cur = readl(reg);
 
@@ -243,77 +256,51 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
 
                if (info->platform != NULL) {
                        if (info->platform->select_chip != NULL)
-                               (info->platform->select_chip)(nmtd->set, chip);
+                               (info->platform->select_chip) (nmtd->set, chip);
                }
 
                cur &= ~bit;
        }
 
        writel(cur, reg);
+
+       if (chip == -1 && allow_clk_stop(info))
+               clk_disable(info->clk);
 }
 
-/* command and control functions
- *
- * Note, these all use tglx's method of changing the IO_ADDR_W field
- * to make the code simpler, and use the nand layer's code to issue the
- * command and address sequences via the proper IO ports.
+/* s3c2410_nand_hwcontrol
  *
+ * Issue command and address cycles to the chip
 */
 
-static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+                                  unsigned int ctrl)
 {
        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-       struct nand_chip *chip = mtd->priv;
-
-       switch (cmd) {
-       case NAND_CTL_SETNCE:
-       case NAND_CTL_CLRNCE:
-               printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__);
-               break;
-
-       case NAND_CTL_SETCLE:
-               chip->IO_ADDR_W = info->regs + S3C2410_NFCMD;
-               break;
-
-       case NAND_CTL_SETALE:
-               chip->IO_ADDR_W = info->regs + S3C2410_NFADDR;
-               break;
-
-               /* NAND_CTL_CLRCLE: */
-               /* NAND_CTL_CLRALE: */
-       default:
-               chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;
-               break;
-       }
+       
+       if (cmd == NAND_CMD_NONE)
+               return;
+
+       if (ctrl & NAND_CLE)
+               writeb(cmd, info->regs + S3C2410_NFCMD);
+       else
+               writeb(cmd, info->regs + S3C2410_NFADDR);
 }
 
 /* command and control functions */
 
-static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+                                  unsigned int ctrl)
 {
        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-       struct nand_chip *chip = mtd->priv;
-
-       switch (cmd) {
-       case NAND_CTL_SETNCE:
-       case NAND_CTL_CLRNCE:
-               printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__);
-               break;
-
-       case NAND_CTL_SETCLE:
-               chip->IO_ADDR_W = info->regs + S3C2440_NFCMD;
-               break;
-
-       case NAND_CTL_SETALE:
-               chip->IO_ADDR_W = info->regs + S3C2440_NFADDR;
-               break;
-
-               /* NAND_CTL_CLRCLE: */
-               /* NAND_CTL_CLRALE: */
-       default:
-               chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;
-               break;
-       }
+
+       if (cmd == NAND_CMD_NONE)
+               return;
+
+       if (ctrl & NAND_CLE)
+               writeb(cmd, info->regs + S3C2440_NFCMD);
+       else
+               writeb(cmd, info->regs + S3C2440_NFADDR);
 }
 
 /* s3c2410_nand_devready()
@@ -330,22 +317,16 @@ static int s3c2410_nand_devready(struct mtd_info *mtd)
        return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
 }
 
-
 /* ECC handling functions */
 
-static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
-                                    u_char *read_ecc, u_char *calc_ecc)
+static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
 {
-       pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n",
-                mtd, dat, read_ecc, calc_ecc);
+       pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc);
 
        pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n",
-                read_ecc[0], read_ecc[1], read_ecc[2],
-                calc_ecc[0], calc_ecc[1], calc_ecc[2]);
+                read_ecc[0], read_ecc[1], read_ecc[2], calc_ecc[0], calc_ecc[1], calc_ecc[2]);
 
-       if (read_ecc[0] == calc_ecc[0] &&
-           read_ecc[1] == calc_ecc[1] &&
-           read_ecc[2] == calc_ecc[2])
+       if (read_ecc[0] == calc_ecc[0] && read_ecc[1] == calc_ecc[1] && read_ecc[2] == calc_ecc[2])
                return 0;
 
        /* we curently have no method for correcting the error */
@@ -378,8 +359,7 @@ static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
        writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT);
 }
 
-static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd,
-                                     const u_char *dat, u_char *ecc_code)
+static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
 {
        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 
@@ -387,15 +367,12 @@ static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd,
        ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
        ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
 
-       pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n",
-                ecc_code[0], ecc_code[1], ecc_code[2]);
+       pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
 
        return 0;
 }
 
-
-static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd,
-                                     const u_char *dat, u_char *ecc_code)
+static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
 {
        struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
        unsigned long ecc = readl(info->regs + S3C2440_NFMECC0);
@@ -404,13 +381,11 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd,
        ecc_code[1] = ecc >> 8;
        ecc_code[2] = ecc >> 16;
 
-       pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n",
-                ecc_code[0], ecc_code[1], ecc_code[2]);
+       pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
 
        return 0;
 }
 
-
 /* over-ride the standard functions for a little more speed. We can
  * use read/write block to move the data buffers to/from the controller
 */
@@ -421,8 +396,7 @@ static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
        readsb(this->IO_ADDR_R, buf, len);
 }
 
-static void s3c2410_nand_write_buf(struct mtd_info *mtd,
-                                  const u_char *buf, int len)
+static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
        struct nand_chip *this = mtd->priv;
        writesb(this->IO_ADDR_W, buf, len);
@@ -459,7 +433,8 @@ static int s3c2410_nand_remove(struct platform_device *pdev)
        /* free the common resources */
 
        if (info->clk != NULL && !IS_ERR(info->clk)) {
-               clk_disable(info->clk);
+               if (!allow_clk_stop(info))
+                       clk_disable(info->clk);
                clk_put(info->clk);
        }
 
@@ -488,9 +463,7 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
                return add_mtd_device(&mtd->mtd);
 
        if (set->nr_partitions > 0 && set->partitions != NULL) {
-               return add_mtd_partitions(&mtd->mtd,
-                                         set->partitions,
-                                         set->nr_partitions);
+               return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
        }
 
        return add_mtd_device(&mtd->mtd);
@@ -517,7 +490,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
 
        chip->IO_ADDR_R    = info->regs + S3C2410_NFDATA;
        chip->IO_ADDR_W    = info->regs + S3C2410_NFDATA;
-       chip->hwcontrol    = s3c2410_nand_hwcontrol;
+       chip->cmd_ctrl     = s3c2410_nand_hwcontrol;
        chip->dev_ready    = s3c2410_nand_devready;
        chip->write_buf    = s3c2410_nand_write_buf;
        chip->read_buf     = s3c2410_nand_read_buf;
@@ -530,26 +503,29 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
        if (info->is_s3c2440) {
                chip->IO_ADDR_R  = info->regs + S3C2440_NFDATA;
                chip->IO_ADDR_W  = info->regs + S3C2440_NFDATA;
-               chip->hwcontrol  = s3c2440_nand_hwcontrol;
+               chip->cmd_ctrl   = s3c2440_nand_hwcontrol;
        }
 
        nmtd->info         = info;
        nmtd->mtd.priv     = chip;
+       nmtd->mtd.owner    = THIS_MODULE;
        nmtd->set          = set;
 
        if (hardware_ecc) {
-               chip->correct_data  = s3c2410_nand_correct_data;
-               chip->enable_hwecc  = s3c2410_nand_enable_hwecc;
-               chip->calculate_ecc = s3c2410_nand_calculate_ecc;
-               chip->eccmode       = NAND_ECC_HW3_512;
-               chip->autooob       = &nand_hw_eccoob;
+               chip->ecc.correct   = s3c2410_nand_correct_data;
+               chip->ecc.hwctl     = s3c2410_nand_enable_hwecc;
+               chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+               chip->ecc.mode      = NAND_ECC_HW;
+               chip->ecc.size      = 512;
+               chip->ecc.bytes     = 3;
+               chip->ecc.layout    = &nand_hw_eccoob;
 
                if (info->is_s3c2440) {
-                       chip->enable_hwecc  = s3c2440_nand_enable_hwecc;
-                       chip->calculate_ecc = s3c2440_nand_calculate_ecc;
+                       chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
+                       chip->ecc.calculate = s3c2440_nand_calculate_ecc;
                }
        } else {
-               chip->eccmode       = NAND_ECC_SOFT;
+               chip->ecc.mode      = NAND_ECC_SOFT;
        }
 }
 
@@ -654,13 +630,11 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
        nmtd = info->mtds;
 
        for (setno = 0; setno < nr_sets; setno++, nmtd++) {
-               pr_debug("initialising set %d (%p, info %p)\n",
-                        setno, nmtd, info);
+               pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info);
 
                s3c2410_nand_init_chip(info, nmtd, sets);
 
-               nmtd->scan_res = nand_scan(&nmtd->mtd,
-                                          (sets) ? sets->nr_chips : 1);
+               nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
 
                if (nmtd->scan_res == 0) {
                        s3c2410_nand_add_partition(info, nmtd, sets);
@@ -670,6 +644,11 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
                        sets++;
        }
 
+       if (allow_clk_stop(info)) {
+               dev_info(&pdev->dev, "clock idle support enabled\n");
+               clk_disable(info->clk);
+       }
+
        pr_debug("initialised ok\n");
        return 0;
 
@@ -681,6 +660,41 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
        return err;
 }
 
+/* PM Support */
+#ifdef CONFIG_PM
+
+static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
+{
+       struct s3c2410_nand_info *info = platform_get_drvdata(dev);
+
+       if (info) {
+               if (!allow_clk_stop(info))
+                       clk_disable(info->clk);
+       }
+
+       return 0;
+}
+
+static int s3c24xx_nand_resume(struct platform_device *dev)
+{
+       struct s3c2410_nand_info *info = platform_get_drvdata(dev);
+
+       if (info) {
+               clk_enable(info->clk);
+               s3c2410_nand_inithw(info, dev);
+
+               if (allow_clk_stop(info))
+                       clk_disable(info->clk);
+       }
+
+       return 0;
+}
+
+#else
+#define s3c24xx_nand_suspend NULL
+#define s3c24xx_nand_resume NULL
+#endif
+
 /* driver device registration */
 
 static int s3c2410_nand_probe(struct platform_device *dev)
@@ -696,6 +710,8 @@ static int s3c2440_nand_probe(struct platform_device *dev)
 static struct platform_driver s3c2410_nand_driver = {
        .probe          = s3c2410_nand_probe,
        .remove         = s3c2410_nand_remove,
+       .suspend        = s3c24xx_nand_suspend,
+       .resume         = s3c24xx_nand_resume,
        .driver         = {
                .name   = "s3c2410-nand",
                .owner  = THIS_MODULE,
@@ -705,6 +721,8 @@ static struct platform_driver s3c2410_nand_driver = {
 static struct platform_driver s3c2440_nand_driver = {
        .probe          = s3c2440_nand_probe,
        .remove         = s3c2410_nand_remove,
+       .suspend        = s3c24xx_nand_suspend,
+       .resume         = s3c24xx_nand_resume,
        .driver         = {
                .name   = "s3c2440-nand",
                .owner  = THIS_MODULE,
index 1924a4f137c79eed315673de214224d225e78e70..21743658d1505942e59fd5f1ead23b8fa8cab755 100644 (file)
@@ -46,7 +46,6 @@ static int sharpsl_phys_base = 0x0C000000;
 #define FLCLE          (1 << 1)
 #define FLCE0          (1 << 0)
 
-
 /*
  * MTD structure for SharpSL
  */
@@ -60,50 +59,44 @@ static struct mtd_info *sharpsl_mtd = NULL;
 static int nr_partitions;
 static struct mtd_partition sharpsl_nand_default_partition_info[] = {
        {
-       .name = "System Area",
-       .offset = 0,
-       .size = 7 * 1024 * 1024,
-       },
+        .name = "System Area",
+        .offset = 0,
+        .size = 7 * 1024 * 1024,
+        },
        {
-       .name = "Root Filesystem",
-       .offset = 7 * 1024 * 1024,
-       .size = 30 * 1024 * 1024,
-       },
+        .name = "Root Filesystem",
+        .offset = 7 * 1024 * 1024,
+        .size = 30 * 1024 * 1024,
+        },
        {
-       .name = "Home Filesystem",
-       .offset = MTDPART_OFS_APPEND ,
-       .size = MTDPART_SIZ_FULL ,
-       },
+        .name = "Home Filesystem",
+        .offset = MTDPART_OFS_APPEND,
+        .size = MTDPART_SIZ_FULL,
+        },
 };
 
 /*
  *     hardware specific access to control-lines
+ *     ctrl:
+ *     NAND_CNE: bit 0 -> bit 0 & 4
+ *     NAND_CLE: bit 1 -> bit 1
+ *     NAND_ALE: bit 2 -> bit 2
+ *
  */
-static void
-sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd)
+static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+                                  unsigned int ctrl)
 {
-       switch (cmd) {
-       case NAND_CTL_SETCLE:
-               writeb(readb(FLASHCTL) | FLCLE, FLASHCTL);
-               break;
-       case NAND_CTL_CLRCLE:
-               writeb(readb(FLASHCTL) & ~FLCLE, FLASHCTL);
-               break;
-
-       case NAND_CTL_SETALE:
-               writeb(readb(FLASHCTL) | FLALE, FLASHCTL);
-               break;
-       case NAND_CTL_CLRALE:
-               writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL);
-               break;
-
-       case NAND_CTL_SETNCE:
-               writeb(readb(FLASHCTL) & ~(FLCE0|FLCE1), FLASHCTL);
-               break;
-       case NAND_CTL_CLRNCE:
-               writeb(readb(FLASHCTL) | (FLCE0|FLCE1), FLASHCTL);
-               break;
+       struct nand_chip *chip = mtd->priv;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               unsigned char bits = ctrl & 0x07;
+
+               bits |= (ctrl & 0x01) << 4;
+               writeb((readb(FLASHCTL) & 0x17) | bits, FLASHCTL);
        }
+
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, chip->IO_ADDR_W);
 }
 
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
@@ -122,31 +115,26 @@ static struct nand_bbt_descr sharpsl_akita_bbt = {
        .pattern = scan_ff_pattern
 };
 
-static struct nand_oobinfo akita_oobinfo = {
-       .useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout akita_oobinfo = {
        .eccbytes = 24,
        .eccpos = {
-               0x5,  0x1,  0x2,  0x3,  0x6,  0x7,  0x15, 0x11,
-               0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
-               0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
-       .oobfree = { {0x08, 0x09} }
+                  0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11,
+                  0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
+                  0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
+       .oobfree = {{0x08, 0x09}}
 };
 
-static int
-sharpsl_nand_dev_ready(struct mtd_info* mtd)
+static int sharpsl_nand_dev_ready(struct mtd_info *mtd)
 {
        return !((readb(FLASHCTL) & FLRYBY) == 0);
 }
 
-static void
-sharpsl_nand_enable_hwecc(struct mtd_info* mtd, int mode)
+static void sharpsl_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 {
-       writeb(0 ,ECCCLRR);
+       writeb(0ECCCLRR);
 }
 
-static int
-sharpsl_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat,
-                               u_char* ecc_code)
+static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code)
 {
        ecc_code[0] = ~readb(ECCLPUB);
        ecc_code[1] = ~readb(ECCLPLB);
@@ -154,47 +142,44 @@ sharpsl_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat,
        return readb(ECCCNTR) != 0;
 }
 
-
 #ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
 
-
 /*
  * Main initialization routine
  */
-int __init
-sharpsl_nand_init(void)
+static int __init sharpsl_nand_init(void)
 {
        struct nand_chip *this;
-       struct mtd_partitionsharpsl_partition_info;
+       struct mtd_partition *sharpsl_partition_info;
        int err = 0;
 
        /* Allocate memory for MTD device structure and private data */
-       sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
-                               GFP_KERNEL);
+       sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!sharpsl_mtd) {
-               printk ("Unable to allocate SharpSL NAND MTD device structure.\n");
+               printk("Unable to allocate SharpSL NAND MTD device structure.\n");
                return -ENOMEM;
        }
 
        /* map physical adress */
        sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000);
-       if(!sharpsl_io_base){
+       if (!sharpsl_io_base) {
                printk("ioremap to access Sharp SL NAND chip failed\n");
                kfree(sharpsl_mtd);
                return -EIO;
        }
 
        /* Get pointer to private data */
-       this = (struct nand_chip *) (&sharpsl_mtd[1]);
+       this = (struct nand_chip *)(&sharpsl_mtd[1]);
 
        /* Initialize structures */
-       memset((char *) sharpsl_mtd, 0, sizeof(struct mtd_info));
-       memset((char *) this, 0, sizeof(struct nand_chip));
+       memset(sharpsl_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
 
        /* Link the private data with the MTD structure */
        sharpsl_mtd->priv = this;
+       sharpsl_mtd->owner = THIS_MODULE;
 
        /*
         * PXA initialize
@@ -205,23 +190,25 @@ sharpsl_nand_init(void)
        this->IO_ADDR_R = FLASHIO;
        this->IO_ADDR_W = FLASHIO;
        /* Set address of hardware control function */
-       this->hwcontrol = sharpsl_nand_hwcontrol;
+       this->cmd_ctrl = sharpsl_nand_hwcontrol;
        this->dev_ready = sharpsl_nand_dev_ready;
        /* 15 us command delay time */
        this->chip_delay = 15;
        /* set eccmode using hardware ECC */
-       this->eccmode = NAND_ECC_HW3_256;
+       this->ecc.mode = NAND_ECC_HW;
+       this->ecc.size = 256;
+       this->ecc.bytes = 3;
        this->badblock_pattern = &sharpsl_bbt;
        if (machine_is_akita() || machine_is_borzoi()) {
                this->badblock_pattern = &sharpsl_akita_bbt;
-               this->autooob = &akita_oobinfo;
+               this->ecc.layout = &akita_oobinfo;
        }
-       this->enable_hwecc = sharpsl_nand_enable_hwecc;
-       this->calculate_ecc = sharpsl_nand_calculate_ecc;
-       this->correct_data = nand_correct_data;
+       this->ecc.hwctl = sharpsl_nand_enable_hwecc;
+       this->ecc.calculate = sharpsl_nand_calculate_ecc;
+       this->ecc.correct = nand_correct_data;
 
        /* Scan to find existence of the device */
-       err=nand_scan(sharpsl_mtd,1);
+       err = nand_scan(sharpsl_mtd, 1);
        if (err) {
                iounmap(sharpsl_io_base);
                kfree(sharpsl_mtd);
@@ -230,24 +217,23 @@ sharpsl_nand_init(void)
 
        /* Register the partitions */
        sharpsl_mtd->name = "sharpsl-nand";
-       nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes,
-                                               &sharpsl_partition_info, 0);
+       nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, &sharpsl_partition_info, 0);
 
        if (nr_partitions <= 0) {
                nr_partitions = DEFAULT_NUM_PARTITIONS;
                sharpsl_partition_info = sharpsl_nand_default_partition_info;
                if (machine_is_poodle()) {
-                       sharpsl_partition_info[1].size=30 * 1024 * 1024;
+                       sharpsl_partition_info[1].size = 22 * 1024 * 1024;
                } else if (machine_is_corgi() || machine_is_shepherd()) {
-                       sharpsl_partition_info[1].size=25 * 1024 * 1024;
+                       sharpsl_partition_info[1].size = 25 * 1024 * 1024;
                } else if (machine_is_husky()) {
-                       sharpsl_partition_info[1].size=53 * 1024 * 1024;
+                       sharpsl_partition_info[1].size = 53 * 1024 * 1024;
                } else if (machine_is_spitz()) {
-                       sharpsl_partition_info[1].size=5 * 1024 * 1024;
+                       sharpsl_partition_info[1].size = 5 * 1024 * 1024;
                } else if (machine_is_akita()) {
-                       sharpsl_partition_info[1].size=58 * 1024 * 1024;
+                       sharpsl_partition_info[1].size = 58 * 1024 * 1024;
                } else if (machine_is_borzoi()) {
-                       sharpsl_partition_info[1].size=32 * 1024 * 1024;
+                       sharpsl_partition_info[1].size = 32 * 1024 * 1024;
                }
        }
 
@@ -261,15 +247,15 @@ sharpsl_nand_init(void)
        /* Return happy */
        return 0;
 }
+
 module_init(sharpsl_nand_init);
 
 /*
  * Clean up routine
  */
-#ifdef MODULE
 static void __exit sharpsl_nand_cleanup(void)
 {
-       struct nand_chip *this = (struct nand_chip *) &sharpsl_mtd[1];
+       struct nand_chip *this = (struct nand_chip *)&sharpsl_mtd[1];
 
        /* Release resources, unregister device */
        nand_release(sharpsl_mtd);
@@ -279,8 +265,8 @@ static void __exit sharpsl_nand_cleanup(void)
        /* Free the MTD device structure */
        kfree(sharpsl_mtd);
 }
+
 module_exit(sharpsl_nand_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
index 9cf1ce718ec150c2bb47b89f1efb3d36b7fad850..1f6d429b158319c6db75f710e8daad63bbe48588 100644 (file)
@@ -39,16 +39,16 @@ static struct mtd_info *spia_mtd = NULL;
  */
 #define SPIA_IO_BASE   0xd0000000      /* Start of EP7212 IO address space */
 #define SPIA_FIO_BASE  0xf0000000      /* Address where flash is mapped */
-#define SPIA_PEDR      0x0080          /*
-                                        * IO offset to Port E data register
-                                        * where the CLE, ALE and NCE pins
-                                        * are wired to.
-                                        */
-#define SPIA_PEDDR     0x00c0          /*
-                                        * IO offset to Port E data direction
-                                        * register so we can control the IO
-                                        * lines.
-                                        */
+#define SPIA_PEDR      0x0080  /*
+                                * IO offset to Port E data register
+                                * where the CLE, ALE and NCE pins
+                                * are wired to.
+                                */
+#define SPIA_PEDDR     0x00c0  /*
+                                * IO offset to Port E data direction
+                                * register so we can control the IO
+                                * lines.
+                                */
 
 /*
  * Module stuff
@@ -69,79 +69,84 @@ module_param(spia_peddr, int, 0);
  */
 static const struct mtd_partition partition_info[] = {
        {
-               .name   = "SPIA flash partition 1",
-               .offset = 0,
-               .size   = 2*1024*1024
-       },
+        .name = "SPIA flash partition 1",
+        .offset = 0,
+        .size = 2 * 1024 * 1024},
        {
-               .name   = "SPIA flash partition 2",
-               .offset = 2*1024*1024,
-               .size   = 6*1024*1024
-       }
+        .name = "SPIA flash partition 2",
+        .offset = 2 * 1024 * 1024,
+        .size = 6 * 1024 * 1024}
 };
-#define NUM_PARTITIONS 2
 
+#define NUM_PARTITIONS 2
 
 /*
  *     hardware specific access to control-lines
-*/
-static void spia_hwcontrol(struct mtd_info *mtd, int cmd){
-
-    switch(cmd){
+ *
+ *     ctrl:
+ *     NAND_CNE: bit 0 -> bit 2
+ *     NAND_CLE: bit 1 -> bit 0
+ *     NAND_ALE: bit 2 -> bit 1
+ */
+static void spia_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+       struct nand_chip *chip = mtd->priv;
 
-       case NAND_CTL_SETCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |=  0x01; break;
-       case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x01; break;
+       if (ctrl & NAND_CTRL_CHANGE) {
+               void __iomem *addr = spia_io_base + spia_pedr;
+               unsigned char bits;
 
-       case NAND_CTL_SETALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |=  0x02; break;
-       case NAND_CTL_CLRALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x02; break;
+               bits = (ctrl & NAND_CNE) << 2;
+               bits |= (ctrl & NAND_CLE | NAND_ALE) >> 1;
+               writeb((readb(addr) & ~0x7) | bits, addr);
+       }
 
-       case NAND_CTL_SETNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x04; break;
-       case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |=  0x04; break;
-    }
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, chip->IO_ADDR_W);
 }
 
 /*
  * Main initialization routine
  */
-int __init spia_init (void)
+static int __init spia_init(void)
 {
        struct nand_chip *this;
 
        /* Allocate memory for MTD device structure and private data */
-       spia_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
-                               GFP_KERNEL);
+       spia_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!spia_mtd) {
-               printk ("Unable to allocate SPIA NAND MTD device structure.\n");
+               printk("Unable to allocate SPIA NAND MTD device structure.\n");
                return -ENOMEM;
        }
 
        /* Get pointer to private data */
-       this = (struct nand_chip *) (&spia_mtd[1]);
+       this = (struct nand_chip *)(&spia_mtd[1]);
 
        /* Initialize structures */
-       memset((char *) spia_mtd, 0, sizeof(struct mtd_info));
-       memset((char *) this, 0, sizeof(struct nand_chip));
+       memset(spia_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
 
        /* Link the private data with the MTD structure */
        spia_mtd->priv = this;
+       spia_mtd->owner = THIS_MODULE;
 
        /*
         * Set GPIO Port E control register so that the pins are configured
         * to be outputs for controlling the NAND flash.
         */
-       (*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07;
+       (*(volatile unsigned char *)(spia_io_base + spia_peddr)) = 0x07;
 
        /* Set address of NAND IO lines */
-       this->IO_ADDR_R = (void __iomem *) spia_fio_base;
-       this->IO_ADDR_W = (void __iomem *) spia_fio_base;
+       this->IO_ADDR_R = (void __iomem *)spia_fio_base;
+       this->IO_ADDR_W = (void __iomem *)spia_fio_base;
        /* Set address of hardware control function */
-       this->hwcontrol = spia_hwcontrol;
+       this->cmd_ctrl = spia_hwcontrol;
        /* 15 us command delay time */
        this->chip_delay = 15;
 
        /* Scan to find existence of the device */
-       if (nand_scan (spia_mtd, 1)) {
-               kfree (spia_mtd);
+       if (nand_scan(spia_mtd, 1)) {
+               kfree(spia_mtd);
                return -ENXIO;
        }
 
@@ -151,22 +156,22 @@ int __init spia_init (void)
        /* Return happy */
        return 0;
 }
+
 module_init(spia_init);
 
 /*
  * Clean up routine
  */
-#ifdef MODULE
-static void __exit spia_cleanup (void)
+static void __exit spia_cleanup(void)
 {
        /* Release resources, unregister device */
-       nand_release (spia_mtd);
+       nand_release(spia_mtd);
 
        /* Free the MTD device structure */
-       kfree (spia_mtd);
+       kfree(spia_mtd);
 }
+
 module_exit(spia_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com");
index 7609c43cb3ec759baf4b24d5728b34d9dbe64a03..f9e2d4a0ab8c661bba8dec6e46f1e194433eecfd 100644 (file)
@@ -32,6 +32,8 @@
 #include <asm/arch-omap1510/hardware.h>
 #include <asm/arch/gpio.h>
 
+#define CONFIG_NAND_WORKAROUND 1
+
 /*
  * MTD structure for TOTO board
  */
@@ -39,25 +41,6 @@ static struct mtd_info *toto_mtd = NULL;
 
 static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
 
-#define CONFIG_NAND_WORKAROUND 1
-
-#define NAND_NCE 0x4000
-#define NAND_CLE 0x1000
-#define NAND_ALE 0x0002
-#define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE)
-
-#define T_NAND_CTL_CLRALE(iob)  gpiosetout(NAND_ALE, 0)
-#define T_NAND_CTL_SETALE(iob)  gpiosetout(NAND_ALE, NAND_ALE)
-#ifdef CONFIG_NAND_WORKAROUND     /* "some" dev boards busted, blue wired to rts2 :( */
-#define T_NAND_CTL_CLRCLE(iob)  gpiosetout(NAND_CLE, 0); rts2setout(2, 2)
-#define T_NAND_CTL_SETCLE(iob)  gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0)
-#else
-#define T_NAND_CTL_CLRCLE(iob)  gpiosetout(NAND_CLE, 0)
-#define T_NAND_CTL_SETCLE(iob)  gpiosetout(NAND_CLE, NAND_CLE)
-#endif
-#define T_NAND_CTL_SETNCE(iob)  gpiosetout(NAND_NCE, 0)
-#define T_NAND_CTL_CLRNCE(iob)  gpiosetout(NAND_NCE, NAND_NCE)
-
 /*
  * Define partitions for flash devices
  */
@@ -91,91 +74,110 @@ static struct mtd_partition partition_info32M[] = {
 
 #define NUM_PARTITIONS32M 3
 #define NUM_PARTITIONS64M 4
+
 /*
  *     hardware specific access to control-lines
-*/
-
-static void toto_hwcontrol(struct mtd_info *mtd, int cmd)
+ *
+ *     ctrl:
+ *     NAND_NCE: bit 0 -> bit 14 (0x4000)
+ *     NAND_CLE: bit 1 -> bit 12 (0x1000)
+ *     NAND_ALE: bit 2 -> bit 1  (0x0002)
+ */
+static void toto_hwcontrol(struct mtd_info *mtd, int cmd,
+                          unsigned int ctrl)
 {
+       struct nand_chip *chip = mtd->priv;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               unsigned long bits;
 
-       udelay(1); /* hopefully enough time for tc make proceding write to clear */
-       switch(cmd){
+               /* hopefully enough time for tc make proceding write to clear */
+               udelay(1);
 
-               case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
-               case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
+               bits = (~ctrl & NAND_NCE) << 14;
+               bits |= (ctrl & NAND_CLE) << 12;
+               bits |= (ctrl & NAND_ALE) >> 1;
 
-               case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break;
-               case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break;
+#warning Wild guess as gpiosetout() is nowhere defined in the kernel source - tglx
+               gpiosetout(0x5002, bits);
 
-               case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
-               case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
+#ifdef CONFIG_NAND_WORKAROUND
+               /* "some" dev boards busted, blue wired to rts2 :( */
+               rts2setout(2, (ctrl & NAND_CLE) << 1);
+#endif
+               /* allow time to ensure gpio state to over take memory write */
+               udelay(1);
        }
-       udelay(1); /* allow time to ensure gpio state to over take memory write */
+
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, chip->IO_ADDR_W);
 }
 
 /*
  * Main initialization routine
  */
-int __init toto_init (void)
+static int __init toto_init(void)
 {
        struct nand_chip *this;
        int err = 0;
 
        /* Allocate memory for MTD device structure and private data */
-       toto_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
-                               GFP_KERNEL);
+       toto_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
        if (!toto_mtd) {
-               printk (KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
+               printk(KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
                err = -ENOMEM;
                goto out;
        }
 
        /* Get pointer to private data */
-       this = (struct nand_chip *) (&toto_mtd[1]);
+       this = (struct nand_chip *)(&toto_mtd[1]);
 
        /* Initialize structures */
-       memset((char *) toto_mtd, 0, sizeof(struct mtd_info));
-       memset((char *) this, 0, sizeof(struct nand_chip));
+       memset(toto_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
 
        /* Link the private data with the MTD structure */
        toto_mtd->priv = this;
+       toto_mtd->owner = THIS_MODULE;
 
        /* Set address of NAND IO lines */
        this->IO_ADDR_R = toto_io_base;
        this->IO_ADDR_W = toto_io_base;
-       this->hwcontrol = toto_hwcontrol;
+       this->cmd_ctrl = toto_hwcontrol;
        this->dev_ready = NULL;
        /* 25 us command delay time */
        this->chip_delay = 30;
-       this->eccmode = NAND_ECC_SOFT;
+       this->ecc.mode = NAND_ECC_SOFT;
 
-        /* Scan to find existance of the device */
-       if (nand_scan (toto_mtd, 1)) {
+       /* Scan to find existance of the device */
+       if (nand_scan(toto_mtd, 1)) {
                err = -ENXIO;
                goto out_mtd;
        }
 
        /* Register the partitions */
-       switch(toto_mtd->size){
-               case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break;
-               case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break;
-               default: {
-                       printk (KERN_WARNING "Unsupported Nand device\n");
+       switch (toto_mtd->size) {
+       case SZ_64M:
+               add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M);
+               break;
+       case SZ_32M:
+               add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M);
+               break;
+       default:{
+                       printk(KERN_WARNING "Unsupported Nand device\n");
                        err = -ENXIO;
                        goto out_buf;
                }
        }
 
-       gpioreserve(NAND_MASK);  /* claim our gpios */
-       archflashwp(0,0);        /* open up flash for writing */
+       gpioreserve(NAND_MASK); /* claim our gpios */
+       archflashwp(0, 0);      /* open up flash for writing */
 
        goto out;
 
-out_buf:
-       kfree (this->data_buf);
-out_mtd:
-       kfree (toto_mtd);
-out:
+ out_mtd:
+       kfree(toto_mtd);
+ out:
        return err;
 }
 
@@ -184,20 +186,21 @@ module_init(toto_init);
 /*
  * Clean up routine
  */
-static void __exit toto_cleanup (void)
+static void __exit toto_cleanup(void)
 {
        /* Release resources, unregister device */
-       nand_release (toto_mtd);
+       nand_release(toto_mtd);
 
        /* Free the MTD device structure */
-       kfree (toto_mtd);
+       kfree(toto_mtd);
 
        /* stop flash writes */
-        archflashwp(0,1);
+       archflashwp(0, 1);
 
        /* release gpios to system */
-        gpiorelease(NAND_MASK);
+       gpiorelease(NAND_MASK);
 }
+
 module_exit(toto_cleanup);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c
new file mode 100644 (file)
index 0000000..a0b4b1e
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * drivers/mtd/nand/ts7250.c
+ *
+ * Copyright (C) 2004 Technologic Systems (support@embeddedARM.com)
+ *
+ * Derived from drivers/mtd/nand/edb7312.c
+ *   Copyright (C) 2004 Marius Gröger (mag@sysgo.de)
+ *
+ * Derived from drivers/mtd/nand/autcpu12.c
+ *   Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
+ *
+ * $Id: ts7250.c,v 1.4 2004/12/30 22:02:07 joff Exp $
+ *
+ * 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.
+ *
+ * Overview:
+ *   This is a device driver for the NAND flash device found on the
+ *   TS-7250 board which utilizes a Samsung 32 Mbyte part.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/sizes.h>
+#include <asm/mach-types.h>
+
+/*
+ * MTD structure for TS7250 board
+ */
+static struct mtd_info *ts7250_mtd = NULL;
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "cmdlinepart", NULL };
+
+#define NUM_PARTITIONS 3
+
+/*
+ * Define static partitions for flash device
+ */
+static struct mtd_partition partition_info32[] = {
+       {
+               .name           = "TS-BOOTROM",
+               .offset         = 0x00000000,
+               .size           = 0x00004000,
+       }, {
+               .name           = "Linux",
+               .offset         = 0x00004000,
+               .size           = 0x01d00000,
+       }, {
+               .name           = "RedBoot",
+               .offset         = 0x01d04000,
+               .size           = 0x002fc000,
+       },
+};
+
+/*
+ * Define static partitions for flash device
+ */
+static struct mtd_partition partition_info128[] = {
+       {
+               .name           = "TS-BOOTROM",
+               .offset         = 0x00000000,
+               .size           = 0x00004000,
+       }, {
+               .name           = "Linux",
+               .offset         = 0x00004000,
+               .size           = 0x07d00000,
+       }, {
+               .name           = "RedBoot",
+               .offset         = 0x07d04000,
+               .size           = 0x002fc000,
+       },
+};
+#endif
+
+
+/*
+ *     hardware specific access to control-lines
+ *
+ *     ctrl:
+ *     NAND_NCE: bit 0 -> bit 2
+ *     NAND_CLE: bit 1 -> bit 1
+ *     NAND_ALE: bit 2 -> bit 0
+ */
+static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+       struct nand_chip *chip = mtd->priv;
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE;
+               unsigned char bits;
+
+               bits = (ctrl & NAND_CNE) << 2;
+               bits |= ctrl & NAND_CLE;
+               bits |= (ctrl & NAND_ALE) >> 2;
+
+               __raw_writeb((__raw_readb(addr) & ~0x7) | bits, addr);
+       }
+
+       if (cmd != NAND_CMD_NONE)
+               writeb(cmd, chip->IO_ADDR_W);
+}
+
+/*
+ *     read device ready pin
+ */
+static int ts7250_device_ready(struct mtd_info *mtd)
+{
+       return __raw_readb(TS72XX_NAND_BUSY_VIRT_BASE) & 0x20;
+}
+
+/*
+ * Main initialization routine
+ */
+static int __init ts7250_init(void)
+{
+       struct nand_chip *this;
+       const char *part_type = 0;
+       int mtd_parts_nb = 0;
+       struct mtd_partition *mtd_parts = 0;
+
+       if (!machine_is_ts72xx() || board_is_ts7200())
+               return -ENXIO;
+
+       /* Allocate memory for MTD device structure and private data */
+       ts7250_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
+       if (!ts7250_mtd) {
+               printk("Unable to allocate TS7250 NAND MTD device structure.\n");
+               return -ENOMEM;
+       }
+
+       /* Get pointer to private data */
+       this = (struct nand_chip *)(&ts7250_mtd[1]);
+
+       /* Initialize structures */
+       memset(ts7250_mtd, 0, sizeof(struct mtd_info));
+       memset(this, 0, sizeof(struct nand_chip));
+
+       /* Link the private data with the MTD structure */
+       ts7250_mtd->priv = this;
+       ts7250_mtd->owner = THIS_MODULE;
+
+       /* insert callbacks */
+       this->IO_ADDR_R = (void *)TS72XX_NAND_DATA_VIRT_BASE;
+       this->IO_ADDR_W = (void *)TS72XX_NAND_DATA_VIRT_BASE;
+       this->cmd_ctrl = ts7250_hwcontrol;
+       this->dev_ready = ts7250_device_ready;
+       this->chip_delay = 15;
+       this->ecc.mode = NAND_ECC_SOFT;
+
+       printk("Searching for NAND flash...\n");
+       /* Scan to find existence of the device */
+       if (nand_scan(ts7250_mtd, 1)) {
+               kfree(ts7250_mtd);
+               return -ENXIO;
+       }
+#ifdef CONFIG_MTD_PARTITIONS
+       ts7250_mtd->name = "ts7250-nand";
+       mtd_parts_nb = parse_mtd_partitions(ts7250_mtd, part_probes, &mtd_parts, 0);
+       if (mtd_parts_nb > 0)
+               part_type = "command line";
+       else
+               mtd_parts_nb = 0;
+#endif
+       if (mtd_parts_nb == 0) {
+               mtd_parts = partition_info32;
+               if (ts7250_mtd->size >= (128 * 0x100000))
+                       mtd_parts = partition_info128;
+               mtd_parts_nb = NUM_PARTITIONS;
+               part_type = "static";
+       }
+
+       /* Register the partitions */
+       printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+       add_mtd_partitions(ts7250_mtd, mtd_parts, mtd_parts_nb);
+
+       /* Return happy */
+       return 0;
+}
+
+module_init(ts7250_init);
+
+/*
+ * Clean up routine
+ */
+static void __exit ts7250_cleanup(void)
+{
+       /* Unregister the device */
+       del_mtd_device(ts7250_mtd);
+
+       /* Free the MTD device structure */
+       kfree(ts7250_mtd);
+}
+
+module_exit(ts7250_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jesse Off <joff@embeddedARM.com>");
+MODULE_DESCRIPTION("MTD map driver for Technologic Systems TS-7250 board");
index d7cd5fa16ba445e8d854760de615e7ec15821949..dc7573501d8c0ded5812f355741c369f72bffdf2 100644 (file)
@@ -70,8 +70,6 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
        nftl->mbd.devnum = -1;
        nftl->mbd.blksize = 512;
        nftl->mbd.tr = tr;
-       memcpy(&nftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
-       nftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
 
         if (NFTL_mount(nftl) < 0) {
                printk(KERN_WARNING "NFTL: could not mount device\n");
@@ -136,6 +134,69 @@ static void nftl_remove_dev(struct mtd_blktrans_dev *dev)
        kfree(nftl);
 }
 
+/*
+ * Read oob data from flash
+ */
+int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                 size_t *retlen, uint8_t *buf)
+{
+       struct mtd_oob_ops ops;
+       int res;
+
+       ops.mode = MTD_OOB_PLACE;
+       ops.ooboffs = offs & (mtd->writesize - 1);
+       ops.ooblen = len;
+       ops.oobbuf = buf;
+       ops.datbuf = NULL;
+       ops.len = len;
+
+       res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+       *retlen = ops.retlen;
+       return res;
+}
+
+/*
+ * Write oob data to flash
+ */
+int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                  size_t *retlen, uint8_t *buf)
+{
+       struct mtd_oob_ops ops;
+       int res;
+
+       ops.mode = MTD_OOB_PLACE;
+       ops.ooboffs = offs & (mtd->writesize - 1);
+       ops.ooblen = len;
+       ops.oobbuf = buf;
+       ops.datbuf = NULL;
+       ops.len = len;
+
+       res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+       *retlen = ops.retlen;
+       return res;
+}
+
+/*
+ * Write data and oob to flash
+ */
+static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
+                     size_t *retlen, uint8_t *buf, uint8_t *oob)
+{
+       struct mtd_oob_ops ops;
+       int res;
+
+       ops.mode = MTD_OOB_PLACE;
+       ops.ooboffs = offs;
+       ops.ooblen = mtd->oobsize;
+       ops.oobbuf = oob;
+       ops.datbuf = buf;
+       ops.len = len;
+
+       res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+       *retlen = ops.retlen;
+       return res;
+}
+
 #ifdef CONFIG_NFTL_RW
 
 /* Actual NFTL access routines */
@@ -185,6 +246,7 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate )
 
 static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock )
 {
+       struct mtd_info *mtd = nftl->mbd.mtd;
        u16 BlockMap[MAX_SECTORS_PER_UNIT];
        unsigned char BlockLastState[MAX_SECTORS_PER_UNIT];
        unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT];
@@ -194,7 +256,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
        unsigned int targetEUN;
        struct nftl_oob oob;
        int inplace = 1;
-        size_t retlen;
+       size_t retlen;
 
        memset(BlockMap, 0xff, sizeof(BlockMap));
        memset(BlockFreeFound, 0, sizeof(BlockFreeFound));
@@ -210,21 +272,21 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
        /* Scan to find the Erase Unit which holds the actual data for each
           512-byte block within the Chain.
        */
-        silly = MAX_LOOPS;
+       silly = MAX_LOOPS;
        targetEUN = BLOCK_NIL;
        while (thisEUN <= nftl->lastEUN ) {
-                unsigned int status, foldmark;
+               unsigned int status, foldmark;
 
                targetEUN = thisEUN;
                for (block = 0; block < nftl->EraseSize / 512; block ++) {
-                       MTD_READOOB(nftl->mbd.mtd,
-                                   (thisEUN * nftl->EraseSize) + (block * 512),
-                                   16 , &retlen, (char *)&oob);
+                       nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
+                                     (block * 512), 16 , &retlen,
+                                     (char *)&oob);
                        if (block == 2) {
-                                foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
-                                if (foldmark == FOLD_MARK_IN_PROGRESS) {
-                                        DEBUG(MTD_DEBUG_LEVEL1,
-                                              "Write Inhibited on EUN %d\n", thisEUN);
+                               foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
+                               if (foldmark == FOLD_MARK_IN_PROGRESS) {
+                                       DEBUG(MTD_DEBUG_LEVEL1,
+                                             "Write Inhibited on EUN %d\n", thisEUN);
                                        inplace = 0;
                                } else {
                                        /* There's no other reason not to do inplace,
@@ -233,7 +295,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
                                        inplace = 1;
                                }
                        }
-                        status = oob.b.Status | oob.b.Status1;
+                       status = oob.b.Status | oob.b.Status1;
                        BlockLastState[block] = status;
 
                        switch(status) {
@@ -328,15 +390,15 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
                        return BLOCK_NIL;
                }
        } else {
-            /* We put a fold mark in the chain we are folding only if
-               we fold in place to help the mount check code. If we do
-               not fold in place, it is possible to find the valid
-               chain by selecting the longer one */
-            oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
-            oob.u.c.unused = 0xffffffff;
-            MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
-                         8, &retlen, (char *)&oob.u);
-        }
+               /* We put a fold mark in the chain we are folding only if we
+               fold in place to help the mount check code. If we do not fold in
+               place, it is possible to find the valid chain by selecting the
+               longer one */
+               oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
+               oob.u.c.unused = 0xffffffff;
+               nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
+                              8, &retlen, (char *)&oob.u);
+       }
 
        /* OK. We now know the location of every block in the Virtual Unit Chain,
           and the Erase Unit into which we are supposed to be copying.
@@ -353,33 +415,33 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
                        continue;
                }
 
-                /* copy only in non free block (free blocks can only
+               /* copy only in non free block (free blocks can only
                    happen in case of media errors or deleted blocks) */
-                if (BlockMap[block] == BLOCK_NIL)
-                        continue;
-
-                ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
-                                 512, &retlen, movebuf);
-                if (ret < 0) {
-                    ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block])
-                                      + (block * 512), 512, &retlen,
-                                      movebuf);
-                    if (ret != -EIO)
-                        printk("Error went away on retry.\n");
-                }
+               if (BlockMap[block] == BLOCK_NIL)
+                       continue;
+
+               ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
+                               512, &retlen, movebuf);
+               if (ret < 0 && ret != -EUCLEAN) {
+                       ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block])
+                                       + (block * 512), 512, &retlen,
+                                       movebuf);
+                       if (ret != -EIO)
+                               printk("Error went away on retry.\n");
+               }
                memset(&oob, 0xff, sizeof(struct nftl_oob));
                oob.b.Status = oob.b.Status1 = SECTOR_USED;
-                MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512),
-                             512, &retlen, movebuf, (char *)&oob, &nftl->oobinfo);
+
+               nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) +
+                          (block * 512), 512, &retlen, movebuf, (char *)&oob);
        }
 
-        /* add the header so that it is now a valid chain */
-        oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum
-                = cpu_to_le16(thisVUC);
-        oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
+       /* add the header so that it is now a valid chain */
+       oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
+       oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
 
-        MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8,
-                     8, &retlen, (char *)&oob.u);
+       nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8,
+                      8, &retlen, (char *)&oob.u);
 
        /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */
 
@@ -396,18 +458,18 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
        while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) {
                unsigned int EUNtmp;
 
-                EUNtmp = nftl->ReplUnitTable[thisEUN];
+               EUNtmp = nftl->ReplUnitTable[thisEUN];
 
-                if (NFTL_formatblock(nftl, thisEUN) < 0) {
+               if (NFTL_formatblock(nftl, thisEUN) < 0) {
                        /* could not erase : mark block as reserved
                         */
                        nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED;
-                } else {
+               } else {
                        /* correctly erased : mark it as free */
                        nftl->ReplUnitTable[thisEUN] = BLOCK_FREE;
                        nftl->numfreeEUNs++;
-                }
-                thisEUN = EUNtmp;
+               }
+               thisEUN = EUNtmp;
        }
 
        /* Make this the new start of chain for thisVUC */
@@ -473,6 +535,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
 {
        u16 lastEUN;
        u16 thisVUC = block / (nftl->EraseSize / 512);
+       struct mtd_info *mtd = nftl->mbd.mtd;
        unsigned int writeEUN;
        unsigned long blockofs = (block * 512) & (nftl->EraseSize -1);
        size_t retlen;
@@ -489,21 +552,22 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
                */
                lastEUN = BLOCK_NIL;
                writeEUN = nftl->EUNtable[thisVUC];
-                silly = MAX_LOOPS;
+               silly = MAX_LOOPS;
                while (writeEUN <= nftl->lastEUN) {
                        struct nftl_bci bci;
                        size_t retlen;
-                        unsigned int status;
+                       unsigned int status;
 
                        lastEUN = writeEUN;
 
-                       MTD_READOOB(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
-                                   8, &retlen, (char *)&bci);
+                       nftl_read_oob(mtd,
+                                     (writeEUN * nftl->EraseSize) + blockofs,
+                                     8, &retlen, (char *)&bci);
 
                        DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n",
                              block , writeEUN, le16_to_cpu(bci.Status));
 
-                        status = bci.Status | bci.Status1;
+                       status = bci.Status | bci.Status1;
                        switch(status) {
                        case SECTOR_FREE:
                                return writeEUN;
@@ -574,10 +638,10 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
                /* We've found a free block. Insert it into the chain. */
 
                if (lastEUN != BLOCK_NIL) {
-                    thisVUC |= 0x8000; /* It's a replacement block */
+                       thisVUC |= 0x8000; /* It's a replacement block */
                } else {
-                    /* The first block in a new chain */
-                    nftl->EUNtable[thisVUC] = writeEUN;
+                       /* The first block in a new chain */
+                       nftl->EUNtable[thisVUC] = writeEUN;
                }
 
                /* set up the actual EUN we're writing into */
@@ -585,29 +649,29 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
                nftl->ReplUnitTable[writeEUN] = BLOCK_NIL;
 
                /* ... and on the flash itself */
-               MTD_READOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8,
-                           &retlen, (char *)&oob.u);
+               nftl_read_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
+                             &retlen, (char *)&oob.u);
 
                oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
 
-               MTD_WRITEOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8,
-                             &retlen, (char *)&oob.u);
+               nftl_write_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
+                              &retlen, (char *)&oob.u);
 
-                /* we link the new block to the chain only after the
+               /* we link the new block to the chain only after the
                    block is ready. It avoids the case where the chain
                    could point to a free block */
-                if (lastEUN != BLOCK_NIL) {
+               if (lastEUN != BLOCK_NIL) {
                        /* Both in our cache... */
                        nftl->ReplUnitTable[lastEUN] = writeEUN;
                        /* ... and on the flash itself */
-                       MTD_READOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8,
-                                   8, &retlen, (char *)&oob.u);
+                       nftl_read_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
+                                     8, &retlen, (char *)&oob.u);
 
                        oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum
                                = cpu_to_le16(writeEUN);
 
-                       MTD_WRITEOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8,
-                                    8, &retlen, (char *)&oob.u);
+                       nftl_write_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
+                                      8, &retlen, (char *)&oob.u);
                }
 
                return writeEUN;
@@ -639,10 +703,9 @@ static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
 
        memset(&oob, 0xff, sizeof(struct nftl_oob));
        oob.b.Status = oob.b.Status1 = SECTOR_USED;
-       MTD_WRITEECC(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
-                    512, &retlen, (char *)buffer, (char *)&oob, &nftl->oobinfo);
-        /* need to write SECTOR_USED flags since they are not written in mtd_writeecc */
 
+       nftl_write(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
+                  512, &retlen, (char *)buffer, (char *)&oob);
        return 0;
 }
 #endif /* CONFIG_NFTL_RW */
@@ -651,20 +714,22 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
                          char *buffer)
 {
        struct NFTLrecord *nftl = (void *)mbd;
+       struct mtd_info *mtd = nftl->mbd.mtd;
        u16 lastgoodEUN;
        u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)];
        unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
-        unsigned int status;
+       unsigned int status;
        int silly = MAX_LOOPS;
-        size_t retlen;
-        struct nftl_bci bci;
+       size_t retlen;
+       struct nftl_bci bci;
 
        lastgoodEUN = BLOCK_NIL;
 
-        if (thisEUN != BLOCK_NIL) {
+       if (thisEUN != BLOCK_NIL) {
                while (thisEUN < nftl->nb_blocks) {
-                       if (MTD_READOOB(nftl->mbd.mtd, (thisEUN * nftl->EraseSize) + blockofs,
-                                       8, &retlen, (char *)&bci) < 0)
+                       if (nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
+                                         blockofs, 8, &retlen,
+                                         (char *)&bci) < 0)
                                status = SECTOR_IGNORE;
                        else
                                status = bci.Status | bci.Status1;
@@ -694,7 +759,7 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
                        }
                        thisEUN = nftl->ReplUnitTable[thisEUN];
                }
-        }
+       }
 
  the_end:
        if (lastgoodEUN == BLOCK_NIL) {
@@ -703,7 +768,9 @@ static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
        } else {
                loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
                size_t retlen;
-               if (MTD_READ(nftl->mbd.mtd, ptr, 512, &retlen, buffer))
+               int res = mtd->read(mtd, ptr, 512, &retlen, buffer);
+
+               if (res < 0 && res != -EUCLEAN)
                        return -EIO;
        }
        return 0;
index 3b104ebb219ad9cbe816575ecd25d9f23b7844b3..067262ee8df0fa2683c7a7bfd8582919fc0f5909 100644 (file)
 
 char nftlmountrev[]="$Revision: 1.41 $";
 
+extern int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                        size_t *retlen, uint8_t *buf);
+extern int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+                         size_t *retlen, uint8_t *buf);
+
 /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
  *     various device information of the NFTL partition and Bad Unit Table. Update
  *     the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
@@ -45,6 +50,7 @@ static int find_boot_record(struct NFTLrecord *nftl)
        size_t retlen;
        u8 buf[SECTORSIZE];
        struct NFTLMediaHeader *mh = &nftl->MediaHdr;
+       struct mtd_info *mtd = nftl->mbd.mtd;
        unsigned int i;
 
         /* Assume logical EraseSize == physical erasesize for starting the scan.
@@ -65,7 +71,8 @@ static int find_boot_record(struct NFTLrecord *nftl)
 
                /* Check for ANAND header first. Then can whinge if it's found but later
                   checks fail */
-               ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf);
+               ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE,
+                               &retlen, buf);
                /* We ignore ret in case the ECC of the MediaHeader is invalid
                   (which is apparently acceptable) */
                if (retlen != SECTORSIZE) {
@@ -90,8 +97,9 @@ static int find_boot_record(struct NFTLrecord *nftl)
                }
 
                /* To be safer with BIOS, also use erase mark as discriminant */
-               if ((ret = MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
-                               8, &retlen, (char *)&h1) < 0)) {
+               if ((ret = nftl_read_oob(mtd, block * nftl->EraseSize +
+                                        SECTORSIZE + 8, 8, &retlen,
+                                        (char *)&h1) < 0)) {
                        printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n",
                               block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
                        continue;
@@ -109,8 +117,8 @@ static int find_boot_record(struct NFTLrecord *nftl)
                }
 
                /* Finally reread to check ECC */
-               if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE,
-                               &retlen, buf, (char *)&oob, NULL) < 0)) {
+               if ((ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE,
+                                    &retlen, buf) < 0)) {
                        printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n",
                               block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
                        continue;
@@ -228,9 +236,9 @@ device is already correct.
 The new DiskOnChip driver already scanned the bad block table.  Just query it.
                        if ((i & (SECTORSIZE - 1)) == 0) {
                                /* read one sector for every SECTORSIZE of blocks */
-                               if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize +
-                                                      i + SECTORSIZE, SECTORSIZE, &retlen, buf,
-                                                      (char *)&oob, NULL)) < 0) {
+                               if ((ret = mtd->read(nftl->mbd.mtd, block * nftl->EraseSize +
+                                                    i + SECTORSIZE, SECTORSIZE, &retlen,
+                                                    buf)) < 0) {
                                        printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n",
                                               ret);
                                        kfree(nftl->ReplUnitTable);
@@ -268,18 +276,22 @@ static int memcmpb(void *a, int c, int n)
 static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
                              int check_oob)
 {
-       int i;
-       size_t retlen;
        u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
+       struct mtd_info *mtd = nftl->mbd.mtd;
+       size_t retlen;
+       int i;
 
        for (i = 0; i < len; i += SECTORSIZE) {
-               if (MTD_READECC(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &nftl->oobinfo) < 0)
+               if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf))
                        return -1;
                if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
                        return -1;
 
                if (check_oob) {
-                       if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0)
+                       if(nftl_read_oob(mtd, address, mtd->oobsize,
+                                        &retlen, &buf[SECTORSIZE]) < 0)
+                               return -1;
+                       if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
                                return -1;
                }
                address += SECTORSIZE;
@@ -301,10 +313,11 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block)
        unsigned int nb_erases, erase_mark;
        struct nftl_uci1 uci;
        struct erase_info *instr = &nftl->instr;
+       struct mtd_info *mtd = nftl->mbd.mtd;
 
        /* Read the Unit Control Information #1 for Wear-Leveling */
-       if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
-                       8, &retlen, (char *)&uci) < 0)
+       if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8,
+                         8, &retlen, (char *)&uci) < 0)
                goto default_uci1;
 
        erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1));
@@ -321,7 +334,7 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block)
        instr->mtd = nftl->mbd.mtd;
        instr->addr = block * nftl->EraseSize;
        instr->len = nftl->EraseSize;
-       MTD_ERASE(nftl->mbd.mtd, instr);
+       mtd->erase(mtd, instr);
 
        if (instr->state == MTD_ERASE_FAILED) {
                printk("Error while formatting block %d\n", block);
@@ -343,8 +356,8 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block)
                        goto fail;
 
                uci.WearInfo = le32_to_cpu(nb_erases);
-               if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
-                                &retlen, (char *)&uci) < 0)
+               if (nftl_write_oob(mtd, block * nftl->EraseSize + SECTORSIZE +
+                                  8, 8, &retlen, (char *)&uci) < 0)
                        goto fail;
                return 0;
 fail:
@@ -365,6 +378,7 @@ fail:
  *     case. */
 static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block)
 {
+       struct mtd_info *mtd = nftl->mbd.mtd;
        unsigned int block, i, status;
        struct nftl_bci bci;
        int sectors_per_block;
@@ -374,8 +388,9 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b
        block = first_block;
        for (;;) {
                for (i = 0; i < sectors_per_block; i++) {
-                       if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i * SECTORSIZE,
-                                       8, &retlen, (char *)&bci) < 0)
+                       if (nftl_read_oob(mtd,
+                                         block * nftl->EraseSize + i * SECTORSIZE,
+                                         8, &retlen, (char *)&bci) < 0)
                                status = SECTOR_IGNORE;
                        else
                                status = bci.Status | bci.Status1;
@@ -394,9 +409,10 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b
                                        /* sector not free actually : mark it as SECTOR_IGNORE  */
                                        bci.Status = SECTOR_IGNORE;
                                        bci.Status1 = SECTOR_IGNORE;
-                                       MTD_WRITEOOB(nftl->mbd.mtd,
-                                                    block * nftl->EraseSize + i * SECTORSIZE,
-                                                    8, &retlen, (char *)&bci);
+                                       nftl_write_oob(mtd, block *
+                                                      nftl->EraseSize +
+                                                      i * SECTORSIZE, 8,
+                                                      &retlen, (char *)&bci);
                                }
                                break;
                        default:
@@ -481,13 +497,14 @@ static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
  *     1. */
 static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
 {
+       struct mtd_info *mtd = nftl->mbd.mtd;
        struct nftl_uci1 h1;
        unsigned int erase_mark;
        size_t retlen;
 
        /* check erase mark. */
-       if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
-                       &retlen, (char *)&h1) < 0)
+       if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
+                         &retlen, (char *)&h1) < 0)
                return -1;
 
        erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
@@ -501,8 +518,9 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
                h1.EraseMark = cpu_to_le16(ERASE_MARK);
                h1.EraseMark1 = cpu_to_le16(ERASE_MARK);
                h1.WearInfo = cpu_to_le32(0);
-               if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
-                                &retlen, (char *)&h1) < 0)
+               if (nftl_write_oob(mtd,
+                                  block * nftl->EraseSize + SECTORSIZE + 8, 8,
+                                  &retlen, (char *)&h1) < 0)
                        return -1;
        } else {
 #if 0
@@ -513,8 +531,8 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
                                                SECTORSIZE, 0) != 0)
                                return -1;
 
-                       if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i,
-                                       16, &retlen, buf) < 0)
+                       if (nftl_read_oob(mtd, block * nftl->EraseSize + i,
+                                         16, &retlen, buf) < 0)
                                return -1;
                        if (i == SECTORSIZE) {
                                /* skip erase mark */
@@ -540,11 +558,12 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
  */
 static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block)
 {
+       struct mtd_info *mtd = nftl->mbd.mtd;
        struct nftl_uci2 uci;
        size_t retlen;
 
-       if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
-                       8, &retlen, (char *)&uci) < 0)
+       if (nftl_read_oob(mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
+                         8, &retlen, (char *)&uci) < 0)
                return 0;
 
        return le16_to_cpu((uci.FoldMark | uci.FoldMark1));
@@ -558,6 +577,7 @@ int NFTL_mount(struct NFTLrecord *s)
        int chain_length, do_format_chain;
        struct nftl_uci0 h0;
        struct nftl_uci1 h1;
+       struct mtd_info *mtd = s->mbd.mtd;
        size_t retlen;
 
        /* search for NFTL MediaHeader and Spare NFTL Media Header */
@@ -582,10 +602,13 @@ int NFTL_mount(struct NFTLrecord *s)
 
                        for (;;) {
                                /* read the block header. If error, we format the chain */
-                               if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8,
-                                               &retlen, (char *)&h0) < 0 ||
-                                   MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8,
-                                               &retlen, (char *)&h1) < 0) {
+                               if (nftl_read_oob(mtd,
+                                                 block * s->EraseSize + 8, 8,
+                                                 &retlen, (char *)&h0) < 0 ||
+                                   nftl_read_oob(mtd,
+                                                 block * s->EraseSize +
+                                                 SECTORSIZE + 8, 8,
+                                                 &retlen, (char *)&h1) < 0) {
                                        s->ReplUnitTable[block] = BLOCK_NIL;
                                        do_format_chain = 1;
                                        break;
index 126ff6bf63d5c8b8cfc733b13f5656f758a40cd7..5930a03736d7557ab9bdfc9137bb604a863560d1 100644 (file)
@@ -29,6 +29,20 @@ config MTD_ONENAND_GENERIC
        help
          Support for OneNAND flash via platform device driver.
 
+config MTD_ONENAND_OTP
+       bool "OneNAND OTP Support"
+       depends on MTD_ONENAND
+       help
+         One Block of the NAND Flash Array memory is reserved as
+         a One-Time Programmable Block memory area.
+         Also, 1st Block of NAND Flash Array can be used as OTP.
+
+         The OTP block can be read, programmed and locked using the same
+         operations as any other NAND Flash Array memory block.
+         OTP block cannot be erased.
+
+         OTP block is fully-guaranteed to be a valid block.
+
 config MTD_ONENAND_SYNC_READ
        bool "OneNAND Sync. Burst Read Support"
        depends on ARCH_OMAP
index a53a73fc2a5af0d0a07a8f880793e2b8c37c4489..84ec40d254386f366a3d4e2f92ad54cda2663eb9 100644 (file)
@@ -23,8 +23,7 @@
 /**
  * onenand_oob_64 - oob info for large (2KB) page
  */
-static struct nand_oobinfo onenand_oob_64 = {
-       .useecc         = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout onenand_oob_64 = {
        .eccbytes       = 20,
        .eccpos         = {
                8, 9, 10, 11, 12,
@@ -34,14 +33,14 @@ static struct nand_oobinfo onenand_oob_64 = {
                },
        .oobfree        = {
                {2, 3}, {14, 2}, {18, 3}, {30, 2},
-               {24, 3}, {46, 2}, {40, 3}, {62, 2} }
+               {34, 3}, {46, 2}, {50, 3}, {62, 2}
+       }
 };
 
 /**
  * onenand_oob_32 - oob info for middle (1KB) page
  */
-static struct nand_oobinfo onenand_oob_32 = {
-       .useecc         = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout onenand_oob_32 = {
        .eccbytes       = 10,
        .eccpos         = {
                8, 9, 10, 11, 12,
@@ -190,7 +189,7 @@ static int onenand_buffer_address(int dataram1, int sectors, int count)
 static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len)
 {
        struct onenand_chip *this = mtd->priv;
-       int value, readcmd = 0;
+       int value, readcmd = 0, block_cmd = 0;
        int block, page;
        /* Now we use page size operation */
        int sectors = 4, count = 4;
@@ -206,6 +205,8 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
 
        case ONENAND_CMD_ERASE:
        case ONENAND_CMD_BUFFERRAM:
+       case ONENAND_CMD_OTP_ACCESS:
+               block_cmd = 1;
                block = (int) (addr >> this->erase_shift);
                page = -1;
                break;
@@ -233,6 +234,12 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
                /* Write 'DFS, FBA' of Flash */
                value = onenand_block_address(this, block);
                this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
+
+               if (block_cmd) {
+                       /* Select DataRAM for DDP */
+                       value = onenand_bufferram_address(this, block);
+                       this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
+               }
        }
 
        if (page != -1) {
@@ -301,6 +308,7 @@ static int onenand_wait(struct mtd_info *mtd, int state)
 
                if (state != FL_READING)
                        cond_resched();
+               touch_softlockup_watchdog();
        }
        /* To get correct interrupt status in timeout case */
        interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
@@ -344,7 +352,7 @@ static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
 
        if (ONENAND_CURRENT_BUFFERRAM(this)) {
                if (area == ONENAND_DATARAM)
-                       return mtd->oobblock;
+                       return mtd->writesize;
                if (area == ONENAND_SPARERAM)
                        return mtd->oobsize;
        }
@@ -372,6 +380,17 @@ static int onenand_read_bufferram(struct mtd_info *mtd, int area,
 
        bufferram += onenand_bufferram_offset(mtd, area);
 
+       if (ONENAND_CHECK_BYTE_ACCESS(count)) {
+               unsigned short word;
+
+               /* Align with word(16-bit) size */
+               count--;
+
+               /* Read word and save byte */
+               word = this->read_word(bufferram + offset + count);
+               buffer[count] = (word & 0xff);
+       }
+
        memcpy(buffer, bufferram + offset, count);
 
        return 0;
@@ -399,6 +418,17 @@ static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area,
 
        this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ);
 
+       if (ONENAND_CHECK_BYTE_ACCESS(count)) {
+               unsigned short word;
+
+               /* Align with word(16-bit) size */
+               count--;
+
+               /* Read word and save byte */
+               word = this->read_word(bufferram + offset + count);
+               buffer[count] = (word & 0xff);
+       }
+
        memcpy(buffer, bufferram + offset, count);
 
        this->mmcontrol(mtd, 0);
@@ -426,6 +456,22 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area,
 
        bufferram += onenand_bufferram_offset(mtd, area);
 
+       if (ONENAND_CHECK_BYTE_ACCESS(count)) {
+               unsigned short word;
+               int byte_offset;
+
+               /* Align with word(16-bit) size */
+               count--;
+
+               /* Calculate byte access offset */
+               byte_offset = offset + count;
+
+               /* Read word and save byte */
+               word = this->read_word(bufferram + byte_offset);
+               word = (word & ~0xff) | buffer[count];
+               this->write_word(word, bufferram + byte_offset);
+       }
+
        memcpy(bufferram + offset, buffer, count);
 
        return 0;
@@ -549,31 +595,28 @@ static void onenand_release_device(struct mtd_info *mtd)
 }
 
 /**
- * onenand_read_ecc - [MTD Interface] Read data with ECC
+ * onenand_read - [MTD Interface] Read data from flash
  * @param mtd          MTD device structure
  * @param from         offset to read from
  * @param len          number of bytes to read
  * @param retlen       pointer to variable to store the number of read bytes
  * @param buf          the databuffer to put data
- * @param oob_buf      filesystem supplied oob data buffer
- * @param oobsel       oob selection structure
  *
- * OneNAND read with ECC
- */
-static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
-       size_t *retlen, u_char *buf,
-       u_char *oob_buf, struct nand_oobinfo *oobsel)
+ * Read with ecc
+*/
+static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
+       size_t *retlen, u_char *buf)
 {
        struct onenand_chip *this = mtd->priv;
        int read = 0, column;
        int thislen;
        int ret = 0;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+       DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
 
        /* Do not allow reads past end of device */
        if ((from + len) > mtd->size) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: Attempt read beyond end of device\n");
+               DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: Attempt read beyond end of device\n");
                *retlen = 0;
                return -EINVAL;
        }
@@ -584,14 +627,14 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
        /* TODO handling oob */
 
        while (read < len) {
-               thislen = min_t(int, mtd->oobblock, len - read);
+               thislen = min_t(int, mtd->writesize, len - read);
 
-               column = from & (mtd->oobblock - 1);
-               if (column + thislen > mtd->oobblock)
-                       thislen = mtd->oobblock - column;
+               column = from & (mtd->writesize - 1);
+               if (column + thislen > mtd->writesize)
+                       thislen = mtd->writesize - column;
 
                if (!onenand_check_bufferram(mtd, from)) {
-                       this->command(mtd, ONENAND_CMD_READ, from, mtd->oobblock);
+                       this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
 
                        ret = this->wait(mtd, FL_READING);
                        /* First copy data and check return value for ECC handling */
@@ -606,7 +649,7 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
                        break;
 
                if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: read failed = %d\n", ret);
+                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret);
                        goto out;
                }
 
@@ -628,23 +671,7 @@ out:
 }
 
 /**
- * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc
- * @param mtd          MTD device structure
- * @param from         offset to read from
- * @param len          number of bytes to read
- * @param retlen       pointer to variable to store the number of read bytes
- * @param buf          the databuffer to put data
- *
- * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL
-*/
-static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
-       size_t *retlen, u_char *buf)
-{
-       return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
-}
-
-/**
- * onenand_read_oob - [MTD Interface] OneNAND read out-of-band
+ * onenand_do_read_oob - [MTD Interface] OneNAND read out-of-band
  * @param mtd          MTD device structure
  * @param from         offset to read from
  * @param len          number of bytes to read
@@ -653,8 +680,8 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
  *
  * OneNAND read out-of-band data from the spare area
  */
-static int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
-       size_t *retlen, u_char *buf)
+int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+                       size_t *retlen, u_char *buf)
 {
        struct onenand_chip *this = mtd->priv;
        int read = 0, thislen, column;
@@ -704,7 +731,7 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
                /* Read more? */
                if (read < len) {
                        /* Page size */
-                       from += mtd->oobblock;
+                       from += mtd->writesize;
                        column = 0;
                }
        }
@@ -717,7 +744,52 @@ out:
        return ret;
 }
 
+/**
+ * onenand_read_oob - [MTD Interface] NAND write data and/or out-of-band
+ * @mtd:       MTD device structure
+ * @from:      offset to read from
+ * @ops:       oob operation description structure
+ */
+static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
+                           struct mtd_oob_ops *ops)
+{
+       BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+       return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->len,
+                                  &ops->retlen, ops->oobbuf);
+}
+
 #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
+/**
+ * onenand_verify_oob - [GENERIC] verify the oob contents after a write
+ * @param mtd          MTD device structure
+ * @param buf          the databuffer to verify
+ * @param to           offset to read from
+ * @param len          number of bytes to read and compare
+ *
+ */
+static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to, int len)
+{
+       struct onenand_chip *this = mtd->priv;
+       char *readp = this->page_buf;
+       int column = to & (mtd->oobsize - 1);
+       int status, i;
+
+       this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
+       onenand_update_bufferram(mtd, to, 0);
+       status = this->wait(mtd, FL_READING);
+       if (status)
+               return status;
+
+       this->read_bufferram(mtd, ONENAND_SPARERAM, readp, column, len);
+
+       for(i = 0; i < len; i++)
+               if (buf[i] != 0xFF && buf[i] != readp[i])
+                       return -EBADMSG;
+
+       return 0;
+}
+
 /**
  * onenand_verify_page - [GENERIC] verify the chip contents after a write
  * @param mtd          MTD device structure
@@ -731,7 +803,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
        void __iomem *dataram0, *dataram1;
        int ret = 0;
 
-       this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock);
+       this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
 
        ret = this->wait(mtd, FL_READING);
        if (ret)
@@ -741,53 +813,51 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr)
 
        /* Check, if the two dataram areas are same */
        dataram0 = this->base + ONENAND_DATARAM;
-       dataram1 = dataram0 + mtd->oobblock;
+       dataram1 = dataram0 + mtd->writesize;
 
-       if (memcmp(dataram0, dataram1, mtd->oobblock))
+       if (memcmp(dataram0, dataram1, mtd->writesize))
                return -EBADMSG;
 
        return 0;
 }
 #else
 #define onenand_verify_page(...)       (0)
+#define onenand_verify_oob(...)                (0)
 #endif
 
-#define NOTALIGNED(x)  ((x & (mtd->oobblock - 1)) != 0)
+#define NOTALIGNED(x)  ((x & (mtd->writesize - 1)) != 0)
 
 /**
- * onenand_write_ecc - [MTD Interface] OneNAND write with ECC
+ * onenand_write - [MTD Interface] write buffer to FLASH
  * @param mtd          MTD device structure
  * @param to           offset to write to
  * @param len          number of bytes to write
  * @param retlen       pointer to variable to store the number of written bytes
  * @param buf          the data to write
- * @param eccbuf       filesystem supplied oob data buffer
- * @param oobsel       oob selection structure
  *
- * OneNAND write with ECC
+ * Write with ECC
  */
-static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
-       size_t *retlen, const u_char *buf,
-       u_char *eccbuf, struct nand_oobinfo *oobsel)
+static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
+       size_t *retlen, const u_char *buf)
 {
        struct onenand_chip *this = mtd->priv;
        int written = 0;
        int ret = 0;
 
-       DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+       DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
 
        /* Initialize retlen, in case of early exit */
        *retlen = 0;
 
        /* Do not allow writes past end of device */
        if (unlikely((to + len) > mtd->size)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt write to past end of device\n");
+               DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt write to past end of device\n");
                return -EINVAL;
        }
 
        /* Reject writes, which are not page aligned */
         if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
-                DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt to write not page aligned data\n");
+                DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt to write not page aligned data\n");
                 return -EINVAL;
         }
 
@@ -796,20 +866,20 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
 
        /* Loop until all data write */
        while (written < len) {
-               int thislen = min_t(int, mtd->oobblock, len - written);
+               int thislen = min_t(int, mtd->writesize, len - written);
 
-               this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
+               this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);
 
                this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
                this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
 
-               this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
+               this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
 
                onenand_update_bufferram(mtd, to, 1);
 
                ret = this->wait(mtd, FL_WRITING);
                if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: write filaed %d\n", ret);
+                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret);
                        goto out;
                }
 
@@ -818,7 +888,7 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
                /* Only check verify write turn on */
                ret = onenand_verify_page(mtd, (u_char *) buf, to);
                if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret);
+                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);
                        goto out;
                }
 
@@ -839,24 +909,7 @@ out:
 }
 
 /**
- * onenand_write - [MTD Interface] compability function for onenand_write_ecc
- * @param mtd          MTD device structure
- * @param to           offset to write to
- * @param len          number of bytes to write
- * @param retlen       pointer to variable to store the number of written bytes
- * @param buf          the data to write
- *
- * This function simply calls onenand_write_ecc
- * with oob buffer and oobsel = NULL
- */
-static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
-       size_t *retlen, const u_char *buf)
-{
-       return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL);
-}
-
-/**
- * onenand_write_oob - [MTD Interface] OneNAND write out-of-band
+ * onenand_do_write_oob - [Internal] OneNAND write out-of-band
  * @param mtd          MTD device structure
  * @param to           offset to write to
  * @param len          number of bytes to write
@@ -865,11 +918,11 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
  *
  * OneNAND write out-of-band
  */
-static int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
-       size_t *retlen, const u_char *buf)
+static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
+                               size_t *retlen, const u_char *buf)
 {
        struct onenand_chip *this = mtd->priv;
-       int column, status;
+       int column, ret = 0;
        int written = 0;
 
        DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
@@ -894,16 +947,27 @@ static int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
 
                this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
 
-               this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
-               this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
+               /* We send data to spare ram with oobsize
+                * to prevent byte access */
+               memset(this->page_buf, 0xff, mtd->oobsize);
+               memcpy(this->page_buf + column, buf, thislen);
+               this->write_bufferram(mtd, ONENAND_SPARERAM, this->page_buf, 0, mtd->oobsize);
 
                this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
 
                onenand_update_bufferram(mtd, to, 0);
 
-               status = this->wait(mtd, FL_WRITING);
-               if (status)
+               ret = this->wait(mtd, FL_WRITING);
+               if (ret) {
+                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: write filaed %d\n", ret);
+                       goto out;
+               }
+
+               ret = onenand_verify_oob(mtd, buf, to, thislen);
+               if (ret) {
+                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: verify failed %d\n", ret);
                        goto out;
+               }
 
                written += thislen;
 
@@ -920,145 +984,22 @@ out:
 
        *retlen = written;
 
-       return 0;
+       return ret;
 }
 
 /**
- * onenand_writev_ecc - [MTD Interface] write with iovec with ecc
- * @param mtd          MTD device structure
- * @param vecs         the iovectors to write
- * @param count                number of vectors
- * @param to           offset to write to
- * @param retlen       pointer to variable to store the number of written bytes
- * @param eccbuf       filesystem supplied oob data buffer
- * @param oobsel       oob selection structure
- *
- * OneNAND write with iovec with ecc
+ * onenand_write_oob - [MTD Interface] NAND write data and/or out-of-band
+ * @mtd:       MTD device structure
+ * @from:      offset to read from
+ * @ops:       oob operation description structure
  */
-static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
-       unsigned long count, loff_t to, size_t *retlen,
-       u_char *eccbuf, struct nand_oobinfo *oobsel)
+static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
+                            struct mtd_oob_ops *ops)
 {
-       struct onenand_chip *this = mtd->priv;
-       unsigned char *pbuf;
-       size_t total_len, len;
-       int i, written = 0;
-       int ret = 0;
-
-       /* Preset written len for early exit */
-       *retlen = 0;
-
-       /* Calculate total length of data */
-       total_len = 0;
-       for (i = 0; i < count; i++)
-               total_len += vecs[i].iov_len;
-
-       DEBUG(MTD_DEBUG_LEVEL3, "onenand_writev_ecc: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count);
-
-       /* Do not allow write past end of the device */
-       if (unlikely((to + total_len) > mtd->size)) {
-               DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempted write past end of device\n");
-               return -EINVAL;
-       }
-
-       /* Reject writes, which are not page aligned */
-        if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(total_len))) {
-                DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempt to write not page aligned data\n");
-                return -EINVAL;
-        }
-
-       /* Grab the lock and see if the device is available */
-       onenand_get_device(mtd, FL_WRITING);
-
-       /* TODO handling oob */
-
-       /* Loop until all keve's data has been written */
-       len = 0;
-       while (count) {
-               pbuf = this->page_buf;
-               /*
-                * If the given tuple is >= pagesize then
-                * write it out from the iov
-                */
-               if ((vecs->iov_len - len) >= mtd->oobblock) {
-                       pbuf = vecs->iov_base + len;
-
-                       len += mtd->oobblock;
-
-                       /* Check, if we have to switch to the next tuple */
-                       if (len >= (int) vecs->iov_len) {
-                               vecs++;
-                               len = 0;
-                               count--;
-                       }
-               } else {
-                       int cnt = 0, thislen;
-                       while (cnt < mtd->oobblock) {
-                               thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len);
-                               memcpy(this->page_buf + cnt, vecs->iov_base + len, thislen);
-                               cnt += thislen;
-                               len += thislen;
-
-                               /* Check, if we have to switch to the next tuple */
-                               if (len >= (int) vecs->iov_len) {
-                                       vecs++;
-                                       len = 0;
-                                       count--;
-                               }
-                       }
-               }
-
-               this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
+       BUG_ON(ops->mode != MTD_OOB_PLACE);
 
-               this->write_bufferram(mtd, ONENAND_DATARAM, pbuf, 0, mtd->oobblock);
-               this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
-
-               this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
-
-               onenand_update_bufferram(mtd, to, 1);
-
-               ret = this->wait(mtd, FL_WRITING);
-               if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: write failed %d\n", ret);
-                       goto out;
-               }
-
-
-               /* Only check verify write turn on */
-               ret = onenand_verify_page(mtd, (u_char *) pbuf, to);
-               if (ret) {
-                       DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: verify failed %d\n", ret);
-                       goto out;
-               }
-
-               written += mtd->oobblock;
-
-               to += mtd->oobblock;
-       }
-
-out:
-       /* Deselect and wakt up anyone waiting on the device */
-       onenand_release_device(mtd);
-
-       *retlen = written;
-
-       return 0;
-}
-
-/**
- * onenand_writev - [MTD Interface] compabilty function for onenand_writev_ecc
- * @param mtd          MTD device structure
- * @param vecs         the iovectors to write
- * @param count                number of vectors
- * @param to           offset to write to
- * @param retlen       pointer to variable to store the number of written bytes
- *
- * OneNAND write with kvec. This just calls the ecc function
- */
-static int onenand_writev(struct mtd_info *mtd, const struct kvec *vecs,
-       unsigned long count, loff_t to, size_t *retlen)
-{
-       return onenand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL);
+       return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->len,
+                                   &ops->retlen, ops->oobbuf);
 }
 
 /**
@@ -1227,7 +1168,7 @@ static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 
         /* We write two bytes, so we dont have to mess with 16 bit access */
         ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
-        return mtd->write_oob(mtd, ofs , 2, &retlen, buf);
+        return onenand_do_write_oob(mtd, ofs , 2, &retlen, buf);
 }
 
 /**
@@ -1324,6 +1265,304 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
        return 0;
 }
 
+#ifdef CONFIG_MTD_ONENAND_OTP
+
+/* Interal OTP operation */
+typedef int (*otp_op_t)(struct mtd_info *mtd, loff_t form, size_t len,
+               size_t *retlen, u_char *buf);
+
+/**
+ * do_otp_read - [DEFAULT] Read OTP block area
+ * @param mtd          MTD device structure
+ * @param from         The offset to read
+ * @param len          number of bytes to read
+ * @param retlen       pointer to variable to store the number of readbytes
+ * @param buf          the databuffer to put/get data
+ *
+ * Read OTP block area.
+ */
+static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
+               size_t *retlen, u_char *buf)
+{
+       struct onenand_chip *this = mtd->priv;
+       int ret;
+
+       /* Enter OTP access mode */
+       this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+       this->wait(mtd, FL_OTPING);
+
+       ret = mtd->read(mtd, from, len, retlen, buf);
+
+       /* Exit OTP access mode */
+       this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+       this->wait(mtd, FL_RESETING);
+
+       return ret;
+}
+
+/**
+ * do_otp_write - [DEFAULT] Write OTP block area
+ * @param mtd          MTD device structure
+ * @param from         The offset to write
+ * @param len          number of bytes to write
+ * @param retlen       pointer to variable to store the number of write bytes
+ * @param buf          the databuffer to put/get data
+ *
+ * Write OTP block area.
+ */
+static int do_otp_write(struct mtd_info *mtd, loff_t from, size_t len,
+               size_t *retlen, u_char *buf)
+{
+       struct onenand_chip *this = mtd->priv;
+       unsigned char *pbuf = buf;
+       int ret;
+
+       /* Force buffer page aligned */
+       if (len < mtd->writesize) {
+               memcpy(this->page_buf, buf, len);
+               memset(this->page_buf + len, 0xff, mtd->writesize - len);
+               pbuf = this->page_buf;
+               len = mtd->writesize;
+       }
+
+       /* Enter OTP access mode */
+       this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+       this->wait(mtd, FL_OTPING);
+
+       ret = mtd->write(mtd, from, len, retlen, pbuf);
+
+       /* Exit OTP access mode */
+       this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+       this->wait(mtd, FL_RESETING);
+
+       return ret;
+}
+
+/**
+ * do_otp_lock - [DEFAULT] Lock OTP block area
+ * @param mtd          MTD device structure
+ * @param from         The offset to lock
+ * @param len          number of bytes to lock
+ * @param retlen       pointer to variable to store the number of lock bytes
+ * @param buf          the databuffer to put/get data
+ *
+ * Lock OTP block area.
+ */
+static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
+               size_t *retlen, u_char *buf)
+{
+       struct onenand_chip *this = mtd->priv;
+       int ret;
+
+       /* Enter OTP access mode */
+       this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+       this->wait(mtd, FL_OTPING);
+
+       ret = onenand_do_write_oob(mtd, from, len, retlen, buf);
+
+       /* Exit OTP access mode */
+       this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+       this->wait(mtd, FL_RESETING);
+
+       return ret;
+}
+
+/**
+ * onenand_otp_walk - [DEFAULT] Handle OTP operation
+ * @param mtd          MTD device structure
+ * @param from         The offset to read/write
+ * @param len          number of bytes to read/write
+ * @param retlen       pointer to variable to store the number of read bytes
+ * @param buf          the databuffer to put/get data
+ * @param action       do given action
+ * @param mode         specify user and factory
+ *
+ * Handle OTP operation.
+ */
+static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
+                       size_t *retlen, u_char *buf,
+                       otp_op_t action, int mode)
+{
+       struct onenand_chip *this = mtd->priv;
+       int otp_pages;
+       int density;
+       int ret = 0;
+
+       *retlen = 0;
+
+       density = this->device_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+       if (density < ONENAND_DEVICE_DENSITY_512Mb)
+               otp_pages = 20;
+       else
+               otp_pages = 10;
+
+       if (mode == MTD_OTP_FACTORY) {
+               from += mtd->writesize * otp_pages;
+               otp_pages = 64 - otp_pages;
+       }
+
+       /* Check User/Factory boundary */
+       if (((mtd->writesize * otp_pages) - (from + len)) < 0)
+               return 0;
+
+       while (len > 0 && otp_pages > 0) {
+               if (!action) {  /* OTP Info functions */
+                       struct otp_info *otpinfo;
+
+                       len -= sizeof(struct otp_info);
+                       if (len <= 0)
+                               return -ENOSPC;
+
+                       otpinfo = (struct otp_info *) buf;
+                       otpinfo->start = from;
+                       otpinfo->length = mtd->writesize;
+                       otpinfo->locked = 0;
+
+                       from += mtd->writesize;
+                       buf += sizeof(struct otp_info);
+                       *retlen += sizeof(struct otp_info);
+               } else {
+                       size_t tmp_retlen;
+                       int size = len;
+
+                       ret = action(mtd, from, len, &tmp_retlen, buf);
+
+                       buf += size;
+                       len -= size;
+                       *retlen += size;
+
+                       if (ret < 0)
+                               return ret;
+               }
+               otp_pages--;
+       }
+
+       return 0;
+}
+
+/**
+ * onenand_get_fact_prot_info - [MTD Interface] Read factory OTP info
+ * @param mtd          MTD device structure
+ * @param buf          the databuffer to put/get data
+ * @param len          number of bytes to read
+ *
+ * Read factory OTP info.
+ */
+static int onenand_get_fact_prot_info(struct mtd_info *mtd,
+                       struct otp_info *buf, size_t len)
+{
+       size_t retlen;
+       int ret;
+
+       ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_FACTORY);
+
+       return ret ? : retlen;
+}
+
+/**
+ * onenand_read_fact_prot_reg - [MTD Interface] Read factory OTP area
+ * @param mtd          MTD device structure
+ * @param from         The offset to read
+ * @param len          number of bytes to read
+ * @param retlen       pointer to variable to store the number of read bytes
+ * @param buf          the databuffer to put/get data
+ *
+ * Read factory OTP area.
+ */
+static int onenand_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
+                       size_t len, size_t *retlen, u_char *buf)
+{
+       return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_FACTORY);
+}
+
+/**
+ * onenand_get_user_prot_info - [MTD Interface] Read user OTP info
+ * @param mtd          MTD device structure
+ * @param buf          the databuffer to put/get data
+ * @param len          number of bytes to read
+ *
+ * Read user OTP info.
+ */
+static int onenand_get_user_prot_info(struct mtd_info *mtd,
+                       struct otp_info *buf, size_t len)
+{
+       size_t retlen;
+       int ret;
+
+       ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_USER);
+
+       return ret ? : retlen;
+}
+
+/**
+ * onenand_read_user_prot_reg - [MTD Interface] Read user OTP area
+ * @param mtd          MTD device structure
+ * @param from         The offset to read
+ * @param len          number of bytes to read
+ * @param retlen       pointer to variable to store the number of read bytes
+ * @param buf          the databuffer to put/get data
+ *
+ * Read user OTP area.
+ */
+static int onenand_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
+                       size_t len, size_t *retlen, u_char *buf)
+{
+       return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_USER);
+}
+
+/**
+ * onenand_write_user_prot_reg - [MTD Interface] Write user OTP area
+ * @param mtd          MTD device structure
+ * @param from         The offset to write
+ * @param len          number of bytes to write
+ * @param retlen       pointer to variable to store the number of write bytes
+ * @param buf          the databuffer to put/get data
+ *
+ * Write user OTP area.
+ */
+static int onenand_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
+                       size_t len, size_t *retlen, u_char *buf)
+{
+       return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_write, MTD_OTP_USER);
+}
+
+/**
+ * onenand_lock_user_prot_reg - [MTD Interface] Lock user OTP area
+ * @param mtd          MTD device structure
+ * @param from         The offset to lock
+ * @param len          number of bytes to unlock
+ *
+ * Write lock mark on spare area in page 0 in OTP block
+ */
+static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
+                       size_t len)
+{
+       unsigned char oob_buf[64];
+       size_t retlen;
+       int ret;
+
+       memset(oob_buf, 0xff, mtd->oobsize);
+       /*
+        * Note: OTP lock operation
+        *       OTP block : 0xXXFC
+        *       1st block : 0xXXF3 (If chip support)
+        *       Both      : 0xXXF0 (If chip support)
+        */
+       oob_buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;
+
+       /*
+        * Write lock mark to 8th word of sector0 of page0 of the spare0.
+        * We write 16 bytes spare area instead of 2 bytes.
+        */
+       from = 0;
+       len = 16;
+
+       ret = onenand_otp_walk(mtd, from, len, &retlen, oob_buf, do_otp_lock, MTD_OTP_USER);
+
+       return ret ? : retlen;
+}
+#endif /* CONFIG_MTD_ONENAND_OTP */
+
 /**
  * onenand_print_device_info - Print device ID
  * @param device        device ID
@@ -1423,15 +1662,15 @@ static int onenand_probe(struct mtd_info *mtd)
 
        /* OneNAND page size & block size */
        /* The data buffer size is equal to page size */
-       mtd->oobblock = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
-       mtd->oobsize = mtd->oobblock >> 5;
+       mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
+       mtd->oobsize = mtd->writesize >> 5;
        /* Pagers per block is always 64 in OneNAND */
-       mtd->erasesize = mtd->oobblock << 6;
+       mtd->erasesize = mtd->writesize << 6;
 
        this->erase_shift = ffs(mtd->erasesize) - 1;
-       this->page_shift = ffs(mtd->oobblock) - 1;
+       this->page_shift = ffs(mtd->writesize) - 1;
        this->ppb_shift = (this->erase_shift - this->page_shift);
-       this->page_mask = (mtd->erasesize / mtd->oobblock) - 1;
+       this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
 
        /* REVIST: Multichip handling */
 
@@ -1475,7 +1714,6 @@ static void onenand_resume(struct mtd_info *mtd)
                                "in suspended state\n");
 }
 
-
 /**
  * onenand_scan - [OneNAND Interface] Scan for the OneNAND device
  * @param mtd          MTD device structure
@@ -1522,7 +1760,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
        /* Allocate buffers, if necessary */
        if (!this->page_buf) {
                size_t len;
-               len = mtd->oobblock + mtd->oobsize;
+               len = mtd->writesize + mtd->oobsize;
                this->page_buf = kmalloc(len, GFP_KERNEL);
                if (!this->page_buf) {
                        printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
@@ -1537,40 +1775,42 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 
        switch (mtd->oobsize) {
        case 64:
-               this->autooob = &onenand_oob_64;
+               this->ecclayout = &onenand_oob_64;
                break;
 
        case 32:
-               this->autooob = &onenand_oob_32;
+               this->ecclayout = &onenand_oob_32;
                break;
 
        default:
                printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
                        mtd->oobsize);
                /* To prevent kernel oops */
-               this->autooob = &onenand_oob_32;
+               this->ecclayout = &onenand_oob_32;
                break;
        }
 
-       memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
+       mtd->ecclayout = this->ecclayout;
 
        /* Fill in remaining MTD driver data */
        mtd->type = MTD_NANDFLASH;
-       mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
+       mtd->flags = MTD_CAP_NANDFLASH;
        mtd->ecctype = MTD_ECC_SW;
        mtd->erase = onenand_erase;
        mtd->point = NULL;
        mtd->unpoint = NULL;
        mtd->read = onenand_read;
        mtd->write = onenand_write;
-       mtd->read_ecc = onenand_read_ecc;
-       mtd->write_ecc = onenand_write_ecc;
        mtd->read_oob = onenand_read_oob;
        mtd->write_oob = onenand_write_oob;
-       mtd->readv = NULL;
-       mtd->readv_ecc = NULL;
-       mtd->writev = onenand_writev;
-       mtd->writev_ecc = onenand_writev_ecc;
+#ifdef CONFIG_MTD_ONENAND_OTP
+       mtd->get_fact_prot_info = onenand_get_fact_prot_info;
+       mtd->read_fact_prot_reg = onenand_read_fact_prot_reg;
+       mtd->get_user_prot_info = onenand_get_user_prot_info;
+       mtd->read_user_prot_reg = onenand_read_user_prot_reg;
+       mtd->write_user_prot_reg = onenand_write_user_prot_reg;
+       mtd->lock_user_prot_reg = onenand_lock_user_prot_reg;
+#endif
        mtd->sync = onenand_sync;
        mtd->lock = NULL;
        mtd->unlock = onenand_unlock;
index 4510d3361eaa82f77ddca510bb4fa460a26cb3f1..1b00dac3d7d601dc6305e52ed9067a94e7a78aaf 100644 (file)
@@ -17,6 +17,9 @@
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/compatmac.h>
 
+extern int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+                              size_t *retlen, u_char *buf);
+
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
  * @param buf          the buffer to search
@@ -87,13 +90,13 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 
                        /* No need to read pages fully,
                         * just read required OOB bytes */
-                       ret = mtd->read_oob(mtd, from + j * mtd->oobblock + bd->offs,
-                                               readlen, &retlen, &buf[0]);
+                       ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs,
+                                                 readlen, &retlen, &buf[0]);
 
                        if (ret)
                                return ret;
 
-                       if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+                       if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
                                bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
                                printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
                                        i >> 1, (unsigned int) from);
index c077d2ec9cddbe5ca19fba9e7acb53f20ed4e890..5b58523e4d4ecd597c8d72e63ae702a7b5d02389 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: redboot.c,v 1.19 2005/12/01 10:03:51 dwmw2 Exp $
+ * $Id: redboot.c,v 1.21 2006/03/30 18:34:37 bjd Exp $
  *
  * Parse RedBoot-style Flash Image System (FIS) tables and
  * produce a Linux partition array to match.
 
 struct fis_image_desc {
     unsigned char name[16];      // Null terminated name
-    unsigned long flash_base;    // Address within FLASH of image
-    unsigned long mem_base;      // Address in memory where it executes
-    unsigned long size;          // Length of image
-    unsigned long entry_point;   // Execution entry point
-    unsigned long data_length;   // Length of actual data
-    unsigned char _pad[256-(16+7*sizeof(unsigned long))];
-    unsigned long desc_cksum;    // Checksum over image descriptor
-    unsigned long file_cksum;    // Checksum over image data
+    uint32_t     flash_base;    // Address within FLASH of image
+    uint32_t     mem_base;      // Address in memory where it executes
+    uint32_t     size;          // Length of image
+    uint32_t     entry_point;   // Execution entry point
+    uint32_t     data_length;   // Length of actual data
+    unsigned char _pad[256-(16+7*sizeof(uint32_t))];
+    uint32_t     desc_cksum;    // Checksum over image descriptor
+    uint32_t     file_cksum;    // Checksum over image data
 };
 
 struct fis_list {
index a3e00a4635a5392180290e6d9b41d6bfd2fb07a8..fa4362fb4dd8a2b7260b75ae66c0866dcb472233 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2005  Sean Young <sean@mess.org>
  *
- * $Id: rfd_ftl.c,v 1.5 2005/11/07 11:14:21 gleixner Exp $
+ * $Id: rfd_ftl.c,v 1.8 2006/01/15 12:51:44 sean Exp $
  *
  * This type of flash translation layer (FTL) is used by the Embedded BIOS
  * by General Software. It is known as the Resident Flash Disk (RFD), see:
@@ -61,6 +61,7 @@ struct block {
                BLOCK_OK,
                BLOCK_ERASING,
                BLOCK_ERASED,
+               BLOCK_UNUSED,
                BLOCK_FAILED
        } state;
        int free_sectors;
@@ -99,10 +100,8 @@ static int build_block_map(struct partition *part, int block_no)
        block->offset = part->block_size * block_no;
 
        if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) {
-               block->state = BLOCK_ERASED; /* assumption */
-               block->free_sectors = part->data_sectors_per_block;
-               part->reserved_block = block_no;
-               return 1;
+               block->state = BLOCK_UNUSED;
+               return -ENOENT;
        }
 
        block->state = BLOCK_OK;
@@ -124,7 +123,7 @@ static int build_block_map(struct partition *part, int block_no)
                        entry = 0;
 
                if (entry >= part->sector_count) {
-                       printk(KERN_NOTICE PREFIX
+                       printk(KERN_WARNING PREFIX
                                "'%s': unit #%d: entry %d corrupt, "
                                "sector %d out of range\n",
                                part->mbd.mtd->name, block_no, i, entry);
@@ -132,7 +131,7 @@ static int build_block_map(struct partition *part, int block_no)
                }
 
                if (part->sector_map[entry] != -1) {
-                       printk(KERN_NOTICE PREFIX
+                       printk(KERN_WARNING PREFIX
                                "'%s': more than one entry for sector %d\n",
                                part->mbd.mtd->name, entry);
                        part->errors = 1;
@@ -167,7 +166,7 @@ static int scan_header(struct partition *part)
        /* each erase block has three bytes header, followed by the map */
        part->header_sectors_per_block =
                        ((HEADER_MAP_OFFSET + sectors_per_block) *
-                       sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;
+                       sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;
 
        part->data_sectors_per_block = sectors_per_block -
                        part->header_sectors_per_block;
@@ -226,7 +225,7 @@ static int scan_header(struct partition *part)
        }
 
        if (part->reserved_block == -1) {
-               printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n",
+               printk(KERN_WARNING PREFIX "'%s': no empty erase unit found\n",
                                part->mbd.mtd->name);
 
                part->errors = 1;
@@ -315,7 +314,7 @@ static void erase_callback(struct erase_info *erase)
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_NOTICE PREFIX "'%s': unable to write RFD "
+               printk(KERN_ERR PREFIX "'%s': unable to write RFD "
                                "header at 0x%lx\n",
                                part->mbd.mtd->name,
                                part->blocks[i].offset);
@@ -348,7 +347,7 @@ static int erase_block(struct partition *part, int block)
        rc = part->mbd.mtd->erase(part->mbd.mtd, erase);
 
        if (rc) {
-               printk(KERN_WARNING PREFIX "erase of region %x,%x on '%s' "
+               printk(KERN_ERR PREFIX "erase of region %x,%x on '%s' "
                                "failed\n", erase->addr, erase->len,
                                part->mbd.mtd->name);
                kfree(erase);
@@ -383,7 +382,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_NOTICE PREFIX "error reading '%s' at "
+               printk(KERN_ERR PREFIX "error reading '%s' at "
                        "0x%lx\n", part->mbd.mtd->name,
                        part->blocks[block_no].offset);
 
@@ -423,7 +422,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
                        rc = -EIO;
 
                if (rc) {
-                       printk(KERN_NOTICE PREFIX "'%s': Unable to "
+                       printk(KERN_ERR PREFIX "'%s': Unable to "
                                "read sector for relocation\n",
                                part->mbd.mtd->name);
 
@@ -520,7 +519,7 @@ static int reclaim_block(struct partition *part, u_long *old_sector)
  * because if we fill that one up first it'll have the most chance of having
  * the least live sectors at reclaim.
  */
-static int find_free_block(const struct partition *part)
+static int find_free_block(struct partition *part)
 {
        int block, stop;
 
@@ -533,6 +532,9 @@ static int find_free_block(const struct partition *part)
                                block != part->reserved_block)
                        return block;
 
+               if (part->blocks[block].state == BLOCK_UNUSED)
+                       erase_block(part, block);
+
                if (++block >= part->total_blocks)
                        block = 0;
 
@@ -541,7 +543,7 @@ static int find_free_block(const struct partition *part)
        return -1;
 }
 
-static int find_writeable_block(struct partition *part, u_long *old_sector)
+static int find_writable_block(struct partition *part, u_long *old_sector)
 {
        int rc, block;
        size_t retlen;
@@ -570,7 +572,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector)
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_NOTICE PREFIX "'%s': unable to read header at "
+               printk(KERN_ERR PREFIX "'%s': unable to read header at "
                                "0x%lx\n", part->mbd.mtd->name,
                                part->blocks[block].offset);
                goto err;
@@ -602,7 +604,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_WARNING PREFIX "error writing '%s' at "
+               printk(KERN_ERR PREFIX "error writing '%s' at "
                        "0x%lx\n", part->mbd.mtd->name, addr);
                if (rc)
                        goto err;
@@ -652,7 +654,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
        if (part->current_block == -1 ||
                !part->blocks[part->current_block].free_sectors) {
 
-               rc = find_writeable_block(part, old_addr);
+               rc = find_writable_block(part, old_addr);
                if (rc)
                        goto err;
        }
@@ -675,7 +677,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",
+               printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n",
                                part->mbd.mtd->name, addr);
                if (rc)
                        goto err;
@@ -695,7 +697,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",
+               printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n",
                                part->mbd.mtd->name, addr);
                if (rc)
                        goto err;
@@ -776,7 +778,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
                part->block_size = block_size;
        else {
                if (!mtd->erasesize) {
-                       printk(KERN_NOTICE PREFIX "please provide block_size");
+                       printk(KERN_WARNING PREFIX "please provide block_size");
                        return;
                }
                else
@@ -791,8 +793,8 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
                if (!(mtd->flags & MTD_WRITEABLE))
                        part->mbd.readonly = 1;
                else if (part->errors) {
-                       printk(KERN_NOTICE PREFIX "'%s': errors found, "
-                                       "setting read-only", mtd->name);
+                       printk(KERN_WARNING PREFIX "'%s': errors found, "
+                                       "setting read-only\n", mtd->name);
                        part->mbd.readonly = 1;
                }
 
index f6d51ce34b005c99e90eb8e1fd8a824a055cd6ed..bb44509fd404b66791793c8bf3da6ea8a8fa8b3a 100644 (file)
@@ -909,7 +909,7 @@ MODULE_PARM_DESC(irq, "EtherLink IRQ number");
  * here also causes the module to be unloaded
  */
  
-int init_module(void)
+int __init init_module(void)
 {
        dev_3c501 = el1_probe(-1);
        if (IS_ERR(dev_3c501))
index dcc98afa65d717c7abe1f7360c0c9a90c75c3ce7..cb5ef75450dc72c19b98a77c5c5f8ce9c39fc5c8 100644 (file)
@@ -688,7 +688,7 @@ MODULE_LICENSE("GPL");
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
+int __init
 init_module(void)
 {
        struct net_device *dev;
index 111601ca4ca3da97d054cf3a70dfad08da476735..19c0b856c488097494f69c27ff14e2c3f615deeb 100644 (file)
@@ -1633,7 +1633,7 @@ MODULE_PARM_DESC(io, "EtherLink Plus I/O base address(es)");
 MODULE_PARM_DESC(irq, "EtherLink Plus IRQ number(s) (assigned)");
 MODULE_PARM_DESC(dma, "EtherLink Plus DMA channel(s)");
 
-int init_module(void)
+int __init init_module(void)
 {
        int this_dev, found = 0;
 
index 4db82893909c3118c17d0ee9435b72cf8666c112..6039049259ed1c1e94e56d787fbfb4dd7b57bceb 100644 (file)
@@ -932,7 +932,7 @@ module_param(irq, int, 0);
 MODULE_PARM_DESC(io, "EtherLink16 I/O base address");
 MODULE_PARM_DESC(irq, "(ignored)");
 
-int init_module(void)
+int __init init_module(void)
 {
        if (io == 0)
                printk("3c507: You should not use auto-probing with insmod!\n");
index b40885d4168092baa1d3e6e691e1aea0b2428227..4bf8510655c52574a543b34bd6204a40ea47f7f5 100644 (file)
@@ -1277,7 +1277,7 @@ MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)");
 MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)");
 MODULE_LICENSE("GPL");
 
-int init_module(void)
+int __init init_module(void)
 {
        int this_dev,found = 0;
 
index 6db3301e7965adfbc53281405ac6220c0204a696..1b1cb0026072e71d200d6a7e8fd01dadf9582661 100644 (file)
@@ -1646,7 +1646,7 @@ static struct net_device *this_device;
  *     insmod multiple modules for now but it's a hack.
  */
 
-int init_module(void)
+int __init init_module(void)
 {
        this_device = mc32_probe(-1);
        if (IS_ERR(this_device))
index 066e22b01a941ed90fcc3edf028ed217b8688da0..46d8c01437e929080703eaf88e617cde75f0106b 100644 (file)
        See the file COPYING in this distribution for more information.
 
        Contributors:
-       
+
                Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br>
                PCI suspend/resume  - Felipe Damasio <felipewd@terra.com.br>
                LinkChg interrupt   - Felipe Damasio <felipewd@terra.com.br>
-                       
+
        TODO:
        * Test Tx checksumming thoroughly
        * Implement dev->tx_timeout
@@ -461,7 +461,7 @@ static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 static inline void cp_set_rxbufsize (struct cp_private *cp)
 {
        unsigned int mtu = cp->dev->mtu;
-       
+
        if (mtu > ETH_DATA_LEN)
                /* MTU + ethernet header + FCS + optional VLAN tag */
                cp->rx_buf_sz = mtu + ETH_HLEN + 8;
@@ -510,7 +510,7 @@ static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
 static inline unsigned int cp_rx_csum_ok (u32 status)
 {
        unsigned int protocol = (status >> 16) & 0x3;
-       
+
        if (likely((protocol == RxProtoTCP) && (!(status & TCPFail))))
                return 1;
        else if ((protocol == RxProtoUDP) && (!(status & UDPFail)))
@@ -1061,7 +1061,7 @@ static void cp_init_hw (struct cp_private *cp)
        cpw8(Config3, PARMEnable);
        cp->wol_enabled = 0;
 
-       cpw8(Config5, cpr8(Config5) & PMEStatus); 
+       cpw8(Config5, cpr8(Config5) & PMEStatus);
 
        cpw32_f(HiTxRingAddr, 0);
        cpw32_f(HiTxRingAddr + 4, 0);
@@ -1351,7 +1351,7 @@ static void netdev_get_wol (struct cp_private *cp,
                         WAKE_MCAST | WAKE_UCAST;
        /* We don't need to go on if WOL is disabled */
        if (!cp->wol_enabled) return;
-       
+
        options        = cpr8 (Config3);
        if (options & LinkUp)        wol->wolopts |= WAKE_PHY;
        if (options & MagicPacket)   wol->wolopts |= WAKE_MAGIC;
@@ -1919,7 +1919,7 @@ static int cp_resume (struct pci_dev *pdev)
        mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
 
        spin_unlock_irqrestore (&cp->lock, flags);
-       
+
        return 0;
 }
 #endif /* CONFIG_PM */
index feae7832fc846b3daef50d83d5cf0184561b9484..abd6261465f16e2692c45033ab81e3263dc6716e 100644 (file)
@@ -165,7 +165,7 @@ static int multicast_filter_limit = 32;
 static int debug = -1;
 
 /*
- * Receive ring size 
+ * Receive ring size
  * Warning: 64K ring has hardware issues and may lock up.
  */
 #if defined(CONFIG_SH_DREAMCAST)
@@ -257,7 +257,7 @@ static struct pci_device_id rtl8139_pci_tbl[] = {
        {0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
        {0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
        {0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-       {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, 
+       {0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 
 #ifdef CONFIG_SH_SECUREEDGE5410
        /* Bogus 8139 silicon reports 8129 without external PROM :-( */
@@ -1824,7 +1824,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
        int tmp_work;
 #endif
 
-       if (netif_msg_rx_err (tp)) 
+       if (netif_msg_rx_err (tp))
                printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n",
                        dev->name, rx_status);
        tp->stats.rx_errors++;
@@ -1944,7 +1944,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
                 RTL_R16 (RxBufAddr),
                 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
 
-       while (netif_running(dev) && received < budget 
+       while (netif_running(dev) && received < budget
               && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
                u32 ring_offset = cur_rx % RX_BUF_LEN;
                u32 rx_status;
@@ -2031,7 +2031,7 @@ no_early_rx:
 
                        netif_receive_skb (skb);
                } else {
-                       if (net_ratelimit()) 
+                       if (net_ratelimit())
                                printk (KERN_WARNING
                                        "%s: Memory squeeze, dropping packet.\n",
                                        dev->name);
@@ -2158,13 +2158,13 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
        status = RTL_R16 (IntrStatus);
 
        /* shared irq? */
-       if (unlikely((status & rtl8139_intr_mask) == 0)) 
+       if (unlikely((status & rtl8139_intr_mask) == 0))
                goto out;
 
        handled = 1;
 
        /* h/w no longer present (hotplug?) or major error, bail */
-       if (unlikely(status == 0xFFFF)) 
+       if (unlikely(status == 0xFFFF))
                goto out;
 
        /* close possible race's with dev_close */
index bdaaad8f2123d5410c1985ceb526e200bb1958e6..0c6b45a11d15f876819d395314b5e8fd5f56078b 100644 (file)
@@ -447,6 +447,7 @@ config MIPS_GT96100ETH
 config MIPS_AU1X00_ENET
        bool "MIPS AU1000 Ethernet support"
        depends on NET_ETHERNET && SOC_AU1X00
+       select PHYLIB
        select CRC32
        help
          If you have an Alchemy Semi AU1X00 based system
@@ -865,6 +866,22 @@ config DM9000
          <file:Documentation/networking/net-modules.txt>.  The module will be
          called dm9000.
 
+config SMC911X
+       tristate "SMSC LAN911[5678] support"
+       select CRC32
+       select MII
+       depends on NET_ETHERNET && ARCH_PXA
+       help
+         This is a driver for SMSC's LAN911x series of Ethernet chipsets
+         including the new LAN9115, LAN9116, LAN9117, and LAN9118.
+         Say Y if you want it compiled into the kernel, 
+         and read the Ethernet-HOWTO, available from
+         <http://www.linuxdoc.org/docs.html#howto>.
+
+         This driver is also available as a module. The module will be 
+         called smc911x.  If you want to compile it as a module, say M 
+         here and read <file:Documentation/modules.txt>
+
 config NET_VENDOR_RACAL
        bool "Racal-Interlan (Micom) NI cards"
        depends on NET_ETHERNET && ISA
@@ -2163,6 +2180,8 @@ config TIGON3
 config BNX2
        tristate "Broadcom NetXtremeII support"
        depends on PCI
+       select CRC32
+       select ZLIB_INFLATE
        help
          This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
 
@@ -2311,6 +2330,23 @@ config S2IO_NAPI
 
          If in doubt, say N.
 
+config MYRI10GE
+       tristate "Myricom Myri-10G Ethernet support"
+       depends on PCI
+       select FW_LOADER
+       select CRC32
+       ---help---
+         This driver supports Myricom Myri-10G Dual Protocol interface in
+         Ethernet mode. If the eeprom on your board is not recent enough,
+         you will need a newer firmware image.
+         You may get this image or more information, at:
+
+         <http://www.myri.com/Myri-10G/>
+
+         To compile this driver as a module, choose M here and read
+         <file:Documentation/networking/net-modules.txt>.  The module
+         will be called myri10ge.
+
 endmenu
 
 source "drivers/net/tokenring/Kconfig"
index b90468aea077aee9a2b5ee95f10acd7869fd72aa..1eced3287507e94462b820408a3a2a8b0c90567f 100644 (file)
@@ -192,7 +192,9 @@ obj-$(CONFIG_R8169) += r8169.o
 obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
 obj-$(CONFIG_IBMVETH) += ibmveth.o
 obj-$(CONFIG_S2IO) += s2io.o
+obj-$(CONFIG_MYRI10GE) += myri10ge/
 obj-$(CONFIG_SMC91X) += smc91x.o
+obj-$(CONFIG_SMC911X) += smc911x.o
 obj-$(CONFIG_DM9000) += dm9000.o
 obj-$(CONFIG_FEC_8XX) += fec_8xx/
 
index 14dbad14afb64da8be9d94f57d74be1579d2f1d7..038d5fcb15e67439bc23ce782eaf3b4beabe1751 100644 (file)
@@ -2,13 +2,16 @@
  *
  * Alchemy Au1x00 ethernet driver
  *
- * Copyright 2001,2002,2003 MontaVista Software Inc.
+ * Copyright 2001-2003, 2006 MontaVista Software Inc.
  * Copyright 2002 TimeSys Corp.
  * Added ethtool/mii-tool support,
  * Copyright 2004 Matt Porter <mporter@kernel.crashing.org>
  * Update: 2004 Bjoern Riemer, riemer@fokus.fraunhofer.de 
  * or riemer@riemer-nt.de: fixed the link beat detection with 
  * ioctls (SIOCGMIIPHY)
+ * Copyright 2006 Herbert Valerio Riedel <hvr@gnu.org>
+ *  converted to use linux-2.6.x's PHY framework
+ *
  * Author: MontaVista Software, Inc.
  *             ppopov@mvista.com or source@mvista.com
  *
@@ -53,6 +56,7 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/crc32.h>
+#include <linux/phy.h>
 #include <asm/mipsregs.h>
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -68,7 +72,7 @@ static int au1000_debug = 5;
 static int au1000_debug = 3;
 #endif
 
-#define DRV_NAME       "au1000eth"
+#define DRV_NAME       "au1000_eth"
 #define DRV_VERSION    "1.5"
 #define DRV_AUTHOR     "Pete Popov <ppopov@embeddedalley.com>"
 #define DRV_DESC       "Au1xxx on-chip Ethernet driver"
@@ -80,7 +84,7 @@ MODULE_LICENSE("GPL");
 // prototypes
 static void hard_stop(struct net_device *);
 static void enable_rx_tx(struct net_device *dev);
-static struct net_device * au1000_probe(u32 ioaddr, int irq, int port_num);
+static struct net_device * au1000_probe(int port_num);
 static int au1000_init(struct net_device *);
 static int au1000_open(struct net_device *);
 static int au1000_close(struct net_device *);
@@ -88,17 +92,15 @@ static int au1000_tx(struct sk_buff *, struct net_device *);
 static int au1000_rx(struct net_device *);
 static irqreturn_t au1000_interrupt(int, void *, struct pt_regs *);
 static void au1000_tx_timeout(struct net_device *);
-static int au1000_set_config(struct net_device *dev, struct ifmap *map);
 static void set_rx_mode(struct net_device *);
 static struct net_device_stats *au1000_get_stats(struct net_device *);
-static void au1000_timer(unsigned long);
 static int au1000_ioctl(struct net_device *, struct ifreq *, int);
 static int mdio_read(struct net_device *, int, int);
 static void mdio_write(struct net_device *, int, int, u16);
-static void dump_mii(struct net_device *dev, int phy_id);
+static void au1000_adjust_link(struct net_device *);
+static void enable_mac(struct net_device *, int);
 
 // externs
-extern  void ack_rise_edge_irq(unsigned int);
 extern int get_ethernet_addr(char *ethernet_addr);
 extern void str2eaddr(unsigned char *ea, unsigned char *str);
 extern char * __init prom_getcmdline(void);
@@ -126,705 +128,83 @@ static unsigned char au1000_mac_addr[6] __devinitdata = {
        0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00
 };
 
-#define nibswap(x) ((((x) >> 4) & 0x0f) | (((x) << 4) & 0xf0))
-#define RUN_AT(x) (jiffies + (x))
-
-// For reading/writing 32-bit words from/to DMA memory
-#define cpu_to_dma32 cpu_to_be32
-#define dma32_to_cpu be32_to_cpu
-
 struct au1000_private *au_macs[NUM_ETH_INTERFACES];
 
-/* FIXME 
- * All of the PHY code really should be detached from the MAC 
- * code.
+/*
+ * board-specific configurations
+ *
+ * PHY detection algorithm
+ *
+ * If AU1XXX_PHY_STATIC_CONFIG is undefined, the PHY setup is
+ * autodetected:
+ *
+ * mii_probe() first searches the current MAC's MII bus for a PHY,
+ * selecting the first (or last, if AU1XXX_PHY_SEARCH_HIGHEST_ADDR is
+ * defined) PHY address not already claimed by another netdev.
+ *
+ * If nothing was found that way when searching for the 2nd ethernet
+ * controller's PHY and AU1XXX_PHY1_SEARCH_ON_MAC0 is defined, then
+ * the first MII bus is searched as well for an unclaimed PHY; this is
+ * needed in case of a dual-PHY accessible only through the MAC0's MII
+ * bus.
+ *
+ * Finally, if no PHY is found, then the corresponding ethernet
+ * controller is not registered to the network subsystem.
  */
 
-/* Default advertise */
-#define GENMII_DEFAULT_ADVERTISE \
-       ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
-       ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
-       ADVERTISED_Autoneg
-
-#define GENMII_DEFAULT_FEATURES \
-       SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
-       SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
-       SUPPORTED_Autoneg
-
-int bcm_5201_init(struct net_device *dev, int phy_addr)
-{
-       s16 data;
-       
-       /* Stop auto-negotiation */
-       data = mdio_read(dev, phy_addr, MII_CONTROL);
-       mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
-       /* Set advertisement to 10/100 and Half/Full duplex
-        * (full capabilities) */
-       data = mdio_read(dev, phy_addr, MII_ANADV);
-       data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
-       mdio_write(dev, phy_addr, MII_ANADV, data);
-       
-       /* Restart auto-negotiation */
-       data = mdio_read(dev, phy_addr, MII_CONTROL);
-       data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-       mdio_write(dev, phy_addr, MII_CONTROL, data);
-
-       if (au1000_debug > 4) 
-               dump_mii(dev, phy_addr);
-       return 0;
-}
-
-int bcm_5201_reset(struct net_device *dev, int phy_addr)
-{
-       s16 mii_control, timeout;
-       
-       mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-       mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-       mdelay(1);
-       for (timeout = 100; timeout > 0; --timeout) {
-               mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-               if ((mii_control & MII_CNTL_RESET) == 0)
-                       break;
-               mdelay(1);
-       }
-       if (mii_control & MII_CNTL_RESET) {
-               printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-               return -1;
-       }
-       return 0;
-}
-
-int 
-bcm_5201_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-       u16 mii_data;
-       struct au1000_private *aup;
-
-       if (!dev) {
-               printk(KERN_ERR "bcm_5201_status error: NULL dev\n");
-               return -1;
-       }
-       aup = (struct au1000_private *) dev->priv;
-
-       mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-       if (mii_data & MII_STAT_LINK) {
-               *link = 1;
-               mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL);
-               if (mii_data & MII_AUX_100) {
-                       if (mii_data & MII_AUX_FDX) {
-                               *speed = IF_PORT_100BASEFX;
-                               dev->if_port = IF_PORT_100BASEFX;
-                       }
-                       else {
-                               *speed = IF_PORT_100BASETX;
-                               dev->if_port = IF_PORT_100BASETX;
-                       }
-               }
-               else  {
-                       *speed = IF_PORT_10BASET;
-                       dev->if_port = IF_PORT_10BASET;
-               }
-
-       }
-       else {
-               *link = 0;
-               *speed = 0;
-               dev->if_port = IF_PORT_UNKNOWN;
-       }
-       return 0;
-}
-
-int lsi_80227_init(struct net_device *dev, int phy_addr)
-{
-       if (au1000_debug > 4)
-               printk("lsi_80227_init\n");
-
-       /* restart auto-negotiation */
-       mdio_write(dev, phy_addr, MII_CONTROL,
-                  MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO); // | MII_CNTL_FDX);
-       mdelay(1);
-
-       /* set up LEDs to correct display */
-#ifdef CONFIG_MIPS_MTX1
-       mdio_write(dev, phy_addr, 17, 0xff80);
-#else
-       mdio_write(dev, phy_addr, 17, 0xffc0);
-#endif
-
-       if (au1000_debug > 4)
-               dump_mii(dev, phy_addr);
-       return 0;
-}
-
-int lsi_80227_reset(struct net_device *dev, int phy_addr)
-{
-       s16 mii_control, timeout;
-       
-       if (au1000_debug > 4) {
-               printk("lsi_80227_reset\n");
-               dump_mii(dev, phy_addr);
-       }
-
-       mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-       mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-       mdelay(1);
-       for (timeout = 100; timeout > 0; --timeout) {
-               mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-               if ((mii_control & MII_CNTL_RESET) == 0)
-                       break;
-               mdelay(1);
-       }
-       if (mii_control & MII_CNTL_RESET) {
-               printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-               return -1;
-       }
-       return 0;
-}
-
-int
-lsi_80227_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-       u16 mii_data;
-       struct au1000_private *aup;
-
-       if (!dev) {
-               printk(KERN_ERR "lsi_80227_status error: NULL dev\n");
-               return -1;
-       }
-       aup = (struct au1000_private *) dev->priv;
-
-       mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-       if (mii_data & MII_STAT_LINK) {
-               *link = 1;
-               mii_data = mdio_read(dev, aup->phy_addr, MII_LSI_PHY_STAT);
-               if (mii_data & MII_LSI_PHY_STAT_SPD) {
-                       if (mii_data & MII_LSI_PHY_STAT_FDX) {
-                               *speed = IF_PORT_100BASEFX;
-                               dev->if_port = IF_PORT_100BASEFX;
-                       }
-                       else {
-                               *speed = IF_PORT_100BASETX;
-                               dev->if_port = IF_PORT_100BASETX;
-                       }
-               }
-               else  {
-                       *speed = IF_PORT_10BASET;
-                       dev->if_port = IF_PORT_10BASET;
-               }
-
-       }
-       else {
-               *link = 0;
-               *speed = 0;
-               dev->if_port = IF_PORT_UNKNOWN;
-       }
-       return 0;
-}
-
-int am79c901_init(struct net_device *dev, int phy_addr)
-{
-       printk("am79c901_init\n");
-       return 0;
-}
-
-int am79c901_reset(struct net_device *dev, int phy_addr)
-{
-       printk("am79c901_reset\n");
-       return 0;
-}
-
-int 
-am79c901_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-       return 0;
-}
-
-int am79c874_init(struct net_device *dev, int phy_addr)
-{
-       s16 data;
-
-       /* 79c874 has quit resembled bit assignments to BCM5201 */
-       if (au1000_debug > 4)
-               printk("am79c847_init\n");
-
-       /* Stop auto-negotiation */
-       data = mdio_read(dev, phy_addr, MII_CONTROL);
-       mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
-       /* Set advertisement to 10/100 and Half/Full duplex
-        * (full capabilities) */
-       data = mdio_read(dev, phy_addr, MII_ANADV);
-       data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
-       mdio_write(dev, phy_addr, MII_ANADV, data);
-       
-       /* Restart auto-negotiation */
-       data = mdio_read(dev, phy_addr, MII_CONTROL);
-       data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-
-       mdio_write(dev, phy_addr, MII_CONTROL, data);
-
-       if (au1000_debug > 4) dump_mii(dev, phy_addr);
-       return 0;
-}
-
-int am79c874_reset(struct net_device *dev, int phy_addr)
-{
-       s16 mii_control, timeout;
-       
-       if (au1000_debug > 4)
-               printk("am79c874_reset\n");
-
-       mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-       mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-       mdelay(1);
-       for (timeout = 100; timeout > 0; --timeout) {
-               mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-               if ((mii_control & MII_CNTL_RESET) == 0)
-                       break;
-               mdelay(1);
-       }
-       if (mii_control & MII_CNTL_RESET) {
-               printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-               return -1;
-       }
-       return 0;
-}
-
-int 
-am79c874_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-       u16 mii_data;
-       struct au1000_private *aup;
-
-       // printk("am79c874_status\n");
-       if (!dev) {
-               printk(KERN_ERR "am79c874_status error: NULL dev\n");
-               return -1;
-       }
-
-       aup = (struct au1000_private *) dev->priv;
-       mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-
-       if (mii_data & MII_STAT_LINK) {
-               *link = 1;
-               mii_data = mdio_read(dev, aup->phy_addr, MII_AMD_PHY_STAT);
-               if (mii_data & MII_AMD_PHY_STAT_SPD) {
-                       if (mii_data & MII_AMD_PHY_STAT_FDX) {
-                               *speed = IF_PORT_100BASEFX;
-                               dev->if_port = IF_PORT_100BASEFX;
-                       }
-                       else {
-                               *speed = IF_PORT_100BASETX;
-                               dev->if_port = IF_PORT_100BASETX;
-                       }
-               }
-               else {
-                       *speed = IF_PORT_10BASET;
-                       dev->if_port = IF_PORT_10BASET;
-               }
-
-       }
-       else {
-               *link = 0;
-               *speed = 0;
-               dev->if_port = IF_PORT_UNKNOWN;
-       }
-       return 0;
-}
-
-int lxt971a_init(struct net_device *dev, int phy_addr)
-{
-       if (au1000_debug > 4)
-               printk("lxt971a_init\n");
-
-       /* restart auto-negotiation */
-       mdio_write(dev, phy_addr, MII_CONTROL,
-                  MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO | MII_CNTL_FDX);
-
-       /* set up LEDs to correct display */
-       mdio_write(dev, phy_addr, 20, 0x0422);
-
-       if (au1000_debug > 4)
-               dump_mii(dev, phy_addr);
-       return 0;
-}
-
-int lxt971a_reset(struct net_device *dev, int phy_addr)
-{
-       s16 mii_control, timeout;
-       
-       if (au1000_debug > 4) {
-               printk("lxt971a_reset\n");
-               dump_mii(dev, phy_addr);
-       }
-
-       mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-       mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-       mdelay(1);
-       for (timeout = 100; timeout > 0; --timeout) {
-               mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-               if ((mii_control & MII_CNTL_RESET) == 0)
-                       break;
-               mdelay(1);
-       }
-       if (mii_control & MII_CNTL_RESET) {
-               printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-               return -1;
-       }
-       return 0;
-}
-
-int
-lxt971a_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-       u16 mii_data;
-       struct au1000_private *aup;
-
-       if (!dev) {
-               printk(KERN_ERR "lxt971a_status error: NULL dev\n");
-               return -1;
-       }
-       aup = (struct au1000_private *) dev->priv;
-
-       mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-       if (mii_data & MII_STAT_LINK) {
-               *link = 1;
-               mii_data = mdio_read(dev, aup->phy_addr, MII_INTEL_PHY_STAT);
-               if (mii_data & MII_INTEL_PHY_STAT_SPD) {
-                       if (mii_data & MII_INTEL_PHY_STAT_FDX) {
-                               *speed = IF_PORT_100BASEFX;
-                               dev->if_port = IF_PORT_100BASEFX;
-                       }
-                       else {
-                               *speed = IF_PORT_100BASETX;
-                               dev->if_port = IF_PORT_100BASETX;
-                       }
-               }
-               else  {
-                       *speed = IF_PORT_10BASET;
-                       dev->if_port = IF_PORT_10BASET;
-               }
-
-       }
-       else {
-               *link = 0;
-               *speed = 0;
-               dev->if_port = IF_PORT_UNKNOWN;
-       }
-       return 0;
-}
-
-int ks8995m_init(struct net_device *dev, int phy_addr)
-{
-       s16 data;
-       
-//     printk("ks8995m_init\n");
-       /* Stop auto-negotiation */
-       data = mdio_read(dev, phy_addr, MII_CONTROL);
-       mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
-       /* Set advertisement to 10/100 and Half/Full duplex
-        * (full capabilities) */
-       data = mdio_read(dev, phy_addr, MII_ANADV);
-       data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
-       mdio_write(dev, phy_addr, MII_ANADV, data);
-       
-       /* Restart auto-negotiation */
-       data = mdio_read(dev, phy_addr, MII_CONTROL);
-       data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-       mdio_write(dev, phy_addr, MII_CONTROL, data);
-
-       if (au1000_debug > 4) dump_mii(dev, phy_addr);
-
-       return 0;
-}
-
-int ks8995m_reset(struct net_device *dev, int phy_addr)
-{
-       s16 mii_control, timeout;
-       
-//     printk("ks8995m_reset\n");
-       mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-       mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-       mdelay(1);
-       for (timeout = 100; timeout > 0; --timeout) {
-               mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-               if ((mii_control & MII_CNTL_RESET) == 0)
-                       break;
-               mdelay(1);
-       }
-       if (mii_control & MII_CNTL_RESET) {
-               printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-               return -1;
-       }
-       return 0;
-}
-
-int ks8995m_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-       u16 mii_data;
-       struct au1000_private *aup;
-
-       if (!dev) {
-               printk(KERN_ERR "ks8995m_status error: NULL dev\n");
-               return -1;
-       }
-       aup = (struct au1000_private *) dev->priv;
-
-       mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-       if (mii_data & MII_STAT_LINK) {
-               *link = 1;
-               mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL);
-               if (mii_data & MII_AUX_100) {
-                       if (mii_data & MII_AUX_FDX) {
-                               *speed = IF_PORT_100BASEFX;
-                               dev->if_port = IF_PORT_100BASEFX;
-                       }
-                       else {
-                               *speed = IF_PORT_100BASETX;
-                               dev->if_port = IF_PORT_100BASETX;
-                       }
-               }
-               else  {                                                                                 
-                       *speed = IF_PORT_10BASET;
-                       dev->if_port = IF_PORT_10BASET;
-               }
-
-       }
-       else {
-               *link = 0;
-               *speed = 0;
-               dev->if_port = IF_PORT_UNKNOWN;
-       }
-       return 0;
-}
-
-int
-smsc_83C185_init (struct net_device *dev, int phy_addr)
-{
-       s16 data;
-
-       if (au1000_debug > 4)
-               printk("smsc_83C185_init\n");
-
-       /* Stop auto-negotiation */
-       data = mdio_read(dev, phy_addr, MII_CONTROL);
-       mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
-       /* Set advertisement to 10/100 and Half/Full duplex
-        * (full capabilities) */
-       data = mdio_read(dev, phy_addr, MII_ANADV);
-       data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
-       mdio_write(dev, phy_addr, MII_ANADV, data);
-       
-       /* Restart auto-negotiation */
-       data = mdio_read(dev, phy_addr, MII_CONTROL);
-       data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-
-       mdio_write(dev, phy_addr, MII_CONTROL, data);
-
-       if (au1000_debug > 4) dump_mii(dev, phy_addr);
-       return 0;
-}
-
-int
-smsc_83C185_reset (struct net_device *dev, int phy_addr)
-{
-       s16 mii_control, timeout;
-       
-       if (au1000_debug > 4)
-               printk("smsc_83C185_reset\n");
-
-       mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-       mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-       mdelay(1);
-       for (timeout = 100; timeout > 0; --timeout) {
-               mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-               if ((mii_control & MII_CNTL_RESET) == 0)
-                       break;
-               mdelay(1);
-       }
-       if (mii_control & MII_CNTL_RESET) {
-               printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-               return -1;
-       }
-       return 0;
-}
-
-int 
-smsc_83C185_status (struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-       u16 mii_data;
-       struct au1000_private *aup;
-
-       if (!dev) {
-               printk(KERN_ERR "smsc_83C185_status error: NULL dev\n");
-               return -1;
-       }
-
-       aup = (struct au1000_private *) dev->priv;
-       mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-
-       if (mii_data & MII_STAT_LINK) {
-               *link = 1;
-               mii_data = mdio_read(dev, aup->phy_addr, 0x1f);
-               if (mii_data & (1<<3)) {
-                       if (mii_data & (1<<4)) {
-                               *speed = IF_PORT_100BASEFX;
-                               dev->if_port = IF_PORT_100BASEFX;
-                       }
-                       else {
-                               *speed = IF_PORT_100BASETX;
-                               dev->if_port = IF_PORT_100BASETX;
-                       }
-               }
-               else {
-                       *speed = IF_PORT_10BASET;
-                       dev->if_port = IF_PORT_10BASET;
-               }
-       }
-       else {
-               *link = 0;
-               *speed = 0;
-               dev->if_port = IF_PORT_UNKNOWN;
-       }
-       return 0;
-}
-
-
-#ifdef CONFIG_MIPS_BOSPORUS
-int stub_init(struct net_device *dev, int phy_addr)
-{
-       //printk("PHY stub_init\n");
-       return 0;
-}
+/* autodetection defaults */
+#undef  AU1XXX_PHY_SEARCH_HIGHEST_ADDR
+#define AU1XXX_PHY1_SEARCH_ON_MAC0
 
-int stub_reset(struct net_device *dev, int phy_addr)
-{
-       //printk("PHY stub_reset\n");
-       return 0;
-}
-
-int 
-stub_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-       //printk("PHY stub_status\n");
-       *link = 1;
-       /* hmmm, revisit */
-       *speed = IF_PORT_100BASEFX;
-       dev->if_port = IF_PORT_100BASEFX;
-       return 0;
-}
-#endif
-
-struct phy_ops bcm_5201_ops = {
-       bcm_5201_init,
-       bcm_5201_reset,
-       bcm_5201_status,
-};
-
-struct phy_ops am79c874_ops = {
-       am79c874_init,
-       am79c874_reset,
-       am79c874_status,
-};
-
-struct phy_ops am79c901_ops = {
-       am79c901_init,
-       am79c901_reset,
-       am79c901_status,
-};
-
-struct phy_ops lsi_80227_ops = { 
-       lsi_80227_init,
-       lsi_80227_reset,
-       lsi_80227_status,
-};
-
-struct phy_ops lxt971a_ops = { 
-       lxt971a_init,
-       lxt971a_reset,
-       lxt971a_status,
-};
+/* static PHY setup
+ *
+ * most boards PHY setup should be detectable properly with the
+ * autodetection algorithm in mii_probe(), but in some cases (e.g. if
+ * you have a switch attached, or want to use the PHY's interrupt
+ * notification capabilities) you can provide a static PHY
+ * configuration here
+ *
+ * IRQs may only be set, if a PHY address was configured
+ * If a PHY address is given, also a bus id is required to be set
+ *
+ * ps: make sure the used irqs are configured properly in the board
+ * specific irq-map
+ */
 
-struct phy_ops ks8995m_ops = {
-       ks8995m_init,
-       ks8995m_reset,
-       ks8995m_status,
-};
+#if defined(CONFIG_MIPS_BOSPORUS)
+/*
+ * Micrel/Kendin 5 port switch attached to MAC0,
+ * MAC0 is associated with PHY address 5 (== WAN port)
+ * MAC1 is not associated with any PHY, since it's connected directly
+ * to the switch.
+ * no interrupts are used
+ */
+# define AU1XXX_PHY_STATIC_CONFIG
 
-struct phy_ops smsc_83C185_ops = {
-       smsc_83C185_init,
-       smsc_83C185_reset,
-       smsc_83C185_status,
-};
+# define AU1XXX_PHY0_ADDR  5
+# define AU1XXX_PHY0_BUSID 0
+#  undef AU1XXX_PHY0_IRQ
 
-#ifdef CONFIG_MIPS_BOSPORUS
-struct phy_ops stub_ops = {
-       stub_init,
-       stub_reset,
-       stub_status,
-};
+#  undef AU1XXX_PHY1_ADDR
+#  undef AU1XXX_PHY1_BUSID
+#  undef AU1XXX_PHY1_IRQ
 #endif
 
-static struct mii_chip_info {
-       const char * name;
-       u16 phy_id0;
-       u16 phy_id1;
-       struct phy_ops *phy_ops;        
-       int dual_phy;
-} mii_chip_table[] = {
-       {"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
-       {"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
-       {"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
-       {"NS DP83847 PHY", 0x2000, 0x5c30, &bcm_5201_ops ,0},
-       {"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
-       {"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
-       {"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
-       {"Intel LXT971A Dual Speed PHY",0x0013,0x78e2, &lxt971a_ops,0},
-       {"Kendin KS8995M 10/100 BaseT PHY",0x0022,0x1450, &ks8995m_ops,0},
-       {"SMSC LAN83C185 10/100 BaseT PHY",0x0007,0xc0a3, &smsc_83C185_ops,0},
-#ifdef CONFIG_MIPS_BOSPORUS
-       {"Stub", 0x1234, 0x5678, &stub_ops },
+#if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0)
+# error MAC0-associated PHY attached 2nd MACs MII bus not supported yet
 #endif
-       {0,},
-};
 
-static int mdio_read(struct net_device *dev, int phy_id, int reg)
+/*
+ * MII operations
+ */
+static int mdio_read(struct net_device *dev, int phy_addr, int reg)
 {
        struct au1000_private *aup = (struct au1000_private *) dev->priv;
-       volatile u32 *mii_control_reg;
-       volatile u32 *mii_data_reg;
+       volatile u32 *const mii_control_reg = &aup->mac->mii_control;
+       volatile u32 *const mii_data_reg = &aup->mac->mii_data;
        u32 timedout = 20;
        u32 mii_control;
 
-       #ifdef CONFIG_BCM5222_DUAL_PHY
-       /* First time we probe, it's for the mac0 phy.
-        * Since we haven't determined yet that we have a dual phy,
-        * aup->mii->mii_control_reg won't be setup and we'll
-        * default to the else statement.
-        * By the time we probe for the mac1 phy, the mii_control_reg
-        * will be setup to be the address of the mac0 phy control since
-        * both phys are controlled through mac0.
-        */
-       if (aup->mii && aup->mii->mii_control_reg) {
-               mii_control_reg = aup->mii->mii_control_reg;
-               mii_data_reg = aup->mii->mii_data_reg;
-       }
-       else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
-               /* assume both phys are controlled through mac0 */
-               mii_control_reg = au_macs[0]->mii->mii_control_reg;
-               mii_data_reg = au_macs[0]->mii->mii_data_reg;
-       }
-       else 
-       #endif
-       {
-               /* default control and data reg addresses */
-               mii_control_reg = &aup->mac->mii_control;
-               mii_data_reg = &aup->mac->mii_data;
-       }
-
        while (*mii_control_reg & MAC_MII_BUSY) {
                mdelay(1);
                if (--timedout == 0) {
@@ -835,7 +215,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int reg)
        }
 
        mii_control = MAC_SET_MII_SELECT_REG(reg) | 
-               MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_READ;
+               MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_READ;
 
        *mii_control_reg = mii_control;
 
@@ -851,32 +231,14 @@ static int mdio_read(struct net_device *dev, int phy_id, int reg)
        return (int)*mii_data_reg;
 }
 
-static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value)
+static void mdio_write(struct net_device *dev, int phy_addr, int reg, u16 value)
 {
        struct au1000_private *aup = (struct au1000_private *) dev->priv;
-       volatile u32 *mii_control_reg;
-       volatile u32 *mii_data_reg;
+       volatile u32 *const mii_control_reg = &aup->mac->mii_control;
+       volatile u32 *const mii_data_reg = &aup->mac->mii_data;
        u32 timedout = 20;
        u32 mii_control;
 
-       #ifdef CONFIG_BCM5222_DUAL_PHY
-       if (aup->mii && aup->mii->mii_control_reg) {
-               mii_control_reg = aup->mii->mii_control_reg;
-               mii_data_reg = aup->mii->mii_data_reg;
-       }
-       else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
-               /* assume both phys are controlled through mac0 */
-               mii_control_reg = au_macs[0]->mii->mii_control_reg;
-               mii_data_reg = au_macs[0]->mii->mii_data_reg;
-       }
-       else 
-       #endif
-       {
-               /* default control and data reg addresses */
-               mii_control_reg = &aup->mac->mii_control;
-               mii_data_reg = &aup->mac->mii_data;
-       }
-
        while (*mii_control_reg & MAC_MII_BUSY) {
                mdelay(1);
                if (--timedout == 0) {
@@ -887,165 +249,145 @@ static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value)
        }
 
        mii_control = MAC_SET_MII_SELECT_REG(reg) | 
-               MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_WRITE;
+               MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_WRITE;
 
        *mii_data_reg = value;
        *mii_control_reg = mii_control;
 }
 
+static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+       /* WARNING: bus->phy_map[phy_addr].attached_dev == dev does
+        * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus) */
+       struct net_device *const dev = bus->priv;
+
+       enable_mac(dev, 0); /* make sure the MAC associated with this
+                            * mii_bus is enabled */
+       return mdio_read(dev, phy_addr, regnum);
+}
 
-static void dump_mii(struct net_device *dev, int phy_id)
+static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+                        u16 value)
 {
-       int i, val;
+       struct net_device *const dev = bus->priv;
 
-       for (i = 0; i < 7; i++) {
-               if ((val = mdio_read(dev, phy_id, i)) >= 0)
-                       printk("%s: MII Reg %d=%x\n", dev->name, i, val);
-       }
-       for (i = 16; i < 25; i++) {
-               if ((val = mdio_read(dev, phy_id, i)) >= 0)
-                       printk("%s: MII Reg %d=%x\n", dev->name, i, val);
-       }
+       enable_mac(dev, 0); /* make sure the MAC associated with this
+                            * mii_bus is enabled */
+       mdio_write(dev, phy_addr, regnum, value);
+       return 0;
 }
 
-static int mii_probe (struct net_device * dev)
+static int mdiobus_reset(struct mii_bus *bus)
 {
-       struct au1000_private *aup = (struct au1000_private *) dev->priv;
-       int phy_addr;
-#ifdef CONFIG_MIPS_BOSPORUS
-       int phy_found=0;
-#endif
+       struct net_device *const dev = bus->priv;
 
-       /* search for total of 32 possible mii phy addresses */
-       for (phy_addr = 0; phy_addr < 32; phy_addr++) {
-               u16 mii_status;
-               u16 phy_id0, phy_id1;
-               int i;
+       enable_mac(dev, 0); /* make sure the MAC associated with this
+                            * mii_bus is enabled */
+       return 0;
+}
 
-               #ifdef CONFIG_BCM5222_DUAL_PHY
-               /* Mask the already found phy, try next one */
-               if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
-                       if (au_macs[0]->phy_addr == phy_addr)
-                               continue;
-               }
-               #endif
-
-               mii_status = mdio_read(dev, phy_addr, MII_STATUS);
-               if (mii_status == 0xffff || mii_status == 0x0000)
-                       /* the mii is not accessable, try next one */
-                       continue;
-
-               phy_id0 = mdio_read(dev, phy_addr, MII_PHY_ID0);
-               phy_id1 = mdio_read(dev, phy_addr, MII_PHY_ID1);
-
-               /* search our mii table for the current mii */ 
-               for (i = 0; mii_chip_table[i].phy_id1; i++) {
-                       if (phy_id0 == mii_chip_table[i].phy_id0 &&
-                           phy_id1 == mii_chip_table[i].phy_id1) {
-                               struct mii_phy * mii_phy = aup->mii;
-
-                               printk(KERN_INFO "%s: %s at phy address %d\n",
-                                      dev->name, mii_chip_table[i].name, 
-                                      phy_addr);
-#ifdef CONFIG_MIPS_BOSPORUS
-                               phy_found = 1;
-#endif
-                               mii_phy->chip_info = mii_chip_table+i;
-                               aup->phy_addr = phy_addr;
-                               aup->want_autoneg = 1;
-                               aup->phy_ops = mii_chip_table[i].phy_ops;
-                               aup->phy_ops->phy_init(dev,phy_addr);
-
-                               // Check for dual-phy and then store required 
-                               // values and set indicators. We need to do 
-                               // this now since mdio_{read,write} need the 
-                               // control and data register addresses.
-                               #ifdef CONFIG_BCM5222_DUAL_PHY
-                               if ( mii_chip_table[i].dual_phy) {
-
-                                       /* assume both phys are controlled 
-                                        * through MAC0. Board specific? */
-                                       
-                                       /* sanity check */
-                                       if (!au_macs[0] || !au_macs[0]->mii)
-                                               return -1;
-                                       aup->mii->mii_control_reg = (u32 *)
-                                               &au_macs[0]->mac->mii_control;
-                                       aup->mii->mii_data_reg = (u32 *)
-                                               &au_macs[0]->mac->mii_data;
-                               }
-                               #endif
-                               goto found;
-                       }
+static int mii_probe (struct net_device *dev)
+{
+       struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+       struct phy_device *phydev = NULL;
+
+#if defined(AU1XXX_PHY_STATIC_CONFIG)
+       BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
+
+       if(aup->mac_id == 0) { /* get PHY0 */
+# if defined(AU1XXX_PHY0_ADDR)
+               phydev = au_macs[AU1XXX_PHY0_BUSID]->mii_bus.phy_map[AU1XXX_PHY0_ADDR];
+# else
+               printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
+                       dev->name);
+               return 0;
+# endif /* defined(AU1XXX_PHY0_ADDR) */
+       } else if (aup->mac_id == 1) { /* get PHY1 */
+# if defined(AU1XXX_PHY1_ADDR)
+               phydev = au_macs[AU1XXX_PHY1_BUSID]->mii_bus.phy_map[AU1XXX_PHY1_ADDR];
+# else
+               printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
+                       dev->name);
+               return 0;
+# endif /* defined(AU1XXX_PHY1_ADDR) */
+       }
+
+#else /* defined(AU1XXX_PHY_STATIC_CONFIG) */
+       int phy_addr;
+
+       /* find the first (lowest address) PHY on the current MAC's MII bus */
+       for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
+               if (aup->mii_bus.phy_map[phy_addr]) {
+                       phydev = aup->mii_bus.phy_map[phy_addr];
+# if !defined(AU1XXX_PHY_SEARCH_HIGHEST_ADDR)
+                       break; /* break out with first one found */
+# endif
                }
-       }
-found:
-
-#ifdef CONFIG_MIPS_BOSPORUS
-       /* This is a workaround for the Micrel/Kendin 5 port switch
-          The second MAC doesn't see a PHY connected... so we need to
-          trick it into thinking we have one.
-               
-          If this kernel is run on another Au1500 development board
-          the stub will be found as well as the actual PHY. However,
-          the last found PHY will be used... usually at Addr 31 (Db1500).      
-       */
-       if ( (!phy_found) )
-       {
-               u16 phy_id0, phy_id1;
-               int i;
 
-               phy_id0 = 0x1234;
-               phy_id1 = 0x5678;
-
-               /* search our mii table for the current mii */ 
-               for (i = 0; mii_chip_table[i].phy_id1; i++) {
-                       if (phy_id0 == mii_chip_table[i].phy_id0 &&
-                           phy_id1 == mii_chip_table[i].phy_id1) {
-                               struct mii_phy * mii_phy;
-
-                               printk(KERN_INFO "%s: %s at phy address %d\n",
-                                      dev->name, mii_chip_table[i].name, 
-                                      phy_addr);
-                               mii_phy = kmalloc(sizeof(struct mii_phy), 
-                                               GFP_KERNEL);
-                               if (mii_phy) {
-                                       mii_phy->chip_info = mii_chip_table+i;
-                                       aup->phy_addr = phy_addr;
-                                       mii_phy->next = aup->mii;
-                                       aup->phy_ops = 
-                                               mii_chip_table[i].phy_ops;
-                                       aup->mii = mii_phy;
-                                       aup->phy_ops->phy_init(dev,phy_addr);
-                               } else {
-                                       printk(KERN_ERR "%s: out of memory\n", 
-                                                       dev->name);
-                                       return -1;
-                               }
-                               mii_phy->chip_info = mii_chip_table+i;
-                               aup->phy_addr = phy_addr;
-                               aup->phy_ops = mii_chip_table[i].phy_ops;
-                               aup->phy_ops->phy_init(dev,phy_addr);
-                               break;
-                       }
+# if defined(AU1XXX_PHY1_SEARCH_ON_MAC0)
+       /* try harder to find a PHY */
+       if (!phydev && (aup->mac_id == 1)) {
+               /* no PHY found, maybe we have a dual PHY? */
+               printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, "
+                       "let's see if it's attached to MAC0...\n");
+
+               BUG_ON(!au_macs[0]);
+
+               /* find the first (lowest address) non-attached PHY on
+                * the MAC0 MII bus */
+               for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+                       struct phy_device *const tmp_phydev =
+                               au_macs[0]->mii_bus.phy_map[phy_addr];
+
+                       if (!tmp_phydev)
+                               continue; /* no PHY here... */
+
+                       if (tmp_phydev->attached_dev)
+                               continue; /* already claimed by MAC0 */
+
+                       phydev = tmp_phydev;
+                       break; /* found it */
                }
        }
-       if (aup->mac_id == 0) {
-               /* the Bosporus phy responds to addresses 0-5 but 
-                * 5 is the correct one.
-                */
-               aup->phy_addr = 5;
-       }
-#endif
+# endif /* defined(AU1XXX_PHY1_SEARCH_OTHER_BUS) */
 
-       if (aup->mii->chip_info == NULL) {
-               printk(KERN_ERR "%s: Au1x No known MII transceivers found!\n",
-                               dev->name);
+#endif /* defined(AU1XXX_PHY_STATIC_CONFIG) */
+       if (!phydev) {
+               printk (KERN_ERR DRV_NAME ":%s: no PHY found\n", dev->name);
                return -1;
        }
 
-       printk(KERN_INFO "%s: Using %s as default\n", 
-                       dev->name, aup->mii->chip_info->name);
+       /* now we are supposed to have a proper phydev, to attach to... */
+       BUG_ON(!phydev);
+       BUG_ON(phydev->attached_dev);
+
+       phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0);
+
+       if (IS_ERR(phydev)) {
+               printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+               return PTR_ERR(phydev);
+       }
+
+       /* mask with MAC supported features */
+       phydev->supported &= (SUPPORTED_10baseT_Half
+                             | SUPPORTED_10baseT_Full
+                             | SUPPORTED_100baseT_Half
+                             | SUPPORTED_100baseT_Full
+                             | SUPPORTED_Autoneg
+                             /* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */
+                             | SUPPORTED_MII
+                             | SUPPORTED_TP);
+
+       phydev->advertising = phydev->supported;
+
+       aup->old_link = 0;
+       aup->old_speed = 0;
+       aup->old_duplex = -1;
+       aup->phy_dev = phydev;
+
+       printk(KERN_INFO "%s: attached PHY driver [%s] "
+              "(mii_bus:phy_addr=%s, irq=%d)\n",
+              dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
 
        return 0;
 }
@@ -1097,35 +439,38 @@ static void hard_stop(struct net_device *dev)
        au_sync_delay(10);
 }
 
-
-static void reset_mac(struct net_device *dev)
+static void enable_mac(struct net_device *dev, int force_reset)
 {
-       int i;
-       u32 flags;
+       unsigned long flags;
        struct au1000_private *aup = (struct au1000_private *) dev->priv;
 
-       if (au1000_debug > 4) 
-               printk(KERN_INFO "%s: reset mac, aup %x\n", 
-                               dev->name, (unsigned)aup);
-
        spin_lock_irqsave(&aup->lock, flags);
-       if (aup->timer.function == &au1000_timer) {/* check if timer initted */
-               del_timer(&aup->timer);
-       }
 
-       hard_stop(dev);
-       #ifdef CONFIG_BCM5222_DUAL_PHY
-       if (aup->mac_id != 0) {
-       #endif
-               /* If BCM5222, we can't leave MAC0 in reset because then 
-                * we can't access the dual phy for ETH1 */
+       if(force_reset || (!aup->mac_enabled)) {
                *aup->enable = MAC_EN_CLOCK_ENABLE;
                au_sync_delay(2);
-               *aup->enable = 0;
+               *aup->enable = (MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
+                               | MAC_EN_CLOCK_ENABLE);
                au_sync_delay(2);
-       #ifdef CONFIG_BCM5222_DUAL_PHY
+
+               aup->mac_enabled = 1;
        }
-       #endif
+
+       spin_unlock_irqrestore(&aup->lock, flags);
+}
+
+static void reset_mac_unlocked(struct net_device *dev)
+{
+       struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+       int i;
+
+       hard_stop(dev);
+
+       *aup->enable = MAC_EN_CLOCK_ENABLE;
+       au_sync_delay(2);
+       *aup->enable = 0;
+       au_sync_delay(2);
+
        aup->tx_full = 0;
        for (i = 0; i < NUM_RX_DMA; i++) {
                /* reset control bits */
@@ -1135,9 +480,26 @@ static void reset_mac(struct net_device *dev)
                /* reset control bits */
                aup->tx_dma_ring[i]->buff_stat &= ~0xf;
        }
-       spin_unlock_irqrestore(&aup->lock, flags);
+
+       aup->mac_enabled = 0;
+
 }
 
+static void reset_mac(struct net_device *dev)
+{
+       struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+       unsigned long flags;
+
+       if (au1000_debug > 4)
+               printk(KERN_INFO "%s: reset mac, aup %x\n",
+                      dev->name, (unsigned)aup);
+
+       spin_lock_irqsave(&aup->lock, flags);
+
+       reset_mac_unlocked (dev);
+
+       spin_unlock_irqrestore(&aup->lock, flags);
+}
 
 /* 
  * Setup the receive and transmit "rings".  These pointers are the addresses
@@ -1160,12 +522,27 @@ setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base)
 }
 
 static struct {
-       int port;
        u32 base_addr;
        u32 macen_addr;
        int irq;
        struct net_device *dev;
-} iflist[2];
+} iflist[2] = {
+#ifdef CONFIG_SOC_AU1000
+       {AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT},
+       {AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT}
+#endif
+#ifdef CONFIG_SOC_AU1100
+       {AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT}
+#endif
+#ifdef CONFIG_SOC_AU1500
+       {AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT},
+       {AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT}
+#endif
+#ifdef CONFIG_SOC_AU1550
+       {AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT},
+       {AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT}
+#endif
+};
 
 static int num_ifs;
 
@@ -1176,58 +553,14 @@ static int num_ifs;
  */
 static int __init au1000_init_module(void)
 {
-       struct cpuinfo_mips *c = &current_cpu_data;
        int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
        struct net_device *dev;
        int i, found_one = 0;
 
-       switch (c->cputype) {
-#ifdef CONFIG_SOC_AU1000
-       case CPU_AU1000:
-               num_ifs = 2 - ni;
-               iflist[0].base_addr = AU1000_ETH0_BASE;
-               iflist[1].base_addr = AU1000_ETH1_BASE;
-               iflist[0].macen_addr = AU1000_MAC0_ENABLE;
-               iflist[1].macen_addr = AU1000_MAC1_ENABLE;
-               iflist[0].irq = AU1000_MAC0_DMA_INT;
-               iflist[1].irq = AU1000_MAC1_DMA_INT;
-               break;
-#endif
-#ifdef CONFIG_SOC_AU1100
-       case CPU_AU1100:
-               num_ifs = 1 - ni;
-               iflist[0].base_addr = AU1100_ETH0_BASE;
-               iflist[0].macen_addr = AU1100_MAC0_ENABLE;
-               iflist[0].irq = AU1100_MAC0_DMA_INT;
-               break;
-#endif
-#ifdef CONFIG_SOC_AU1500
-       case CPU_AU1500:
-               num_ifs = 2 - ni;
-               iflist[0].base_addr = AU1500_ETH0_BASE;
-               iflist[1].base_addr = AU1500_ETH1_BASE;
-               iflist[0].macen_addr = AU1500_MAC0_ENABLE;
-               iflist[1].macen_addr = AU1500_MAC1_ENABLE;
-               iflist[0].irq = AU1500_MAC0_DMA_INT;
-               iflist[1].irq = AU1500_MAC1_DMA_INT;
-               break;
-#endif
-#ifdef CONFIG_SOC_AU1550
-       case CPU_AU1550:
-               num_ifs = 2 - ni;
-               iflist[0].base_addr = AU1550_ETH0_BASE;
-               iflist[1].base_addr = AU1550_ETH1_BASE;
-               iflist[0].macen_addr = AU1550_MAC0_ENABLE;
-               iflist[1].macen_addr = AU1550_MAC1_ENABLE;
-               iflist[0].irq = AU1550_MAC0_DMA_INT;
-               iflist[1].irq = AU1550_MAC1_DMA_INT;
-               break;
-#endif
-       default:
-               num_ifs = 0;
-       }
+       num_ifs = NUM_ETH_INTERFACES - ni;
+
        for(i = 0; i < num_ifs; i++) {
-               dev = au1000_probe(iflist[i].base_addr, iflist[i].irq, i);
+               dev = au1000_probe(i);
                iflist[i].dev = dev;
                if (dev)
                        found_one++;
@@ -1237,178 +570,31 @@ static int __init au1000_init_module(void)
        return 0;
 }
 
-static int au1000_setup_aneg(struct net_device *dev, u32 advertise)
-{
-       struct au1000_private *aup = (struct au1000_private *)dev->priv;
-       u16 ctl, adv;
-
-       /* Setup standard advertise */
-       adv = mdio_read(dev, aup->phy_addr, MII_ADVERTISE);
-       adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-       if (advertise & ADVERTISED_10baseT_Half)
-               adv |= ADVERTISE_10HALF;
-       if (advertise & ADVERTISED_10baseT_Full)
-               adv |= ADVERTISE_10FULL;
-       if (advertise & ADVERTISED_100baseT_Half)
-               adv |= ADVERTISE_100HALF;
-       if (advertise & ADVERTISED_100baseT_Full)
-               adv |= ADVERTISE_100FULL;
-       mdio_write(dev, aup->phy_addr, MII_ADVERTISE, adv);
-
-       /* Start/Restart aneg */
-       ctl = mdio_read(dev, aup->phy_addr, MII_BMCR);
-       ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-       mdio_write(dev, aup->phy_addr, MII_BMCR, ctl);
-
-       return 0;
-}
+/*
+ * ethtool operations
+ */
 
-static int au1000_setup_forced(struct net_device *dev, int speed, int fd)
+static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct au1000_private *aup = (struct au1000_private *)dev->priv;
-       u16 ctl;
-
-       ctl = mdio_read(dev, aup->phy_addr, MII_BMCR);
-       ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE);
-
-       /* First reset the PHY */
-       mdio_write(dev, aup->phy_addr, MII_BMCR, ctl | BMCR_RESET);
-
-       /* Select speed & duplex */
-       switch (speed) {
-               case SPEED_10:
-                       break;
-               case SPEED_100:
-                       ctl |= BMCR_SPEED100;
-                       break;
-               case SPEED_1000:
-               default:
-                       return -EINVAL;
-       }
-       if (fd == DUPLEX_FULL)
-               ctl |= BMCR_FULLDPLX;
-       mdio_write(dev, aup->phy_addr, MII_BMCR, ctl);
-
-       return 0;
-}
 
+       if (aup->phy_dev)
+               return phy_ethtool_gset(aup->phy_dev, cmd);
 
-static void
-au1000_start_link(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       struct au1000_private *aup = (struct au1000_private *)dev->priv;
-       u32 advertise;
-       int autoneg;
-       int forced_speed;
-       int forced_duplex;
-
-       /* Default advertise */
-       advertise = GENMII_DEFAULT_ADVERTISE;
-       autoneg = aup->want_autoneg;
-       forced_speed = SPEED_100;
-       forced_duplex = DUPLEX_FULL;
-
-       /* Setup link parameters */
-       if (cmd) {
-               if (cmd->autoneg == AUTONEG_ENABLE) {
-                       advertise = cmd->advertising;
-                       autoneg = 1;
-               } else {
-                       autoneg = 0;
-
-                       forced_speed = cmd->speed;
-                       forced_duplex = cmd->duplex;
-               }
-       }
-
-       /* Configure PHY & start aneg */
-       aup->want_autoneg = autoneg;
-       if (autoneg)
-               au1000_setup_aneg(dev, advertise);
-       else
-               au1000_setup_forced(dev, forced_speed, forced_duplex);
-       mod_timer(&aup->timer, jiffies + HZ);
+       return -EINVAL;
 }
 
-static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct au1000_private *aup = (struct au1000_private *)dev->priv;
-       u16 link, speed;
-
-       cmd->supported = GENMII_DEFAULT_FEATURES;
-       cmd->advertising = GENMII_DEFAULT_ADVERTISE;
-       cmd->port = PORT_MII;
-       cmd->transceiver = XCVR_EXTERNAL;
-       cmd->phy_address = aup->phy_addr;
-       spin_lock_irq(&aup->lock);
-       cmd->autoneg = aup->want_autoneg;
-       aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed);
-       if ((speed == IF_PORT_100BASETX) || (speed == IF_PORT_100BASEFX))
-               cmd->speed = SPEED_100;
-       else if (speed == IF_PORT_10BASET)
-               cmd->speed = SPEED_10;
-       if (link && (dev->if_port == IF_PORT_100BASEFX))
-               cmd->duplex = DUPLEX_FULL;
-       else
-               cmd->duplex = DUPLEX_HALF;
-       spin_unlock_irq(&aup->lock);
-       return 0;
-}
 
-static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-        struct au1000_private *aup = (struct au1000_private *)dev->priv;
-         unsigned long features = GENMII_DEFAULT_FEATURES;
-
-        if (!capable(CAP_NET_ADMIN))
-                return -EPERM;
-
-        if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
-                return -EINVAL;
-        if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
-                return -EINVAL;
-        if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL)
-                return -EINVAL;
-        if (cmd->autoneg == AUTONEG_DISABLE)
-                switch (cmd->speed) {
-                case SPEED_10:
-                        if (cmd->duplex == DUPLEX_HALF &&
-                                (features & SUPPORTED_10baseT_Half) == 0)
-                                return -EINVAL;
-                        if (cmd->duplex == DUPLEX_FULL &&
-                                (features & SUPPORTED_10baseT_Full) == 0)
-                                return -EINVAL;
-                        break;
-                case SPEED_100:
-                        if (cmd->duplex == DUPLEX_HALF &&
-                                (features & SUPPORTED_100baseT_Half) == 0)
-                                return -EINVAL;
-                        if (cmd->duplex == DUPLEX_FULL &&
-                                (features & SUPPORTED_100baseT_Full) == 0)
-                                return -EINVAL;
-                        break;
-                default:
-                        return -EINVAL;
-                }
-        else if ((features & SUPPORTED_Autoneg) == 0)
-                return -EINVAL;
-
-        spin_lock_irq(&aup->lock);
-        au1000_start_link(dev, cmd);
-        spin_unlock_irq(&aup->lock);
-        return 0;
-}
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
 
-static int au1000_nway_reset(struct net_device *dev)
-{
-       struct au1000_private *aup = (struct au1000_private *)dev->priv;
+       if (aup->phy_dev)
+               return phy_ethtool_sset(aup->phy_dev, cmd);
 
-       if (!aup->want_autoneg)
-               return -EINVAL;
-       spin_lock_irq(&aup->lock);
-       au1000_start_link(dev, NULL);
-       spin_unlock_irq(&aup->lock);
-       return 0;
+       return -EINVAL;
 }
 
 static void
@@ -1423,21 +609,14 @@ au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
        info->regdump_len = 0;
 }
 
-static u32 au1000_get_link(struct net_device *dev)
-{
-       return netif_carrier_ok(dev);
-}
-
 static struct ethtool_ops au1000_ethtool_ops = {
        .get_settings = au1000_get_settings,
        .set_settings = au1000_set_settings,
        .get_drvinfo = au1000_get_drvinfo,
-       .nway_reset = au1000_nway_reset,
-       .get_link = au1000_get_link
+       .get_link = ethtool_op_get_link,
 };
 
-static struct net_device *
-au1000_probe(u32 ioaddr, int irq, int port_num)
+static struct net_device * au1000_probe(int port_num)
 {
        static unsigned version_printed = 0;
        struct au1000_private *aup = NULL;
@@ -1445,106 +624,115 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
        db_dest_t *pDB, *pDBfree;
        char *pmac, *argptr;
        char ethaddr[6];
-       int i, err;
+       int irq, i, err;
+       u32 base, macen;
+
+       if (port_num >= NUM_ETH_INTERFACES)
+               return NULL;
 
-       if (!request_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE, "Au1x00 ENET"))
+       base  = CPHYSADDR(iflist[port_num].base_addr );
+       macen = CPHYSADDR(iflist[port_num].macen_addr);
+       irq = iflist[port_num].irq;
+
+       if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") ||
+           !request_mem_region(macen, 4, "Au1x00 ENET"))
                return NULL;
 
-       if (version_printed++ == 0) 
+       if (version_printed++ == 0)
                printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
 
        dev = alloc_etherdev(sizeof(struct au1000_private));
        if (!dev) {
-               printk (KERN_ERR "au1000 eth: alloc_etherdev failed\n");  
+               printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
                return NULL;
        }
 
-       if ((err = register_netdev(dev))) {
-               printk(KERN_ERR "Au1x_eth Cannot register net device err %d\n",
-                               err);
+       if ((err = register_netdev(dev)) != 0) {
+               printk(KERN_ERR "%s: Cannot register net device, error %d\n",
+                               DRV_NAME, err);
                free_netdev(dev);
                return NULL;
        }
 
-       printk("%s: Au1x Ethernet found at 0x%x, irq %d\n", 
-                       dev->name, ioaddr, irq);
+       printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
+               dev->name, base, irq);
 
        aup = dev->priv;
 
        /* Allocate the data buffers */
        /* Snooping works fine with eth on all au1xxx */
-       aup->vaddr = (u32)dma_alloc_noncoherent(NULL,
-                       MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
-                       &aup->dma_addr,
-                       0);
+       aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
+                                               (NUM_TX_BUFFS + NUM_RX_BUFFS),
+                                               &aup->dma_addr, 0);
        if (!aup->vaddr) {
                free_netdev(dev);
-               release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+               release_mem_region( base, MAC_IOSIZE);
+               release_mem_region(macen, 4);
                return NULL;
        }
 
        /* aup->mac is the base address of the MAC's registers */
-       aup->mac = (volatile mac_reg_t *)((unsigned long)ioaddr);
+       aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr;
+
        /* Setup some variables for quick register address access */
-       if (ioaddr == iflist[0].base_addr)
-       {
-               /* check env variables first */
-               if (!get_ethernet_addr(ethaddr)) { 
+       aup->enable = (volatile u32 *)iflist[port_num].macen_addr;
+       aup->mac_id = port_num;
+       au_macs[port_num] = aup;
+
+       if (port_num == 0) {
+               /* Check the environment variables first */
+               if (get_ethernet_addr(ethaddr) == 0)
                        memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
-               else {
+               else {
                        /* Check command line */
                        argptr = prom_getcmdline();
-                       if ((pmac = strstr(argptr, "ethaddr=")) == NULL) {
-                               printk(KERN_INFO "%s: No mac address found\n", 
-                                               dev->name);
-                               /* use the hard coded mac addresses */
-                       else {
+                       if ((pmac = strstr(argptr, "ethaddr=")) == NULL)
+                               printk(KERN_INFO "%s: No MAC address found\n",
+                                                dev->name);
+                               /* Use the hard coded MAC addresses */
+                       else {
                                str2eaddr(ethaddr, pmac + strlen("ethaddr="));
                                memcpy(au1000_mac_addr, ethaddr, 
-                                               sizeof(au1000_mac_addr));
+                                      sizeof(au1000_mac_addr));
                        }
                }
-                       aup->enable = (volatile u32 *) 
-                               ((unsigned long)iflist[0].macen_addr);
-               memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+
                setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
-               aup->mac_id = 0;
-               au_macs[0] = aup;
-       }
-               else
-       if (ioaddr == iflist[1].base_addr)
-       {
-                       aup->enable = (volatile u32 *) 
-                               ((unsigned long)iflist[1].macen_addr);
-               memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
-               dev->dev_addr[4] += 0x10;
+       } else if (port_num == 1)
                setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
-               aup->mac_id = 1;
-               au_macs[1] = aup;
-       }
-       else
-       {
-               printk(KERN_ERR "%s: bad ioaddr\n", dev->name);
-       }
-
-       /* bring the device out of reset, otherwise probing the mii
-        * will hang */
-       *aup->enable = MAC_EN_CLOCK_ENABLE;
-       au_sync_delay(2);
-       *aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
-               MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
-       au_sync_delay(2);
 
-       aup->mii = kmalloc(sizeof(struct mii_phy), GFP_KERNEL);
-       if (!aup->mii) {
-               printk(KERN_ERR "%s: out of memory\n", dev->name);
-               goto err_out;
-       }
-       aup->mii->next = NULL;
-       aup->mii->chip_info = NULL;
-       aup->mii->status = 0;
-       aup->mii->mii_control_reg = 0;
-       aup->mii->mii_data_reg = 0;
+       /*
+        * Assign to the Ethernet ports two consecutive MAC addresses
+        * to match those that are printed on their stickers
+        */
+       memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+       dev->dev_addr[5] += port_num;
+
+       *aup->enable = 0;
+       aup->mac_enabled = 0;
+
+       aup->mii_bus.priv = dev;
+       aup->mii_bus.read = mdiobus_read;
+       aup->mii_bus.write = mdiobus_write;
+       aup->mii_bus.reset = mdiobus_reset;
+       aup->mii_bus.name = "au1000_eth_mii";
+       aup->mii_bus.id = aup->mac_id;
+       aup->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+       for(i = 0; i < PHY_MAX_ADDR; ++i)
+               aup->mii_bus.irq[i] = PHY_POLL;
+
+       /* if known, set corresponding PHY IRQs */
+#if defined(AU1XXX_PHY_STATIC_CONFIG)
+# if defined(AU1XXX_PHY0_IRQ)
+       if (AU1XXX_PHY0_BUSID == aup->mii_bus.id)
+               aup->mii_bus.irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
+# endif
+# if defined(AU1XXX_PHY1_IRQ)
+       if (AU1XXX_PHY1_BUSID == aup->mii_bus.id)
+               aup->mii_bus.irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
+# endif
+#endif
+       mdiobus_register(&aup->mii_bus);
 
        if (mii_probe(dev) != 0) {
                goto err_out;
@@ -1581,7 +769,7 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
        }
 
        spin_lock_init(&aup->lock);
-       dev->base_addr = ioaddr;
+       dev->base_addr = base;
        dev->irq = irq;
        dev->open = au1000_open;
        dev->hard_start_xmit = au1000_tx;
@@ -1590,7 +778,6 @@ au1000_probe(u32 ioaddr, int irq, int port_num)
        dev->set_multicast_list = &set_rx_mode;
        dev->do_ioctl = &au1000_ioctl;
        SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
-       dev->set_config = &au1000_set_config;
        dev->tx_timeout = au1000_tx_timeout;
        dev->watchdog_timeo = ETH_TX_TIMEOUT;
 
@@ -1606,7 +793,7 @@ err_out:
        /* here we should have a valid dev plus aup-> register addresses
         * so we can reset the mac properly.*/
        reset_mac(dev);
-       kfree(aup->mii);
+
        for (i = 0; i < NUM_RX_DMA; i++) {
                if (aup->rx_db_inuse[i])
                        ReleaseDB(aup, aup->rx_db_inuse[i]);
@@ -1615,13 +802,12 @@ err_out:
                if (aup->tx_db_inuse[i])
                        ReleaseDB(aup, aup->tx_db_inuse[i]);
        }
-       dma_free_noncoherent(NULL,
-                       MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
-                       (void *)aup->vaddr,
-                       aup->dma_addr);
+       dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
+                            (void *)aup->vaddr, aup->dma_addr);
        unregister_netdev(dev);
        free_netdev(dev);
-       release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+       release_mem_region( base, MAC_IOSIZE);
+       release_mem_region(macen, 4);
        return NULL;
 }
 
@@ -1640,19 +826,14 @@ static int au1000_init(struct net_device *dev)
        u32 flags;
        int i;
        u32 control;
-       u16 link, speed;
 
        if (au1000_debug > 4) 
                printk("%s: au1000_init\n", dev->name);
 
-       spin_lock_irqsave(&aup->lock, flags);
-
        /* bring the device out of reset */
-       *aup->enable = MAC_EN_CLOCK_ENABLE;
-        au_sync_delay(2);
-       *aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
-               MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
-       au_sync_delay(20);
+       enable_mac(dev, 1);
+
+       spin_lock_irqsave(&aup->lock, flags);
 
        aup->mac->control = 0;
        aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2;
@@ -1668,12 +849,16 @@ static int au1000_init(struct net_device *dev)
        }
        au_sync();
 
-       aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed);
-       control = MAC_DISABLE_RX_OWN | MAC_RX_ENABLE | MAC_TX_ENABLE;
+       control = MAC_RX_ENABLE | MAC_TX_ENABLE;
 #ifndef CONFIG_CPU_LITTLE_ENDIAN
        control |= MAC_BIG_ENDIAN;
 #endif
-       if (link && (dev->if_port == IF_PORT_100BASEFX)) {
+       if (aup->phy_dev) {
+               if (aup->phy_dev->link && (DUPLEX_FULL == aup->phy_dev->duplex))
+                       control |= MAC_FULL_DUPLEX;
+               else
+                       control |= MAC_DISABLE_RX_OWN;
+       } else { /* PHY-less op, assume full-duplex */
                control |= MAC_FULL_DUPLEX;
        }
 
@@ -1685,57 +870,84 @@ static int au1000_init(struct net_device *dev)
        return 0;
 }
 
-static void au1000_timer(unsigned long data)
+static void
+au1000_adjust_link(struct net_device *dev)
 {
-       struct net_device *dev = (struct net_device *)data;
        struct au1000_private *aup = (struct au1000_private *) dev->priv;
-       unsigned char if_port;
-       u16 link, speed;
+       struct phy_device *phydev = aup->phy_dev;
+       unsigned long flags;
 
-       if (!dev) {
-               /* fatal error, don't restart the timer */
-               printk(KERN_ERR "au1000_timer error: NULL dev\n");
-               return;
-       }
+       int status_change = 0;
 
-       if_port = dev->if_port;
-       if (aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed) == 0) {
-               if (link) {
-                       if (!netif_carrier_ok(dev)) {
-                               netif_carrier_on(dev);
-                               printk(KERN_INFO "%s: link up\n", dev->name);
-                       }
-               }
-               else {
-                       if (netif_carrier_ok(dev)) {
-                               netif_carrier_off(dev);
-                               dev->if_port = 0;
-                               printk(KERN_INFO "%s: link down\n", dev->name);
-                       }
+       BUG_ON(!aup->phy_dev);
+
+       spin_lock_irqsave(&aup->lock, flags);
+
+       if (phydev->link && (aup->old_speed != phydev->speed)) {
+               // speed changed
+
+               switch(phydev->speed) {
+               case SPEED_10:
+               case SPEED_100:
+                       break;
+               default:
+                       printk(KERN_WARNING
+                              "%s: Speed (%d) is not 10/100 ???\n",
+                              dev->name, phydev->speed);
+                       break;
                }
+
+               aup->old_speed = phydev->speed;
+
+               status_change = 1;
        }
 
-       if (link && (dev->if_port != if_port) && 
-                       (dev->if_port != IF_PORT_UNKNOWN)) {
+       if (phydev->link && (aup->old_duplex != phydev->duplex)) {
+               // duplex mode changed
+
+               /* switching duplex mode requires to disable rx and tx! */
                hard_stop(dev);
-               if (dev->if_port == IF_PORT_100BASEFX) {
-                       printk(KERN_INFO "%s: going to full duplex\n", 
-                                       dev->name);
-                       aup->mac->control |= MAC_FULL_DUPLEX;
-                       au_sync_delay(1);
-               }
-               else {
-                       aup->mac->control &= ~MAC_FULL_DUPLEX;
-                       au_sync_delay(1);
-               }
+
+               if (DUPLEX_FULL == phydev->duplex)
+                       aup->mac->control = ((aup->mac->control
+                                            | MAC_FULL_DUPLEX)
+                                            & ~MAC_DISABLE_RX_OWN);
+               else
+                       aup->mac->control = ((aup->mac->control
+                                             & ~MAC_FULL_DUPLEX)
+                                            | MAC_DISABLE_RX_OWN);
+               au_sync_delay(1);
+
                enable_rx_tx(dev);
+               aup->old_duplex = phydev->duplex;
+
+               status_change = 1;
+       }
+
+       if(phydev->link != aup->old_link) {
+               // link state changed
+
+               if (phydev->link) // link went up
+                       netif_schedule(dev);
+               else { // link went down
+                       aup->old_speed = 0;
+                       aup->old_duplex = -1;
+               }
+
+               aup->old_link = phydev->link;
+               status_change = 1;
        }
 
-       aup->timer.expires = RUN_AT((1*HZ)); 
-       aup->timer.data = (unsigned long)dev;
-       aup->timer.function = &au1000_timer; /* timer handler */
-       add_timer(&aup->timer);
+       spin_unlock_irqrestore(&aup->lock, flags);
 
+       if (status_change) {
+               if (phydev->link)
+                       printk(KERN_INFO "%s: link up (%d/%s)\n",
+                              dev->name, phydev->speed,
+                              DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
+               else
+                       printk(KERN_INFO "%s: link down\n", dev->name);
+       }
 }
 
 static int au1000_open(struct net_device *dev)
@@ -1746,25 +958,26 @@ static int au1000_open(struct net_device *dev)
        if (au1000_debug > 4)
                printk("%s: open: dev=%p\n", dev->name, dev);
 
+       if ((retval = request_irq(dev->irq, &au1000_interrupt, 0,
+                                       dev->name, dev))) {
+               printk(KERN_ERR "%s: unable to get IRQ %d\n",
+                               dev->name, dev->irq);
+               return retval;
+       }
+
        if ((retval = au1000_init(dev))) {
                printk(KERN_ERR "%s: error in au1000_init\n", dev->name);
                free_irq(dev->irq, dev);
                return retval;
        }
-       netif_start_queue(dev);
 
-       if ((retval = request_irq(dev->irq, &au1000_interrupt, 0, 
-                                       dev->name, dev))) {
-               printk(KERN_ERR "%s: unable to get IRQ %d\n", 
-                               dev->name, dev->irq);
-               return retval;
+       if (aup->phy_dev) {
+               /* cause the PHY state machine to schedule a link state check */
+               aup->phy_dev->state = PHY_CHANGELINK;
+               phy_start(aup->phy_dev);
        }
 
-       init_timer(&aup->timer); /* used in ioctl() */
-       aup->timer.expires = RUN_AT((3*HZ)); 
-       aup->timer.data = (unsigned long)dev;
-       aup->timer.function = &au1000_timer; /* timer handler */
-       add_timer(&aup->timer);
+       netif_start_queue(dev);
 
        if (au1000_debug > 4)
                printk("%s: open: Initialization done.\n", dev->name);
@@ -1774,16 +987,19 @@ static int au1000_open(struct net_device *dev)
 
 static int au1000_close(struct net_device *dev)
 {
-       u32 flags;
-       struct au1000_private *aup = (struct au1000_private *) dev->priv;
+       unsigned long flags;
+       struct au1000_private *const aup = (struct au1000_private *) dev->priv;
 
        if (au1000_debug > 4)
                printk("%s: close: dev=%p\n", dev->name, dev);
 
-       reset_mac(dev);
+       if (aup->phy_dev)
+               phy_stop(aup->phy_dev);
 
        spin_lock_irqsave(&aup->lock, flags);
-       
+
+       reset_mac_unlocked (dev);
+
        /* stop the device */
        netif_stop_queue(dev);
 
@@ -1805,21 +1021,18 @@ static void __exit au1000_cleanup_module(void)
                if (dev) {
                        aup = (struct au1000_private *) dev->priv;
                        unregister_netdev(dev);
-                       kfree(aup->mii);
-                       for (j = 0; j < NUM_RX_DMA; j++) {
+                       for (j = 0; j < NUM_RX_DMA; j++)
                                if (aup->rx_db_inuse[j])
                                        ReleaseDB(aup, aup->rx_db_inuse[j]);
-                       }
-                       for (j = 0; j < NUM_TX_DMA; j++) {
+                       for (j = 0; j < NUM_TX_DMA; j++)
                                if (aup->tx_db_inuse[j])
                                        ReleaseDB(aup, aup->tx_db_inuse[j]);
-                       }
-                       dma_free_noncoherent(NULL,
-                                       MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
-                                       (void *)aup->vaddr,
-                                       aup->dma_addr);
+                       dma_free_noncoherent(NULL, MAX_BUF_SIZE *
+                                            (NUM_TX_BUFFS + NUM_RX_BUFFS),
+                                            (void *)aup->vaddr, aup->dma_addr);
+                       release_mem_region(dev->base_addr, MAC_IOSIZE);
+                       release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4);
                        free_netdev(dev);
-                       release_mem_region(CPHYSADDR(iflist[i].base_addr), MAC_IOSIZE);
                }
        }
 }
@@ -1830,7 +1043,7 @@ static void update_tx_stats(struct net_device *dev, u32 status)
        struct net_device_stats *ps = &aup->stats;
 
        if (status & TX_FRAME_ABORTED) {
-               if (dev->if_port == IF_PORT_100BASEFX) {
+               if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) {
                        if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) {
                                /* any other tx errors are only valid
                                 * in half duplex mode */
@@ -2104,126 +1317,15 @@ static void set_rx_mode(struct net_device *dev)
        }
 }
 
-
 static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct au1000_private *aup = (struct au1000_private *)dev->priv;
-       u16 *data = (u16 *)&rq->ifr_ifru;
-
-       switch(cmd) { 
-               case SIOCDEVPRIVATE:    /* Get the address of the PHY in use. */
-               case SIOCGMIIPHY:
-                       if (!netif_running(dev)) return -EINVAL;
-                       data[0] = aup->phy_addr;
-               case SIOCDEVPRIVATE+1:  /* Read the specified MII register. */
-               case SIOCGMIIREG:
-                       data[3] =  mdio_read(dev, data[0], data[1]); 
-                       return 0;
-               case SIOCDEVPRIVATE+2:  /* Write the specified MII register */
-               case SIOCSMIIREG: 
-                       if (!capable(CAP_NET_ADMIN))
-                               return -EPERM;
-                       mdio_write(dev, data[0], data[1],data[2]);
-                       return 0;
-               default:
-                       return -EOPNOTSUPP;
-       }
-
-}
-
-
-static int au1000_set_config(struct net_device *dev, struct ifmap *map)
-{
-       struct au1000_private *aup = (struct au1000_private *) dev->priv;
-       u16 control;
 
-       if (au1000_debug > 4)  {
-               printk("%s: set_config called: dev->if_port %d map->port %x\n", 
-                               dev->name, dev->if_port, map->port);
-       }
+       if (!netif_running(dev)) return -EINVAL;
 
-       switch(map->port){
-               case IF_PORT_UNKNOWN: /* use auto here */   
-                       printk(KERN_INFO "%s: config phy for aneg\n", 
-                                       dev->name);
-                       dev->if_port = map->port;
-                       /* Link Down: the timer will bring it up */
-                       netif_carrier_off(dev);
-       
-                       /* read current control */
-                       control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
-                       control &= ~(MII_CNTL_FDX | MII_CNTL_F100);
-
-                       /* enable auto negotiation and reset the negotiation */
-                       mdio_write(dev, aup->phy_addr, MII_CONTROL, 
-                                       control | MII_CNTL_AUTO | 
-                                       MII_CNTL_RST_AUTO);
+       if (!aup->phy_dev) return -EINVAL; // PHY not controllable
 
-                       break;
-    
-               case IF_PORT_10BASET: /* 10BaseT */         
-                       printk(KERN_INFO "%s: config phy for 10BaseT\n", 
-                                       dev->name);
-                       dev->if_port = map->port;
-       
-                       /* Link Down: the timer will bring it up */
-                       netif_carrier_off(dev);
-
-                       /* set Speed to 10Mbps, Half Duplex */
-                       control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
-                       control &= ~(MII_CNTL_F100 | MII_CNTL_AUTO | 
-                                       MII_CNTL_FDX);
-       
-                       /* disable auto negotiation and force 10M/HD mode*/
-                       mdio_write(dev, aup->phy_addr, MII_CONTROL, control);
-                       break;
-    
-               case IF_PORT_100BASET: /* 100BaseT */
-               case IF_PORT_100BASETX: /* 100BaseTx */ 
-                       printk(KERN_INFO "%s: config phy for 100BaseTX\n", 
-                                       dev->name);
-                       dev->if_port = map->port;
-       
-                       /* Link Down: the timer will bring it up */
-                       netif_carrier_off(dev);
-       
-                       /* set Speed to 100Mbps, Half Duplex */
-                       /* disable auto negotiation and enable 100MBit Mode */
-                       control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
-                       control &= ~(MII_CNTL_AUTO | MII_CNTL_FDX);
-                       control |= MII_CNTL_F100;
-                       mdio_write(dev, aup->phy_addr, MII_CONTROL, control);
-                       break;
-    
-               case IF_PORT_100BASEFX: /* 100BaseFx */
-                       printk(KERN_INFO "%s: config phy for 100BaseFX\n", 
-                                       dev->name);
-                       dev->if_port = map->port;
-       
-                       /* Link Down: the timer will bring it up */
-                       netif_carrier_off(dev);
-       
-                       /* set Speed to 100Mbps, Full Duplex */
-                       /* disable auto negotiation and enable 100MBit Mode */
-                       control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
-                       control &= ~MII_CNTL_AUTO;
-                       control |=  MII_CNTL_F100 | MII_CNTL_FDX;
-                       mdio_write(dev, aup->phy_addr, MII_CONTROL, control);
-                       break;
-               case IF_PORT_10BASE2: /* 10Base2 */
-               case IF_PORT_AUI: /* AUI */
-               /* These Modes are not supported (are they?)*/
-                       printk(KERN_ERR "%s: 10Base2/AUI not supported", 
-                                       dev->name);
-                       return -EOPNOTSUPP;
-                       break;
-    
-               default:
-                       printk(KERN_ERR "%s: Invalid media selected", 
-                                       dev->name);
-                       return -EINVAL;
-       }
-       return 0;
+       return phy_mii_ioctl(aup->phy_dev, if_mii(rq), cmd);
 }
 
 static struct net_device_stats *au1000_get_stats(struct net_device *dev)
index 7f9326e39cc0b68cff95e02bafe5ef64ac1599b2..41c2f848d2c421bd662a2002b0fd20e7c22fabf3 100644 (file)
 
 #define MULTICAST_FILTER_LIMIT 64
 
-/* FIXME 
- * The PHY defines should be in a separate file.
- */
-
-/* MII register offsets */
-#define        MII_CONTROL 0x0000
-#define MII_STATUS  0x0001
-#define MII_PHY_ID0 0x0002
-#define        MII_PHY_ID1 0x0003
-#define MII_ANADV   0x0004
-#define MII_ANLPAR  0x0005
-#define MII_AEXP    0x0006
-#define MII_ANEXT   0x0007
-#define MII_LSI_PHY_CONFIG 0x0011
-/* Status register */
-#define MII_LSI_PHY_STAT   0x0012
-#define MII_AMD_PHY_STAT   MII_LSI_PHY_STAT
-#define MII_INTEL_PHY_STAT 0x0011
-
-#define MII_AUX_CNTRL  0x0018
-/* mii registers specific to AMD 79C901 */
-#define        MII_STATUS_SUMMARY = 0x0018
-
-/* MII Control register bit definitions. */
-#define        MII_CNTL_FDX      0x0100
-#define MII_CNTL_RST_AUTO 0x0200
-#define        MII_CNTL_ISOLATE  0x0400
-#define MII_CNTL_PWRDWN   0x0800
-#define        MII_CNTL_AUTO     0x1000
-#define MII_CNTL_F100     0x2000
-#define        MII_CNTL_LPBK     0x4000
-#define MII_CNTL_RESET    0x8000
-
-/* MII Status register bit  */
-#define        MII_STAT_EXT        0x0001 
-#define MII_STAT_JAB        0x0002
-#define        MII_STAT_LINK       0x0004
-#define MII_STAT_CAN_AUTO   0x0008
-#define        MII_STAT_FAULT      0x0010 
-#define MII_STAT_AUTO_DONE  0x0020
-#define        MII_STAT_CAN_T      0x0800
-#define MII_STAT_CAN_T_FDX  0x1000
-#define        MII_STAT_CAN_TX     0x2000 
-#define MII_STAT_CAN_TX_FDX 0x4000
-#define        MII_STAT_CAN_T4     0x8000
-
-
-#define                MII_ID1_OUI_LO          0xFC00  /* low bits of OUI mask */
-#define                MII_ID1_MODEL           0x03F0  /* model number */
-#define                MII_ID1_REV             0x000F  /* model number */
-
-/* MII NWAY Register Bits ...
-   valid for the ANAR (Auto-Negotiation Advertisement) and
-   ANLPAR (Auto-Negotiation Link Partner) registers */
-#define        MII_NWAY_NODE_SEL 0x001f
-#define MII_NWAY_CSMA_CD  0x0001
-#define        MII_NWAY_T        0x0020
-#define MII_NWAY_T_FDX    0x0040
-#define        MII_NWAY_TX       0x0080
-#define MII_NWAY_TX_FDX   0x0100
-#define        MII_NWAY_T4       0x0200 
-#define MII_NWAY_PAUSE    0x0400 
-#define        MII_NWAY_RF       0x2000 /* Remote Fault */
-#define MII_NWAY_ACK      0x4000 /* Remote Acknowledge */
-#define        MII_NWAY_NP       0x8000 /* Next Page (Enable) */
-
-/* mii stsout register bits */
-#define        MII_STSOUT_LINK_FAIL 0x4000
-#define        MII_STSOUT_SPD       0x0080
-#define MII_STSOUT_DPLX      0x0040
-
-/* mii stsics register bits */
-#define        MII_STSICS_SPD       0x8000
-#define MII_STSICS_DPLX      0x4000
-#define        MII_STSICS_LINKSTS   0x0001
-
-/* mii stssum register bits */
-#define        MII_STSSUM_LINK  0x0008
-#define MII_STSSUM_DPLX  0x0004
-#define        MII_STSSUM_AUTO  0x0002
-#define MII_STSSUM_SPD   0x0001
-
-/* lsi phy status register */
-#define MII_LSI_PHY_STAT_FDX   0x0040
-#define MII_LSI_PHY_STAT_SPD   0x0080
-
-/* amd phy status register */
-#define MII_AMD_PHY_STAT_FDX   0x0800
-#define MII_AMD_PHY_STAT_SPD   0x0400
-
-/* intel phy status register */
-#define MII_INTEL_PHY_STAT_FDX 0x0200
-#define MII_INTEL_PHY_STAT_SPD 0x4000
-
-/* Auxilliary Control/Status Register */
-#define MII_AUX_FDX      0x0001
-#define MII_AUX_100      0x0002
-#define MII_AUX_F100     0x0004
-#define MII_AUX_ANEG     0x0008
-
-typedef struct mii_phy {
-       struct mii_phy * next;
-       struct mii_chip_info * chip_info;
-       u16 status;
-       u32 *mii_control_reg;
-       u32 *mii_data_reg;
-} mii_phy_t;
-
-struct phy_ops {
-       int (*phy_init) (struct net_device *, int);
-       int (*phy_reset) (struct net_device *, int);
-       int (*phy_status) (struct net_device *, int, u16 *, u16 *);
-};
-
 /* 
  * Data Buffer Descriptor. Data buffers must be aligned on 32 byte 
  * boundary for both, receive and transmit.
@@ -200,7 +86,6 @@ typedef struct mac_reg {
 
 
 struct au1000_private {
-       
        db_dest_t *pDBfree;
        db_dest_t db[NUM_RX_BUFFS+NUM_TX_BUFFS];
        volatile rx_dma_t *rx_dma_ring[NUM_RX_DMA];
@@ -213,8 +98,15 @@ struct au1000_private {
        u32 tx_full;
 
        int mac_id;
-       mii_phy_t *mii;
-       struct phy_ops *phy_ops;
+
+       int mac_enabled;       /* whether MAC is currently enabled and running (req. for mdio) */
+
+       int old_link;          /* used by au1000_adjust_link */
+       int old_speed;
+       int old_duplex;
+
+       struct phy_device *phy_dev;
+       struct mii_bus mii_bus;
        
        /* These variables are just for quick access to certain regs addresses. */
        volatile mac_reg_t *mac;  /* mac registers                      */   
@@ -223,14 +115,6 @@ struct au1000_private {
        u32 vaddr;                /* virtual address of rx/tx buffers   */
        dma_addr_t dma_addr;      /* dma address of rx/tx buffers       */
 
-       u8 *hash_table;
-       u32 hash_mode;
-       u32 intr_work_done; /* number of Rx and Tx pkts processed in the isr */
-       int phy_addr;          /* phy address */
-       u32 options;           /* User-settable misc. driver options. */
-       u32 drv_flags;
-       int want_autoneg;
        struct net_device_stats stats;
-       struct timer_list timer;
        spinlock_t lock;       /* Serialise access to device */
 };
index 54161aef3cac0cd763479a3a5bc9d7b00da1f83b..702d546567ad3f63e74de9565c1f12e329f4906e 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/irq.h>
 #include <linux/delay.h>
 #include <asm/byteorder.h>
+#include <asm/page.h>
 #include <linux/time.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/crc32.h>
 #include <linux/prefetch.h>
 #include <linux/cache.h>
+#include <linux/zlib.h>
 
 #include "bnx2.h"
 #include "bnx2_fw.h"
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.4.40"
-#define DRV_MODULE_RELDATE     "May 22, 2006"
+#define DRV_MODULE_VERSION     "1.4.42"
+#define DRV_MODULE_RELDATE     "June 12, 2006"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -1820,7 +1822,7 @@ reuse_rx:
                skb->protocol = eth_type_trans(skb, bp->dev);
 
                if ((len > (bp->dev->mtu + ETH_HLEN)) &&
-                       (htons(skb->protocol) != 0x8100)) {
+                       (ntohs(skb->protocol) != 0x8100)) {
 
                        dev_kfree_skb_irq(skb);
                        goto next_rx;
@@ -2009,7 +2011,7 @@ bnx2_poll(struct net_device *dev, int *budget)
        return 1;
 }
 
-/* Called with rtnl_lock from vlan functions and also dev->xmit_lock
+/* Called with rtnl_lock from vlan functions and also netif_tx_lock
  * from set_multicast.
  */
 static void
@@ -2083,6 +2085,92 @@ bnx2_set_rx_mode(struct net_device *dev)
        spin_unlock_bh(&bp->phy_lock);
 }
 
+#define FW_BUF_SIZE    0x8000
+
+static int
+bnx2_gunzip_init(struct bnx2 *bp)
+{
+       if ((bp->gunzip_buf = vmalloc(FW_BUF_SIZE)) == NULL)
+               goto gunzip_nomem1;
+
+       if ((bp->strm = kmalloc(sizeof(*bp->strm), GFP_KERNEL)) == NULL)
+               goto gunzip_nomem2;
+
+       bp->strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
+       if (bp->strm->workspace == NULL)
+               goto gunzip_nomem3;
+
+       return 0;
+
+gunzip_nomem3:
+       kfree(bp->strm);
+       bp->strm = NULL;
+
+gunzip_nomem2:
+       vfree(bp->gunzip_buf);
+       bp->gunzip_buf = NULL;
+
+gunzip_nomem1:
+       printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for "
+                           "uncompression.\n", bp->dev->name);
+       return -ENOMEM;
+}
+
+static void
+bnx2_gunzip_end(struct bnx2 *bp)
+{
+       kfree(bp->strm->workspace);
+
+       kfree(bp->strm);
+       bp->strm = NULL;
+
+       if (bp->gunzip_buf) {
+               vfree(bp->gunzip_buf);
+               bp->gunzip_buf = NULL;
+       }
+}
+
+static int
+bnx2_gunzip(struct bnx2 *bp, u8 *zbuf, int len, void **outbuf, int *outlen)
+{
+       int n, rc;
+
+       /* check gzip header */
+       if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED))
+               return -EINVAL;
+
+       n = 10;
+
+#define FNAME  0x8
+       if (zbuf[3] & FNAME)
+               while ((zbuf[n++] != 0) && (n < len));
+
+       bp->strm->next_in = zbuf + n;
+       bp->strm->avail_in = len - n;
+       bp->strm->next_out = bp->gunzip_buf;
+       bp->strm->avail_out = FW_BUF_SIZE;
+
+       rc = zlib_inflateInit2(bp->strm, -MAX_WBITS);
+       if (rc != Z_OK)
+               return rc;
+
+       rc = zlib_inflate(bp->strm, Z_FINISH);
+
+       *outlen = FW_BUF_SIZE - bp->strm->avail_out;
+       *outbuf = bp->gunzip_buf;
+
+       if ((rc != Z_OK) && (rc != Z_STREAM_END))
+               printk(KERN_ERR PFX "%s: Firmware decompression error: %s\n",
+                      bp->dev->name, bp->strm->msg);
+
+       zlib_inflateEnd(bp->strm);
+
+       if (rc == Z_STREAM_END)
+               return 0;
+
+       return rc;
+}
+
 static void
 load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
        u32 rv2p_proc)
@@ -2092,9 +2180,9 @@ load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
 
 
        for (i = 0; i < rv2p_code_len; i += 8) {
-               REG_WR(bp, BNX2_RV2P_INSTR_HIGH, *rv2p_code);
+               REG_WR(bp, BNX2_RV2P_INSTR_HIGH, cpu_to_le32(*rv2p_code));
                rv2p_code++;
-               REG_WR(bp, BNX2_RV2P_INSTR_LOW, *rv2p_code);
+               REG_WR(bp, BNX2_RV2P_INSTR_LOW, cpu_to_le32(*rv2p_code));
                rv2p_code++;
 
                if (rv2p_proc == RV2P_PROC1) {
@@ -2134,7 +2222,7 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
                int j;
 
                for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
-                       REG_WR_IND(bp, offset, fw->text[j]);
+                       REG_WR_IND(bp, offset, cpu_to_le32(fw->text[j]));
                }
        }
 
@@ -2190,15 +2278,32 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
        REG_WR_IND(bp, cpu_reg->mode, val);
 }
 
-static void
+static int
 bnx2_init_cpus(struct bnx2 *bp)
 {
        struct cpu_reg cpu_reg;
        struct fw_info fw;
+       int rc = 0;
+       void *text;
+       u32 text_len;
+
+       if ((rc = bnx2_gunzip_init(bp)) != 0)
+               return rc;
 
        /* Initialize the RV2P processor. */
-       load_rv2p_fw(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), RV2P_PROC1);
-       load_rv2p_fw(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), RV2P_PROC2);
+       rc = bnx2_gunzip(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), &text,
+                        &text_len);
+       if (rc)
+               goto init_cpu_err;
+
+       load_rv2p_fw(bp, text, text_len, RV2P_PROC1);
+
+       rc = bnx2_gunzip(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), &text,
+                        &text_len);
+       if (rc)
+               goto init_cpu_err;
+
+       load_rv2p_fw(bp, text, text_len, RV2P_PROC2);
 
        /* Initialize the RX Processor. */
        cpu_reg.mode = BNX2_RXP_CPU_MODE;
@@ -2222,7 +2327,13 @@ bnx2_init_cpus(struct bnx2 *bp)
        fw.text_addr = bnx2_RXP_b06FwTextAddr;
        fw.text_len = bnx2_RXP_b06FwTextLen;
        fw.text_index = 0;
-       fw.text = bnx2_RXP_b06FwText;
+
+       rc = bnx2_gunzip(bp, bnx2_RXP_b06FwText, sizeof(bnx2_RXP_b06FwText),
+                        &text, &text_len);
+       if (rc)
+               goto init_cpu_err;
+
+       fw.text = text;
 
        fw.data_addr = bnx2_RXP_b06FwDataAddr;
        fw.data_len = bnx2_RXP_b06FwDataLen;
@@ -2268,7 +2379,13 @@ bnx2_init_cpus(struct bnx2 *bp)
        fw.text_addr = bnx2_TXP_b06FwTextAddr;
        fw.text_len = bnx2_TXP_b06FwTextLen;
        fw.text_index = 0;
-       fw.text = bnx2_TXP_b06FwText;
+
+       rc = bnx2_gunzip(bp, bnx2_TXP_b06FwText, sizeof(bnx2_TXP_b06FwText),
+                        &text, &text_len);
+       if (rc)
+               goto init_cpu_err;
+
+       fw.text = text;
 
        fw.data_addr = bnx2_TXP_b06FwDataAddr;
        fw.data_len = bnx2_TXP_b06FwDataLen;
@@ -2314,7 +2431,13 @@ bnx2_init_cpus(struct bnx2 *bp)
        fw.text_addr = bnx2_TPAT_b06FwTextAddr;
        fw.text_len = bnx2_TPAT_b06FwTextLen;
        fw.text_index = 0;
-       fw.text = bnx2_TPAT_b06FwText;
+
+       rc = bnx2_gunzip(bp, bnx2_TPAT_b06FwText, sizeof(bnx2_TPAT_b06FwText),
+                        &text, &text_len);
+       if (rc)
+               goto init_cpu_err;
+
+       fw.text = text;
 
        fw.data_addr = bnx2_TPAT_b06FwDataAddr;
        fw.data_len = bnx2_TPAT_b06FwDataLen;
@@ -2360,7 +2483,13 @@ bnx2_init_cpus(struct bnx2 *bp)
        fw.text_addr = bnx2_COM_b06FwTextAddr;
        fw.text_len = bnx2_COM_b06FwTextLen;
        fw.text_index = 0;
-       fw.text = bnx2_COM_b06FwText;
+
+       rc = bnx2_gunzip(bp, bnx2_COM_b06FwText, sizeof(bnx2_COM_b06FwText),
+                        &text, &text_len);
+       if (rc)
+               goto init_cpu_err;
+
+       fw.text = text;
 
        fw.data_addr = bnx2_COM_b06FwDataAddr;
        fw.data_len = bnx2_COM_b06FwDataLen;
@@ -2384,6 +2513,9 @@ bnx2_init_cpus(struct bnx2 *bp)
 
        load_cpu_fw(bp, &cpu_reg, &fw);
 
+init_cpu_err:
+       bnx2_gunzip_end(bp);
+       return rc;
 }
 
 static int
@@ -3256,7 +3388,9 @@ bnx2_init_chip(struct bnx2 *bp)
         * context block must have already been enabled. */
        bnx2_init_context(bp);
 
-       bnx2_init_cpus(bp);
+       if ((rc = bnx2_init_cpus(bp)) != 0)
+               return rc;
+
        bnx2_init_nvram(bp);
 
        bnx2_set_mac_addr(bp);
@@ -3556,7 +3690,9 @@ bnx2_reset_nic(struct bnx2 *bp, u32 reset_code)
        if (rc)
                return rc;
 
-       bnx2_init_chip(bp);
+       if ((rc = bnx2_init_chip(bp)) != 0)
+               return rc;
+
        bnx2_init_tx_ring(bp);
        bnx2_init_rx_ring(bp);
        return 0;
@@ -4034,6 +4170,8 @@ bnx2_timer(unsigned long data)
        msg = (u32) ++bp->fw_drv_pulse_wr_seq;
        REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg);
 
+       bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
+
        if ((bp->phy_flags & PHY_SERDES_FLAG) &&
            (CHIP_NUM(bp) == CHIP_NUM_5706)) {
 
@@ -4252,7 +4390,7 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
 }
 #endif
 
-/* Called with dev->xmit_lock.
+/* Called with netif_tx_lock.
  * hard_start_xmit is pseudo-lockless - a lock is only required when
  * the tx queue is full. This way, we get the benefit of lockless
  * operations most of the time without the complexities to handle
@@ -4310,7 +4448,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
                ip_tcp_len = (skb->nh.iph->ihl << 2) + sizeof(struct tcphdr);
 
                skb->nh.iph->check = 0;
-               skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len);
+               skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
                skb->h.th->check =
                        ~csum_tcpudp_magic(skb->nh.iph->saddr,
                                            skb->nh.iph->daddr,
@@ -4504,6 +4642,10 @@ bnx2_get_stats(struct net_device *dev)
                net_stats->tx_aborted_errors +
                net_stats->tx_carrier_errors;
 
+       net_stats->rx_missed_errors =
+               (unsigned long) (stats_blk->stat_IfInMBUFDiscards +
+               stats_blk->stat_FwRxDrop);
+
        return net_stats;
 }
 
@@ -4986,7 +5128,7 @@ bnx2_set_rx_csum(struct net_device *dev, u32 data)
        return 0;
 }
 
-#define BNX2_NUM_STATS 45
+#define BNX2_NUM_STATS 46
 
 static struct {
        char string[ETH_GSTRING_LEN];
@@ -5036,6 +5178,7 @@ static struct {
        { "rx_mac_ctrl_frames" },
        { "rx_filtered_packets" },
        { "rx_discards" },
+       { "rx_fw_discards" },
 };
 
 #define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
@@ -5086,6 +5229,7 @@ static const unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
     STATS_OFFSET32(stat_MacControlFramesReceived),                    
     STATS_OFFSET32(stat_IfInFramesL2FilterDiscards),                  
     STATS_OFFSET32(stat_IfInMBUFDiscards),                            
+    STATS_OFFSET32(stat_FwRxDrop),
 };
 
 /* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are
@@ -5096,7 +5240,7 @@ static u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = {
        4,0,4,4,4,4,4,4,4,4,
        4,4,4,4,4,4,4,4,4,4,
        4,4,4,4,4,4,4,4,4,4,
-       4,4,4,4,4,
+       4,4,4,4,4,4,
 };
 
 static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = {
@@ -5104,7 +5248,7 @@ static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = {
        4,4,4,4,4,4,4,4,4,4,
        4,4,4,4,4,4,4,4,4,4,
        4,4,4,4,4,4,4,4,4,4,
-       4,4,4,4,4,
+       4,4,4,4,4,4,
 };
 
 #define BNX2_NUM_TESTS 6
@@ -5634,7 +5778,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                }
        }
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5708)
+       if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
+           (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
+           (CHIP_ID(bp) == CHIP_ID_5708_B1))
                bp->flags |= NO_WOL_FLAG;
 
        if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
index b87925f6a2283582b19a57fcb4e3b4fcece0b927..5845e334941b4f8e71ca80ad5c674bf7a7ffd5e9 100644 (file)
@@ -231,6 +231,7 @@ struct statistics_block {
        u32 stat_GenStat13;
        u32 stat_GenStat14;
        u32 stat_GenStat15;
+       u32 stat_FwRxDrop;
 };
 
 
@@ -3481,6 +3482,8 @@ struct l2_fhdr {
 
 #define BNX2_COM_SCRATCH                               0x00120000
 
+#define BNX2_FW_RX_DROP_COUNT                           0x00120084
+
 
 /*
  *  cp_reg definition
@@ -3747,7 +3750,12 @@ struct l2_fhdr {
 #define DMA_READ_CHANS 5
 #define DMA_WRITE_CHANS        3
 
-#define BCM_PAGE_BITS  12
+/* Use CPU native page size up to 16K for the ring sizes.  */
+#if (PAGE_SHIFT > 14)
+#define BCM_PAGE_BITS  14
+#else
+#define BCM_PAGE_BITS  PAGE_SHIFT
+#endif
 #define BCM_PAGE_SIZE  (1 << BCM_PAGE_BITS)
 
 #define TX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct tx_bd))
@@ -3770,7 +3778,7 @@ struct l2_fhdr {
 
 #define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
 
-#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> 8)
+#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4))
 #define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
 
 /* Context size. */
@@ -4048,6 +4056,9 @@ struct bnx2 {
        u32                     flash_size;
 
        int                     status_stats_size;
+
+       struct z_stream_s       *strm;
+       void                    *gunzip_buf;
 };
 
 static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
index 8158974c35a8040ef692eaa6559ff48601d116c3..2d753dca0d75952129dc01ce95f5dc153c368812 100644 (file)
@@ -7,7 +7,7 @@
  * the Free Software Foundation, except as noted below.
  *
  * This file contains firmware data derived from proprietary unpublished
- * source code, Copyright (c) 2004, 2005 Broadcom Corporation.
+ * source code, Copyright (c) 2004, 2005, 2006 Broadcom Corporation.
  *
  * Permission is hereby granted for the distribution of this firmware data
  * in hexadecimal or equivalent format, provided this copyright notice is
@@ -28,943 +28,641 @@ static const u32 bnx2_COM_b06FwBssAddr = 0x08005860;
 static const int bnx2_COM_b06FwBssLen = 0x88;
 static const u32 bnx2_COM_b06FwSbssAddr = 0x08005840;
 static const int bnx2_COM_b06FwSbssLen = 0x1c;
-static u32 bnx2_COM_b06FwText[(0x57bc/4) + 1] = {
-       0x0a00022d, 0x00000000, 0x00000000, 0x0000000d, 0x636f6d20, 0x322e352e,
-       0x38000000, 0x02050802, 0x00000000, 0x00000003, 0x00000014, 0x00000032,
-       0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000010, 0x000003e8, 0x0000ea60, 0x00000001, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000002, 0x00000020, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24425840,
-       0x3c030800, 0x246358e8, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004,
-       0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x261008b4, 0x3c1c0800,
-       0x279c5840, 0x0e0002f7, 0x00000000, 0x0000000d, 0x27bdffe8, 0x3c1a8000,
-       0x3c020008, 0x0342d825, 0x3c036010, 0xafbf0010, 0x8c655000, 0x3c020800,
-       0x24470f30, 0x3c040800, 0x24865860, 0x2402ff7f, 0x00a22824, 0x34a5380c,
-       0xac655000, 0x00002821, 0x24020037, 0x24030c80, 0xaf420008, 0xaf430024,
-       0xacc70000, 0x24a50001, 0x2ca20016, 0x1440fffc, 0x24c60004, 0x24845860,
-       0x3c020800, 0x24420f3c, 0x3c030800, 0x24630e2c, 0xac820004, 0x3c020800,
-       0x24420a2c, 0x3c050800, 0x24a51268, 0xac82000c, 0x3c020800, 0x244243dc,
-       0xac830008, 0x3c030800, 0x24633698, 0xac820014, 0x3c020800, 0x24423c24,
-       0xac830018, 0xac83001c, 0x3c030800, 0x24630f44, 0xac820024, 0x3c020800,
-       0x244243ac, 0xac83002c, 0x3c030800, 0x246343cc, 0xac820030, 0x3c020800,
-       0x244242f0, 0xac830034, 0x3c030800, 0x24633d78, 0xac82003c, 0x3c020800,
-       0x24420fd4, 0xac850010, 0xac850020, 0xac830040, 0x0e0010b7, 0xac820050,
-       0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafb00010, 0x27500100,
-       0xafbf0018, 0xafb10014, 0x9203000b, 0x24020003, 0x1462005b, 0x96110008,
-       0x32220001, 0x10400009, 0x27430080, 0x8e020000, 0x96040014, 0x000211c2,
-       0x00021040, 0x00621821, 0xa4640000, 0x0a0002d0, 0x3c020800, 0x3c020800,
-       0x8c430020, 0x1060002a, 0x3c030800, 0x0e00148e, 0x00000000, 0x97420108,
-       0x8f850018, 0x9743010c, 0x3042003e, 0x00021400, 0x00621825, 0xaca30000,
-       0x8f840018, 0x8f420100, 0xac820004, 0x97430116, 0x9742010e, 0x8f840018,
-       0x00031c00, 0x00431025, 0xac820008, 0x97430110, 0x97440112, 0x8f850018,
-       0x00031c00, 0x00832025, 0xaca4000c, 0x97420114, 0x8f840018, 0x3042ffff,
-       0xac820010, 0x8f830018, 0xac600014, 0x8f820018, 0x3c030800, 0xac400018,
-       0x946258ce, 0x8f840018, 0x3c032000, 0x00431025, 0xac82001c, 0x0e0014cc,
-       0x24040001, 0x3c030800, 0x8c620040, 0x24420001, 0xac620040, 0x3c020800,
-       0x8c430044, 0x32240004, 0x24630001, 0x10800017, 0xac430044, 0x8f4202b8,
-       0x04430007, 0x8e020020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001,
-       0x0a0002f2, 0xac830060, 0x3c060800, 0x8cc4005c, 0xaf420280, 0x96030016,
-       0x00001021, 0xa7430284, 0x8e050004, 0x24840001, 0x3c031000, 0xaf450288,
-       0xaf4302b8, 0x0a0002f2, 0xacc4005c, 0x32220002, 0x0a0002f2, 0x0002102b,
-       0x3c026000, 0xac400808, 0x0000000d, 0x00001021, 0x8fbf0018, 0x8fb10014,
-       0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffc8, 0xafbf0034, 0xafbe0030,
-       0xafb7002c, 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c, 0xafb20018,
-       0xafb10014, 0x0e000244, 0xafb00010, 0x3c170800, 0x3c160800, 0x24110020,
-       0x24150030, 0x2794000c, 0x27930008, 0x3c124000, 0x3c1e0800, 0x8f820004,
-       0x3c040800, 0x8c830020, 0x10430005, 0x8ee200a4, 0xaf830004, 0x0e001593,
-       0x00000000, 0x8ee200a4, 0x8ec300a0, 0x10430004, 0x26c400a0, 0x94820002,
-       0xa742009e, 0xaee300a4, 0x8f500000, 0x32020007, 0x1040ffee, 0x32020001,
-       0x1040002c, 0x32020002, 0x8f420100, 0xaf420020, 0x8f430104, 0xaf4300a8,
-       0x9342010b, 0x93630000, 0x306300ff, 0x10710005, 0x304400ff, 0x10750006,
-       0x2c820016, 0x0a000333, 0x00000000, 0xaf940000, 0x0a000334, 0x2c820016,
-       0xaf930000, 0x0a000334, 0x00000000, 0xaf800000, 0x14400005, 0x00041880,
-       0x0e0003cc, 0x00000000, 0x0a000340, 0x00000000, 0x3c020800, 0x24425860,
-       0x00621821, 0x8c620000, 0x0040f809, 0x00000000, 0x10400005, 0x3c030800,
-       0x8f420104, 0x3c016020, 0xac220014, 0x3c030800, 0x8c620034, 0xaf520138,
-       0x24420001, 0xac620034, 0x32020002, 0x1040001a, 0x32020004, 0x8f420140,
-       0xaf420020, 0x93630000, 0x306300ff, 0x10710005, 0x00000000, 0x10750006,
-       0x00000000, 0x0a00035d, 0x00000000, 0xaf940000, 0x0a00035e, 0x00000000,
-       0xaf930000, 0x0a00035e, 0x00000000, 0xaf800000, 0x0e000c7b, 0x00000000,
-       0x3c040800, 0x8c820038, 0xaf520178, 0x24420001, 0xac820038, 0x32020004,
-       0x1040ffa4, 0x00000000, 0x8f420180, 0xaf420020, 0x93630000, 0x306300ff,
-       0x10710005, 0x00000000, 0x10750006, 0x00000000, 0x0a000378, 0x00000000,
-       0xaf940000, 0x0a000379, 0x00000000, 0xaf930000, 0x0a000379, 0x00000000,
-       0xaf800000, 0x8f430180, 0x24020f00, 0x14620005, 0x00000000, 0x8f420188,
-       0xa742009c, 0x0a000387, 0x8fc2003c, 0x93620000, 0x14510004, 0x8fc2003c,
-       0x0e000bad, 0x00000000, 0x8fc2003c, 0xaf5201b8, 0x24420001, 0x0a00030b,
-       0xafc2003c, 0x27bdffe8, 0xafbf0010, 0x97420108, 0x24033000, 0x30447000,
-       0x10830016, 0x28823001, 0x10400007, 0x24024000, 0x1080000b, 0x24022000,
-       0x1082000c, 0x00000000, 0x0a0003b3, 0x00000000, 0x10820010, 0x24025000,
-       0x10820012, 0x00000000, 0x0a0003b3, 0x00000000, 0x0000000d, 0x0a0003b5,
-       0x00001021, 0x0e000442, 0x00000000, 0x0a0003b6, 0x8fbf0010, 0x0e00041a,
-       0x00000000, 0x0a0003b5, 0x00001021, 0x0e000669, 0x00000000, 0x0a0003b5,
-       0x00001021, 0x0e001467, 0x00000000, 0x0a0003b5, 0x00001021, 0x0000000d,
-       0x00001021, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x93620000, 0x24030020,
-       0x304400ff, 0x10830005, 0x24020030, 0x10820007, 0x00000000, 0x0a0003c9,
-       0x00000000, 0x2782000c, 0xaf820000, 0x03e00008, 0x00000000, 0x27820008,
-       0xaf820000, 0x03e00008, 0x00000000, 0xaf800000, 0x03e00008, 0x00000000,
-       0x0000000d, 0x03e00008, 0x00001021, 0x03e00008, 0x00001021, 0x27440100,
-       0x94830008, 0x30620004, 0x10400017, 0x30620002, 0x8f4202b8, 0x04430007,
-       0x8c820020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001, 0x03e00008,
-       0xac830060, 0xaf420280, 0x94830016, 0x3c060800, 0xa7430284, 0x8c850004,
-       0x8cc4005c, 0x00001021, 0x3c031000, 0x24840001, 0xaf450288, 0xaf4302b8,
-       0x03e00008, 0xacc4005c, 0x14400003, 0x3c040800, 0x03e00008, 0x00001021,
-       0x8c830084, 0x24020001, 0x24630001, 0x03e00008, 0xac830084, 0x27450100,
-       0x3c040800, 0x8c820088, 0x94a3000c, 0x24420001, 0x007a1821, 0xac820088,
-       0x8ca40018, 0x90664000, 0xaf440038, 0x8ca2001c, 0x2403fff8, 0x00063600,
-       0x00431024, 0x34420004, 0x3c030005, 0xaf42003c, 0xaf430030, 0x00000000,
-       0x00000000, 0x00000000, 0xaf460404, 0x00000000, 0x00000000, 0x00000000,
-       0x3c020006, 0x34420001, 0xaf420030, 0x00000000, 0x00000000, 0x00000000,
-       0x8f420000, 0x30420010, 0x1040fffd, 0x00001021, 0x03e00008, 0x00000000,
-       0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x1060001e,
-       0xafbf0014, 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020018, 0xac620000,
-       0x8f840018, 0x9602000c, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018,
-       0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f840018,
-       0x3c026000, 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce,
-       0x8f850018, 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c,
-       0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010,
-       0x27500100, 0xafbf0014, 0x92020009, 0x14400003, 0x3c020800, 0x0a00046c,
-       0x24020001, 0x8c430020, 0x1060001f, 0x00001021, 0x0e00148e, 0x00000000,
-       0x8f830018, 0x8e020018, 0xac620000, 0x8f840018, 0x9602000c, 0xac820004,
-       0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-       0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, 0x8c434448, 0xac830018,
-       0x96020008, 0x3c030800, 0x946458ce, 0x8f850018, 0x00021400, 0x00441025,
-       0x24040001, 0x0e0014cc, 0xaca2001c, 0x00001021, 0x8fbf0014, 0x8fb00010,
-       0x03e00008, 0x27bd0018, 0x3c0b0800, 0x8d6808b0, 0x3c070800, 0x24e700b0,
-       0x00084900, 0x01271821, 0xac640000, 0x93620005, 0x97660008, 0x00e95021,
-       0x93630023, 0x9364003f, 0x25080001, 0x00021600, 0x00063400, 0x00461025,
-       0x00031a00, 0x00431025, 0x00822025, 0xad440004, 0x9362007e, 0x9366007f,
-       0x8f630178, 0x9364007a, 0x00021600, 0x00063400, 0x00461025, 0x00031a00,
-       0x00431025, 0x00822025, 0xad440008, 0x93620080, 0x9363007d, 0x3108007f,
-       0x01403821, 0xad6808b0, 0x00021600, 0x00031c00, 0x00431025, 0x00451025,
-       0x03e00008, 0xace2000c, 0x27bdffb8, 0xafb3002c, 0x00009821, 0xafbe0040,
-       0x0000f021, 0xafb50034, 0x27550100, 0xafbf0044, 0xafb7003c, 0xafb60038,
-       0xafb40030, 0xafb20028, 0xafb10024, 0xafb00020, 0xafa00010, 0xafa00014,
-       0x96a20008, 0x8f540100, 0x8eb10018, 0x30420001, 0x10400037, 0x02a0b821,
-       0x8f630054, 0x2622ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d,
-       0x00000000, 0x2400015c, 0x0a0004e5, 0x00002021, 0x8f62004c, 0x02221023,
-       0x18400028, 0x00002021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c,
-       0x308400ff, 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, 0xac62008c,
-       0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001,
-       0x00021023, 0x30420005, 0x0a0004e5, 0x34440004, 0x27660100, 0x00041080,
-       0x00c21021, 0x8c430000, 0x02231823, 0x04600004, 0x24820001, 0x30440007,
-       0x1485fff9, 0x00041080, 0x10870007, 0x3c030800, 0xa3640121, 0x8c620094,
-       0x24040005, 0x24420001, 0x0a0004e5, 0xac620094, 0x24040004, 0x00809821,
-       0x9362003f, 0x304400ff, 0x38830016, 0x2c630001, 0x38820010, 0x2c420001,
-       0x00621825, 0x1460000c, 0x24020001, 0x38830008, 0x2c630001, 0x38820014,
-       0x2c420001, 0x00621825, 0x14600005, 0x24020001, 0x24020012, 0x14820002,
-       0x00001021, 0x24020001, 0x10400009, 0x00000000, 0x8ea20020, 0x8f630040,
-       0x0040b021, 0x00431023, 0x5c400010, 0x8f760040, 0x0a000511, 0x00000000,
-       0x9343010b, 0x24020004, 0x1462000a, 0x8eb60020, 0x8f630040, 0x3c021000,
-       0x00761823, 0x0043102a, 0x10400004, 0x00000000, 0x0000000d, 0x00000000,
-       0x240002fa, 0x9343010b, 0x24020004, 0x5462000b, 0x96a20008, 0x24020001,
-       0xafa20010, 0x96a20008, 0x24030001, 0xafa30018, 0x8eb2001c, 0x36730002,
-       0x30420020, 0x0a000526, 0xafa20014, 0x36730080, 0x30420002, 0x10400003,
-       0xafa00018, 0x0a000526, 0x8eb2001c, 0x8eb20014, 0x2402fffb, 0x02628024,
-       0x1200002a, 0x3c030800, 0x8c620030, 0x02021024, 0x10400026, 0x3c020800,
-       0x8c430020, 0x10600024, 0x32620004, 0x0e00148e, 0x00000000, 0x8f830018,
-       0x8f420100, 0xac620000, 0x8f840018, 0x02401821, 0x32620002, 0xac900004,
-       0x8f840018, 0x54400001, 0x02c01821, 0xac830008, 0x8f830018, 0x8ee20020,
-       0xac62000c, 0x8f840018, 0x8f620040, 0xac820010, 0x8f830018, 0x8ee20018,
-       0xac620014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
-       0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, 0x0e0014cc,
-       0xaca3001c, 0x32620004, 0x10400063, 0x00003821, 0x3c029000, 0x34420001,
-       0x3c038000, 0x02821025, 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024,
-       0x1440fffd, 0x00000000, 0x93620023, 0x30420080, 0x10400011, 0x00000000,
-       0x8f65005c, 0x8f63004c, 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821,
-       0x00a2102b, 0x54400006, 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023,
-       0xaf710064, 0x3c023fff, 0x0a000580, 0x3442ffff, 0x8f62005c, 0x02221023,
-       0x04400011, 0x00000000, 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff,
-       0x3442ffff, 0xaf710064, 0x00a32823, 0x00852821, 0x0045102b, 0x10400004,
-       0x02251021, 0x3c053fff, 0x34a5ffff, 0x02251021, 0xaf62005c, 0x24070001,
-       0xaf71004c, 0x8f620054, 0x16220005, 0x00000000, 0x93620023, 0x30420040,
-       0x10400017, 0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001,
-       0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804,
-       0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b,
-       0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021,
-       0xaf62000c, 0x93620082, 0x30420080, 0x50400001, 0xa3600081, 0x3c028000,
-       0x34420001, 0x02821025, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004,
-       0x00000000, 0x0e0013c4, 0x00000000, 0x00403821, 0x54e00001, 0x241e0001,
-       0x8f700040, 0x8f620040, 0x14520003, 0x00521023, 0x0a0005bf, 0x00001021,
-       0x28420001, 0x10400041, 0x8fa20010, 0x0e000fae, 0x02402021, 0xaf720040,
-       0x9362003e, 0x30420001, 0x1440000b, 0x3c029000, 0x93620022, 0x24420001,
-       0xa3620022, 0x93630022, 0x3c020800, 0x8c440098, 0x0064182b, 0x14600027,
-       0x3c020800, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000,
-       0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000,
-       0x34420001, 0xa362007d, 0x8f640074, 0x34630001, 0x02831825, 0xaf430020,
-       0x04810006, 0x3c038000, 0x02802021, 0x0e000470, 0x24050273, 0x0a0005f2,
-       0x24050001, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000,
-       0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x24050001, 0x24020001, 0xa7620012,
-       0xa3600022, 0x0a0005fe, 0x2ca20001, 0x9743007a, 0x9444002a, 0x00002821,
-       0x00641821, 0x3063fffe, 0xa7630012, 0x2ca20001, 0x00021023, 0x03c2f024,
-       0x8fa20010, 0x10400004, 0x8fa30014, 0x0e0013c1, 0x00000000, 0x8fa30014,
-       0x10600003, 0x00000000, 0x0e0010eb, 0x00000000, 0x13c0001f, 0x3c029000,
-       0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
-       0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074,
-       0x34630001, 0x02831825, 0xaf430020, 0x04810006, 0x3c038000, 0x02802021,
-       0x0e000470, 0x2405036c, 0x0a00062b, 0x8fa20018, 0x8f4201f8, 0x00431024,
-       0x1440fffd, 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4, 0xaf4301f8,
-       0x8fa20018, 0x5040002f, 0x96a20008, 0x8f620048, 0x8f630024, 0x00761821,
-       0xaf630048, 0x9764003c, 0x00501023, 0x0044102b, 0x10400025, 0x3c029000,
-       0x34420001, 0x3c040800, 0x8c830080, 0x8f450100, 0x3c068000, 0x24630001,
-       0x00a21025, 0xac830080, 0xaf420020, 0x8f420020, 0x00461024, 0x1440fffd,
-       0x00000000, 0x9362007d, 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074,
-       0x34630001, 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021,
-       0x0e000470, 0x2405038a, 0x0a00065b, 0x96a20008, 0x8f4201f8, 0x00431024,
-       0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8,
-       0x96a20008, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038, 0x8fb50034,
-       0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x00021042,
-       0x30420001, 0x03e00008, 0x27bd0048, 0x27bdffe0, 0xafbf0018, 0x97420108,
-       0x24030019, 0x304400ff, 0x10830065, 0x2882001a, 0x1040001a, 0x2882000a,
-       0x1040000f, 0x28820008, 0x10400040, 0x24020001, 0x1082003a, 0x28820002,
-       0x50400005, 0x24020006, 0x10800032, 0x3c026000, 0x0a0006fb, 0x00000000,
-       0x1082003d, 0x00000000, 0x0a0006fb, 0x00000000, 0x2402000b, 0x10820044,
-       0x2882000b, 0x1440004b, 0x2402000e, 0x10820045, 0x00000000, 0x0a0006fb,
-       0x00000000, 0x24020020, 0x10820062, 0x28820021, 0x1040000e, 0x2402001c,
-       0x1082004c, 0x2882001d, 0x10400005, 0x2402001b, 0x10820043, 0x00000000,
-       0x0a0006fb, 0x00000000, 0x2402001f, 0x10820050, 0x00000000, 0x0a0006fb,
-       0x00000000, 0x240200c1, 0x10820042, 0x288200c2, 0x10400005, 0x24020080,
-       0x10820021, 0x00000000, 0x0a0006fb, 0x00000000, 0x240200c2, 0x1082003d,
-       0x240200c9, 0x50820049, 0xafa00010, 0x0a0006fb, 0x00000000, 0x0e001163,
-       0xac400808, 0x0a0006fd, 0x8fbf0018, 0x3c026000, 0x8c444448, 0x3c030800,
-       0xac640064, 0x0e001163, 0x00000000, 0x3c026000, 0x8c444448, 0x3c030800,
-       0x0a0006fc, 0xac640068, 0x8f440100, 0x0e0006ff, 0x00000000, 0x3c026000,
-       0x8c444448, 0x3c030800, 0x0a0006fc, 0xac64006c, 0x0e001191, 0x00000000,
-       0x0a0006fd, 0x8fbf0018, 0x8f440100, 0x0e0011bb, 0x00000000, 0x0a0006fd,
-       0x8fbf0018, 0x0e001202, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0000000d,
-       0x0a0006fd, 0x8fbf0018, 0x0e000826, 0x00000000, 0x0a0006fd, 0x8fbf0018,
-       0x8f440100, 0x0e001264, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e00134e,
-       0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e00087c, 0x27440100, 0x0a0006fd,
-       0x8fbf0018, 0x8f640040, 0x0e000fae, 0x00000000, 0x0a0006fd, 0x8fbf0018,
-       0x8f440100, 0x0e001059, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e001417,
-       0x00000000, 0x0a0006fd, 0x8fbf0018, 0xafa00014, 0x8f440100, 0x8f450118,
-       0x8f46011c, 0x0e001439, 0x8f470120, 0x0a0006fd, 0x8fbf0018, 0x0000000d,
-       0x8fbf0018, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x9742010c,
-       0x1440005e, 0x00803821, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020,
-       0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023,
-       0x30420010, 0x14400026, 0x3c030800, 0x8f630074, 0x3c027fff, 0x3442ffff,
-       0x00621824, 0xaf630074, 0x93620005, 0x34420001, 0xa3620005, 0x8f63004c,
-       0x8f620054, 0x10620021, 0x24040001, 0x9762006a, 0x00022880, 0x50a00001,
-       0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821,
-       0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050,
-       0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824,
-       0x00a21021, 0xaf62000c, 0x0a00073d, 0x24040001, 0x8c6200a8, 0x00002021,
-       0x24420001, 0xac6200a8, 0x0000000d, 0x00000000, 0x2400044d, 0x3c028000,
-       0x34420001, 0x00e21025, 0xaf420020, 0x1080001f, 0x3c029000, 0x34420001,
-       0x00e21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-       0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001,
-       0x00e31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00e02021, 0x0e000470,
-       0x24050455, 0x0a000761, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd,
-       0x24020002, 0x3c031000, 0xaf4701c0, 0xa34201c4, 0xaf4301f8, 0x0e001163,
-       0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffd8, 0xafbf0024,
-       0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x93630005,
-       0x00809821, 0x24020030, 0x30630030, 0x146200ac, 0x00a0a021, 0x3c020800,
-       0x8c430020, 0x106000a6, 0x00000000, 0x0e00148e, 0x00000000, 0x8f830018,
-       0xac730000, 0x936200c4, 0x30420002, 0x10400004, 0x24020001, 0x8f830018,
-       0x0a000784, 0x00000000, 0x8f830018, 0x24020003, 0xac620004, 0x8f6200dc,
-       0x8f630040, 0x00431023, 0x18400004, 0x00000000, 0x0000000d, 0x00000000,
-       0x24000509, 0x8f840018, 0x8f6200dc, 0xac820008, 0x8f830018, 0xac60000c,
-       0x8f820018, 0xac400010, 0x8f830018, 0x8f62004c, 0x3c100800, 0xac620014,
-       0x8f850018, 0x3c026000, 0x8c434448, 0x261258c0, 0x00002021, 0xaca30018,
-       0x9642000e, 0x8f850018, 0x3c034010, 0x00431025, 0x0e0014cc, 0xaca2001c,
-       0x8f830018, 0xac730000, 0x9362003e, 0x9363003f, 0x8f840018, 0x00021200,
-       0x00621825, 0xac830004, 0x93620081, 0x93630082, 0x8f840018, 0x00021600,
-       0x00031c00, 0x00431025, 0xac820008, 0x8f830018, 0x8f620040, 0xac62000c,
-       0x8f840018, 0x8f620048, 0xac820010, 0x8f71004c, 0x8f820018, 0xac510014,
-       0x8f620050, 0x8f850018, 0x00401821, 0x02221023, 0x5c400001, 0x02201821,
-       0x00002021, 0xaca30018, 0x9642000e, 0x8f850018, 0x3c03c00b, 0x00431025,
-       0x0e0014cc, 0xaca2001c, 0x8f620054, 0x8f840018, 0x00401821, 0x02221023,
-       0x5c400001, 0x02201821, 0xac830000, 0x8f840018, 0x8f630058, 0xac830004,
-       0x93620023, 0x30420010, 0x10400004, 0x00000000, 0x8f830018, 0x0a0007dd,
-       0x8f620148, 0x8f830018, 0x8f62005c, 0xac620008, 0x8f830018, 0x8f620060,
-       0xac62000c, 0x8f840018, 0x8f620064, 0xac820010, 0x97630068, 0x9762006a,
-       0x8f840018, 0x00031c00, 0x00431025, 0xac820014, 0x8f850018, 0x00002021,
-       0x2402ffff, 0x260358c0, 0xaca20018, 0x9462000e, 0x8f850018, 0x3c03c00c,
-       0x00431025, 0x0e0014cc, 0xaca2001c, 0x8f840018, 0x8f630018, 0xac830000,
-       0x936200c4, 0x30420002, 0x10400006, 0x00000000, 0x976200c8, 0x8f830018,
-       0x3042ffff, 0x0a000803, 0xac620004, 0x8f820018, 0xac400004, 0x8f830018,
-       0x8f62006c, 0xac620008, 0x8f840018, 0x8f6200dc, 0xac82000c, 0x8f830018,
-       0xac600010, 0x93620005, 0x8f830018, 0x00021600, 0x00541025, 0xac620014,
-       0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x260258c0, 0xaca30018,
-       0x9443000e, 0x8f850018, 0x3c02400d, 0x00621825, 0x0e0014cc, 0xaca3001c,
-       0x0e00122e, 0x02602021, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
-       0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0028, 0x27bdffe0, 0xafb00010,
-       0x27500100, 0xafbf0018, 0xafb10014, 0x9603000c, 0x240200c1, 0x54620024,
-       0x8e040000, 0x3c029000, 0x8f450100, 0x34420001, 0x3c038000, 0x00a21025,
-       0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d,
-       0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, 0x34630001, 0x00a31825,
-       0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, 0x0e000470, 0x240505b2,
-       0x0a000878, 0x8fbf0018, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002,
-       0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, 0x0a000878, 0x8fbf0018,
-       0x8f65004c, 0x24060001, 0x0e0012a3, 0x240705be, 0x3c020800, 0x8c430020,
-       0x9611000c, 0x1060001d, 0x8e100000, 0x0e00148e, 0x00000000, 0x8f820018,
-       0xac500000, 0x8f840018, 0x00111400, 0xac820004, 0x8f830018, 0xac600008,
-       0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f840018, 0x240205c1,
-       0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
-       0xaca30018, 0x944358ce, 0x8f850018, 0x3c024019, 0x00621825, 0x0e0014cc,
-       0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
-       0x27bdffb0, 0xafb5003c, 0x0000a821, 0xafbe0048, 0x0000f021, 0xafb70044,
-       0x0000b821, 0xafb30034, 0x00009821, 0xafb60040, 0x0080b021, 0xafbf004c,
-       0xafb40038, 0xafb20030, 0xafb1002c, 0xafb00028, 0xafa00010, 0x8f620040,
-       0x8ec30014, 0x96d1000c, 0x00431023, 0x04410025, 0x8ed40000, 0x32220401,
-       0x1040030c, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000,
-       0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000,
-       0x34420004, 0xa362007d, 0x8f640074, 0x34630001, 0x02831825, 0xaf430020,
-       0x04810006, 0x3c038000, 0x02802021, 0x0e000470, 0x24050664, 0x0a000ba2,
-       0x8fbf004c, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000,
-       0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x0a000ba2, 0x8fbf004c, 0x32220010,
-       0x1040006b, 0x00003021, 0x9362003f, 0x92c6000f, 0x304500ff, 0x24c3fff8,
-       0x2c62000f, 0x10400057, 0x3c020800, 0x244257c0, 0x00031880, 0x00621821,
-       0x8c640000, 0x00800008, 0x00000000, 0x38a20012, 0x0a000924, 0x0002a82b,
-       0x2402000e, 0x14a20004, 0x2402000c, 0x24150001, 0x0a000924, 0x24060010,
-       0x10a20049, 0x38a30010, 0x2c630001, 0x38a20016, 0x2c420001, 0x00621825,
-       0x1460004d, 0x0000a821, 0x24020014, 0x10a2004a, 0x00000000, 0x0000000d,
-       0x00000000, 0x2400069c, 0x0a000924, 0x0000a821, 0x24020016, 0x14a20005,
-       0x2402000c, 0x24150001, 0x24060010, 0x0a000924, 0x3231fffd, 0x10a20032,
-       0x38a30010, 0x2c630001, 0x38a2000e, 0x2c420001, 0x00621825, 0x14600036,
-       0x0000a821, 0x24020014, 0x14a20003, 0x24150001, 0x0a000924, 0x24060012,
-       0x0000000d, 0x00000000, 0x240006bc, 0x0a000924, 0x0000a821, 0x2402000e,
-       0x14a20004, 0x24020016, 0x24150001, 0x0a000924, 0x3231fffb, 0x14a20004,
-       0x24020014, 0x24150001, 0x0a000924, 0x3231fffd, 0x54a20013, 0x92c2000e,
-       0x24150001, 0x24060012, 0x0a000924, 0x3231fffd, 0x2402000c, 0x54a2000c,
-       0x92c2000e, 0x92c3000e, 0x2402000a, 0x10620005, 0x24150001, 0x0000000d,
-       0x00000000, 0x240006e8, 0x24150001, 0x0a000924, 0x24060014, 0x92c2000e,
-       0x14a20003, 0x00000000, 0x0a000924, 0x24150001, 0x10a6ffc1, 0x24020012,
-       0x10a20005, 0x0000a821, 0x0000000d, 0x00000000, 0x24000704, 0x0000a821,
-       0x12a00022, 0x32220004, 0x10400002, 0x24020001, 0xafa20010, 0x32230102,
-       0x24020002, 0x1462000f, 0x00000000, 0x92c2000a, 0x30420020, 0x1440000b,
-       0x00000000, 0x8f630048, 0x8f620040, 0x14620004, 0x00000000, 0x8f620048,
-       0x24420001, 0xaf620048, 0x8f620040, 0x24420001, 0xaf620040, 0xa366003f,
-       0x38c30012, 0x2c630001, 0x38c20010, 0x2c420001, 0x00621825, 0x10600005,
-       0x3c030800, 0x8c620074, 0x24420001, 0x0e00140d, 0xac620074, 0x32220040,
-       0x32230020, 0xafa30020, 0x32230080, 0xafa30024, 0x32230001, 0xafa30018,
-       0x32230008, 0xafa3001c, 0x32230100, 0x104000c4, 0xafa30014, 0x8ec60010,
-       0x8f630054, 0x24c2ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d,
-       0x00000000, 0x2400015c, 0x0a000989, 0x00009021, 0x8f62004c, 0x00c21023,
-       0x18400028, 0x00009021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c,
-       0x308400ff, 0x24420001, 0x30a500ff, 0x00804021, 0x1485000b, 0xac62008c,
-       0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001,
-       0x00021023, 0x30420005, 0x0a000989, 0x34520004, 0x27670100, 0x00041080,
-       0x00e21021, 0x8c430000, 0x00c31823, 0x04600004, 0x24820001, 0x30440007,
-       0x1485fff9, 0x00041080, 0x10880007, 0x3c030800, 0xa3640121, 0x8c620094,
-       0x24120005, 0x24420001, 0x0a000989, 0xac620094, 0x24120004, 0x32420001,
-       0x10400021, 0x3c020800, 0x8c430020, 0x8ed00000, 0x1060001c, 0x8ed30010,
-       0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001,
-       0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
-       0xac600010, 0x8f820018, 0xac530014, 0x8f850018, 0x3c026000, 0x8c434448,
-       0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010,
-       0x00621825, 0x0e0014cc, 0xaca3001c, 0x24130001, 0x32420004, 0x10400068,
-       0x00003821, 0x3c029000, 0x8ec60010, 0x34420001, 0x3c038000, 0x02821025,
-       0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
-       0x93620023, 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c,
-       0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006,
-       0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, 0xaf660064, 0x3c023fff,
-       0x0a0009da, 0x3442ffff, 0x8f62005c, 0x00c21023, 0x04400011, 0x00000000,
-       0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf660064,
-       0x00a32823, 0x00852821, 0x0045102b, 0x10400004, 0x00c51021, 0x3c053fff,
-       0x34a5ffff, 0x00c51021, 0xaf62005c, 0x24070001, 0xaf66004c, 0x8fa20010,
-       0x10400003, 0x00000000, 0xaf660050, 0xaf660054, 0x8f620054, 0x14c20005,
-       0x00000000, 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a,
-       0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800,
-       0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021,
-       0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074,
-       0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x93620082, 0x30420080,
-       0x50400001, 0xa3600081, 0x3c028000, 0x34420001, 0x02821025, 0xaf420020,
-       0x9363007e, 0x9362007a, 0x10620005, 0x00e0b821, 0x0e0013c4, 0x00000000,
-       0x00403821, 0x00e0b821, 0x8fa30020, 0x10600009, 0x8fa20010, 0x8ec20018,
-       0xaf620018, 0x8ec3001c, 0xaf63001c, 0x8ec20020, 0x24170001, 0xaf620058,
-       0x8fa20010, 0x10400057, 0x8fa30024, 0x93620023, 0x30420040, 0x10400053,
-       0x00000000, 0x16600021, 0x3c120800, 0x8e420020, 0x8f70004c, 0x1040001e,
-       0x24130001, 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018,
-       0x24020001, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
-       0x8f830018, 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000,
-       0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
-       0x3c024010, 0x00621825, 0xaca3001c, 0x0e0014cc, 0x24130001, 0x8e420020,
-       0x1040001c, 0x8ed00000, 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000,
-       0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c,
-       0x8f820018, 0xac400010, 0x8f830018, 0x24020798, 0xac620014, 0x8f850018,
-       0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce,
-       0x8f850018, 0x3c024019, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000,
-       0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
-       0x1440fffd, 0x24020001, 0xaf62000c, 0x93630023, 0x3c028000, 0x34420001,
-       0x02821025, 0x306300bf, 0xa3630023, 0xaf420020, 0x8fa30024, 0x10600012,
-       0x8fa30018, 0x9362007c, 0x24420001, 0xa362007c, 0x9363007e, 0x9362007a,
-       0x1462000b, 0x8fa30018, 0x9362007c, 0x3c030800, 0x8c640024, 0x0044102b,
-       0x14400005, 0x8fa30018, 0x0e0013c4, 0x00000000, 0x02e2b825, 0x8fa30018,
-       0x3062ffff, 0x10400003, 0x32220200, 0x0a000a94, 0x241e0004, 0x10400003,
-       0x00000000, 0x241e0040, 0x24170001, 0x12a000d0, 0x32220002, 0x104000cf,
-       0x8fa2001c, 0x92c2000a, 0x30420002, 0x5040003b, 0x92c2000a, 0x93620023,
-       0x30420008, 0x54400037, 0x92c2000a, 0x3c020800, 0x8c430020, 0x10600023,
-       0x3c029000, 0x0e00148e, 0x00000000, 0x8f840018, 0x8ec30000, 0xac830000,
-       0x92c2000a, 0x8f830018, 0x00021600, 0xac620004, 0x8f840018, 0x8f620040,
-       0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, 0x9362003f, 0x8f840018,
-       0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018,
-       0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
-       0x3c02401a, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001,
-       0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-       0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x34630008,
-       0xa3630023, 0xaf420020, 0x92c2000a, 0x30420020, 0x1040008e, 0x8fa2001c,
-       0x93620023, 0x30420001, 0x14400035, 0x3c020800, 0x8c430020, 0x10600023,
-       0x3c029000, 0x0e00148e, 0x00000000, 0x8f840018, 0x8ec30000, 0xac830000,
-       0x92c2000a, 0x8f830018, 0x00021600, 0xac620004, 0x8f840018, 0x8f620040,
-       0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, 0x9362003f, 0x8f840018,
-       0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018,
-       0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
-       0x3c02401a, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001,
-       0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-       0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x34630001,
-       0xa3630023, 0xaf420020, 0x93620023, 0x30420040, 0x10400052, 0x8fa2001c,
-       0x16600020, 0x3c120800, 0x8e420020, 0x8f70004c, 0x1040003c, 0x3c029000,
-       0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, 0x24020001,
-       0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
-       0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448,
-       0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010,
-       0x00621825, 0x0e0014cc, 0xaca3001c, 0x8e420020, 0x1040001e, 0x3c029000,
-       0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, 0x3c02008d,
-       0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
-       0xac600010, 0x8f840018, 0x240207ee, 0xac820014, 0x8f850018, 0x3c026000,
-       0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
-       0x3c024019, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001,
-       0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-       0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x306300bf,
-       0xa3630023, 0xaf420020, 0x8fa2001c, 0x1040000e, 0x8fa20014, 0x92c2000a,
-       0xa3620082, 0x57c00005, 0x37de0008, 0x8fa30014, 0x10600004, 0x00000000,
-       0x37de0008, 0x0a000b75, 0x24170001, 0x0e0012cf, 0x02802021, 0x8fa20014,
-       0x10400003, 0x00000000, 0x37de0010, 0x24170001, 0x12e00020, 0x3c029000,
-       0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
-       0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x03c21025, 0xa362007d,
-       0x8f640074, 0x34630001, 0x02831825, 0xaf430020, 0x04810006, 0x3c038000,
-       0x02802021, 0x0e000470, 0x2405082a, 0x0a000b9b, 0x00000000, 0x8f4201f8,
-       0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4,
-       0xaf4301f8, 0x9363003f, 0x24020012, 0x14620004, 0x8fbf004c, 0x0e00140d,
-       0x00000000, 0x8fbf004c, 0x8fbe0048, 0x8fb70044, 0x8fb60040, 0x8fb5003c,
-       0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x03e00008,
-       0x27bd0050, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f500180, 0x97420184,
-       0x30420200, 0x14400015, 0x00000000, 0x8f430188, 0x3c02ff00, 0x00621824,
-       0x3c020200, 0x10620031, 0x0043102b, 0x14400007, 0x3c020300, 0x1060000b,
-       0x3c020100, 0x1062000d, 0x00000000, 0x0a000c2c, 0x00000000, 0x10620027,
-       0x3c020400, 0x1062003e, 0x02002021, 0x0a000c2c, 0x00000000, 0x0e000c31,
-       0x02002021, 0x0a000c2e, 0x8fbf0014, 0x93620005, 0x30420020, 0x1440005e,
-       0x8fbf0014, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000,
-       0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000,
-       0x34630001, 0x02031825, 0x34420020, 0xa3620005, 0xaf430020, 0x93620005,
-       0x30420020, 0x14400003, 0x02002021, 0x0000000d, 0x02002021, 0x0e000766,
-       0x24055854, 0x0a000c2e, 0x8fbf0014, 0x93620005, 0x30420001, 0x1040003f,
-       0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020,
-       0x00431024, 0x1440fffd, 0x00000000, 0x93620023, 0x34420004, 0xa3620023,
-       0x93630005, 0x3c048000, 0x3c020800, 0x306300fe, 0xa3630005, 0x8c430020,
-       0x34840001, 0x02042025, 0x0a000c0a, 0xaf440020, 0x00002821, 0x00003021,
-       0x0e000fb1, 0x240708d9, 0x3c020800, 0x8c430020, 0x10600023, 0x8fbf0014,
-       0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x93630082, 0x9362003f,
-       0x8f840018, 0x00031a00, 0x00431025, 0xac820004, 0x8f830018, 0xac600008,
-       0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014,
-       0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018,
-       0x944358ce, 0x8f850018, 0x3c02400a, 0x00621825, 0x0e0014cc, 0xaca3001c,
-       0x0a000c2e, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, 0x03e00008,
-       0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x8f420188, 0x00803021, 0x93640000,
-       0x24030020, 0x00021402, 0x10830008, 0x304500ff, 0x3c036018, 0x8c625000,
-       0x34420400, 0xac625000, 0x0000000d, 0x00000000, 0x24000955, 0x9363003f,
-       0x24020012, 0x14620023, 0x3c029000, 0x34420001, 0x3c038000, 0x00c21025,
-       0xaf650178, 0xa365007a, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd,
-       0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001,
-       0x00c31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00c02021, 0x0e000470,
-       0x24050963, 0x0a000c79, 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd,
-       0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4, 0xaf4301f8, 0x0a000c79,
-       0x8fbf0010, 0x9362007e, 0x1445000e, 0x00000000, 0x8f620178, 0x1045000b,
-       0x00000000, 0x8f820000, 0xaf650178, 0x8f660178, 0x8f440180, 0x8f65004c,
-       0x8c430000, 0x0060f809, 0x30c600ff, 0x0a000c79, 0x8fbf0010, 0xaf650178,
-       0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93630000,
-       0x24020020, 0x10620005, 0x00000000, 0x93630000, 0x24020030, 0x1462004d,
-       0x8fbf0010, 0x93420148, 0x2444ffff, 0x2c830005, 0x10600047, 0x3c020800,
-       0x24425800, 0x00041880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000,
-       0x8f430144, 0x8f62000c, 0x14620006, 0x24020001, 0xaf62000c, 0x0e000d59,
-       0x00000000, 0x0a000cd1, 0x8fbf0010, 0x8f62000c, 0x0a000cca, 0x00000000,
-       0x97630010, 0x8f420144, 0x14430006, 0x24020001, 0xa7620010, 0x0e00137a,
-       0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620010, 0x0a000cca, 0x00000000,
-       0x97630012, 0x8f420144, 0x14430006, 0x24020001, 0xa7620012, 0x0e001395,
-       0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620012, 0x0a000cca, 0x00000000,
-       0x97630014, 0x8f420144, 0x14430006, 0x24020001, 0xa7620014, 0x0e0013bb,
-       0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620014, 0x0a000cca, 0x00000000,
-       0x97630016, 0x8f420144, 0x14430006, 0x24020001, 0xa7620016, 0x0e0013be,
-       0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620016, 0x14400006, 0x8fbf0010,
-       0x3c030800, 0x8c620070, 0x24420001, 0xac620070, 0x8fbf0010, 0x03e00008,
-       0x27bd0018, 0x27bdffe0, 0x3c029000, 0xafbf001c, 0xafb20018, 0xafb10014,
-       0xafb00010, 0x8f500140, 0x34420001, 0x3c038000, 0x02021025, 0xaf420020,
-       0x8f420020, 0x00431024, 0x1440fffd, 0x24020012, 0x24030080, 0xa362003f,
-       0xa3630082, 0x93620023, 0x30420040, 0x10400007, 0x00008821, 0x93620023,
-       0x24110001, 0x304200bf, 0xa3620023, 0x0a000cf0, 0x3c028000, 0x3c028000,
-       0x34420001, 0x3c039000, 0x34630001, 0x3c048000, 0x02021025, 0x02031825,
-       0xaf420020, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000,
-       0x9362007d, 0x3c038000, 0x34420020, 0xa362007d, 0x8f640074, 0x34630001,
-       0x02031825, 0xaf430020, 0x04810006, 0x3c038000, 0x02002021, 0x0e000470,
-       0x24050a63, 0x0a000d13, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd,
-       0x24020002, 0x3c031000, 0xaf5001c0, 0xa34201c4, 0xaf4301f8, 0x1220003f,
-       0x3c120800, 0x8e420020, 0x8f71004c, 0x1040003c, 0x8fbf001c, 0x0e00148e,
-       0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004,
-       0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-       0x8f820018, 0xac510014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001,
-       0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825,
-       0x0e0014cc, 0xaca3001c, 0x8e420020, 0x1040001e, 0x8fbf001c, 0x0e00148e,
-       0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x3c02008d, 0xac820004,
-       0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-       0x8f840018, 0x24020a6a, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448,
-       0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024019,
-       0x00621825, 0x0e0014cc, 0xaca3001c, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-       0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x93620081,
-       0x3c030800, 0x8c640048, 0x0044102b, 0x14400005, 0x00000000, 0x0e000cd3,
-       0x00000000, 0x0a000da4, 0x8fbf0010, 0x93620081, 0x24420001, 0x0e0013c4,
-       0xa3620081, 0x9763006a, 0x00032880, 0x14a00002, 0x00403821, 0x24050001,
-       0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804,
-       0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b,
-       0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021,
-       0xaf62000c, 0x10e00021, 0x3c029000, 0x8f450140, 0x34420001, 0x3c038000,
-       0x00a21025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
-       0x9362007d, 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, 0x34630001,
-       0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, 0x0e000470,
-       0x24050a92, 0x0a000da4, 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd,
-       0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, 0x8fbf0010,
-       0x03e00008, 0x27bd0018, 0x27bdffd8, 0xafb3001c, 0x27530100, 0xafbf0024,
-       0xafb40020, 0xafb20018, 0xafb10014, 0xafb00010, 0x96620008, 0x3c140800,
-       0x8f520100, 0x30420001, 0x104000da, 0x00000000, 0x8e700018, 0x8f630054,
-       0x2602ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, 0x00000000,
-       0x2400015c, 0x0a000dea, 0x00008821, 0x8f62004c, 0x02021023, 0x18400028,
-       0x00008821, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff,
-       0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, 0xac62008c, 0x3c040800,
-       0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, 0x00021023,
-       0x30420005, 0x0a000dea, 0x34510004, 0x27660100, 0x00041080, 0x00c21021,
-       0x8c430000, 0x02031823, 0x04600004, 0x24820001, 0x30440007, 0x1485fff9,
-       0x00041080, 0x10870007, 0x3c030800, 0xa3640121, 0x8c620094, 0x24110005,
-       0x24420001, 0x0a000dea, 0xac620094, 0x24110004, 0x32220001, 0x1040001e,
-       0x8e820020, 0x1040001d, 0x32220004, 0x0e00148e, 0x00000000, 0x8f820018,
-       0xac520000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018, 0xac600008,
-       0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac500014,
-       0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018,
-       0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, 0x0e0014cc, 0xaca3001c,
-       0x32220004, 0x10400081, 0x00003821, 0x3c029000, 0x34420001, 0x3c038000,
-       0x02421025, 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd,
-       0x00000000, 0x93620023, 0x30420080, 0x10400011, 0x00000000, 0x8f65005c,
-       0x8f63004c, 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b,
-       0x54400006, 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, 0xaf700064,
-       0x3c023fff, 0x0a000e37, 0x3442ffff, 0x8f62005c, 0x02021023, 0x04400011,
-       0x00000000, 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff,
-       0xaf700064, 0x00a32823, 0x00852821, 0x0045102b, 0x10400004, 0x02051021,
-       0x3c053fff, 0x34a5ffff, 0x02051021, 0xaf62005c, 0x24070001, 0xaf70004c,
-       0x8f620054, 0x16020005, 0x00000000, 0x93620023, 0x30420040, 0x10400017,
-       0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, 0x97630068,
-       0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b,
-       0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001,
-       0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c,
-       0x93620082, 0x30420080, 0x50400001, 0xa3600081, 0x3c028000, 0x34420001,
-       0x02421025, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, 0x00000000,
-       0x0e0013c4, 0x00000000, 0x00403821, 0x10e0001f, 0x3c029000, 0x34420001,
-       0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-       0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001,
-       0x02431825, 0xaf430020, 0x04810006, 0x3c038000, 0x02402021, 0x0e000470,
-       0x24050b3d, 0x0a000e8d, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd,
-       0x24020002, 0x3c031000, 0xaf5201c0, 0xa34201c4, 0xaf4301f8, 0x9342010b,
-       0x9343010b, 0x8e820020, 0x27500100, 0x38630006, 0x10400029, 0x2c710001,
-       0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018,
-       0x96020008, 0xac820004, 0x8f830018, 0x8e020014, 0xac620008, 0x8f850018,
-       0x3c026000, 0x8c434448, 0xaca3000c, 0x8f840018, 0x96020012, 0xac820010,
-       0x8f850018, 0x8e030020, 0xaca30014, 0x9602000c, 0x9603000e, 0x8f840018,
-       0x00021400, 0x00431025, 0xac820018, 0x12200005, 0x3c020800, 0x944358ce,
-       0x8f840018, 0x0a000eb8, 0x3c024013, 0x944358ce, 0x8f840018, 0x3c024014,
-       0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8e700014, 0x8f620040,
-       0x14500003, 0x00501023, 0x0a000ec3, 0x00001021, 0x28420001, 0x1040003a,
-       0x00000000, 0x0e000fae, 0x02002021, 0xaf700040, 0x9362003e, 0x30420001,
-       0x1440000b, 0x3c029000, 0x93620022, 0x24420001, 0xa3620022, 0x93630022,
-       0x3c020800, 0x8c440098, 0x0064182b, 0x14600025, 0x3c020800, 0x3c029000,
-       0x34420001, 0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
-       0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x34420001, 0xa362007d,
-       0x8f640074, 0x34630001, 0x02431825, 0xaf430020, 0x04810006, 0x3c038000,
-       0x02402021, 0x0e000470, 0x24050273, 0x0a000ef6, 0x24020001, 0x8f4201f8,
-       0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5201c0, 0xa34201c4,
-       0xaf4301f8, 0x24020001, 0xa7620012, 0x0a000efe, 0xa3600022, 0x9743007a,
-       0x9444002a, 0x00641821, 0x3063fffe, 0xa7630012, 0x97420108, 0x8fbf0024,
-       0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042,
-       0x30420001, 0x03e00008, 0x27bd0028, 0x27bdffe0, 0xafb20018, 0x3c120800,
-       0x8e420020, 0xafb00010, 0x27500100, 0xafbf001c, 0x10400046, 0xafb10014,
-       0x0e00148e, 0x00000000, 0x8f840018, 0x8e020000, 0xac820000, 0x936300b1,
-       0x936200c5, 0x8f850018, 0x00031e00, 0x00021400, 0x34420100, 0x00621825,
-       0xaca30004, 0x8f840018, 0x8e02001c, 0xac820008, 0x8f830018, 0x8f620048,
-       0xac62000c, 0x8f840018, 0x96020012, 0xac820010, 0x8f830018, 0x8f620040,
-       0x24040001, 0xac620014, 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800,
-       0x245158c0, 0xaca30018, 0x9623000e, 0x8f850018, 0x3c024016, 0x00621825,
-       0x0e0014cc, 0xaca3001c, 0x96030008, 0x30630010, 0x1060001c, 0x8e420020,
-       0x1040001a, 0x8e100000, 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000,
-       0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c,
-       0x8f820018, 0xac400010, 0x8f830018, 0xac600014, 0x8f850018, 0x3c036000,
-       0x8c634448, 0x24040001, 0xaca30018, 0x9622000e, 0x8f850018, 0x3c034015,
-       0x00431025, 0x0e0014cc, 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018,
-       0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe0, 0xafb20018,
-       0x3c120800, 0x8e420020, 0xafb00010, 0x27500100, 0xafbf001c, 0x10400041,
-       0xafb10014, 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000,
-       0x8f840018, 0x24020100, 0xac820004, 0x8f830018, 0x8e02001c, 0xac620008,
-       0x8f840018, 0x8e020018, 0xac82000c, 0x8f830018, 0x96020012, 0xac620010,
-       0x8f840018, 0x96020008, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448,
-       0x24040001, 0x3c020800, 0x245158c0, 0xaca30018, 0x9623000e, 0x8f850018,
-       0x3c024017, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x96030008, 0x30630010,
-       0x1060001c, 0x8e420020, 0x1040001a, 0x8e100000, 0x0e00148e, 0x00000000,
-       0x8f820018, 0xac500000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008,
-       0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, 0xac600014,
-       0x8f850018, 0x3c036000, 0x8c634448, 0x24040001, 0xaca30018, 0x9622000e,
-       0x8f850018, 0x3c034015, 0x00431025, 0x0e0014cc, 0xaca2001c, 0x00001021,
-       0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
-       0x27bdfff0, 0x03e00008, 0x27bd0010, 0x27bdffd0, 0xafb10014, 0x00808821,
-       0xafb40020, 0x00c0a021, 0xafbf0028, 0xafb50024, 0xafb3001c, 0xafb20018,
-       0xafb00010, 0x93620023, 0x00e0a821, 0x30420040, 0x1040003e, 0x30b3ffff,
-       0x3c120800, 0x8e420020, 0x1040003a, 0x8f70004c, 0x0e00148e, 0x00000000,
-       0x8f820018, 0xac510000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018,
-       0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018,
-       0x24040001, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800,
-       0x245058c0, 0xaca30018, 0x9603000e, 0x8f850018, 0x3c024010, 0x00621825,
-       0x0e0014cc, 0xaca3001c, 0x8e430020, 0x1060001b, 0x00000000, 0x0e00148e,
-       0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x3c02008d, 0xac820004,
-       0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-       0x8f820018, 0xac550014, 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001,
-       0xaca30018, 0x9602000e, 0x8f850018, 0x3c034019, 0x00431025, 0x0e0014cc,
-       0xaca2001c, 0x93620023, 0x30420020, 0x14400003, 0x3c120800, 0x1280003f,
-       0x3c029000, 0x8e420020, 0x8f70004c, 0x1040003b, 0x3c029000, 0x0e00148e,
-       0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x24020001, 0xac820004,
-       0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-       0x8f820018, 0x24040001, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448,
-       0x3c020800, 0x245058c0, 0xaca30018, 0x9603000e, 0x8f850018, 0x3c024010,
-       0x00621825, 0x0e0014cc, 0xaca3001c, 0x8e430020, 0x1060001c, 0x3c029000,
-       0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x00131400,
-       0xac820004, 0x8f830018, 0xac750008, 0x8f820018, 0xac40000c, 0x8f830018,
-       0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c036000, 0x8c634448,
-       0x24040001, 0xaca30018, 0x9602000e, 0x8f850018, 0x3c03401b, 0x00431025,
-       0x0e0014cc, 0xaca2001c, 0x3c029000, 0x34420001, 0x02221025, 0xaf420020,
-       0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023,
-       0x3c028000, 0x34420001, 0x02221025, 0x8fbf0028, 0x8fb50024, 0x8fb40020,
-       0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3063009f, 0xa3630023,
-       0xaf420020, 0x03e00008, 0x27bd0030, 0x27bdffe0, 0xafb10014, 0x27510100,
-       0x3c029000, 0x34420001, 0xafb00010, 0x00808021, 0x02021025, 0x3c038000,
-       0xafbf0018, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
-       0xa7600008, 0x8f63005c, 0x3c028000, 0x34420001, 0xaf630148, 0x8f640050,
-       0x02021025, 0x3c039000, 0xaf64017c, 0xaf420020, 0x8f450100, 0x34630001,
-       0x3c048000, 0x00a31825, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd,
-       0x00000000, 0x9362007d, 0x3c038000, 0x34420001, 0xa362007d, 0x8f640074,
-       0x34630001, 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021,
-       0x0e000470, 0x24050de5, 0x0a001093, 0x3c020800, 0x8f4201f8, 0x00431024,
-       0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8,
-       0x3c020800, 0x8c430020, 0x1060001e, 0x8fbf0018, 0x0e00148e, 0x00000000,
-       0x8f830018, 0xac700000, 0x9622000c, 0x8f840018, 0x00021400, 0xac820004,
-       0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-       0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001,
-       0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02401f, 0x00621825,
-       0x0e0014cc, 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008,
-       0x27bd0020, 0x3c020800, 0x24424c3c, 0xaf82000c, 0x03e00008, 0x00000000,
-       0x27bdffe8, 0xafb00010, 0x27500100, 0xafbf0014, 0x8e02001c, 0x14400003,
-       0x3c020800, 0x0000000d, 0x3c020800, 0x8c430020, 0x10600020, 0x00001021,
-       0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018,
-       0x8e02001c, 0xac820004, 0x8f830018, 0xac600008, 0x8f840018, 0x8e020018,
-       0xac82000c, 0x8f850018, 0x96020012, 0xaca20010, 0x8f830018, 0x3c026000,
-       0xac600014, 0x8f840018, 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce,
-       0x8f840018, 0x3c024012, 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001,
-       0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800,
-       0x97430078, 0x9444002e, 0x00001021, 0x00641821, 0x3063fffe, 0x03e00008,
-       0xa7630010, 0x27bdfff0, 0x00001021, 0x03e00008, 0x27bd0010, 0x8f420100,
-       0x34420001, 0xaf4200a4, 0x03e00008, 0x00001021, 0x27bdffe0, 0xafbf0018,
-       0xafb10014, 0xafb00010, 0x9362007e, 0x30d000ff, 0x16020031, 0x00808821,
-       0x8f620178, 0x1602002e, 0x00000000, 0x9362007f, 0x1602002b, 0x00000000,
-       0x9362007a, 0x16020004, 0x00000000, 0x0000000d, 0x00000000, 0x240009d2,
-       0x0e0013e6, 0x00000000, 0x3c039000, 0x34630001, 0x3c048000, 0x02231825,
-       0xa370007a, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000,
-       0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, 0x02231825,
-       0xaf430020, 0x04810006, 0x3c038000, 0x02202021, 0x0e000470, 0x240509dd,
-       0x0a001138, 0x8fbf0018, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002,
-       0x3c031000, 0xaf5101c0, 0xa34201c4, 0xaf4301f8, 0x0a001138, 0x8fbf0018,
-       0x0000000d, 0x00000000, 0x240009e2, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-       0x03e00008, 0x27bd0020, 0x27bdffe8, 0x30a500ff, 0x3c029000, 0x34420001,
-       0x00803821, 0x00e21025, 0x3c038000, 0xafbf0010, 0xaf420020, 0x8f420020,
-       0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x00a21025,
-       0xa362007d, 0x8f640074, 0x34630001, 0x00e31825, 0xaf430020, 0x04810006,
-       0x3c038000, 0x00e02021, 0x0e000470, 0x00c02821, 0x0a001161, 0x8fbf0010,
-       0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4701c0,
-       0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800,
-       0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x10600024, 0xafbf0014,
-       0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018,
-       0x8e020004, 0xac820004, 0x8f830018, 0x8e020018, 0xac620008, 0x8f840018,
-       0x8e03001c, 0xac83000c, 0x9602000c, 0x9203000a, 0x8f840018, 0x00021400,
-       0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018,
-       0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018,
-       0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, 0x8fbf0014,
-       0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8,
-       0xafb00010, 0x27500100, 0x10600020, 0xafbf0014, 0x0e00148e, 0x00000000,
-       0x8f820018, 0xac400000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008,
-       0x8f830018, 0xac60000c, 0x9602000c, 0x9603000e, 0x8f840018, 0x00021400,
-       0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018,
-       0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018,
-       0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, 0x8fbf0014,
-       0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010, 0x27500100,
-       0xafbf0014, 0x9602000c, 0x10400024, 0x00802821, 0x3c020800, 0x8c430020,
-       0x1060003a, 0x8fbf0014, 0x0e00148e, 0x00000000, 0x8f840018, 0x8e030000,
-       0xac830000, 0x9602000c, 0x8f840018, 0x00021400, 0xac820004, 0x8f830018,
-       0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018,
-       0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
-       0xaca30018, 0x944358ce, 0x8f850018, 0x3c02400b, 0x00621825, 0x0e0014cc,
-       0xaca3001c, 0x0a0011ff, 0x8fbf0014, 0x93620005, 0x30420010, 0x14400015,
-       0x3c029000, 0x34420001, 0x00a21025, 0xaf420020, 0x3c038000, 0x8f420020,
-       0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x93620005, 0x34630001,
-       0x00a02021, 0x00a31825, 0x24055852, 0x34420010, 0xa3620005, 0x0e000766,
-       0xaf430020, 0x0a0011ff, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010,
-       0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010,
-       0x27500100, 0x10600022, 0xafbf0014, 0x0e00148e, 0x00000000, 0x8f840018,
-       0x8e020004, 0xac820000, 0x9603000c, 0x9762002c, 0x8f840018, 0x00031c00,
-       0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
-       0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000,
-       0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
-       0x3c02400e, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x0e00122e, 0x8e040000,
-       0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c038000, 0x8f420278,
-       0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf440240, 0xa3420244,
-       0x03e00008, 0xaf430278, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014,
-       0x00808821, 0xafb20018, 0x00c09021, 0xafb00010, 0x30b0ffff, 0x1060001c,
-       0xafbf001c, 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018,
-       0x00101400, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
-       0x8f830018, 0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000,
-       0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024019,
-       0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018,
-       0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x27450100,
-       0xafbf0010, 0x94a3000c, 0x240200c1, 0x14620031, 0x00803021, 0x3c029000,
-       0x34420001, 0x00c21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
-       0x1440fffd, 0x3c028000, 0x34420001, 0x3c049000, 0x34840001, 0x3c058000,
-       0x24030012, 0x00c21025, 0x00c42025, 0xa363003f, 0xaf420020, 0xaf440020,
-       0x8f420020, 0x00451024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000,
-       0x34420020, 0xa362007d, 0x8f640074, 0x34630001, 0x00c31825, 0xaf430020,
-       0x04810006, 0x3c038000, 0x00c02021, 0x0e000470, 0x24050906, 0x0a0012a1,
-       0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000,
-       0xaf4601c0, 0xa34201c4, 0xaf4301f8, 0x0a0012a1, 0x8fbf0010, 0x00c02021,
-       0x94a5000c, 0x24060001, 0x0e000fb1, 0x2407090e, 0x8fbf0010, 0x03e00008,
-       0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00808021,
-       0xafb20018, 0x00a09021, 0xafb10014, 0x30d100ff, 0x1060001c, 0xafbf001c,
-       0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001,
-       0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
-       0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000, 0x8c434448,
-       0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024010, 0x00621825,
-       0xac83001c, 0x0e0014cc, 0x02202021, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-       0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010,
-       0x93620005, 0x30420001, 0x10400036, 0x00808021, 0x3c029000, 0x34420001,
-       0x02021025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-       0x00000000, 0x93620023, 0x34420004, 0xa3620023, 0x93630005, 0x3c048000,
-       0x3c020800, 0x306300fe, 0xa3630005, 0x8c430020, 0x34840001, 0x02042025,
-       0xaf440020, 0x10600020, 0x8fbf0014, 0x0e00148e, 0x00000000, 0x8f820018,
-       0xac500000, 0x93630082, 0x9362003f, 0x8f840018, 0x00031a00, 0x00431025,
-       0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
-       0xac600010, 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, 0x8c434448,
-       0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c02400a, 0x00621825,
-       0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf0014, 0x8fb00010, 0x03e00008,
-       0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014, 0x00808821,
-       0xafb20018, 0x00a09021, 0xafb00010, 0x30d000ff, 0x1060002f, 0xafbf001c,
-       0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f830018, 0xac700004,
-       0x8f820018, 0xac520008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010,
-       0x9763006a, 0x00032880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081,
-       0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001,
-       0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021,
-       0x8f830018, 0x2402fffe, 0x00822824, 0x3c026000, 0xac650014, 0x8f840018,
-       0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024011,
-       0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018,
-       0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014,
-       0xafb00010, 0x8f440100, 0x27500100, 0x8f650050, 0x0e0010fc, 0x9206001b,
-       0x3c020800, 0x8c430020, 0x1060001d, 0x8e100018, 0x0e00148e, 0x00000000,
-       0x8f840018, 0x8f420100, 0xac820000, 0x8f830018, 0xac700004, 0x8f840018,
-       0x8f620050, 0xac820008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010,
-       0x8f830018, 0x3c026000, 0xac600014, 0x8f850018, 0x8c434448, 0x24040001,
-       0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02401c, 0x00621825,
-       0x0e0014cc, 0xaca3001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018,
-       0x8f430238, 0x3c020800, 0x04610013, 0x8c44009c, 0x2406fffe, 0x3c050800,
-       0x3c038000, 0x2484ffff, 0x14800009, 0x00000000, 0x97420078, 0x8ca3007c,
-       0x24420001, 0x00461024, 0x24630001, 0xa7620010, 0x03e00008, 0xaca3007c,
-       0x8f420238, 0x00431024, 0x1440fff3, 0x2484ffff, 0x8f420140, 0x3c031000,
-       0xaf420200, 0x03e00008, 0xaf430238, 0x27bdffe8, 0x3c029000, 0xafbf0010,
-       0x8f450140, 0x34420001, 0x3c038000, 0x00a21025, 0xaf420020, 0x8f420020,
-       0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x34420001,
-       0xa362007d, 0x8f640074, 0x34630001, 0x00a31825, 0xaf430020, 0x04810006,
-       0x3c038000, 0x00a02021, 0x0e000470, 0x24050ac7, 0x0a0013b9, 0x8fbf0010,
-       0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0,
-       0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x0000000d,
-       0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x24020001,
-       0x03e00008, 0xa7620010, 0x9362003f, 0x304400ff, 0x3883000e, 0x2c630001,
-       0x38820010, 0x2c420001, 0x00621825, 0x14600003, 0x24020012, 0x14820003,
-       0x00000000, 0x03e00008, 0x00001021, 0x9363007e, 0x9362007a, 0x14620006,
-       0x00000000, 0x9363007e, 0x24020001, 0x24630001, 0x03e00008, 0xa363007e,
-       0x9362007e, 0x8f630178, 0x304200ff, 0x14430006, 0x00000000, 0x9363000b,
-       0x24020001, 0x24630001, 0x03e00008, 0xa363000b, 0x03e00008, 0x00001021,
-       0x9362000b, 0x10400023, 0x00001021, 0xa360000b, 0x9362003f, 0x304400ff,
-       0x3883000e, 0x2c630001, 0x38820010, 0x2c420001, 0x00621825, 0x14600017,
-       0x00001821, 0x24020012, 0x10820014, 0x00000000, 0x9363007e, 0x9362007a,
-       0x14620007, 0x00000000, 0x9362007e, 0x24030001, 0x24420001, 0xa362007e,
-       0x03e00008, 0x00601021, 0x9362007e, 0x8f630178, 0x304200ff, 0x14430005,
-       0x00001821, 0x9362000b, 0x24030001, 0x24420001, 0xa362000b, 0x03e00008,
-       0x00601021, 0x03e00008, 0x00000000, 0x24040001, 0xaf64000c, 0x8f6300dc,
-       0x8f6200cc, 0x50620001, 0xa7640010, 0xa7640012, 0xa7640014, 0x03e00008,
-       0xa7640016, 0x3c020800, 0x8c430020, 0x27bdffe8, 0x1060001b, 0xafbf0010,
-       0x0e00148e, 0x00000000, 0x8f820018, 0xac400000, 0x8f830018, 0xac600004,
-       0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010,
-       0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, 0x8c434448, 0x3c020800,
-       0xac830018, 0x944358ce, 0x8f840018, 0x3c024020, 0x00621825, 0xac83001c,
-       0x0e0014cc, 0x24040001, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800,
-       0x8c430020, 0x27bdffe0, 0xafb00010, 0x00a08021, 0xafb10014, 0x00c08821,
-       0xafb20018, 0x00e09021, 0x1060001e, 0xafbf001c, 0x0e00148e, 0x00000000,
-       0x8f840018, 0x8f420100, 0xac820000, 0x8f830018, 0xac700004, 0x8f820018,
-       0xac510008, 0x8f830018, 0xac72000c, 0x8f840018, 0x8fa20030, 0xac820010,
-       0x8f830018, 0x8fa20034, 0xac620014, 0x8f840018, 0x3c026000, 0x8c434448,
-       0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c0240c9, 0x00621825,
-       0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-       0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800, 0x8c430020, 0x27bdffe8,
-       0xafb00010, 0x27500100, 0x1060001d, 0xafbf0014, 0x0e00148e, 0x00000000,
-       0x8f830018, 0x8e020004, 0xac620000, 0x8f840018, 0x8e020018, 0xac820004,
-       0x8f850018, 0x8e020000, 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018,
-       0xac400010, 0x8f830018, 0xac600014, 0x8f820018, 0xac400018, 0x96030008,
-       0x3c020800, 0x944458ce, 0x8f850018, 0x00031c00, 0x00641825, 0x24040001,
-       0x0e0014cc, 0xaca3001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018,
-       0x3c060800, 0x24c558c0, 0x3c02000a, 0x03421821, 0x94640006, 0x94a2000a,
-       0x00441023, 0x00021400, 0x00021c03, 0x04610006, 0xa4a40006, 0x0000000d,
-       0x00000000, 0x2400005a, 0x0a0014a3, 0x24020001, 0x8f820014, 0x0062102b,
-       0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1040001c, 0x274a0400,
-       0x3c07000a, 0x3c020800, 0x244558c0, 0x94a9000a, 0x8f880014, 0x03471021,
-       0x94430006, 0x00402021, 0xa4a30006, 0x94820006, 0xa4a20006, 0x01221023,
-       0x00021400, 0x00021403, 0x04410006, 0x0048102b, 0x0000000d, 0x00000000,
-       0x2400005a, 0x0a0014be, 0x24020001, 0x14400002, 0x00001021, 0x24020001,
-       0x304200ff, 0x1440ffec, 0x03471021, 0x24c458c0, 0x8c820010, 0xaf420038,
-       0x8c830014, 0x3c020005, 0xaf43003c, 0xaf420030, 0xaf800010, 0xaf8a0018,
-       0x03e00008, 0x00000000, 0x27bdffe0, 0x8f820010, 0x8f850018, 0x3c070800,
-       0x24e858c0, 0xafbf001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x9503000a,
-       0x8d060014, 0x00009021, 0x309000ff, 0x00e08821, 0x24420001, 0x24a50020,
-       0x24630001, 0xaf820010, 0xaf850018, 0xa503000a, 0x24c30020, 0x3c028000,
-       0x04c10007, 0xad030014, 0x00621024, 0x14400005, 0x262258c0, 0x8d020010,
-       0x24420001, 0xad020010, 0x262258c0, 0x9444000a, 0x94450018, 0x0010102b,
-       0x00a41826, 0x2c630001, 0x00621825, 0x1060001c, 0x3c030006, 0x8f820010,
-       0x24120001, 0x00021140, 0x00431025, 0xaf420030, 0x00000000, 0x00000000,
-       0x00000000, 0x27450400, 0x8f420000, 0x30420010, 0x1040fffd, 0x262258c0,
-       0x9444000a, 0x94430018, 0xaf800010, 0xaf850018, 0x14830012, 0x262758c0,
-       0x0e00155a, 0x00000000, 0x1600000e, 0x262758c0, 0x0e00148e, 0x00000000,
-       0x0a001517, 0x262758c0, 0x00041c00, 0x00031c03, 0x00051400, 0x00021403,
-       0x00621823, 0x18600002, 0x3c026000, 0xac400808, 0x262758c0, 0x94e2000e,
-       0x94e3000c, 0x24420001, 0xa4e2000e, 0x3042ffff, 0x50430001, 0xa4e0000e,
-       0x12000005, 0x3c02000a, 0x94e2000a, 0xa74200a2, 0x0a001554, 0x02401021,
-       0x03421821, 0x94640006, 0x94e2000a, 0x00441023, 0x00021400, 0x00021c03,
-       0x04610006, 0xa4e40006, 0x0000000d, 0x00000000, 0x2400005a, 0x0a001536,
-       0x24020001, 0x8f820014, 0x0062102b, 0x14400002, 0x00001021, 0x24020001,
-       0x304200ff, 0x1040001b, 0x3c020800, 0x3c06000a, 0x244558c0, 0x94a8000a,
-       0x8f870014, 0x03461021, 0x94430006, 0x00402021, 0xa4a30006, 0x94820006,
-       0xa4a20006, 0x01021023, 0x00021400, 0x00021403, 0x04410006, 0x0047102b,
-       0x0000000d, 0x00000000, 0x2400005a, 0x0a001550, 0x24020001, 0x14400002,
-       0x00001021, 0x24020001, 0x304200ff, 0x1440ffec, 0x03461021, 0x02401021,
-       0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
-       0x3c020800, 0x244558c0, 0x94a3001a, 0x8ca40024, 0x00403021, 0x000318c0,
-       0x00832021, 0xaf44003c, 0x8ca20020, 0xaf420038, 0x3c020050, 0x34420008,
-       0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x8f420000, 0x30420020,
-       0x1040fffd, 0x00000000, 0x8f430400, 0x24c658c0, 0xacc30010, 0x8f420404,
-       0x3c030020, 0xacc20014, 0xaf430030, 0x94c40018, 0x94c3001c, 0x94c2001a,
-       0x94c5001e, 0x00832021, 0x24420001, 0xa4c2001a, 0x3042ffff, 0x14450002,
-       0xa4c40018, 0xa4c0001a, 0x03e00008, 0x00000000, 0x8f820010, 0x3c030006,
-       0x00021140, 0x00431025, 0xaf420030, 0x00000000, 0x00000000, 0x00000000,
-       0x27430400, 0x8f420000, 0x30420010, 0x1040fffd, 0x00000000, 0xaf800010,
-       0xaf830018, 0x03e00008, 0x00000000, 0x27bdffe8, 0xafb00010, 0x3c100800,
-       0x261058c0, 0x3c05000a, 0x02002021, 0x03452821, 0xafbf0014, 0x0e0015b0,
-       0x2406000a, 0x96020002, 0x9603001e, 0x3042000f, 0x24420003, 0x00431804,
-       0x24027fff, 0x0043102b, 0xaf830014, 0x10400004, 0x00000000, 0x0000000d,
-       0x00000000, 0x24000043, 0x0e00155a, 0x00000000, 0x8fbf0014, 0x8fb00010,
-       0x03e00008, 0x27bd0018, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff,
-       0x24a50004, 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000,
-       0x0a0015c1, 0x00a01021, 0xac860000, 0x00000000, 0x00000000, 0x24840004,
-       0x00a01021, 0x1440fffa, 0x24a5ffff, 0x03e00008, 0x00000000, 0x3c036000,
-       0x8c642b7c, 0x3c036010, 0x8c6553fc, 0x00041582, 0x00042302, 0x308403ff,
-       0x00052d82, 0x00441026, 0x0002102b, 0x0005282b, 0x00451025, 0x1440000d,
-       0x3c020050, 0x34420004, 0xaf400038, 0xaf40003c, 0xaf420030, 0x00000000,
-       0x00000000, 0x8f420000, 0x30420020, 0x1040fffd, 0x3c020020, 0xaf420030,
-       0x0000000d, 0x03e00008, 0x00000000, 0x3c020050, 0x34420004, 0xaf440038,
-       0xaf45003c, 0xaf420030, 0x00000000, 0x00000000, 0x8f420000, 0x30420020,
-       0x1040fffd, 0x3c020020, 0xaf420030, 0x03e00008, 0x00000000, 0x00000000};
+static u8 bnx2_COM_b06FwText[] = {
+       0x1f, 0x8b, 0x08, 0x08, 0x09, 0x83, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5b, 0x7d, 0x6c,
+       0x5b, 0xd7, 0x75, 0x3f, 0xef, 0xf1, 0x51, 0x7a, 0x96, 0x68, 0xf9, 0x99,
+       0x7e, 0x96, 0x59, 0x4f, 0xb1, 0x49, 0xf1, 0xc9, 0xd2, 0x62, 0x2d, 0x63,
+       0x34, 0x35, 0xd1, 0x3a, 0x26, 0x66, 0x48, 0xda, 0x71, 0x36, 0x67, 0xa0,
+       0x1d, 0x05, 0x51, 0x51, 0xaf, 0xd0, 0x48, 0xd9, 0xcd, 0xb2, 0x0c, 0x73,
+       0x96, 0xb4, 0x70, 0xbc, 0xb4, 0xa1, 0x25, 0x79, 0xf5, 0x06, 0x45, 0xcf,
+       0xb3, 0x34, 0x39, 0xc0, 0x82, 0x41, 0x10, 0x9d, 0x3a, 0x7f, 0x30, 0xa5,
+       0xed, 0x7c, 0x19, 0xe8, 0x12, 0x29, 0xb2, 0x93, 0xb5, 0x43, 0xd0, 0xa6,
+       0x68, 0xff, 0xe8, 0x8a, 0x6e, 0x30, 0x52, 0x0c, 0xf3, 0x3a, 0xa0, 0x30,
+       0xfa, 0xc7, 0xe6, 0x2d, 0x1f, 0xdc, 0xef, 0xdc, 0x77, 0x1f, 0xf9, 0x48,
+       0x51, 0x96, 0x1c, 0x34, 0x5d, 0xb7, 0x99, 0x80, 0xf0, 0xde, 0xbd, 0xf7,
+       0xbc, 0x7b, 0xcf, 0x3d, 0xdf, 0xe7, 0xdc, 0xab, 0x5f, 0x53, 0xa9, 0x85,
+       0xe4, 0x6f, 0x2d, 0xfe, 0xc2, 0x7f, 0xf4, 0xc7, 0xb9, 0xdb, 0x3e, 0x7d,
+       0x5b, 0x1f, 0x5e, 0x07, 0x54, 0xdd, 0xaf, 0x72, 0xbf, 0x0f, 0x7f, 0x26,
+       0xfe, 0xfa, 0xe4, 0x7b, 0xa3, 0x9f, 0x81, 0xbf, 0x2b, 0x18, 0x1c, 0xfe,
+       0x09, 0x91, 0xb2, 0x0c, 0x8c, 0xf7, 0x57, 0x2e, 0x5f, 0x7f, 0x9c, 0x17,
+       0x0e, 0xaf, 0x62, 0x9e, 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf,
+       0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, 0xff, 0x3f, 0x3f, 0x9f, 0x13, 0x72,
+       0x88, 0x98, 0x85, 0xff, 0x48, 0x57, 0xe3, 0x89, 0xa1, 0xa4, 0x45, 0xba,
+       0x2f, 0x7e, 0x65, 0x28, 0x67, 0x11, 0x25, 0x8a, 0xdb, 0xc3, 0x29, 0xfa,
+       0xb0, 0x9c, 0x37, 0x35, 0xe2, 0xfe, 0x5b, 0xe2, 0x1f, 0x3c, 0xfd, 0xfa,
+       0x9d, 0x91, 0xab, 0xb3, 0x3e, 0xd2, 0x8d, 0xf8, 0xcb, 0xba, 0xb1, 0x8d,
+       0xf4, 0x0e, 0x7c, 0xf3, 0x5c, 0xf7, 0x7f, 0xa8, 0xd4, 0xe6, 0xce, 0x75,
+       0xa5, 0xfc, 0x7a, 0x37, 0xe5, 0x37, 0xc7, 0x75, 0x52, 0xe3, 0x5d, 0x3f,
+       0x48, 0xfa, 0x8c, 0x61, 0x5f, 0xdc, 0xa0, 0xf9, 0x12, 0x65, 0x0e, 0x4c,
+       0xf0, 0x1a, 0xb1, 0x75, 0xf7, 0x62, 0x2e, 0x2d, 0x3e, 0x3c, 0xf4, 0x67,
+       0xd6, 0xd3, 0x65, 0xd5, 0xb2, 0x7a, 0xe6, 0x28, 0x30, 0xf0, 0x7c, 0x3f,
+       0xc6, 0x8b, 0x91, 0x1e, 0xa2, 0x3b, 0x49, 0xb5, 0xf2, 0x01, 0x9f, 0xa5,
+       0x53, 0xb2, 0x64, 0x51, 0xaa, 0x44, 0xf4, 0x77, 0x45, 0x85, 0x9e, 0xb7,
+       0xda, 0x69, 0xae, 0xf7, 0x83, 0x72, 0x02, 0xb8, 0xbc, 0x6d, 0x0d, 0x0f,
+       0x8d, 0x5b, 0x3c, 0x57, 0x7c, 0x9d, 0x83, 0x6f, 0x6f, 0x5b, 0xce, 0xd2,
+       0x68, 0xb4, 0xc8, 0x7d, 0xbd, 0x2d, 0xdc, 0xe7, 0x8f, 0x3f, 0x1c, 0x7c,
+       0xde, 0x0a, 0xc8, 0xbe, 0x1f, 0xa5, 0x92, 0x98, 0x6f, 0xac, 0xc8, 0xb0,
+       0xcf, 0xde, 0x91, 0xb3, 0x4c, 0xd9, 0x6f, 0xc5, 0x93, 0x56, 0x08, 0xfd,
+       0x1d, 0x72, 0x2c, 0xbd, 0x2e, 0x67, 0x59, 0x72, 0xac, 0x88, 0x6f, 0x7a,
+       0x65, 0xff, 0x3b, 0xa9, 0x9c, 0x15, 0x93, 0xfd, 0x57, 0x93, 0x49, 0xab,
+       0x5f, 0xf6, 0x1f, 0xbe, 0x2b, 0x67, 0xc5, 0x65, 0xff, 0xf7, 0x81, 0x8b,
+       0x41, 0xc7, 0x8a, 0x61, 0xfc, 0x25, 0x30, 0xfe, 0x9a, 0x41, 0x6d, 0x19,
+       0x8c, 0x61, 0xef, 0xb6, 0x4e, 0x97, 0x7d, 0x21, 0x7a, 0xbd, 0xfb, 0x32,
+       0x68, 0x63, 0xd0, 0xd9, 0x12, 0x29, 0x99, 0xee, 0x10, 0x68, 0x62, 0xd2,
+       0xb9, 0x52, 0x2b, 0xf9, 0x4e, 0xfa, 0xb0, 0xe7, 0xcf, 0x51, 0xd6, 0xd4,
+       0x69, 0xfd, 0x8c, 0x42, 0x9d, 0x7d, 0x6b, 0x28, 0x61, 0xe4, 0x29, 0xd5,
+       0x8d, 0x28, 0x6e, 0xd2, 0x24, 0x6d, 0x66, 0x71, 0xbd, 0x8a, 0x1e, 0x95,
+       0x22, 0xa1, 0x2c, 0x28, 0x3c, 0x72, 0xfa, 0x5d, 0x8e, 0x39, 0xb1, 0x26,
+       0xff, 0x85, 0x29, 0x35, 0x71, 0x2b, 0x0d, 0x1b, 0x8c, 0x0f, 0x80, 0x05,
+       0x1f, 0x74, 0x25, 0x79, 0x2a, 0x44, 0xc7, 0xec, 0x80, 0x92, 0x3a, 0x75,
+       0x37, 0x25, 0x63, 0x64, 0xaa, 0xd4, 0x25, 0xbe, 0x2d, 0x14, 0x43, 0x34,
+       0x6e, 0x93, 0x92, 0xb4, 0x99, 0x5e, 0xed, 0x18, 0x6f, 0x13, 0xb0, 0xe8,
+       0xeb, 0xf0, 0x51, 0x97, 0x91, 0x22, 0x9d, 0x71, 0x46, 0x7f, 0x50, 0x49,
+       0x8b, 0x39, 0x44, 0x7f, 0x78, 0x8c, 0x02, 0x74, 0xba, 0x68, 0x4a, 0xd8,
+       0x72, 0x39, 0x19, 0x33, 0x00, 0x07, 0xda, 0xd9, 0x26, 0x0d, 0xe3, 0x39,
+       0x6a, 0xf3, 0xfa, 0x21, 0xc8, 0xcc, 0xb7, 0x87, 0xb2, 0xd3, 0x62, 0xbe,
+       0xb0, 0x2f, 0xce, 0xf3, 0x75, 0x00, 0xee, 0x1d, 0xe0, 0xa5, 0x90, 0x26,
+       0x78, 0x95, 0xa0, 0xec, 0x84, 0x02, 0x79, 0xc2, 0x53, 0xd0, 0x2d, 0x0d,
+       0xfc, 0x35, 0xb2, 0xfa, 0x14, 0xca, 0x59, 0x9b, 0x28, 0x6f, 0xa0, 0x5d,
+       0xbc, 0xa0, 0x26, 0xed, 0x66, 0x4a, 0x69, 0x61, 0xec, 0x5f, 0xc8, 0x0a,
+       0x8d, 0xe1, 0x1b, 0xd5, 0x62, 0x98, 0x9f, 0x61, 0xef, 0xc3, 0x82, 0xfe,
+       0x4d, 0xf1, 0xfd, 0x74, 0x69, 0x22, 0xaf, 0x26, 0x4b, 0xed, 0xe4, 0x9b,
+       0x89, 0x40, 0x9a, 0xc7, 0xd5, 0xd4, 0x19, 0x8d, 0xfc, 0x93, 0x0a, 0x41,
+       0x3e, 0x0c, 0x5f, 0xfc, 0xb8, 0xba, 0xb3, 0x74, 0x41, 0x4d, 0x95, 0xf8,
+       0x1b, 0xc0, 0x16, 0x55, 0xd0, 0x96, 0xdf, 0xb7, 0x83, 0x96, 0x34, 0xac,
+       0xc6, 0x75, 0x3d, 0x51, 0x64, 0x99, 0xe5, 0x6f, 0xc1, 0x0f, 0xec, 0xe5,
+       0x9c, 0x0d, 0xfe, 0x08, 0x7e, 0x85, 0xc1, 0xaf, 0x6f, 0x82, 0x5f, 0xfd,
+       0xe0, 0x53, 0x8c, 0xde, 0x28, 0xf5, 0xd2, 0x6b, 0xa5, 0x1e, 0x7a, 0x15,
+       0x32, 0xf9, 0x4a, 0x29, 0x4c, 0x2f, 0x97, 0x3a, 0xe8, 0xa5, 0x52, 0x88,
+       0xce, 0x0b, 0x1e, 0xa6, 0x21, 0xff, 0x82, 0xaf, 0xfa, 0x26, 0xf0, 0xa4,
+       0x1d, 0x3c, 0x59, 0x0f, 0x79, 0xd9, 0x08, 0xf9, 0x9b, 0xee, 0xd6, 0x69,
+       0xaa, 0x9b, 0x12, 0x41, 0xf4, 0x6f, 0x89, 0x6b, 0x82, 0x4e, 0x1a, 0xc6,
+       0xc7, 0x26, 0xfc, 0x94, 0x32, 0x4e, 0xd3, 0x7b, 0x93, 0x1a, 0x8d, 0x95,
+       0xa6, 0x36, 0x3a, 0x7c, 0xe3, 0xf6, 0x2c, 0x5d, 0x44, 0x5f, 0xca, 0x98,
+       0xa5, 0x4b, 0xdb, 0x54, 0x1a, 0x9d, 0xfe, 0x1b, 0x4a, 0x9e, 0x39, 0x4d,
+       0x3f, 0xfe, 0x3a, 0x51, 0x06, 0x34, 0x51, 0xfb, 0x7e, 0x5a, 0x4e, 0x18,
+       0xa0, 0x45, 0x5f, 0xaf, 0x90, 0x08, 0xb5, 0x8f, 0x79, 0x19, 0x86, 0xae,
+       0x68, 0x4a, 0xca, 0x7e, 0x01, 0xfa, 0xd2, 0xaa, 0x24, 0xa7, 0x88, 0x72,
+       0x53, 0x65, 0xca, 0xc5, 0xfc, 0xf4, 0x98, 0x51, 0xa6, 0x74, 0xac, 0x89,
+       0xbe, 0x68, 0xb4, 0xd3, 0x68, 0xef, 0x6f, 0xf8, 0xdc, 0x5c, 0x65, 0xba,
+       0xd4, 0x8f, 0x77, 0xee, 0x23, 0x9a, 0x12, 0xef, 0x4e, 0x7f, 0xbe, 0xe4,
+       0xa7, 0x84, 0x99, 0x0f, 0x69, 0xf4, 0x8e, 0xcf, 0xc1, 0x29, 0xe1, 0x8e,
+       0x81, 0x57, 0xc3, 0xb0, 0x0f, 0x8e, 0x0c, 0x66, 0x27, 0xd6, 0x5c, 0x4b,
+       0x88, 0x6e, 0xc0, 0x0b, 0xd9, 0xd3, 0x18, 0x8f, 0x61, 0x25, 0x6e, 0x52,
+       0xa7, 0xd0, 0x8d, 0x7e, 0xc0, 0x0c, 0x28, 0xfb, 0x4a, 0xcc, 0x6b, 0xbc,
+       0x17, 0x19, 0xd7, 0xcd, 0x80, 0xd5, 0xf0, 0x4c, 0x48, 0x9c, 0xbd, 0x78,
+       0xf2, 0x5c, 0x8c, 0x27, 0x3f, 0x7f, 0xcf, 0x83, 0xe7, 0xe7, 0x2b, 0xef,
+       0x53, 0x9e, 0xf7, 0x7c, 0xe9, 0x4f, 0x03, 0x0e, 0x7e, 0x4c, 0xcf, 0x01,
+       0x1a, 0x9d, 0x38, 0x2c, 0xd7, 0xc2, 0x7b, 0x91, 0xd7, 0x38, 0x0d, 0x3a,
+       0x09, 0xc8, 0x15, 0xd6, 0x3a, 0xec, 0x59, 0xeb, 0x49, 0xcf, 0x5a, 0x4f,
+       0x7a, 0xd6, 0xca, 0x83, 0xb6, 0xb4, 0x4e, 0xb5, 0xfc, 0xd0, 0x51, 0xee,
+       0x39, 0x8e, 0x39, 0x9f, 0x03, 0x5f, 0xbe, 0x0a, 0x98, 0x38, 0x2d, 0xda,
+       0xa0, 0xc7, 0x94, 0x46, 0x7b, 0x4d, 0x7e, 0x7f, 0xb1, 0xd5, 0xc1, 0x8b,
+       0xdf, 0x2f, 0x48, 0x9c, 0x5a, 0x1d, 0xb8, 0xd2, 0x15, 0xa1, 0xff, 0xf3,
+       0x25, 0xd6, 0x4f, 0x8a, 0xf9, 0x2c, 0x3a, 0x94, 0x8e, 0xb5, 0xd3, 0x98,
+       0xa1, 0xc4, 0x46, 0x7b, 0x9a, 0x99, 0x8e, 0x09, 0xd5, 0x6a, 0x85, 0x0e,
+       0x50, 0x58, 0x65, 0xdb, 0x25, 0xf0, 0x7b, 0x49, 0xe2, 0x61, 0x70, 0x3b,
+       0xa3, 0x5a, 0xc1, 0xba, 0x7e, 0x96, 0xdf, 0x57, 0xf0, 0xce, 0x32, 0x9c,
+       0xd4, 0x9c, 0xb5, 0x5f, 0x45, 0x9b, 0xed, 0xce, 0x66, 0xd9, 0x76, 0xc7,
+       0xff, 0xa0, 0xa9, 0xb6, 0xfd, 0x05, 0xb3, 0xb6, 0xed, 0xea, 0x82, 0xd7,
+       0x66, 0xf1, 0xde, 0xc2, 0xe4, 0xb3, 0x58, 0x8e, 0xfc, 0xc0, 0x35, 0x06,
+       0x3d, 0x6c, 0x96, 0x38, 0x7c, 0x4b, 0xe2, 0x00, 0x5c, 0x01, 0x37, 0x5a,
+       0xe2, 0x6f, 0x04, 0x4b, 0xea, 0xda, 0x4c, 0x43, 0xf7, 0x7d, 0xad, 0x18,
+       0xbf, 0xec, 0xe3, 0x75, 0xdc, 0x27, 0x29, 0x69, 0xe8, 0xc9, 0xd8, 0xb4,
+       0x46, 0xd9, 0xd8, 0x26, 0x21, 0xd7, 0xd9, 0x58, 0xd5, 0x06, 0x8c, 0x4e,
+       0xd4, 0xdb, 0x00, 0xfe, 0x8e, 0x6d, 0x80, 0xa3, 0xfb, 0x63, 0xd3, 0x6c,
+       0x0b, 0x1c, 0xdd, 0x3f, 0x36, 0xc1, 0x36, 0x41, 0xcc, 0x09, 0xfd, 0x67,
+       0x3b, 0xe0, 0xda, 0x00, 0xfe, 0x86, 0x6d, 0x80, 0x0f, 0xf2, 0xcd, 0xf3,
+       0xb9, 0x6b, 0x8f, 0xd7, 0xcd, 0x3b, 0xce, 0xb6, 0x45, 0xd9, 0xd9, 0xcd,
+       0x30, 0xc7, 0xb1, 0x76, 0x80, 0x0a, 0xd3, 0xcc, 0xc3, 0x48, 0xe8, 0x08,
+       0x1d, 0x17, 0x36, 0xef, 0xf4, 0x04, 0x25, 0x0e, 0x9e, 0x18, 0xa0, 0x34,
+       0x6c, 0xc0, 0xdc, 0xc4, 0xb5, 0x32, 0xf8, 0x78, 0x47, 0x13, 0x59, 0xb0,
+       0x75, 0xf0, 0x93, 0xfd, 0x7e, 0xf2, 0xc5, 0xe3, 0x90, 0xb7, 0x98, 0xf0,
+       0x5d, 0xd5, 0x9f, 0xa6, 0xed, 0xaa, 0x69, 0x37, 0xc1, 0x3f, 0x62, 0xde,
+       0xfe, 0x98, 0x90, 0x4d, 0xef, 0x2f, 0x09, 0x1b, 0x94, 0x8c, 0x7d, 0x08,
+       0xf9, 0x75, 0x69, 0xe4, 0xea, 0x1f, 0xdb, 0xfa, 0x2b, 0x1e, 0x1f, 0xb2,
+       0x05, 0x76, 0xdf, 0x84, 0x3c, 0xb9, 0x76, 0x9f, 0xed, 0x71, 0x88, 0x6d,
+       0x26, 0xf4, 0x8d, 0x6d, 0x70, 0x80, 0xd4, 0x19, 0x4d, 0xda, 0x69, 0x5d,
+       0xda, 0xe9, 0x00, 0x6c, 0x34, 0xb7, 0x0d, 0xd9, 0x36, 0x45, 0x1b, 0xf6,
+       0x1a, 0xf6, 0x70, 0x77, 0x3a, 0x35, 0xc1, 0xfe, 0x10, 0xbe, 0x7b, 0x86,
+       0x75, 0xf8, 0xdb, 0x43, 0x23, 0xd3, 0xc2, 0x07, 0xb0, 0xff, 0x80, 0x65,
+       0x66, 0x1b, 0xce, 0xb6, 0x1c, 0xfb, 0x2e, 0x62, 0xdd, 0x8a, 0xad, 0x64,
+       0x39, 0xf1, 0xe2, 0xc5, 0x38, 0xad, 0x21, 0xf5, 0xa4, 0x43, 0x6b, 0x35,
+       0xfe, 0xa8, 0x46, 0x2d, 0x4c, 0x63, 0xc6, 0x7f, 0x2b, 0x70, 0xe6, 0x7d,
+       0xfd, 0x4f, 0xe0, 0xcc, 0xeb, 0xd6, 0xe3, 0x4d, 0x7a, 0x6b, 0xfc, 0xac,
+       0xfe, 0xf0, 0x33, 0xa4, 0x37, 0xc7, 0xcf, 0xd2, 0xbf, 0x58, 0x74, 0x9f,
+       0x0e, 0x3f, 0xdb, 0xad, 0xc0, 0xcf, 0x16, 0xa1, 0xef, 0x53, 0x3a, 0x1d,
+       0x3c, 0x15, 0xc9, 0xfc, 0x2b, 0x45, 0x61, 0x3f, 0x76, 0xd0, 0xc8, 0x94,
+       0x42, 0x7a, 0x17, 0xb5, 0xc3, 0x7f, 0xf4, 0x37, 0x61, 0xfe, 0x5d, 0x44,
+       0x9b, 0x1d, 0xbf, 0xd9, 0x15, 0x1e, 0x05, 0xff, 0xd3, 0x2f, 0x7e, 0x05,
+       0xdf, 0x3c, 0x4d, 0x07, 0xa7, 0x0e, 0x2b, 0x39, 0xfb, 0x08, 0xe0, 0x97,
+       0x83, 0xd5, 0x01, 0x9b, 0x07, 0xec, 0x97, 0x31, 0xef, 0xd3, 0xa4, 0xdf,
+       0x1e, 0x19, 0x48, 0x28, 0xc0, 0xe3, 0x45, 0x01, 0x2f, 0x7d, 0x71, 0x97,
+       0xb1, 0x53, 0xf0, 0x3f, 0x40, 0xef, 0x15, 0x2f, 0x80, 0xbe, 0xbd, 0xf0,
+       0x39, 0x91, 0x67, 0x61, 0x93, 0xe1, 0x8f, 0x22, 0x57, 0x31, 0x2d, 0x7c,
+       0x11, 0x29, 0x0f, 0x76, 0xa7, 0x41, 0xef, 0x38, 0xfc, 0xd3, 0x00, 0xfc,
+       0x53, 0x0c, 0xbe, 0xa9, 0x07, 0x7e, 0xc9, 0x82, 0x5f, 0x0a, 0x83, 0x1f,
+       0x06, 0xcd, 0xc2, 0x47, 0xcd, 0x42, 0xfe, 0xe7, 0x66, 0x48, 0x19, 0x04,
+       0xad, 0xcf, 0xc1, 0x3f, 0x26, 0x63, 0x77, 0x42, 0xcf, 0x22, 0x17, 0x66,
+       0xd5, 0x41, 0xca, 0xc1, 0x9f, 0x77, 0x6e, 0x8b, 0x62, 0xbd, 0x26, 0x4a,
+       0x84, 0x5c, 0x1d, 0xe5, 0xdf, 0x7e, 0x85, 0xac, 0x7f, 0x06, 0xef, 0x22,
+       0x61, 0xa2, 0x3d, 0x94, 0xb5, 0xa3, 0x46, 0xa7, 0xda, 0x03, 0x18, 0x6e,
+       0x87, 0x95, 0x03, 0x53, 0x11, 0x05, 0xfb, 0x03, 0xcd, 0x27, 0x60, 0xeb,
+       0xcb, 0x34, 0x1e, 0x63, 0x3d, 0x29, 0xd3, 0xf3, 0xb1, 0xc8, 0x40, 0x9e,
+       0x5a, 0xe9, 0x98, 0x39, 0x21, 0x7c, 0xbc, 0x16, 0x3f, 0x21, 0x74, 0x2c,
+       0x67, 0xe1, 0x59, 0xec, 0x54, 0xb2, 0x53, 0xbc, 0x7e, 0x14, 0x5a, 0xee,
+       0xc7, 0x93, 0xe7, 0x07, 0xdd, 0xfa, 0x49, 0x39, 0xd8, 0x9d, 0x87, 0x77,
+       0x88, 0x18, 0x8b, 0x58, 0x39, 0x35, 0x11, 0x0d, 0x45, 0x55, 0x8d, 0x86,
+       0x35, 0x85, 0x46, 0x61, 0x6f, 0xd2, 0xb1, 0xff, 0x2c, 0x1f, 0x33, 0x79,
+       0xbc, 0x99, 0xbe, 0x2a, 0xfc, 0x0d, 0xd6, 0x2e, 0x4c, 0x63, 0x5d, 0x3f,
+       0xf8, 0xcb, 0xeb, 0xf2, 0x3c, 0x68, 0xc3, 0xf6, 0x6b, 0x56, 0xe4, 0xd9,
+       0x3c, 0xed, 0x00, 0x6d, 0xd9, 0x66, 0xc1, 0x3e, 0x0c, 0x60, 0xed, 0x5e,
+       0xd8, 0x4f, 0x3c, 0x93, 0xbd, 0x1c, 0x07, 0x05, 0x68, 0xd8, 0x64, 0x79,
+       0xd4, 0xe5, 0x98, 0xe9, 0x19, 0xf3, 0xcb, 0xb1, 0x20, 0xfe, 0xe0, 0x7f,
+       0x4d, 0x96, 0x19, 0x6e, 0x73, 0x4c, 0xc6, 0x34, 0x09, 0xd3, 0xdc, 0x64,
+       0x02, 0x34, 0x8b, 0x9c, 0x4d, 0x10, 0xd3, 0x0c, 0x46, 0x7b, 0x7f, 0x82,
+       0xbe, 0x64, 0xaf, 0xf7, 0x3b, 0xb6, 0xb0, 0x55, 0x49, 0xc1, 0x17, 0xa8,
+       0x56, 0x0b, 0x7c, 0x45, 0x98, 0x5e, 0x15, 0xb0, 0x64, 0xa8, 0xf1, 0x68,
+       0xe8, 0x4b, 0x74, 0xab, 0xb0, 0x11, 0x09, 0xc3, 0x4b, 0xe3, 0xff, 0x52,
+       0xc9, 0x72, 0xbf, 0x69, 0xa5, 0xec, 0x20, 0xf3, 0x89, 0xd7, 0x33, 0x68,
+       0xae, 0xe4, 0xbc, 0xfb, 0x10, 0xa3, 0x16, 0x60, 0x6b, 0xce, 0x4f, 0xaa,
+       0xf4, 0xf8, 0x1d, 0xf0, 0x65, 0xb1, 0x6d, 0x58, 0xcb, 0xc4, 0x78, 0x1e,
+       0x6d, 0x15, 0x6d, 0xe8, 0x99, 0x11, 0x02, 0x8f, 0xb9, 0x9f, 0xe1, 0x4c,
+       0xfc, 0xbd, 0xcf, 0xb1, 0x75, 0x3e, 0xab, 0xde, 0x4a, 0x14, 0x64, 0x7a,
+       0xc5, 0x40, 0x2b, 0xcb, 0x50, 0xd5, 0x6d, 0xc2, 0x5f, 0x3b, 0xb6, 0xc4,
+       0x82, 0x2e, 0xc2, 0xe6, 0xf6, 0x79, 0x75, 0x91, 0xe3, 0x09, 0x57, 0x17,
+       0x23, 0xa1, 0x84, 0x0a, 0x5b, 0xdc, 0xa7, 0xd1, 0x09, 0xd1, 0x56, 0x28,
+       0x31, 0x18, 0x09, 0x2d, 0xa8, 0x1c, 0x4b, 0x33, 0x6c, 0x18, 0xf1, 0x4a,
+       0x40, 0xc2, 0x22, 0x9e, 0xb3, 0xdd, 0x98, 0x30, 0x84, 0x7e, 0x53, 0xf4,
+       0x1f, 0xab, 0xe8, 0xa8, 0x13, 0xff, 0xa9, 0x88, 0x11, 0x0b, 0x88, 0x11,
+       0x53, 0x42, 0x47, 0x8d, 0x04, 0x72, 0x04, 0xd0, 0xdc, 0xd1, 0xcf, 0x42,
+       0x91, 0x71, 0xc9, 0xb1, 0x5c, 0x0e, 0x00, 0x99, 0x13, 0x8e, 0x7d, 0xa4,
+       0x3c, 0xc7, 0x91, 0xa3, 0xea, 0x53, 0x34, 0x5c, 0x60, 0x3f, 0x8e, 0x3f,
+       0x9b, 0x6d, 0x2d, 0xec, 0xa3, 0xf0, 0xc5, 0x51, 0xf0, 0x39, 0x0f, 0x1a,
+       0xac, 0x97, 0x74, 0xdd, 0x4f, 0x07, 0xec, 0x3d, 0xa0, 0x79, 0x9c, 0x46,
+       0x4e, 0x8d, 0xb0, 0xcc, 0xf6, 0x14, 0x28, 0xd2, 0x73, 0x8c, 0xb6, 0x1b,
+       0x73, 0x2c, 0xdf, 0x83, 0xe5, 0x1d, 0xe0, 0x85, 0xd0, 0x51, 0xc8, 0x20,
+       0x65, 0x0b, 0x23, 0xf4, 0x58, 0x89, 0xfb, 0xf2, 0xa0, 0x1d, 0xe2, 0xda,
+       0xfe, 0xfd, 0x52, 0xce, 0x31, 0x9f, 0xe6, 0xce, 0x37, 0x22, 0xe7, 0x63,
+       0x38, 0x86, 0xe1, 0x6f, 0xaa, 0xf3, 0xee, 0x14, 0x3c, 0x8d, 0x18, 0x5d,
+       0x6a, 0x79, 0x87, 0x1f, 0xe3, 0xcf, 0xf7, 0xf3, 0x3b, 0xe6, 0x81, 0xef,
+       0x6f, 0xb6, 0xf6, 0x00, 0x76, 0x10, 0x73, 0xfa, 0xa9, 0xb3, 0xdd, 0xc5,
+       0x37, 0x81, 0xb5, 0xd9, 0xcf, 0x31, 0x9f, 0x1f, 0xa1, 0xec, 0xa9, 0x7c,
+       0x8f, 0x0a, 0x19, 0x9b, 0xcd, 0x28, 0xe4, 0xb7, 0x1e, 0xa6, 0xdc, 0xa9,
+       0xa3, 0x6c, 0x37, 0x40, 0xab, 0x3d, 0xb4, 0x6b, 0x22, 0xd2, 0x73, 0x80,
+       0x34, 0xb1, 0xce, 0x5b, 0x24, 0xe8, 0x1f, 0x9b, 0x15, 0xbe, 0x20, 0x43,
+       0xe9, 0x89, 0xed, 0xa1, 0x4b, 0xe8, 0x1b, 0x1e, 0x8c, 0x84, 0x17, 0xe8,
+       0x09, 0xd0, 0xe5, 0x23, 0xf8, 0x22, 0xab, 0x67, 0x0c, 0x3a, 0x84, 0x9c,
+       0x0a, 0xeb, 0x8f, 0x4a, 0xda, 0xe0, 0xbb, 0xcc, 0x51, 0xd0, 0x8f, 0xf2,
+       0x0e, 0x4d, 0x99, 0x9e, 0x4c, 0xcb, 0xaf, 0xc0, 0xf6, 0x1c, 0x11, 0xb1,
+       0x4b, 0x56, 0xd0, 0xee, 0xd2, 0x06, 0x47, 0x0e, 0x60, 0x8b, 0x30, 0xef,
+       0xe5, 0x41, 0x85, 0xb6, 0x20, 0x4e, 0x3f, 0x24, 0x78, 0xeb, 0xa3, 0x7d,
+       0x66, 0xd4, 0xd8, 0x47, 0xf3, 0x7e, 0x27, 0x56, 0xc0, 0x3c, 0x3d, 0xf7,
+       0x60, 0x0f, 0x90, 0x53, 0xfb, 0xeb, 0xeb, 0xa8, 0x2d, 0x12, 0x4e, 0xa8,
+       0x09, 0xfa, 0x93, 0xd2, 0xdd, 0xe4, 0xe8, 0x77, 0x2b, 0xdb, 0x7e, 0xf0,
+       0xb0, 0xd3, 0x69, 0x5b, 0x78, 0x16, 0x3a, 0xb1, 0x1e, 0xe3, 0xfe, 0xac,
+       0xc0, 0x7d, 0x84, 0xba, 0xa1, 0x6b, 0x22, 0x8f, 0x39, 0x51, 0x8b, 0x17,
+       0xf3, 0xbc, 0x9e, 0xcf, 0x5f, 0xc6, 0x3c, 0xdc, 0xcf, 0x70, 0x78, 0x2f,
+       0x3c, 0x41, 0x23, 0x90, 0xc7, 0x5c, 0x7f, 0x57, 0x68, 0x0c, 0xdf, 0xa4,
+       0x4a, 0x4d, 0x74, 0x54, 0xe3, 0xf1, 0x48, 0x38, 0xaf, 0x1e, 0x42, 0xdc,
+       0xf3, 0xb8, 0xea, 0xb7, 0x7e, 0xe6, 0x67, 0xbf, 0xe3, 0xb7, 0xae, 0x29,
+       0xd5, 0xb9, 0x10, 0x87, 0x8a, 0xdc, 0x60, 0x41, 0x19, 0x2c, 0x5d, 0x52,
+       0x92, 0x85, 0x6b, 0x4a, 0xaa, 0xc4, 0x30, 0x8e, 0xce, 0x67, 0xcf, 0x74,
+       0x82, 0x4e, 0x1f, 0x89, 0xef, 0xe6, 0x7a, 0x8f, 0x50, 0xea, 0xd4, 0xad,
+       0x94, 0x9e, 0xe6, 0xbc, 0x34, 0x02, 0x7c, 0x3f, 0x2a, 0xe7, 0x62, 0x41,
+       0xca, 0x9d, 0xe1, 0x31, 0xb6, 0x5f, 0xd6, 0xd5, 0x45, 0x1f, 0xef, 0x9f,
+       0xf9, 0x6f, 0x52, 0xc1, 0x7e, 0x53, 0xd2, 0x8f, 0xdf, 0x7d, 0x9c, 0x93,
+       0xe1, 0xf7, 0x6f, 0x86, 0xd3, 0xb7, 0x95, 0x16, 0x36, 0xdc, 0xc8, 0x3e,
+       0x57, 0xb3, 0xc7, 0x47, 0x7d, 0x7e, 0x6b, 0x7b, 0x13, 0xb5, 0x84, 0x80,
+       0xc3, 0x4a, 0x7b, 0x64, 0x98, 0x5f, 0x87, 0x1c, 0xb0, 0x4d, 0xd9, 0x0d,
+       0x7e, 0x5a, 0x6c, 0xc3, 0x60, 0x93, 0x76, 0x53, 0xae, 0xc4, 0xb2, 0x1d,
+       0x35, 0x32, 0x90, 0xb1, 0x34, 0x75, 0xb1, 0x1e, 0xb9, 0xba, 0x07, 0xdb,
+       0x9d, 0x87, 0xed, 0x46, 0x3c, 0x64, 0x53, 0xbe, 0x29, 0xce, 0x36, 0xbc,
+       0x0b, 0xb2, 0x85, 0xbe, 0x62, 0x55, 0x17, 0x77, 0x2d, 0xc1, 0x5d, 0x5b,
+       0xc2, 0xa3, 0x02, 0xd5, 0xe2, 0x3f, 0x4b, 0x8c, 0xff, 0x5f, 0x00, 0xff,
+       0xcf, 0x01, 0x7f, 0xc6, 0xa9, 0x31, 0xfe, 0x3b, 0x2b, 0xf8, 0x33, 0x0c,
+       0xfc, 0x1c, 0x64, 0xf1, 0x0d, 0xe8, 0xe2, 0x6b, 0x36, 0x7c, 0x9d, 0x0d,
+       0xff, 0x67, 0xc3, 0xdf, 0xd9, 0xf0, 0x8b, 0x36, 0x7c, 0x1e, 0xf6, 0x74,
+       0x0e, 0x36, 0xe9, 0xac, 0x9d, 0x34, 0x58, 0x9f, 0x92, 0x31, 0xf6, 0x9d,
+       0xbb, 0x65, 0xde, 0x1d, 0x92, 0x71, 0xf7, 0xa7, 0x64, 0x2c, 0x7b, 0x00,
+       0xb1, 0xec, 0x66, 0x1a, 0xed, 0xe1, 0x9c, 0xa4, 0x05, 0xcf, 0x75, 0x78,
+       0x22, 0x6e, 0xed, 0x49, 0x48, 0xbd, 0xfc, 0x0c, 0x62, 0x5c, 0xd8, 0xff,
+       0x1e, 0xe4, 0x37, 0x19, 0xc4, 0x6a, 0x56, 0x1f, 0xc7, 0xe5, 0xb0, 0x65,
+       0xef, 0x37, 0x39, 0x76, 0xfe, 0x2e, 0x19, 0x03, 0xbb, 0xed, 0x56, 0xc0,
+       0xa4, 0xd1, 0xd7, 0x8a, 0x6f, 0x7e, 0x07, 0xb2, 0xdf, 0x86, 0xf6, 0xce,
+       0x3a, 0x18, 0xe4, 0xb3, 0x56, 0x16, 0x7d, 0x11, 0xc0, 0xb4, 0x61, 0x9d,
+       0x0e, 0xb4, 0xf7, 0xa0, 0x7d, 0x8b, 0xb3, 0x8e, 0xf1, 0x2b, 0x68, 0xa7,
+       0xea, 0xbe, 0xd9, 0x8a, 0xbe, 0x4c, 0x5d, 0xdf, 0x9b, 0xe8, 0x4b, 0xa2,
+       0x6f, 0x51, 0x7e, 0x97, 0x47, 0x3b, 0x52, 0x07, 0xb3, 0x88, 0x3e, 0xc6,
+       0xf1, 0x5b, 0x78, 0xde, 0x47, 0xa3, 0x19, 0x8e, 0x03, 0xdc, 0xb1, 0xdc,
+       0x7a, 0x6a, 0xe3, 0xdc, 0xf7, 0x43, 0x21, 0x3b, 0xf3, 0xd2, 0x46, 0xa7,
+       0x27, 0xd8, 0x4f, 0x8c, 0x20, 0xee, 0xe1, 0x71, 0xe1, 0x9c, 0x3c, 0xfd,
+       0x1f, 0x00, 0xf6, 0x61, 0x8c, 0x21, 0x56, 0xb7, 0xcb, 0x4d, 0x8d, 0xc7,
+       0x1f, 0xc5, 0xf8, 0x5f, 0xca, 0x6f, 0x2b, 0x73, 0x03, 0xfe, 0x1b, 0x75,
+       0x7d, 0x6a, 0xb0, 0xb6, 0xbd, 0xd6, 0xf3, 0xbe, 0x4d, 0x5f, 0xfa, 0xfd,
+       0x48, 0x1d, 0xfc, 0xef, 0x6e, 0xa8, 0x6d, 0x3f, 0xc5, 0xdf, 0x20, 0x87,
+       0x70, 0xdb, 0x09, 0xc8, 0x1d, 0xdb, 0xa4, 0xfa, 0x79, 0x3e, 0x6b, 0xd4,
+       0xf6, 0x6d, 0x32, 0x6b, 0xdb, 0x1c, 0x27, 0x31, 0x5c, 0x08, 0xf2, 0xde,
+       0xa1, 0xec, 0xb2, 0x7f, 0x13, 0xe3, 0x61, 0xe5, 0x5e, 0xdb, 0x8b, 0x67,
+       0x48, 0xe6, 0x46, 0xe1, 0x4a, 0xcc, 0x3b, 0x5f, 0x0a, 0x40, 0xae, 0x3e,
+       0x0f, 0x9e, 0x73, 0xdc, 0x53, 0xd5, 0xf1, 0xf7, 0x68, 0x39, 0x1d, 0x67,
+       0x1f, 0xc0, 0x31, 0xfe, 0x36, 0x11, 0x1f, 0xfb, 0xe2, 0x4f, 0x70, 0x0c,
+       0xf6, 0xb4, 0xe3, 0x5b, 0x2c, 0xf8, 0x43, 0xb4, 0x4b, 0x7e, 0xc7, 0x6e,
+       0x22, 0x9f, 0xc8, 0x16, 0xd8, 0x9f, 0xb1, 0x0f, 0x89, 0xc0, 0x4e, 0xb3,
+       0x1f, 0xfd, 0x24, 0x7d, 0xc6, 0x5d, 0xcd, 0x6c, 0xfb, 0x34, 0xeb, 0x05,
+       0xc4, 0x0b, 0x1c, 0xe7, 0xb1, 0xed, 0xc6, 0x7b, 0xd1, 0x8d, 0x57, 0xee,
+       0xd7, 0xc8, 0xaa, 0xfa, 0x11, 0x67, 0x8f, 0x5b, 0x59, 0x37, 0x56, 0xb1,
+       0xef, 0xc6, 0xb6, 0xed, 0xc7, 0x75, 0xb6, 0xe1, 0xb2, 0xb0, 0x0d, 0x0f,
+       0x6a, 0x7e, 0xeb, 0xf7, 0x9b, 0x1d, 0x79, 0x6d, 0x6c, 0x1b, 0xee, 0xad,
+       0xd8, 0x06, 0x57, 0x5e, 0xbd, 0x79, 0xeb, 0x0f, 0xc0, 0x1b, 0x0b, 0xbc,
+       0xa9, 0xaf, 0xd5, 0x70, 0x8e, 0xe2, 0x87, 0x1f, 0xe2, 0x18, 0x91, 0x73,
+       0xd9, 0x18, 0xe5, 0x62, 0x45, 0xc4, 0x6a, 0x91, 0xd9, 0xd9, 0x4a, 0x8e,
+       0xf5, 0x35, 0x69, 0xbb, 0x6b, 0xe2, 0x22, 0x7a, 0xbc, 0x78, 0x09, 0xf8,
+       0x73, 0xbc, 0xa5, 0x49, 0x1b, 0xc1, 0xfd, 0xe3, 0x12, 0x47, 0x7e, 0xe7,
+       0x3a, 0x1e, 0x7c, 0x69, 0xf1, 0x47, 0xe0, 0x15, 0xc7, 0x7d, 0x51, 0x27,
+       0xde, 0xab, 0x89, 0xa9, 0xd7, 0xf8, 0xc9, 0xe2, 0x78, 0x89, 0x61, 0x74,
+       0x19, 0x2f, 0x05, 0x64, 0x5e, 0x63, 0xc8, 0x3c, 0x87, 0x63, 0x6d, 0xae,
+       0xb1, 0xd6, 0xc7, 0x50, 0x0b, 0x43, 0xc1, 0x6d, 0xcc, 0x13, 0x8e, 0xa1,
+       0xda, 0x28, 0x39, 0xe3, 0xc4, 0x50, 0x4e, 0x9d, 0xcd, 0xcd, 0x71, 0x5c,
+       0x5c, 0xd9, 0x0f, 0xef, 0xc0, 0x3e, 0x45, 0x9e, 0x14, 0x74, 0xea, 0x7f,
+       0x1a, 0xec, 0xf6, 0x51, 0xf4, 0x8f, 0xba, 0xfd, 0x9e, 0x5c, 0xc3, 0xc5,
+       0x85, 0x7d, 0xbd, 0x1b, 0xd3, 0xed, 0x96, 0x31, 0x1d, 0x62, 0x18, 0xdb,
+       0xc9, 0xbb, 0xf6, 0x16, 0x33, 0xe8, 0xe3, 0x75, 0x11, 0x1b, 0x12, 0xc7,
+       0x49, 0x90, 0xaf, 0xfd, 0x91, 0x50, 0x58, 0xad, 0xc7, 0xab, 0x75, 0xa1,
+       0x16, 0xaf, 0x41, 0xf1, 0xdd, 0xf8, 0x92, 0xef, 0x48, 0xc4, 0x92, 0xe3,
+       0xf6, 0x10, 0xe8, 0xc5, 0xf8, 0xb9, 0xba, 0xe1, 0xc6, 0xc9, 0x8c, 0xd3,
+       0x3f, 0x82, 0xc6, 0xbb, 0x15, 0xfe, 0x7e, 0xcc, 0xde, 0x2f, 0xe8, 0x96,
+       0x15, 0xb8, 0x0e, 0x7b, 0x70, 0x1d, 0x91, 0xb8, 0xb2, 0x2e, 0xb0, 0x7e,
+       0x78, 0x6b, 0x9a, 0xa6, 0xd8, 0x1b, 0x70, 0x0e, 0xf3, 0xb9, 0xb9, 0x6a,
+       0x2d, 0x0c, 0xf9, 0xb6, 0xc1, 0x1f, 0x02, 0xd7, 0xac, 0x88, 0x43, 0x03,
+       0x0b, 0xf5, 0x34, 0x1c, 0xc7, 0x5a, 0x88, 0xdb, 0x81, 0x8f, 0xcb, 0xf3,
+       0x26, 0x89, 0xcf, 0x37, 0xc5, 0xdc, 0x63, 0xa2, 0x06, 0xea, 0xd3, 0x39,
+       0x77, 0xc9, 0x0a, 0xde, 0x69, 0x92, 0x77, 0x8f, 0x56, 0xf0, 0x73, 0x78,
+       0x1c, 0x90, 0x74, 0xe5, 0xdc, 0x95, 0x75, 0x5a, 0xf0, 0xa7, 0x9d, 0x73,
+       0xd3, 0x41, 0x6a, 0x14, 0x23, 0x2f, 0x0c, 0xa9, 0xdb, 0x1c, 0x3a, 0x3a,
+       0x31, 0xf2, 0xda, 0xba, 0x18, 0xf9, 0xb6, 0x20, 0xc7, 0x5a, 0xc3, 0x50,
+       0x82, 0x79, 0xf8, 0xba, 0x97, 0x6d, 0xc8, 0x36, 0x70, 0x3d, 0x5f, 0x53,
+       0xbb, 0xec, 0x59, 0xa6, 0xd6, 0x1c, 0x20, 0xdf, 0x0c, 0xfb, 0x0e, 0x0b,
+       0x79, 0x06, 0x91, 0x36, 0xc9, 0x3a, 0xcb, 0xbe, 0xbd, 0x1a, 0x67, 0xcf,
+       0x51, 0xa3, 0x18, 0xfb, 0x46, 0xfd, 0xfa, 0x79, 0xbf, 0xdf, 0x3a, 0xac,
+       0x3b, 0x36, 0x73, 0x25, 0xbf, 0xee, 0xc2, 0xed, 0x41, 0x9c, 0xad, 0x50,
+       0x93, 0x55, 0xc0, 0xfe, 0xde, 0xf0, 0x37, 0x5b, 0xae, 0x2e, 0x06, 0x68,
+       0xfd, 0xcc, 0x2d, 0x42, 0x1f, 0x8d, 0xc9, 0xaa, 0x3e, 0x8e, 0x82, 0x37,
+       0x19, 0xa7, 0x06, 0x60, 0xae, 0xa7, 0xeb, 0xd7, 0x0b, 0xc6, 0xed, 0x37,
+       0xfd, 0xaa, 0xe5, 0xca, 0xc0, 0xf5, 0xf2, 0x91, 0x4f, 0xd5, 0xd1, 0xba,
+       0x51, 0x4d, 0xf8, 0x2c, 0xe8, 0x1a, 0x47, 0xde, 0x1d, 0x79, 0x81, 0x10,
+       0x3b, 0x39, 0x79, 0x78, 0x1a, 0xb9, 0x77, 0xe4, 0x02, 0xe7, 0xe3, 0x6e,
+       0x7e, 0xfe, 0x6a, 0x29, 0x72, 0x36, 0x8f, 0x9c, 0x79, 0x1e, 0x39, 0xf9,
+       0xcb, 0xc8, 0xc9, 0xcf, 0x97, 0x7a, 0x41, 0xff, 0x1e, 0x99, 0x8f, 0xb3,
+       0x8e, 0x99, 0x74, 0x11, 0xb9, 0xd3, 0x77, 0x67, 0xd8, 0x46, 0x74, 0xd1,
+       0x3d, 0xc8, 0x35, 0xbe, 0x3f, 0xa9, 0x68, 0x9d, 0x7d, 0x01, 0x5f, 0xc2,
+       0xb8, 0x91, 0x38, 0x71, 0x29, 0x4f, 0x1a, 0xc7, 0x8a, 0x23, 0x4d, 0x7e,
+       0x6b, 0xae, 0x95, 0x5a, 0xf6, 0x2c, 0xcb, 0x93, 0x6a, 0xac, 0xe8, 0xc2,
+       0x19, 0xd4, 0xd9, 0xf7, 0x87, 0x9c, 0xdb, 0xc4, 0x48, 0xe4, 0xd3, 0xeb,
+       0xe8, 0xed, 0x93, 0x65, 0xda, 0x19, 0xbb, 0x56, 0xbe, 0x68, 0xad, 0xa3,
+       0x6c, 0xef, 0x43, 0x32, 0x97, 0x5c, 0x78, 0x28, 0x69, 0xe5, 0x43, 0x3e,
+       0xf7, 0x7c, 0x62, 0x42, 0x47, 0x84, 0xc8, 0xbf, 0x20, 0xcd, 0x0d, 0x20,
+       0x71, 0x6e, 0xd9, 0xfe, 0x02, 0x1f, 0x10, 0xb1, 0x6d, 0x9c, 0x33, 0x03,
+       0xa2, 0xd6, 0xb6, 0xd1, 0xe2, 0x7e, 0x03, 0xfc, 0xbe, 0x8f, 0xe6, 0x90,
+       0x43, 0x14, 0x44, 0x1e, 0xde, 0x0e, 0x78, 0x37, 0x0f, 0xbf, 0x1f, 0xb9,
+       0x01, 0xd3, 0xd8, 0x04, 0xfc, 0x6f, 0x03, 0xc6, 0x6b, 0x43, 0x9f, 0x6b,
+       0x22, 0xf1, 0x3d, 0x8f, 0xb7, 0x13, 0xd7, 0x65, 0xab, 0xf3, 0xf2, 0x9c,
+       0x3c, 0xf6, 0x61, 0xf9, 0xf6, 0xbe, 0x3e, 0xcf, 0xdc, 0x6d, 0x9e, 0xb9,
+       0xef, 0xf0, 0xcc, 0xed, 0xc3, 0xb7, 0x2e, 0x3e, 0x41, 0x7c, 0xeb, 0xae,
+       0xf1, 0xb7, 0x9e, 0x35, 0x5c, 0xdc, 0xdb, 0x3d, 0xb8, 0xbf, 0x8f, 0xf9,
+       0xb9, 0xcf, 0xf4, 0xf4, 0xf1, 0x9a, 0x1b, 0x68, 0x6e, 0xb0, 0x8d, 0x16,
+       0x4f, 0x72, 0x5f, 0xd0, 0x83, 0x0b, 0xe3, 0x17, 0x90, 0x63, 0x6d, 0x74,
+       0xf1, 0x64, 0x8b, 0xc0, 0x9b, 0xfd, 0xf9, 0xc6, 0xca, 0x9a, 0x57, 0xb0,
+       0xa6, 0x3b, 0x97, 0x89, 0x6f, 0x19, 0x96, 0xf1, 0xe3, 0x31, 0xee, 0xe3,
+       0xb1, 0x37, 0xcb, 0x5f, 0x33, 0x82, 0xce, 0x9e, 0x0d, 0xc6, 0xcd, 0xfd,
+       0x56, 0x6b, 0x26, 0x8b, 0xdb, 0x9d, 0x34, 0x1b, 0xd4, 0xc0, 0x37, 0x55,
+       0xfa, 0x28, 0xae, 0x23, 0xa8, 0x4a, 0xb4, 0x8f, 0xf9, 0xbc, 0x4e, 0xd6,
+       0xaf, 0x5b, 0x30, 0x6f, 0xd8, 0xcd, 0xd1, 0x88, 0xe5, 0x38, 0x27, 0xec,
+       0xbe, 0x26, 0xc7, 0xd9, 0xee, 0xb3, 0xdf, 0xc7, 0x53, 0xc8, 0xaa, 0x3c,
+       0xaf, 0x29, 0xed, 0xa0, 0x83, 0x50, 0xcf, 0x8b, 0xb2, 0x9e, 0xb2, 0xe8,
+       0xad, 0x99, 0x18, 0x4e, 0x1c, 0xe3, 0x9c, 0xed, 0xac, 0x85, 0xfe, 0xe0,
+       0xbd, 0x98, 0x00, 0x1e, 0x61, 0x8a, 0xe2, 0xaf, 0x50, 0xca, 0xe3, 0x69,
+       0xe1, 0xa9, 0xe0, 0xc9, 0xf5, 0x0c, 0x1d, 0x4f, 0xe8, 0x18, 0xec, 0x53,
+       0xb4, 0xef, 0x92, 0x93, 0x3f, 0x41, 0x37, 0xde, 0x9e, 0x74, 0xea, 0x51,
+       0x8b, 0xd6, 0x72, 0xf5, 0xa8, 0x3f, 0x67, 0x9e, 0x9c, 0x70, 0xeb, 0x51,
+       0x8b, 0x24, 0xea, 0x51, 0x27, 0x56, 0xa8, 0x47, 0x25, 0x56, 0x5f, 0x8f,
+       0xe2, 0xf9, 0x35, 0xda, 0xd7, 0x4f, 0xca, 0x17, 0x64, 0x3d, 0xea, 0x3d,
+       0x72, 0xea, 0x51, 0x17, 0xa9, 0x71, 0x3d, 0xea, 0x78, 0x5d, 0x3d, 0x2a,
+       0x28, 0xea, 0x51, 0x3c, 0x8f, 0x53, 0x8f, 0x12, 0xed, 0xbe, 0x88, 0xa7,
+       0xee, 0x42, 0xf4, 0xee, 0x64, 0x07, 0x68, 0x66, 0xd0, 0xf7, 0x1a, 0xda,
+       0x34, 0x45, 0xc8, 0xdb, 0x4a, 0x35, 0xd0, 0x07, 0x6e, 0xb8, 0xbe, 0xa2,
+       0xd0, 0x06, 0xcc, 0x9b, 0xec, 0x7b, 0xd8, 0x53, 0x63, 0x61, 0x9a, 0xff,
+       0x62, 0xea, 0x2c, 0x07, 0x45, 0x9d, 0xe5, 0x87, 0x6b, 0xbc, 0x75, 0x96,
+       0x45, 0xba, 0x7e, 0x9d, 0xe5, 0x60, 0x83, 0x3a, 0xcb, 0x5b, 0x54, 0xad,
+       0xb3, 0xbc, 0x45, 0xd5, 0x3a, 0xcb, 0xc1, 0x12, 0xe7, 0xe2, 0x3e, 0x89,
+       0x5f, 0x06, 0xed, 0x41, 0xf1, 0xc7, 0xb5, 0x97, 0xc5, 0xca, 0x1e, 0x7e,
+       0xd9, 0x6a, 0x2f, 0x6c, 0x03, 0x22, 0x17, 0x2e, 0xd7, 0xd4, 0x5e, 0xb8,
+       0x0d, 0x9d, 0xb1, 0xd7, 0x08, 0x19, 0x99, 0x83, 0x7f, 0x5f, 0x9c, 0x0c,
+       0x61, 0xce, 0x0e, 0xf8, 0x8c, 0x0e, 0xe4, 0x06, 0x61, 0xb4, 0x15, 0xda,
+       0x64, 0x0d, 0xa1, 0x8f, 0xc7, 0xd9, 0x0e, 0x43, 0xb7, 0x6c, 0x77, 0x7f,
+       0x0f, 0x48, 0x1a, 0x44, 0x68, 0xb8, 0x9d, 0xf4, 0x20, 0xfb, 0x8e, 0xc9,
+       0x3d, 0x74, 0xc8, 0xde, 0x22, 0xf6, 0xbd, 0xc1, 0xaa, 0x95, 0xb9, 0xc1,
+       0x1b, 0x90, 0xb9, 0xcc, 0xaa, 0x65, 0x8e, 0xe5, 0xcd, 0x39, 0xf7, 0xdd,
+       0x60, 0xf1, 0xfa, 0x1d, 0x02, 0xa7, 0x77, 0x1b, 0xc8, 0xfb, 0x18, 0xec,
+       0x8e, 0x33, 0xbf, 0x2e, 0xd7, 0xab, 0x8f, 0x87, 0x9f, 0x6d, 0x66, 0xff,
+       0xbd, 0x72, 0x3d, 0xb1, 0xde, 0x7f, 0xaf, 0xe4, 0x47, 0x15, 0x61, 0x93,
+       0xb3, 0x25, 0xae, 0xed, 0x7b, 0xf9, 0x33, 0x8f, 0x9c, 0x00, 0x7d, 0x42,
+       0x0f, 0x98, 0xae, 0x41, 0xf0, 0x01, 0xeb, 0xd8, 0x4f, 0xc9, 0x5a, 0x16,
+       0x9e, 0x05, 0x97, 0x7f, 0xad, 0xb0, 0x99, 0xee, 0x18, 0xdb, 0x01, 0x0b,
+       0xfe, 0x8f, 0xeb, 0x28, 0x7c, 0x8e, 0xca, 0xfd, 0x2e, 0x5f, 0xbb, 0x2e,
+       0xbc, 0xa7, 0x72, 0xbb, 0x5c, 0xce, 0x8a, 0x7a, 0x2d, 0xa9, 0x9d, 0x7d,
+       0xd3, 0x2d, 0x6c, 0x6b, 0xb6, 0x58, 0xae, 0xcc, 0x26, 0xf0, 0xce, 0x7c,
+       0x7d, 0x17, 0x36, 0x9c, 0xcf, 0xaa, 0xbf, 0x23, 0x6a, 0x04, 0x73, 0x36,
+       0xdb, 0x6b, 0x8e, 0x41, 0x7f, 0x0b, 0xb2, 0xc4, 0xef, 0x51, 0x71, 0x2e,
+       0x21, 0x6a, 0xf8, 0x83, 0xdc, 0x76, 0xed, 0x4a, 0x94, 0xed, 0x30, 0xf6,
+       0x5c, 0xa5, 0x31, 0xe2, 0x23, 0xc8, 0x0c, 0xc7, 0xb1, 0x0c, 0xe7, 0xc6,
+       0x9e, 0x9a, 0xa7, 0x66, 0xab, 0xcb, 0xb8, 0x88, 0x75, 0x39, 0x00, 0x9a,
+       0xed, 0x10, 0x31, 0xea, 0xb8, 0x5d, 0xa6, 0xea, 0x19, 0x3f, 0xd3, 0xdc,
+       0x39, 0xe7, 0x3f, 0x66, 0x2f, 0x47, 0xfb, 0xcd, 0x37, 0x48, 0x7b, 0x47,
+       0x1f, 0x6b, 0xe9, 0xae, 0x23, 0x7e, 0x71, 0xe9, 0xee, 0xfa, 0xa8, 0x49,
+       0x49, 0x83, 0xa8, 0xac, 0x2b, 0x7e, 0x5a, 0x9e, 0x29, 0xfd, 0x5f, 0xd8,
+       0xaf, 0xe2, 0xd9, 0xaf, 0xab, 0xbb, 0xfb, 0xe4, 0x7e, 0xc3, 0x75, 0xba,
+       0x1b, 0x97, 0x75, 0xb9, 0x5f, 0x84, 0xee, 0xba, 0x7b, 0xe2, 0xb5, 0xb7,
+       0x5c, 0x67, 0xdd, 0x67, 0x48, 0x8d, 0xaf, 0x14, 0x7b, 0xff, 0xb4, 0xf9,
+       0xe3, 0xc5, 0xde, 0x1f, 0x87, 0x9e, 0x5e, 0xbd, 0x65, 0x1a, 0xb6, 0x89,
+       0xb8, 0xc2, 0xd1, 0x1f, 0xd8, 0xe3, 0x82, 0x9f, 0x16, 0x1e, 0xd2, 0xe9,
+       0x9f, 0xee, 0xe4, 0xfa, 0xac, 0x26, 0x73, 0x7c, 0x6e, 0x7f, 0xb1, 0x95,
+       0x63, 0xab, 0x4d, 0xd6, 0x77, 0x44, 0x6e, 0x95, 0x57, 0x4d, 0x8f, 0x1f,
+       0x31, 0x30, 0xce, 0x63, 0x61, 0xba, 0x1c, 0xbc, 0x91, 0xb8, 0xbc, 0xcb,
+       0x58, 0xf4, 0xad, 0x26, 0x2e, 0xbf, 0x55, 0xf7, 0x5b, 0x7f, 0xdd, 0x7a,
+       0xbd, 0x3a, 0x47, 0x35, 0x2e, 0xe7, 0x7c, 0x3e, 0xe8, 0xd4, 0x18, 0x4c,
+       0x8e, 0xcf, 0xd7, 0x4a, 0x9e, 0xf0, 0x3b, 0x72, 0x11, 0x1b, 0x79, 0x08,
+       0x64, 0xfc, 0x55, 0xc8, 0xca, 0x2b, 0x36, 0xf2, 0x0e, 0x1b, 0xf9, 0x88,
+       0x8d, 0xdc, 0xc3, 0x46, 0xee, 0x61, 0xf7, 0xc8, 0x1c, 0x26, 0x23, 0xeb,
+       0x56, 0x7c, 0x46, 0xcb, 0xf9, 0x61, 0x5e, 0xc9, 0xd8, 0xe3, 0x7c, 0x1f,
+       0x41, 0x4d, 0xc6, 0x36, 0xca, 0x78, 0xf0, 0x38, 0xdf, 0x77, 0x28, 0xab,
+       0x71, 0xae, 0x45, 0x91, 0xaa, 0xc6, 0x6f, 0x87, 0x8f, 0xda, 0x0e, 0xbc,
+       0x9a, 0x79, 0xdc, 0xa7, 0xc6, 0x5b, 0x99, 0x76, 0x8a, 0x1a, 0x5f, 0x2b,
+       0xcf, 0x0d, 0x7a, 0x03, 0x0e, 0xfe, 0xdd, 0xdc, 0xd6, 0xd4, 0xf8, 0xdd,
+       0xec, 0xd3, 0xc2, 0xa4, 0xba, 0xfd, 0xb7, 0x07, 0x98, 0xae, 0xa4, 0xde,
+       0x16, 0xe0, 0xb8, 0x76, 0xde, 0xf6, 0x8b, 0x3b, 0x05, 0xc9, 0x18, 0xd7,
+       0xcc, 0xb8, 0x5d, 0xa5, 0xab, 0xba, 0x2c, 0x5d, 0xfd, 0x95, 0xfa, 0x3f,
+       0xd3, 0xd2, 0xc7, 0x70, 0xa2, 0x36, 0xc6, 0x34, 0x75, 0xe7, 0xe3, 0xf3,
+       0x66, 0x5e, 0x47, 0xdc, 0x63, 0xc0, 0xf3, 0x60, 0x33, 0xb5, 0x0d, 0x0e,
+       0xf9, 0x2d, 0xef, 0xba, 0x6c, 0x43, 0x76, 0x90, 0x37, 0xc7, 0x5a, 0x7e,
+       0xcd, 0xa8, 0x38, 0x1b, 0x49, 0xf6, 0x47, 0x85, 0xec, 0xb0, 0xac, 0x69,
+       0xe2, 0xce, 0xd5, 0x47, 0xe2, 0x1e, 0x09, 0xcb, 0x19, 0xcb, 0xf2, 0x78,
+       0x7f, 0x57, 0x58, 0x53, 0x5b, 0xb0, 0x46, 0x98, 0xd2, 0x25, 0x71, 0x56,
+       0x80, 0x7c, 0xe9, 0xdc, 0x3a, 0x6a, 0xfb, 0x07, 0xbd, 0x9a, 0xc7, 0x46,
+       0x9d, 0xb3, 0x7a, 0xbb, 0xde, 0xff, 0x8d, 0x8a, 0x73, 0x65, 0xc7, 0x06,
+       0xb9, 0xe7, 0xc3, 0xab, 0x3b, 0xff, 0xbe, 0xbe, 0x3e, 0xb5, 0xd4, 0xd7,
+       0x0d, 0x24, 0x0d, 0x98, 0x36, 0x8d, 0xcf, 0xee, 0xe7, 0x4b, 0x7c, 0xaf,
+       0x25, 0x12, 0xe3, 0xdc, 0x6d, 0x44, 0xdc, 0xf9, 0x50, 0x21, 0x85, 0x3a,
+       0x8d, 0x19, 0x9c, 0xf3, 0x85, 0x86, 0x7d, 0x71, 0xca, 0x64, 0x27, 0x48,
+       0x43, 0xac, 0x98, 0xa9, 0xd6, 0x03, 0x1f, 0x5c, 0x43, 0x96, 0x2b, 0x97,
+       0x51, 0xce, 0x1f, 0x6a, 0xce, 0xed, 0x16, 0xe9, 0xb0, 0x72, 0xa0, 0x74,
+       0x84, 0x0e, 0x34, 0x8c, 0x29, 0x1b, 0xd7, 0x03, 0x2f, 0xd6, 0xd5, 0x14,
+       0x16, 0x44, 0x4d, 0x21, 0xb7, 0xc6, 0x6f, 0x3d, 0x19, 0x70, 0xee, 0xb5,
+       0x34, 0xd6, 0x93, 0x5d, 0x15, 0x3d, 0x71, 0xe1, 0xf8, 0x2c, 0xbe, 0x8d,
+       0x76, 0x8a, 0xb5, 0x0e, 0x2b, 0x59, 0xbb, 0x95, 0x76, 0x1a, 0x0e, 0xd6,
+       0xa3, 0x36, 0xe3, 0x75, 0x58, 0x39, 0x68, 0xe7, 0x95, 0xb4, 0xa8, 0x3d,
+       0x70, 0x8c, 0xbf, 0xe6, 0xda, 0x30, 0x95, 0xe9, 0xed, 0x98, 0xfb, 0x3d,
+       0xc3, 0x78, 0x6b, 0x8a, 0x2e, 0x9d, 0xf8, 0x2e, 0x51, 0x58, 0xe6, 0x6f,
+       0xce, 0x7c, 0xb9, 0x29, 0xae, 0x25, 0xde, 0x8f, 0xfd, 0x33, 0xfc, 0x6e,
+       0x25, 0x39, 0x55, 0x2e, 0xa7, 0x31, 0x3e, 0xd6, 0x7b, 0xaf, 0xc8, 0x8d,
+       0xd4, 0x38, 0x0d, 0x71, 0x8e, 0xac, 0x2d, 0xc9, 0x91, 0xd3, 0xd0, 0x35,
+       0xc4, 0x20, 0x76, 0x13, 0xbe, 0x75, 0xe3, 0x91, 0xcf, 0xae, 0x75, 0x64,
+       0xe4, 0xbb, 0x12, 0x0f, 0x1e, 0xff, 0xfb, 0x80, 0x7b, 0x0f, 0x28, 0x77,
+       0x2a, 0x8d, 0xfd, 0x37, 0x51, 0xca, 0x74, 0xf2, 0xbb, 0xec, 0x99, 0x23,
+       0x1b, 0x6a, 0xe1, 0xd1, 0x77, 0xca, 0x85, 0x0f, 0xd6, 0xc1, 0xf3, 0x19,
+       0xd7, 0x5f, 0xd5, 0xc1, 0x07, 0x3d, 0xf0, 0x66, 0x1d, 0x3c, 0xe2, 0xae,
+       0x33, 0xdf, 0xa8, 0x83, 0x37, 0x3d, 0xf0, 0xed, 0x75, 0xf0, 0xed, 0x80,
+       0x7f, 0xa3, 0x0e, 0x1e, 0x7d, 0xa7, 0x90, 0x13, 0x08, 0xda, 0x70, 0x8c,
+       0x74, 0x48, 0xe6, 0x89, 0x78, 0x2e, 0xb9, 0x1f, 0xc9, 0xf2, 0xd3, 0x01,
+       0x1a, 0x7b, 0xeb, 0xb5, 0x09, 0xd8, 0xa8, 0xaa, 0x4c, 0x39, 0xfa, 0xea,
+       0x95, 0x25, 0x96, 0xbd, 0x3c, 0xe4, 0x15, 0x7a, 0x54, 0x80, 0x3e, 0x15,
+       0x5c, 0x5f, 0xca, 0x77, 0xaa, 0x22, 0xc7, 0x1d, 0x3d, 0x56, 0x68, 0xbd,
+       0x35, 0x2f, 0x73, 0x91, 0xab, 0x8c, 0x3b, 0xfc, 0x86, 0xeb, 0x3b, 0xe8,
+       0x84, 0x63, 0x57, 0x58, 0xbf, 0x79, 0x7e, 0x69, 0x5f, 0x4a, 0x2c, 0x87,
+       0xce, 0x3a, 0xe9, 0x25, 0x32, 0x1b, 0x5e, 0x52, 0x77, 0xf1, 0xd5, 0xd9,
+       0x77, 0x12, 0xf6, 0x3d, 0xd7, 0xe2, 0xb7, 0x36, 0xac, 0xbd, 0x9e, 0x7d,
+       0xcf, 0x78, 0xec, 0x7b, 0x38, 0x58, 0xf5, 0xf9, 0x8f, 0x09, 0x9f, 0xdf,
+       0xd1, 0xc0, 0x66, 0xac, 0xde, 0xe7, 0xef, 0xfd, 0xd8, 0x3e, 0x7f, 0xb9,
+       0x75, 0x57, 0xe3, 0xf3, 0x1f, 0x69, 0xf9, 0x78, 0x3e, 0x9f, 0xd7, 0xac,
+       0xaf, 0x65, 0x7a, 0xcf, 0x59, 0x8e, 0xca, 0x18, 0x7b, 0xb7, 0x27, 0xc6,
+       0x66, 0xfc, 0xbe, 0x27, 0xef, 0x02, 0x9e, 0x5e, 0xeb, 0xc8, 0xdb, 0x51,
+       0x19, 0xa7, 0x73, 0xec, 0x8d, 0xf7, 0xc2, 0x23, 0x90, 0xd1, 0x7c, 0x8f,
+       0x8f, 0x54, 0x9a, 0x35, 0x9d, 0xb3, 0xed, 0x9f, 0x6f, 0xae, 0x17, 0xa1,
+       0xcb, 0xc2, 0x9f, 0x24, 0x3e, 0x81, 0x5a, 0xea, 0x49, 0xc8, 0x8f, 0xbb,
+       0xaf, 0x95, 0x6a, 0xa9, 0xf5, 0xe7, 0x1f, 0x7c, 0xee, 0x41, 0xca, 0x03,
+       0x95, 0x73, 0x10, 0xaf, 0x4e, 0xe9, 0x94, 0x9d, 0x21, 0xdd, 0x8c, 0x93,
+       0xb2, 0x8f, 0x71, 0x8e, 0xfd, 0xb0, 0x52, 0x6f, 0x3f, 0x24, 0x6b, 0x30,
+       0xea, 0xb2, 0x77, 0x82, 0x7e, 0x02, 0x7c, 0x58, 0xaf, 0x9c, 0x1a, 0x8c,
+       0xea, 0xdc, 0x09, 0x3a, 0xfe, 0xf3, 0xbb, 0x13, 0xc4, 0xf3, 0x6b, 0xb4,
+       0xb7, 0xc1, 0x9d, 0x20, 0xdf, 0x2a, 0xef, 0x04, 0xad, 0x17, 0x35, 0x18,
+       0x9e, 0xc7, 0xa9, 0xc1, 0x70, 0xbb, 0xb3, 0x8f, 0xe5, 0x3a, 0x4c, 0xa3,
+       0x93, 0xb7, 0x88, 0x7b, 0xa8, 0x9d, 0x7d, 0xb5, 0xf2, 0xbd, 0xef, 0x13,
+       0x8d, 0xa5, 0x79, 0xbd, 0xa3, 0x0d, 0xef, 0xb6, 0x24, 0x3f, 0xc1, 0x9a,
+       0xcb, 0x21, 0x51, 0x73, 0xb9, 0xb3, 0xcd, 0x5b, 0x73, 0x51, 0x57, 0xb8,
+       0xdb, 0x72, 0xa8, 0x41, 0xcd, 0xc5, 0xef, 0xb9, 0xdb, 0xe2, 0xf7, 0xdc,
+       0x6d, 0x39, 0x24, 0xeb, 0x2b, 0xea, 0x2f, 0xd1, 0xdd, 0x96, 0xe4, 0x8a,
+       0x77, 0x5b, 0xb6, 0x4a, 0x7d, 0xf5, 0xc2, 0xaf, 0xfe, 0xbc, 0x32, 0x55,
+       0x67, 0xe7, 0x13, 0xc2, 0xce, 0xdf, 0xd5, 0xea, 0xb7, 0x9e, 0x69, 0xbb,
+       0x9e, 0x9d, 0xdf, 0x57, 0xd1, 0x53, 0xbe, 0xa3, 0xcd, 0x77, 0xbe, 0x58,
+       0x16, 0xf9, 0x7c, 0xa6, 0x89, 0x72, 0x03, 0xbf, 0x2a, 0x68, 0xf6, 0x58,
+       0x6f, 0xed, 0x99, 0x63, 0xf5, 0x5e, 0xa4, 0xee, 0xb9, 0x17, 0x69, 0xa2,
+       0x5f, 0xaf, 0xab, 0x87, 0x04, 0xe4, 0xdd, 0x7e, 0xf8, 0xc2, 0x19, 0x43,
+       0xda, 0x5e, 0xc4, 0x70, 0x98, 0xae, 0x50, 0xe4, 0x3b, 0x95, 0x6d, 0xe4,
+       0x9b, 0x71, 0xce, 0x4b, 0x54, 0x11, 0x63, 0x42, 0x8e, 0x8b, 0x7e, 0xe1,
+       0x6f, 0xd4, 0xb8, 0x23, 0xb3, 0xe3, 0xf6, 0x05, 0xe0, 0xbf, 0x21, 0x51,
+       0x6d, 0x9b, 0x95, 0x5a, 0xce, 0x58, 0xe5, 0x0e, 0xbf, 0x09, 0xfb, 0xe0,
+       0xdc, 0x07, 0xca, 0x98, 0x7c, 0x67, 0xe4, 0x62, 0x5b, 0xf5, 0x3e, 0xd0,
+       0x67, 0xa4, 0x9c, 0x3a, 0xf7, 0x81, 0x48, 0x4d, 0x40, 0x3e, 0x6e, 0xe4,
+       0x3e, 0x50, 0xd7, 0x92, 0xfb, 0x40, 0x2b, 0xf3, 0x66, 0xe9, 0x7d, 0xa0,
+       0xc6, 0xfc, 0xe1, 0xfb, 0x40, 0xff, 0xde, 0xe6, 0xdc, 0x43, 0x5d, 0x89,
+       0x3f, 0x6e, 0x9c, 0xf4, 0x11, 0xe0, 0xf9, 0x3e, 0x50, 0xe5, 0x1e, 0x90,
+       0xe7, 0x0e, 0x10, 0xdf, 0x25, 0x59, 0xee, 0x0c, 0xce, 0x7b, 0xff, 0xa4,
+       0xa7, 0x72, 0xff, 0xe4, 0x7c, 0xc9, 0xf5, 0xed, 0xee, 0xb9, 0x1c, 0xc7,
+       0x39, 0xbb, 0x44, 0x8e, 0x7a, 0xae, 0x54, 0x5b, 0xc3, 0x60, 0xbe, 0x8f,
+       0x16, 0xcf, 0x81, 0x3e, 0x6f, 0x89, 0xdc, 0x00, 0x7c, 0xde, 0xe2, 0x23,
+       0xe6, 0x1d, 0x29, 0xa0, 0x8b, 0x38, 0xcb, 0x75, 0xf8, 0xdd, 0x21, 0x64,
+       0xc1, 0x91, 0x8b, 0xdd, 0x9e, 0xf3, 0xd0, 0xaa, 0x1c, 0x38, 0x67, 0xba,
+       0x0e, 0xef, 0x6a, 0x65, 0x46, 0x9c, 0xdd, 0x0c, 0xed, 0xb5, 0x9c, 0xf3,
+       0xc6, 0xa8, 0x38, 0xb7, 0x6d, 0xaf, 0xb3, 0x5b, 0x3a, 0xe4, 0x06, 0x31,
+       0x67, 0x8c, 0xeb, 0xd5, 0x8c, 0xfb, 0x66, 0xc1, 0xe3, 0x46, 0x67, 0x71,
+       0x2b, 0xd7, 0xf1, 0xdc, 0x9a, 0x0a, 0x21, 0x97, 0xd8, 0x9d, 0xce, 0x09,
+       0xbb, 0xe9, 0xac, 0xdd, 0x29, 0xd6, 0xde, 0x58, 0x77, 0x96, 0xcd, 0x72,
+       0xb5, 0x5c, 0x4c, 0x70, 0x3d, 0x9a, 0xde, 0xb3, 0x84, 0xa6, 0xb5, 0xba,
+       0x84, 0xdc, 0xb5, 0x62, 0xe3, 0x3b, 0x2a, 0xba, 0x34, 0x2e, 0xee, 0x21,
+       0xbb, 0xe7, 0xb5, 0x0e, 0xfd, 0xaa, 0xba, 0xb7, 0x5c, 0x3c, 0x53, 0x4f,
+       0xbf, 0x4d, 0xff, 0x4b, 0xe8, 0x77, 0x15, 0xf4, 0xe3, 0x77, 0x03, 0xef,
+       0xef, 0x8a, 0x7a, 0xc0, 0xb9, 0x52, 0xe4, 0x78, 0x9e, 0x38, 0x4e, 0x88,
+       0xcc, 0x2e, 0x50, 0x0f, 0xe8, 0xc8, 0xff, 0xeb, 0xe2, 0xde, 0x9d, 0x60,
+       0xfa, 0xb2, 0x7d, 0x8f, 0xbc, 0x70, 0x99, 0xd8, 0xc6, 0xdf, 0x8d, 0x7d,
+       0x94, 0xcb, 0x2f, 0xc5, 0x5c, 0xfa, 0xb3, 0xee, 0x73, 0x9d, 0xaa, 0x76,
+       0x5f, 0x7b, 0x57, 0xed, 0x53, 0x1d, 0xf9, 0xcc, 0x34, 0x90, 0xcf, 0x8c,
+       0xdc, 0xa3, 0x6f, 0xa6, 0x71, 0xbc, 0x9a, 0x9a, 0xfc, 0xef, 0x5e, 0xae,
+       0x26, 0xb6, 0x8d, 0x22, 0x0a, 0xbf, 0xac, 0xd7, 0x4e, 0xe3, 0xa4, 0x61,
+       0x93, 0x3a, 0xad, 0x69, 0xd2, 0x60, 0xc7, 0x4b, 0x12, 0x29, 0xa5, 0xa4,
+       0x52, 0x55, 0x45, 0x60, 0xa9, 0x21, 0x4e, 0xda, 0x0a, 0x71, 0x70, 0x0b,
+       0x48, 0x51, 0xc5, 0x21, 0x4d, 0xd3, 0x7b, 0x85, 0x84, 0x54, 0xa1, 0x8a,
+       0x46, 0x4e, 0x02, 0x15, 0x4a, 0xe5, 0x0a, 0x96, 0x72, 0x41, 0xa2, 0xd8,
+       0x8e, 0x02, 0x52, 0x2a, 0xf7, 0xca, 0x85, 0xba, 0xbf, 0x08, 0x89, 0x03,
+       0x70, 0x06, 0x29, 0x2a, 0x3f, 0xe2, 0xc0, 0x8d, 0x1b, 0x54, 0x5d, 0xde,
+       0x37, 0xb3, 0x63, 0xaf, 0x77, 0xd7, 0x8e, 0x03, 0x11, 0x07, 0x27, 0xbb,
+       0xf6, 0xcc, 0xce, 0xec, 0xcc, 0x37, 0x6f, 0xbe, 0xf7, 0x37, 0xfd, 0xbe,
+       0x78, 0x8d, 0x5a, 0xdb, 0x5b, 0xf3, 0x55, 0xec, 0xe7, 0xaf, 0x37, 0x18,
+       0x57, 0xed, 0xba, 0xe4, 0xa9, 0xf5, 0xe3, 0x9a, 0x72, 0xd9, 0x1b, 0xf0,
+       0xfe, 0xc7, 0x68, 0x51, 0xd8, 0x86, 0x94, 0xad, 0xee, 0xc5, 0x40, 0x9b,
+       0xd9, 0xff, 0x33, 0x16, 0x03, 0x3e, 0x9b, 0x68, 0xad, 0x6d, 0x8a, 0xed,
+       0x71, 0xd9, 0x16, 0xde, 0xda, 0xc2, 0xb6, 0x10, 0x3c, 0x16, 0xfd, 0x9e,
+       0xb1, 0xa8, 0xc9, 0xea, 0xa1, 0x16, 0xed, 0x74, 0x88, 0x21, 0xbf, 0x9d,
+       0x67, 0x6c, 0x05, 0xca, 0xce, 0x4f, 0x5d, 0x36, 0x3c, 0xe0, 0x73, 0xdc,
+       0x59, 0xeb, 0xc0, 0x27, 0xb5, 0x9d, 0x1a, 0x51, 0xed, 0x01, 0x8f, 0xc9,
+       0xc5, 0x45, 0x82, 0xbe, 0x86, 0x36, 0xe3, 0x82, 0xe3, 0xfa, 0x39, 0x14,
+       0x8f, 0xf1, 0xfa, 0x1b, 0x88, 0xe5, 0x70, 0xda, 0x3f, 0xd9, 0x76, 0xae,
+       0x9c, 0xe5, 0xbd, 0x42, 0xd4, 0x63, 0xbd, 0xef, 0x52, 0xdb, 0x82, 0xa8,
+       0x27, 0xe3, 0x20, 0x1c, 0x1d, 0xd0, 0xe1, 0xe2, 0x8d, 0x74, 0x3f, 0xff,
+       0x9e, 0x13, 0xcc, 0xdd, 0x7f, 0xdd, 0x1d, 0x36, 0x3f, 0x34, 0x64, 0xae,
+       0xde, 0x56, 0xdc, 0x5d, 0xd9, 0x89, 0x06, 0x85, 0xaf, 0xc1, 0xad, 0x7b,
+       0x41, 0x76, 0x5d, 0xe0, 0x3d, 0x7c, 0xa8, 0xba, 0x7f, 0xef, 0x84, 0x7d,
+       0xe8, 0x99, 0x16, 0x62, 0x1d, 0x44, 0x8e, 0xe5, 0x2b, 0x53, 0xc8, 0x45,
+       0xaa, 0xe6, 0xef, 0x78, 0xf3, 0x3c, 0x20, 0x3f, 0x55, 0x9e, 0x87, 0xca,
+       0x23, 0xc5, 0x7b, 0x24, 0x02, 0xf2, 0x3c, 0xdc, 0x32, 0x18, 0xf5, 0xea,
+       0xdf, 0xc3, 0x2d, 0x7f, 0x57, 0x1c, 0xf9, 0x5b, 0xf0, 0xd8, 0xe3, 0x97,
+       0xf3, 0x6a, 0x2d, 0x20, 0xe7, 0x43, 0xf1, 0x94, 0xde, 0x00, 0x9e, 0x12,
+       0x9c, 0xeb, 0xa1, 0xa5, 0x2f, 0xf2, 0x5e, 0x7e, 0x08, 0x7b, 0xb9, 0x51,
+       0x8b, 0xe9, 0x95, 0x72, 0xf0, 0xdc, 0x3a, 0x64, 0xa2, 0xca, 0xb9, 0x81,
+       0x5c, 0x44, 0x2c, 0x3c, 0xe6, 0xba, 0xe4, 0x60, 0x11, 0xbf, 0xa9, 0x58,
+       0x52, 0xa5, 0x47, 0xbd, 0x23, 0xf2, 0x0c, 0xbe, 0x1b, 0x3f, 0xcc, 0x1c,
+       0x18, 0xf2, 0x13, 0x76, 0xa6, 0x43, 0x0e, 0x1f, 0xbe, 0xcc, 0xbf, 0x8d,
+       0x39, 0xd7, 0x92, 0x8b, 0xca, 0x6b, 0xa5, 0x4b, 0xfd, 0xd0, 0x41, 0xe6,
+       0x6f, 0x0e, 0x2f, 0xad, 0xb3, 0x41, 0xc4, 0x53, 0xda, 0xdb, 0x74, 0xa1,
+       0xd8, 0x0c, 0x83, 0xf5, 0xf8, 0x4b, 0x79, 0x38, 0x4f, 0x42, 0x70, 0x9e,
+       0x9f, 0x3a, 0xc2, 0xe6, 0x44, 0x4f, 0xb3, 0x38, 0x9c, 0x53, 0x55, 0xfc,
+       0xa9, 0x72, 0xaa, 0x6f, 0x8f, 0x3a, 0x10, 0xa7, 0xe6, 0xc7, 0x04, 0xe6,
+       0x1f, 0xfa, 0x9c, 0x5a, 0x87, 0xd0, 0xeb, 0x10, 0xf3, 0x87, 0x76, 0x8d,
+       0x06, 0x6b, 0xb0, 0x66, 0x13, 0x2f, 0x50, 0x2b, 0xb1, 0x7f, 0xc9, 0xd1,
+       0x0a, 0x9d, 0xed, 0x69, 0xa6, 0xf3, 0x9e, 0x08, 0xd4, 0x79, 0x83, 0x72,
+       0xa4, 0xcc, 0x80, 0x1c, 0x29, 0x37, 0x0e, 0x75, 0x17, 0x0e, 0xe3, 0x2e,
+       0x2e, 0x30, 0xc0, 0xdc, 0xb9, 0x8b, 0xf1, 0x04, 0xee, 0x1c, 0xa5, 0xd0,
+       0x07, 0x6e, 0xee, 0xec, 0xf7, 0x13, 0x49, 0x5c, 0xfe, 0xdb, 0xdc, 0xa9,
+       0xa0, 0x7e, 0x27, 0x7c, 0xfd, 0x86, 0x1c, 0x9f, 0x6c, 0xc8, 0x13, 0x82,
+       0x38, 0xfe, 0x4e, 0xf7, 0xd3, 0xbb, 0xf6, 0xd1, 0xa6, 0x09, 0xfd, 0x70,
+       0x74, 0xb1, 0xba, 0xee, 0x5f, 0xf0, 0xd9, 0xb9, 0xc1, 0x67, 0x43, 0xc2,
+       0x27, 0xd7, 0x25, 0xf6, 0x90, 0x9d, 0x93, 0x61, 0x9d, 0x1e, 0x19, 0x66,
+       0xf7, 0xd4, 0xec, 0xfc, 0x88, 0x21, 0xec, 0x73, 0x74, 0x0e, 0xb9, 0xef,
+       0x14, 0x1a, 0xc6, 0xa5, 0xe2, 0x3b, 0xe9, 0x1b, 0x38, 0x77, 0x04, 0xb2,
+       0x1b, 0xf2, 0xfc, 0xf4, 0x6c, 0xd8, 0x34, 0x1c, 0x1f, 0x03, 0xfc, 0x08,
+       0xc0, 0xa9, 0x7a, 0x7e, 0x90, 0x0d, 0x3d, 0x68, 0x0e, 0x87, 0x7c, 0x73,
+       0x28, 0xf1, 0x06, 0x6e, 0x8f, 0x58, 0xbc, 0x83, 0x9e, 0x38, 0xc5, 0x9d,
+       0x18, 0x93, 0xee, 0x80, 0x78, 0x41, 0xc4, 0xfa, 0xf9, 0xfa, 0xcb, 0xef,
+       0x7c, 0x51, 0xf3, 0xaf, 0xad, 0x49, 0x6d, 0xba, 0x3c, 0xad, 0x4d, 0x15,
+       0x51, 0xee, 0xa2, 0x56, 0xdb, 0x97, 0x36, 0x5d, 0x1c, 0x11, 0x7c, 0x30,
+       0x79, 0xad, 0x42, 0x78, 0x4f, 0xdb, 0xbe, 0x25, 0xb8, 0xed, 0x80, 0x0f,
+       0xab, 0x8a, 0x73, 0x18, 0x2d, 0xbc, 0x97, 0xb4, 0xbd, 0xb8, 0xb9, 0x8e,
+       0x5b, 0xbe, 0x3f, 0x1d, 0x20, 0xdf, 0x9b, 0xd9, 0x0a, 0x91, 0xbf, 0x29,
+       0xe2, 0xb2, 0xa9, 0x68, 0x21, 0xde, 0xf1, 0x30, 0xe2, 0x7b, 0xe1, 0xd7,
+       0xa8, 0x62, 0xe1, 0x6e, 0x30, 0x16, 0xaa, 0xf6, 0x60, 0x1d, 0xb9, 0xa3,
+       0x2c, 0x8b, 0xc3, 0xe9, 0x5e, 0x0a, 0x99, 0x28, 0xff, 0x6c, 0xe2, 0x3e,
+       0x1d, 0x73, 0x78, 0x09, 0xfc, 0x3c, 0xb2, 0xde, 0x4c, 0x0b, 0x76, 0xe1,
+       0x60, 0x7f, 0x46, 0x84, 0x65, 0xf3, 0x67, 0xbd, 0xad, 0xf9, 0x33, 0x54,
+       0x39, 0xd4, 0xed, 0xa2, 0x35, 0x0b, 0x71, 0x92, 0xf0, 0x2f, 0x75, 0x77,
+       0xb4, 0x9b, 0x41, 0xf2, 0x4f, 0xc5, 0x7e, 0x82, 0x1f, 0xc9, 0xb9, 0xba,
+       0x41, 0x98, 0x3b, 0x9b, 0xbe, 0x6f, 0x30, 0x57, 0xdb, 0xb1, 0x29, 0x37,
+       0x9f, 0x2b, 0xc3, 0x33, 0x57, 0xd8, 0x8b, 0x9a, 0xcd, 0x95, 0xf2, 0x43,
+       0x2a, 0xdf, 0xdc, 0x51, 0xc8, 0x93, 0x45, 0xf7, 0x5c, 0xed, 0x8c, 0x7f,
+       0x4e, 0xce, 0xd9, 0x4e, 0xfb, 0xe0, 0x1a, 0x8f, 0x43, 0x34, 0xd0, 0x76,
+       0x12, 0x2c, 0x33, 0xfc, 0x6b, 0xeb, 0x86, 0x5c, 0x5b, 0xcc, 0x2b, 0x9e,
+       0x6f, 0xb8, 0xb6, 0xb0, 0x0f, 0x5c, 0x70, 0xf6, 0x81, 0xd3, 0x3e, 0x7d,
+       0x51, 0xd9, 0xbc, 0xff, 0xab, 0xed, 0x0d, 0xcf, 0x7d, 0x22, 0xce, 0xe9,
+       0xc8, 0x91, 0xdc, 0x47, 0xce, 0x37, 0xe4, 0x61, 0x3d, 0xdb, 0x5c, 0xa7,
+       0x6a, 0xee, 0x91, 0x73, 0x01, 0x79, 0x99, 0xa5, 0xf3, 0xf9, 0xc7, 0x06,
+       0x75, 0xf7, 0x53, 0xa4, 0x1a, 0xd3, 0x72, 0x40, 0xf0, 0x61, 0xb7, 0xbe,
+       0xbc, 0xec, 0xe4, 0x28, 0xe6, 0x5c, 0x63, 0xb0, 0x9c, 0xcf, 0x36, 0x89,
+       0xa7, 0x6f, 0x25, 0x9e, 0x63, 0xc0, 0x23, 0x37, 0xbd, 0x73, 0x35, 0xa1,
+       0x65, 0xf2, 0xa8, 0xb3, 0x87, 0xce, 0xea, 0x9f, 0xf0, 0x18, 0x3d, 0xb1,
+       0x23, 0xe2, 0x9c, 0x11, 0xe0, 0xd2, 0xb6, 0x97, 0xcd, 0x0e, 0x5a, 0x94,
+       0x7e, 0x46, 0x9a, 0xfa, 0xf8, 0x12, 0x15, 0x85, 0x7f, 0x0b, 0xb9, 0x51,
+       0xb0, 0x71, 0xc3, 0x47, 0x87, 0xe7, 0xf0, 0xf7, 0x1b, 0x13, 0x8e, 0xcc,
+       0xfd, 0x93, 0x31, 0x8c, 0x7a, 0x38, 0x0b, 0x01, 0xeb, 0x9d, 0x34, 0xc9,
+       0x31, 0xb9, 0x1d, 0x71, 0x4e, 0x80, 0x8c, 0xcd, 0xbb, 0x5d, 0xde, 0x8e,
+       0x4f, 0xa1, 0x55, 0xbd, 0xe4, 0xeb, 0x68, 0xd8, 0xfc, 0x72, 0xcf, 0xf6,
+       0x7d, 0x0a, 0x2a, 0x77, 0x5f, 0x71, 0x58, 0x75, 0x2d, 0x73, 0x69, 0xc1,
+       0x99, 0xe7, 0xd7, 0x55, 0xde, 0x6d, 0x77, 0x40, 0xde, 0x6d, 0x88, 0xe6,
+       0x84, 0xaf, 0x2e, 0x44, 0x39, 0x47, 0x37, 0x93, 0x9c, 0x5a, 0xd9, 0x6a,
+       0x23, 0x4e, 0xfc, 0x29, 0xee, 0xdd, 0x39, 0xf9, 0x7c, 0x5f, 0x04, 0xcf,
+       0x46, 0x4e, 0xb5, 0x2d, 0x62, 0xf1, 0x33, 0xa2, 0x5c, 0xa7, 0xa7, 0x1c,
+       0xdf, 0x17, 0xd5, 0x33, 0x3b, 0xb9, 0x7c, 0x8a, 0x64, 0x0e, 0x7d, 0x27,
+       0xcd, 0x15, 0x9b, 0xf5, 0x6b, 0x1f, 0xe2, 0x81, 0xe3, 0xf0, 0x95, 0x0a,
+       0xbf, 0x95, 0xa1, 0xfa, 0x80, 0x3e, 0xb5, 0x57, 0xfb, 0x04, 0xf9, 0x14,
+       0x12, 0x7e, 0x05, 0xbe, 0x76, 0xda, 0x99, 0x23, 0x77, 0xbf, 0xc2, 0xdc,
+       0x2f, 0x3c, 0xa7, 0xd3, 0x55, 0xb6, 0xd3, 0x55, 0xb6, 0x36, 0x5e, 0x3a,
+       0xeb, 0x54, 0x0b, 0xe5, 0x1f, 0x59, 0x2f, 0xfd, 0x56, 0xd8, 0xe6, 0xe6,
+       0xb3, 0x06, 0x2d, 0xac, 0xf7, 0xf2, 0x27, 0xc6, 0x1f, 0x94, 0xdb, 0xcb,
+       0xff, 0xdd, 0x9c, 0xa2, 0x5f, 0xc4, 0x02, 0xb6, 0xce, 0x07, 0x83, 0xf1,
+       0x1f, 0xbc, 0x6e, 0x13, 0x01, 0xeb, 0xb6, 0xf9, 0xbe, 0x22, 0xf7, 0x93,
+       0xe4, 0x95, 0x8a, 0x23, 0xaf, 0x36, 0x69, 0xd0, 0x27, 0xa7, 0x82, 0xd6,
+       0x29, 0xfa, 0x78, 0xca, 0xe9, 0xe3, 0x9b, 0xa2, 0x3f, 0xe3, 0x54, 0xa8,
+       0xe6, 0x0d, 0x1f, 0xe1, 0xeb, 0x98, 0xb2, 0xd1, 0x35, 0x90, 0xab, 0xdf,
+       0x6c, 0x43, 0xc6, 0x04, 0x71, 0xb2, 0x03, 0x01, 0xfa, 0x80, 0xee, 0xd2,
+       0x07, 0xe2, 0x55, 0x7d, 0x60, 0x45, 0xe8, 0x09, 0xbb, 0x1c, 0x1d, 0x34,
+       0xd8, 0x16, 0x97, 0xcb, 0xe3, 0xcc, 0x1b, 0xd8, 0xf8, 0xa4, 0x1d, 0x7d,
+       0xda, 0xaa, 0x9e, 0x99, 0xc3, 0xba, 0x65, 0x8d, 0x4b, 0xfb, 0xe5, 0x09,
+       0xce, 0xac, 0xa8, 0xcc, 0x3e, 0x30, 0xa3, 0xa4, 0xa5, 0x93, 0xf1, 0xa9,
+       0x50, 0x84, 0x16, 0xac, 0x28, 0x15, 0xac, 0x14, 0x73, 0x70, 0xf0, 0xe3,
+       0xd0, 0x80, 0x46, 0x11, 0x96, 0x35, 0x11, 0x2a, 0x95, 0x94, 0x4e, 0x76,
+       0x86, 0xc8, 0x2c, 0xc6, 0xa4, 0x0d, 0x9b, 0x71, 0x9a, 0x1f, 0x33, 0xe6,
+       0x49, 0x43, 0xcc, 0x8b, 0x93, 0xa3, 0x0e, 0x0c, 0x8a, 0x38, 0x4b, 0xfd,
+       0xe5, 0x91, 0x28, 0xb5, 0xa7, 0xa5, 0xcd, 0x68, 0x86, 0xdb, 0xf8, 0xc2,
+       0x8a, 0xd1, 0x95, 0x7c, 0xd2, 0x38, 0xc1, 0xed, 0x64, 0xac, 0x64, 0x62,
+       0x92, 0x9f, 0x5d, 0x2c, 0x45, 0x28, 0x67, 0x45, 0xa8, 0x50, 0x4a, 0x19,
+       0x43, 0x6d, 0xa2, 0xcd, 0x18, 0xda, 0x7c, 0x49, 0x1f, 0x33, 0x4e, 0x92,
+       0xbb, 0xcd, 0xaf, 0x9c, 0x36, 0xbd, 0x6d, 0xfd, 0x61, 0xe3, 0xfe, 0x44,
+       0xa8, 0x32, 0x7b, 0x9f, 0xf1, 0x92, 0x5b, 0x9d, 0x60, 0xd9, 0x14, 0x13,
+       0x67, 0xdb, 0x68, 0xe9, 0x34, 0xcb, 0x1d, 0x9c, 0x6d, 0x61, 0xd0, 0x62,
+       0x39, 0x4e, 0xef, 0x57, 0xed, 0x07, 0x12, 0x43, 0x39, 0x91, 0x43, 0x84,
+       0x33, 0x17, 0x2a, 0xb3, 0xbf, 0x9b, 0x5e, 0x7f, 0x3f, 0xeb, 0x5b, 0x1f,
+       0xc5, 0x28, 0x72, 0x15, 0x71, 0xdd, 0x36, 0x5d, 0x1b, 0x4f, 0x5e, 0xd9,
+       0x14, 0x79, 0x68, 0x09, 0x5a, 0x33, 0xa5, 0x3c, 0xcd, 0x71, 0xf9, 0x15,
+       0x94, 0x5b, 0x4b, 0xd0, 0x3d, 0x91, 0x8f, 0xd6, 0x4e, 0x77, 0xf4, 0x18,
+       0x85, 0x6e, 0x9a, 0xc6, 0xbc, 0xf0, 0x0b, 0x57, 0x66, 0x87, 0x86, 0x0d,
+       0xd2, 0xae, 0xa2, 0x1e, 0xff, 0xbf, 0x89, 0xfb, 0x28, 0x61, 0x7e, 0x66,
+       0xac, 0x31, 0x5e, 0x49, 0xc3, 0xf1, 0x12, 0x64, 0xf3, 0x41, 0x89, 0xa5,
+       0x39, 0x23, 0x42, 0xd0, 0x5f, 0x61, 0x7b, 0xeb, 0x35, 0x27, 0x7b, 0xa4,
+       0xfe, 0xe4, 0x3b, 0x9b, 0x43, 0x9f, 0x19, 0x71, 0x9f, 0xcf, 0x51, 0x7b,
+       0x66, 0xc6, 0x92, 0xef, 0xb9, 0x52, 0xee, 0xa5, 0x25, 0x6e, 0x7b, 0x64,
+       0xf8, 0x8c, 0x73, 0xa6, 0x0f, 0xff, 0xd9, 0x8b, 0x7b, 0x85, 0xb7, 0x7d,
+       0x7d, 0x14, 0xc5, 0x3d, 0x0d, 0xe8, 0x3c, 0xc7, 0xb0, 0xe9, 0x87, 0xc5,
+       0xb8, 0xa7, 0xe2, 0x98, 0xcb, 0xb9, 0xb8, 0x3a, 0x97, 0x08, 0x65, 0xba,
+       0xe9, 0x91, 0xd5, 0x45, 0x3f, 0x8b, 0xf3, 0x47, 0xf8, 0xba, 0x84, 0x9c,
+       0xa3, 0x36, 0xca, 0x64, 0xbb, 0x69, 0xb3, 0x14, 0x66, 0x71, 0x05, 0xec,
+       0x44, 0xb9, 0x4c, 0x81, 0xa6, 0xd6, 0x5f, 0xeb, 0x83, 0x1f, 0x66, 0x52,
+       0xab, 0x61, 0xe9, 0x51, 0x00, 0x96, 0x7e, 0xa9, 0xc3, 0xd2, 0xd1, 0xbe,
+       0xe6, 0x58, 0xea, 0x77, 0x62, 0xd6, 0xa3, 0x14, 0x71, 0x70, 0xf4, 0x39,
+       0xe3, 0xe8, 0x3d, 0xc6, 0xd1, 0xf1, 0x06, 0x38, 0xd2, 0x3c, 0x38, 0x3a,
+       0x51, 0x87, 0xa3, 0x6c, 0x5f, 0x33, 0x1c, 0x1d, 0x0f, 0xa1, 0xff, 0xcd,
+       0xd6, 0x32, 0xfa, 0xb0, 0x9f, 0x39, 0xbd, 0x49, 0xa5, 0xd5, 0xe4, 0xf8,
+       0x24, 0x55, 0x90, 0x73, 0x92, 0x58, 0xa2, 0xb4, 0xe0, 0x76, 0x05, 0x81,
+       0xbf, 0x2c, 0x8f, 0xc9, 0xae, 0x06, 0xe7, 0xaa, 0x24, 0x9c, 0x79, 0x93,
+       0x73, 0x99, 0xc9, 0x57, 0x66, 0x1f, 0x32, 0x36, 0xee, 0x6d, 0xe8, 0x3a,
+       0x7e, 0x0b, 0xb1, 0x8c, 0xbc, 0xbb, 0x81, 0x73, 0x5b, 0xe2, 0x74, 0xdf,
+       0x1a, 0xa0, 0x7b, 0xd6, 0x7e, 0xba, 0x6b, 0x0d, 0xd2, 0x03, 0x0b, 0x6d,
+       0x60, 0x0e, 0xf8, 0x5e, 0xcc, 0x81, 0x46, 0x33, 0x31, 0x2e, 0x53, 0xda,
+       0x4f, 0x95, 0x92, 0xc2, 0x35, 0xb0, 0x03, 0x0c, 0x35, 0xc6, 0x4e, 0xa6,
+       0x0e, 0x3b, 0xb2, 0x0e, 0x30, 0xb3, 0xe4, 0xb7, 0xad, 0xed, 0x32, 0xf8,
+       0x5d, 0x0d, 0xc6, 0x56, 0x58, 0xc4, 0x91, 0x24, 0x47, 0x67, 0x42, 0x90,
+       0x59, 0xb7, 0x18, 0x53, 0x3c, 0x17, 0x3c, 0x7e, 0xda, 0xf5, 0x41, 0x96,
+       0x39, 0x4f, 0x09, 0x1b, 0xf4, 0x94, 0xa9, 0xc7, 0x33, 0x64, 0x5f, 0xd6,
+       0xcc, 0x31, 0x91, 0xeb, 0xb6, 0x54, 0xf6, 0x9e, 0x31, 0x91, 0xe1, 0xb1,
+       0x57, 0x78, 0xf4, 0xca, 0xa1, 0x76, 0xaa, 0x38, 0x31, 0x4c, 0x85, 0x55,
+       0xdb, 0x7e, 0xc8, 0xfc, 0x7f, 0xcd, 0x84, 0xcc, 0xfe, 0xdb, 0xae, 0xc4,
+       0x74, 0x5a, 0x36, 0x55, 0xdf, 0xee, 0x08, 0x7c, 0x31, 0x47, 0xa4, 0x77,
+       0x37, 0xaa, 0xaf, 0xc4, 0xbf, 0xe3, 0xbb, 0xbf, 0x04, 0x97, 0x59, 0xab,
+       0x96, 0x85, 0xed, 0xf8, 0xd2, 0xd8, 0xc2, 0x2a, 0xce, 0x7e, 0x7b, 0xfc,
+       0xea, 0xf9, 0xd5, 0x5c, 0x1f, 0x4b, 0xd8, 0x94, 0x4e, 0x76, 0x68, 0x79,
+       0x3c, 0xf7, 0x5c, 0x98, 0x86, 0x19, 0x97, 0x38, 0x83, 0x6b, 0x6c, 0x34,
+       0x2c, 0xce, 0x38, 0xd9, 0xcd, 0x78, 0xc8, 0x0a, 0x3b, 0xfd, 0xd4, 0x91,
+       0x09, 0x9a, 0x2c, 0xa7, 0xf9, 0x53, 0x3f, 0x7e, 0xb5, 0xb9, 0xe3, 0xe1,
+       0x48, 0xe3, 0x37, 0x37, 0xff, 0xa8, 0xd5, 0x9d, 0xe6, 0xba, 0x33, 0x5b,
+       0xd6, 0x55, 0xe7, 0x12, 0xfd, 0x03, 0x69, 0xae, 0x1b, 0xa3, 0xbc, 0x57,
+       0x00, 0x00, 0x00 };
 
 static u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 };
 static u32 bnx2_COM_b06FwRodata[(0x58/4) + 1] = {
@@ -989,952 +687,368 @@ static u32 bnx2_RXP_b06FwBssAddr = 0x08005900;
 static int bnx2_RXP_b06FwBssLen = 0x13a4;
 static u32 bnx2_RXP_b06FwSbssAddr = 0x080058e0;
 static int bnx2_RXP_b06FwSbssLen = 0x1c;
-static u32 bnx2_RXP_b06FwText[(0x588c/4) + 1] = {
-       0x0a000c61, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e362e,
-       0x31000000, 0x02060103, 0x00000000, 0x0000000d, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d,
-       0x3c020800, 0x244258e0, 0x3c030800, 0x24636ca4, 0xac400000, 0x0043202b,
-       0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800,
-       0x26103184, 0x3c1c0800, 0x279c58e0, 0x0e00104a, 0x00000000, 0x0000000d,
-       0x27bdffe8, 0xafb00010, 0xafbf0014, 0x0e000f1d, 0x00808021, 0x1440000d,
-       0x00000000, 0x8f820010, 0x10400005, 0x00000000, 0x9743011c, 0x9742011e,
-       0x0a000c89, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825,
-       0xaf830004, 0x8f840008, 0x3c020020, 0x34424000, 0x00821824, 0x54620004,
-       0x3c020020, 0x8f820014, 0x0a000c9a, 0x34421000, 0x34428000, 0x00821824,
-       0x14620004, 0x00000000, 0x8f820014, 0x34428000, 0xaf820014, 0x8f820008,
-       0x9743010c, 0x00403021, 0x30421000, 0x10400010, 0x3069ffff, 0x30c20020,
-       0x1440000e, 0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff,
-       0x3463ffff, 0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001,
-       0x0a000cb2, 0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d,
-       0x00405821, 0x8f820014, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01,
-       0x00c24024, 0x3c031000, 0x15030015, 0x3c020001, 0x31220200, 0x14400012,
-       0x3c020001, 0x9744010e, 0x24020003, 0xa342018b, 0x97850016, 0x24020002,
-       0x34e30002, 0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff,
-       0xa744018e, 0xa74501a6, 0xaf4801b8, 0x0a000f19, 0x00001021, 0x3c020001,
-       0x00c21024, 0x1040002f, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff,
-       0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9784000a,
-       0x8f850004, 0x8f870014, 0x24020080, 0x24030002, 0xaf420180, 0x24020003,
-       0xa743018c, 0xa746018e, 0xa7420188, 0x30e28000, 0xa7440190, 0x1040000c,
-       0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000,
-       0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014,
-       0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff,
-       0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19,
-       0x00001021, 0x8f820014, 0x30434000, 0x10600016, 0x00404021, 0x3c020f00,
-       0x00c21024, 0x14400012, 0x00000000, 0x93420116, 0x34424000, 0x03421821,
-       0x94650002, 0x2ca21389, 0x1040000b, 0x3c020800, 0x24425900, 0x00051942,
-       0x00031880, 0x00621821, 0x30a5001f, 0x8c640000, 0x24020001, 0x00a21004,
-       0x00822024, 0x02048025, 0x12000030, 0x3c021000, 0x9742010e, 0x34e80002,
-       0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-       0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180,
-       0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000,
-       0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
-       0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
-       0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
-       0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
-       0xaf4201b8, 0x0a000f19, 0x00001021, 0x00c21024, 0x104000c0, 0x3c020800,
-       0x8c430030, 0x10600037, 0x31024000, 0x10400035, 0x3c030f00, 0x00c31824,
-       0x3c020100, 0x0043102b, 0x14400031, 0x3c030800, 0x9742010e, 0x34e80002,
-       0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-       0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020080,
-       0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000,
-       0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
-       0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
-       0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
-       0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
-       0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800, 0x8c620024, 0x30420008,
-       0x10400035, 0x34ea0002, 0x3c020f00, 0x00c21024, 0x14400032, 0x8d620034,
-       0x31220200, 0x1040002f, 0x8d620034, 0x9742010e, 0x30e8fffb, 0x3c038000,
-       0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
-       0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180, 0x24030002,
-       0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, 0xa7440190,
-       0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
-       0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024,
-       0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
-       0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
-       0x8d620034, 0x8f860008, 0x10400012, 0x30c20100, 0x10400010, 0x3c020f00,
-       0x00c21024, 0x3c030200, 0x1043000c, 0x3c020800, 0x8c430038, 0x8f840004,
-       0x3c020800, 0x2442003c, 0x2463ffff, 0x00832024, 0x00822021, 0x90830000,
-       0x24630004, 0x0a000de1, 0x000329c0, 0x00000000, 0x00061602, 0x3042000f,
-       0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300, 0x0062182b, 0x50600001,
-       0x24050800, 0x9742010e, 0x3148ffff, 0x3c038000, 0x24420004, 0x3046ffff,
-       0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
-       0x8f840004, 0x8f870014, 0x24020002, 0xaf450180, 0xa742018c, 0xa746018e,
-       0xa7480188, 0x30e28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116,
-       0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
-       0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c,
-       0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
-       0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x8f424000,
-       0x30420100, 0x104000d5, 0x3c020800, 0x8c440024, 0x24030001, 0x1483002f,
-       0x00405021, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3045ffff,
-       0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
-       0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c, 0xa745018e,
-       0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116,
-       0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
-       0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016, 0x9743010c,
-       0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
-       0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x30820001,
-       0x1040002e, 0x30eb0004, 0x9742010e, 0x30e9fffb, 0x3c038000, 0x24420004,
-       0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b,
-       0x9783000a, 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c,
-       0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8,
-       0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff,
-       0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016,
-       0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825,
-       0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3127ffff, 0x8d420024,
-       0x30420004, 0x10400030, 0x8d420024, 0x9742010e, 0x30e9fffb, 0x3c038000,
-       0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
-       0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020100, 0x24030002,
-       0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000, 0xa7440190,
-       0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
-       0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x01021024,
-       0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
-       0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
-       0x3127ffff, 0x8d420024, 0x30420008, 0x1040002d, 0x00000000, 0x9742010e,
-       0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-       0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020180,
-       0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000,
-       0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
-       0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
-       0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
-       0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
-       0xaf4201b8, 0x15600041, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8,
-       0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b,
-       0xa4800010, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800,
-       0x8c620024, 0x30420001, 0x1040002e, 0x00001021, 0x9742010e, 0x34e70002,
-       0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-       0x24020003, 0xa342018b, 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002,
-       0xaf400180, 0xa742018c, 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190,
-       0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
-       0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024,
-       0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
-       0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
-       0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x8f4b0070,
-       0x93420112, 0x8f840008, 0x00022882, 0x30820100, 0x14400003, 0x24a30003,
-       0x03e00008, 0x00001021, 0x30824000, 0x10400010, 0x27424000, 0x00031880,
-       0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021,
-       0x8c490000, 0x93430116, 0x27424000, 0x306300fc, 0x00431021, 0x8c4a0000,
-       0x0a000f45, 0x3c030800, 0x30822000, 0x1040ffea, 0x00031880, 0x27424000,
-       0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021,
-       0x8c490000, 0x00005021, 0x3c030800, 0x24680100, 0x00071602, 0x00021080,
-       0x00481021, 0x8c460000, 0x00071b82, 0x306303fc, 0x01031821, 0x8c640400,
-       0x00071182, 0x304203fc, 0x01021021, 0x8c450800, 0x30e300ff, 0x00031880,
-       0x01031821, 0x00091602, 0x00021080, 0x01021021, 0x00c43026, 0x8c640c00,
-       0x8c431000, 0x00c53026, 0x00091382, 0x304203fc, 0x01021021, 0x8c451400,
-       0x312200ff, 0x00021080, 0x01021021, 0x00c43026, 0x00c33026, 0x00091982,
-       0x306303fc, 0x01031821, 0x8c641800, 0x8c431c00, 0x00c53026, 0x00c43026,
-       0x11400015, 0x00c33026, 0x000a1602, 0x00021080, 0x01021021, 0x8c432000,
-       0x000a1382, 0x304203fc, 0x01021021, 0x8c452400, 0x314200ff, 0x00021080,
-       0x01021021, 0x00c33026, 0x000a1982, 0x306303fc, 0x01031821, 0x8c642800,
-       0x8c432c00, 0x00c53026, 0x00c43026, 0x00c33026, 0x8f430070, 0x3c050800,
-       0x8ca43100, 0x2c820020, 0x10400008, 0x006b5823, 0x3c020800, 0x24423104,
-       0x00041880, 0x00621821, 0x24820001, 0xac6b0000, 0xaca23100, 0xaf860004,
-       0x03e00008, 0x24020001, 0x27bdffe8, 0xafbf0010, 0x8f460128, 0x8f840010,
-       0xaf460020, 0x8f450104, 0x8f420100, 0x24030800, 0xaf850008, 0xaf820014,
-       0xaf4301b8, 0x1080000a, 0x3c020800, 0x8c430034, 0x10600007, 0x30a22000,
-       0x10400005, 0x34a30100, 0x8f82000c, 0xaf830008, 0x24420001, 0xaf82000c,
-       0x3c020800, 0x8c4300c0, 0x10600006, 0x3c030800, 0x8c6200c4, 0x24040001,
-       0x24420001, 0x0a000fd5, 0xac6200c4, 0x8f820008, 0x3c030010, 0x00431024,
-       0x14400009, 0x3c02001f, 0x3c030800, 0x8c620020, 0x00002021, 0x24420001,
-       0x0e000c78, 0xac620020, 0x0a000fd5, 0x00402021, 0x3442ff00, 0x14c20009,
-       0x2403bfff, 0x3c030800, 0x8c620020, 0x24040001, 0x24420001, 0x0e000c78,
-       0xac620020, 0x0a000fd5, 0x00402021, 0x8f820014, 0x00431024, 0x14400006,
-       0x00000000, 0xaf400048, 0x0e0011a9, 0xaf400040, 0x0a000fd5, 0x00402021,
-       0x0e001563, 0x00000000, 0x00402021, 0x10800005, 0x3c024000, 0x8f430124,
-       0x3c026020, 0xac430014, 0x3c024000, 0xaf420138, 0x00000000, 0x8fbf0010,
-       0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010,
-       0x8f420140, 0xaf420020, 0x8f430148, 0x3c027000, 0x00621824, 0x3c023000,
-       0x10620021, 0x0043102b, 0x14400006, 0x3c024000, 0x3c022000, 0x10620009,
-       0x3c024000, 0x0a001040, 0x00000000, 0x10620045, 0x3c025000, 0x10620047,
-       0x3c024000, 0x0a001040, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8,
-       0x00431024, 0x1440fffd, 0x00000000, 0x8f420148, 0x24030002, 0xa083000b,
-       0x00021402, 0xa4820008, 0x8f430148, 0xa4830010, 0x8f420144, 0x3c031000,
-       0xac820024, 0xaf4301b8, 0x0a001040, 0x3c024000, 0x8f420148, 0x24030002,
-       0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003,
-       0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001027, 0x3c038000,
-       0x12020007, 0x00000000, 0x0a001034, 0x00000000, 0x0e00112c, 0x00000000,
-       0x0a001025, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000,
-       0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008,
-       0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8,
-       0x0a001040, 0x3c024000, 0x0000000d, 0x00000000, 0x240002bf, 0x0a001040,
-       0x3c024000, 0x0e001441, 0x00000000, 0x0a001040, 0x3c024000, 0x0e0015ea,
-       0x00000000, 0x3c024000, 0xaf420178, 0x00000000, 0x8fbf0018, 0x8fb10014,
-       0x8fb00010, 0x03e00008, 0x27bd0020, 0x24020800, 0x03e00008, 0xaf4201b8,
-       0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000,
-       0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000,
-       0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800,
-       0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001,
-       0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000,
-       0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c,
-       0x8e021980, 0x34420200, 0xae021980, 0x8f500000, 0x32020003, 0x1040fffd,
-       0x32020001, 0x10400004, 0x32020002, 0x0e000f92, 0x00000000, 0x32020002,
-       0x1040fff6, 0x00000000, 0x0e000fe0, 0x00000000, 0x0a001071, 0x00000000,
-       0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000,
-       0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000,
-       0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800,
-       0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001,
-       0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000,
-       0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c,
-       0x8e021980, 0x8fbf0014, 0x34420200, 0xae021980, 0x8fb00010, 0x03e00008,
-       0x27bd0018, 0x00804821, 0x30a5ffff, 0x30c6ffff, 0x30e7ffff, 0x3c038000,
-       0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
-       0x8f840004, 0x8f880014, 0xaf490180, 0xa745018c, 0xa746018e, 0xa7470188,
-       0x31028000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc,
-       0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff,
-       0x34427fff, 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104,
-       0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
-       0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000,
-       0x8f4201b8, 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008,
-       0xa083000b, 0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000,
-       0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
-       0x8f420148, 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148,
-       0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8,
-       0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002,
-       0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003,
-       0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001117, 0x3c038000,
-       0x12020007, 0x00000000, 0x0a001124, 0x00000000, 0x0e00112c, 0x00000000,
-       0x0a001115, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000,
-       0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008,
-       0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8,
-       0x0a001128, 0x8fbf0018, 0x0000000d, 0x00000000, 0x240002bf, 0x8fbf0018,
-       0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389,
-       0x1040000d, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880,
-       0x00a32821, 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025,
-       0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389,
-       0x1040000e, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880,
-       0x00a32821, 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827,
-       0x00832024, 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x9482000c,
-       0x24870014, 0x00021302, 0x00021080, 0x00824021, 0x00e8182b, 0x1060004f,
-       0x00000000, 0x90e30000, 0x2c620009, 0x10400047, 0x3c020800, 0x24425890,
-       0x00031880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000, 0x0a0011a4,
-       0x24e70001, 0x90e30001, 0x2402000a, 0x54620024, 0x01003821, 0x01071023,
-       0x2c42000a, 0x54400020, 0x01003821, 0x3c050800, 0x8ca26c98, 0x24e70002,
-       0x34420100, 0xaca26c98, 0x90e30000, 0x90e20001, 0x90e40002, 0x90e60003,
-       0x24e70004, 0x24a56c98, 0x00031e00, 0x00021400, 0x00621825, 0x00042200,
-       0x00641825, 0x00661825, 0xaca30004, 0x90e20000, 0x90e30001, 0x90e40002,
-       0x90e60003, 0x24e70004, 0x00021600, 0x00031c00, 0x00431025, 0x00042200,
-       0x00441025, 0x00461025, 0x0a0011a4, 0xaca20008, 0x90e30001, 0x24020004,
-       0x1062000e, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020003,
-       0x10620008, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020002,
-       0x14620003, 0x01001021, 0x00601021, 0x00e21021, 0x0a0011a4, 0x00403821,
-       0x90e20001, 0x0a0011a4, 0x00e23821, 0x01003821, 0x00e8102b, 0x5440ffb4,
-       0x90e30000, 0x03e00008, 0x24020001, 0x27bdff90, 0x3c030800, 0xafbf006c,
-       0xafbe0068, 0xafb70064, 0xafb60060, 0xafb5005c, 0xafb40058, 0xafb30054,
-       0xafb20050, 0xafb1004c, 0xafb00048, 0xac606c98, 0x93620023, 0x30420010,
-       0x1440027c, 0x24020001, 0x93420116, 0x93630005, 0x34424000, 0x30630001,
-       0x14600005, 0x0342b021, 0x0e0015e0, 0x00000000, 0x0a001436, 0x8fbf006c,
-       0x93420112, 0x8f430104, 0x3c040020, 0x34424000, 0x00641824, 0x10600012,
-       0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
-       0x00000000, 0x8f420128, 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1,
-       0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000, 0x0a0011f1, 0xa0a3000a,
-       0x8f420104, 0x3c030040, 0x00431024, 0x1040001d, 0x3c038000, 0x27450180,
-       0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000,
-       0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a3000a,
-       0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010, 0xa0a00012, 0xa0a00013,
-       0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x0e0015e0,
-       0xaf4201b8, 0x0a001436, 0x8fbf006c, 0x8f820000, 0x10400016, 0x00000000,
-       0x8f420104, 0x3c030001, 0x00431024, 0x10400011, 0x00000000, 0x8ca3000c,
-       0x8f620030, 0x1462022d, 0x24020001, 0x8ca30010, 0x8f62002c, 0x14620229,
-       0x24020001, 0x9763003a, 0x96c20000, 0x14430225, 0x24020001, 0x97630038,
-       0x96c20002, 0x14430221, 0x24020001, 0xaf400048, 0xaf400054, 0xaf400040,
-       0x8f740040, 0x8f650048, 0x00b43023, 0x04c10004, 0x00000000, 0x0000000d,
-       0x00000000, 0x240001af, 0x9742011a, 0x3052ffff, 0x12400004, 0x8ed30004,
-       0x02721021, 0x0a001228, 0x2451ffff, 0x02608821, 0x92d7000d, 0xa7a00020,
-       0xa3a0001a, 0xafa00028, 0x9362003f, 0x32e30004, 0x1060003a, 0x305000ff,
-       0x24040012, 0x16040006, 0x24020001, 0x3c040800, 0x8c830028, 0x24630001,
-       0x0a001328, 0xac830028, 0x8f620044, 0x16620010, 0x27a60010, 0x27450180,
-       0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020, 0xafb40028, 0xa3b00022,
-       0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
-       0x0a00130d, 0x00000000, 0x8f620044, 0x02621023, 0x0440001a, 0x02651023,
-       0x044100d9, 0x24020001, 0x3c020800, 0x8c4300d8, 0x10600004, 0x24020001,
-       0xa7a20020, 0x0a00125e, 0xafb40028, 0x2402001a, 0xa7a20020, 0x24020020,
-       0xafb40028, 0xa3b00022, 0xa3a40023, 0xa3a2001a, 0x27a60010, 0x27450180,
-       0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d,
-       0x00000000, 0x0a001328, 0x24020001, 0x0293f023, 0x1bc00016, 0x025e102a,
-       0x54400007, 0x32f700fe, 0x57d2000f, 0x027e9821, 0x32e20001, 0x5440000c,
-       0x027e9821, 0x32f700fe, 0x0240f021, 0x3c040800, 0x8c8300c8, 0x00009021,
-       0x24020001, 0xa7a20020, 0xafb40028, 0x24630001, 0x0a001282, 0xac8300c8,
-       0x025e1023, 0x0a001282, 0x3052ffff, 0x0000f021, 0x24a2ffff, 0x02221823,
-       0x1860001f, 0x0072102a, 0x54400019, 0x00a08821, 0x97a20020, 0x3c040800,
-       0x8c8300cc, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020, 0x02741026,
-       0x2c420001, 0xac8300cc, 0x2cc30001, 0x00431024, 0x1440000a, 0x02401821,
-       0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
-       0x00000000, 0x0a00130d, 0x00000000, 0x00a08821, 0x02431023, 0x3052ffff,
-       0x0a0012ae, 0x32f700f6, 0x02741023, 0x18400008, 0x97a20020, 0x3c040800,
-       0x8c8300d4, 0xafb30028, 0x34420400, 0x24630001, 0xa7a20020, 0xac8300d4,
-       0x32e20002, 0x1040001c, 0x32e20010, 0x8f620044, 0x1662000d, 0x27a60010,
-       0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020,
-       0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000,
-       0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020,
-       0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000,
-       0x54400003, 0x8ed50008, 0x0a001328, 0x24020001, 0x8f630054, 0x26a2ffff,
-       0x00431023, 0x18400011, 0x27a60010, 0x97a20020, 0x3c040800, 0x8c8300d0,
-       0x27450180, 0x3c078000, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020,
-       0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000, 0x0a00130d,
-       0x00000000, 0x32e20020, 0x10400011, 0x00000000, 0x96c20012, 0x0052102b,
-       0x10400008, 0x97a20020, 0x96d20012, 0x12400003, 0x02721021, 0x0a0012f2,
-       0x2451ffff, 0x02608821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004,
-       0xa7a20020, 0xa3a3001a, 0x8f420104, 0x3c030080, 0x00431024, 0x10400037,
-       0x3a03000a, 0x0e001151, 0x02c02021, 0x24030002, 0x1443002b, 0x3c030800,
-       0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001,
-       0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128,
-       0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, 0x90c4000a,
-       0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, 0x90c30012,
-       0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, 0x8cc20024,
-       0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, 0x3c031000,
-       0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a001436, 0x8fbf006c,
-       0x8c626c98, 0x30420100, 0x10400003, 0x24636c98, 0x8c620004, 0xaf62017c,
-       0x3a03000a, 0x2c630001, 0x3a02000c, 0x2c420001, 0x00621825, 0x14600003,
-       0x2402000e, 0x56020030, 0x00009021, 0x52400008, 0x96c4000e, 0x12400004,
-       0xa7b20040, 0x02721021, 0x0a001343, 0x2451ffff, 0x02608821, 0x96c4000e,
-       0x93630035, 0x8f62004c, 0x00642004, 0x00952021, 0x00821023, 0x18400015,
-       0x00000000, 0x8f620018, 0x02621023, 0x1c400015, 0x97a20020, 0x8f620018,
-       0x1662001c, 0x00000000, 0x8f62001c, 0x02a21023, 0x1c40000e, 0x97a20020,
-       0x8f62001c, 0x16a20015, 0x00000000, 0x8f620058, 0x00821023, 0x18400011,
-       0x97a20020, 0x0a001364, 0xafb10028, 0x8f620058, 0x00821023, 0x0441000b,
-       0x97a20020, 0xafb10028, 0xafb30034, 0xafb50038, 0xafa4003c, 0x34420020,
-       0x0a00136d, 0xa7a20020, 0x02809821, 0x02608821, 0x8f640058, 0x8f62004c,
-       0x02a21023, 0x18400009, 0x00000000, 0x8f620054, 0x02a21023, 0x1c400005,
-       0x97a20020, 0xafb10028, 0xafb50024, 0x0a001385, 0x34420040, 0x9742011a,
-       0x1440000c, 0x24020014, 0x8f620058, 0x14820009, 0x24020014, 0x8f63004c,
-       0x8f620054, 0x10620004, 0x97a20020, 0xafb10028, 0x34420080, 0xa7a20020,
-       0x24020014, 0x1202000a, 0x2a020015, 0x10400005, 0x2402000c, 0x12020006,
-       0x32e20001, 0x0a0013c6, 0x00000000, 0x24020016, 0x16020035, 0x32e20001,
-       0x8f620084, 0x24420001, 0x16a20031, 0x32e20001, 0x24020014, 0x12020021,
-       0x2a020015, 0x10400005, 0x2402000c, 0x12020008, 0x32e20001, 0x0a0013c6,
-       0x00000000, 0x24020016, 0x1202000c, 0x32e20001, 0x0a0013c6, 0x00000000,
-       0x97a30020, 0x2402000e, 0xafb10028, 0xa3b00022, 0xa3a20023, 0xafb50024,
-       0x34630054, 0x0a0013c5, 0xa7a30020, 0x97a20020, 0x93a4001a, 0x24030010,
-       0xafb10028, 0xa3b00022, 0xa3a30023, 0xafb50024, 0x3442005d, 0x34840002,
-       0xa7a20020, 0x0a0013c5, 0xa3a4001a, 0x97a20020, 0x24030012, 0xa3a30023,
-       0x93a3001a, 0xafb10028, 0xa3b00022, 0xafb50024, 0x3042fffe, 0x3442005c,
-       0x34630002, 0xa7a20020, 0xa3a3001a, 0x32e20001, 0x10400030, 0x2402000c,
-       0x12020013, 0x2a02000d, 0x10400005, 0x2402000a, 0x12020008, 0x97a20020,
-       0x0a0013f8, 0x32e20009, 0x2402000e, 0x1202001b, 0x32e20009, 0x0a0013f9,
-       0x0002102b, 0x93a4001a, 0x24030008, 0xafb10028, 0xa3b00022, 0xa3a30023,
-       0x0a0013f4, 0x34420013, 0x97a30020, 0x30620004, 0x14400005, 0x93a2001a,
-       0x3463001b, 0xa7a30020, 0x0a0013e7, 0x24030016, 0x3463001b, 0xa7a30020,
-       0x24030010, 0xafb10028, 0xa3b00022, 0xa3a30023, 0x34420002, 0x0a0013f7,
-       0xa3a2001a, 0x97a20020, 0x93a4001a, 0x24030010, 0xafb10028, 0xa3b00022,
-       0xa3a30023, 0x3442001b, 0x34840002, 0xa7a20020, 0xa3a4001a, 0x32e20009,
-       0x0002102b, 0x00021023, 0x30420007, 0x12400015, 0x34450003, 0x8f820018,
-       0x24030800, 0x27440180, 0x24420001, 0xaf820018, 0x24020004, 0xaf4301b8,
-       0xa4850008, 0xa082000b, 0x93430120, 0x00003021, 0x3c021000, 0xa492000e,
-       0xac950024, 0xac930028, 0x007e1821, 0xa483000c, 0xaf4201b8, 0x0a001413,
-       0x97a20020, 0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000,
-       0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000,
-       0x8fa30028, 0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002,
-       0xa0a2000b, 0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012,
-       0x93a20023, 0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024,
-       0x8fa30038, 0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8,
-       0x00c01021, 0x8fbf006c, 0x8fbe0068, 0x8fb70064, 0x8fb60060, 0x8fb5005c,
-       0x8fb40058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, 0x03e00008,
-       0x27bd0070, 0x8f470140, 0x8f460148, 0x3c028000, 0x00c24024, 0x00062c02,
-       0x30a300ff, 0x24020019, 0x106200e7, 0x27440180, 0x2862001a, 0x1040001f,
-       0x24020008, 0x106200be, 0x28620009, 0x1040000d, 0x24020001, 0x10620046,
-       0x28620002, 0x50400005, 0x24020006, 0x1060002e, 0x00a01821, 0x0a00155e,
-       0x00000000, 0x1062005b, 0x00a01821, 0x0a00155e, 0x00000000, 0x2402000b,
-       0x10620084, 0x2862000c, 0x10400005, 0x24020009, 0x106200bc, 0x00061c02,
-       0x0a00155e, 0x00000000, 0x2402000e, 0x106200b7, 0x00061c02, 0x0a00155e,
-       0x00000000, 0x28620021, 0x10400009, 0x2862001f, 0x104000c1, 0x2402001b,
-       0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02, 0x0a00155e, 0x00000000,
-       0x240200c2, 0x106200ca, 0x286200c3, 0x10400005, 0x24020080, 0x1062005a,
-       0x00a01821, 0x0a00155e, 0x00000000, 0x240200c9, 0x106200cd, 0x30c5ffff,
-       0x0a00155e, 0x00000000, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
-       0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a,
-       0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024,
-       0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808, 0x11000009, 0x00a01821,
-       0x3c020800, 0x24030002, 0xa0436c88, 0x24426c88, 0xac470008, 0x8f430144,
-       0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
-       0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b,
-       0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x3c026000,
-       0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800, 0x3c058000, 0x8f4201b8,
-       0x00451024, 0x1440fffd, 0x00000000, 0xac870000, 0x91026c88, 0x00002821,
-       0x10400002, 0x25076c88, 0x8ce50008, 0xac850004, 0xa4830008, 0x91036c88,
-       0x24020002, 0xa082000b, 0xa4860010, 0x34630001, 0xa083000a, 0x8f420144,
-       0xac820024, 0x91036c88, 0x10600002, 0x00001021, 0x8ce20004, 0xac820028,
-       0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006c88, 0x03e00008, 0xac400808,
-       0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xa082000b,
-       0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000, 0xa4820012, 0x03e00008,
-       0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02, 0x93620005, 0x30420004,
-       0x14400020, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020, 0x3c038000,
-       0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000,
-       0x34630001, 0x00e31825, 0x34420004, 0xa3620005, 0xaf430020, 0x93620005,
-       0x30420004, 0x14400003, 0x3c038000, 0x0000000d, 0x3c038000, 0x8f4201b8,
-       0x00431024, 0x1440fffd, 0x24020005, 0x3c031000, 0xac870000, 0xa082000b,
-       0xaf4301b8, 0x0a00150d, 0x00061c02, 0x0000000d, 0x03e00008, 0x00000000,
-       0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001,
-       0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a, 0xa083000b,
-       0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024, 0x03e00008,
-       0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002,
-       0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b, 0xa4860010,
-       0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x03e00008, 0xaf4301b8,
-       0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001,
-       0xa4830008, 0x24030002, 0xa082000a, 0x3c021000, 0xac870000, 0xac800004,
-       0xa083000b, 0xa4860010, 0xac800024, 0xac800028, 0x03e00008, 0xaf4201b8,
-       0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002,
-       0xac870000, 0xac800004, 0xa4830008, 0xa080000a, 0x0a001518, 0xa082000b,
-       0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002,
-       0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4401a4,
-       0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8, 0x0000000d, 0x03e00008,
-       0x00000000, 0x03e00008, 0x00000000, 0x8f420100, 0x3042003e, 0x14400011,
-       0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, 0x10400005, 0x00000000,
-       0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, 0xaf400054, 0xaf400040,
-       0x8f420100, 0x30423800, 0x54400001, 0xaf400044, 0x24020001, 0x03e00008,
-       0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002,
-       0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4501a4,
-       0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8, 0x3c029000, 0x34420001,
-       0x00822025, 0xaf440020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-       0x00000000, 0x03e00008, 0x00000000, 0x3c028000, 0x34420001, 0x00822025,
-       0x03e00008, 0xaf440020, 0x308600ff, 0x27450180, 0x3c038000, 0x8f4201b8,
-       0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040,
-       0x24030008, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000,
-       0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024,
-       0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008, 0xaf4201b8, 0x24020001,
-       0xacc40000, 0x03e00008, 0xa4e50000, 0x24020001, 0xaf400044, 0x03e00008,
-       0xaf400050, 0x00803021, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024,
-       0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1,
-       0xa4a20008, 0xaca30018, 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a,
-       0x94c20010, 0xa4a20010, 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013,
-       0x8cc30014, 0xaca30014, 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028,
-       0x8cc2002c, 0x3c031000, 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044,
-       0x03e00008, 0xaf400050, 0x27bdffe8, 0xafbf0010, 0x0e001047, 0x00000000,
-       0x00002021, 0x0e000c78, 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018,
-       0x8f460148, 0x27450180, 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8,
-       0x00431024, 0x1440fffd, 0x00000000, 0x8f440140, 0x00061202, 0x304200ff,
-       0x00061c02, 0xaca20004, 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b,
-       0xaca30024, 0x10e0000a, 0xaca40000, 0x28e20004, 0x14400005, 0x24020001,
-       0x24020005, 0x54e20005, 0xa0a0000a, 0x24020001, 0x0a001609, 0xa0a2000a,
-       0xa0a0000a, 0x3c021000, 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021,
-       0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000,
-       0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00161f, 0x00a01021,
-       0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa,
-       0x24a5ffff, 0x03e00008, 0x00000000, 0x00000000 }; 
+static u8 bnx2_RXP_b06FwText[] = {
+       0x1f, 0x8b, 0x08, 0x08, 0x07, 0x87, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x5d, 0x6c,
+       0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x71, 0x49, 0x91, 0xd4, 0x70, 0xb9,
+       0x62, 0x57, 0x12, 0x65, 0xed, 0x8a, 0x43, 0x71, 0x6d, 0x31, 0xce, 0x50,
+       0x58, 0xdb, 0x82, 0xb1, 0x48, 0xc7, 0xb3, 0xa4, 0xc8, 0x24, 0x02, 0x42,
+       0x1b, 0x42, 0xab, 0xa4, 0xa9, 0xc1, 0x90, 0x72, 0x91, 0x22, 0x2c, 0xa0,
+       0x1a, 0x79, 0xf0, 0x43, 0x10, 0x2f, 0x56, 0x3f, 0xa6, 0xd1, 0x8d, 0x96,
+       0xb6, 0x1c, 0x53, 0x08, 0x82, 0x82, 0xe5, 0x52, 0x52, 0x0b, 0x2c, 0xb4,
+       0x96, 0xed, 0x36, 0x7e, 0xa8, 0x23, 0x9a, 0x92, 0x8d, 0xa6, 0x68, 0x81,
+       0x22, 0xad, 0xd1, 0xf4, 0x4d, 0x95, 0x9a, 0x4a, 0x75, 0x5f, 0xd4, 0xa2,
+       0x48, 0xda, 0x46, 0xcd, 0xf4, 0xfb, 0xee, 0xcc, 0x88, 0xd4, 0x9a, 0xb2,
+       0x2c, 0x3b, 0x0d, 0x62, 0x74, 0x0e, 0x30, 0xd8, 0xb9, 0x7f, 0xe7, 0xef,
+       0x9e, 0x73, 0xee, 0x39, 0x77, 0x28, 0x7d, 0xa5, 0x43, 0xda, 0x25, 0x84,
+       0x4e, 0x3c, 0x99, 0xc3, 0xcf, 0x3c, 0xfd, 0xe0, 0xc3, 0x0f, 0xee, 0xc1,
+       0xeb, 0xb0, 0xa1, 0x6d, 0xd0, 0xa3, 0xfe, 0x18, 0x62, 0x88, 0x21, 0x86,
+       0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62,
+       0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21,
+       0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18,
+       0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88,
+       0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0xff, 0xef, 0x60, 0x88, 0x58,
+       0xfc, 0xed, 0x0c, 0x1f, 0x49, 0xe8, 0x85, 0xcb, 0x07, 0x3d, 0x5b, 0x12,
+       0x46, 0x61, 0x69, 0x66, 0xda, 0x16, 0x71, 0xeb, 0xbb, 0x33, 0x45, 0xf9,
+       0x1f, 0xbf, 0x94, 0x32, 0x85, 0xfd, 0xdb, 0x0b, 0x37, 0x9f, 0x7d, 0xf3,
+       0x91, 0xec, 0x8d, 0x05, 0x43, 0x12, 0x56, 0xe1, 0xe8, 0xb0, 0xb5, 0x4b,
+       0x12, 0x7d, 0x58, 0xf3, 0xdd, 0xc1, 0xcf, 0x59, 0xd2, 0x15, 0xe1, 0xba,
+       0xee, 0xbf, 0x39, 0x68, 0xc9, 0x2b, 0x8d, 0x94, 0x5c, 0x68, 0x6c, 0xdf,
+       0x24, 0x5d, 0xd9, 0x52, 0x09, 0xfd, 0x6e, 0x8a, 0xe3, 0x96, 0x94, 0xab,
+       0x2d, 0xe2, 0x2a, 0xba, 0x7d, 0x5a, 0x71, 0xfe, 0x3e, 0xcd, 0x9b, 0x7f,
+       0x9e, 0xff, 0x1e, 0x24, 0xa5, 0xcb, 0x7d, 0x68, 0xf7, 0xa1, 0xcd, 0xf7,
+       0x81, 0xf4, 0x94, 0x98, 0x72, 0xa4, 0x91, 0x90, 0xa3, 0xd5, 0x8c, 0xe8,
+       0x05, 0x71, 0xbd, 0xbc, 0x9d, 0x2e, 0xa3, 0x6f, 0xea, 0x00, 0xdb, 0x29,
+       0xe0, 0xf9, 0x0e, 0xd7, 0x59, 0x5e, 0x5e, 0x4a, 0xb7, 0xc6, 0x14, 0x0d,
+       0x8e, 0xb1, 0x0f, 0xbf, 0x58, 0x5f, 0xae, 0x76, 0x00, 0x6f, 0xd6, 0x71,
+       0x41, 0xdc, 0x73, 0x2c, 0xd0, 0xf6, 0xfd, 0xdf, 0x75, 0x32, 0xb2, 0xe2,
+       0x74, 0x81, 0xa7, 0x16, 0x69, 0xb5, 0xc5, 0xd2, 0x0b, 0xb6, 0xb5, 0x22,
+       0x6d, 0x1c, 0xeb, 0x34, 0x0a, 0xbe, 0x3f, 0x9d, 0x97, 0xae, 0xa0, 0x6f,
+       0xb7, 0xe2, 0x63, 0x72, 0x42, 0xc3, 0xbc, 0x57, 0x49, 0x0f, 0x3a, 0xe2,
+       0x3b, 0x7f, 0xf3, 0x52, 0xac, 0x6c, 0x97, 0xc9, 0x54, 0xf6, 0xa0, 0x1b,
+       0xd0, 0x74, 0x3d, 0x67, 0x2b, 0x70, 0x6a, 0xe0, 0x4f, 0xdb, 0x81, 0xf5,
+       0xee, 0x0a, 0x68, 0x1a, 0x85, 0xcd, 0x62, 0x6c, 0x66, 0x9f, 0xe8, 0x3b,
+       0x87, 0x93, 0xe1, 0x78, 0x97, 0x36, 0x32, 0x6f, 0x88, 0x6e, 0xff, 0x81,
+       0xe6, 0xd5, 0x7a, 0xe5, 0xd8, 0xbc, 0x8e, 0x77, 0x5d, 0xae, 0xe6, 0x4b,
+       0x9a, 0xdb, 0xa8, 0x68, 0xde, 0xd9, 0x59, 0xad, 0x78, 0xd6, 0x94, 0xa3,
+       0xb6, 0x7f, 0xe1, 0xb4, 0x73, 0x42, 0x1b, 0x39, 0x7b, 0x46, 0x1b, 0x3d,
+       0xfb, 0x86, 0x36, 0xde, 0xd8, 0xb2, 0x49, 0xda, 0xb3, 0xd0, 0x1e, 0x71,
+       0x90, 0xbf, 0x4f, 0x87, 0xba, 0xec, 0xa2, 0xde, 0x4a, 0xe4, 0x7d, 0x9f,
+       0xf3, 0x86, 0xe6, 0x55, 0x6d, 0x8b, 0xfb, 0xe6, 0xa6, 0x22, 0x1a, 0xed,
+       0x72, 0x74, 0xde, 0x94, 0x63, 0xd5, 0x94, 0x3c, 0x57, 0x2d, 0x29, 0x5a,
+       0x86, 0x5d, 0xd2, 0xbc, 0x06, 0xc7, 0x2b, 0xa0, 0x75, 0x42, 0xdb, 0x07,
+       0x9a, 0xde, 0x59, 0x29, 0x5d, 0x71, 0xe6, 0x40, 0xaf, 0x03, 0x78, 0xff,
+       0x58, 0x1b, 0x6d, 0xf4, 0x6a, 0xde, 0xc9, 0x9b, 0xe2, 0x39, 0x59, 0xeb,
+       0x4b, 0x62, 0xba, 0xb0, 0x01, 0xc8, 0x0c, 0xfd, 0x38, 0xd0, 0x49, 0xca,
+       0xf7, 0xf5, 0x82, 0xff, 0x2c, 0x74, 0x6f, 0x5d, 0xa1, 0xfc, 0x8d, 0x5e,
+       0x29, 0xcf, 0x53, 0xd7, 0xa6, 0x36, 0x52, 0xf5, 0x2f, 0x78, 0x8e, 0xf4,
+       0x19, 0xe2, 0xfb, 0x47, 0x9d, 0x81, 0xf4, 0x21, 0x39, 0x03, 0xdc, 0x75,
+       0xad, 0xd8, 0xa0, 0xae, 0xc1, 0xdf, 0x2d, 0x39, 0x02, 0xbd, 0x15, 0x9d,
+       0x5e, 0x99, 0xb4, 0xb2, 0x2e, 0xf6, 0x68, 0x53, 0x20, 0x57, 0x32, 0xb4,
+       0x17, 0xd2, 0xe7, 0xde, 0x67, 0xd3, 0x9e, 0xa1, 0xcb, 0x53, 0x2f, 0x3d,
+       0xdf, 0xb3, 0x38, 0xb4, 0x91, 0x32, 0x43, 0xff, 0xf2, 0x45, 0xcf, 0xf6,
+       0xb6, 0xb4, 0x48, 0x29, 0x6d, 0x48, 0x16, 0xfb, 0xb4, 0x43, 0x4e, 0x3b,
+       0x22, 0x87, 0x2a, 0xd0, 0x8d, 0x6d, 0x5a, 0x8b, 0x62, 0x67, 0xca, 0x32,
+       0x50, 0x32, 0x75, 0x74, 0x26, 0x49, 0x97, 0x3a, 0xd2, 0xe5, 0x7a, 0x9e,
+       0x7a, 0xa2, 0x3d, 0x7f, 0x28, 0x5d, 0x69, 0xab, 0xba, 0x5a, 0xd5, 0xd3,
+       0xf8, 0x2f, 0x5d, 0x4f, 0xd4, 0xc9, 0x72, 0x28, 0xb7, 0x03, 0xdc, 0x8f,
+       0x40, 0x5f, 0xe2, 0xea, 0xc3, 0x0f, 0xb1, 0x6f, 0x93, 0x51, 0xb0, 0xd3,
+       0x17, 0x61, 0x14, 0x7a, 0x61, 0x37, 0x64, 0x19, 0xa6, 0xee, 0xe0, 0xc3,
+       0x1f, 0x49, 0x5e, 0xf9, 0xd5, 0x90, 0x97, 0xfc, 0xdb, 0x32, 0x55, 0x49,
+       0x80, 0x06, 0x65, 0xd4, 0xe5, 0xbd, 0x7c, 0x64, 0x1b, 0x7b, 0x20, 0x5f,
+       0x5e, 0xa6, 0xbe, 0x45, 0x7f, 0xa2, 0xfd, 0xf3, 0x9d, 0xb2, 0xfe, 0xcc,
+       0xbf, 0xee, 0x7c, 0x92, 0xf6, 0x96, 0x7c, 0x27, 0xe4, 0x78, 0x35, 0xc9,
+       0x3d, 0xd4, 0x56, 0x54, 0x6c, 0x8a, 0x64, 0x14, 0xdd, 0x28, 0x74, 0x48,
+       0x51, 0xed, 0xf7, 0x5e, 0xd0, 0x43, 0x2c, 0xa8, 0xf2, 0xbd, 0xa0, 0x64,
+       0x9b, 0xb6, 0xed, 0xcc, 0x11, 0xc9, 0xc2, 0xbe, 0x45, 0x8e, 0xcc, 0x99,
+       0x32, 0x6d, 0xff, 0x63, 0xa7, 0xb4, 0x2f, 0xdf, 0x6f, 0xa8, 0xb8, 0xae,
+       0xf7, 0x6e, 0x90, 0x4d, 0xe0, 0x77, 0xf9, 0x7e, 0x5d, 0xe4, 0xa6, 0x59,
+       0xc8, 0x5a, 0x23, 0x08, 0xf6, 0x46, 0x81, 0xb1, 0x4c, 0x43, 0x2c, 0x93,
+       0x44, 0x8b, 0x4d, 0x7d, 0xf9, 0xfe, 0xf8, 0xf0, 0xdd, 0xf5, 0x75, 0x64,
+       0x9e, 0xb4, 0xa9, 0x2f, 0xc6, 0xa8, 0x12, 0xf4, 0xc1, 0xf8, 0x74, 0xbb,
+       0xae, 0x8a, 0xa1, 0xae, 0x46, 0xfe, 0xef, 0xed, 0xc2, 0xf5, 0xaa, 0xa2,
+       0x79, 0xce, 0xbb, 0xa1, 0x2f, 0xd8, 0x32, 0x02, 0x7f, 0x37, 0xec, 0x4f,
+       0xcb, 0x91, 0x54, 0x76, 0xc2, 0x95, 0xc0, 0xe6, 0xaf, 0xad, 0xb1, 0xf9,
+       0xd1, 0xbb, 0xc8, 0x75, 0x3c, 0x94, 0xcb, 0x0d, 0xe5, 0x1a, 0x85, 0x5c,
+       0x63, 0x90, 0x6b, 0xe5, 0x23, 0xc8, 0xb5, 0xf2, 0x91, 0xe5, 0xd2, 0xa4,
+       0xec, 0x3c, 0x08, 0x5a, 0xa6, 0xfc, 0xab, 0x13, 0xd8, 0xf2, 0xbf, 0x38,
+       0x9f, 0x14, 0x19, 0x7c, 0x7f, 0x70, 0xd8, 0x16, 0xef, 0x5b, 0xe0, 0xd5,
+       0x71, 0x40, 0x8b, 0xef, 0xef, 0x97, 0xe1, 0x6e, 0xfe, 0x38, 0x8b, 0x7d,
+       0x5d, 0xcf, 0x1f, 0x29, 0x87, 0x3e, 0x7c, 0xef, 0xfe, 0xa8, 0x6b, 0x1f,
+       0x55, 0x0e, 0xc6, 0x9c, 0x4f, 0x35, 0x9d, 0xab, 0x1f, 0x56, 0x86, 0xf5,
+       0x63, 0xca, 0x2f, 0x4f, 0x86, 0xc7, 0x64, 0x72, 0x33, 0xed, 0xa9, 0xa4,
+       0x8d, 0x0c, 0x92, 0xef, 0xb5, 0xfc, 0x4a, 0x26, 0xe0, 0x0d, 0x39, 0xd1,
+       0xd2, 0x46, 0x39, 0xb2, 0x60, 0x49, 0x69, 0xe9, 0x4e, 0x71, 0x57, 0x03,
+       0x6f, 0xb4, 0x47, 0xf6, 0x7d, 0xd2, 0x7c, 0x2a, 0xc8, 0x2b, 0x2e, 0x54,
+       0x91, 0x83, 0x56, 0x13, 0x72, 0xd9, 0x48, 0xcb, 0x9b, 0x83, 0x87, 0xe5,
+       0xf3, 0xd5, 0x24, 0xe8, 0x31, 0x9f, 0x2c, 0xe7, 0x10, 0x17, 0xb5, 0xb2,
+       0x63, 0x08, 0x79, 0xaf, 0xd9, 0x9c, 0x13, 0xc4, 0x96, 0x72, 0x10, 0x83,
+       0x5d, 0x6f, 0x50, 0xe5, 0x14, 0x90, 0x4f, 0x64, 0x0c, 0xb1, 0xb7, 0x66,
+       0xb3, 0xcd, 0xfe, 0xa0, 0xef, 0xb3, 0x95, 0x5e, 0xad, 0xc8, 0xbc, 0x64,
+       0xf0, 0xa6, 0x4c, 0x3b, 0x41, 0xdf, 0xe7, 0x2a, 0xa3, 0x9b, 0x98, 0x1f,
+       0x1a, 0x05, 0xc9, 0x94, 0x9d, 0xf7, 0x7c, 0xd7, 0xba, 0x7d, 0xcd, 0xfa,
+       0x78, 0xb2, 0x13, 0x81, 0xce, 0x45, 0xfb, 0xaa, 0xad, 0xf7, 0xb6, 0x4a,
+       0x09, 0x27, 0x5d, 0xd6, 0x1a, 0x47, 0xe7, 0xbe, 0x4a, 0x79, 0x5b, 0xab,
+       0xdc, 0x34, 0x80, 0x3f, 0x6d, 0x68, 0x62, 0x1e, 0xaa, 0x94, 0xbb, 0xd9,
+       0xa6, 0xbe, 0x74, 0x4d, 0x12, 0xa3, 0x15, 0x5f, 0xae, 0x3a, 0x41, 0xee,
+       0x63, 0x68, 0x7a, 0x6f, 0x5b, 0xb8, 0x56, 0xd7, 0x76, 0x39, 0x97, 0x44,
+       0x3a, 0x0e, 0x55, 0xc4, 0x2a, 0x56, 0x76, 0x39, 0x6f, 0x4b, 0xb9, 0xa7,
+       0x6d, 0x75, 0x5d, 0x8a, 0xeb, 0x76, 0x0e, 0xaf, 0x9d, 0xbb, 0xcb, 0xb9,
+       0x28, 0xe5, 0x2d, 0x6d, 0xab, 0xb4, 0xd2, 0x58, 0xdb, 0x17, 0xac, 0xe5,
+       0xf8, 0x66, 0x71, 0xbb, 0x39, 0x47, 0xef, 0x6d, 0xbf, 0x45, 0x43, 0x32,
+       0xc5, 0x4a, 0xb9, 0xa7, 0x7d, 0x15, 0xaf, 0x4d, 0xbc, 0xde, 0x1a, 0xbc,
+       0xc4, 0xd9, 0xbe, 0x8a, 0x33, 0x07, 0x9c, 0x43, 0xab, 0x38, 0x39, 0x7e,
+       0x58, 0x8a, 0x38, 0xd3, 0x5a, 0x0a, 0x32, 0xbc, 0x54, 0xc9, 0x48, 0x79,
+       0x28, 0x01, 0xdd, 0xf7, 0x1f, 0xfc, 0x9a, 0xaa, 0x43, 0xcc, 0x61, 0x0f,
+       0xba, 0x32, 0x55, 0x5e, 0x87, 0xd8, 0x08, 0xdb, 0xf8, 0x5a, 0x5d, 0x86,
+       0x17, 0xeb, 0xa6, 0x1c, 0x6f, 0x70, 0xbf, 0x98, 0xe3, 0x05, 0x75, 0xc6,
+       0x85, 0x46, 0x4e, 0xdb, 0x87, 0xbd, 0x66, 0x9d, 0xb0, 0xaf, 0x61, 0x6a,
+       0xa3, 0x3c, 0x1f, 0x80, 0x97, 0x76, 0x7e, 0xac, 0x41, 0xdb, 0x79, 0x03,
+       0xb6, 0x41, 0xce, 0xa3, 0x9c, 0xbd, 0x95, 0xb9, 0x53, 0x66, 0xd1, 0x51,
+       0x75, 0x88, 0x56, 0xcb, 0x77, 0x20, 0x07, 0x4d, 0xa0, 0xd6, 0x80, 0xcd,
+       0xdb, 0x78, 0x6f, 0x70, 0xde, 0x32, 0xe6, 0x6d, 0xe0, 0x3c, 0xec, 0xcd,
+       0x25, 0xe5, 0x0f, 0xa6, 0xcd, 0xf1, 0x77, 0xb1, 0xc7, 0x68, 0xd7, 0x59,
+       0x57, 0x58, 0x02, 0x5f, 0xc1, 0x3e, 0xa2, 0x6e, 0x48, 0xed, 0x60, 0x7e,
+       0x8f, 0xb9, 0x19, 0xcc, 0xcd, 0x66, 0x18, 0xcf, 0x3d, 0xfb, 0x99, 0x0e,
+       0xe9, 0x42, 0xbb, 0xce, 0x35, 0xd9, 0x0c, 0x72, 0x5b, 0xdf, 0xcb, 0xb7,
+       0xc9, 0x4a, 0xca, 0xbf, 0x60, 0xd8, 0xd1, 0xdc, 0x08, 0x6f, 0xf3, 0x5c,
+       0xe6, 0xc5, 0xc4, 0xbd, 0x21, 0xcc, 0x83, 0xc7, 0xc5, 0x6d, 0xfc, 0x49,
+       0xb7, 0x74, 0xb9, 0xf8, 0x8d, 0xe6, 0x4c, 0x6f, 0x0e, 0x6a, 0x2e, 0xbe,
+       0xb7, 0x50, 0x3e, 0x17, 0xe7, 0xa1, 0x56, 0xac, 0x66, 0x26, 0x59, 0x1f,
+       0x15, 0xeb, 0x6c, 0xef, 0x85, 0x3f, 0x04, 0x75, 0xd7, 0x85, 0x5b, 0xbe,
+       0x70, 0x19, 0x7a, 0x4b, 0x43, 0x6f, 0x29, 0x39, 0xdf, 0x60, 0x9d, 0xe6,
+       0x42, 0x5f, 0x19, 0xf1, 0x1a, 0xe3, 0x58, 0x2b, 0x87, 0x81, 0x03, 0x3a,
+       0x17, 0x47, 0x2f, 0x64, 0x65, 0xca, 0xda, 0x1d, 0xf1, 0x00, 0x5c, 0x88,
+       0x1f, 0x85, 0x36, 0xf4, 0xf1, 0x1d, 0x9a, 0x53, 0xff, 0x86, 0x7f, 0x94,
+       0xed, 0x09, 0xbd, 0x30, 0xd6, 0xd4, 0xbf, 0x6e, 0xfc, 0xa1, 0x1c, 0x68,
+       0x33, 0x06, 0x31, 0xfe, 0xe8, 0xa8, 0xf3, 0x18, 0x8b, 0x48, 0xd7, 0x92,
+       0x23, 0x4b, 0x23, 0xdc, 0x37, 0x8b, 0xf1, 0xa7, 0x5c, 0xe7, 0x9e, 0x29,
+       0x5c, 0xc0, 0x19, 0xad, 0xf1, 0xfd, 0x11, 0x87, 0x6b, 0x7c, 0x99, 0x70,
+       0x3a, 0xc4, 0x48, 0x96, 0xb4, 0xc7, 0x07, 0x11, 0x7b, 0x1e, 0xe0, 0x3e,
+       0x32, 0x06, 0x6d, 0x17, 0xb0, 0xea, 0xb4, 0x3c, 0x3c, 0xc8, 0x75, 0xa0,
+       0xdd, 0x2a, 0x7a, 0x92, 0x34, 0xf3, 0x21, 0x4f, 0x43, 0xdd, 0x81, 0xbe,
+       0x06, 0xac, 0x40, 0x7f, 0x9f, 0xe9, 0x5e, 0xd5, 0x1f, 0xd7, 0x35, 0xf3,
+       0xcb, 0x18, 0x96, 0x90, 0x81, 0x33, 0x1b, 0x65, 0xe7, 0xa2, 0x25, 0xf6,
+       0x99, 0x55, 0xfe, 0x76, 0x9e, 0x5b, 0xcb, 0x5f, 0xf4, 0x7f, 0x15, 0x5c,
+       0xd0, 0xc5, 0x8e, 0xfa, 0x1e, 0x4b, 0x05, 0xb8, 0xa3, 0xf6, 0x7b, 0xe1,
+       0x5e, 0xf1, 0xfd, 0x99, 0x70, 0x4f, 0xb0, 0x07, 0x88, 0x95, 0xe7, 0x6f,
+       0xc5, 0xa9, 0x0c, 0xf6, 0x06, 0xb6, 0xa7, 0xe2, 0x11, 0xe3, 0x18, 0xed,
+       0xbb, 0x63, 0xd2, 0x2c, 0xb0, 0x8e, 0xe6, 0x3e, 0xc9, 0x44, 0xb9, 0x22,
+       0xa5, 0xad, 0x85, 0x67, 0x7d, 0xd8, 0xcf, 0xa4, 0xa5, 0x6c, 0xaf, 0x63,
+       0xaf, 0x97, 0x37, 0xa0, 0x1b, 0x8c, 0xc1, 0x26, 0xf5, 0x42, 0x42, 0x8a,
+       0x8d, 0x44, 0xc2, 0x3c, 0x31, 0xf0, 0x23, 0xcf, 0x48, 0x24, 0xf4, 0x13,
+       0x81, 0x9d, 0x4d, 0xd6, 0x6f, 0x20, 0x56, 0x6a, 0x72, 0x74, 0xe8, 0x86,
+       0xcf, 0x1a, 0xd8, 0xdb, 0x0b, 0x9b, 0x1b, 0x82, 0xcf, 0x80, 0x8f, 0x72,
+       0xa3, 0xa3, 0x37, 0xe0, 0xed, 0x2b, 0x11, 0x8f, 0xa6, 0x8e, 0xdc, 0xd3,
+       0xcb, 0xfb, 0xbe, 0x51, 0xd8, 0x90, 0x98, 0xce, 0x8f, 0x6f, 0xd1, 0xcf,
+       0xed, 0xdf, 0x62, 0x9c, 0x2b, 0x6d, 0x01, 0x3e, 0xdd, 0xcb, 0xe3, 0xf7,
+       0x9c, 0xc8, 0x44, 0x15, 0x3a, 0xdf, 0x03, 0x3d, 0x59, 0xf0, 0xc5, 0x3d,
+       0xa6, 0xca, 0xd1, 0xf5, 0x3d, 0x2f, 0x6e, 0x0a, 0x70, 0xf0, 0xfd, 0x27,
+       0x7e, 0x70, 0x86, 0x5e, 0x0e, 0xfb, 0x7e, 0x3f, 0xdc, 0x87, 0x5f, 0x45,
+       0xb9, 0x78, 0x5e, 0x44, 0xb2, 0xad, 0x3d, 0x37, 0xb2, 0xe3, 0x25, 0x9c,
+       0x33, 0xa7, 0x1d, 0xdf, 0x7f, 0x07, 0xcf, 0x35, 0xa7, 0xd9, 0x46, 0xde,
+       0x7f, 0xf6, 0x31, 0x07, 0xf8, 0x2c, 0xce, 0xbd, 0xd1, 0xa6, 0xb3, 0xff,
+       0x5e, 0xcf, 0xbd, 0x7b, 0x3f, 0xfb, 0xc9, 0xf3, 0x1d, 0x7d, 0xef, 0x03,
+       0xce, 0xfe, 0x0f, 0x5c, 0x77, 0x0f, 0x3e, 0x1b, 0xd8, 0x6d, 0xb1, 0xd1,
+       0x1c, 0x5f, 0xee, 0xd5, 0x7f, 0x7f, 0xad, 0xfb, 0x76, 0xff, 0xb5, 0xbb,
+       0x6f, 0xf7, 0xdf, 0xcd, 0xdd, 0xbf, 0x18, 0xff, 0xcd, 0x01, 0x0f, 0x7d,
+       0x70, 0xad, 0xff, 0xae, 0xe7, 0x93, 0xd4, 0xf7, 0xf3, 0x3d, 0xe5, 0xa1,
+       0xce, 0x30, 0x1f, 0x52, 0xe7, 0xf5, 0x17, 0xa7, 0x6d, 0xef, 0x7e, 0x53,
+       0x4a, 0xb9, 0x16, 0xc9, 0xe6, 0x6a, 0xb2, 0x43, 0x8e, 0x3b, 0x22, 0x4b,
+       0xaa, 0x16, 0x31, 0x51, 0x8b, 0x0f, 0xa0, 0x3e, 0x0b, 0xf4, 0xba, 0xa4,
+       0xf4, 0xf2, 0x02, 0x78, 0x89, 0xf0, 0x74, 0xdd, 0x05, 0x0f, 0x71, 0x10,
+       0x17, 0xf1, 0x0c, 0xe2, 0x7c, 0xb7, 0xd7, 0xc1, 0x85, 0x73, 0xea, 0x25,
+       0xd4, 0x64, 0xb6, 0xde, 0xa3, 0x07, 0x67, 0xb2, 0x5b, 0x96, 0xdd, 0xe9,
+       0xeb, 0xf2, 0x05, 0x9e, 0x59, 0x0a, 0xae, 0xce, 0x21, 0x56, 0x0f, 0x8d,
+       0x85, 0x75, 0xd2, 0xdc, 0x41, 0xcf, 0x8e, 0xee, 0x49, 0x78, 0x47, 0x92,
+       0x90, 0x92, 0x9a, 0xb5, 0x04, 0x1d, 0x68, 0x72, 0x0d, 0x67, 0xd0, 0xd5,
+       0xb9, 0x76, 0xe0, 0x45, 0xee, 0x77, 0x20, 0xbb, 0x57, 0xb4, 0x7e, 0xab,
+       0x55, 0x6b, 0x87, 0x2f, 0x65, 0xc4, 0x55, 0x6d, 0x9e, 0xd3, 0xa7, 0x66,
+       0x16, 0x2b, 0xc8, 0x03, 0x6d, 0x9c, 0xaf, 0x79, 0xbc, 0xd7, 0x49, 0x43,
+       0x93, 0x2b, 0x73, 0xba, 0xfc, 0xd3, 0x9c, 0x21, 0xff, 0x8c, 0x3a, 0xf4,
+       0x9a, 0x7d, 0x6a, 0xe6, 0xb4, 0x2d, 0xf7, 0x81, 0xd5, 0xf0, 0x0e, 0x4f,
+       0x76, 0x9a, 0x42, 0x5b, 0x1d, 0x48, 0xff, 0x8e, 0x20, 0xff, 0xc1, 0x9a,
+       0x2b, 0x73, 0xa4, 0xb5, 0x76, 0x8d, 0xf4, 0x22, 0x1f, 0x83, 0x5d, 0x0f,
+       0x30, 0x27, 0xe2, 0x7c, 0xd4, 0xab, 0x03, 0xd6, 0x3e, 0xc5, 0x5b, 0x42,
+       0x16, 0xeb, 0x9c, 0x6f, 0x82, 0xb7, 0x2e, 0x9c, 0x31, 0x59, 0x6b, 0x52,
+       0xfe, 0xb0, 0x5b, 0xe5, 0xaa, 0x1a, 0xfb, 0x0d, 0xb5, 0xc7, 0xef, 0xef,
+       0xe7, 0xde, 0x1b, 0x32, 0x95, 0x62, 0x9b, 0x63, 0x59, 0xd4, 0x9c, 0xc4,
+       0x97, 0xdd, 0xeb, 0x0a, 0x79, 0x0e, 0xde, 0xaf, 0x08, 0x65, 0xdb, 0x6d,
+       0x5d, 0x97, 0xd7, 0x7d, 0xf7, 0x00, 0xe5, 0x89, 0x72, 0x8b, 0x39, 0x9f,
+       0xb1, 0xd8, 0x28, 0xcc, 0xc0, 0x8e, 0xbf, 0x2a, 0xdf, 0x6f, 0x1c, 0x92,
+       0xef, 0x35, 0x26, 0xe5, 0xcf, 0x1a, 0x5f, 0x96, 0x3f, 0x6d, 0x1c, 0x94,
+       0xd7, 0x1b, 0x07, 0xe4, 0xb5, 0xc6, 0x84, 0xbc, 0xda, 0xd8, 0x0f, 0x1b,
+       0x1f, 0x87, 0x8d, 0x9f, 0x9a, 0x99, 0xac, 0xf7, 0xcb, 0xd4, 0x49, 0xc4,
+       0x20, 0xe7, 0x1b, 0xba, 0xba, 0xe3, 0xb3, 0xe9, 0xe7, 0x2d, 0x32, 0xad,
+       0xee, 0xaf, 0x34, 0xe4, 0x89, 0x2d, 0xbc, 0x2b, 0x7c, 0xc5, 0x33, 0x2e,
+       0x87, 0xf1, 0xe8, 0xe1, 0x94, 0xb4, 0x03, 0xbf, 0xca, 0x4b, 0x4d, 0x9e,
+       0xdb, 0x62, 0x86, 0xf7, 0x9c, 0x87, 0x24, 0xc9, 0xfb, 0xb0, 0x9c, 0x67,
+       0xa0, 0xde, 0x5e, 0xd7, 0x27, 0x73, 0xb4, 0x65, 0xe8, 0xc6, 0x95, 0x43,
+       0xb0, 0x53, 0xc3, 0x7e, 0xcb, 0xa5, 0x1e, 0x16, 0x97, 0x28, 0xf7, 0x46,
+       0x59, 0x5c, 0xa0, 0x6f, 0xff, 0x1b, 0x64, 0x6c, 0x97, 0xda, 0x82, 0x89,
+       0xb9, 0x6e, 0x98, 0xab, 0x6c, 0xa7, 0x3d, 0x00, 0x1f, 0xf1, 0x7e, 0x10,
+       0x4e, 0xab, 0x09, 0x27, 0xf1, 0x24, 0x54, 0x0c, 0x08, 0x70, 0x5b, 0x52,
+       0x5b, 0x4a, 0xca, 0xc2, 0x42, 0x0f, 0x9e, 0x94, 0x2c, 0xd4, 0x6d, 0x3c,
+       0x39, 0x3c, 0x43, 0x78, 0xd2, 0xb0, 0x53, 0xca, 0xc8, 0xd8, 0x12, 0xc9,
+       0x88, 0x78, 0x5c, 0xed, 0x0d, 0x6b, 0x2a, 0xf2, 0xa3, 0x85, 0xfc, 0x74,
+       0x87, 0x7d, 0x1d, 0x52, 0xab, 0x38, 0x32, 0x55, 0xfd, 0x94, 0x3e, 0xa5,
+       0x74, 0x07, 0xfc, 0x95, 0x21, 0xb4, 0xef, 0x0f, 0xdb, 0x8f, 0xca, 0xf4,
+       0xbc, 0xc8, 0xca, 0xcb, 0x03, 0x7a, 0x51, 0xb5, 0xf7, 0xa2, 0xad, 0xa3,
+       0x9d, 0x0d, 0xdb, 0xcc, 0x8f, 0x0e, 0xe0, 0x71, 0xd5, 0xf3, 0xf5, 0xea,
+       0xb8, 0x3c, 0x55, 0xed, 0x77, 0x5e, 0x87, 0xcd, 0xbd, 0x65, 0x46, 0xf7,
+       0xd2, 0x04, 0x24, 0x79, 0xf6, 0x56, 0x75, 0xf7, 0xf1, 0x04, 0xe2, 0xad,
+       0x9b, 0x34, 0xe5, 0x6f, 0x4f, 0x64, 0xad, 0xa7, 0xf5, 0x5c, 0x52, 0xda,
+       0x7d, 0xff, 0x71, 0x3b, 0x3b, 0x3b, 0xa9, 0x77, 0xca, 0xdf, 0xbf, 0x98,
+       0x91, 0x85, 0xb3, 0x5b, 0x65, 0xa1, 0x06, 0x99, 0x1a, 0xbf, 0x8e, 0x7d,
+       0x35, 0xe5, 0xea, 0x9e, 0x47, 0xb1, 0x27, 0x8c, 0x5d, 0x49, 0xe4, 0x6c,
+       0x1b, 0xc4, 0xec, 0x25, 0x5d, 0x49, 0x98, 0x85, 0x9c, 0x1c, 0x81, 0xdf,
+       0x4f, 0xdb, 0xb9, 0x1e, 0x69, 0xc7, 0x7b, 0x7d, 0x04, 0x7c, 0x5b, 0x32,
+       0xd5, 0x6b, 0xc9, 0x99, 0xc1, 0x68, 0xff, 0xb6, 0x62, 0x6e, 0x46, 0x16,
+       0xcf, 0x66, 0xf0, 0x9b, 0x83, 0xfd, 0xec, 0x94, 0x57, 0x6a, 0xfd, 0xb2,
+       0x54, 0xdb, 0x2a, 0x8b, 0xb5, 0xe6, 0x7d, 0xe8, 0xec, 0x09, 0xe2, 0x1d,
+       0xf1, 0xf4, 0x5b, 0x53, 0xfa, 0x56, 0x71, 0xcd, 0x7e, 0xeb, 0x29, 0xfd,
+       0x1f, 0xe4, 0x31, 0x33, 0xa0, 0xa9, 0x17, 0x7e, 0xa4, 0xee, 0x84, 0x26,
+       0x79, 0xf6, 0x2a, 0xbc, 0x4f, 0x26, 0x49, 0xfb, 0xf5, 0xc6, 0x07, 0xd1,
+       0x59, 0xcb, 0xcf, 0x9d, 0x68, 0x52, 0x06, 0xe2, 0xec, 0xbf, 0x71, 0x52,
+       0xef, 0x95, 0xe5, 0x6d, 0x0f, 0x58, 0x4f, 0xea, 0xad, 0x88, 0x01, 0x3f,
+       0x97, 0x9f, 0xee, 0xd9, 0x24, 0x3f, 0xfc, 0xcd, 0xec, 0xa9, 0x6f, 0x22,
+       0xd9, 0xbf, 0xb2, 0xa7, 0x83, 0x71, 0x01, 0xef, 0xec, 0xcf, 0xde, 0x70,
+       0x75, 0xea, 0xe1, 0x2f, 0xa0, 0x87, 0xec, 0x9c, 0xba, 0x9b, 0x56, 0x3c,
+       0x90, 0x3e, 0xf5, 0x52, 0x06, 0x6f, 0x18, 0xab, 0xf7, 0x03, 0x57, 0x59,
+       0xe9, 0xf9, 0x09, 0x27, 0x7b, 0x03, 0xe9, 0xb0, 0xbf, 0x68, 0xf7, 0xa7,
+       0x77, 0xea, 0x3b, 0x64, 0x32, 0xfd, 0x80, 0xf5, 0xb4, 0x6c, 0x21, 0xce,
+       0xd9, 0x05, 0xc1, 0xda, 0x79, 0xe2, 0xfb, 0x2b, 0xe0, 0x0b, 0x70, 0x28,
+       0xff, 0x51, 0x38, 0x77, 0x59, 0x5f, 0xd7, 0x79, 0xc6, 0x63, 0x0c, 0x71,
+       0xe1, 0xe2, 0x10, 0x65, 0x40, 0x82, 0x95, 0xca, 0xa6, 0x5d, 0xfd, 0xc3,
+       0xc8, 0x47, 0xfc, 0xfd, 0x56, 0x51, 0x27, 0x0f, 0xe7, 0xc0, 0xcb, 0x4f,
+       0xc0, 0x7f, 0x3f, 0x70, 0xa2, 0xf6, 0x48, 0x47, 0x74, 0xff, 0x4e, 0xd1,
+       0x7d, 0xad, 0x21, 0xe6, 0x2a, 0x5d, 0xf4, 0xd5, 0x75, 0xc8, 0xdd, 0x07,
+       0x7b, 0xb5, 0xf0, 0xcb, 0xbd, 0xe9, 0x0c, 0xf7, 0x98, 0xeb, 0x22, 0xba,
+       0x11, 0xbf, 0x5c, 0x73, 0x27, 0x1e, 0xee, 0x75, 0x3e, 0xea, 0xd4, 0x03,
+       0x09, 0x79, 0xf7, 0x44, 0xb4, 0x37, 0x07, 0x64, 0xba, 0x0a, 0xdd, 0xed,
+       0xea, 0x0f, 0xfc, 0x27, 0x1d, 0xf1, 0x40, 0xde, 0xff, 0x06, 0xbc, 0x07,
+       0xb8, 0x5b, 0x0b, 0xcd, 0xba, 0xc3, 0x58, 0x3d, 0xa0, 0x31, 0xb6, 0x0e,
+       0x4f, 0x57, 0xf6, 0x44, 0xbe, 0x98, 0x84, 0x5f, 0xed, 0xb6, 0x9e, 0x10,
+       0xd6, 0x63, 0xc4, 0x9b, 0x94, 0x1f, 0xbe, 0x0c, 0x1e, 0x92, 0xf4, 0x93,
+       0x7f, 0x5f, 0xe3, 0x27, 0x1c, 0xdb, 0x2a, 0x35, 0xd4, 0xd4, 0x5e, 0xde,
+       0x94, 0x69, 0x25, 0x03, 0xda, 0x35, 0xfa, 0x77, 0x29, 0xf4, 0xef, 0x47,
+       0x80, 0xa3, 0x5d, 0x8c, 0x47, 0x1f, 0xc7, 0x59, 0x9d, 0xcd, 0x2c, 0xeb,
+       0xcc, 0x03, 0x76, 0x4b, 0x51, 0xdd, 0x4f, 0xdf, 0x8b, 0xee, 0xa2, 0xd8,
+       0x94, 0x96, 0x8b, 0x95, 0x28, 0x2e, 0xa5, 0x71, 0x9e, 0xb4, 0xcb, 0xa5,
+       0xb9, 0x28, 0xe6, 0xb5, 0xcb, 0x12, 0xf2, 0x9a, 0x95, 0x97, 0x2c, 0x8c,
+       0x25, 0xe5, 0xe2, 0x5c, 0x12, 0x31, 0xab, 0x47, 0x56, 0xe6, 0x7a, 0x30,
+       0x96, 0xc2, 0xba, 0x14, 0xe6, 0xdb, 0xb2, 0x52, 0xb1, 0x81, 0x27, 0x87,
+       0x76, 0x0e, 0xed, 0x21, 0xb9, 0xa4, 0xbe, 0x17, 0x30, 0x2f, 0x18, 0x42,
+       0xdc, 0x62, 0x5e, 0x30, 0x82, 0x18, 0x32, 0x81, 0x27, 0x8a, 0x5d, 0xa7,
+       0x66, 0xa6, 0x2a, 0xbc, 0x73, 0x84, 0x0e, 0xac, 0x53, 0x33, 0xd3, 0xb6,
+       0x89, 0xba, 0xed, 0x1b, 0xda, 0x54, 0x83, 0x72, 0x41, 0xb7, 0x43, 0x1d,
+       0xa2, 0x3f, 0x4a, 0x9b, 0xe4, 0x79, 0x67, 0x20, 0xc6, 0x77, 0x01, 0x9f,
+       0x23, 0xfa, 0x6f, 0xd0, 0x17, 0xa0, 0xc3, 0x27, 0xba, 0xe4, 0xd2, 0xcb,
+       0x8c, 0x35, 0xae, 0xbc, 0x7a, 0x96, 0x3a, 0x2c, 0xf6, 0xac, 0xea, 0x90,
+       0x63, 0x0f, 0xe1, 0x8c, 0xd8, 0x0f, 0x7b, 0x32, 0x33, 0x87, 0x90, 0xcb,
+       0x7c, 0x1b, 0xf6, 0x59, 0x66, 0xcd, 0x9d, 0x0e, 0x6a, 0x84, 0x20, 0x06,
+       0xa0, 0xdd, 0x47, 0x5d, 0xb1, 0xdd, 0x07, 0xbb, 0xe3, 0x58, 0x9f, 0x1a,
+       0x5b, 0x04, 0x8e, 0x60, 0x8c, 0xed, 0xcd, 0xb2, 0xa8, 0xc6, 0x0e, 0xaa,
+       0xb1, 0xb2, 0xb2, 0x0f, 0x8e, 0x1d, 0x52, 0xb1, 0xe9, 0x7c, 0x23, 0xea,
+       0xdf, 0x88, 0x58, 0xc2, 0x7e, 0xf6, 0xe5, 0x61, 0xeb, 0x7b, 0x71, 0xae,
+       0x15, 0x64, 0xa9, 0x81, 0x3a, 0x30, 0xff, 0x7b, 0x98, 0xcb, 0x3d, 0xc8,
+       0x9e, 0x2a, 0xe9, 0xe4, 0xf1, 0x20, 0xce, 0x83, 0xfd, 0x21, 0xad, 0xb6,
+       0x90, 0xaf, 0x03, 0x61, 0xbb, 0x25, 0xa4, 0x4d, 0x3c, 0x36, 0x70, 0x1c,
+       0xc3, 0x5a, 0x17, 0x38, 0x18, 0x63, 0x11, 0x23, 0x52, 0x29, 0xe8, 0x82,
+       0x34, 0xdb, 0xa4, 0xac, 0xde, 0xf7, 0xc3, 0x76, 0xb9, 0x16, 0x3a, 0xb4,
+       0xa2, 0x75, 0xa5, 0x70, 0xcf, 0x53, 0xea, 0x9c, 0xd1, 0x93, 0x9b, 0xc3,
+       0x9c, 0x10, 0x7a, 0x45, 0x9c, 0xd5, 0x93, 0x8c, 0x37, 0xef, 0x84, 0x76,
+       0xda, 0x8b, 0xbe, 0x87, 0x44, 0xef, 0x65, 0xdf, 0x51, 0xe0, 0x61, 0xed,
+       0x3c, 0x0c, 0x99, 0xd9, 0xe6, 0xfa, 0x6c, 0xd3, 0xfa, 0xc4, 0x3a, 0xeb,
+       0x3b, 0x9a, 0xfa, 0x32, 0x52, 0x9b, 0xef, 0x52, 0xf1, 0xf2, 0x7c, 0x18,
+       0x2f, 0x17, 0x6b, 0x94, 0x05, 0x7e, 0x96, 0x7f, 0x5b, 0xe9, 0xa2, 0x76,
+       0x36, 0xb0, 0xf5, 0xa5, 0x93, 0x3c, 0x17, 0x57, 0xe7, 0xd5, 0xd4, 0xbc,
+       0xdf, 0x06, 0xff, 0xba, 0x1c, 0x55, 0x32, 0x70, 0x3e, 0xe6, 0xd5, 0x02,
+       0xbf, 0x31, 0x6c, 0xce, 0xa1, 0x8f, 0x44, 0x6b, 0x38, 0xff, 0xe7, 0xa8,
+       0x55, 0xbe, 0xac, 0xd6, 0xac, 0xfa, 0x0c, 0xf9, 0x71, 0x42, 0x9e, 0x7b,
+       0xc0, 0x5f, 0x67, 0x28, 0x43, 0x7b, 0x28, 0x03, 0xf1, 0xfd, 0x27, 0x70,
+       0xb7, 0x61, 0x1e, 0x79, 0xdd, 0x86, 0x3e, 0xbe, 0xff, 0x17, 0xfa, 0x76,
+       0x23, 0xff, 0x23, 0x6f, 0x89, 0x26, 0xde, 0xfe, 0x03, 0x63, 0x3d, 0x4a,
+       0xb7, 0x35, 0xd4, 0x26, 0x53, 0xbc, 0xef, 0x48, 0xe1, 0x1c, 0x38, 0xb9,
+       0x4d, 0xd1, 0xad, 0x9d, 0xbd, 0x86, 0xf1, 0x5e, 0xac, 0x89, 0xda, 0xcd,
+       0xb2, 0xe9, 0x58, 0xfb, 0x53, 0x25, 0xcf, 0x62, 0xed, 0x4e, 0xf2, 0x6f,
+       0x5b, 0x23, 0x3b, 0xe5, 0x26, 0x4f, 0xe4, 0xa7, 0x1f, 0x4f, 0x2b, 0x72,
+       0x21, 0xd8, 0x6d, 0xd2, 0x90, 0xd1, 0x7c, 0x9a, 0xdf, 0xf9, 0x12, 0xbc,
+       0x17, 0x1d, 0x19, 0xe4, 0x9e, 0xa1, 0xdd, 0x60, 0x4e, 0x47, 0x7f, 0x4b,
+       0xc8, 0x31, 0xd4, 0x24, 0xe5, 0x85, 0x8c, 0x56, 0x3c, 0x99, 0x45, 0x16,
+       0xad, 0xbe, 0xd5, 0xc9, 0x8b, 0x4b, 0xb6, 0x7c, 0x1b, 0x7e, 0x7a, 0xb2,
+       0x9e, 0x4d, 0x7f, 0x13, 0xf9, 0xc1, 0x91, 0x25, 0xe6, 0x13, 0x3d, 0x29,
+       0x65, 0x9b, 0xf3, 0x9a, 0x6c, 0x60, 0x4c, 0x9b, 0x47, 0x7e, 0x6a, 0xdd,
+       0x2d, 0x47, 0x82, 0x9f, 0x57, 0xd7, 0xc6, 0x0c, 0xca, 0xb1, 0x36, 0x66,
+       0x10, 0x0f, 0x63, 0xc6, 0x4e, 0xec, 0x13, 0x63, 0x06, 0xf6, 0xff, 0x24,
+       0x63, 0x86, 0x8d, 0x75, 0x8c, 0x19, 0x79, 0x59, 0xac, 0x32, 0x66, 0xec,
+       0x45, 0x9b, 0x31, 0xa3, 0x80, 0x76, 0x10, 0x2f, 0x16, 0x55, 0xbc, 0xc8,
+       0x5a, 0xcb, 0xc2, 0x38, 0x81, 0x3c, 0xb1, 0x8a, 0x3c, 0xb1, 0x8a, 0x3c,
+       0xb1, 0x8a, 0x3c, 0xb1, 0x8a, 0x3c, 0x11, 0xb6, 0xfe, 0x5a, 0x15, 0x79,
+       0x22, 0xfc, 0xe7, 0x3c, 0x72, 0x92, 0xa0, 0xa6, 0x38, 0x8c, 0x9a, 0xc2,
+       0xd5, 0xc6, 0xaa, 0xe3, 0xda, 0xbe, 0x2a, 0x6a, 0x43, 0xf5, 0x9d, 0x58,
+       0x1f, 0xda, 0x80, 0xba, 0xa8, 0xe6, 0x6c, 0x01, 0x5f, 0xd7, 0xe0, 0x1b,
+       0xd4, 0xd3, 0x56, 0x99, 0xca, 0xed, 0x80, 0x7c, 0xd8, 0x7f, 0xfb, 0xfb,
+       0xe8, 0x43, 0x3e, 0x9f, 0x63, 0x0d, 0xc2, 0x78, 0xb5, 0x0f, 0x6d, 0x1d,
+       0x6d, 0xec, 0xe9, 0x04, 0x7c, 0xc4, 0x7e, 0x90, 0xf9, 0x62, 0x7a, 0x41,
+       0x9e, 0xdc, 0x1c, 0xd8, 0xf4, 0x6f, 0x31, 0x27, 0x5e, 0xd3, 0xde, 0x88,
+       0x39, 0xf0, 0x17, 0xd8, 0x97, 0x5a, 0x03, 0x5c, 0xba, 0xfd, 0xe7, 0xc4,
+       0xd1, 0xb7, 0xe1, 0xd6, 0x1c, 0xda, 0xd5, 0xf7, 0x9a, 0xfa, 0xb2, 0x98,
+       0xcf, 0xef, 0xe2, 0x3b, 0xf0, 0xfb, 0x16, 0x7e, 0x61, 0x77, 0xf6, 0x05,
+       0xcc, 0xe9, 0xc3, 0xef, 0x77, 0x9a, 0xe6, 0x42, 0x0a, 0xfb, 0x2f, 0xd1,
+       0x77, 0x31, 0xa4, 0xc1, 0x6f, 0x89, 0x5f, 0x6a, 0xe2, 0xe3, 0x07, 0xe8,
+       0xfb, 0x6b, 0xf4, 0xf9, 0xfe, 0xdb, 0x4e, 0xd4, 0x27, 0xa5, 0x96, 0x70,
+       0xef, 0x46, 0xd5, 0xde, 0x69, 0xca, 0xe6, 0x8f, 0x2c, 0xe9, 0xaa, 0x0e,
+       0x7a, 0xae, 0x8e, 0xea, 0x08, 0x71, 0xbe, 0xbc, 0x10, 0xd4, 0xad, 0xc7,
+       0x51, 0x73, 0x16, 0xab, 0xb4, 0x91, 0x1c, 0xfa, 0x6d, 0x9c, 0x69, 0x32,
+       0x69, 0xdc, 0xaa, 0x63, 0x13, 0x89, 0xc9, 0x7a, 0x9b, 0x48, 0x37, 0x69,
+       0x32, 0x4f, 0x22, 0x8e, 0xd9, 0x99, 0xe2, 0xc2, 0xec, 0x8c, 0x07, 0x9c,
+       0x63, 0x75, 0xae, 0xe5, 0x3c, 0x93, 0xf7, 0x63, 0x4d, 0x74, 0x69, 0x13,
+       0x60, 0x06, 0xf4, 0x9e, 0xab, 0x93, 0x7e, 0x40, 0xb3, 0xac, 0x68, 0xda,
+       0xe8, 0x8f, 0xea, 0xc7, 0x1c, 0x6a, 0x5d, 0x99, 0x64, 0xed, 0x5c, 0x0c,
+       0x69, 0xba, 0x75, 0x49, 0x24, 0x0a, 0xcd, 0xf8, 0x82, 0x8c, 0xf3, 0xb9,
+       0xfa, 0xec, 0x8c, 0xfe, 0x42, 0x36, 0xc7, 0x3b, 0x11, 0xd7, 0x9a, 0x9d,
+       0x69, 0x1d, 0x48, 0xc8, 0x8f, 0x91, 0xbb, 0x1d, 0x53, 0x34, 0x66, 0x67,
+       0x8c, 0x17, 0x02, 0x5b, 0x0c, 0xe8, 0xe0, 0x3c, 0xc9, 0xb7, 0x43, 0x4e,
+       0xd2, 0x62, 0x4d, 0x1d, 0x8c, 0x4f, 0xaa, 0x7a, 0xd1, 0x94, 0x2b, 0x15,
+       0x45, 0x3b, 0xac, 0xdb, 0xc9, 0xc3, 0xec, 0x8c, 0xfc, 0xd1, 0x2d, 0x1e,
+       0xd6, 0x91, 0x87, 0x78, 0x49, 0x27, 0xd0, 0x5b, 0xc0, 0x7f, 0x12, 0xf5,
+       0x7b, 0x54, 0xab, 0xfb, 0xfe, 0x8a, 0x93, 0x43, 0x5c, 0xe0, 0x3e, 0xb6,
+       0xa8, 0x3c, 0xd7, 0x73, 0x32, 0xbc, 0xef, 0x9b, 0xe3, 0xdf, 0x39, 0x78,
+       0xf9, 0x01, 0xd4, 0x4d, 0xbc, 0x1b, 0xa4, 0x7f, 0xe1, 0xf7, 0x36, 0xff,
+       0xe2, 0x7c, 0xf6, 0x93, 0xe7, 0x81, 0xf4, 0x55, 0xf0, 0xe7, 0xe5, 0xd1,
+       0x87, 0x58, 0x51, 0x6c, 0x44, 0xb8, 0x78, 0xc7, 0xce, 0x39, 0x2a, 0xff,
+       0x6e, 0xf2, 0xd1, 0x96, 0xf0, 0xdc, 0xa5, 0x8e, 0xc8, 0x27, 0xf9, 0xe9,
+       0x84, 0x4d, 0x90, 0x17, 0xce, 0x8f, 0xee, 0x25, 0xd8, 0xfe, 0xb8, 0x36,
+       0x12, 0xdd, 0xa9, 0x7d, 0x9c, 0x3d, 0x8f, 0x74, 0x76, 0x37, 0x7e, 0x88,
+       0x83, 0xb4, 0x23, 0xbe, 0x22, 0x9e, 0x88, 0x8f, 0xfc, 0x44, 0xbc, 0x28,
+       0x1b, 0x5d, 0x97, 0x9f, 0x60, 0x5d, 0xc0, 0x4f, 0x69, 0x21, 0x0d, 0x9d,
+       0x90, 0xa7, 0x11, 0x6d, 0xa4, 0xba, 0xde, 0x1d, 0xc7, 0x0f, 0x5c, 0xc6,
+       0xd5, 0xb1, 0x06, 0xef, 0xa1, 0x48, 0x97, 0x7f, 0x3b, 0xb2, 0xa4, 0x8d,
+       0x34, 0xf8, 0x9d, 0xa9, 0xae, 0xb9, 0x8d, 0x88, 0xde, 0x5a, 0x9d, 0x46,
+       0xbf, 0xbc, 0x2b, 0xff, 0x0c, 0xf6, 0xa9, 0x3b, 0xf8, 0xbb, 0x14, 0x55,
+       0x47, 0xb1, 0x6f, 0xb9, 0xd5, 0x73, 0xa2, 0xbf, 0xd3, 0xd9, 0x1f, 0xe6,
+       0x43, 0x51, 0x6d, 0x1c, 0xd5, 0x59, 0xea, 0x9e, 0x7d, 0xaf, 0xe7, 0x68,
+       0xc8, 0x4f, 0x99, 0x33, 0x05, 0x3a, 0x08, 0xf1, 0xde, 0x91, 0xcf, 0x91,
+       0x26, 0x3e, 0x47, 0xc1, 0xe7, 0x3e, 0xf0, 0x39, 0x76, 0x8b, 0xcf, 0x5b,
+       0xb6, 0x97, 0x29, 0xc3, 0xf6, 0x46, 0xd6, 0xb5, 0xbd, 0x55, 0x3a, 0xab,
+       0x73, 0x83, 0xfb, 0x9a, 0x91, 0x86, 0x2f, 0xc7, 0x9d, 0x8f, 0x53, 0x37,
+       0xb7, 0xcb, 0x99, 0x85, 0xbb, 0xd5, 0xb7, 0x11, 0xaf, 0x2a, 0x77, 0x94,
+       0x4b, 0xf5, 0x80, 0x9f, 0x1f, 0x2f, 0xb1, 0x3d, 0x12, 0xea, 0x8a, 0x3a,
+       0xcb, 0x3a, 0x25, 0xb9, 0x1b, 0x2f, 0xbf, 0xf8, 0x9c, 0x76, 0xa5, 0x12,
+       0x9d, 0x4f, 0x5a, 0x78, 0xc6, 0xae, 0xe5, 0x29, 0xfa, 0x6e, 0x32, 0x66,
+       0x45, 0xf7, 0x67, 0x22, 0xfc, 0xfe, 0xc0, 0xef, 0x75, 0x6b, 0xbf, 0x13,
+       0xf0, 0x7c, 0x8a, 0x78, 0xd7, 0x53, 0x3c, 0x9f, 0xc6, 0x9c, 0x66, 0x19,
+       0x5c, 0xd8, 0xa4, 0x9e, 0xe4, 0x98, 0xe7, 0xd0, 0x2f, 0x4c, 0xd0, 0x0c,
+       0xee, 0xdd, 0x6a, 0x4b, 0xbe, 0x5c, 0x74, 0x36, 0x06, 0xe7, 0x28, 0x64,
+       0xba, 0x6c, 0xf1, 0xfe, 0x0a, 0x31, 0x8c, 0x67, 0x83, 0xb2, 0xb5, 0x16,
+       0xf5, 0x5c, 0x39, 0xd0, 0x0e, 0x1d, 0xb3, 0xdd, 0xd6, 0xcb, 0xfb, 0x0a,
+       0xca, 0xbc, 0xa0, 0xf6, 0x21, 0xd2, 0x71, 0xf4, 0x7d, 0xae, 0x55, 0x96,
+       0xc3, 0xbb, 0xad, 0xc5, 0x8a, 0xef, 0xbf, 0x83, 0x3c, 0xfc, 0x34, 0x74,
+       0x5f, 0xae, 0xff, 0xcc, 0x5f, 0x4e, 0xf1, 0x6f, 0xa5, 0x22, 0x9b, 0xd8,
+       0xd1, 0xcb, 0x7b, 0x20, 0xf8, 0x96, 0x1c, 0xaf, 0x87, 0x65, 0xbf, 0x70,
+       0x9c, 0x7d, 0xff, 0x0d, 0xbe, 0x7d, 0xff, 0xf4, 0xaa, 0x9d, 0x02, 0xfe,
+       0x17, 0x33, 0xe1, 0x9b, 0xdd, 0x90, 0x58, 0x00, 0x00, 0x00 };
 
 static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 };
 static u32 bnx2_RXP_b06FwRodata[(0x28/4) + 1] = {
@@ -1943,387 +1057,264 @@ static u32 bnx2_RXP_b06FwRodata[(0x28/4) + 1] = {
 static u32 bnx2_RXP_b06FwBss[(0x13a4/4) + 1] = { 0x0 };
 static u32 bnx2_RXP_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
 
-static u32 bnx2_rv2p_proc1[] = {
-       0x00000008, 0xac000001, 0x0000000c, 0x2f800001, 0x00000010, 0x213f0004,
-       0x00000010, 0x20bf002c, 0x00000010, 0x203f0143, 0x00000018, 0x8000fffd,
-       0x00000010, 0xb1b8b017, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000,
-       0x00000000, 0x2c380000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000,
-       0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x00000008, 0x02000002,
-       0x00000010, 0x91de0000, 0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08,
-       0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000008, 0x2d800150,
-       0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000010, 0x2c620002,
-       0x00000018, 0x80000012, 0x0000000b, 0x2fdf0002, 0x0000000c, 0x1f800002,
-       0x00000000, 0x2c070000, 0x00000018, 0x8000ffe6, 0x00000008, 0x02000002,
-       0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08, 0x00000008, 0x2c8000b0,
-       0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108,
-       0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000018, 0x80000004,
-       0x0000000c, 0x1f800002, 0x00000000, 0x00000000, 0x00000018, 0x8000ffd9,
-       0x0000000c, 0x29800002, 0x0000000c, 0x1f800002, 0x00000000, 0x2adf0000,
-       0x00000008, 0x2a000005, 0x00000018, 0x8000ffd4, 0x00000008, 0x02240030,
-       0x00000018, 0x00040000, 0x00000018, 0x80000015, 0x00000018, 0x80000017,
-       0x00000018, 0x8000001b, 0x00000018, 0x8000004c, 0x00000018, 0x8000008c,
-       0x00000018, 0x8000000f, 0x00000018, 0x8000000e, 0x00000018, 0x8000000d,
-       0x00000018, 0x8000000c, 0x00000018, 0x800000c2, 0x00000018, 0x8000000a,
-       0x00000018, 0x80000009, 0x00000018, 0x80000008, 0x00000018, 0x800000fd,
-       0x00000018, 0x80000006, 0x00000018, 0x80000005, 0x00000018, 0x800000ff,
-       0x00000018, 0x80000104, 0x00000018, 0x80000002, 0x00000018, 0x80000098,
-       0x00000018, 0x80000000, 0x0000000c, 0x1f800001, 0x00000000, 0x00000000,
-       0x00000018, 0x8000ffba, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001,
-       0x0000000c, 0x1f800001, 0x00000008, 0x2a000002, 0x00000018, 0x8000ffb5,
-       0x00000010, 0xb1a0b012, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000,
-       0x00000008, 0x2c800000, 0x00000008, 0x2d000000, 0x00000010, 0x91d40000,
-       0x00000008, 0x2d80011c, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
-       0x0000000f, 0x47600008, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000,
-       0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
-       0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000018, 0x80000013,
-       0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002, 0x00000008, 0x2c800000,
-       0x00000008, 0x2d000000, 0x00000010, 0x91d40000, 0x00000008, 0x2d80011c,
-       0x0000000f, 0x060e0001, 0x00000010, 0x001f0000, 0x00000000, 0x0f580000,
-       0x00000010, 0x91de0000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
-       0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000000, 0x02620000,
-       0x0000000b, 0x2fdf0002, 0x00000000, 0x309a0000, 0x00000000, 0x31040000,
-       0x00000000, 0x0c961800, 0x00000009, 0x0c99ffff, 0x00000004, 0xcc993400,
-       0x00000010, 0xb1963202, 0x00000008, 0x0f800000, 0x0000000c, 0x29800001,
-       0x00000010, 0x00220002, 0x0000000c, 0x29520001, 0x0000000c, 0x29520000,
-       0x00000008, 0x22000001, 0x0000000c, 0x1f800001, 0x00000000, 0x2adf0000,
-       0x00000008, 0x2a000003, 0x00000018, 0x8000ff83, 0x00000010, 0xb1a0b01d,
-       0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0,
-       0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150,
-       0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000,
-       0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000000, 0x00000000,
-       0x00000010, 0x91de0000, 0x0000000f, 0x47600008, 0x00000000, 0x060e0000,
-       0x00000010, 0x001f0000, 0x00000000, 0x0f580000, 0x00000010, 0x91de0000,
-       0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, 0x00000000, 0x0b670000,
-       0x00000000, 0x0d620000, 0x00000000, 0x0ce71800, 0x00000009, 0x0c99ffff,
-       0x00000004, 0xcc993400, 0x00000010, 0xb1963220, 0x00000008, 0x0f800000,
-       0x00000018, 0x8000001e, 0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002,
-       0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000010, 0x91d40000,
-       0x00000008, 0x2d80012c, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000,
-       0x00000000, 0x0f580000, 0x00000010, 0x91de0000, 0x00000000, 0x0a640000,
-       0x00000000, 0x0ae50000, 0x00000000, 0x0b670000, 0x00000000, 0x0d620000,
-       0x00000000, 0x02630000, 0x0000000f, 0x47620010, 0x00000000, 0x0ce71800,
-       0x0000000b, 0x2fdf0002, 0x00000000, 0x311a0000, 0x00000000, 0x31840000,
-       0x0000000b, 0xc20000ff, 0x00000002, 0x42040000, 0x00000001, 0x31620800,
-       0x0000000f, 0x020e0010, 0x00000002, 0x31620800, 0x00000009, 0x0c99ffff,
-       0x00000004, 0xcc993400, 0x00000010, 0xb1963202, 0x00000008, 0x0f800000,
-       0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x0000000c, 0x61420006,
-       0x00000008, 0x22000008, 0x00000000, 0x2adf0000, 0x00000008, 0x2a000004,
-       0x00000018, 0x8000ff42, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
-       0x00000010, 0x91a0b008, 0x00000010, 0x91d40000, 0x0000000c, 0x31620018,
-       0x00000008, 0x2d800001, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
-       0x00000008, 0xac000001, 0x00000018, 0x8000000e, 0x00000000, 0x0380b000,
-       0x0000000b, 0x2fdf0002, 0x00000000, 0x2c004000, 0x00000010, 0x91d40000,
-       0x00000008, 0x2d800101, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
-       0x0000000c, 0x31620018, 0x00000008, 0x2d800001, 0x00000000, 0x00000000,
-       0x00000010, 0x91de0000, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c000e00,
-       0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000008, 0x2a000007,
-       0x00000018, 0x8000ff27, 0x00000010, 0xb1a0b016, 0x0000000b, 0x2fdf0002,
-       0x00000000, 0x03d80000, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0,
-       0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150,
-       0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000,
-       0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000008, 0x07000001,
-       0x00000010, 0xb5de1c00, 0x00000010, 0x2c620002, 0x00000018, 0x8000000a,
-       0x0000000b, 0x2fdf0002, 0x00000000, 0x2c070000, 0x0000000c, 0x1f800001,
-       0x00000010, 0x91de0000, 0x00000018, 0x8000ff11, 0x00000008, 0x2c8000b0,
-       0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108,
-       0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000010, 0x91de0000,
-       0x00000000, 0x2adf0000, 0x00000008, 0x2a00000a, 0x00000018, 0x8000ff07,
-       0x00000000, 0x82265600, 0x0000000f, 0x47220008, 0x00000009, 0x070e000f,
-       0x00000008, 0x070e0008, 0x00000008, 0x02800001, 0x00000007, 0x02851c00,
-       0x00000008, 0x82850001, 0x00000000, 0x02840a00, 0x00000007, 0x42851c00,
-       0x00000003, 0xc3aa5200, 0x00000000, 0x03b10e00, 0x00000010, 0x001f0000,
-       0x0000000f, 0x0f280007, 0x00000007, 0x4b071c00, 0x00000000, 0x00000000,
-       0x0000000f, 0x0a960003, 0x00000000, 0x0a955c00, 0x00000000, 0x4a005a00,
-       0x00000000, 0x0c960a00, 0x00000009, 0x0c99ffff, 0x00000008, 0x0d00ffff,
-       0x00000010, 0xb1963202, 0x00000008, 0x0f800005, 0x00000010, 0x00220020,
-       0x00000000, 0x02a70000, 0x00000010, 0xb1850002, 0x00000008, 0x82850200,
-       0x00000000, 0x02000000, 0x00000000, 0x03a60000, 0x00000018, 0x8000004e,
-       0x00000000, 0x072b0000, 0x00000001, 0x878c1c00, 0x00000000, 0x870e1e00,
-       0x00000000, 0x860c1e00, 0x00000000, 0x03061e00, 0x00000010, 0xb18e0003,
-       0x00000018, 0x80000047, 0x00000018, 0x8000fffa, 0x00000010, 0x918c0003,
-       0x00000010, 0xb1870002, 0x00000018, 0x80000043, 0x00000010, 0x91d40000,
-       0x0000000c, 0x29800001, 0x00000000, 0x2a860000, 0x00000000, 0x230c0000,
-       0x00000000, 0x2b070000, 0x00000010, 0xb187000e, 0x00000008, 0x2a000008,
-       0x00000018, 0x8000003b, 0x00000010, 0x91d40000, 0x00000000, 0x28d18c00,
-       0x00000000, 0x2a860000, 0x00000000, 0x230c0000, 0x00000000, 0x2b070000,
-       0x00000018, 0x8000fff8, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001,
-       0x00000000, 0x2aab0000, 0x00000000, 0xa3265600, 0x00000000, 0x2b000000,
-       0x0000000c, 0x1f800001, 0x00000008, 0x2a000008, 0x00000018, 0x8000fec8,
-       0x00000010, 0x91d40000, 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001,
-       0x00000008, 0x2a000009, 0x00000018, 0x8000fec3, 0x00000010, 0x91d40000,
-       0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000000, 0x29420000,
-       0x00000008, 0x2a000002, 0x00000018, 0x8000febd, 0x00000018, 0x8000febc,
-       0x00000010, 0xb1bcb016, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000,
-       0x00000000, 0x2c3c0000, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
-       0x00000010, 0x91d40000, 0x00000008, 0x2d800150, 0x00000000, 0x00000000,
-       0x00000010, 0x205f0000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000,
-       0x00000008, 0x2d800108, 0x00000008, 0x07000001, 0x00000010, 0xb5de1c00,
-       0x00000010, 0x2c620002, 0x00000018, 0x8000000a, 0x0000000b, 0x2fdf0002,
-       0x00000000, 0x2c070000, 0x0000000c, 0x1f800000, 0x00000010, 0x91de0000,
-       0x00000018, 0x8000fea6, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
-       0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x0000000c, 0x29800000,
-       0x0000000c, 0x1f800000, 0x00000010, 0x91de0000, 0x00000000, 0x2adf0000,
-       0x00000008, 0x2a000006, 0x00000018, 0x8000fe9c, 0x00000008, 0x03050004,
-       0x00000006, 0x83040c00, 0x00000008, 0x02850200, 0x00000000, 0x86050c00,
-       0x00000001, 0x860c0e00, 0x00000008, 0x02040004, 0x00000000, 0x02041800,
-       0x00000000, 0x83871800, 0x00000018, 0x00020000 };
+static u8 bnx2_rv2p_proc1[] = {
+       0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x56, 0xcf, 0x6b,
+       0x13, 0x51, 0x10, 0x9e, 0xec, 0x6e, 0xb2, 0xdb, 0x74, 0xbb, 0x1b, 0x2b,
+       0xda, 0xa0, 0xb1, 0x8d, 0x51, 0x6a, 0x7f, 0xa4, 0xb4, 0x11, 0x0f, 0x82,
+       0x42, 0x25, 0x3d, 0x04, 0x54, 0x44, 0x7a, 0x28, 0x22, 0x82, 0x36, 0x8a,
+       0xfe, 0x1b, 0xa1, 0x3f, 0xd2, 0x4b, 0x10, 0x7a, 0xb0, 0x58, 0xf1, 0x50,
+       0x10, 0x2a, 0x68, 0x0f, 0xc9, 0xa1, 0x20, 0x52, 0x11, 0xda, 0x8b, 0x07,
+       0x2f, 0x42, 0x0f, 0x7a, 0x69, 0xbd, 0xa8, 0xff, 0x82, 0x08, 0x4d, 0x7c,
+       0x6f, 0x66, 0x9e, 0xee, 0x6e, 0xb2, 0x4d, 0x15, 0xc1, 0x85, 0xf6, 0xe3,
+       0xbd, 0x9d, 0x79, 0x33, 0xf3, 0xcd, 0x37, 0xfb, 0x62, 0x01, 0x40, 0x04,
+       0x60, 0xcd, 0x46, 0x2c, 0x8d, 0x26, 0x04, 0x1a, 0x30, 0x7e, 0x52, 0x62,
+       0x16, 0xde, 0xa6, 0x25, 0x4e, 0x44, 0xc6, 0xd3, 0x49, 0x81, 0x7b, 0x0d,
+       0x28, 0xc9, 0x75, 0x4f, 0xf5, 0x55, 0xad, 0x53, 0xa0, 0x06, 0xbb, 0xa3,
+       0x80, 0xcf, 0x47, 0x9d, 0xf0, 0x7c, 0xd6, 0x42, 0x2c, 0x31, 0xc2, 0x48,
+       0x02, 0x61, 0x7b, 0x51, 0xae, 0xad, 0x48, 0x69, 0xc4, 0x42, 0x3f, 0xd0,
+       0x68, 0x7f, 0x67, 0xd1, 0x15, 0xff, 0x53, 0xf0, 0x39, 0x2f, 0xd7, 0x56,
+       0x7c, 0x0e, 0xed, 0xaa, 0xec, 0x2f, 0xfe, 0xd0, 0xfe, 0xba, 0xf0, 0x03,
+       0x7e, 0x94, 0x5f, 0x02, 0xcf, 0x29, 0x66, 0x65, 0x5e, 0xdd, 0x22, 0xa0,
+       0xca, 0xc7, 0x46, 0x2c, 0xf5, 0x91, 0xb5, 0x89, 0xef, 0xbf, 0x8a, 0xbc,
+       0x55, 0xdc, 0x76, 0xf1, 0x82, 0xf9, 0x06, 0xe3, 0x26, 0x91, 0x1f, 0x28,
+       0xf9, 0xe3, 0x00, 0xc8, 0xfd, 0x4f, 0x8d, 0x5f, 0xfb, 0x83, 0xfe, 0xf7,
+       0xbb, 0x43, 0xf2, 0xbc, 0x28, 0xc0, 0x90, 0xb4, 0xdb, 0xe6, 0x7c, 0xc6,
+       0xe0, 0xb4, 0x96, 0xc4, 0xf7, 0x06, 0xfa, 0x1f, 0x11, 0xe7, 0x4a, 0xec,
+       0x61, 0x3c, 0xce, 0x78, 0x95, 0xb1, 0xc2, 0xe8, 0x32, 0x3a, 0x8c, 0x5d,
+       0x8c, 0x36, 0xe3, 0x26, 0x63, 0x9c, 0xb1, 0x83, 0xd1, 0x62, 0xdc, 0x63,
+       0x8c, 0x31, 0x46, 0x19, 0x1b, 0x8c, 0x46, 0x84, 0x50, 0xe3, 0xf5, 0x63,
+       0x46, 0xe0, 0xba, 0x23, 0x81, 0xba, 0x5f, 0xb3, 0x2e, 0x24, 0x6f, 0xfc,
+       0x7e, 0x50, 0xd9, 0x31, 0xef, 0x58, 0xf7, 0x3a, 0xdb, 0x75, 0x57, 0x57,
+       0x02, 0xfa, 0x49, 0xef, 0xab, 0x9b, 0x54, 0x8b, 0x3e, 0xb8, 0x58, 0xcf,
+       0x9d, 0x82, 0x8b, 0x71, 0x9c, 0x18, 0xed, 0xab, 0xb4, 0x6e, 0xb8, 0x84,
+       0xf7, 0xe2, 0x84, 0x5f, 0x18, 0xef, 0x77, 0x12, 0x4e, 0x77, 0xc9, 0x7c,
+       0x0e, 0x8b, 0x80, 0xea, 0x1c, 0x95, 0x4f, 0xbb, 0x3c, 0xc2, 0xe2, 0xa9,
+       0xbc, 0xda, 0xc5, 0x25, 0x2c, 0x6a, 0xfe, 0xfa, 0x9f, 0x8c, 0x11, 0x1a,
+       0x39, 0x22, 0x75, 0xc9, 0x16, 0x3d, 0x83, 0x46, 0x63, 0xd9, 0x36, 0xe4,
+       0xfa, 0xdc, 0xf2, 0x7b, 0xd4, 0xfb, 0xd9, 0xa5, 0x1a, 0xe7, 0xe7, 0x2a,
+       0x9e, 0x69, 0x0e, 0x32, 0x40, 0xeb, 0x49, 0xe4, 0x1d, 0x04, 0x5a, 0xb8,
+       0x86, 0x8c, 0xbf, 0x5f, 0xa4, 0x43, 0x9d, 0xfb, 0x31, 0xcb, 0xfd, 0x38,
+       0x11, 0xd2, 0x8f, 0xb0, 0xb9, 0x68, 0x9e, 0xc7, 0xdb, 0xe9, 0x20, 0x6f,
+       0x61, 0xf3, 0xa3, 0xf8, 0xa6, 0xdd, 0x3f, 0xe5, 0xf1, 0x01, 0xf3, 0x58,
+       0x24, 0x1e, 0x93, 0xdf, 0x5a, 0xf2, 0x94, 0xf6, 0xf0, 0x24, 0xeb, 0xec,
+       0x0d, 0xe9, 0x73, 0x58, 0x7d, 0xd9, 0xbf, 0xee, 0x73, 0x20, 0x3f, 0xb8,
+       0x8b, 0xdf, 0x9b, 0x04, 0x14, 0x0b, 0x2a, 0x5f, 0x3f, 0xcf, 0xc7, 0xa8,
+       0xdf, 0x30, 0x97, 0x93, 0xfb, 0x62, 0xfe, 0x36, 0x35, 0x5c, 0x1b, 0xf9,
+       0x88, 0x04, 0xab, 0x98, 0x23, 0x7f, 0x47, 0xd3, 0x78, 0x7d, 0x50, 0x5d,
+       0xa8, 0xbe, 0x4b, 0x8c, 0x41, 0x7e, 0x9a, 0xeb, 0xcc, 0x50, 0x3c, 0xd2,
+       0x81, 0xc1, 0x3a, 0xc8, 0xf3, 0xf7, 0x28, 0xc8, 0x87, 0x55, 0x5d, 0x59,
+       0xf4, 0xce, 0x75, 0x12, 0x8a, 0x39, 0xd2, 0x55, 0x73, 0x5f, 0x59, 0x6f,
+       0x6b, 0xea, 0xbb, 0x84, 0xdb, 0xd5, 0x92, 0xee, 0xab, 0xf7, 0x12, 0x64,
+       0xbd, 0x3c, 0x47, 0x5a, 0xe8, 0xa3, 0x5d, 0x1c, 0xdf, 0x79, 0x0e, 0x64,
+       0x5b, 0x7d, 0x6f, 0x4c, 0xae, 0xeb, 0x0c, 0xeb, 0xfb, 0x68, 0x93, 0xbe,
+       0xd5, 0x7d, 0xf5, 0xef, 0x74, 0xce, 0xf5, 0x9b, 0x68, 0x97, 0xda, 0x59,
+       0xf7, 0xde, 0x4f, 0x71, 0xcf, 0xfd, 0x44, 0x6e, 0xa6, 0xca, 0xbb, 0xcf,
+       0x7b, 0xaf, 0x1c, 0x0a, 0xe9, 0x83, 0xf7, 0x3e, 0x0a, 0xd6, 0xeb, 0xd7,
+       0x23, 0xf5, 0x35, 0xce, 0xf5, 0x9b, 0x0d, 0xee, 0xc3, 0x54, 0xff, 0x0c,
+       0xe9, 0x3f, 0x53, 0x90, 0xfa, 0x71, 0xc1, 0x31, 0xe9, 0x7c, 0x42, 0x71,
+       0x8e, 0x66, 0x62, 0xde, 0xf3, 0x1a, 0xad, 0xe7, 0x67, 0xd0, 0x2f, 0x3e,
+       0xa7, 0xf6, 0xf3, 0x48, 0xd8, 0xe4, 0x8b, 0x2d, 0xe2, 0xbd, 0xa6, 0xab,
+       0xb9, 0x70, 0x91, 0xef, 0x01, 0x97, 0xec, 0xcc, 0x2b, 0x8a, 0x2f, 0xb9,
+       0xaf, 0xc3, 0x12, 0xcd, 0xc5, 0xad, 0x47, 0x84, 0x37, 0xe1, 0x32, 0x9d,
+       0xfb, 0xfb, 0xfb, 0x66, 0x21, 0x42, 0x97, 0x57, 0xc7, 0x51, 0xa1, 0x63,
+       0x9c, 0x63, 0x25, 0x57, 0x78, 0xae, 0x11, 0x9f, 0xf3, 0xa4, 0x73, 0x8d,
+       0xf3, 0xc3, 0xab, 0x45, 0x3e, 0xab, 0xba, 0xac, 0xf7, 0x9a, 0xd2, 0x1d,
+       0x0c, 0x9b, 0x38, 0x3f, 0xa9, 0xca, 0x02, 0x2e, 0x7b, 0x1d, 0x46, 0xbb,
+       0x4c, 0x18, 0xc3, 0xfc, 0x75, 0x78, 0x58, 0x93, 0x7e, 0x05, 0xbe, 0xdf,
+       0x7e, 0xb0, 0x5e, 0x74, 0xa8, 0xf0, 0xef, 0x8b, 0x05, 0x7c, 0x3f, 0x01,
+       0xcd, 0xf7, 0x1b, 0xc5, 0x29, 0x0f, 0x11, 0xda, 0xa7, 0xb8, 0xaf, 0xc3,
+       0xd2, 0xce, 0x11, 0x7e, 0xdc, 0x3f, 0xec, 0xc3, 0x05, 0x8f, 0x3f, 0x42,
+       0xe5, 0xc3, 0x40, 0x98, 0xbf, 0xb4, 0xff, 0xde, 0xe2, 0x3e, 0xa5, 0xf7,
+       0x2f, 0xc9, 0x7e, 0xaa, 0xff, 0x19, 0xd7, 0x3f, 0xec, 0xd5, 0xbd, 0x8a,
+       0xf7, 0xae, 0xbe, 0xff, 0x7d, 0xdc, 0xc1, 0x76, 0x5b, 0xfb, 0xd8, 0xd1,
+       0xf1, 0xf9, 0x41, 0xef, 0xfd, 0xfd, 0xa6, 0x4e, 0x3c, 0x6d, 0xd4, 0xd5,
+       0x5c, 0x6d, 0x84, 0xcc, 0xd5, 0xc5, 0xff, 0x3a, 0x57, 0x10, 0x98, 0xab,
+       0xd5, 0xfa, 0xc1, 0xe6, 0x0a, 0xb8, 0x7e, 0x08, 0x99, 0xab, 0x18, 0xf3,
+       0xf0, 0x94, 0xcf, 0x33, 0x20, 0xaa, 0xc7, 0xb0, 0x7d, 0xc6, 0x2c, 0xeb,
+       0x92, 0xf4, 0x68, 0x47, 0xcb, 0xa8, 0x3f, 0xc7, 0x2e, 0x93, 0x9d, 0x41,
+       0xfb, 0x49, 0x85, 0x0b, 0xb3, 0xf4, 0x7b, 0x4a, 0x83, 0x9f, 0x94, 0x15,
+       0x12, 0x3d, 0x80, 0x0b, 0x00, 0x00, 0x00 };
 
-static u32 bnx2_rv2p_proc2[] = {
-       0x00000000, 0x2a000000, 0x00000010, 0xb1d40000, 0x00000008, 0x02540003,
-       0x00000018, 0x00040000, 0x00000018, 0x8000000a, 0x00000018, 0x8000000a,
-       0x00000018, 0x8000000e, 0x00000018, 0x80000056, 0x00000018, 0x800001b9,
-       0x00000018, 0x800001e1, 0x00000018, 0x8000019b, 0x00000018, 0x800001f9,
-       0x00000018, 0x8000019f, 0x00000018, 0x800001a6, 0x00000018, 0x80000000,
-       0x0000000c, 0x29800001, 0x00000000, 0x2a000000, 0x0000000c, 0x29800000,
-       0x00000010, 0x20530000, 0x00000018, 0x8000ffee, 0x0000000c, 0x29800001,
-       0x00000010, 0x91de0000, 0x00000010, 0x001f0000, 0x00000000, 0x2f80aa00,
-       0x00000000, 0x2a000000, 0x00000000, 0x0d610000, 0x00000000, 0x03620000,
-       0x00000000, 0x2c400000, 0x00000000, 0x02638c00, 0x00000000, 0x26460000,
-       0x00000010, 0x00420002, 0x00000008, 0x02040012, 0x00000010, 0xb9060836,
-       0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
-       0x00000000, 0x0b660000, 0x00000000, 0x0c000000, 0x00000000, 0x0b800000,
-       0x00000010, 0x00420009, 0x00000008, 0x0cc60012, 0x00000008, 0x0f800003,
-       0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000008, 0x27110012,
-       0x00000000, 0x66900000, 0x00000008, 0xa31b0012, 0x00000018, 0x80000008,
-       0x00000000, 0x0cc60000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000,
-       0x00000010, 0x009f0000, 0x00000000, 0x27110000, 0x00000000, 0x66900000,
-       0x00000000, 0x231b0000, 0x00000010, 0xb197320e, 0x00000000, 0x25960000,
-       0x00000000, 0x021b0000, 0x00000010, 0x001f0000, 0x00000008, 0x0f800003,
-       0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000000, 0x22c50800,
-       0x00000010, 0x009f0000, 0x00000000, 0x27002200, 0x00000000, 0x26802000,
-       0x00000000, 0x231b0000, 0x0000000c, 0x69520001, 0x00000018, 0x8000fff3,
-       0x00000010, 0x01130002, 0x00000010, 0xb1980003, 0x00000010, 0x001f0000,
-       0x00000008, 0x0f800004, 0x00000008, 0x22000003, 0x00000008, 0x2c80000c,
-       0x00000008, 0x2d00000c, 0x00000010, 0x009f0000, 0x00000000, 0x25960000,
-       0x0000000c, 0x29800000, 0x00000000, 0x32140000, 0x00000000, 0x32950000,
-       0x00000000, 0x33160000, 0x00000000, 0x31e32e00, 0x00000008, 0x2d800010,
-       0x00000010, 0x20530000, 0x00000018, 0x8000ffac, 0x00000000, 0x23000000,
-       0x00000000, 0x25e60000, 0x00000008, 0x2200000b, 0x0000000c, 0x69520000,
-       0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000018, 0x8000ffa5,
-       0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000,
-       0x00000010, 0x001f0000, 0x00000000, 0x02700000, 0x00000000, 0x0d620000,
-       0x00000000, 0xbb630800, 0x00000000, 0x2a000000, 0x00000009, 0x076000ff,
-       0x0000000f, 0x2c0e0007, 0x00000008, 0x2c800000, 0x00000008, 0x2d000064,
-       0x00000008, 0x2d80011c, 0x00000009, 0x06420002, 0x0000000c, 0x61420001,
-       0x00000000, 0x0f400000, 0x00000000, 0x02d08c00, 0x00000000, 0x23000000,
-       0x00000004, 0x826da000, 0x00000000, 0x8304a000, 0x00000000, 0x22c50c00,
-       0x00000000, 0x03760000, 0x00000004, 0x83860a00, 0x00000000, 0x83870c00,
-       0x00000010, 0x91de0000, 0x00000000, 0x037c0000, 0x00000000, 0x837b0c00,
-       0x00000001, 0x83060e00, 0x00000000, 0x83870c00, 0x00000000, 0x82850e00,
-       0x00000010, 0xb1860016, 0x0000000f, 0x47610018, 0x00000000, 0x068e0000,
-       0x0000000f, 0x47670010, 0x0000000f, 0x47e20010, 0x00000000, 0x870e1e00,
-       0x00000010, 0xb70e1a10, 0x00000010, 0x0ce7000e, 0x00000008, 0x22000009,
-       0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400,
-       0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004,
-       0x00000018, 0x8000023f, 0x00000000, 0x37ed0000, 0x0000000c, 0x73e7001a,
-       0x00000010, 0x20530000, 0x00000008, 0x22000008, 0x0000000c, 0x61420004,
-       0x00000000, 0x02f60000, 0x00000004, 0x82840a00, 0x00000010, 0xb1840a2b,
-       0x00000010, 0x2d67000a, 0x00000010, 0xb96d0804, 0x00000004, 0xb6ed0a00,
-       0x00000000, 0x37ed0000, 0x00000018, 0x80000029, 0x0000000c, 0x61420000,
-       0x00000000, 0x37040000, 0x00000000, 0x37850000, 0x0000000c, 0x33e7001a,
-       0x00000018, 0x80000024, 0x00000010, 0xb96d0809, 0x00000004, 0xb6ed0a00,
-       0x00000000, 0x036d0000, 0x00000004, 0xb76e0c00, 0x00000010, 0x91ee0c1f,
-       0x0000000c, 0x73e7001a, 0x00000004, 0xb6ef0c00, 0x00000000, 0x37ed0000,
-       0x00000018, 0x8000001b, 0x0000000c, 0x61420000, 0x00000010, 0xb7ee0a05,
-       0x00000010, 0xb96f0815, 0x00000003, 0xb76e0800, 0x00000004, 0xb7ef0a00,
-       0x00000018, 0x80000015, 0x00000010, 0x0ce7000c, 0x00000008, 0x22000009,
-       0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400,
-       0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004,
-       0x00000018, 0x80000215, 0x00000010, 0x20530000, 0x00000008, 0x22000008,
-       0x0000000c, 0x61420004, 0x00000000, 0x37040000, 0x00000000, 0x37850000,
-       0x00000000, 0x036d0000, 0x00000003, 0xb8f10c00, 0x00000018, 0x80000004,
-       0x00000000, 0x02840000, 0x00000002, 0x21421800, 0x0000000c, 0x61420000,
-       0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff,
-       0x00000000, 0x23000000, 0x00000010, 0xb1840a3d, 0x00000010, 0x01420002,
-       0x00000004, 0xb8f10a00, 0x00000003, 0x83760a00, 0x00000010, 0xb8040c39,
-       0x00000010, 0xb7e6080a, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
-       0x00000009, 0x0c68ffff, 0x00000009, 0x0b67ffff, 0x00000000, 0x0be60000,
-       0x00000000, 0x0c840000, 0x00000010, 0xb197320c, 0x00000008, 0x0f800002,
-       0x00000018, 0x8000000a, 0x00000000, 0x0a6a0000, 0x00000000, 0x0aeb0000,
-       0x00000000, 0x0c000000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0be90000,
-       0x00000000, 0x0c840000, 0x00000010, 0xb1973203, 0x00000008, 0x0f800002,
-       0x00000018, 0x80000001, 0x00000010, 0x001f0000, 0x00000000, 0x0c860000,
-       0x00000000, 0x06980000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000,
-       0x00000010, 0x009f0000, 0x00000010, 0xb1973210, 0x00000000, 0x231b0000,
-       0x00000000, 0x02043600, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
-       0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000,
-       0x0000000c, 0x29000000, 0x00000018, 0x800001de, 0x00000000, 0x06980000,
-       0x00000010, 0x20530000, 0x00000000, 0x22c58c00, 0x00000010, 0x001f0000,
-       0x00000008, 0x0f800003, 0x00000018, 0x8000fff0, 0x00000000, 0x02043600,
-       0x00000000, 0x231b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
-       0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000,
-       0x0000000c, 0x29000000, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
-       0x00000000, 0x32140000, 0x00000000, 0x32950000, 0x00000005, 0x73e72c00,
-       0x00000005, 0x74683000, 0x00000000, 0x33170000, 0x00000018, 0x80000138,
-       0x00000010, 0x91c60004, 0x00000008, 0x07000004, 0x00000010, 0xb1c41c02,
-       0x00000010, 0x91840a04, 0x00000018, 0x800001c3, 0x00000010, 0x20530000,
-       0x00000000, 0x22c58c00, 0x00000010, 0xb1840a8e, 0x0000000c, 0x21420006,
-       0x00000010, 0x0ce7001a, 0x0000000f, 0x43680010, 0x00000000, 0x03f30c00,
-       0x00000010, 0x91870850, 0x0000000f, 0x46ec0010, 0x00000010, 0xb68d0c4e,
-       0x00000000, 0x838d0c00, 0x00000000, 0xa3050800, 0x00000001, 0xa3460e00,
-       0x00000000, 0x02048c00, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
-       0x00000010, 0x001f0000, 0x00000008, 0x22000008, 0x00000003, 0x8384a000,
-       0x0000000f, 0x65870010, 0x00000009, 0x2607ffff, 0x00000000, 0x27750c00,
-       0x00000000, 0x66f40000, 0x0000000c, 0x29000000, 0x00000018, 0x800001aa,
-       0x00000000, 0x03068c00, 0x00000003, 0xf4680c00, 0x00000010, 0x20530000,
-       0x00000000, 0x22c58c00, 0x00000018, 0x8000ffe5, 0x00000000, 0x39760000,
-       0x00000000, 0x39840000, 0x0000000c, 0x33e70019, 0x00000010, 0x001f0000,
-       0x00000000, 0x031e0000, 0x00000000, 0x0760fe00, 0x0000000f, 0x0f0e0007,
-       0x00000000, 0x83850800, 0x00000000, 0x0a7d0000, 0x00000000, 0x0afe0000,
-       0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000, 0x00000000, 0x0c000000,
-       0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003,
-       0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff,
-       0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010,
-       0x00000002, 0x33e70e00, 0x00000000, 0x28f30000, 0x00000010, 0x009f0000,
-       0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
-       0x00000008, 0x22000006, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000,
-       0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
-       0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000,
-       0x0000000c, 0x29000000, 0x00000018, 0x8000017e, 0x00000003, 0xf4683600,
-       0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400,
-       0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004,
-       0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000,
-       0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000,
-       0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000,
-       0x00000000, 0x22c53600, 0x00000018, 0x8000ffac, 0x00000010, 0x001f0000,
-       0x00000000, 0x031e0000, 0x00000000, 0x83850800, 0x00000009, 0x076000ff,
-       0x0000000f, 0x0f0e0007, 0x00000000, 0x0c000000, 0x00000000, 0x0a7d0000,
-       0x00000000, 0x0afe0000, 0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000,
-       0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003,
-       0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff,
-       0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010,
-       0x00000002, 0x33e70e00, 0x00000000, 0x39840000, 0x00000003, 0xb9720800,
-       0x00000000, 0x28f30000, 0x0000000f, 0x65680010, 0x00000010, 0x009f0000,
-       0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
-       0x00000008, 0x22000007, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000,
-       0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
-       0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000,
-       0x0000000c, 0x29000000, 0x00000018, 0x80000145, 0x00000003, 0xf4683600,
-       0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400,
-       0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004,
-       0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000,
-       0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000,
-       0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000,
-       0x00000000, 0x22c53600, 0x00000018, 0x8000ff73, 0x00000010, 0x0ce70005,
-       0x00000008, 0x2c80000c, 0x00000008, 0x2d000070, 0x00000008, 0x2d800010,
-       0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000018, 0x8000011d,
-       0x00000000, 0x2c1e0000, 0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010,
-       0x00000008, 0x2d800048, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
-       0x00000018, 0x8000fe5d, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000,
-       0x00000010, 0x001f0000, 0x00000000, 0x0f008000, 0x00000008, 0x0f800007,
-       0x00000018, 0x80000006, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000,
-       0x00000010, 0x001f0000, 0x0000000f, 0x0f470007, 0x00000008, 0x0f800008,
-       0x00000018, 0x80000119, 0x00000010, 0x20530000, 0x00000018, 0x8000fe4f,
-       0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000,
-       0x00000000, 0x2a000000, 0x00000009, 0x0261ffff, 0x0000000d, 0x70e10001,
-       0x00000018, 0x80000101, 0x00000000, 0x2c400000, 0x00000008, 0x2c8000c4,
-       0x00000008, 0x2d00001c, 0x00000008, 0x2d800001, 0x00000005, 0x70e10800,
-       0x00000010, 0x91de0000, 0x00000018, 0x8000fe41, 0x0000000c, 0x29800001,
-       0x00000010, 0x91de0000, 0x00000000, 0x2fd50000, 0x00000010, 0x001f0000,
-       0x00000000, 0x02700000, 0x00000000, 0x0d620000, 0x00000000, 0xbb630800,
-       0x00000000, 0x2a000000, 0x00000000, 0x0f400000, 0x00000000, 0x2c400000,
-       0x0000000c, 0x73e7001b, 0x00000010, 0x0ce7000e, 0x00000000, 0x286d0000,
-       0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff, 0x00000018, 0x80000069,
-       0x00000008, 0x02000004, 0x00000010, 0x91c40803, 0x00000018, 0x800000f6,
-       0x00000010, 0x20530000, 0x00000018, 0x800000e5, 0x00000008, 0x2c8000b8,
-       0x00000008, 0x2d000010, 0x00000008, 0x2d800048, 0x00000018, 0x80000005,
-       0x00000008, 0x2c8000c4, 0x00000008, 0x2d00001c, 0x00000008, 0x2d800001,
-       0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800048,
-       0x00000008, 0x2d000068, 0x00000008, 0x2d800104, 0x00000000, 0x00000000,
-       0x00000010, 0x91de0000, 0x00000000, 0x27f60000, 0x00000010, 0xb87a9e04,
-       0x00000008, 0x2200000d, 0x00000018, 0x800000e2, 0x00000010, 0x20530000,
-       0x00000018, 0x8000fe18, 0x0000000c, 0x29800001, 0x00000010, 0x91de0000,
-       0x00000000, 0x2fd50000, 0x00000010, 0x001f0000, 0x00000000, 0x02700000,
-       0x00000000, 0x0d620000, 0x00000000, 0xbb630800, 0x00000000, 0x2a000000,
-       0x00000010, 0x0e670011, 0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010,
-       0x00000009, 0x266dffff, 0x00000004, 0xb8f1a000, 0x00000000, 0x0f400000,
-       0x0000000c, 0x73e7001c, 0x00000018, 0x80000040, 0x00000008, 0x02000004,
-       0x00000010, 0x91c40802, 0x00000018, 0x800000cd, 0x00000000, 0x2c1e0000,
-       0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010, 0x00000008, 0x2d800048,
-       0x00000010, 0x20530000, 0x00000010, 0x91de0000, 0x00000018, 0x8000fdfe,
-       0x0000000c, 0x29800001, 0x00000000, 0x03550000, 0x00000000, 0x06460000,
-       0x00000000, 0x03d60000, 0x00000000, 0x2a000000, 0x0000000f, 0x0f480007,
-       0x00000010, 0xb18c0027, 0x0000000f, 0x47420008, 0x00000009, 0x070e000f,
-       0x00000008, 0x070e0008, 0x00000010, 0x001f0000, 0x00000008, 0x09000001,
-       0x00000007, 0x09121c00, 0x00000003, 0xcbca9200, 0x00000000, 0x0b97a200,
-       0x00000007, 0x4b171c00, 0x0000000f, 0x0a960003, 0x00000000, 0x0a959c00,
-       0x00000000, 0x4a009a00, 0x00000008, 0x82120001, 0x00000001, 0x0c170800,
-       0x00000000, 0x02180000, 0x00000000, 0x0c971800, 0x00000008, 0x0d00ffff,
-       0x00000008, 0x0f800006, 0x0000000c, 0x29000000, 0x00000008, 0x22000001,
-       0x00000000, 0x22c50c00, 0x00000010, 0x009f0000, 0x00000010, 0xb197320b,
-       0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000,
-       0x00000018, 0x800000a4, 0x00000000, 0x02180000, 0x00000010, 0x20530000,
-       0x00000000, 0x22c53600, 0x00000010, 0x001f0000, 0x00000008, 0x0f800006,
-       0x00000018, 0x8000fff5, 0x00000010, 0x91870002, 0x00000008, 0x2200000a,
-       0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000,
-       0x00000018, 0x80000098, 0x00000008, 0x0200000a, 0x00000010, 0x91c40804,
-       0x00000010, 0x02c20003, 0x00000010, 0x001f0000, 0x00000008, 0x0f800008,
-       0x00000010, 0x20530000, 0x00000018, 0x8000fdc9, 0x00000000, 0x06820000,
-       0x00000010, 0x001f0000, 0x00000010, 0x0ce70028, 0x00000000, 0x03720000,
-       0x00000000, 0xa8760c00, 0x00000000, 0x0cf60000, 0x00000010, 0xb8723224,
-       0x00000000, 0x03440000, 0x00000008, 0x22000010, 0x00000000, 0x03ca0000,
-       0x0000000f, 0x65680010, 0x00000000, 0x0bcf0000, 0x00000000, 0x27f20000,
-       0x00000010, 0xb7ef3203, 0x0000000c, 0x21420004, 0x0000000c, 0x73e70019,
-       0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x8000007e,
-       0x00000004, 0xb9723200, 0x00000010, 0x20530000, 0x00000000, 0x22060000,
-       0x0000000c, 0x61420004, 0x00000000, 0x25070000, 0x00000000, 0x27970000,
-       0x00000000, 0x290e0000, 0x00000010, 0x0ce70010, 0x00000010, 0xb873320f,
-       0x0000000f, 0x436c0010, 0x00000000, 0x03f30c00, 0x00000000, 0x03f30000,
-       0x00000000, 0x83990e00, 0x00000001, 0x83860e00, 0x00000000, 0x83060e00,
-       0x00000003, 0xf66c0c00, 0x00000000, 0x39f30e00, 0x00000000, 0x3af50e00,
-       0x00000000, 0x7a740000, 0x0000000f, 0x43680010, 0x00000001, 0x83860e00,
-       0x00000000, 0x83060e00, 0x00000003, 0xf4680c00, 0x00000000, 0x286d0000,
-       0x00000000, 0x03690000, 0x00000010, 0xb1f60c54, 0x00000000, 0x0a6a0000,
-       0x00000000, 0x0aeb0000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0c000000,
-       0x00000000, 0x0be90000, 0x00000003, 0x8cf6a000, 0x0000000c, 0x09800002,
-       0x00000010, 0x009f0000, 0x00000010, 0xb8173209, 0x00000000, 0x35140000,
-       0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34970000,
-       0x00000004, 0xb8f12e00, 0x00000010, 0x001f0000, 0x00000008, 0x0f800004,
-       0x00000018, 0x8000fff7, 0x00000000, 0x03e90000, 0x00000010, 0xb8f6a01a,
-       0x00000010, 0x20130019, 0x00000010, 0xb1f10e18, 0x00000000, 0x83973200,
-       0x00000000, 0x38700e00, 0x00000000, 0xbb760e00, 0x00000000, 0x37d00000,
-       0x0000000c, 0x73e7001a, 0x00000003, 0xb8f1a000, 0x00000000, 0x32140000,
-       0x00000000, 0x32950000, 0x00000005, 0x73e72c00, 0x00000000, 0x33190000,
-       0x00000005, 0x74680000, 0x00000010, 0x0ce7000d, 0x00000008, 0x22000009,
-       0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x0000000c, 0x73e70019,
-       0x0000000f, 0x65680010, 0x0000000c, 0x21420004, 0x00000018, 0x8000003c,
-       0x00000010, 0x20530000, 0x0000000c, 0x61420004, 0x00000000, 0x290e0000,
-       0x00000018, 0x80000002, 0x00000010, 0x91973206, 0x00000000, 0x35140000,
-       0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34990000,
-       0x00000004, 0xb8f13200, 0x00000000, 0x83690c00, 0x00000010, 0xb1860013,
-       0x00000000, 0x28e90000, 0x00000008, 0x22000004, 0x00000000, 0x23ec0000,
-       0x00000000, 0x03690000, 0x00000010, 0xb8660c07, 0x00000009, 0x036cffff,
-       0x00000000, 0x326a0000, 0x00000000, 0x32eb0000, 0x00000005, 0x73e70c00,
-       0x00000000, 0x33690000, 0x00000005, 0x74680000, 0x0000000c, 0x73e7001c,
-       0x00000000, 0x03690000, 0x00000010, 0xb1f60c12, 0x00000010, 0xb1d00c11,
-       0x0000000c, 0x21420005, 0x0000000c, 0x33e7001c, 0x00000018, 0x8000000e,
-       0x00000010, 0x2e67000d, 0x00000000, 0x03690000, 0x00000010, 0xb1f60c0b,
-       0x00000010, 0xb1d00c0a, 0x00000000, 0x03440000, 0x00000008, 0x2200000c,
-       0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x80000015,
-       0x0000000c, 0x33e7001c, 0x00000010, 0x20530000, 0x00000000, 0x22060000,
-       0x00000000, 0x290e0000, 0x00000018, 0x000d0000, 0x00000000, 0x06820000,
-       0x00000010, 0x2de7000d, 0x00000010, 0x0ce7000c, 0x00000000, 0x27f20000,
-       0x00000010, 0xb96d9e0a, 0x00000000, 0xa86d9e00, 0x00000009, 0x0361ffff,
-       0x00000010, 0xb7500c07, 0x00000008, 0x2200000f, 0x0000000f, 0x65680010,
-       0x00000000, 0x29000000, 0x00000018, 0x80000004, 0x0000000c, 0x33e7001b,
-       0x00000010, 0x20530000, 0x00000018, 0x000d0000, 0x00000000, 0x2b820000,
-       0x00000010, 0x20d2002f, 0x00000010, 0x0052002e, 0x00000009, 0x054e0007,
-       0x00000010, 0xb18a002c, 0x00000000, 0x050a8c00, 0x00000008, 0x850a0008,
-       0x00000010, 0x918a0029, 0x00000003, 0xc5008800, 0x00000008, 0xa3460001,
-       0x00000010, 0xb1c60007, 0x00000008, 0x22000001, 0x0000000c, 0x29800000,
-       0x00000010, 0x20530000, 0x00000000, 0x274e8c00, 0x00000000, 0x66cd0000,
-       0x00000000, 0x22c58c00, 0x00000008, 0x22000014, 0x00000003, 0x22c58e00,
-       0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00,
-       0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000,
-       0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x0000000c, 0x69520000,
-       0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000003, 0x22c58e00,
-       0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00,
-       0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000,
-       0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x00000000, 0xa2c58c00,
-       0x00000000, 0xa74e8c00, 0x00000000, 0xe6cd0000, 0x0000000f, 0x620a0010,
-       0x00000008, 0x23460001, 0x0000000c, 0x29800000, 0x00000010, 0x20530000,
-       0x0000000c, 0x29520000, 0x00000018, 0x80000002, 0x0000000c, 0x29800000,
-       0x00000018, 0x00570000 };
+static u8 bnx2_rv2p_proc2[] = {
+       0x1f, 0x8b, 0x08, 0x08, 0x7e, 0xd1, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xcd, 0x58, 0x5b, 0x6c,
+       0x54, 0x55, 0x14, 0x3d, 0xf3, 0xe8, 0xcc, 0x9d, 0xe9, 0xed, 0x9d, 0xf2,
+       0xb2, 0x03, 0xad, 0x08, 0xe5, 0xd1, 0x56, 0x29, 0xe8, 0x54, 0xab, 0x18,
+       0x15, 0x2c, 0x5a, 0x8c, 0x26, 0x68, 0xf0, 0xf9, 0x63, 0x14, 0x04, 0xda,
+       0x9a, 0x56, 0x9b, 0x16, 0xfb, 0x81, 0xaf, 0x09, 0x14, 0x6a, 0x4c, 0x25,
+       0xd6, 0x08, 0xc5, 0x47, 0xa0, 0x11, 0x1f, 0x84, 0xf0, 0xd3, 0x1f, 0x3b,
+       0x8d, 0x7f, 0x0a, 0x24, 0x6a, 0x88, 0xc4, 0xa8, 0x9f, 0x24, 0x68, 0xa0,
+       0x21, 0x0a, 0x58, 0x8b, 0x63, 0x4c, 0xb4, 0xf5, 0xec, 0xbd, 0xf6, 0xb9,
+       0x73, 0xef, 0x6d, 0x8b, 0x1a, 0xf9, 0x70, 0x3e, 0xba, 0x7b, 0xce, 0xd9,
+       0x67, 0x3f, 0xd6, 0xde, 0x67, 0x9f, 0x7d, 0xae, 0x52, 0xfc, 0xbb, 0xb6,
+       0x94, 0xc9, 0x37, 0x83, 0x96, 0xfe, 0x1b, 0x51, 0x0f, 0x85, 0xd3, 0x3c,
+       0x8e, 0x2a, 0xa2, 0x49, 0xa5, 0xb2, 0x5e, 0xea, 0x08, 0x7d, 0x44, 0xe8,
+       0x70, 0x08, 0xf4, 0xb4, 0xd0, 0x77, 0x84, 0xfe, 0x2e, 0xf4, 0x80, 0xd0,
+       0x0f, 0x85, 0xea, 0x5f, 0xd6, 0xd6, 0x7f, 0xf4, 0xb0, 0x46, 0x89, 0x7e,
+       0x1b, 0xd3, 0x35, 0xb0, 0xe3, 0xc1, 0x05, 0xc4, 0x77, 0x61, 0xa2, 0xc0,
+       0x87, 0xf9, 0x53, 0x7d, 0xa0, 0xd7, 0x60, 0xd7, 0xe1, 0xec, 0x0a, 0xb3,
+       0x1f, 0x64, 0x43, 0x09, 0xe8, 0xc6, 0x08, 0xe8, 0xea, 0x65, 0x4c, 0x7a,
+       0x9f, 0x0a, 0x63, 0xdc, 0xb8, 0x94, 0xf6, 0x87, 0x55, 0x83, 0x22, 0x3f,
+       0x67, 0xaa, 0x68, 0x98, 0xc6, 0xf5, 0x56, 0x6c, 0x18, 0xeb, 0x8f, 0xa5,
+       0x40, 0x37, 0x25, 0x41, 0xcf, 0x08, 0xdd, 0x52, 0x2c, 0x7a, 0x6c, 0x31,
+       0xbf, 0x98, 0xf6, 0x25, 0x5c, 0x39, 0xc7, 0x6d, 0xe0, 0x96, 0x95, 0xfd,
+       0x4a, 0xc1, 0xce, 0x03, 0xb2, 0x3e, 0xa3, 0x0a, 0xb3, 0xaf, 0x6f, 0xc1,
+       0xb8, 0xfc, 0x20, 0xf9, 0xa7, 0xff, 0xcf, 0x62, 0x7e, 0xfa, 0xfd, 0xf8,
+       0x15, 0xf6, 0x83, 0x96, 0x2f, 0xa2, 0x75, 0x27, 0xd3, 0x3f, 0x88, 0xf1,
+       0xde, 0x25, 0x32, 0x1f, 0x36, 0xf8, 0x18, 0x79, 0x41, 0x5c, 0x99, 0x58,
+       0xc7, 0x2a, 0x7d, 0xf2, 0x2b, 0x15, 0xe4, 0x2f, 0xc8, 0x2e, 0x35, 0xf2,
+       0x81, 0xfb, 0xfa, 0x16, 0xb2, 0x73, 0x4c, 0xc7, 0x01, 0xb8, 0xcd, 0x0a,
+       0x95, 0xb2, 0xdc, 0x7d, 0x83, 0x5e, 0x3d, 0x51, 0xad, 0x07, 0xfa, 0x54,
+       0xa5, 0xc5, 0x20, 0x65, 0x97, 0x81, 0xaa, 0x5a, 0xbf, 0x1f, 0x7b, 0x97,
+       0x18, 0x7b, 0x30, 0x9e, 0x9d, 0x01, 0xdd, 0x23, 0xf4, 0xaa, 0x3a, 0x26,
+       0xcb, 0x7f, 0xb8, 0xc1, 0x62, 0x0c, 0xb2, 0xb5, 0xde, 0x7c, 0x38, 0x32,
+       0x61, 0xf0, 0x52, 0x8b, 0x40, 0xce, 0x2e, 0x21, 0x3e, 0x1d, 0x9c, 0x4a,
+       0xc8, 0x5d, 0xdf, 0x32, 0x55, 0x1e, 0x7d, 0x30, 0x45, 0x1e, 0x61, 0xff,
+       0xb7, 0x2b, 0x7c, 0xf9, 0xa4, 0xda, 0x25, 0x4f, 0x36, 0x22, 0x8f, 0xac,
+       0xa7, 0x3e, 0x91, 0x85, 0x6b, 0x13, 0xfa, 0xcf, 0x84, 0x7a, 0x32, 0x4e,
+       0x01, 0x8a, 0x2b, 0x87, 0xfd, 0x53, 0xe2, 0xe7, 0x26, 0xed, 0x27, 0xd1,
+       0x8a, 0x50, 0xb6, 0x36, 0xc1, 0x38, 0x35, 0xc4, 0xa0, 0xaf, 0x61, 0x03,
+       0xb6, 0xaf, 0x46, 0x5c, 0x7b, 0x4f, 0x86, 0x8d, 0xfd, 0x51, 0xfa, 0x3b,
+       0xd0, 0xb6, 0x9d, 0x47, 0x03, 0xd1, 0x1d, 0x4c, 0xed, 0x63, 0x95, 0x58,
+       0xee, 0x8a, 0xf0, 0x7a, 0x72, 0x97, 0xcc, 0xf7, 0xec, 0xf0, 0xdb, 0xfd,
+       0x02, 0xf2, 0xdb, 0x7e, 0x7e, 0x47, 0x88, 0xa8, 0x13, 0x73, 0xf9, 0x98,
+       0x3a, 0x3b, 0xb7, 0x13, 0xff, 0x55, 0x6a, 0xd7, 0x20, 0x29, 0x4e, 0xab,
+       0x0d, 0x6b, 0xb1, 0x6f, 0x77, 0x2c, 0xc5, 0xb8, 0x36, 0xad, 0x05, 0xfd,
+       0x1e, 0xf3, 0xf3, 0x9d, 0x1e, 0xe2, 0x2f, 0x9d, 0xe7, 0x0c, 0x71, 0x5e,
+       0xa9, 0x11, 0xce, 0xc7, 0x04, 0x65, 0x06, 0xff, 0xda, 0xaa, 0xc1, 0xdf,
+       0xbc, 0x99, 0x15, 0xbf, 0xd9, 0x9a, 0xe7, 0x3c, 0x18, 0xe8, 0x18, 0x26,
+       0x3f, 0xe7, 0xaa, 0x91, 0x4e, 0xa2, 0x51, 0xd5, 0xb0, 0x90, 0xf0, 0x5e,
+       0x15, 0x36, 0x71, 0x3a, 0x7f, 0x33, 0xcd, 0xcf, 0xd3, 0xeb, 0x26, 0x1e,
+       0x24, 0xd7, 0x92, 0x78, 0x45, 0x5d, 0x7c, 0xf2, 0x61, 0xf8, 0xdb, 0xcd,
+       0x76, 0x5f, 0x97, 0xec, 0xe6, 0xfc, 0x4a, 0xaa, 0x26, 0x8e, 0x7f, 0xd4,
+       0x6a, 0x1b, 0xc6, 0xfa, 0xf9, 0x8f, 0x8d, 0x5c, 0xd2, 0x53, 0x23, 0x75,
+       0x44, 0xb9, 0x72, 0xa2, 0x37, 0x83, 0xee, 0x34, 0x7a, 0xeb, 0x88, 0x6f,
+       0xb1, 0x42, 0xfe, 0x26, 0x26, 0xc9, 0x69, 0x03, 0xce, 0xf6, 0x33, 0xec,
+       0xf7, 0x35, 0xf6, 0x85, 0x3e, 0x63, 0x2f, 0xe6, 0x2f, 0xfa, 0xf4, 0x95,
+       0x7b, 0xf4, 0x11, 0x7f, 0x51, 0xf2, 0x02, 0xef, 0x9b, 0x63, 0x3d, 0x3b,
+       0xcc, 0xb8, 0x58, 0xcf, 0x0c, 0x41, 0xfe, 0xc5, 0x21, 0xe2, 0x9f, 0x23,
+       0x7a, 0xed, 0xff, 0x88, 0xe7, 0x9c, 0x30, 0xe4, 0x4c, 0x8f, 0x5f, 0xc1,
+       0x6f, 0xe3, 0x17, 0xcb, 0xb5, 0x47, 0x73, 0x69, 0xe6, 0x33, 0xf1, 0xe8,
+       0x0e, 0x73, 0x02, 0xa6, 0x1b, 0x16, 0xfa, 0x71, 0x33, 0xf6, 0x9c, 0xdf,
+       0xcc, 0x79, 0x3e, 0xd1, 0x26, 0x75, 0x40, 0x71, 0x9d, 0xb9, 0x5d, 0xe2,
+       0xa1, 0xf3, 0x3a, 0x04, 0xff, 0x46, 0x73, 0x2c, 0x3f, 0xd9, 0xc5, 0x79,
+       0xb9, 0xd2, 0x8e, 0xe6, 0x38, 0x5e, 0xd6, 0xd9, 0x21, 0x6c, 0x2b, 0xd4,
+       0x4f, 0xc8, 0x6b, 0xb6, 0x41, 0x9b, 0xa4, 0x8e, 0x9e, 0x15, 0xda, 0x6d,
+       0x33, 0x3e, 0xba, 0x8e, 0x59, 0x2c, 0x3f, 0x9b, 0x32, 0xf7, 0x0c, 0xd6,
+       0x9f, 0x16, 0x39, 0x3f, 0x0a, 0x55, 0x22, 0xa7, 0x55, 0xf6, 0x9f, 0xf3,
+       0xc9, 0x89, 0x04, 0xe4, 0x84, 0x94, 0xc1, 0xcd, 0x9c, 0xef, 0x5d, 0x52,
+       0xbf, 0xf7, 0xc5, 0xa6, 0xab, 0xb7, 0x7c, 0x0e, 0xdc, 0xba, 0x5a, 0x8e,
+       0x3a, 0x53, 0x1f, 0x0d, 0xb3, 0xbf, 0x03, 0xdd, 0x3b, 0x80, 0x53, 0x8f,
+       0xe0, 0x14, 0x07, 0x4e, 0xf3, 0x0a, 0xf5, 0x59, 0x14, 0xd4, 0x90, 0xfe,
+       0x53, 0x21, 0xe3, 0xc7, 0xbe, 0x98, 0xaf, 0xfe, 0xf6, 0x9a, 0xfa, 0x5b,
+       0xa8, 0xd3, 0xc4, 0xff, 0xb3, 0xa9, 0x6f, 0x5a, 0x9f, 0xd1, 0xff, 0x6f,
+       0xf5, 0x72, 0x9c, 0x92, 0xdd, 0x7d, 0x26, 0xce, 0x98, 0x2e, 0xd4, 0xd9,
+       0x22, 0x22, 0xcb, 0x46, 0x3a, 0x99, 0x5e, 0xdf, 0xbc, 0x15, 0xf3, 0x65,
+       0x7c, 0x4e, 0x6e, 0x09, 0x01, 0xaf, 0xa8, 0x3a, 0xde, 0x87, 0xba, 0xae,
+       0xe2, 0x2c, 0xaf, 0xe2, 0x28, 0xc7, 0x3f, 0xaa, 0xe5, 0x12, 0xdf, 0x67,
+       0xa1, 0x42, 0x3e, 0x7a, 0xfd, 0xd9, 0xad, 0xf3, 0x84, 0xec, 0x88, 0xe9,
+       0xbc, 0xa5, 0xb1, 0x3e, 0x47, 0xb6, 0xe4, 0xf9, 0x1a, 0xe6, 0xb3, 0xc7,
+       0x22, 0x34, 0xff, 0x80, 0xd5, 0xd3, 0x87, 0xf9, 0x9f, 0x1a, 0x69, 0xbc,
+       0xce, 0x7e, 0x0d, 0xe7, 0xcc, 0x7e, 0x0d, 0xf5, 0xcb, 0x2a, 0x3a, 0x88,
+       0xba, 0xd6, 0x78, 0x10, 0xf2, 0x71, 0x4f, 0x7b, 0xfd, 0xf2, 0xe2, 0x47,
+       0xe7, 0xe1, 0xb2, 0x38, 0xd9, 0xcf, 0x09, 0x4e, 0x97, 0x7c, 0xf1, 0x39,
+       0x6c, 0xe2, 0xd3, 0x1b, 0x93, 0xf3, 0xd2, 0x7c, 0x29, 0xe8, 0x17, 0xf1,
+       0x9d, 0x71, 0xef, 0x9d, 0xae, 0x95, 0xa0, 0xdd, 0x2b, 0xe5, 0x9c, 0xd6,
+       0xf9, 0xf3, 0x6b, 0x3e, 0xea, 0xf2, 0xb8, 0x7b, 0x4f, 0x20, 0xbf, 0xac,
+       0x9d, 0xf0, 0x4b, 0xbd, 0x28, 0x79, 0x3c, 0x2e, 0xf4, 0x65, 0xc9, 0xdf,
+       0x6d, 0xd2, 0xb7, 0x98, 0xfe, 0xe2, 0x0f, 0xcc, 0x3b, 0xfd, 0x6e, 0x5f,
+       0x60, 0xea, 0x36, 0x8d, 0x43, 0xca, 0x89, 0x13, 0x83, 0x36, 0xeb, 0x33,
+       0x24, 0x4a, 0xcf, 0x1a, 0xe0, 0x35, 0x52, 0x07, 0xbe, 0xdd, 0x91, 0xb0,
+       0x8c, 0x21, 0x6f, 0xac, 0xda, 0x77, 0x0f, 0xd7, 0x4f, 0xc6, 0x93, 0xe4,
+       0xc6, 0xdc, 0xfa, 0x24, 0x79, 0xaf, 0x26, 0x84, 0x96, 0x2f, 0xbe, 0x2c,
+       0xbe, 0x85, 0xfe, 0x64, 0xa9, 0x17, 0xdf, 0x97, 0x34, 0xbe, 0xbc, 0xaf,
+       0xbe, 0xf9, 0x12, 0xa6, 0x4b, 0x6f, 0x05, 0xed, 0xbb, 0x95, 0xe7, 0x17,
+       0xa3, 0xee, 0x11, 0x7e, 0x9c, 0x5f, 0xf5, 0x6f, 0x0c, 0x9a, 0x7e, 0x42,
+       0xf0, 0x08, 0xf4, 0x41, 0x65, 0x77, 0x80, 0xbe, 0x29, 0x74, 0xce, 0x2a,
+       0xd0, 0xbd, 0xab, 0xfc, 0x71, 0x88, 0xa5, 0x7c, 0x71, 0xac, 0x47, 0x1c,
+       0x8f, 0x4c, 0x04, 0xeb, 0x81, 0xc4, 0x4b, 0xc7, 0x27, 0x70, 0xbf, 0x1b,
+       0xfd, 0xe2, 0xce, 0xdf, 0xc5, 0xed, 0x4a, 0xc7, 0xab, 0x7b, 0x25, 0xee,
+       0x93, 0x0e, 0xe9, 0x4b, 0xc7, 0xdc, 0xfb, 0xe2, 0x9f, 0xc4, 0x31, 0x7e,
+       0x85, 0xe3, 0x78, 0xf7, 0xff, 0x2c, 0x8e, 0x9d, 0x12, 0xc7, 0x22, 0xb9,
+       0x57, 0x4d, 0xbf, 0xd9, 0x2e, 0x7d, 0x18, 0xf5, 0x8d, 0x7e, 0xbd, 0x4f,
+       0x70, 0x1f, 0x78, 0xb5, 0x5b, 0x8f, 0xe7, 0x33, 0x7f, 0x4e, 0xf6, 0x95,
+       0xca, 0xbe, 0x7b, 0x26, 0xed, 0x3b, 0xc5, 0xf5, 0xee, 0xf1, 0xf1, 0xc9,
+       0xef, 0x15, 0x9f, 0x9d, 0x59, 0x95, 0x02, 0xee, 0xa8, 0xe3, 0xb1, 0x29,
+       0xde, 0x37, 0x86, 0x1f, 0xf9, 0xb5, 0x36, 0x85, 0xba, 0x05, 0xfe, 0xb9,
+       0x9e, 0x7a, 0x4a, 0xe3, 0xfb, 0xc7, 0xa7, 0xef, 0x57, 0x8d, 0x3c, 0xc4,
+       0x6d, 0x43, 0xb8, 0x84, 0xf9, 0x4e, 0xb7, 0xf3, 0x7d, 0xe7, 0xfa, 0xb7,
+       0x9a, 0xfd, 0x3a, 0x2a, 0xfe, 0x55, 0x88, 0x7f, 0x7a, 0xb9, 0x96, 0xeb,
+       0xbe, 0x75, 0xba, 0xdd, 0xeb, 0xdf, 0x9d, 0x97, 0xd1, 0xf7, 0x4f, 0xfb,
+       0x63, 0xd1, 0x9b, 0x32, 0xfa, 0x49, 0x5e, 0xb9, 0xf4, 0x7d, 0xd4, 0x4f,
+       0x62, 0x7e, 0x72, 0x9f, 0x41, 0xfa, 0x5b, 0x34, 0x5e, 0x72, 0xdf, 0x70,
+       0x3e, 0x47, 0xac, 0xa3, 0x6c, 0x57, 0x5e, 0xf9, 0x71, 0x39, 0x23, 0x7c,
+       0x53, 0xc5, 0x8d, 0xd6, 0x8b, 0x64, 0x7d, 0x2a, 0xbf, 0xc5, 0x4e, 0x37,
+       0x1f, 0x64, 0x1f, 0xf3, 0x35, 0x0b, 0x5f, 0x34, 0x34, 0x39, 0xfe, 0x18,
+       0xe5, 0xab, 0x38, 0xaf, 0xf7, 0x6f, 0xcb, 0x11, 0x9f, 0x76, 0x9e, 0xf3,
+       0xf0, 0xfb, 0x80, 0x7d, 0xe9, 0x2b, 0x80, 0x23, 0xf1, 0xcd, 0x50, 0x4d,
+       0xce, 0x74, 0x78, 0xe1, 0xdd, 0x30, 0x9a, 0x33, 0x78, 0xdb, 0xec, 0xe7,
+       0x48, 0x27, 0xe9, 0x5f, 0x1d, 0xc0, 0x31, 0x2c, 0x38, 0x9e, 0x50, 0x7f,
+       0x9f, 0xf7, 0xc6, 0x0f, 0x6f, 0x5e, 0x8c, 0xff, 0x19, 0xcc, 0xe3, 0x87,
+       0xe5, 0x5d, 0xdd, 0x18, 0x03, 0xfd, 0x2e, 0x62, 0xec, 0x46, 0x5e, 0xdf,
+       0xc3, 0xe7, 0xb5, 0x4a, 0xf5, 0xf2, 0xbb, 0xc3, 0x52, 0x0d, 0x6b, 0xc9,
+       0xee, 0x94, 0xae, 0x7f, 0xc8, 0x77, 0x27, 0xee, 0xbd, 0xb7, 0x75, 0x0d,
+       0x4c, 0xc4, 0x69, 0x58, 0x31, 0x33, 0xc1, 0x82, 0xde, 0xf8, 0xe2, 0x4b,
+       0x5e, 0x7e, 0xaf, 0xbf, 0x18, 0xf3, 0x65, 0xf7, 0x91, 0x9c, 0x88, 0xda,
+       0x8b, 0xba, 0xfb, 0xee, 0x1e, 0xd0, 0xb7, 0xd5, 0xbd, 0xd8, 0x3f, 0x73,
+       0x3b, 0xd7, 0x51, 0xab, 0x4c, 0xf2, 0x2b, 0x0d, 0x5c, 0xd3, 0xa8, 0xc3,
+       0x13, 0x13, 0xaa, 0x04, 0xf7, 0x9a, 0x79, 0x07, 0xab, 0x1a, 0xd1, 0x8b,
+       0xfa, 0x68, 0x17, 0xde, 0xc1, 0x44, 0x8b, 0x83, 0x7d, 0x9f, 0x55, 0xe8,
+       0xaf, 0x08, 0x8f, 0xf7, 0x5d, 0x1c, 0xd3, 0xe1, 0x60, 0x5d, 0xf2, 0xfa,
+       0x15, 0x93, 0x73, 0xfd, 0xab, 0xfb, 0x6e, 0xee, 0xe1, 0x7e, 0x2a, 0x19,
+       0xac, 0xcb, 0x01, 0xf9, 0xfb, 0x24, 0x7e, 0x49, 0x89, 0x5f, 0x54, 0xc7,
+       0x0f, 0xef, 0xed, 0x4f, 0x7d, 0xef, 0x7a, 0xaa, 0x1b, 0xde, 0xbc, 0xfb,
+       0xfc, 0x4f, 0x63, 0xd7, 0xf6, 0x98, 0xb7, 0x0e, 0x57, 0xbb, 0xe7, 0xae,
+       0x43, 0xde, 0x8b, 0x5d, 0x87, 0x30, 0xce, 0x73, 0xbf, 0xbc, 0x38, 0xd3,
+       0x21, 0x79, 0x74, 0x57, 0x44, 0xf2, 0x41, 0xec, 0xfb, 0x22, 0x62, 0xee,
+       0x1b, 0x8c, 0xbf, 0x92, 0xfb, 0xee, 0x97, 0x2a, 0xf4, 0xd9, 0x17, 0x87,
+       0xcc, 0xfb, 0xc4, 0xbc, 0x57, 0xb0, 0xbe, 0x3e, 0xae, 0x04, 0x67, 0xbe,
+       0xff, 0xb5, 0x3f, 0x9c, 0xaf, 0x99, 0x8e, 0x61, 0x1f, 0x5e, 0x2a, 0x16,
+       0x78, 0xbf, 0xc4, 0xe5, 0xfb, 0x45, 0xbf, 0xe0, 0xe1, 0xf0, 0xf9, 0x29,
+       0xd5, 0xf6, 0x13, 0x4d, 0x65, 0x3a, 0x73, 0xb0, 0xa7, 0xd5, 0xed, 0x23,
+       0xc1, 0x27, 0xd4, 0x79, 0x4b, 0xde, 0xc1, 0xf2, 0x5e, 0xd6, 0xef, 0x61,
+       0xf4, 0x73, 0xad, 0x79, 0x8c, 0xc7, 0xd0, 0xb7, 0x39, 0xbf, 0xca, 0xbd,
+       0xb5, 0x75, 0x9b, 0xe9, 0x4b, 0xa7, 0xde, 0x67, 0xee, 0xb9, 0xb6, 0x6a,
+       0xd0, 0x16, 0xee, 0x5b, 0x1f, 0xb2, 0xf3, 0x92, 0x1f, 0x85, 0x77, 0x89,
+       0xff, 0x3d, 0x62, 0xfa, 0x85, 0x73, 0xc5, 0xb8, 0x67, 0xf3, 0xbd, 0x34,
+       0xa1, 0xdf, 0x23, 0x09, 0x6f, 0x9e, 0x25, 0x32, 0x65, 0x82, 0xfb, 0xec,
+       0x9b, 0x40, 0xf7, 0xdc, 0x84, 0xbe, 0xbc, 0xb5, 0x4b, 0x70, 0xb8, 0x91,
+       0x71, 0x5b, 0x3e, 0x9a, 0x0b, 0x7e, 0x67, 0x21, 0x5c, 0x7f, 0x73, 0xfb,
+       0xd1, 0x73, 0x6c, 0xd7, 0xbc, 0x81, 0x3c, 0xf3, 0xcd, 0x55, 0xb3, 0xf8,
+       0xfc, 0xa6, 0x9d, 0x51, 0xd8, 0x99, 0xe9, 0x17, 0xbf, 0xda, 0x6f, 0x01,
+       0xed, 0x92, 0x3a, 0x73, 0xd2, 0x7d, 0x97, 0xc3, 0x4e, 0x53, 0x4f, 0x26,
+       0xbf, 0x13, 0x30, 0x9e, 0x5b, 0xc7, 0x63, 0xd5, 0xbc, 0x95, 0xe4, 0x97,
+       0x4c, 0x7a, 0xcf, 0x16, 0xe2, 0x6e, 0xf2, 0xc1, 0xe4, 0x8f, 0xf7, 0x1d,
+       0x7b, 0x9b, 0xa7, 0x5e, 0xfa, 0xe3, 0xef, 0x70, 0xbe, 0x84, 0x65, 0x3d,
+       0x96, 0xe9, 0xef, 0xbb, 0x3c, 0x3e, 0x6f, 0x01, 0x9f, 0x8c, 0xd8, 0x6d,
+       0xb7, 0xf0, 0x3b, 0x74, 0x96, 0xda, 0x25, 0xf1, 0x39, 0x57, 0x2d, 0x75,
+       0x50, 0xec, 0xfb, 0x49, 0xfa, 0x1f, 0xc4, 0x31, 0x6e, 0x6f, 0xc9, 0x49,
+       0xdc, 0x24, 0x8f, 0x9e, 0x16, 0xbf, 0x7f, 0x84, 0xdf, 0xb6, 0xf1, 0xbb,
+       0xc5, 0xf5, 0xdb, 0xd4, 0x59, 0xaf, 0x9c, 0x99, 0x3a, 0x1f, 0xb8, 0x5e,
+       0xdb, 0x27, 0xf9, 0xdd, 0x53, 0x24, 0xe7, 0xa1, 0x42, 0xbe, 0x3b, 0x38,
+       0xe2, 0x4f, 0x89, 0x6a, 0x5a, 0xee, 0xdd, 0x57, 0x2c, 0xfb, 0x92, 0x7a,
+       0x1f, 0xe6, 0x71, 0xfe, 0xec, 0x29, 0xf0, 0x34, 0xdf, 0x11, 0x8c, 0xdc,
+       0xe0, 0x39, 0xf2, 0xe2, 0xc7, 0x37, 0x13, 0xff, 0x50, 0x07, 0x74, 0x9c,
+       0x6a, 0xcd, 0xf7, 0x07, 0xcc, 0xe3, 0xfc, 0x26, 0xf7, 0xb7, 0xa1, 0xaf,
+       0xdc, 0xdf, 0x76, 0x48, 0xfa, 0x08, 0xc1, 0xe5, 0x81, 0x21, 0xb2, 0x43,
+       0xc7, 0xae, 0xd2, 0x7f, 0xfe, 0x61, 0x47, 0x54, 0xec, 0x28, 0xf7, 0xd8,
+       0x11, 0xd0, 0x7b, 0x1d, 0xcd, 0xaf, 0x50, 0x5f, 0x73, 0x1e, 0x2e, 0x57,
+       0xeb, 0x29, 0x47, 0xf4, 0xbd, 0xb0, 0xae, 0x88, 0xc6, 0xcb, 0xd4, 0xab,
+       0xf0, 0xb7, 0x37, 0x59, 0x84, 0x3a, 0x96, 0xdc, 0x49, 0xf3, 0x35, 0xea,
+       0xd5, 0x3e, 0x0e, 0xc4, 0x2b, 0xea, 0x18, 0xea, 0x73, 0xe3, 0x41, 0xb6,
+       0x47, 0x1d, 0x1f, 0x34, 0xf5, 0x7a, 0xca, 0xef, 0x98, 0xbd, 0xeb, 0xa4,
+       0x5e, 0x9c, 0xc0, 0x77, 0x51, 0xfd, 0x5e, 0x23, 0xfe, 0xd9, 0xe6, 0x3d,
+       0xb8, 0xfb, 0x98, 0xa1, 0x8b, 0x7c, 0xe3, 0xfd, 0x27, 0x96, 0x0a, 0xad,
+       0xf2, 0x8d, 0x07, 0xd6, 0x55, 0x09, 0xad, 0x36, 0xe3, 0xe9, 0xbe, 0x2b,
+       0x5e, 0x29, 0xf9, 0x62, 0xf7, 0x7b, 0xe2, 0xcf, 0x47, 0xe2, 0xcf, 0x59,
+       0xe0, 0x9f, 0xdc, 0x28, 0x78, 0x2c, 0x0a, 0xea, 0x17, 0xbb, 0xdc, 0x73,
+       0x63, 0xd6, 0x11, 0x8f, 0x47, 0xd5, 0x5f, 0x3f, 0x97, 0x8f, 0x31, 0xd8,
+       0x17, 0x00, 0x00, 0x00 };
 
 static const int bnx2_TPAT_b06FwReleaseMajor = 0x1;
 static const int bnx2_TPAT_b06FwReleaseMinor = 0x0;
@@ -2339,201 +1330,199 @@ static const u32 bnx2_TPAT_b06FwBssAddr = 0x08001aa0;
 static const int bnx2_TPAT_b06FwBssLen = 0x250;
 static const u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60;
 static const int bnx2_TPAT_b06FwSbssLen = 0x34;
-static u32 bnx2_TPAT_b06FwText[(0x122c/4) + 1] = {
-       0x0a000218, 0x00000000, 0x00000000, 0x0000000d, 0x74706174, 0x20322e35,
-       0x2e313100, 0x02050b01, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800,
-       0x24421a60, 0x3c030800, 0x24631cf0, 0xac400000, 0x0043202b, 0x1480fffd,
-       0x24420004, 0x3c1d0800, 0x37bd2ffc, 0x03a0f021, 0x3c100800, 0x26100860,
-       0x3c1c0800, 0x279c1a60, 0x0e000546, 0x00000000, 0x0000000d, 0x8f820010,
-       0x8c450008, 0x24030800, 0xaf430178, 0x97430104, 0x3c020008, 0xaf420140,
-       0x8f820024, 0x30420001, 0x10400007, 0x3069ffff, 0x24020002, 0x2523fffe,
-       0xa7420146, 0xa7430148, 0x0a000242, 0x3c020800, 0xa7400146, 0x3c020800,
-       0x8c43083c, 0x1460000e, 0x24020f00, 0x8f820024, 0x30430020, 0x0003182b,
-       0x00031823, 0x30650009, 0x30420c00, 0x24030400, 0x14430002, 0x34a40001,
-       0x34a40005, 0xa744014a, 0x0a000264, 0x3c020800, 0x8f830014, 0x14620008,
-       0x00000000, 0x8f820024, 0x30420020, 0x0002102b, 0x00021023, 0x3042000d,
-       0x0a000262, 0x34420005, 0x8f820024, 0x30420020, 0x0002102b, 0x00021023,
-       0x30420009, 0x34420001, 0xa742014a, 0x3c020800, 0x8c430820, 0x8f840024,
-       0x3c020048, 0x00621825, 0x30840006, 0x24020002, 0x1082000d, 0x2c820003,
-       0x50400005, 0x24020004, 0x10800012, 0x3c020001, 0x0a000284, 0x00000000,
-       0x10820007, 0x24020006, 0x1482000f, 0x3c020111, 0x0a00027c, 0x00621025,
-       0x0a00027b, 0x3c020101, 0x3c020011, 0x00621025, 0x24030001, 0xaf421000,
-       0xaf830020, 0x0a000284, 0x00000000, 0x00621025, 0xaf421000, 0xaf800020,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f830020, 0x1060003f,
-       0x3c048000, 0x8f421000, 0x00441024, 0x1040fffd, 0x00000000, 0x10600039,
-       0x00000000, 0x8f421000, 0x3c030020, 0x00431024, 0x10400034, 0x00000000,
-       0x97421014, 0x14400031, 0x00000000, 0x97421008, 0x8f840010, 0x24420006,
-       0x00024082, 0x00081880, 0x00643821, 0x8ce50000, 0x30430003, 0x30420001,
-       0x10400004, 0x00000000, 0x0000000d, 0x0a0002c3, 0x00081080, 0x5460000f,
-       0x30a5ffff, 0x3c06ffff, 0x00a62824, 0x0005182b, 0x00a61026, 0x0002102b,
-       0x00621824, 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x240001fb,
-       0x8ce20000, 0x0a0002c2, 0x00462825, 0x0005182b, 0x38a2ffff, 0x0002102b,
-       0x00621824, 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x24000205,
-       0x8ce20000, 0x3445ffff, 0x00081080, 0x00441021, 0x3c030800, 0xac450000,
-       0x8c620830, 0x24420001, 0xac620830, 0x8f840018, 0x01202821, 0x24820008,
-       0x30421fff, 0x24434000, 0x0343d821, 0x30a30007, 0xaf84000c, 0xaf820018,
-       0xaf420084, 0x10600002, 0x24a20007, 0x3045fff8, 0x8f820030, 0x8f840000,
-       0x00451821, 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023,
-       0xaf820030, 0x8f840030, 0x34028000, 0x00821021, 0x03421821, 0x3c021000,
-       0xaf830010, 0xaf440080, 0x03e00008, 0xaf420178, 0x8f830024, 0x27bdffe0,
-       0xafbf0018, 0xafb10014, 0x30620200, 0x14400004, 0xafb00010, 0x0000000d,
-       0x00000000, 0x24000242, 0x00031a82, 0x30630003, 0x000310c0, 0x00431021,
-       0x00021080, 0x00431021, 0x00021080, 0x3c030800, 0x24631aa0, 0x00438821,
-       0x8e240000, 0x10800004, 0x00000000, 0x0000000d, 0x00000000, 0x2400024d,
-       0x8f850010, 0x24020001, 0xae220000, 0x8ca70008, 0xa2200007, 0x8f620004,
-       0x26300014, 0x02002021, 0x00021402, 0xa2220004, 0x304600ff, 0x24c60005,
-       0x0e000673, 0x00063082, 0x8f620004, 0xa6220008, 0x8f430108, 0x3c021000,
-       0x00621824, 0x10600008, 0x00000000, 0x97420104, 0x92230007, 0x2442ffec,
-       0x3045ffff, 0x34630002, 0x0a000321, 0xa2230007, 0x97420104, 0x2442fff0,
-       0x3045ffff, 0x8f620004, 0x3042ffff, 0x2c420013, 0x54400005, 0x92230007,
-       0x92220007, 0x34420001, 0xa2220007, 0x92230007, 0x24020001, 0x10620009,
-       0x28620002, 0x14400014, 0x24020002, 0x10620012, 0x24020003, 0x1062000a,
-       0x00000000, 0x0a000342, 0x00000000, 0x8f820010, 0x8c43000c, 0x3c04ffff,
-       0x00641824, 0x00651825, 0x0a000342, 0xac43000c, 0x8f820010, 0x8c430010,
-       0x3c04ffff, 0x00641824, 0x00651825, 0xac430010, 0x8f620004, 0x3042ffff,
-       0x24420002, 0x00021083, 0xa2220005, 0x304500ff, 0x8f820010, 0x3c04ffff,
-       0x00052880, 0x00a22821, 0x8ca70000, 0x96220008, 0x97430104, 0x00e42024,
-       0x24420002, 0x00621823, 0x00833825, 0xaca70000, 0x92240005, 0x00041080,
-       0x02021021, 0x90430000, 0x3c05fff6, 0x34a5ffff, 0x3063000f, 0x00832021,
-       0xa2240006, 0x308200ff, 0x24420003, 0x00021080, 0x02021021, 0x8c460000,
-       0x308300ff, 0x8f820010, 0x3c04ff3f, 0x00031880, 0x00c53824, 0x00621821,
-       0xae26000c, 0xac67000c, 0x8e22000c, 0x92230006, 0x3484ffff, 0x00441024,
-       0x24630003, 0x00031880, 0x02031821, 0x00e42024, 0xae22000c, 0xac640000,
-       0x92220006, 0x24420004, 0x00021080, 0x02021021, 0x94470002, 0xac470000,
-       0x92230006, 0x8f820010, 0x00031880, 0x00621821, 0x24020010, 0xac670010,
-       0x24030002, 0xa7420140, 0xa7400142, 0xa7400144, 0xa7430146, 0x97420104,
-       0x24030001, 0x2442fffe, 0xa7420148, 0xa743014a, 0x8f820024, 0x24030002,
-       0x30440006, 0x1083000d, 0x2c820003, 0x10400005, 0x24020004, 0x10800011,
-       0x3c020009, 0x0a0003a5, 0x00000000, 0x10820007, 0x24020006, 0x1482000d,
-       0x3c020119, 0x0a00039f, 0x24030001, 0x0a00039e, 0x3c020109, 0x3c020019,
-       0x24030001, 0xaf421000, 0xaf830020, 0x0a0003a5, 0x00000000, 0xaf421000,
-       0xaf800020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x92220004,
-       0x24030008, 0x8f840020, 0x24420002, 0x30420007, 0x00621823, 0x30630007,
-       0x10800006, 0xae230010, 0x3c038000, 0x8f421000, 0x00431024, 0x1040fffd,
-       0x00000000, 0x8f820018, 0xaf82000c, 0x24420010, 0x30421fff, 0xaf820018,
-       0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, 0x30620007,
-       0x10400002, 0x24620007, 0x3043fff8, 0x8f820030, 0x8f840000, 0x00431821,
-       0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, 0xaf820030,
-       0x8f840030, 0x34028000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x00821021,
-       0x03421821, 0x3c021000, 0xaf830010, 0xaf440080, 0xaf420178, 0x03e00008,
-       0x27bd0020, 0x8f830024, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0x30620200,
-       0x14400004, 0xafb00010, 0x0000000d, 0x00000000, 0x240002e4, 0x00031a82,
-       0x30630003, 0x000310c0, 0x00431021, 0x00021080, 0x00431021, 0x00021080,
-       0x3c030800, 0x24631aa0, 0x00438021, 0x8e040000, 0x14800004, 0x00000000,
-       0x0000000d, 0x00000000, 0x240002e9, 0x8f620004, 0x04410008, 0x26050014,
-       0x92020006, 0x8e03000c, 0x24420003, 0x00021080, 0x00a21021, 0xac430000,
-       0xae000000, 0x92020005, 0x24420001, 0x00021080, 0x00a21021, 0x8c430000,
-       0x3c040001, 0x00641821, 0xac430000, 0x92060004, 0x27710008, 0x02202021,
-       0x24c60005, 0x0e000673, 0x00063082, 0x92040006, 0x3c057fff, 0x8f620004,
-       0x00042080, 0x00912021, 0x8c830004, 0x34a5ffff, 0x00451024, 0x00621821,
-       0xac830004, 0x92050005, 0x3c07ffff, 0x92040004, 0x00052880, 0x00b12821,
-       0x8ca30000, 0x97420104, 0x96060008, 0x00671824, 0x00441021, 0x00461023,
-       0x3042ffff, 0x00621825, 0xaca30000, 0x92030007, 0x24020001, 0x1062000a,
-       0x28620002, 0x1440001d, 0x2402000a, 0x24020002, 0x10620019, 0x24020003,
-       0x1062000e, 0x2402000a, 0x0a000447, 0x00000000, 0x92020004, 0x97430104,
-       0x8e24000c, 0x00621821, 0x2463fff2, 0x3063ffff, 0x00872024, 0x00832025,
-       0xae24000c, 0x0a000447, 0x2402000a, 0x92020004, 0x97430104, 0x8e240010,
-       0x00621821, 0x2463ffee, 0x3063ffff, 0x00872024, 0x00832025, 0xae240010,
-       0x2402000a, 0xa7420140, 0x96030012, 0x8f840024, 0xa7430142, 0x92020004,
-       0xa7420144, 0xa7400146, 0x97430104, 0x30840006, 0x24020001, 0xa7430148,
-       0xa742014a, 0x24020002, 0x1082000d, 0x2c820003, 0x10400005, 0x24020004,
-       0x10800011, 0x3c020041, 0x0a00046c, 0x00000000, 0x10820007, 0x24020006,
-       0x1482000d, 0x3c020151, 0x0a000466, 0x24030001, 0x0a000465, 0x3c020141,
-       0x3c020051, 0x24030001, 0xaf421000, 0xaf830020, 0x0a00046c, 0x00000000,
-       0xaf421000, 0xaf800020, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x8f820020, 0x8f840018, 0x10400006, 0x92030004, 0x3c058000, 0x8f421000,
-       0x00451024, 0x1040fffd, 0x00000000, 0x2463000a, 0x30620007, 0x10400002,
-       0x24620007, 0x304303f8, 0x00831021, 0x30421fff, 0xaf84000c, 0xaf820018,
-       0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, 0x30620007,
-       0x10400002, 0x24620007, 0x3043fff8, 0x8f820030, 0x8f840000, 0x00431821,
-       0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, 0xaf820030,
-       0x8f840030, 0x34028000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x00821021,
-       0x03421821, 0x3c021000, 0xaf830010, 0xaf440080, 0xaf420178, 0x03e00008,
-       0x27bd0020, 0x8f620000, 0x97430104, 0x3c048000, 0x3045ffff, 0x3066ffff,
-       0x8f420178, 0x00441024, 0x1440fffd, 0x2402000a, 0x30a30007, 0xa7420140,
-       0x24020008, 0x00431023, 0x30420007, 0x24a3fffe, 0xa7420142, 0xa7430144,
-       0xa7400146, 0xa7460148, 0x8f420108, 0x8f830024, 0x30420020, 0x0002102b,
-       0x00021023, 0x30420009, 0x34420001, 0x30630006, 0xa742014a, 0x24020002,
-       0x1062000d, 0x2c620003, 0x10400005, 0x24020004, 0x10600011, 0x3c020041,
-       0x0a0004d6, 0x00000000, 0x10620007, 0x24020006, 0x1462000d, 0x3c020151,
-       0x0a0004d0, 0x24030001, 0x0a0004cf, 0x3c020141, 0x3c020051, 0x24030001,
-       0xaf421000, 0xaf830020, 0x0a0004d6, 0x00000000, 0xaf421000, 0xaf800020,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f820020, 0x24a30008,
-       0x8f850018, 0x10400006, 0x30c6ffff, 0x3c048000, 0x8f421000, 0x00441024,
-       0x1040fffd, 0x00000000, 0x3063ffff, 0x30620007, 0x10400002, 0x24620007,
-       0x3043fff8, 0x00a31021, 0x30421fff, 0x24434000, 0x0343d821, 0x00c02021,
-       0x30830007, 0xaf85000c, 0xaf820018, 0xaf420084, 0x10600002, 0x24820007,
-       0x3044fff8, 0x8f820030, 0x8f850000, 0x00441821, 0xaf82001c, 0x0065102b,
-       0xaf830030, 0x14400002, 0x00651023, 0xaf820030, 0x8f840030, 0x34028000,
-       0x3c030800, 0x8c650834, 0x00821021, 0x03421821, 0xaf830010, 0xaf440080,
-       0x10a00006, 0x2402000e, 0x9383002f, 0x14620004, 0x3c021000, 0x2402043f,
-       0xa7420148, 0x3c021000, 0x03e00008, 0xaf420178, 0x8f820024, 0x30424000,
-       0x10400005, 0x24020800, 0x0000000d, 0x00000000, 0x2400040e, 0x24020800,
-       0xaf420178, 0x97440104, 0x3c030008, 0xaf430140, 0x8f820024, 0x30420001,
-       0x10400006, 0x3085ffff, 0x24020002, 0x24a3fffe, 0xa7420146, 0x0a000526,
-       0xa7430148, 0xa7400146, 0x8f840018, 0x2402000d, 0xa742014a, 0x24830008,
-       0x30631fff, 0x24624000, 0x0342d821, 0x30a20007, 0xaf84000c, 0xaf830018,
-       0xaf430084, 0x10400002, 0x24a20007, 0x3045fff8, 0x8f820030, 0x8f840000,
-       0x00451821, 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023,
-       0xaf820030, 0x8f840030, 0x34028000, 0x00821021, 0x03421821, 0x3c021000,
-       0xaf830010, 0xaf440080, 0x03e00008, 0xaf420178, 0x27bdffe8, 0x3c046008,
-       0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x375b4000,
-       0x00431024, 0x3442380c, 0xac825000, 0x8f430008, 0x3c100800, 0x37428000,
-       0x34630001, 0xaf430008, 0xaf820010, 0x3c02601c, 0xaf800018, 0xaf400080,
-       0xaf400084, 0x8c450008, 0x3c036000, 0x8c620808, 0x3c040800, 0x3c030080,
-       0xac830820, 0x3042fff0, 0x38420010, 0x2c420001, 0xaf850000, 0xaf820004,
-       0x0e000658, 0x00000000, 0x8f420000, 0x30420001, 0x1040fffb, 0x00000000,
-       0x8f430108, 0x8f440100, 0x30622000, 0xaf830024, 0xaf840014, 0x10400004,
-       0x8e02082c, 0x24420001, 0x0a0005c6, 0xae02082c, 0x30620200, 0x14400003,
-       0x24020f00, 0x14820027, 0x24020d00, 0x97420104, 0x1040001c, 0x30624000,
-       0x14400005, 0x00000000, 0x0e00022f, 0x00000000, 0x0a0005bb, 0x00000000,
-       0x8f620008, 0x8f630000, 0x24020030, 0x00031e02, 0x306300f0, 0x10620007,
-       0x28620031, 0x1440002f, 0x24020040, 0x10620007, 0x00000000, 0x0a0005bb,
-       0x00000000, 0x0e0002e8, 0x00000000, 0x0a0005bb, 0x00000000, 0x0e0003db,
-       0x00000000, 0x0a0005bb, 0x00000000, 0x30620040, 0x1440002b, 0x00000000,
-       0x0000000d, 0x00000000, 0x240004b2, 0x0a0005c6, 0x00000000, 0x1482000f,
-       0x30620006, 0x97420104, 0x10400005, 0x30620040, 0x0e000510, 0x00000000,
-       0x0a0005bb, 0x00000000, 0x1440001b, 0x00000000, 0x0000000d, 0x00000000,
-       0x240004c4, 0x0a0005c6, 0x00000000, 0x1040000e, 0x30621000, 0x10400005,
-       0x00000000, 0x0e000688, 0x00000000, 0x0a0005bb, 0x00000000, 0x0e0004a1,
-       0x00000000, 0x8f82002c, 0x24420001, 0xaf82002c, 0x0a0005c6, 0x00000000,
-       0x30620040, 0x14400004, 0x00000000, 0x0000000d, 0x00000000, 0x240004db,
-       0x8f420138, 0x3c034000, 0x00431025, 0xaf420138, 0x0a000566, 0x00000000,
-       0x3c046008, 0x8c835000, 0x3c1a8000, 0x2402ff7f, 0x375b4000, 0x00621824,
-       0x3463380c, 0xac835000, 0x8f420008, 0x3c056000, 0x3c03601c, 0x34420001,
-       0xaf420008, 0x37428000, 0xaf800018, 0xaf820010, 0xaf400080, 0xaf400084,
-       0x8c660008, 0x8ca20808, 0x3c040800, 0x3c030080, 0xac830820, 0x3042fff0,
-       0x38420010, 0x2c420001, 0xaf860000, 0xaf820004, 0x03e00008, 0x00000000,
-       0x3084ffff, 0x30820007, 0x10400002, 0x24820007, 0x3044fff8, 0x8f820018,
-       0x00441821, 0x30631fff, 0x24644000, 0x0344d821, 0xaf82000c, 0xaf830018,
-       0x03e00008, 0xaf430084, 0x3084ffff, 0x30820007, 0x10400002, 0x24820007,
-       0x3044fff8, 0x8f820030, 0x8f830000, 0x00442021, 0xaf82001c, 0x0083102b,
-       0xaf840030, 0x14400002, 0x00831023, 0xaf820030, 0x8f820030, 0x34038000,
-       0x00431821, 0x03432021, 0xaf840010, 0x03e00008, 0xaf420080, 0x8f830024,
-       0x24020002, 0x30630006, 0x1062000d, 0x2c620003, 0x50400005, 0x24020004,
-       0x10600012, 0x3c020001, 0x0a00062a, 0x00000000, 0x10620007, 0x24020006,
-       0x1462000f, 0x3c020111, 0x0a000622, 0x00821025, 0x0a000621, 0x3c020101,
-       0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830020, 0x0a00062a,
-       0x00000000, 0x00821025, 0xaf421000, 0xaf800020, 0x00000000, 0x00000000,
-       0x00000000, 0x03e00008, 0x00000000, 0x8f820020, 0x10400005, 0x3c038000,
-       0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x03e00008, 0x00000000,
-       0x8f820024, 0x27bdffe8, 0x30424000, 0x14400005, 0xafbf0010, 0x0e00022f,
-       0x00000000, 0x0a000656, 0x8fbf0010, 0x8f620008, 0x8f630000, 0x24020030,
-       0x00031e02, 0x306300f0, 0x10620008, 0x28620031, 0x1440000d, 0x8fbf0010,
-       0x24020040, 0x10620007, 0x00000000, 0x0a000656, 0x00000000, 0x0e0002e8,
-       0x00000000, 0x0a000656, 0x8fbf0010, 0x0e0003db, 0x00000000, 0x8fbf0010,
-       0x03e00008, 0x27bd0018, 0x8f840028, 0x1080000f, 0x3c026000, 0x8c430c3c,
-       0x30630fff, 0xaf830008, 0x14600011, 0x3082000f, 0x10400005, 0x308200f0,
-       0x10400003, 0x30820f00, 0x14400006, 0x00000000, 0x0000000d, 0x00000000,
-       0x2400051a, 0x03e00008, 0x00000000, 0x0000000d, 0x00000000, 0x2400051f,
-       0x03e00008, 0x00000000, 0xaf830028, 0x03e00008, 0x00000000, 0x10c00007,
-       0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb,
-       0x24840004, 0x03e00008, 0x00000000, 0x0a000684, 0x00a01021, 0xac860000,
-       0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, 0x24a5ffff,
-       0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x00000000};
+static u8 bnx2_TPAT_b06FwText[] = {
+       0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x57, 0x4d, 0x68,
+       0x1c, 0xe7, 0x19, 0x7e, 0xe7, 0x77, 0x47, 0x62, 0x25, 0x8d, 0x93, 0x3d,
+       0xac, 0x5d, 0xa5, 0x99, 0x91, 0x46, 0x3f, 0x54, 0x26, 0x9e, 0x84, 0xa5,
+       0x56, 0x61, 0x20, 0xe3, 0x99, 0x95, 0x2c, 0x0c, 0x05, 0x07, 0x42, 0x08,
+       0xe4, 0xb2, 0x1d, 0x49, 0x36, 0x85, 0x1e, 0x5a, 0x9a, 0x43, 0xa0, 0x05,
+       0x0f, 0x33, 0xeb, 0x34, 0x87, 0xc5, 0xdb, 0xaa, 0xc5, 0xbe, 0x94, 0xd6,
+       0x95, 0xea, 0xe8, 0xb2, 0x68, 0xe2, 0x53, 0x0f, 0xc5, 0xd8, 0xb4, 0x54,
+       0xd0, 0x53, 0x7b, 0x0a, 0x85, 0x5c, 0x4c, 0x69, 0x20, 0x85, 0x12, 0x44,
+       0x0f, 0x21, 0xd4, 0xad, 0xa7, 0xcf, 0xfb, 0xcd, 0x8c, 0xbc, 0xbb, 0x95,
+       0x5b, 0x1f, 0x02, 0x15, 0xac, 0x66, 0xe6, 0xfb, 0xde, 0xf7, 0xfb, 0x79,
+       0x9f, 0xe7, 0x79, 0xbf, 0xf7, 0x6b, 0xca, 0x34, 0x49, 0xe5, 0xdf, 0x14,
+       0x7e, 0x6f, 0x7f, 0xe3, 0xdb, 0x6f, 0x7f, 0xf5, 0xa5, 0x57, 0x2c, 0xa2,
+       0x57, 0x5e, 0x92, 0x64, 0x5d, 0xa6, 0x2f, 0xe0, 0x4f, 0x21, 0x32, 0xab,
+       0xf1, 0xf9, 0x47, 0x86, 0xec, 0x75, 0xce, 0x04, 0x0e, 0x19, 0x8a, 0x77,
+       0x34, 0xbb, 0xe9, 0x10, 0xf9, 0x83, 0x15, 0x2b, 0xa4, 0x7f, 0xe5, 0x71,
+       0x43, 0x25, 0x6e, 0x7f, 0xc1, 0xfb, 0xe7, 0xb9, 0x7b, 0xe7, 0xed, 0xa3,
+       0xdb, 0x0a, 0x19, 0xa6, 0xd7, 0x31, 0xcc, 0x45, 0x32, 0x66, 0xe1, 0xf3,
+       0xd3, 0xa5, 0x75, 0x8d, 0xa6, 0xab, 0xb1, 0x4c, 0x4a, 0xfa, 0x06, 0xad,
+       0xf5, 0x30, 0x8e, 0xf3, 0x8e, 0x14, 0x66, 0xaa, 0x14, 0xde, 0x32, 0x48,
+       0xf6, 0x7c, 0x29, 0xc8, 0x1c, 0xf4, 0x49, 0x14, 0xb8, 0x35, 0xf2, 0xcd,
+       0x3c, 0xff, 0xa6, 0x2b, 0x93, 0xec, 0x3c, 0xce, 0xe7, 0x17, 0xd6, 0xa5,
+       0x60, 0x7f, 0x43, 0x0a, 0xf7, 0x03, 0xde, 0x37, 0xd6, 0xb1, 0x2e, 0xf9,
+       0xfb, 0xfc, 0xf4, 0x8c, 0xb0, 0x37, 0x4d, 0x9d, 0x06, 0xcd, 0xc8, 0x0e,
+       0xfb, 0x5a, 0x14, 0xba, 0x2b, 0x4d, 0x85, 0xe6, 0xf1, 0x9b, 0xa0, 0x6d,
+       0x97, 0xea, 0x81, 0x4b, 0xaa, 0xe2, 0xc8, 0x14, 0x36, 0x24, 0xfa, 0x65,
+       0x4b, 0xc3, 0xef, 0x92, 0xd4, 0xde, 0xdf, 0x2a, 0xc7, 0x69, 0x50, 0x8a,
+       0xb5, 0x44, 0x0d, 0x5e, 0x5b, 0xe1, 0x1f, 0xb8, 0x2b, 0xa6, 0x4c, 0xf3,
+       0xf8, 0x4d, 0xe1, 0x3d, 0x82, 0x9d, 0x46, 0x41, 0x6b, 0xbc, 0x6f, 0x02,
+       0xef, 0x58, 0x27, 0xc6, 0x0a, 0xc4, 0x3a, 0x2c, 0xac, 0xc3, 0xa1, 0x6e,
+       0x7f, 0x03, 0xfb, 0x58, 0x68, 0x46, 0xa4, 0x53, 0x57, 0xac, 0x7d, 0x8a,
+       0x12, 0x53, 0xa1, 0xe4, 0xac, 0x46, 0xfe, 0x65, 0x15, 0xdf, 0xcf, 0x51,
+       0x6c, 0x4a, 0xb0, 0xe9, 0x96, 0xf8, 0xd5, 0xd0, 0xaf, 0xa3, 0x7d, 0x86,
+       0x92, 0xc6, 0x29, 0x49, 0xf6, 0xbe, 0x8f, 0xf6, 0x05, 0x33, 0xa2, 0xef,
+       0xe1, 0x29, 0xe1, 0xfb, 0x14, 0x8f, 0x87, 0x6f, 0x89, 0x14, 0x87, 0xcc,
+       0x20, 0xb3, 0x28, 0xcd, 0x2a, 0x5f, 0x6e, 0x2f, 0xda, 0xe2, 0x6c, 0x1c,
+       0x3b, 0xd8, 0xf5, 0x5f, 0xa5, 0x8e, 0x49, 0xb1, 0xea, 0xc1, 0xa6, 0xef,
+       0x98, 0x6d, 0xe0, 0xe4, 0x0b, 0x3c, 0xbf, 0xc6, 0xed, 0xfc, 0x87, 0x76,
+       0x8b, 0x14, 0xcf, 0x31, 0x43, 0x6a, 0x51, 0xd1, 0xd7, 0x30, 0x83, 0x5b,
+       0x2f, 0x93, 0x2f, 0xe2, 0x61, 0xe0, 0xdd, 0xc4, 0x9e, 0x74, 0x60, 0x9b,
+       0xf8, 0x32, 0xc5, 0x4d, 0x83, 0xec, 0xd5, 0x2d, 0xf4, 0x7c, 0xdc, 0x53,
+       0x10, 0x67, 0xc6, 0x49, 0x2d, 0xfd, 0x18, 0xd7, 0xdf, 0x62, 0x5d, 0xb1,
+       0x69, 0xd0, 0x0c, 0x75, 0x5e, 0xcf, 0xf3, 0x3b, 0x6e, 0x9e, 0xeb, 0x9e,
+       0xb3, 0xfc, 0x3e, 0xad, 0x34, 0x35, 0x5a, 0x34, 0xf1, 0x44, 0xdc, 0x1c,
+       0xc4, 0x46, 0x2d, 0xe7, 0x9f, 0x2a, 0xd7, 0xfa, 0x48, 0x42, 0xe8, 0xe9,
+       0xcf, 0xbd, 0xdf, 0xf0, 0xde, 0x97, 0xd7, 0x85, 0x7d, 0x9e, 0xef, 0xae,
+       0x3e, 0xcd, 0x5e, 0x93, 0x0b, 0xfb, 0x3c, 0x5f, 0x6b, 0xf1, 0x7c, 0x36,
+       0xf6, 0xc6, 0x9c, 0x24, 0x5a, 0x1b, 0xb8, 0x46, 0xd4, 0xc3, 0xba, 0x1c,
+       0x3c, 0x07, 0x4d, 0xac, 0xdd, 0x5e, 0xb6, 0x24, 0x83, 0x12, 0x27, 0x7f,
+       0x11, 0x3c, 0xf0, 0x43, 0xc7, 0xfe, 0x53, 0xa8, 0xd4, 0x68, 0xcf, 0xad,
+       0x53, 0x37, 0x6b, 0x52, 0x92, 0x75, 0x29, 0xc8, 0x64, 0x8c, 0x5f, 0xa3,
+       0x5d, 0xe7, 0xf3, 0x7c, 0xcd, 0x75, 0x81, 0x33, 0xb1, 0x5f, 0x73, 0x8d,
+       0x66, 0xd1, 0xbf, 0x62, 0x6e, 0x91, 0x8b, 0x98, 0xcb, 0x88, 0xc9, 0xbc,
+       0x78, 0x4f, 0x32, 0x17, 0xfd, 0x14, 0xcb, 0x2d, 0xdb, 0x4c, 0xc8, 0x6e,
+       0x06, 0x0a, 0x99, 0xb2, 0x67, 0xc2, 0x26, 0xa6, 0x76, 0x66, 0xd0, 0x43,
+       0xe5, 0x1d, 0xc1, 0xe3, 0xb4, 0xff, 0x30, 0xbf, 0xb7, 0xd4, 0xa4, 0xfb,
+       0x59, 0x83, 0xee, 0x66, 0x24, 0x47, 0x1c, 0xab, 0x86, 0x49, 0x1f, 0x64,
+       0xd5, 0x3e, 0xc0, 0x65, 0x27, 0x39, 0xa3, 0x40, 0x67, 0x9b, 0xee, 0x03,
+       0xb0, 0xc4, 0x06, 0x0e, 0x31, 0xf6, 0x5c, 0x3d, 0x79, 0x4f, 0xb7, 0xcf,
+       0x6c, 0x3a, 0xf6, 0x7b, 0x21, 0xb3, 0xf3, 0x86, 0x8a, 0xd6, 0xe1, 0x38,
+       0x7c, 0x1d, 0xfe, 0x26, 0x5d, 0x87, 0x5e, 0x64, 0xc4, 0x63, 0xee, 0xc0,
+       0xa0, 0xfd, 0x5e, 0x8d, 0xac, 0x5d, 0x95, 0xa2, 0x7e, 0x83, 0xdc, 0x45,
+       0xdb, 0x22, 0x59, 0x6e, 0xc8, 0x88, 0xdf, 0xdc, 0x6e, 0x4e, 0xeb, 0xae,
+       0x46, 0x87, 0xce, 0x77, 0x75, 0x9a, 0x4e, 0x5c, 0x9d, 0xd8, 0xc6, 0xa0,
+       0xb9, 0xf7, 0x0d, 0x29, 0xec, 0xf3, 0xfa, 0x39, 0xce, 0x46, 0x19, 0x67,
+       0x55, 0x0a, 0x6e, 0xd5, 0x68, 0x7e, 0xe7, 0x6f, 0x79, 0xe0, 0x20, 0xc6,
+       0xe0, 0xf1, 0x66, 0xcb, 0x56, 0x68, 0x12, 0x6d, 0xbb, 0xdc, 0x77, 0x54,
+       0xb6, 0xf3, 0x18, 0x79, 0x1e, 0xb8, 0xcf, 0x53, 0xc0, 0xfc, 0x7e, 0x9d,
+       0x7d, 0x6a, 0x34, 0xb7, 0xc3, 0xba, 0xc0, 0x73, 0x97, 0xbf, 0x79, 0x6d,
+       0x13, 0x14, 0x61, 0x37, 0xd1, 0x72, 0x03, 0xfb, 0x97, 0x85, 0x06, 0x22,
+       0xec, 0x56, 0x76, 0x26, 0xf1, 0x14, 0x71, 0x50, 0x0a, 0x3e, 0x73, 0x5e,
+       0xa8, 0x53, 0x08, 0x5c, 0x55, 0xac, 0x67, 0x8b, 0x16, 0x9a, 0xdb, 0xa2,
+       0x0f, 0x6d, 0x03, 0xee, 0x33, 0xc7, 0xfa, 0xf0, 0x3d, 0xa8, 0xd6, 0x20,
+       0x03, 0xf3, 0x14, 0xb3, 0x68, 0x62, 0xaf, 0x6b, 0x2e, 0xdb, 0xb3, 0x6d,
+       0xbc, 0xac, 0x91, 0xbd, 0xbc, 0x8b, 0xd1, 0xf7, 0x7b, 0xd8, 0xef, 0x4d,
+       0xce, 0x35, 0x8e, 0xf5, 0x17, 0x62, 0xfb, 0x79, 0xec, 0x79, 0x61, 0x35,
+       0xe5, 0xbe, 0x81, 0x46, 0xce, 0x4e, 0x6c, 0xaa, 0x88, 0xbd, 0x8c, 0xc0,
+       0x87, 0x3f, 0xfc, 0x2c, 0xd7, 0x3c, 0x70, 0xb8, 0x35, 0x03, 0x6c, 0x6c,
+       0x2b, 0x85, 0x9e, 0x1d, 0x8c, 0x9b, 0xb8, 0x0a, 0xfc, 0x0a, 0x8c, 0xd8,
+       0x6e, 0xbd, 0x97, 0x53, 0x2a, 0xe6, 0xba, 0xc6, 0x73, 0x21, 0xe7, 0x38,
+       0xab, 0xbf, 0x03, 0x27, 0x22, 0xaa, 0xd3, 0xe2, 0x41, 0x9d, 0xae, 0x0e,
+       0xea, 0x34, 0x77, 0x43, 0x47, 0x1c, 0xf2, 0xbc, 0xdb, 0x62, 0x0d, 0x02,
+       0x6b, 0x87, 0xed, 0xec, 0xa6, 0x22, 0xf3, 0x3a, 0xd0, 0x7f, 0x40, 0xb4,
+       0x35, 0xd0, 0x11, 0x37, 0x75, 0x68, 0x6c, 0x99, 0x2e, 0xfe, 0x84, 0xe8,
+       0xe2, 0x80, 0x7d, 0x79, 0xfc, 0xc2, 0x27, 0xc2, 0x9e, 0x65, 0x60, 0x7e,
+       0x75, 0x20, 0x23, 0x1f, 0x20, 0x5f, 0xee, 0x07, 0xc8, 0x83, 0x6d, 0xfc,
+       0xd6, 0x91, 0x1b, 0x19, 0x1b, 0xce, 0x13, 0x8f, 0x81, 0xcf, 0x06, 0xfa,
+       0x2e, 0xa1, 0x8d, 0xf3, 0x16, 0xdb, 0xea, 0xd4, 0x76, 0xa7, 0x28, 0xad,
+       0x72, 0x91, 0xc9, 0xb9, 0xe8, 0x14, 0xf8, 0x34, 0x81, 0xfc, 0x72, 0x47,
+       0x19, 0xcd, 0x45, 0xc8, 0x59, 0x8d, 0xd3, 0xc8, 0x3d, 0x3f, 0x47, 0x3b,
+       0x8f, 0xf7, 0x33, 0x3c, 0x27, 0xf0, 0x7d, 0x1a, 0xb6, 0xc3, 0x79, 0xa8,
+       0xf2, 0x7b, 0x5a, 0x0e, 0x02, 0xef, 0x76, 0x0c, 0xd8, 0x5b, 0xd0, 0x0b,
+       0xc7, 0xbb, 0x86, 0x7c, 0xc1, 0x31, 0xaf, 0x21, 0xa6, 0x3a, 0xe6, 0x36,
+       0x69, 0xfe, 0x80, 0x62, 0xa5, 0xcc, 0x4f, 0xe1, 0x71, 0x7e, 0x6a, 0x0a,
+       0x1e, 0x24, 0x99, 0x09, 0x1f, 0xd6, 0x6d, 0xa5, 0x53, 0xc6, 0x8e, 0xfc,
+       0x00, 0x1a, 0x0e, 0x94, 0x3c, 0xdf, 0xc4, 0x19, 0x11, 0x01, 0x77, 0x1f,
+       0xda, 0x8d, 0xa0, 0xdd, 0x70, 0x48, 0xbb, 0xe1, 0xff, 0xd4, 0x2e, 0x74,
+       0x09, 0x8d, 0xdc, 0x05, 0xa7, 0x3e, 0xe8, 0x9f, 0xa4, 0x63, 0xd6, 0x30,
+       0x6b, 0xd9, 0xa2, 0x7b, 0x4b, 0xcf, 0xa2, 0xe5, 0xbf, 0x3e, 0xab, 0x96,
+       0x63, 0xd6, 0xb2, 0xca, 0x5a, 0x6e, 0x0c, 0x6b, 0xf9, 0x53, 0xf8, 0x17,
+       0x9a, 0xbc, 0xa0, 0x36, 0x48, 0x5b, 0x04, 0x0e, 0x3b, 0x75, 0x52, 0x6e,
+       0x3c, 0xe1, 0x1b, 0x73, 0x38, 0x1c, 0xe0, 0xdf, 0x81, 0x86, 0x3e, 0x69,
+       0xb4, 0x1d, 0x39, 0x4f, 0xf5, 0xec, 0xe6, 0x96, 0xb0, 0x51, 0x49, 0x47,
+       0xdc, 0xbf, 0xb3, 0x64, 0x5b, 0x96, 0x3c, 0xac, 0x79, 0xa8, 0x7e, 0x27,
+       0xbf, 0xa6, 0x79, 0x3c, 0x4f, 0x6c, 0x81, 0xeb, 0xd6, 0x8f, 0x80, 0x51,
+       0xda, 0x63, 0x9e, 0x3b, 0xe6, 0x9a, 0xe0, 0x17, 0xbe, 0xa1, 0x05, 0x0d,
+       0x7c, 0xad, 0xc1, 0x4e, 0xdd, 0x29, 0xf4, 0x73, 0x17, 0xe3, 0xee, 0xf5,
+       0x98, 0x5f, 0x06, 0xe9, 0x37, 0x9d, 0xe6, 0x55, 0x91, 0x73, 0xe7, 0xcd,
+       0x75, 0x62, 0xed, 0xf1, 0x79, 0x87, 0xfe, 0x41, 0x8d, 0x14, 0xa1, 0xf7,
+       0xc9, 0x52, 0xef, 0x2f, 0x20, 0x46, 0x93, 0xf8, 0x66, 0xcd, 0x9f, 0x2e,
+       0x35, 0x3f, 0x8d, 0x27, 0xb7, 0x5d, 0x54, 0x0b, 0xee, 0x80, 0x87, 0x3b,
+       0x8c, 0x6b, 0x1d, 0xf9, 0x8d, 0xe7, 0xff, 0x7b, 0xbe, 0xe9, 0x30, 0xb6,
+       0x8e, 0xf5, 0x03, 0x5a, 0x80, 0xee, 0xd0, 0x7e, 0xc0, 0xb6, 0xec, 0x53,
+       0xd9, 0x9a, 0xa5, 0xed, 0xa7, 0x63, 0xb6, 0x68, 0x3f, 0x60, 0x3b, 0xd6,
+       0xc5, 0x73, 0xa4, 0xdc, 0xe4, 0xf3, 0x38, 0x60, 0x5d, 0xc0, 0xaf, 0x8d,
+       0x36, 0xae, 0x19, 0xd8, 0x9f, 0xcf, 0x66, 0x5e, 0x27, 0xd7, 0x13, 0x7c,
+       0x7e, 0x8f, 0x9d, 0xd3, 0xc7, 0xda, 0xb8, 0x00, 0xbe, 0x7f, 0x4b, 0xfd,
+       0x4f, 0x6d, 0xbc, 0x06, 0x2d, 0x5c, 0x51, 0x0b, 0x6d, 0x6c, 0xe3, 0x79,
+       0x01, 0xdf, 0xaf, 0x8d, 0x69, 0xa3, 0xf2, 0x7b, 0xfa, 0xf9, 0x9c, 0xf4,
+       0x9b, 0xe2, 0x6c, 0xe5, 0xf9, 0x94, 0x1d, 0x8a, 0xb5, 0x52, 0x07, 0x6b,
+       0xc7, 0x3a, 0x98, 0x44, 0xae, 0x18, 0xe1, 0xb8, 0x12, 0xba, 0xb6, 0x99,
+       0x12, 0x6b, 0x62, 0xf8, 0xfc, 0xfa, 0x7f, 0xe9, 0x82, 0xc0, 0x23, 0x31,
+       0x37, 0x6a, 0x0c, 0x3e, 0x0f, 0xf2, 0xfc, 0x8a, 0x8b, 0xfe, 0xaa, 0xd6,
+       0x10, 0xd8, 0xf3, 0x59, 0xcb, 0x78, 0xa0, 0xbe, 0x73, 0xe6, 0xa1, 0x05,
+       0xce, 0x01, 0x8f, 0xf3, 0x3d, 0x27, 0x40, 0x5b, 0x1b, 0xf1, 0x67, 0x4c,
+       0x36, 0xa4, 0xf5, 0x7d, 0x83, 0xfd, 0xa0, 0xb3, 0x93, 0x6a, 0x2c, 0x1d,
+       0x9a, 0x7a, 0x82, 0x13, 0xf3, 0x28, 0x1a, 0xc2, 0xa9, 0x23, 0x70, 0xfa,
+       0xf0, 0x18, 0xa7, 0xa8, 0xc4, 0x29, 0x12, 0x38, 0xfd, 0xb1, 0xc4, 0xe9,
+       0x0f, 0x4f, 0xc1, 0xe9, 0xc3, 0x67, 0xc0, 0xc9, 0xa0, 0x3d, 0xa7, 0x89,
+       0x73, 0x56, 0x17, 0x35, 0xe9, 0xa1, 0x7b, 0x52, 0x4d, 0x75, 0x52, 0xdc,
+       0x6d, 0x73, 0x8f, 0x86, 0xeb, 0x0e, 0xdb, 0x7a, 0x80, 0xf5, 0xa5, 0xc0,
+       0xee, 0xfa, 0x58, 0xed, 0x91, 0xc0, 0xbe, 0x5d, 0xe2, 0x74, 0x1d, 0x38,
+       0xb5, 0x4b, 0x9c, 0xb6, 0x87, 0x70, 0xda, 0x1e, 0xc1, 0x89, 0xf3, 0x49,
+       0xcb, 0xd8, 0xee, 0x55, 0x18, 0x55, 0xf8, 0xe8, 0x74, 0xdb, 0x9c, 0xc6,
+       0xfe, 0xcf, 0x51, 0xfa, 0x63, 0x95, 0xeb, 0x5a, 0x60, 0xf7, 0xaa, 0x2a,
+       0x8b, 0xf3, 0x80, 0xdf, 0x9f, 0xd4, 0x27, 0x98, 0xcb, 0x0f, 0x5c, 0x8e,
+       0x23, 0xea, 0x57, 0xa7, 0xca, 0x43, 0xcf, 0xab, 0xa8, 0xad, 0xf0, 0xcd,
+       0x36, 0xaa, 0xd4, 0x86, 0xde, 0x15, 0xd4, 0xe5, 0xe1, 0x71, 0x5d, 0x5e,
+       0xc4, 0xe0, 0x7a, 0x59, 0x97, 0xef, 0x39, 0x5c, 0x97, 0x2f, 0x6a, 0x34,
+       0xb9, 0x51, 0x62, 0xc9, 0x9c, 0x9e, 0x42, 0xdf, 0x25, 0x81, 0x79, 0x8a,
+       0xfc, 0xbd, 0x89, 0xfd, 0x47, 0x82, 0x9b, 0xa8, 0xb1, 0x4a, 0xde, 0xa2,
+       0x86, 0xa5, 0x30, 0x2b, 0x62, 0xf5, 0xc5, 0xd6, 0x5d, 0x9f, 0x20, 0x4f,
+       0x1b, 0x1d, 0x15, 0x75, 0xfd, 0xfd, 0x8c, 0xf3, 0x33, 0x5d, 0x4e, 0x7a,
+       0x14, 0x9f, 0xf1, 0xae, 0xe5, 0xc0, 0xdc, 0x7f, 0xeb, 0x3c, 0x9f, 0x33,
+       0xf5, 0xd5, 0xa0, 0x85, 0xf6, 0x81, 0x41, 0xa8, 0x7d, 0x70, 0x4f, 0xa1,
+       0x38, 0x38, 0x2f, 0xa1, 0xc6, 0xc1, 0x37, 0x7c, 0x92, 0x6c, 0xb6, 0x23,
+       0x7b, 0x4d, 0x70, 0x21, 0x26, 0x1f, 0xeb, 0xf4, 0x33, 0x71, 0x57, 0xe9,
+       0x28, 0x9e, 0x81, 0xda, 0x92, 0x0c, 0x9c, 0xf3, 0x88, 0x89, 0x65, 0xa4,
+       0x03, 0xd4, 0x41, 0x38, 0xfb, 0x83, 0x55, 0xc4, 0xe5, 0x2c, 0x70, 0xcb,
+       0x54, 0xf8, 0xbe, 0xa9, 0x17, 0xf7, 0x1c, 0x54, 0x35, 0x22, 0x5e, 0x8f,
+       0x4a, 0x7e, 0x88, 0x3a, 0x4b, 0x6a, 0xf7, 0xc9, 0x8a, 0x5c, 0xf0, 0x1c,
+       0xe7, 0x48, 0x37, 0xe3, 0xda, 0xf9, 0xac, 0x21, 0xdf, 0xe0, 0x5c, 0x7e,
+       0x88, 0x18, 0xe2, 0xfd, 0x80, 0xcf, 0x16, 0x85, 0xeb, 0x6f, 0xdc, 0x67,
+       0x96, 0x90, 0x6b, 0x68, 0x0a, 0x79, 0x0f, 0x79, 0x77, 0x96, 0x71, 0xf2,
+       0x23, 0xc6, 0x4b, 0x9c, 0x1b, 0xe7, 0xe4, 0x62, 0x9e, 0x5f, 0x6b, 0x05,
+       0x7f, 0x71, 0x87, 0x41, 0xfc, 0x36, 0xfb, 0x2e, 0xe7, 0xdb, 0x2f, 0x2b,
+       0x74, 0x44, 0x82, 0x8f, 0xe6, 0xcb, 0xc8, 0xc3, 0xe7, 0xe0, 0xe3, 0x0b,
+       0x2d, 0x16, 0xf5, 0x56, 0xe5, 0xf3, 0xc9, 0xd8, 0x18, 0x1f, 0x29, 0xa3,
+       0xdf, 0x3e, 0xf8, 0xbc, 0x52, 0xce, 0x57, 0xf1, 0xe3, 0x57, 0xe0, 0xc7,
+       0x61, 0xd9, 0xcf, 0x77, 0x16, 0x1d, 0x36, 0xbc, 0x3e, 0xe6, 0x11, 0xdb,
+       0x9b, 0xda, 0xe8, 0x18, 0x5f, 0x1a, 0xf3, 0xff, 0xfd, 0x90, 0xff, 0x34,
+       0xef, 0xc9, 0x8c, 0x0a, 0x0e, 0xe2, 0xef, 0x3d, 0x7d, 0xd4, 0xf7, 0x17,
+       0x6a, 0xf1, 0x7d, 0xb6, 0xe0, 0x9e, 0x83, 0x67, 0x76, 0x38, 0xb4, 0x36,
+       0x75, 0x6c, 0xec, 0x87, 0x18, 0x7b, 0x15, 0x79, 0x84, 0x7c, 0x05, 0x77,
+       0xa6, 0x90, 0xf0, 0x9e, 0x5d, 0xa9, 0xe2, 0x03, 0x4e, 0xd0, 0xe5, 0xb4,
+       0xe4, 0x82, 0x5c, 0x70, 0x81, 0xeb, 0xb4, 0xd5, 0x4d, 0x70, 0x21, 0x05,
+       0x17, 0xe0, 0xd7, 0xd1, 0xbc, 0x59, 0xe0, 0xcc, 0x39, 0x07, 0xdf, 0x19,
+       0xf3, 0x82, 0x79, 0xc0, 0x9c, 0x78, 0xc2, 0x85, 0x2b, 0x3d, 0xc3, 0xd8,
+       0xfd, 0x2f, 0x3c, 0x78, 0x57, 0xf0, 0x80, 0xf9, 0x58, 0xe4, 0x85, 0x2e,
+       0x70, 0x48, 0xca, 0xbc, 0x50, 0xe8, 0x9c, 0xeb, 0x1b, 0xd6, 0x78, 0xa1,
+       0x8d, 0x2d, 0x68, 0xa3, 0xad, 0x70, 0xbd, 0xc3, 0xba, 0x60, 0x3f, 0xd6,
+       0xc6, 0x49, 0x7e, 0x85, 0x46, 0xd2, 0xbe, 0x6d, 0x55, 0xf9, 0x21, 0x85,
+       0x2e, 0xba, 0xa5, 0x46, 0xd2, 0x52, 0x23, 0xb0, 0x89, 0x95, 0x16, 0xe7,
+       0x7a, 0xdb, 0x0a, 0x91, 0x17, 0xba, 0x62, 0xcc, 0x98, 0x8a, 0x3b, 0x09,
+       0xeb, 0x96, 0xf3, 0xe9, 0x50, 0x1e, 0x2d, 0xef, 0xa5, 0x1d, 0x71, 0x2f,
+       0xfd, 0x8a, 0x3e, 0x9a, 0x47, 0x67, 0x90, 0x43, 0xf8, 0x5e, 0x3a, 0xa7,
+       0xf3, 0xbd, 0x14, 0xba, 0xd3, 0x87, 0xef, 0xa5, 0xc9, 0xc8, 0xbd, 0xb4,
+       0xf2, 0xe5, 0xf6, 0x93, 0xf2, 0x69, 0x15, 0x13, 0xce, 0xa9, 0x02, 0xf3,
+       0x13, 0x6a, 0xbf, 0xca, 0x86, 0xf3, 0x0d, 0x6b, 0xb9, 0xcc, 0x51, 0xa8,
+       0xb5, 0xee, 0x67, 0x15, 0xe7, 0xdf, 0xc0, 0x3c, 0xf8, 0xee, 0x9f, 0xc4,
+       0x79, 0xa3, 0xe4, 0xfc, 0x54, 0xe1, 0xd3, 0x1f, 0xe6, 0xfd, 0x1b, 0xfa,
+       0x28, 0xef, 0xab, 0x71, 0x2a, 0xde, 0x17, 0x63, 0x3e, 0x54, 0x9a, 0x38,
+       0xdb, 0x96, 0x91, 0x6b, 0x66, 0xf8, 0xbe, 0x85, 0x5c, 0xe0, 0xd5, 0x71,
+       0xef, 0x98, 0xe1, 0xb1, 0xd3, 0x0c, 0xe7, 0x4d, 0x03, 0xbc, 0x17, 0x9c,
+       0x3d, 0x12, 0xf7, 0x01, 0xac, 0x7b, 0x86, 0xab, 0xab, 0x51, 0x2e, 0xbe,
+       0x88, 0x0b, 0x45, 0xb5, 0x97, 0xaa, 0xcd, 0x19, 0x6a, 0x5b, 0x2e, 0xb1,
+       0x2e, 0x62, 0xfd, 0xa0, 0xb8, 0x8f, 0xd3, 0x2e, 0x6a, 0xb1, 0x43, 0xd4,
+       0x39, 0x77, 0x70, 0x9f, 0x4b, 0x06, 0x8f, 0xf2, 0x07, 0x0d, 0x95, 0xba,
+       0xc7, 0x3e, 0x5d, 0xac, 0xd7, 0x36, 0x6f, 0xe3, 0xed, 0xdd, 0x41, 0x15,
+       0x53, 0xee, 0xe7, 0xb6, 0x7f, 0xe0, 0xbc, 0x45, 0x1d, 0x37, 0x32, 0x67,
+       0xf5, 0xce, 0x7f, 0xff, 0x06, 0x63, 0xe1, 0x4b, 0x7b, 0x30, 0x12, 0x00,
+       0x00, 0x00 };
 
 static u32 bnx2_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 };
 static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 };
@@ -2554,939 +1543,422 @@ static const u32 bnx2_TXP_b06FwBssAddr = 0x080057a0;
 static const int bnx2_TXP_b06FwBssLen = 0x1c4;
 static const u32 bnx2_TXP_b06FwSbssAddr = 0x08005760;
 static const int bnx2_TXP_b06FwSbssLen = 0x38;
-static u32 bnx2_TXP_b06FwText[(0x5748/4) + 1] = {
-       0x0a000d2c, 0x00000000, 0x00000000, 0x0000000d, 0x74787020, 0x322e352e,
-       0x38000000, 0x02050800, 0x0000000a, 0x000003e8, 0x0000ea60, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800,
-       0x24425760, 0x3c030800, 0x24635964, 0xac400000, 0x0043202b, 0x1480fffd,
-       0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x261034b0,
-       0x3c1c0800, 0x279c5760, 0x0e000f5b, 0x00000000, 0x0000000d, 0x8f840014,
-       0x27bdffe8, 0xafb10014, 0xafb00010, 0x8f460104, 0x8f830008, 0x8c8500ac,
-       0xaf430080, 0x948200a8, 0xa7420e10, 0x948300aa, 0xa7430e12, 0x8c8200ac,
-       0xaf420e18, 0x97430e10, 0xa7430e14, 0x97420e12, 0x00008021, 0xa7420e16,
-       0x8f430e18, 0x00006021, 0x00c53023, 0xaf430e1c, 0x10c001a2, 0x2d820001,
-       0x3c0e1000, 0x2419fff8, 0x24110010, 0x240f0f00, 0x3c188100, 0x93620008,
-       0x10400009, 0x00000000, 0x97620010, 0x00c2102b, 0x14400005, 0x00000000,
-       0x97620010, 0x3042ffff, 0x0a000d6d, 0xaf420e00, 0xaf460e00, 0x8f420000,
-       0x30420008, 0x1040fffd, 0x00000000, 0x97420e08, 0x8f450e04, 0x3044ffff,
-       0x30820001, 0x14400005, 0x00000000, 0x14a00005, 0x3083a040, 0x0a000f34,
-       0x00000000, 0x0000000d, 0x3083a040, 0x24020040, 0x1462004f, 0x3082a000,
-       0x308a0036, 0x8f88000c, 0x30890008, 0x24020800, 0xaf420178, 0x01001821,
-       0x9742008a, 0x00431023, 0x2442ffff, 0x30421fff, 0x2c420008, 0x1440fffa,
-       0x00a06021, 0x8f820018, 0x00cc3023, 0x24070001, 0x8f830008, 0x304b00ff,
-       0x24420001, 0xaf820018, 0x25024000, 0x106f0005, 0x03422021, 0x93820012,
-       0x30420007, 0x00021240, 0x34470001, 0x000b1400, 0x3c030100, 0x00431025,
-       0xac820000, 0x8f830018, 0x00ea3825, 0x1120000f, 0xac830004, 0x97430e0a,
-       0x8f84000c, 0x00ee3825, 0x2402000e, 0x00781825, 0xaf430160, 0x25830006,
-       0x24840008, 0x30841fff, 0xa742015a, 0xa7430158, 0xaf84000c, 0x0a000db7,
-       0x00000000, 0x8f83000c, 0x25820002, 0xa7420158, 0x24630008, 0x30631fff,
-       0xaf83000c, 0x54c0000f, 0x8f420e14, 0x8f820008, 0x504f0002, 0x24100001,
-       0x34e70040, 0x97420e10, 0x97430e12, 0x8f850014, 0x00021400, 0x00621825,
-       0xaca300a8, 0x8f840014, 0x8f420e18, 0xac8200ac, 0x8f420e14, 0x8f430e1c,
-       0xaf420144, 0xaf430148, 0xa34b0152, 0xaf470154, 0x0a000efb, 0xaf4e0178,
-       0x10400165, 0x00000000, 0x93620008, 0x50400008, 0xafa60008, 0x97620010,
-       0x00a2102b, 0x10400003, 0x30820040, 0x1040015c, 0x00000000, 0xafa60008,
-       0xa7840010, 0xaf850004, 0x93620008, 0x1440005f, 0x27ac0008, 0xaf60000c,
-       0x97820010, 0x30424000, 0x10400002, 0x2403000e, 0x24030016, 0xa363000a,
-       0x24034007, 0xaf630014, 0x93820012, 0x8f630014, 0x30420007, 0x00021240,
-       0x00621825, 0xaf630014, 0x97820010, 0x8f630014, 0x30420010, 0x00621825,
-       0xaf630014, 0x97820010, 0x30420008, 0x5040000e, 0x00002821, 0x8f620014,
-       0x004e1025, 0xaf620014, 0x97430e0a, 0x2402000e, 0x00781825, 0xaf630004,
-       0xa3620002, 0x9363000a, 0x3405fffc, 0x24630004, 0x0a000e06, 0xa363000a,
-       0xaf600004, 0xa3600002, 0x97820010, 0x9363000a, 0x30421f00, 0x00021182,
-       0x24420028, 0x00621821, 0xa3630009, 0x97420e0c, 0xa7620010, 0x93630009,
-       0x24020008, 0x24630002, 0x30630007, 0x00431023, 0x30420007, 0xa362000b,
-       0x93640009, 0x97620010, 0x8f890004, 0x97830010, 0x00441021, 0x00a21021,
-       0x30630040, 0x10600007, 0x3045ffff, 0x00a9102b, 0x14400005, 0x0125102b,
-       0x3c068000, 0x0a000e3a, 0x00005821, 0x0125102b, 0x544000c7, 0x00006021,
-       0x97420e14, 0xa7420e10, 0x97430e16, 0xa7430e12, 0x8f420e1c, 0xaf420e18,
-       0xaf450e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000, 0x97420e08,
-       0x00a04821, 0xa7820010, 0x8f430e04, 0x00003021, 0x240b0001, 0xaf830004,
-       0x97620010, 0x0a000e4c, 0x304dffff, 0x8f890004, 0x97820010, 0x30420040,
-       0x10400004, 0x01206821, 0x3c068000, 0x0a000e4c, 0x00005821, 0x97630010,
-       0x8f820004, 0x10430003, 0x00003021, 0x0a000eee, 0x00006021, 0x240b0001,
-       0x8d820000, 0x00491023, 0x1440000d, 0xad820000, 0x8f620014, 0x34420040,
-       0xaf620014, 0x97430e10, 0x97420e12, 0x8f840014, 0x00031c00, 0x00431025,
-       0xac8200a8, 0x8f830014, 0x8f420e18, 0xac6200ac, 0x93620008, 0x1440003e,
-       0x00000000, 0x25260002, 0x8f84000c, 0x9743008a, 0x3063ffff, 0xafa30000,
-       0x8fa20000, 0x00441023, 0x2442ffff, 0x30421fff, 0x2c420010, 0x1440fff7,
-       0x00000000, 0x8f82000c, 0x8f830018, 0x00021082, 0x00021080, 0x24424000,
-       0x03422821, 0x00605021, 0x24630001, 0x314200ff, 0x00021400, 0xaf830018,
-       0x3c033200, 0x00431025, 0xaca20000, 0x93630009, 0x9362000a, 0x00031c00,
-       0x00431025, 0xaca20004, 0x8f830018, 0xaca30008, 0x97820010, 0x30420008,
-       0x10400002, 0x00c04021, 0x25280006, 0x97430e14, 0x93640002, 0x8f450e1c,
-       0x8f660004, 0x8f670014, 0x3063ffff, 0xa7430144, 0x97420e16, 0xa7420146,
-       0xaf450148, 0xa34a0152, 0x8f82000c, 0x308400ff, 0xa744015a, 0xaf460160,
-       0xa7480158, 0xaf470154, 0xaf4e0178, 0x00511021, 0x30421fff, 0xaf82000c,
-       0x0a000ed9, 0x8d820000, 0x93620009, 0x9363000b, 0x8f85000c, 0x2463000a,
-       0x00435021, 0x25440007, 0x00992024, 0x9743008a, 0x3063ffff, 0xafa30000,
-       0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b, 0x1440fff7,
-       0x00000000, 0x8f82000c, 0x8f840018, 0x00021082, 0x00021080, 0x24424000,
-       0x03422821, 0x00804021, 0x24840001, 0xaf840018, 0x93630009, 0x310200ff,
-       0x00022400, 0x3c024100, 0x24630002, 0x00621825, 0x00832025, 0xaca40000,
-       0x8f62000c, 0x00461025, 0xaca20004, 0x97430e14, 0x93640002, 0x8f450e1c,
-       0x8f660004, 0x8f670014, 0x3063ffff, 0xa7430144, 0x97420e16, 0x308400ff,
-       0xa7420146, 0xaf450148, 0xa3480152, 0x8f83000c, 0x25420007, 0x00591024,
-       0xa744015a, 0xaf460160, 0xa7490158, 0xaf470154, 0xaf4e0178, 0x00621821,
-       0x30631fff, 0xaf83000c, 0x8d820000, 0x14400005, 0x00000000, 0x8f620014,
-       0x2403ffbf, 0x00431024, 0xaf620014, 0x8f62000c, 0x004d1021, 0xaf62000c,
-       0x93630008, 0x14600008, 0x00000000, 0x11600006, 0x00000000, 0x8f630014,
-       0x3c02efff, 0x3442fffe, 0x00621824, 0xaf630014, 0xa36b0008, 0x01206021,
-       0x1580000c, 0x8fa60008, 0x97420e14, 0x97430e16, 0x8f850014, 0x00021400,
-       0x00621825, 0xaca300a8, 0x8f840014, 0x8f420e1c, 0xac8200ac, 0x0a000efd,
-       0x2d820001, 0x14c0fe65, 0x2d820001, 0x00501025, 0x10400058, 0x24020f00,
-       0x8f830008, 0x14620023, 0x3c048000, 0x11800009, 0x3c038000, 0x97420e08,
-       0x30420040, 0x14400005, 0x00000000, 0x0000000d, 0x00000000, 0x2400032c,
-       0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x00000000, 0x97420e10,
-       0x3c030500, 0x00431025, 0xaf42014c, 0x97430e14, 0xa7430144, 0x97420e16,
-       0xa7420146, 0x8f430e1c, 0x24022000, 0xaf430148, 0x3c031000, 0xa3400152,
-       0xa740015a, 0xaf400160, 0xa7400158, 0xaf420154, 0xaf430178, 0x8f830008,
-       0x3c048000, 0x8f420178, 0x00441024, 0x1440fffd, 0x24020f00, 0x10620016,
-       0x00000000, 0x97420e14, 0xa7420144, 0x97430e16, 0xa7430146, 0x8f420e1c,
-       0x3c031000, 0xaf420148, 0x0a000f51, 0x24020240, 0x97420e14, 0x97430e16,
-       0x8f840014, 0x00021400, 0x00621825, 0xac8300a8, 0x8f850014, 0x8f420e1c,
-       0x00006021, 0xaca200ac, 0x0a000efd, 0x2d820001, 0xaf40014c, 0x11800007,
-       0x00000000, 0x97420e10, 0xa7420144, 0x97430e12, 0xa7430146, 0x0a000f4e,
-       0x8f420e18, 0x97420e14, 0xa7420144, 0x97430e16, 0xa7430146, 0x8f420e1c,
-       0xaf420148, 0x24020040, 0x3c031000, 0xa3400152, 0xa740015a, 0xaf400160,
-       0xa7400158, 0xaf420154, 0xaf430178, 0x8fb10014, 0x8fb00010, 0x03e00008,
-       0x27bd0018, 0x27bdffd0, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008,
-       0x03421821, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c,
-       0xafb20018, 0xafb10014, 0xafb00010, 0xaf830014, 0xaf440e00, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd,
-       0x3c046004, 0xaf420e00, 0x8c835000, 0x24160800, 0x24150d00, 0x3c140800,
-       0x24130f00, 0x3c120800, 0x3c114000, 0x2402ff7f, 0x00621824, 0x3463380c,
-       0x24020009, 0xac835000, 0xaf420008, 0xaf800018, 0xaf80000c, 0x0e001559,
-       0x00000000, 0x0e000ff0, 0x00000000, 0x3c020800, 0x245057c0, 0x8f420000,
-       0x30420001, 0x1040fffd, 0x00000000, 0x8f440100, 0xaf840008, 0xaf440020,
-       0xaf560178, 0x93430108, 0xa3830012, 0x93820012, 0x30420001, 0x10400008,
-       0x00000000, 0x93820012, 0x30420006, 0x00021100, 0x0e000d43, 0x0050d821,
-       0x0a000fac, 0x00000000, 0x14950005, 0x00000000, 0x0e000d43, 0x269b5840,
-       0x0a000fac, 0x00000000, 0x14930005, 0x00000000, 0x0e000d43, 0x265b5860,
-       0x0a000fac, 0x00000000, 0x0e0010ea, 0x00000000, 0xaf510138, 0x0a000f89,
-       0x00000000, 0x27bdfff8, 0x3084ffff, 0x24820007, 0x3044fff8, 0x8f85000c,
-       0x9743008a, 0x3063ffff, 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff,
-       0x30421fff, 0x0044102b, 0x1440fff7, 0x00000000, 0x8f82000c, 0x00021082,
-       0x00021080, 0x24424000, 0x03421021, 0x03e00008, 0x27bd0008, 0x3084ffff,
-       0x8f82000c, 0x24840007, 0x3084fff8, 0x00441021, 0x30421fff, 0xaf82000c,
-       0x03e00008, 0x00000000, 0x27bdffe8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd,
-       0x3c020008, 0x03421821, 0xafbf0010, 0xaf830014, 0xaf440e00, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd,
-       0x3c046004, 0xaf420e00, 0x8c825000, 0x2403ff7f, 0x00431024, 0x3442380c,
-       0x24030009, 0xac825000, 0xaf430008, 0xaf800018, 0xaf80000c, 0x0e001559,
-       0x00000000, 0x0e000ff0, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018,
-       0x27bdffe8, 0x3c02000a, 0x03421821, 0x3c040800, 0x24845880, 0x24050019,
-       0xafbf0010, 0xaf830024, 0x0e001565, 0x00003021, 0x3c050800, 0x3c020800,
-       0x24425330, 0xaca258e8, 0x24a558e8, 0x3c020800, 0x244254f8, 0x3c030800,
-       0x2463550c, 0x3c040800, 0xaca20004, 0x3c020800, 0x24425338, 0xaca30008,
-       0xac825900, 0x24845900, 0x3c020800, 0x244253c4, 0x3c070800, 0x24e75404,
-       0x3c060800, 0x24c65520, 0x3c050800, 0x24a55438, 0x3c030800, 0xac820004,
-       0x3c020800, 0x24425528, 0xac870008, 0xac86000c, 0xac850010, 0xac625920,
-       0x24635920, 0x8fbf0010, 0x3c020800, 0x24425540, 0xac620004, 0x3c020800,
-       0xac670008, 0xac66000c, 0xac650010, 0xac400048, 0x03e00008, 0x27bd0018,
-       0x974309da, 0x00804021, 0xad030000, 0x8f4209dc, 0xad020004, 0x8f4309e0,
-       0xad030008, 0x934409d9, 0x24020001, 0x30840003, 0x1082001f, 0x30a900ff,
-       0x28820002, 0x10400005, 0x24020002, 0x10800009, 0x3c0a0800, 0x0a001078,
-       0x93420934, 0x1082000b, 0x24020003, 0x10820026, 0x3c0a0800, 0x0a001078,
-       0x93420934, 0x974209e4, 0x00021400, 0x34420800, 0xad02000c, 0x0a001077,
-       0x25080010, 0x974209e4, 0x00021400, 0x34428100, 0xad02000c, 0x974309e8,
-       0x3c0a0800, 0x00031c00, 0x34630800, 0xad030010, 0x0a001077, 0x25080014,
-       0x974409e4, 0x3c050800, 0x24a25880, 0x9443001c, 0x94460014, 0x94470010,
-       0x00a05021, 0x24020800, 0xad000010, 0xad020014, 0x00042400, 0x00661821,
-       0x00671823, 0x2463fff2, 0x00832025, 0xad04000c, 0x0a001077, 0x25080018,
-       0x974209e4, 0x3c050800, 0x00021400, 0x34428100, 0xad02000c, 0x974409e8,
-       0x24a25880, 0x9443001c, 0x94460014, 0x94470010, 0x00a05021, 0x24020800,
-       0xad000014, 0xad020018, 0x00042400, 0x00661821, 0x00671823, 0x2463ffee,
-       0x00832025, 0xad040010, 0x2508001c, 0x93420934, 0x93450921, 0x3c074000,
-       0x25445880, 0x94830018, 0x94860014, 0x00021082, 0x00021600, 0x00052c00,
-       0x00a72825, 0x00451025, 0x00661821, 0x00431025, 0xad020000, 0x9783002c,
-       0x974209ea, 0x00621821, 0x00031c00, 0xad030004, 0x9782002c, 0x24420001,
-       0x30427fff, 0xa782002c, 0x93430920, 0x3c020006, 0x00031e00, 0x00621825,
-       0xad030008, 0x8f42092c, 0xad02000c, 0x8f430930, 0xad030010, 0x8f440938,
-       0x25080014, 0xad040000, 0x8f820020, 0x11200004, 0xad020004, 0x8f420940,
-       0x0a0010a1, 0x2442ffff, 0x8f420940, 0xad020008, 0x8f440948, 0x8f420940,
-       0x93430936, 0x00823023, 0x00663006, 0x3402ffff, 0x0046102b, 0x54400001,
-       0x3406ffff, 0x93420937, 0x25445880, 0x90830024, 0xad000010, 0x00021700,
-       0x34630010, 0x00031c00, 0x00431025, 0x00461025, 0xad02000c, 0x8c830008,
-       0x14600031, 0x25080014, 0x3c020800, 0x8c430048, 0x1060002d, 0x00000000,
-       0x9342010b, 0xad020000, 0x8f830000, 0x8c6200b0, 0xad020004, 0x8f830000,
-       0x8c6200b4, 0xad020008, 0x8f830000, 0x8c6200c0, 0xad02000c, 0x8f830000,
-       0x8c6200c4, 0xad020010, 0x8f830000, 0x8c6200c8, 0xad020014, 0x8f830000,
-       0x8c6200cc, 0xad020018, 0x8f830000, 0x8c6200e0, 0xad02001c, 0x8f830000,
-       0x8c6200e8, 0xad020020, 0x8f830000, 0x8c6200f0, 0x3c04600e, 0xad020024,
-       0x8c8200d0, 0xad020028, 0x8c8300d4, 0xad03002c, 0x8f820028, 0x3c046012,
-       0xad020030, 0x8c8200a8, 0xad020034, 0x8c8300ac, 0x3c026000, 0xad030038,
-       0x8c434448, 0xad03003c, 0x03e00008, 0x01001021, 0x27bdffa8, 0x3c020008,
-       0x03423021, 0xafbf0054, 0xafbe0050, 0xafb7004c, 0xafb60048, 0xafb50044,
-       0xafb40040, 0xafb3003c, 0xafb20038, 0xafb10034, 0xafb00030, 0xaf860000,
-       0x24020040, 0xaf420814, 0xaf400810, 0x8f420944, 0x8f430950, 0x8f440954,
-       0x8f45095c, 0xaf820034, 0xaf830020, 0xaf84001c, 0xaf850030, 0x90c20000,
-       0x24030020, 0x304400ff, 0x10830005, 0x24020030, 0x10820022, 0x3c030800,
-       0x0a001139, 0x8c62002c, 0x24020088, 0xaf420818, 0x3c020800, 0x244258e8,
-       0xafa20020, 0x93430109, 0x3c020800, 0x10600009, 0x24575900, 0x3c026000,
-       0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000,
-       0x24000376, 0x9342010a, 0x30420080, 0x14400021, 0x24020800, 0x3c026000,
-       0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000,
-       0x2400037d, 0x0a001141, 0x24020800, 0x93430109, 0x3063007f, 0x00031140,
-       0x000318c0, 0x00431021, 0x24430088, 0xaf430818, 0x0000000d, 0x3c020800,
-       0x24425940, 0x3c030800, 0x24775950, 0x0a001140, 0xafa20020, 0x24420001,
-       0xac62002c, 0x0000000d, 0x00000000, 0x24000395, 0x0a0014c1, 0x8fbf0054,
-       0x24020800, 0xaf420178, 0x8f450104, 0x8f420988, 0x00a21023, 0x58400005,
-       0x8f4309a0, 0x0000000d, 0x00000000, 0x240003b1, 0x8f4309a0, 0x3c100800,
-       0xae0358b0, 0x8f4209a4, 0x8f830020, 0x260458b0, 0x2491ffd0, 0xae220034,
-       0x00a21023, 0xae230028, 0xac82ffd0, 0x8fa30020, 0x8c620000, 0x0040f809,
-       0x0200b021, 0x00409021, 0x32440010, 0x32420002, 0x10400007, 0xafa40024,
-       0x8e220020, 0x32530040, 0x2403ffbf, 0x00431024, 0x0a001493, 0xae220020,
-       0x32420020, 0x10400002, 0x3c020800, 0x24575920, 0x32420001, 0x14400007,
-       0x00000000, 0x8f820008, 0xaf420080, 0x8ec358b0, 0xaf430e10, 0x8e220034,
-       0xaf420e18, 0x9343010b, 0x93420905, 0x30420008, 0x1040003c, 0x307400ff,
-       0x8f820000, 0x8c430074, 0x0460000a, 0x00000000, 0x3c026000, 0x24030100,
-       0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x240003ed,
-       0x8f820000, 0x9044007b, 0x9343010a, 0x14830027, 0x32530040, 0x00003821,
-       0x24052000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd,
-       0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030100,
-       0xaf420148, 0x24020047, 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000,
-       0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001, 0xad230030,
-       0x9342010a, 0x3c030047, 0xafa50014, 0x00021600, 0x00431025, 0x00471025,
-       0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b,
-       0x3c070100, 0x3c050800, 0x24a25880, 0x0a001250, 0x8c430020, 0x32820002,
-       0x10400050, 0x00000000, 0x0e0015b9, 0x32530040, 0x3c039000, 0x34630001,
-       0x8f820008, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024,
-       0x1440fffd, 0x00000000, 0x8f830000, 0x90620005, 0x34420008, 0xa0620005,
-       0x8f840000, 0x8c820074, 0x3c038000, 0x00431025, 0xac820074, 0x90830000,
-       0x24020020, 0x10620004, 0x00000000, 0x0000000d, 0x00000000, 0x2400040b,
-       0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x9084007b,
-       0x9342010a, 0x14820028, 0x3c030800, 0x00003821, 0x24052000, 0x3c090800,
-       0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, 0x26c458b0,
-       0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030100, 0xaf420148, 0x24020046,
-       0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7470158, 0xaf450154,
-       0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030046,
-       0xafa50014, 0x00021600, 0x00431025, 0x00471025, 0xafa20010, 0x9343010b,
-       0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x3c070100, 0x3c030800,
-       0x24625880, 0x0a001250, 0x8c430020, 0x93420108, 0x30420010, 0x50400056,
-       0x9343093f, 0x8f860000, 0x90c2007f, 0x8cc30178, 0x304800ff, 0x15030004,
-       0x00000000, 0x0000000d, 0x00000000, 0x24000425, 0x90c2007e, 0x90c40080,
-       0x00081c00, 0x00021600, 0x00431025, 0x00042200, 0x90c3007a, 0x90c5000a,
-       0x00441025, 0x11050028, 0x00623825, 0xa0c8000a, 0x00004021, 0x24056000,
-       0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0,
-       0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, 0xaf420148, 0x24020052,
-       0xaf47014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7480158, 0xaf450154,
-       0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030052,
-       0xafa50014, 0x00021600, 0x00431025, 0x00481025, 0xafa20010, 0x9343010b,
-       0xafa30018, 0x8f440100, 0x0e00159b, 0x8f450104, 0x0a00124a, 0x00000000,
-       0x3c026000, 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d,
-       0x00000000, 0x2400043e, 0x16800009, 0x3c050800, 0x3c040800, 0x24825880,
-       0x8c430020, 0x32530040, 0x2404ffbf, 0x00641824, 0x0a001493, 0xac430020,
-       0x8ca25880, 0x10400005, 0x3c030800, 0x8c620034, 0xaca05880, 0x24420001,
-       0xac620034, 0x9343093f, 0x24020012, 0x5462000e, 0x97420908, 0x32820038,
-       0x14400009, 0x3c030800, 0x8f830000, 0x8c62004c, 0xac62005c, 0x3c020800,
-       0x24445880, 0x8c820020, 0x0a001285, 0x32530040, 0xac605880, 0x97420908,
-       0x5440001c, 0x97420908, 0x3c039000, 0x34630001, 0x8f820008, 0x32530040,
-       0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, 0x1440fffd,
-       0x3c028000, 0x8f840000, 0x8f850008, 0x8c830050, 0x34420001, 0x00a22825,
-       0xaf830020, 0xac830070, 0xac83005c, 0xaf450020, 0x3c050800, 0x24a45880,
-       0x8c820020, 0x2403ffbf, 0x00431024, 0x0a001493, 0xac820020, 0x000211c0,
-       0xaf420024, 0x97420908, 0x3c030080, 0x34630003, 0x000211c0, 0xaf42080c,
-       0xaf43081c, 0x974209ec, 0x8f4309a4, 0xa782002c, 0x3c020800, 0x24445880,
-       0xac83002c, 0x93420937, 0x93430934, 0x00021080, 0x00621821, 0xa4830018,
-       0x934209d8, 0x32850038, 0xafa50028, 0x00621821, 0xa483001a, 0x934209d8,
-       0x93430934, 0x3c1e0800, 0x00809821, 0x00431021, 0x24420010, 0xa4820016,
-       0x24020006, 0xae620020, 0x8fa20028, 0x10400003, 0x0000a821, 0x0a0012f0,
-       0x24120008, 0x8f420958, 0x8f830020, 0x8f840030, 0x00431023, 0x00832023,
-       0x04800003, 0xae620004, 0x04410003, 0x0082102b, 0x0a0012bc, 0xae600004,
-       0x54400001, 0xae640004, 0x8ee20000, 0x0040f809, 0x00000000, 0x00409021,
-       0x32420001, 0x5440001e, 0x8ee20004, 0x8e630008, 0x1060002b, 0x3c02c000,
-       0x00621025, 0xaf420e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000,
-       0x97420e08, 0xa7820010, 0x8f430e04, 0x8e620008, 0xaf830004, 0x8f840004,
-       0x0044102b, 0x1040000b, 0x24150001, 0x24020100, 0x3c016000, 0xac22081c,
-       0x3c020001, 0x3c016000, 0xac22081c, 0x0000000d, 0x00000000, 0x240004cd,
-       0x24150001, 0x8ee20004, 0x0040f809, 0x00000000, 0x02429025, 0x32420002,
-       0x5040001d, 0x8f470940, 0x12a00006, 0x8ec258b0, 0x8f830000, 0xac6200a8,
-       0x8f840000, 0x8e620034, 0xac8200ac, 0x32420004, 0x50400013, 0x8f470940,
-       0x3c020800, 0x3283007d, 0x10600110, 0x24575920, 0x32820001, 0x50400006,
-       0x36520002, 0x8f830034, 0x8f420940, 0x10620109, 0x00000000, 0x36520002,
-       0x24020008, 0xa6600010, 0xa6620012, 0xae600008, 0xa2600024, 0x8f470940,
-       0x3c030800, 0x24685880, 0x8d02002c, 0x8d050008, 0x95040010, 0x9506000a,
-       0x95030026, 0x00451021, 0x00862021, 0x00641821, 0xaf870034, 0xad02002c,
-       0x32820030, 0x10400008, 0xa5030014, 0x91020024, 0x32910040, 0x34420004,
-       0xa1020024, 0xaf400048, 0x0a001345, 0x3c040800, 0x93420923, 0x30420002,
-       0x10400029, 0x32910040, 0x8f830000, 0x8f840020, 0x8c620084, 0x00441023,
-       0x0442000a, 0x3c039000, 0x95020014, 0x8c630084, 0x00821021, 0x00621823,
-       0x1c600004, 0x3c039000, 0x91020024, 0x34420001, 0xa1020024, 0x34630001,
-       0x8f820008, 0x32910040, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020,
-       0x00441024, 0x1440fffd, 0x00000000, 0x8f840000, 0x9083003f, 0x2402000a,
-       0x10620005, 0x2402000c, 0x9083003f, 0x24020008, 0x14620002, 0x24020014,
-       0xa082003f, 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020,
-       0x3c040800, 0x24865880, 0x94c20010, 0x94c3001a, 0x8cc40008, 0x00432821,
-       0x14800006, 0xa4c5001c, 0x3c020800, 0x8c430048, 0x10600002, 0x24a20040,
-       0xa4c2001c, 0x27d05880, 0x9604001c, 0x96020012, 0x00822021, 0x24840002,
-       0x0e000faf, 0x3084ffff, 0x8f850018, 0x00a01821, 0xa2030025, 0x8ee60008,
-       0x00402021, 0x24a50001, 0xaf850018, 0x00c0f809, 0x00000000, 0x00402021,
-       0x0e001026, 0x02202821, 0x8ee3000c, 0x0060f809, 0x00402021, 0x9604001c,
-       0x96020012, 0x00822021, 0x24840002, 0x0e000fc5, 0x3084ffff, 0x8fc25880,
-       0x8e030008, 0x00431023, 0x14400012, 0xafc25880, 0x54600006, 0x8e020020,
-       0x3243004a, 0x24020002, 0x14620005, 0x00000000, 0x8e020020, 0x34420040,
-       0x0a001382, 0xae020020, 0x52a00006, 0x36520002, 0x8e020030, 0xaf420e10,
-       0x8e030034, 0xaf430e18, 0x36520002, 0x52a00008, 0x96670014, 0x8f830000,
-       0x8f420e10, 0xac6200a8, 0x8f840000, 0x8f420e18, 0xac8200ac, 0x96670014,
-       0x92680024, 0x24020040, 0xaf420814, 0x8f830020, 0x8f82001c, 0x00671821,
-       0x00621023, 0xaf830020, 0x18400008, 0x00000000, 0x8f820000, 0xaf83001c,
-       0xac430054, 0x54e00005, 0xaf400040, 0x0a0013a0, 0x8f42095c, 0x54e00001,
-       0xaf400044, 0x8f42095c, 0x31030008, 0xaf820030, 0x1060001a, 0x00000000,
-       0x8f840000, 0x90820120, 0x90830121, 0x304600ff, 0x00c31823, 0x30630007,
-       0x24020007, 0x1062000e, 0x00000000, 0x90820122, 0x304200fe, 0xa0820122,
-       0x8f850000, 0x00061880, 0x8f840020, 0x24a20100, 0x00431021, 0x24c30001,
-       0x30630007, 0xac440000, 0x0a0013bd, 0xa0a30120, 0x90820122, 0x34420001,
-       0xa0820122, 0x14e00003, 0x31020001, 0x10400031, 0x32510002, 0x8f820000,
-       0x8c43000c, 0x30630001, 0x1060002c, 0x32510002, 0x3c029000, 0x8f830008,
-       0x34420001, 0x3c048000, 0x00621825, 0xaf430020, 0x8f420020, 0x00441024,
-       0x1440fffd, 0x00000000, 0x8f870000, 0x8ce2000c, 0x30420001, 0x10400018,
-       0x00000000, 0x94e2006a, 0x00022880, 0x50a00001, 0x24050001, 0x94e30068,
-       0x90e40081, 0x3c020800, 0x8c460024, 0x00652821, 0x00852804, 0x00c5102b,
-       0x54400001, 0x00a03021, 0x3c020800, 0x8c440028, 0x00c4182b, 0x54600001,
-       0x00c02021, 0x8f430074, 0x2402fffe, 0x00822824, 0x00a31821, 0xace3000c,
-       0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x8f820020,
-       0x3c050800, 0x24b05880, 0xae020028, 0x8ee30010, 0x0060f809, 0x00000000,
-       0x8f820028, 0x24420001, 0xaf820028, 0x12a00005, 0xaf40004c, 0x8f420e10,
-       0xae020030, 0x8f430e18, 0xae030034, 0x1220fea7, 0x24020006, 0x8f870024,
-       0x9786002c, 0x8f830000, 0x8f820034, 0x8f840020, 0x8f85001c, 0x32530040,
-       0xa4e6002c, 0xac620044, 0x32420008, 0xac640050, 0xac650054, 0x1040007a,
-       0x32820020, 0x10400027, 0x32910010, 0x00003821, 0x24052000, 0x3c090800,
-       0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, 0x26c458b0,
-       0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030400, 0xaf420148, 0x24020041,
-       0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7470158, 0xaf450154,
-       0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030041,
-       0xafa50014, 0x00021600, 0x00431025, 0x00471025, 0xafa20010, 0x9343010b,
-       0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x3c070400, 0x12200028,
-       0x00003821, 0x24052000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024,
-       0x1440fffd, 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034,
-       0x3c030300, 0xaf420148, 0x2402004e, 0xaf43014c, 0xa3420152, 0x8d230030,
-       0x3c021000, 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001,
-       0xad230030, 0x9342010a, 0x3c03004e, 0xafa50014, 0x00021600, 0x00431025,
-       0x00471025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104,
-       0x0e00159b, 0x3c070300, 0x0a00148b, 0x8fa20024, 0x32820008, 0x10400026,
-       0x24052000, 0x00003821, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024,
-       0x1440fffd, 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034,
-       0x3c030200, 0xaf420148, 0x2402004b, 0xaf43014c, 0xa3420152, 0x8d230030,
-       0x3c021000, 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001,
-       0xad230030, 0x9342010a, 0x3c03004b, 0xafa50014, 0x00021600, 0x00431025,
-       0x00471025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104,
-       0x0e00159b, 0x3c070200, 0x8fa20024, 0x14400004, 0x8fa30020, 0x32420010,
-       0x10400004, 0x00000000, 0x8c620004, 0x0040f809, 0x00000000, 0x12600006,
-       0x8fa40020, 0x8c820008, 0x0040f809, 0x00000000, 0x0a0014c1, 0x8fbf0054,
-       0x3c030800, 0x8c6258a0, 0x30420040, 0x14400023, 0x8fbf0054, 0x00002821,
-       0x24040040, 0x8f870020, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd,
-       0x8ec258b0, 0x26c358b0, 0x2463ffd0, 0xaf420144, 0x8c620034, 0xaf420148,
-       0x24020049, 0xaf47014c, 0xa3420152, 0x3c021000, 0xa7450158, 0xaf440154,
-       0xaf420178, 0x8c660034, 0x9342010a, 0x3c030049, 0xafa40014, 0x00021600,
-       0x00431025, 0x00451025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100,
-       0x0e00159b, 0x8f450104, 0x8fbf0054, 0x8fbe0050, 0x8fb7004c, 0x8fb60048,
-       0x8fb50044, 0x8fb40040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
-       0x03e00008, 0x27bd0058, 0x03e00008, 0x00001021, 0x3c020800, 0x24435880,
-       0x8c650004, 0x8c445880, 0x0085182b, 0x10600002, 0x00403021, 0x00802821,
-       0x9744093c, 0x00a4102b, 0x54400001, 0x00a02021, 0x93420923, 0x0004182b,
-       0x00021042, 0x30420001, 0x00431024, 0x1040000d, 0x24c25880, 0x8f850000,
-       0x8f830020, 0x8ca20084, 0x00431023, 0x04420007, 0x24c25880, 0x8ca20084,
-       0x00641821, 0x00431023, 0x28420001, 0x00822023, 0x24c25880, 0xac440008,
-       0xa4400026, 0x03e00008, 0x00001021, 0x8f850004, 0x97840010, 0x3c030800,
-       0x24635880, 0x24020008, 0xa4620012, 0x8f820004, 0xa4600010, 0x000420c2,
-       0x30840008, 0x2c420001, 0x00021023, 0x30420006, 0xac650008, 0x03e00008,
-       0xa0640024, 0x3c020800, 0x24425880, 0x90450025, 0x9443001c, 0x3c021100,
-       0xac800004, 0x00052c00, 0x24630002, 0x00621825, 0x00a32825, 0x24820008,
-       0x03e00008, 0xac850000, 0x27bdffd8, 0x3c020800, 0x24425880, 0xafbf0020,
-       0x90480025, 0x8c440008, 0x8c460020, 0x8f870020, 0x3c030800, 0x3c058000,
-       0x8f420178, 0x00451024, 0x1440fffd, 0x8c6258b0, 0x246358b0, 0x2469ffd0,
-       0xaf420144, 0x8d220034, 0x30c32000, 0xaf420148, 0x3c021000, 0xaf47014c,
-       0xa3480152, 0xa7440158, 0xaf460154, 0xaf420178, 0x10600004, 0x3c030800,
-       0x8c620030, 0x24420001, 0xac620030, 0x9342010a, 0x00081c00, 0x3084ffff,
-       0xafa60014, 0x00021600, 0x00431025, 0x00441025, 0xafa20010, 0x9343010b,
-       0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x8d260034, 0x8fbf0020,
-       0x03e00008, 0x27bd0028, 0x0000000d, 0x00000000, 0x2400019d, 0x03e00008,
-       0x00000000, 0x0000000d, 0x00000000, 0x240001a9, 0x03e00008, 0x00000000,
-       0x03e00008, 0x00000000, 0x3c020800, 0x24425880, 0xac400008, 0xa4400026,
-       0x03e00008, 0x24020001, 0x3c020800, 0x24425880, 0x24030008, 0xac400008,
-       0xa4400010, 0xa4430012, 0xa0400024, 0x03e00008, 0x24020004, 0x03e00008,
-       0x00001021, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004,
-       0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00156c,
-       0x00a01021, 0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021,
-       0x1440fffa, 0x24a5ffff, 0x03e00008, 0x00000000, 0x3c0a0800, 0x8d490068,
-       0x3c050800, 0x24a52098, 0x00093140, 0x00c51021, 0xac440000, 0x8f440e04,
-       0x00a61021, 0xac440004, 0x97430e08, 0x97420e0c, 0x00a62021, 0x00031c00,
-       0x00431025, 0xac820008, 0x8f430e10, 0x00801021, 0xac43000c, 0x8f440e14,
-       0xac440010, 0x8f430e18, 0x3c0800ff, 0xac430014, 0x8f470e1c, 0x3508ffff,
-       0x25290001, 0xac470018, 0x3c070800, 0x8ce3006c, 0x9344010a, 0x3c026000,
-       0x24630001, 0xace3006c, 0x8c434448, 0x3129007f, 0x00a62821, 0xad490068,
-       0x00042600, 0x00681824, 0x00832025, 0x03e00008, 0xaca4001c, 0x8fac0010,
-       0x8fad0014, 0x8fae0018, 0x3c0b0800, 0x8d6a0060, 0x3c080800, 0x25080080,
-       0x000a4940, 0x01281021, 0x01091821, 0xac440000, 0x00601021, 0xac650004,
-       0xac460008, 0xac67000c, 0xac4c0010, 0xac6d0014, 0x3c036000, 0xac4e0018,
-       0x8c654448, 0x3c040800, 0x8c820064, 0x254a0001, 0x314a00ff, 0x01094021,
-       0xad6a0060, 0x24420001, 0xac820064, 0x03e00008, 0xad05001c, 0x3c030800,
-       0x3c090800, 0x8d250070, 0x246330b0, 0x8f460100, 0x00053900, 0x00e31021,
-       0xac460000, 0x8f440104, 0x00671021, 0xac440004, 0x8f460108, 0x8f840014,
-       0x24a50001, 0xac460008, 0x8c880074, 0x3c060800, 0x8cc20074, 0x30a5003f,
-       0x00671821, 0xad250070, 0x24420001, 0xacc20074, 0x03e00008, 0xac68000c,
-       0x00000000 };
+static u8 bnx2_TXP_b06FwText[] = {
+       0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+       0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x6d, 0x6c,
+       0x1b, 0xf7, 0x79, 0x7f, 0xee, 0x85, 0xd2, 0x51, 0x96, 0xe9, 0x93, 0xc2,
+       0x78, 0x6c, 0xc0, 0xa6, 0x77, 0xd6, 0x51, 0x66, 0x20, 0xb5, 0xa0, 0x05,
+       0x36, 0x55, 0x87, 0x43, 0x73, 0x3e, 0x52, 0x2f, 0x4e, 0x5c, 0x57, 0x71,
+       0x94, 0x86, 0x6e, 0x0d, 0x8c, 0xa0, 0xec, 0xd8, 0xeb, 0x5a, 0x2c, 0x1f,
+       0x8c, 0xd5, 0x68, 0xd1, 0x99, 0xa1, 0x68, 0xc7, 0xc9, 0x68, 0x51, 0xa9,
+       0xe5, 0xa8, 0x43, 0x57, 0x80, 0x95, 0x64, 0xcb, 0x29, 0x4e, 0x3a, 0x65,
+       0xcb, 0x16, 0x0c, 0x58, 0x16, 0xcd, 0x2f, 0x5d, 0x3f, 0x74, 0x80, 0x3f,
+       0xec, 0x43, 0x3a, 0xec, 0x83, 0x91, 0x14, 0xad, 0x11, 0x6c, 0x59, 0xb0,
+       0x2f, 0x33, 0xd6, 0x26, 0xb7, 0xdf, 0x73, 0x77, 0x94, 0x95, 0xc4, 0x4e,
+       0xab, 0x7d, 0xbe, 0x07, 0x20, 0xee, 0x7f, 0xff, 0xd7, 0xe7, 0xfd, 0xe5,
+       0x7f, 0x90, 0x06, 0xb7, 0x53, 0x17, 0x85, 0xb0, 0x1d, 0x3f, 0xed, 0x99,
+       0x93, 0x27, 0x3e, 0xf7, 0xf9, 0xcf, 0x0d, 0xa1, 0x39, 0x4c, 0x4a, 0x4c,
+       0xe4, 0xc1, 0x5b, 0x12, 0x51, 0xf9, 0x1d, 0x8a, 0x20, 0x82, 0x08, 0x22,
+       0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20,
+       0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08,
+       0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88,
+       0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82,
+       0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22,
+       0xf8, 0x9d, 0x20, 0x11, 0xa9, 0xfc, 0xdc, 0x1e, 0xfe, 0x48, 0x11, 0xcd,
+       0xf2, 0x53, 0xb6, 0x41, 0x8a, 0x64, 0x1e, 0x39, 0x34, 0x65, 0x10, 0x59,
+       0xce, 0x80, 0x56, 0xa0, 0xf7, 0xbd, 0x6a, 0x52, 0x26, 0xee, 0xff, 0xb4,
+       0xf9, 0xdb, 0x53, 0xaf, 0x7f, 0x41, 0x7f, 0xaf, 0x25, 0x91, 0xa2, 0x9a,
+       0x6b, 0x79, 0xb5, 0x9f, 0x94, 0x34, 0xd6, 0xfc, 0xd5, 0xee, 0xaf, 0xef,
+       0xa0, 0x44, 0x7b, 0xaf, 0x24, 0xd5, 0x9b, 0xb7, 0xbc, 0xd7, 0x77, 0x27,
+       0xe9, 0x15, 0x57, 0xa5, 0x35, 0x57, 0x16, 0x46, 0x9b, 0x0a, 0x4d, 0x37,
+       0x1d, 0x3a, 0xdd, 0xa8, 0x52, 0xc1, 0xbd, 0x4c, 0xb5, 0x39, 0x35, 0x61,
+       0x2f, 0xff, 0x84, 0xa6, 0xe7, 0x7a, 0x13, 0x85, 0x65, 0x87, 0x6a, 0x8d,
+       0x54, 0xc2, 0x76, 0xd5, 0x44, 0x61, 0x3e, 0x89, 0xf7, 0xde, 0x84, 0x3d,
+       0xaf, 0x57, 0x89, 0x76, 0x62, 0x4e, 0x2a, 0x51, 0x68, 0xea, 0x65, 0xa2,
+       0xbe, 0xdc, 0x75, 0x4a, 0x27, 0x0a, 0xee, 0x82, 0xb0, 0xae, 0x0a, 0x54,
+       0xfb, 0x2c, 0xa9, 0x09, 0xf3, 0xb6, 0xf7, 0x29, 0x43, 0xa5, 0x1e, 0x83,
+       0x76, 0xec, 0x30, 0xe8, 0xd9, 0x94, 0xa9, 0x50, 0xe5, 0x7c, 0x9c, 0x2c,
+       0x9f, 0x26, 0x95, 0x2a, 0xf3, 0x03, 0xea, 0x15, 0x8a, 0x91, 0x95, 0x6c,
+       0xbf, 0x7b, 0x9e, 0x9d, 0xfb, 0x16, 0xff, 0x9d, 0x16, 0xce, 0xa2, 0xc4,
+       0xa8, 0x4b, 0x64, 0x03, 0x2f, 0x3b, 0xf7, 0xbe, 0x17, 0xac, 0x51, 0x70,
+       0xae, 0x9c, 0x18, 0x69, 0x7a, 0x5e, 0x31, 0x87, 0x33, 0x72, 0xed, 0xb5,
+       0x31, 0x6a, 0x25, 0xad, 0xd6, 0x74, 0x2e, 0xbf, 0x23, 0xf8, 0x1b, 0x2f,
+       0xa6, 0x91, 0xdf, 0x2d, 0x12, 0x8d, 0xaf, 0x50, 0x25, 0x49, 0xad, 0x5a,
+       0xee, 0x61, 0x7a, 0x21, 0xd7, 0x4d, 0x67, 0xb1, 0xdf, 0xf3, 0x39, 0xf0,
+       0xd1, 0x38, 0x29, 0xd8, 0xae, 0x9e, 0x22, 0xe1, 0x05, 0xb2, 0xe7, 0xfb,
+       0xd4, 0x02, 0xe1, 0x6c, 0xc3, 0xfb, 0x8c, 0x9d, 0xc3, 0x79, 0x83, 0xff,
+       0xeb, 0x59, 0x49, 0xbd, 0xdc, 0xa2, 0x14, 0xd5, 0x9a, 0x7d, 0xb9, 0x9f,
+       0x93, 0x40, 0x9d, 0x06, 0xf3, 0xc7, 0xa3, 0xc7, 0x70, 0xae, 0x6d, 0xa0,
+       0xdf, 0x25, 0x4b, 0xcc, 0xc4, 0xe8, 0x4f, 0x55, 0x5d, 0xb3, 0xa5, 0x5e,
+       0xaa, 0x9d, 0xef, 0x04, 0x9e, 0x56, 0xaf, 0x88, 0xb9, 0x63, 0x79, 0x4a,
+       0x6e, 0x23, 0x12, 0x24, 0x33, 0x83, 0x7d, 0x89, 0x6a, 0x4e, 0x0a, 0x6b,
+       0x33, 0xc3, 0xef, 0xd0, 0x0e, 0xd2, 0x7a, 0x64, 0x9a, 0x76, 0xba, 0xc0,
+       0xc7, 0x6e, 0xc8, 0x20, 0x33, 0xfc, 0x2e, 0x84, 0x22, 0x1a, 0x99, 0xd4,
+       0x49, 0x2a, 0x0b, 0x05, 0xb7, 0x83, 0xa6, 0x33, 0x0a, 0xd5, 0x81, 0x47,
+       0x3d, 0xf7, 0x35, 0xc1, 0x5e, 0x2e, 0x09, 0x85, 0x65, 0xcc, 0x73, 0x5f,
+       0x0b, 0xff, 0x76, 0xad, 0x1b, 0xfb, 0x88, 0x54, 0xcb, 0x94, 0x30, 0xa6,
+       0xd0, 0x14, 0xe6, 0x4d, 0x81, 0xa6, 0x69, 0x77, 0x07, 0xad, 0x4f, 0x26,
+       0x13, 0xcc, 0xab, 0x1a, 0xc6, 0xbf, 0x32, 0x21, 0x90, 0x6a, 0x58, 0xf4,
+       0xeb, 0x3c, 0x64, 0x38, 0xdf, 0xcb, 0x32, 0xa3, 0xd3, 0x4d, 0x4a, 0x8a,
+       0x94, 0x49, 0x55, 0xe8, 0x32, 0x2d, 0x3a, 0x2c, 0x7f, 0xc8, 0x13, 0xf2,
+       0xae, 0x39, 0xbc, 0x0e, 0x72, 0x6b, 0x16, 0xc1, 0x8f, 0x71, 0xe0, 0x70,
+       0x50, 0x78, 0x6c, 0x71, 0x52, 0x18, 0x73, 0x7f, 0x93, 0xa0, 0xae, 0x93,
+       0xc2, 0x01, 0xf7, 0xa8, 0x10, 0xf2, 0x1e, 0xb2, 0x53, 0xc8, 0x9a, 0x50,
+       0xe8, 0x92, 0x1b, 0xc8, 0x6e, 0x01, 0xfa, 0x69, 0xa9, 0x16, 0xe4, 0x70,
+       0x78, 0x63, 0x0e, 0x8f, 0xd5, 0x97, 0x65, 0x3a, 0xed, 0xf2, 0xfc, 0x3f,
+       0x82, 0x7c, 0x14, 0x72, 0x76, 0x77, 0x53, 0x19, 0xfd, 0xb5, 0x79, 0xb2,
+       0xec, 0x9c, 0x88, 0x35, 0x09, 0x92, 0x8c, 0x9d, 0xf8, 0x75, 0xd1, 0xd4,
+       0x62, 0xa7, 0x25, 0x19, 0x49, 0x9a, 0x72, 0x99, 0x87, 0x78, 0x36, 0xdb,
+       0x7c, 0x64, 0x5c, 0xb9, 0x9f, 0xd7, 0x71, 0xbf, 0x8a, 0xfe, 0xcd, 0x7d,
+       0xac, 0x17, 0x09, 0xe0, 0xa3, 0x67, 0x59, 0x9f, 0x2b, 0xcd, 0x8c, 0x7a,
+       0x80, 0x9f, 0x2e, 0xf3, 0xb6, 0xcd, 0x53, 0x19, 0x73, 0x45, 0xaa, 0x2c,
+       0xe2, 0x9c, 0xf3, 0xbf, 0xf5, 0x62, 0x79, 0xbc, 0x1b, 0x1d, 0xa0, 0x8b,
+       0xcf, 0x95, 0x81, 0x93, 0x48, 0xe5, 0x45, 0xde, 0x8b, 0xc7, 0x09, 0xb2,
+       0xaf, 0xf5, 0x88, 0x94, 0x85, 0x7c, 0x75, 0x9c, 0x13, 0xc7, 0x9c, 0x6e,
+       0xf0, 0x0f, 0xb4, 0x2e, 0xa3, 0x0d, 0xda, 0x45, 0x43, 0xc4, 0xfa, 0x4e,
+       0x9a, 0xca, 0xb1, 0xbe, 0x30, 0x9e, 0xdb, 0xb0, 0x77, 0x9c, 0x8e, 0x9c,
+       0x67, 0x7e, 0xc8, 0xf4, 0x3c, 0x70, 0x9c, 0x9e, 0xd7, 0xd5, 0x22, 0xe9,
+       0xe0, 0x8d, 0x85, 0x79, 0x9d, 0x54, 0x56, 0x3d, 0x6f, 0x24, 0x37, 0xa0,
+       0xbe, 0xec, 0xeb, 0xf9, 0x80, 0x9a, 0x11, 0xa8, 0xda, 0x61, 0xfe, 0x21,
+       0x70, 0xd0, 0x4b, 0x44, 0xfc, 0xfe, 0xcf, 0x64, 0x4d, 0xb2, 0xfd, 0x24,
+       0xf9, 0x2c, 0xd8, 0xd3, 0x4e, 0xe0, 0xcf, 0x36, 0x97, 0x86, 0x5c, 0x52,
+       0xbe, 0x1d, 0x8c, 0xdc, 0xd5, 0x0e, 0xf4, 0xf1, 0x16, 0x6c, 0xa6, 0xb6,
+       0x2c, 0xb3, 0xfd, 0xe5, 0xa0, 0x6e, 0xb4, 0xcd, 0x80, 0x6e, 0xf9, 0xb2,
+       0xd9, 0x8f, 0xfd, 0x3d, 0xef, 0xcb, 0xb9, 0x00, 0xa7, 0xda, 0xbc, 0x85,
+       0xb5, 0x32, 0xf8, 0xae, 0x1f, 0xd7, 0xfc, 0xf3, 0xf7, 0x87, 0xe7, 0xab,
+       0x34, 0x05, 0xbc, 0x6b, 0x4d, 0x89, 0x0a, 0x2a, 0xef, 0xf1, 0x2e, 0xf7,
+       0x97, 0x83, 0xbd, 0xa0, 0xb7, 0xe7, 0xfa, 0xd4, 0x7d, 0xb0, 0x25, 0xb6,
+       0xb1, 0xda, 0x0a, 0xf3, 0x18, 0xfb, 0xe4, 0x99, 0xc7, 0xaa, 0x8f, 0xa3,
+       0x3d, 0xcf, 0x7a, 0x44, 0x69, 0x89, 0x58, 0xcf, 0x2f, 0xb3, 0x2e, 0x41,
+       0x3f, 0x03, 0xbd, 0xaa, 0x38, 0x2c, 0xff, 0x2f, 0x85, 0xf6, 0x29, 0x52,
+       0x7f, 0x86, 0xf5, 0xfd, 0x05, 0x2a, 0xc0, 0xc6, 0xa7, 0x70, 0xd2, 0x22,
+       0x68, 0x5a, 0x68, 0xf6, 0x81, 0x57, 0x6d, 0xbb, 0x83, 0x7c, 0x07, 0xff,
+       0xc7, 0x0b, 0xe6, 0x77, 0x03, 0x27, 0xb6, 0x99, 0x9a, 0x2a, 0x52, 0x15,
+       0x3f, 0xe8, 0x8d, 0xa1, 0x67, 0x6d, 0x49, 0x9f, 0x28, 0x03, 0x37, 0xe8,
+       0x3d, 0xd9, 0x7b, 0x58, 0x9f, 0x31, 0xc7, 0xa5, 0xa1, 0xb6, 0x9d, 0x2d,
+       0x38, 0x2c, 0xa7, 0x2e, 0x9c, 0xdb, 0xc6, 0x49, 0x46, 0x1f, 0xef, 0xa3,
+       0x40, 0xe7, 0xdb, 0x3a, 0xc3, 0xfa, 0xa7, 0x5b, 0xeb, 0xd4, 0x41, 0xd9,
+       0x0c, 0x7c, 0xd9, 0xbc, 0x08, 0xf9, 0xa5, 0xe1, 0x53, 0x64, 0x7a, 0xba,
+       0x99, 0xa4, 0x63, 0x4d, 0xc6, 0xaf, 0x08, 0xbb, 0x83, 0x6f, 0x9b, 0x1f,
+       0x85, 0x9d, 0x8d, 0x0b, 0x23, 0xb0, 0x89, 0x47, 0x17, 0x19, 0x27, 0x8f,
+       0xd8, 0x2e, 0x8b, 0xcb, 0x65, 0x61, 0xd4, 0x2d, 0x09, 0xe3, 0xcb, 0x6c,
+       0x27, 0x6c, 0x23, 0xba, 0xfa, 0x38, 0x31, 0x0d, 0x98, 0xe3, 0xfe, 0x22,
+       0xc1, 0xb6, 0x5a, 0x3b, 0x17, 0x07, 0x1e, 0xdb, 0x80, 0x4f, 0x37, 0x6c,
+       0x0f, 0xfa, 0x65, 0xe8, 0x13, 0xac, 0x33, 0xc5, 0x8c, 0xa1, 0xfd, 0x25,
+       0x7d, 0x9c, 0x0f, 0x23, 0x1b, 0x7c, 0x18, 0x00, 0x4f, 0x3e, 0xcc, 0x87,
+       0xfa, 0xc7, 0xf9, 0x60, 0x55, 0xc1, 0x87, 0x3a, 0xfc, 0x50, 0xdd, 0x65,
+       0x9a, 0x3d, 0x12, 0xf7, 0x10, 0xb4, 0x93, 0xf6, 0x8a, 0x26, 0xeb, 0x28,
+       0xdb, 0x49, 0x46, 0x9b, 0xc6, 0x0e, 0x4b, 0x4e, 0xb7, 0x6f, 0x1b, 0xa3,
+       0x3e, 0x2f, 0x7e, 0x17, 0xbd, 0x4c, 0xdf, 0x1d, 0x9a, 0xc7, 0x17, 0xd9,
+       0xdf, 0x40, 0xcf, 0x33, 0x86, 0x7a, 0x88, 0xee, 0xd0, 0xbd, 0xef, 0x0e,
+       0xdd, 0x38, 0xa7, 0xed, 0x83, 0x98, 0xe6, 0xb6, 0x3f, 0x66, 0x5d, 0x79,
+       0xc3, 0x93, 0x0c, 0x03, 0x32, 0x60, 0x7d, 0x61, 0x1c, 0x74, 0xf5, 0xcb,
+       0xa0, 0xa7, 0x02, 0xbf, 0xc0, 0xb6, 0x54, 0xf6, 0xe7, 0x75, 0x50, 0xb9,
+       0x27, 0x98, 0x3f, 0xd5, 0xf4, 0xfe, 0x4b, 0x34, 0x3f, 0xf0, 0xec, 0xbc,
+       0x11, 0xda, 0xb8, 0x42, 0x7f, 0xb2, 0xa8, 0x97, 0x35, 0xa1, 0x9b, 0xaa,
+       0xf7, 0xc3, 0xaf, 0x34, 0xd9, 0x3e, 0x76, 0xde, 0xc3, 0x97, 0xa5, 0x43,
+       0x5f, 0xf6, 0x3e, 0x78, 0xcf, 0xb1, 0xe7, 0xe8, 0x07, 0xeb, 0x49, 0x7e,
+       0x66, 0xd4, 0x09, 0x2a, 0x71, 0xbc, 0xd9, 0x21, 0xfa, 0xfe, 0xbb, 0x8f,
+       0x63, 0x41, 0x55, 0x36, 0xe3, 0x54, 0xed, 0xa1, 0xaa, 0x64, 0xb2, 0x1d,
+       0xb1, 0x6d, 0xb4, 0xf1, 0xde, 0x1e, 0xc6, 0xdd, 0x41, 0x89, 0x0c, 0x1e,
+       0x47, 0x8c, 0x68, 0x32, 0x0d, 0xef, 0x87, 0xf2, 0x60, 0x7f, 0x4a, 0xb1,
+       0x40, 0xdf, 0xf6, 0xc3, 0x5f, 0x32, 0x3f, 0x37, 0xeb, 0x0a, 0xfb, 0x51,
+       0xd2, 0x44, 0x83, 0xfd, 0x28, 0xa9, 0x92, 0x79, 0x50, 0xb0, 0x16, 0xbf,
+       0x26, 0x58, 0xe0, 0x9b, 0x05, 0xbe, 0x59, 0xe0, 0x9b, 0x0d, 0xbe, 0x15,
+       0x5c, 0xc6, 0x85, 0xf1, 0x08, 0xf6, 0x2f, 0x06, 0xfb, 0x03, 0xc7, 0x9d,
+       0x54, 0xf1, 0xed, 0x9b, 0x69, 0x85, 0x3f, 0xf6, 0x7d, 0xc1, 0xa8, 0x10,
+       0xf8, 0x02, 0xde, 0x6f, 0x1c, 0xeb, 0x1f, 0x47, 0x8c, 0xb3, 0x44, 0xd1,
+       0xb8, 0xc3, 0x8f, 0xfa, 0x26, 0x7e, 0x4c, 0x3b, 0xcc, 0x1f, 0x9e, 0xcf,
+       0x76, 0xec, 0x40, 0xe6, 0x6d, 0x9e, 0xec, 0x07, 0x0e, 0x9d, 0x4c, 0x77,
+       0x48, 0x07, 0xef, 0xdf, 0x1b, 0xee, 0x7f, 0x00, 0x7b, 0xb2, 0xdd, 0xde,
+       0xed, 0x5c, 0x3e, 0x93, 0xe3, 0xe8, 0x27, 0xd1, 0x83, 0x3c, 0x02, 0x7e,
+       0x66, 0x0d, 0x76, 0x76, 0x53, 0x4a, 0xd1, 0xeb, 0xbb, 0x6f, 0x20, 0xb7,
+       0xa0, 0xea, 0x03, 0xa6, 0xa7, 0xc9, 0xe6, 0xfb, 0x5e, 0x3d, 0x0f, 0xdf,
+       0x69, 0xea, 0x29, 0x5b, 0x1a, 0xa4, 0x37, 0xdc, 0x2c, 0xfd, 0x9d, 0x6b,
+       0xd0, 0xdf, 0xba, 0x1a, 0xbd, 0xea, 0xa6, 0xe9, 0x6f, 0xdc, 0x14, 0xfd,
+       0xb5, 0xdb, 0xce, 0x43, 0x92, 0xac, 0x47, 0x89, 0xa2, 0x7b, 0xb7, 0x5c,
+       0x08, 0x3a, 0x8e, 0xbd, 0xec, 0xbc, 0x5c, 0x96, 0x4d, 0x3f, 0x3f, 0x98,
+       0x98, 0x6e, 0x90, 0xb2, 0xd3, 0xa0, 0xed, 0xf7, 0x23, 0xef, 0x49, 0x9a,
+       0xb4, 0xe3, 0x3e, 0x3c, 0x7b, 0x4d, 0xb2, 0x7a, 0xcc, 0x53, 0x9e, 0x68,
+       0xb0, 0x1e, 0x75, 0x0f, 0x4f, 0xe5, 0xe3, 0x8c, 0xfb, 0xc4, 0x34, 0xfc,
+       0x91, 0x8d, 0xb3, 0xaa, 0xd0, 0xc5, 0xaa, 0x7b, 0xe8, 0xfe, 0x20, 0x17,
+       0x7a, 0x2f, 0xcc, 0x89, 0x38, 0xaf, 0x5a, 0x7f, 0x6a, 0xc2, 0x60, 0x3f,
+       0x2b, 0x6c, 0xf2, 0xb3, 0x24, 0x14, 0x41, 0x53, 0x1d, 0xb8, 0x16, 0x41,
+       0xe7, 0x57, 0x5d, 0x45, 0x28, 0x9c, 0xef, 0xa5, 0xe9, 0x45, 0x8e, 0x55,
+       0x3c, 0x4f, 0x09, 0x73, 0x19, 0x7e, 0xef, 0xc0, 0x3b, 0x21, 0x7e, 0x14,
+       0xb6, 0x53, 0x42, 0x7f, 0x73, 0x82, 0x9c, 0x30, 0x17, 0x89, 0xd1, 0x05,
+       0x5f, 0x77, 0xb8, 0xdf, 0x2a, 0xfd, 0xb0, 0xff, 0x4e, 0xff, 0xf9, 0x8d,
+       0xfe, 0x72, 0xe9, 0xeb, 0x1b, 0xfd, 0xef, 0xa8, 0x01, 0x4e, 0xc3, 0xc2,
+       0xe3, 0xee, 0xf3, 0x61, 0xdf, 0x6d, 0xf0, 0xd3, 0xf3, 0xea, 0x88, 0x27,
+       0x35, 0xe3, 0x36, 0x72, 0x1f, 0xf6, 0x29, 0x5b, 0xf1, 0x21, 0x1f, 0xf2,
+       0x1f, 0xaa, 0x2d, 0xb1, 0x9c, 0x14, 0x0a, 0xf6, 0xe4, 0xf1, 0x4e, 0xf8,
+       0x92, 0xdb, 0x68, 0x73, 0xec, 0x6a, 0xfb, 0x31, 0x9e, 0xc3, 0xeb, 0x6f,
+       0xdd, 0x43, 0x96, 0x2a, 0x64, 0xb9, 0x35, 0x79, 0xd5, 0x1a, 0xa7, 0x42,
+       0x9f, 0xd0, 0x3d, 0x6c, 0x43, 0x2e, 0x12, 0xe4, 0x52, 0x83, 0x5c, 0x0a,
+       0xf7, 0x94, 0x0b, 0xce, 0xd8, 0xd0, 0x29, 0xc6, 0xa3, 0x2b, 0x3c, 0x9b,
+       0x14, 0xd9, 0xac, 0x96, 0xea, 0xc6, 0xa7, 0x28, 0x66, 0x30, 0x1e, 0x06,
+       0xf0, 0x38, 0x8a, 0xb5, 0x1c, 0xc3, 0x48, 0x89, 0x99, 0x2c, 0xcf, 0xdc,
+       0x13, 0xb6, 0x71, 0xab, 0xb4, 0xe0, 0xdc, 0x2a, 0x5d, 0x34, 0xf8, 0xfd,
+       0xf6, 0x64, 0x90, 0x37, 0x77, 0x3f, 0x89, 0xbc, 0x19, 0xeb, 0xd9, 0x1f,
+       0x72, 0xff, 0x30, 0xe6, 0x71, 0x7c, 0xa0, 0x43, 0x35, 0xfc, 0xea, 0xfe,
+       0xdc, 0x6b, 0x4f, 0xf0, 0xdc, 0x4e, 0x53, 0x9e, 0xfc, 0x35, 0x9e, 0x1d,
+       0xa6, 0xf6, 0xe4, 0x4f, 0x0d, 0xde, 0x77, 0x78, 0xf2, 0xa2, 0xbf, 0x07,
+       0x62, 0xa6, 0xbf, 0x36, 0xfb, 0x24, 0xaf, 0x7d, 0x0e, 0x3e, 0xf6, 0x0c,
+       0xe2, 0xcb, 0x69, 0x47, 0x3b, 0x54, 0xc1, 0x6f, 0x8a, 0x71, 0x6a, 0xf2,
+       0xb8, 0x85, 0x71, 0x19, 0xb1, 0x90, 0xdb, 0x0a, 0x1d, 0xc3, 0xbc, 0xa7,
+       0x31, 0xef, 0xa8, 0x33, 0x8e, 0xbc, 0xbd, 0x4d, 0xd7, 0xbf, 0xc5, 0x0b,
+       0xf3, 0xec, 0xcf, 0x91, 0xed, 0xaf, 0xfc, 0x7b, 0xdc, 0x86, 0x5f, 0x16,
+       0x57, 0x6e, 0xc6, 0x0b, 0xa0, 0x5b, 0x5a, 0xf9, 0x45, 0xbc, 0x08, 0x3d,
+       0x13, 0x0d, 0x09, 0x7e, 0xf9, 0x33, 0x54, 0x53, 0x3d, 0x7a, 0x19, 0xf1,
+       0xab, 0x96, 0x85, 0xbf, 0x82, 0x34, 0x45, 0x03, 0x7e, 0x4c, 0x25, 0xa5,
+       0xcb, 0x3c, 0xa9, 0x52, 0x57, 0x3e, 0x6e, 0x23, 0xde, 0xd4, 0x54, 0x09,
+       0xfd, 0xfd, 0x78, 0x6e, 0xee, 0xff, 0x65, 0x1c, 0x7e, 0x0b, 0x3e, 0x82,
+       0x14, 0x3b, 0xdf, 0x8d, 0xfd, 0xbf, 0x8d, 0x7e, 0x4c, 0xc8, 0x6c, 0xf4,
+       0x3f, 0x1b, 0xf4, 0xdf, 0x02, 0x2e, 0xbc, 0x8e, 0xe3, 0x27, 0x29, 0x53,
+       0x79, 0x15, 0x38, 0xf0, 0xdc, 0xa4, 0x3f, 0xb7, 0x38, 0xcf, 0x3c, 0xa8,
+       0x96, 0x16, 0x8c, 0x34, 0x15, 0xe6, 0x92, 0x34, 0x3a, 0xa7, 0xd2, 0xd8,
+       0x9c, 0x3e, 0xd1, 0x62, 0xfb, 0x01, 0xcd, 0x84, 0x1c, 0x41, 0x5c, 0x21,
+       0x50, 0xac, 0xa7, 0x9e, 0xa6, 0xbe, 0xd4, 0x31, 0xfa, 0x6f, 0x0f, 0xb1,
+       0x08, 0x71, 0xa8, 0x9b, 0x64, 0x7f, 0x9f, 0x54, 0xfb, 0x4c, 0x96, 0xd1,
+       0x87, 0xce, 0x2d, 0xce, 0xdf, 0x6b, 0x5f, 0x28, 0xf1, 0x4a, 0xea, 0x23,
+       0xfb, 0xbe, 0x1b, 0xee, 0xab, 0x62, 0xdf, 0x34, 0xf6, 0x64, 0x1a, 0xf5,
+       0xf8, 0xc8, 0x79, 0xb2, 0x3a, 0x81, 0x5f, 0x31, 0x83, 0x98, 0x8f, 0x7d,
+       0xce, 0xcc, 0xb1, 0xde, 0xd3, 0x4e, 0xfc, 0x06, 0x63, 0x94, 0xc9, 0x2e,
+       0x23, 0x27, 0x18, 0xf1, 0xf7, 0x08, 0xf2, 0x05, 0x71, 0x65, 0x10, 0xf9,
+       0xda, 0x3b, 0xc0, 0x87, 0xe3, 0x18, 0xd3, 0x2c, 0x83, 0xde, 0x41, 0xe4,
+       0x09, 0x9c, 0xe3, 0x7b, 0xa7, 0xec, 0x1c, 0xda, 0xcb, 0x5a, 0xbc, 0x00,
+       0xdb, 0x16, 0x4d, 0x7a, 0x50, 0xf2, 0x7d, 0x2c, 0xcb, 0x65, 0x10, 0x72,
+       0x62, 0xbc, 0x73, 0x90, 0x13, 0xf3, 0x68, 0x38, 0x5e, 0x6c, 0x32, 0x8f,
+       0x08, 0xf8, 0x68, 0xb0, 0x27, 0xd9, 0xcf, 0xf3, 0xc5, 0x15, 0x0b, 0xf3,
+       0x7e, 0xac, 0x72, 0x2e, 0x66, 0x1b, 0xdc, 0x86, 0xed, 0xac, 0x8c, 0x63,
+       0x2e, 0xb7, 0x1f, 0xc6, 0xbe, 0x7d, 0xb9, 0x1a, 0x75, 0xe4, 0x9e, 0x86,
+       0xdd, 0x8a, 0xf9, 0x01, 0xc4, 0x68, 0x01, 0xb9, 0xa0, 0xe7, 0x75, 0xe4,
+       0xbf, 0x00, 0x7a, 0x98, 0x0e, 0xe8, 0xf5, 0x2c, 0xf3, 0x95, 0xfe, 0x40,
+       0xe4, 0x5c, 0x2d, 0xdf, 0xce, 0x6b, 0x38, 0x9e, 0xf3, 0xf9, 0x88, 0x23,
+       0x8d, 0x3d, 0x88, 0xa5, 0xfe, 0xd9, 0xd0, 0xb1, 0x71, 0x2a, 0x34, 0x3e,
+       0x8b, 0x9c, 0x93, 0x6d, 0x67, 0x9b, 0x60, 0x9f, 0x67, 0x1a, 0x09, 0xb1,
+       0x66, 0x8d, 0x2a, 0x0d, 0x39, 0x6c, 0xbf, 0x8a, 0xb6, 0x12, 0xb6, 0xd7,
+       0xd1, 0xee, 0x0e, 0xdb, 0xd7, 0xd0, 0x56, 0xc3, 0xf6, 0xcf, 0xd0, 0x4e,
+       0x86, 0xed, 0x9f, 0xa3, 0x9d, 0x0a, 0xdb, 0x37, 0xd1, 0x4e, 0x87, 0xed,
+       0x5b, 0x68, 0x6b, 0x61, 0xfb, 0x3d, 0xb4, 0x13, 0xb0, 0x73, 0x03, 0xef,
+       0x37, 0x50, 0x2b, 0x66, 0xf1, 0xfc, 0x57, 0xe0, 0x36, 0x08, 0xde, 0x64,
+       0xc1, 0x8f, 0x5e, 0x8c, 0xe5, 0xd0, 0x87, 0x1c, 0xb1, 0x91, 0xc7, 0xd3,
+       0xc1, 0x18, 0x95, 0x61, 0x7b, 0x18, 0x1f, 0x2f, 0x16, 0x1a, 0x26, 0x9e,
+       0x6c, 0x0f, 0xba, 0x4a, 0xc2, 0x65, 0xd8, 0xb9, 0xef, 0x63, 0x72, 0xb6,
+       0x34, 0x09, 0xdb, 0x9e, 0xa0, 0x7f, 0x74, 0xf7, 0xd3, 0x6b, 0xee, 0x38,
+       0xe2, 0x46, 0x11, 0x71, 0xc3, 0x42, 0xdc, 0x30, 0x11, 0x37, 0x86, 0x11,
+       0x37, 0xf2, 0x88, 0x1b, 0x39, 0xc4, 0x0d, 0xa2, 0x33, 0x7e, 0x8c, 0x4a,
+       0x2a, 0xa8, 0x51, 0x15, 0xcb, 0x2d, 0x82, 0xbf, 0x13, 0x90, 0xcd, 0x24,
+       0x78, 0x7d, 0x38, 0x3e, 0xd2, 0xcc, 0xc3, 0x9f, 0x69, 0xf0, 0x11, 0x69,
+       0xf8, 0xf2, 0x1c, 0x6a, 0x13, 0xa2, 0x2b, 0xb3, 0x1a, 0xfc, 0x8f, 0x47,
+       0x45, 0xc4, 0xfe, 0x69, 0x15, 0xb8, 0x19, 0xbb, 0x7c, 0x9b, 0x91, 0xcc,
+       0x2f, 0xf6, 0x50, 0xd7, 0x20, 0xe8, 0x39, 0x8b, 0xbe, 0x14, 0xf6, 0x63,
+       0xbe, 0xde, 0x2a, 0xd9, 0x86, 0x46, 0x0b, 0x6e, 0x1c, 0xfe, 0x9f, 0xdf,
+       0xe3, 0xcc, 0xe3, 0x43, 0x4f, 0x19, 0x4c, 0x03, 0xea, 0x3c, 0x23, 0xad,
+       0x14, 0x1c, 0x81, 0x24, 0x93, 0x9f, 0xed, 0x1c, 0xe2, 0xcf, 0x90, 0x43,
+       0x74, 0x41, 0x06, 0x55, 0xc4, 0x05, 0x9d, 0xf3, 0x0b, 0xe8, 0xf2, 0x27,
+       0xcd, 0xff, 0x1e, 0xe6, 0xef, 0xc5, 0xd9, 0x3c, 0x8f, 0xcf, 0x39, 0x85,
+       0xfa, 0xc1, 0xea, 0x91, 0x68, 0x3d, 0x25, 0xa1, 0x9e, 0x28, 0xd0, 0x59,
+       0x2a, 0x00, 0x9f, 0x82, 0xdb, 0xbe, 0x07, 0xb0, 0x0e, 0x05, 0xfe, 0x6c,
+       0xe2, 0xd0, 0xb7, 0x0d, 0x0b, 0xeb, 0x18, 0x3f, 0xd6, 0x5b, 0xe0, 0xbe,
+       0xb1, 0xe7, 0x05, 0xec, 0xf9, 0x4f, 0x49, 0xea, 0x9a, 0x0c, 0xfc, 0x91,
+       0x5f, 0xf3, 0xca, 0xc2, 0x48, 0xf3, 0x2c, 0xf8, 0xd3, 0x87, 0x1a, 0x05,
+       0x7e, 0xa4, 0xd4, 0x02, 0x9f, 0xda, 0xf3, 0x5f, 0xc1, 0x7c, 0x7e, 0xf7,
+       0xef, 0x0e, 0x4a, 0xd2, 0xea, 0x12, 0xe6, 0x69, 0xac, 0x3f, 0x25, 0xb9,
+       0xff, 0x86, 0xf7, 0xa2, 0x91, 0xa7, 0x5d, 0xab, 0xbc, 0x2e, 0x4b, 0x7d,
+       0xab, 0x37, 0xbc, 0x9a, 0xa3, 0xd1, 0x62, 0x93, 0xc0, 0xab, 0xf8, 0x6d,
+       0x8b, 0xf4, 0x35, 0x12, 0xf5, 0x59, 0x0b, 0x7a, 0x5a, 0x1c, 0x12, 0xc9,
+       0x1e, 0xea, 0x84, 0x8f, 0x32, 0x68, 0x09, 0x7c, 0xdf, 0x35, 0x63, 0xd1,
+       0x13, 0x43, 0xed, 0x7c, 0x10, 0x51, 0x0f, 0xb8, 0xee, 0x5a, 0xd5, 0x30,
+       0x87, 0x73, 0x71, 0xa6, 0x45, 0x03, 0x2f, 0x85, 0x60, 0x8d, 0x1f, 0xb3,
+       0xb8, 0x8e, 0x05, 0xdf, 0xdc, 0xb5, 0xd2, 0xd5, 0x19, 0xd4, 0x1a, 0x90,
+       0xf3, 0xae, 0x19, 0xae, 0x85, 0xb6, 0x81, 0x2f, 0x31, 0xd8, 0x06, 0xe7,
+       0xf1, 0x08, 0xf4, 0xf0, 0x87, 0x27, 0xe0, 0xf1, 0x6b, 0xcd, 0x13, 0xd0,
+       0xfb, 0x2e, 0x2a, 0xcb, 0x3e, 0x11, 0x9f, 0xc0, 0xe3, 0xff, 0xe4, 0xbc,
+       0x0e, 0xf3, 0xbf, 0x4b, 0xc5, 0xd9, 0x2e, 0xec, 0xb5, 0x9b, 0xa6, 0x93,
+       0x8c, 0x9b, 0x3e, 0x8c, 0x41, 0x2d, 0x06, 0x7e, 0xc6, 0xcd, 0x8f, 0xe6,
+       0x7d, 0x6b, 0xa5, 0x2b, 0x33, 0x6b, 0xa5, 0x6b, 0xa0, 0xbf, 0x6e, 0x70,
+       0x8d, 0x0c, 0x5d, 0x6a, 0x70, 0x6d, 0xcf, 0x79, 0xd1, 0x18, 0x74, 0x64,
+       0xbf, 0x5f, 0x33, 0xdb, 0x8b, 0x39, 0xea, 0x3b, 0x47, 0xaa, 0x68, 0x96,
+       0x84, 0x31, 0xe4, 0x45, 0x23, 0xee, 0x49, 0x7f, 0xee, 0x99, 0x06, 0xd7,
+       0x2b, 0x18, 0x5b, 0x61, 0x5d, 0x18, 0x03, 0x3e, 0x49, 0xba, 0xe8, 0xb2,
+       0x4f, 0x0a, 0xec, 0x78, 0x0c, 0xfc, 0x5a, 0xf0, 0xe9, 0x4a, 0x71, 0x1c,
+       0x47, 0xbe, 0xc1, 0xf2, 0xf9, 0x21, 0xc7, 0x41, 0xa1, 0xd3, 0x6c, 0xfb,
+       0xdb, 0x89, 0x5e, 0xe6, 0x59, 0xa1, 0x01, 0xdf, 0x3f, 0x34, 0x11, 0xe6,
+       0x1c, 0x7f, 0x8f, 0x39, 0x8c, 0x3b, 0xcd, 0x4a, 0x26, 0xce, 0xc8, 0x33,
+       0xcf, 0x38, 0xa7, 0xe4, 0x7d, 0xc1, 0x5b, 0xf0, 0x7d, 0x53, 0x6e, 0xe9,
+       0xc3, 0x74, 0x33, 0x46, 0x95, 0x59, 0xf0, 0x2e, 0x8f, 0x27, 0x9c, 0x6b,
+       0x1d, 0x7c, 0x03, 0x2d, 0xd5, 0x20, 0x9f, 0x3d, 0xc1, 0x31, 0x0d, 0xfe,
+       0x06, 0x36, 0xcd, 0x31, 0x6b, 0xe3, 0xde, 0xc9, 0xf7, 0x25, 0x32, 0x19,
+       0x41, 0xce, 0x2a, 0xe2, 0x2c, 0x3b, 0xcf, 0x7e, 0x10, 0xf8, 0xb8, 0xdf,
+       0xa5, 0xfa, 0x2c, 0xd3, 0x05, 0x1b, 0x4f, 0xb2, 0x2e, 0xfe, 0x7f, 0xf9,
+       0x38, 0xba, 0x45, 0x3e, 0x8e, 0x6e, 0x99, 0x8f, 0x12, 0xf8, 0x58, 0xd9,
+       0xe0, 0xa3, 0x82, 0x3d, 0xf8, 0x3e, 0xe1, 0xab, 0x64, 0x4d, 0x3c, 0x02,
+       0x3f, 0x0c, 0xff, 0xd1, 0x3c, 0x05, 0x9f, 0x70, 0x52, 0xb8, 0xda, 0xf0,
+       0x68, 0x1c, 0xb5, 0xb2, 0x74, 0xff, 0x66, 0xfa, 0x33, 0xa0, 0xff, 0xcf,
+       0x31, 0x5e, 0xa5, 0x6b, 0xb3, 0x94, 0x56, 0xa8, 0x7d, 0x2e, 0xed, 0x92,
+       0xe9, 0x3b, 0x74, 0x75, 0xb6, 0x8b, 0xae, 0xcf, 0x66, 0xc0, 0xeb, 0x2c,
+       0xc5, 0x7a, 0x32, 0xc3, 0x15, 0x18, 0xf1, 0xcf, 0x5a, 0xba, 0xc5, 0xba,
+       0xf8, 0xfb, 0xf3, 0x82, 0xf9, 0x70, 0xd0, 0xe7, 0xc3, 0xd8, 0x47, 0xf8,
+       0x30, 0x7e, 0x4f, 0x3e, 0x1c, 0xfc, 0x18, 0x1f, 0xc6, 0x3f, 0xc6, 0x07,
+       0xe6, 0x01, 0xf3, 0xe2, 0xd1, 0xde, 0xf0, 0xff, 0x1f, 0x7d, 0x82, 0x7d,
+       0x7c, 0x09, 0x74, 0x22, 0xa7, 0xd8, 0x19, 0xe4, 0x50, 0x9c, 0x63, 0xd5,
+       0x0c, 0xe6, 0x57, 0x60, 0xbf, 0x32, 0x72, 0xea, 0x23, 0xa1, 0xfd, 0x16,
+       0x1c, 0xe8, 0x65, 0x23, 0xe6, 0xdb, 0xaf, 0x64, 0xe6, 0xe1, 0x03, 0xaa,
+       0xa5, 0x96, 0xc3, 0xfe, 0x07, 0x6d, 0x87, 0x79, 0xda, 0x0b, 0x5a, 0x12,
+       0x54, 0x99, 0x54, 0x10, 0x5f, 0x87, 0xa1, 0xb7, 0x71, 0xdf, 0x07, 0x4a,
+       0x26, 0xeb, 0xe1, 0x7e, 0xcc, 0x3f, 0x1c, 0xe6, 0x45, 0x88, 0x73, 0x38,
+       0xa3, 0xd6, 0x38, 0x0d, 0xfc, 0xf8, 0x9c, 0x6a, 0xa9, 0xec, 0xf0, 0x9a,
+       0x34, 0x62, 0x21, 0x3f, 0x37, 0xeb, 0xb7, 0xaf, 0xef, 0xf7, 0xd2, 0x71,
+       0xe8, 0x26, 0xeb, 0xb4, 0x82, 0xdc, 0x78, 0x02, 0xf1, 0xc5, 0xd7, 0xd3,
+       0xec, 0x02, 0xb1, 0xdf, 0x7f, 0x06, 0x75, 0xd1, 0x61, 0xfc, 0x34, 0x1a,
+       0x71, 0x03, 0x9b, 0x5a, 0xf2, 0xcf, 0xfc, 0xb0, 0x4f, 0xaa, 0x39, 0xeb,
+       0xc8, 0xdf, 0x0d, 0xec, 0xcb, 0xe7, 0x56, 0xc1, 0x1b, 0x09, 0xe7, 0x72,
+       0x5f, 0x37, 0xe2, 0x00, 0xf8, 0xe4, 0xfe, 0x07, 0xfa, 0x97, 0xe0, 0x1f,
+       0x39, 0x2f, 0x68, 0xe3, 0x8e, 0x1c, 0xc2, 0xe1, 0x78, 0x9d, 0x07, 0xcd,
+       0x9c, 0x63, 0x73, 0x2e, 0x81, 0xfc, 0x63, 0xe9, 0x4d, 0xf4, 0x0d, 0xd3,
+       0xe9, 0xa1, 0x2c, 0xe4, 0xc3, 0x7d, 0x0f, 0x84, 0x7d, 0x3c, 0x8f, 0x94,
+       0x07, 0x4d, 0xfd, 0x07, 0x55, 0xdf, 0xaf, 0x43, 0x0f, 0x51, 0xf7, 0xd5,
+       0x96, 0x90, 0x63, 0x00, 0xa7, 0xca, 0x6a, 0x16, 0xb9, 0x3c, 0xdf, 0xab,
+       0xe9, 0x97, 0x91, 0x07, 0x83, 0x27, 0x0a, 0xf5, 0x1a, 0xa5, 0xd0, 0x0f,
+       0xe7, 0x40, 0x1f, 0xdf, 0x3d, 0xf5, 0x21, 0xf7, 0x91, 0xc0, 0x08, 0xd8,
+       0xe9, 0xaa, 0x44, 0x7b, 0xe5, 0x01, 0xb5, 0x46, 0xff, 0x80, 0xb9, 0x32,
+       0x95, 0x57, 0x39, 0x87, 0x90, 0xe9, 0xc8, 0x2a, 0xd1, 0x5b, 0x33, 0xec,
+       0x97, 0x19, 0xd8, 0x2f, 0xb3, 0x7f, 0x7d, 0xd0, 0x1f, 0x7b, 0x6b, 0x06,
+       0x35, 0xf8, 0xcc, 0x00, 0xc7, 0xb0, 0x75, 0x11, 0xbc, 0x44, 0xee, 0xc3,
+       0xf9, 0xf9, 0x5d, 0xee, 0x98, 0xda, 0xf7, 0x4b, 0x0a, 0x55, 0x66, 0xf8,
+       0x6e, 0x49, 0xc6, 0xf9, 0x5c, 0x5b, 0x6c, 0x03, 0x7e, 0x02, 0xa1, 0xee,
+       0x12, 0x38, 0xa6, 0x09, 0xd0, 0xa1, 0x5d, 0x90, 0x3d, 0xf8, 0x1f, 0xb6,
+       0xdb, 0xfa, 0xf4, 0x2f, 0xd0, 0x27, 0x9e, 0x27, 0x6f, 0xc2, 0x25, 0x33,
+       0x6b, 0x8b, 0x1c, 0x1f, 0x3e, 0x0d, 0xdb, 0xb3, 0xe2, 0x63, 0xcd, 0x0e,
+       0x6a, 0xf5, 0xb2, 0x3d, 0xb0, 0x5e, 0x5c, 0x66, 0x9d, 0xc0, 0x19, 0xd0,
+       0xa1, 0x19, 0xae, 0xe7, 0x65, 0xcc, 0xbb, 0x2f, 0x9c, 0xc7, 0xfc, 0xfe,
+       0x1e, 0x4d, 0x0f, 0xa9, 0x42, 0x59, 0x0d, 0xe2, 0x45, 0x6d, 0xa8, 0x03,
+       0x63, 0x22, 0x1d, 0x7c, 0x38, 0x8f, 0xb5, 0x9c, 0x53, 0xc5, 0x85, 0xc0,
+       0x6f, 0x71, 0x1f, 0xdf, 0xd7, 0xa9, 0x54, 0xbe, 0xd4, 0x4b, 0x95, 0x4b,
+       0x0a, 0xf8, 0x02, 0x44, 0x17, 0x82, 0x7d, 0xd8, 0x17, 0x1c, 0x87, 0xdc,
+       0xc4, 0x73, 0x0a, 0xc5, 0xce, 0x21, 0x87, 0xbc, 0xd0, 0x45, 0x1d, 0x17,
+       0xfa, 0x49, 0xba, 0xa0, 0x73, 0x7e, 0xa8, 0x9d, 0x81, 0x0c, 0x8f, 0x50,
+       0x9e, 0x9e, 0x73, 0x07, 0x39, 0xc7, 0xc3, 0x39, 0x5c, 0xe7, 0x25, 0x49,
+       0x42, 0xf2, 0x2f, 0xbe, 0x68, 0xd1, 0x8b, 0x43, 0xc0, 0x2b, 0x8f, 0xf6,
+       0x8f, 0x91, 0xc7, 0xbb, 0x23, 0xf7, 0x71, 0xcc, 0x96, 0xcd, 0x3e, 0xc8,
+       0x16, 0x74, 0xe5, 0x1e, 0xf2, 0xef, 0x44, 0x5f, 0x1c, 0x62, 0x7a, 0x34,
+       0xd0, 0x52, 0x87, 0xae, 0xf3, 0x3d, 0x57, 0x17, 0xd9, 0x32, 0xeb, 0x32,
+       0xf2, 0xaa, 0x0b, 0x75, 0x9a, 0x6a, 0xe8, 0x90, 0x59, 0x1f, 0xf4, 0x02,
+       0x32, 0x4b, 0x73, 0x3f, 0xef, 0x2d, 0x84, 0xfb, 0xde, 0xd1, 0xf7, 0x17,
+       0xef, 0xad, 0xef, 0x3e, 0xd4, 0x9b, 0x8f, 0xc0, 0x67, 0xa3, 0x2e, 0x32,
+       0xe0, 0xd3, 0x55, 0xe4, 0x72, 0x06, 0xbf, 0x07, 0x77, 0x95, 0x15, 0xe4,
+       0x85, 0xfc, 0x5e, 0x6b, 0xdd, 0xcd, 0x77, 0x07, 0xf6, 0x7d, 0x06, 0x3c,
+       0xba, 0x32, 0xf7, 0x00, 0x5d, 0x9d, 0x53, 0xe8, 0x5a, 0x43, 0xcf, 0x16,
+       0xa8, 0x83, 0xaa, 0xc9, 0x34, 0x5d, 0x5f, 0x6a, 0xe7, 0x93, 0x22, 0xf4,
+       0xc4, 0x22, 0xce, 0xcd, 0xaf, 0x2c, 0x55, 0x4b, 0x37, 0x76, 0xa7, 0x49,
+       0x7e, 0x09, 0xb6, 0xfd, 0x92, 0xae, 0xd5, 0xc0, 0xe7, 0xba, 0xe1, 0xa2,
+       0x56, 0xe3, 0x3a, 0x32, 0x05, 0xbb, 0xd3, 0x53, 0x2d, 0xca, 0x90, 0xb4,
+       0xa0, 0xd0, 0xaf, 0x66, 0x74, 0x8d, 0x75, 0xee, 0xa2, 0x81, 0x7e, 0x37,
+       0x7e, 0x7b, 0x3d, 0xd0, 0x43, 0xf4, 0xf5, 0xa3, 0xbe, 0xd5, 0xb3, 0x9a,
+       0xd8, 0x4d, 0x6f, 0x43, 0x27, 0xca, 0x7e, 0xdf, 0x47, 0xf7, 0xbc, 0x1e,
+       0xee, 0x59, 0x2d, 0x5d, 0xe1, 0x3a, 0x68, 0x86, 0x75, 0xbe, 0x17, 0xfe,
+       0x03, 0xef, 0x6e, 0x07, 0x95, 0x27, 0x11, 0xa3, 0x66, 0x1e, 0xa5, 0xc2,
+       0x90, 0x18, 0xd0, 0xed, 0xf3, 0x82, 0xfb, 0xf8, 0x7e, 0xb2, 0x76, 0x1f,
+       0xdb, 0xb2, 0xb8, 0x0a, 0xbd, 0x3a, 0xc8, 0x7a, 0x80, 0xdc, 0x0e, 0x39,
+       0x04, 0xfb, 0x4e, 0x09, 0x39, 0x44, 0xc1, 0x0d, 0x74, 0xa3, 0x75, 0x30,
+       0x49, 0xc7, 0x5e, 0x62, 0x19, 0x61, 0x6c, 0x43, 0xef, 0x36, 0xee, 0xc4,
+       0x31, 0x66, 0xd0, 0xf1, 0xef, 0xb7, 0x73, 0x4a, 0xb6, 0xbd, 0x34, 0xe4,
+       0xa1, 0xa3, 0xf6, 0xe8, 0x53, 0x2b, 0xbe, 0x4f, 0x81, 0x4e, 0xa4, 0x02,
+       0x19, 0xd4, 0x30, 0x36, 0xed, 0x4e, 0xc2, 0x27, 0xc6, 0xe8, 0xe6, 0xa4,
+       0x05, 0x9d, 0x68, 0x01, 0x87, 0xc3, 0x71, 0xbe, 0x4b, 0xb8, 0x39, 0x59,
+       0xc4, 0xfb, 0x61, 0x3f, 0xf7, 0x97, 0xf6, 0x40, 0x97, 0xdc, 0x07, 0xc2,
+       0xfc, 0x9c, 0xcf, 0xd3, 0x84, 0xda, 0xac, 0x2e, 0x4c, 0xcf, 0x7a, 0x34,
+       0x9a, 0xeb, 0x4b, 0x5d, 0xa5, 0x4e, 0xff, 0xce, 0xd8, 0xf7, 0x9b, 0xfe,
+       0x9c, 0x5d, 0x18, 0xff, 0x00, 0x3a, 0x85, 0x27, 0xe2, 0xf5, 0xe9, 0x66,
+       0x35, 0xd5, 0x41, 0xac, 0x53, 0x24, 0x2c, 0x18, 0xec, 0x3b, 0x04, 0xba,
+       0xea, 0xdf, 0x47, 0x13, 0x15, 0x9d, 0xd7, 0x99, 0x6e, 0x61, 0xb1, 0xc5,
+       0x6b, 0x58, 0xce, 0xbc, 0x46, 0xa2, 0x9b, 0x49, 0xd8, 0xe5, 0x9e, 0x3d,
+       0x7e, 0xbd, 0xf8, 0xf8, 0x10, 0xe3, 0xda, 0x0d, 0x99, 0x42, 0xbf, 0x50,
+       0xdb, 0x94, 0x83, 0xbe, 0x59, 0xae, 0x4d, 0xa7, 0xf9, 0xde, 0x23, 0xef,
+       0xeb, 0x5a, 0xa8, 0x1f, 0x1f, 0xd7, 0xb5, 0xe7, 0xb0, 0xf6, 0x2d, 0xf6,
+       0xab, 0x90, 0x75, 0xe0, 0x23, 0xbe, 0x41, 0x6f, 0xcd, 0x55, 0xb3, 0xfc,
+       0xcd, 0xa3, 0x35, 0x21, 0xa0, 0x16, 0x3f, 0x4e, 0x6f, 0xcf, 0x3d, 0x4b,
+       0xbf, 0x9c, 0x65, 0xdd, 0x31, 0x68, 0x14, 0xfa, 0x74, 0x94, 0xe4, 0xec,
+       0x69, 0x1a, 0x50, 0xaf, 0xfb, 0xb5, 0x8d, 0x9e, 0xf3, 0x6b, 0x3a, 0x33,
+       0x4b, 0xc5, 0xc6, 0x40, 0xea, 0x1a, 0xfa, 0xca, 0x93, 0xba, 0xb6, 0x8e,
+       0xdc, 0xa3, 0xd0, 0xfc, 0x80, 0xef, 0x6c, 0xb2, 0x35, 0xd8, 0xde, 0x22,
+       0x6a, 0x9b, 0xb7, 0x9d, 0xbb, 0xe9, 0x2c, 0xd7, 0x56, 0x81, 0xff, 0x5e,
+       0x33, 0x50, 0x63, 0xac, 0xaa, 0xa1, 0x0e, 0x31, 0x70, 0x9d, 0xc1, 0xf1,
+       0x07, 0x4f, 0x37, 0x06, 0x9f, 0xb2, 0x1f, 0x7c, 0x67, 0xd9, 0x42, 0xfe,
+       0xab, 0xfc, 0x8d, 0x0a, 0xf2, 0x5f, 0x5d, 0xfe, 0x40, 0xeb, 0x65, 0x3f,
+       0x6b, 0x80, 0x96, 0x41, 0x3a, 0x33, 0xcf, 0xf2, 0x47, 0xec, 0xf5, 0xed,
+       0x34, 0x0d, 0xfe, 0x72, 0x7c, 0x19, 0xa4, 0x5f, 0x2d, 0x15, 0xfd, 0xfb,
+       0x6b, 0x1b, 0xb9, 0xd6, 0x11, 0x67, 0x12, 0xf5, 0xfa, 0x77, 0x40, 0x2f,
+       0xce, 0x1e, 0xda, 0x8d, 0xa7, 0x0a, 0x9b, 0xdc, 0x72, 0x9e, 0x23, 0x07,
+       0x79, 0xce, 0xde, 0x2d, 0xe6, 0x39, 0x7b, 0xb7, 0x92, 0xe7, 0xc8, 0x9d,
+       0xe0, 0xab, 0xd6, 0xbb, 0x65, 0xdc, 0xa4, 0x00, 0xb7, 0x03, 0x5b, 0xc4,
+       0xed, 0xc0, 0x56, 0x70, 0x93, 0x3a, 0xcd, 0xbf, 0x40, 0x8c, 0x35, 0x10,
+       0xdb, 0xe0, 0xd7, 0x86, 0xfa, 0x59, 0x7f, 0x80, 0xa3, 0x8f, 0xeb, 0xef,
+       0x8b, 0xa7, 0x18, 0xe0, 0xf9, 0xd8, 0x16, 0xf1, 0x7c, 0x6c, 0x2b, 0x78,
+       0x8a, 0x9d, 0x26, 0xe3, 0x28, 0xc3, 0xd7, 0x70, 0x6d, 0x83, 0xd8, 0x3c,
+       0x24, 0x87, 0xba, 0x2e, 0x87, 0x75, 0x0e, 0x03, 0x7c, 0x50, 0xaf, 0x46,
+       0x4b, 0x4c, 0xcb, 0x46, 0xdf, 0x9d, 0x3a, 0x4b, 0x32, 0x5b, 0xa5, 0x4a,
+       0x83, 0xef, 0x95, 0xfb, 0xb0, 0x0f, 0xf7, 0xf1, 0x37, 0x2a, 0x8b, 0x64,
+       0xc4, 0xf7, 0xe7, 0x9a, 0x77, 0xa7, 0xf5, 0x2a, 0x68, 0x9d, 0x0a, 0x69,
+       0xad, 0xf8, 0xb9, 0xe0, 0xbe, 0x4d, 0xb9, 0x60, 0x40, 0xe3, 0x08, 0x68,
+       0x2c, 0x86, 0x34, 0x3e, 0xdd, 0x60, 0xda, 0xf6, 0xf9, 0xb4, 0x2d, 0x6d,
+       0xa2, 0x6d, 0xe4, 0x9e, 0xf9, 0x1f, 0xe3, 0x81, 0x5a, 0x1a, 0xb9, 0xd7,
+       0x6b, 0x4d, 0xd4, 0xd2, 0x4d, 0xd4, 0xd2, 0xd0, 0xf7, 0x57, 0x9b, 0xa8,
+       0xa5, 0x9b, 0xa8, 0xa5, 0x61, 0x07, 0xaf, 0xc0, 0x56, 0x82, 0x3b, 0xdc,
+       0x12, 0x71, 0x0d, 0xee, 0xd7, 0xe3, 0x14, 0xe4, 0x39, 0x05, 0xc4, 0xf0,
+       0xa3, 0xc8, 0xf1, 0xd8, 0x6e, 0x4f, 0x13, 0xc7, 0x04, 0x3d, 0x87, 0x9a,
+       0x2f, 0x5b, 0x25, 0x33, 0x5e, 0x9c, 0x1f, 0x50, 0x97, 0x02, 0xfb, 0xd6,
+       0x5a, 0xc4, 0x71, 0x70, 0x20, 0x85, 0x08, 0xa9, 0xb2, 0x5f, 0xb0, 0x73,
+       0x4c, 0xe7, 0x76, 0xf0, 0x10, 0xbe, 0xdb, 0x60, 0x1f, 0xc6, 0xbe, 0xb4,
+       0x4e, 0x0b, 0x8d, 0xf0, 0x1b, 0x9a, 0xcc, 0xfd, 0xfc, 0xce, 0x31, 0xb7,
+       0xcf, 0xf7, 0x69, 0x76, 0xb6, 0x0f, 0x71, 0x80, 0xfb, 0x15, 0xf8, 0x35,
+       0xe8, 0xca, 0x52, 0x1b, 0x17, 0x19, 0xeb, 0x55, 0xaa, 0xcf, 0x07, 0x31,
+       0x7c, 0xca, 0xe0, 0x38, 0x87, 0xf8, 0xbe, 0xc4, 0xdf, 0xb0, 0x10, 0xeb,
+       0x97, 0xae, 0x68, 0x32, 0x6a, 0xc7, 0x3a, 0x7f, 0xa3, 0x1d, 0xec, 0xc3,
+       0xf9, 0x1d, 0xfe, 0x1d, 0xed, 0x51, 0xff, 0xae, 0xcd, 0xa0, 0x23, 0xad,
+       0x80, 0x16, 0xdb, 0xc8, 0xd0, 0xc8, 0x2c, 0xdf, 0x35, 0x51, 0x8f, 0x68,
+       0xca, 0x54, 0x75, 0xf8, 0x7e, 0x68, 0xe3, 0xbb, 0x49, 0x76, 0x91, 0xeb,
+       0x4f, 0x23, 0xb8, 0xff, 0x3c, 0xed, 0xbc, 0xc9, 0xf7, 0x9f, 0xe1, 0x3a,
+       0x8d, 0xde, 0x70, 0x33, 0x34, 0x8e, 0xf8, 0x5a, 0x6c, 0x68, 0xf0, 0x6f,
+       0xbe, 0x3c, 0x39, 0xa7, 0xad, 0xc6, 0x42, 0x99, 0x8e, 0x84, 0x32, 0xad,
+       0x34, 0xd6, 0x80, 0xdf, 0x0d, 0xef, 0x8f, 0x43, 0x99, 0xee, 0x3a, 0x47,
+       0xda, 0xd5, 0x1c, 0xcb, 0x95, 0x65, 0x19, 0xc8, 0x75, 0x7c, 0xb1, 0x24,
+       0x14, 0x21, 0xd3, 0x51, 0x5f, 0xa6, 0x32, 0xc7, 0x05, 0xec, 0x95, 0x83,
+       0xfc, 0xd9, 0x8f, 0xe1, 0xe9, 0xb0, 0x8c, 0xb9, 0xde, 0xe0, 0x58, 0x98,
+       0xa4, 0x4b, 0x9b, 0xe4, 0x5c, 0xbc, 0xa7, 0x0e, 0xe7, 0xa9, 0xff, 0x9c,
+       0x16, 0xde, 0x9b, 0x66, 0x21, 0xc7, 0x76, 0x2e, 0xf6, 0x23, 0x81, 0x8c,
+       0xf6, 0x9d, 0x6e, 0xbb, 0xef, 0xe5, 0x4d, 0x7d, 0xed, 0x67, 0x9b, 0x56,
+       0xc4, 0xb7, 0x0d, 0xde, 0xf3, 0x1d, 0xe4, 0x9d, 0x7e, 0xc9, 0x1f, 0x53,
+       0x31, 0xd6, 0x4b, 0x85, 0x25, 0x83, 0xac, 0x16, 0xcf, 0x91, 0x49, 0x34,
+       0xda, 0x72, 0xea, 0xa4, 0xf5, 0x30, 0xc6, 0x2d, 0x34, 0x3c, 0xef, 0xa7,
+       0xd0, 0x9d, 0x8b, 0x5c, 0x77, 0x3b, 0xbf, 0xf1, 0xd6, 0x93, 0xc8, 0x21,
+       0x37, 0xce, 0xfc, 0xe6, 0xfd, 0xd4, 0xa5, 0xab, 0x88, 0x09, 0x74, 0xc6,
+       0x09, 0x51, 0x22, 0x1e, 0xe7, 0x3e, 0xfe, 0x06, 0xef, 0x79, 0x17, 0x8d,
+       0x3b, 0x78, 0x75, 0x99, 0xc7, 0x69, 0xdf, 0x39, 0xf6, 0xff, 0x3f, 0xd0,
+       0x2e, 0x1a, 0xd6, 0x9e, 0x38, 0xf2, 0xe7, 0xeb, 0xc4, 0xb1, 0x4f, 0x4e,
+       0x14, 0x9b, 0xba, 0x7a, 0x09, 0x6b, 0x8b, 0x8e, 0xc2, 0xdf, 0xd6, 0xf9,
+       0xfb, 0xa8, 0x76, 0x89, 0xda, 0xf7, 0x65, 0x90, 0xa7, 0xa3, 0xf2, 0x77,
+       0x52, 0xb5, 0x8a, 0xd8, 0x52, 0x70, 0x92, 0x98, 0xaf, 0x62, 0x2e, 0xc7,
+       0x05, 0x8f, 0x14, 0xd8, 0x50, 0xc1, 0x49, 0x27, 0xc6, 0x9a, 0x9e, 0xa7,
+       0x7c, 0x5e, 0xa0, 0x87, 0x32, 0x29, 0x1a, 0x73, 0xf8, 0xfe, 0xf7, 0x9b,
+       0xf4, 0x36, 0xec, 0xac, 0x78, 0x9e, 0x6b, 0x26, 0xf6, 0x29, 0x78, 0x77,
+       0xf8, 0xbe, 0xea, 0x14, 0x3d, 0xb4, 0x47, 0xcf, 0x5e, 0x22, 0xe0, 0xb3,
+       0x42, 0xfd, 0x48, 0x72, 0x53, 0xc7, 0xfd, 0xef, 0x6d, 0x8c, 0x6b, 0x9a,
+       0x96, 0xc0, 0x1b, 0xa7, 0x99, 0xa4, 0x95, 0x66, 0x8a, 0x56, 0xa1, 0x1f,
+       0xdb, 0xcc, 0x32, 0x7d, 0x03, 0x78, 0x2b, 0x66, 0x95, 0x94, 0x8c, 0xb5,
+       0xaf, 0x0b, 0x78, 0x67, 0x05, 0x3d, 0x15, 0x17, 0x18, 0x77, 0x5d, 0x2d,
+       0x03, 0x6f, 0xd6, 0xd1, 0x51, 0xa7, 0x9b, 0x8e, 0x61, 0xed, 0x7e, 0xe4,
+       0x1f, 0xdf, 0x72, 0xa8, 0x2c, 0x99, 0x29, 0x3a, 0x80, 0xf3, 0x8e, 0x36,
+       0x38, 0x57, 0x3b, 0x02, 0x5f, 0x23, 0xd0, 0xa3, 0x19, 0x8f, 0x1e, 0xdd,
+       0xa3, 0x5b, 0x71, 0x01, 0x7b, 0xae, 0xb0, 0x9e, 0xa0, 0xdf, 0x09, 0xce,
+       0x8d, 0xad, 0xf8, 0xba, 0x08, 0x7f, 0xfa, 0x0c, 0x65, 0xce, 0xad, 0xe5,
+       0xa6, 0x90, 0x9f, 0x8f, 0x36, 0xe9, 0x8b, 0x31, 0x9c, 0xf7, 0x36, 0xf8,
+       0x34, 0xea, 0xc8, 0x02, 0xf3, 0xe9, 0x58, 0xc0, 0x27, 0x8c, 0xf1, 0xb7,
+       0x23, 0xce, 0xd1, 0xf8, 0xec, 0x13, 0x74, 0xb6, 0xc1, 0x77, 0xdd, 0x27,
+       0xe8, 0x4a, 0xe3, 0x11, 0xba, 0x98, 0xe3, 0x5c, 0x07, 0xfb, 0xf8, 0x67,
+       0xa0, 0xcf, 0x3f, 0xa3, 0x9b, 0x8e, 0xfb, 0x72, 0xfa, 0x3f, 0xc3, 0x06,
+       0xd0, 0x70, 0x4c, 0x57, 0x00, 0x00, 0x00 };
 
 static u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x0 };
 static u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 };
index 55d236726d118382d0237db9d503305de3d7eba0..8171cae066888c23d0ec22d0019bdda9353c840f 100644 (file)
@@ -1199,8 +1199,7 @@ int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
 }
 
 #define BOND_INTERSECT_FEATURES \
-       (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
-       NETIF_F_TSO|NETIF_F_UFO)
+       (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO)
 
 /* 
  * Compute the common dev->feature set available to all slaves.  Some
@@ -1218,9 +1217,7 @@ static int bond_compute_features(struct bonding *bond)
                features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
 
        if ((features & NETIF_F_SG) && 
-           !(features & (NETIF_F_IP_CSUM |
-                         NETIF_F_NO_CSUM |
-                         NETIF_F_HW_CSUM)))
+           !(features & NETIF_F_ALL_CSUM))
                features &= ~NETIF_F_SG;
 
        /* 
@@ -4191,7 +4188,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
         */
        bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
 
-       /* don't acquire bond device's xmit_lock when 
+       /* don't acquire bond device's netif_tx_lock when
         * transmitting */
        bond_dev->features |= NETIF_F_LLTX;
 
index ac48f7543500b7c53d5099383fa26c83c247a45e..39f36aa05aa8b005bf4b2b2638ef7f1a47810f6e 100644 (file)
@@ -4877,7 +4877,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
        static int cas_version_printed = 0;
-       unsigned long casreg_base, casreg_len;
+       unsigned long casreg_len;
        struct net_device *dev;
        struct cas *cp;
        int i, err, pci_using_dac;
@@ -4972,7 +4972,6 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
                pci_using_dac = 0;
        }
 
-       casreg_base = pci_resource_start(pdev, 0);
        casreg_len = pci_resource_len(pdev, 0);
 
        cp = netdev_priv(dev);
@@ -5024,7 +5023,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
        cp->timer_ticks = 0;
 
        /* give us access to cassini registers */
-       cp->regs = ioremap(casreg_base, casreg_len);
+       cp->regs = pci_iomap(pdev, 0, casreg_len);
        if (cp->regs == 0UL) {
                printk(KERN_ERR PFX "Cannot map device registers, "
                       "aborting.\n");
@@ -5123,7 +5122,7 @@ err_out_iounmap:
                cas_shutdown(cp);
        mutex_unlock(&cp->pm_mutex);
 
-       iounmap(cp->regs);
+       pci_iounmap(pdev, cp->regs);
 
 
 err_out_free_res:
@@ -5171,7 +5170,7 @@ static void __devexit cas_remove_one(struct pci_dev *pdev)
 #endif
        pci_free_consistent(pdev, sizeof(struct cas_init_block),
                            cp->init_block, cp->block_dvma);
-       iounmap(cp->regs);
+       pci_iounmap(pdev, cp->regs);
        free_netdev(dev);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
index 31ac001f5517b244baf2b39c9b7969a5ad9faa2e..f37170cc1a377fb3b05a17622c28c27f048fe043 100644 (file)
@@ -2780,6 +2780,80 @@ static void e100_shutdown(struct pci_dev *pdev)
                DPRINTK(PROBE,ERR, "Error enabling wake\n");
 }
 
+/* ------------------ PCI Error Recovery infrastructure  -------------- */
+/**
+ * e100_io_error_detected - called when PCI error is detected.
+ * @pdev: Pointer to PCI device
+ * @state: The current pci conneection state
+ */
+static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+
+       /* Similar to calling e100_down(), but avoids adpater I/O. */
+       netdev->stop(netdev);
+
+       /* Detach; put netif into state similar to hotplug unplug. */
+       netif_poll_enable(netdev);
+       netif_device_detach(netdev);
+
+       /* Request a slot reset. */
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * e100_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch.
+ */
+static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct nic *nic = netdev_priv(netdev);
+
+       if (pci_enable_device(pdev)) {
+               printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+       pci_set_master(pdev);
+
+       /* Only one device per card can do a reset */
+       if (0 != PCI_FUNC(pdev->devfn))
+               return PCI_ERS_RESULT_RECOVERED;
+       e100_hw_reset(nic);
+       e100_phy_init(nic);
+
+       return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * e100_io_resume - resume normal operations
+ * @pdev: Pointer to PCI device
+ *
+ * Resume normal operations after an error recovery
+ * sequence has been completed.
+ */
+static void e100_io_resume(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct nic *nic = netdev_priv(netdev);
+
+       /* ack any pending wake events, disable PME */
+       pci_enable_wake(pdev, 0, 0);
+
+       netif_device_attach(netdev);
+       if (netif_running(netdev)) {
+               e100_open(netdev);
+               mod_timer(&nic->watchdog, jiffies);
+       }
+}
+
+static struct pci_error_handlers e100_err_handler = {
+       .error_detected = e100_io_error_detected,
+       .slot_reset = e100_io_slot_reset,
+       .resume = e100_io_resume,
+};
 
 static struct pci_driver e100_driver = {
        .name =         DRV_NAME,
@@ -2791,6 +2865,7 @@ static struct pci_driver e100_driver = {
        .resume =       e100_resume,
 #endif
        .shutdown =     e100_shutdown,
+       .err_handler = &e100_err_handler,
 };
 
 static int __init e100_init_module(void)
index ca9f89552da37507bab48b49e304145597ff1cf9..5dea2b7dea4d6b9118f4ad9426ea7093058779e7 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # 
-# Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+# Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -22,6 +22,7 @@
 # 
 # Contact Information:
 # Linux NICS <linux.nics@intel.com>
+# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
 # Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 #
 ################################################################################
index 281de41d030a9991b590314f89b53e25ef07540e..2bc34fbfa69c0ee93b7b17f277c6fd14e67d4712 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
@@ -114,6 +115,8 @@ struct e1000_adapter;
 /* Supported Rx Buffer Sizes */
 #define E1000_RXBUFFER_128   128    /* Used for packet split */
 #define E1000_RXBUFFER_256   256    /* Used for packet split */
+#define E1000_RXBUFFER_512   512
+#define E1000_RXBUFFER_1024  1024
 #define E1000_RXBUFFER_2048  2048
 #define E1000_RXBUFFER_4096  4096
 #define E1000_RXBUFFER_8192  8192
@@ -334,7 +337,6 @@ struct e1000_adapter {
        boolean_t have_msi;
 #endif
        /* to not mess up cache alignment, always add to the bottom */
-       boolean_t txb2b;
 #ifdef NETIF_F_TSO
        boolean_t tso_force;
 #endif
index ecccca35c6f4db1ba739224a6cdc978f7a2c82ad..6ed7f599eba3dd656ce3e3d1bb4776d21c4af93a 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
@@ -864,19 +865,22 @@ static int
 e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
 {
        struct net_device *netdev = adapter->netdev;
-       uint32_t mask, i=0, shared_int = TRUE;
-       uint32_t irq = adapter->pdev->irq;
+       uint32_t mask, i=0, shared_int = TRUE;
+       uint32_t irq = adapter->pdev->irq;
 
        *data = 0;
 
        /* Hook up test interrupt handler just for this test */
-       if (!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
+       if (!request_irq(irq, &e1000_test_intr, SA_PROBEIRQ, netdev->name,
+                        netdev)) {
                shared_int = FALSE;
        } else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ,
                              netdev->name, netdev)){
                *data = 1;
                return -1;
        }
+       DPRINTK(PROBE,INFO, "testing %s interrupt\n",
+               (shared_int ? "shared" : "unshared"));
 
        /* Disable all the interrupts */
        E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
@@ -888,22 +892,22 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
                /* Interrupt to test */
                mask = 1 << i;
 
-               if (!shared_int) {
-                       /* Disable the interrupt to be reported in
-                        * the cause register and then force the same
-                        * interrupt and see if one gets posted.  If
-                        * an interrupt was posted to the bus, the
-                        * test failed.
-                        */
-                       adapter->test_icr = 0;
-                       E1000_WRITE_REG(&adapter->hw, IMC, mask);
-                       E1000_WRITE_REG(&adapter->hw, ICS, mask);
-                       msec_delay(10);
-
-                       if (adapter->test_icr & mask) {
-                               *data = 3;
-                               break;
-                       }
+               if (!shared_int) {
+                       /* Disable the interrupt to be reported in
+                        * the cause register and then force the same
+                        * interrupt and see if one gets posted.  If
+                        * an interrupt was posted to the bus, the
+                        * test failed.
+                        */
+                       adapter->test_icr = 0;
+                       E1000_WRITE_REG(&adapter->hw, IMC, mask);
+                       E1000_WRITE_REG(&adapter->hw, ICS, mask);
+                       msec_delay(10);
+
+                       if (adapter->test_icr & mask) {
+                               *data = 3;
+                               break;
+                       }
                }
 
                /* Enable the interrupt to be reported in
@@ -922,7 +926,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
                        break;
                }
 
-               if (!shared_int) {
+               if (!shared_int) {
                        /* Disable the other interrupts to be reported in
                         * the cause register and then force the other
                         * interrupts and see if any get posted.  If
index 523c2c9fc0ac6e315ded95e4c8cc23dec2364ddf..3959039b16ec375e9fcd798666494082ac5fa506 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
@@ -764,7 +765,7 @@ e1000_init_hw(struct e1000_hw *hw)
     }
 
     if (hw->mac_type == e1000_82573) {
-        e1000_enable_tx_pkt_filtering(hw); 
+        e1000_enable_tx_pkt_filtering(hw);
     }
 
     switch (hw->mac_type) {
@@ -860,7 +861,7 @@ e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
 
     if(eeprom_data != EEPROM_RESERVED_WORD) {
         /* Adjust SERDES output amplitude only. */
-        eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; 
+        eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
         if(ret_val)
             return ret_val;
@@ -1227,7 +1228,7 @@ e1000_copper_link_igp_setup(struct e1000_hw *hw)
 
     if (hw->phy_reset_disable)
         return E1000_SUCCESS;
-    
+
     ret_val = e1000_phy_reset(hw);
     if (ret_val) {
         DEBUGOUT("Error Resetting the PHY\n");
@@ -1369,7 +1370,7 @@ e1000_copper_link_ggp_setup(struct e1000_hw *hw)
     DEBUGFUNC("e1000_copper_link_ggp_setup");
 
     if(!hw->phy_reset_disable) {
-        
+
         /* Enable CRS on TX for half-duplex operation. */
         ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
                                      &phy_data);
@@ -1518,7 +1519,7 @@ e1000_copper_link_mgp_setup(struct e1000_hw *hw)
 
     if(hw->phy_reset_disable)
         return E1000_SUCCESS;
-    
+
     /* Enable CRS on TX. This must be set for half-duplex operation. */
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
     if(ret_val)
@@ -1664,7 +1665,7 @@ e1000_copper_link_autoneg(struct e1000_hw *hw)
 *      collision distance in the Transmit Control Register.
 *   2) Set up flow control on the MAC to that established with
 *      the link partner.
-*   3) Config DSP to improve Gigabit link quality for some PHY revisions.    
+*   3) Config DSP to improve Gigabit link quality for some PHY revisions.
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
@@ -1673,7 +1674,7 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
 {
     int32_t ret_val;
     DEBUGFUNC("e1000_copper_link_postconfig");
-    
+
     if(hw->mac_type >= e1000_82544) {
         e1000_config_collision_dist(hw);
     } else {
@@ -1697,7 +1698,7 @@ e1000_copper_link_postconfig(struct e1000_hw *hw)
             return ret_val;
         }
     }
-                
+
     return E1000_SUCCESS;
 }
 
@@ -1753,11 +1754,11 @@ e1000_setup_copper_link(struct e1000_hw *hw)
     }
 
     if(hw->autoneg) {
-        /* Setup autoneg and flow control advertisement 
-          * and perform autonegotiation */   
+        /* Setup autoneg and flow control advertisement
+          * and perform autonegotiation */
         ret_val = e1000_copper_link_autoneg(hw);
         if(ret_val)
-            return ret_val;           
+            return ret_val;
     } else {
         /* PHY will be set to 10H, 10F, 100H,or 100F
           * depending on value from forced_speed_duplex. */
@@ -1785,7 +1786,7 @@ e1000_setup_copper_link(struct e1000_hw *hw)
             ret_val = e1000_copper_link_postconfig(hw);
             if(ret_val)
                 return ret_val;
-            
+
             DEBUGOUT("Valid link established!!!\n");
             return E1000_SUCCESS;
         }
@@ -1983,7 +1984,7 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
 
     DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
 
-    ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);    
+    ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
     if(ret_val)
         return ret_val;
 
@@ -2272,7 +2273,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
 
     DEBUGFUNC("e1000_config_mac_to_phy");
 
-    /* 82544 or newer MAC, Auto Speed Detection takes care of 
+    /* 82544 or newer MAC, Auto Speed Detection takes care of
     * MAC speed/duplex configuration.*/
     if (hw->mac_type >= e1000_82544)
         return E1000_SUCCESS;
@@ -2291,9 +2292,9 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
     if(ret_val)
         return ret_val;
 
-    if(phy_data & M88E1000_PSSR_DPLX) 
+    if(phy_data & M88E1000_PSSR_DPLX)
         ctrl |= E1000_CTRL_FD;
-    else 
+    else
         ctrl &= ~E1000_CTRL_FD;
 
     e1000_config_collision_dist(hw);
@@ -2492,10 +2493,10 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                  */
                 if(hw->original_fc == e1000_fc_full) {
                     hw->fc = e1000_fc_full;
-                    DEBUGOUT("Flow Control = FULL.\r\n");
+                    DEBUGOUT("Flow Control = FULL.\n");
                 } else {
                     hw->fc = e1000_fc_rx_pause;
-                    DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                    DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
                 }
             }
             /* For receiving PAUSE frames ONLY.
@@ -2511,7 +2512,7 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                     (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                     (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                 hw->fc = e1000_fc_tx_pause;
-                DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
             }
             /* For transmitting PAUSE frames ONLY.
              *
@@ -2526,7 +2527,7 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                     !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                     (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                 hw->fc = e1000_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
             }
             /* Per the IEEE spec, at this point flow control should be
              * disabled.  However, we want to consider that we could
@@ -2552,10 +2553,10 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                      hw->original_fc == e1000_fc_tx_pause) ||
                     hw->fc_strict_ieee) {
                 hw->fc = e1000_fc_none;
-                DEBUGOUT("Flow Control = NONE.\r\n");
+                DEBUGOUT("Flow Control = NONE.\n");
             } else {
                 hw->fc = e1000_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
             }
 
             /* Now we need to do one last check...  If we auto-
@@ -2580,7 +2581,7 @@ e1000_config_fc_after_link_up(struct e1000_hw *hw)
                 return ret_val;
             }
         } else {
-            DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n");
+            DEBUGOUT("Copper PHY and Auto Neg has not completed.\n");
         }
     }
     return E1000_SUCCESS;
@@ -2763,7 +2764,7 @@ e1000_check_for_link(struct e1000_hw *hw)
             hw->autoneg_failed = 1;
             return 0;
         }
-        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n");
+        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
 
         /* Disable auto-negotiation in the TXCW register */
         E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE));
@@ -2788,7 +2789,7 @@ e1000_check_for_link(struct e1000_hw *hw)
     else if(((hw->media_type == e1000_media_type_fiber) ||
              (hw->media_type == e1000_media_type_internal_serdes)) &&
             (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
+        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
         E1000_WRITE_REG(hw, TXCW, hw->txcw);
         E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
 
@@ -2851,13 +2852,13 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
 
         if(status & E1000_STATUS_FD) {
             *duplex = FULL_DUPLEX;
-            DEBUGOUT("Full Duplex\r\n");
+            DEBUGOUT("Full Duplex\n");
         } else {
             *duplex = HALF_DUPLEX;
-            DEBUGOUT(" Half Duplex\r\n");
+            DEBUGOUT(" Half Duplex\n");
         }
     } else {
-        DEBUGOUT("1000 Mbs, Full Duplex\r\n");
+        DEBUGOUT("1000 Mbs, Full Duplex\n");
         *speed = SPEED_1000;
         *duplex = FULL_DUPLEX;
     }
@@ -2883,7 +2884,7 @@ e1000_get_speed_and_duplex(struct e1000_hw *hw,
         }
     }
 
-    if ((hw->mac_type == e1000_80003es2lan) && 
+    if ((hw->mac_type == e1000_80003es2lan) &&
         (hw->media_type == e1000_media_type_copper)) {
         if (*speed == SPEED_1000)
             ret_val = e1000_configure_kmrn_for_1000(hw);
@@ -3159,7 +3160,7 @@ e1000_read_phy_reg(struct e1000_hw *hw,
     if (e1000_swfw_sync_acquire(hw, swfw))
         return -E1000_ERR_SWFW_SYNC;
 
-    if((hw->phy_type == e1000_phy_igp || 
+    if((hw->phy_type == e1000_phy_igp ||
         hw->phy_type == e1000_phy_igp_2) &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
@@ -3298,7 +3299,7 @@ e1000_write_phy_reg(struct e1000_hw *hw,
     if (e1000_swfw_sync_acquire(hw, swfw))
         return -E1000_ERR_SWFW_SYNC;
 
-    if((hw->phy_type == e1000_phy_igp || 
+    if((hw->phy_type == e1000_phy_igp ||
         hw->phy_type == e1000_phy_igp_2) &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
@@ -3496,22 +3497,22 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
         }
         /* Read the device control register and assert the E1000_CTRL_PHY_RST
          * bit. Then, take it out of reset.
-         * For pre-e1000_82571 hardware, we delay for 10ms between the assert 
+         * For pre-e1000_82571 hardware, we delay for 10ms between the assert
          * and deassert.  For e1000_82571 hardware and later, we instead delay
          * for 50us between and 10ms after the deassertion.
          */
         ctrl = E1000_READ_REG(hw, CTRL);
         E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
         E1000_WRITE_FLUSH(hw);
-        
-        if (hw->mac_type < e1000_82571) 
+
+        if (hw->mac_type < e1000_82571)
             msec_delay(10);
         else
             udelay(100);
-        
+
         E1000_WRITE_REG(hw, CTRL, ctrl);
         E1000_WRITE_FLUSH(hw);
-        
+
         if (hw->mac_type >= e1000_82571)
             msec_delay(10);
         e1000_swfw_sync_release(hw, swfw);
@@ -3815,7 +3816,7 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
     /* Check polarity status */
     ret_val = e1000_check_polarity(hw, &polarity);
     if(ret_val)
-        return ret_val; 
+        return ret_val;
     phy_info->cable_polarity = polarity;
 
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
@@ -4540,14 +4541,14 @@ e1000_read_eeprom_eerd(struct e1000_hw *hw,
 
         E1000_WRITE_REG(hw, EERD, eerd);
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
-        
+
         if(error) {
             break;
         }
         data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA);
-      
+
     }
-    
+
     return error;
 }
 
@@ -4573,24 +4574,24 @@ e1000_write_eeprom_eewr(struct e1000_hw *hw,
         return -E1000_ERR_SWFW_SYNC;
 
     for (i = 0; i < words; i++) {
-        register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | 
-                         ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | 
+        register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) |
+                         ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) |
                          E1000_EEPROM_RW_REG_START;
 
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
         if(error) {
             break;
-        }       
+        }
 
         E1000_WRITE_REG(hw, EEWR, register_value);
-        
+
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
-        
+
         if(error) {
             break;
-        }       
+        }
     }
-    
+
     e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
     return error;
 }
@@ -4610,7 +4611,7 @@ e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
     for(i = 0; i < attempts; i++) {
         if(eerd == E1000_EEPROM_POLL_READ)
             reg = E1000_READ_REG(hw, EERD);
-        else 
+        else
             reg = E1000_READ_REG(hw, EEWR);
 
         if(reg & E1000_EEPROM_RW_REG_DONE) {
@@ -5135,7 +5136,7 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
     uint32_t i;
     uint32_t num_rar_entry;
     uint32_t num_mta_entry;
-    
+
     DEBUGFUNC("e1000_mc_addr_list_update");
 
     /* Set the new number of MC addresses that we are being requested to use. */
@@ -6240,7 +6241,7 @@ e1000_check_polarity(struct e1000_hw *hw,
  *                                1 - Downshift ocured.
  *
  * returns: - E1000_ERR_XXX
- *            E1000_SUCCESS 
+ *            E1000_SUCCESS
  *
  * For phy's older then IGP, this function reads the Downshift bit in the Phy
  * Specific Status register.  For IGP phy's, it reads the Downgrade bit in the
@@ -6255,7 +6256,7 @@ e1000_check_downshift(struct e1000_hw *hw)
 
     DEBUGFUNC("e1000_check_downshift");
 
-    if(hw->phy_type == e1000_phy_igp || 
+    if(hw->phy_type == e1000_phy_igp ||
         hw->phy_type == e1000_phy_igp_2) {
         ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
                                      &phy_data);
@@ -6684,8 +6685,8 @@ e1000_set_d0_lplu_state(struct e1000_hw *hw,
 
 
     } else {
-            phy_data |= IGP02E1000_PM_D0_LPLU;   
+
+            phy_data |= IGP02E1000_PM_D0_LPLU;
             ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
             if (ret_val)
                 return ret_val;
@@ -6777,7 +6778,7 @@ int32_t
 e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
 {
     uint8_t i;
-    uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET; 
+    uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET;
     uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH;
 
     length = (length >> 2);
@@ -6796,7 +6797,7 @@ e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
  * and also checks whether the previous command is completed.
  * It busy waits in case of previous command is not completed.
  *
- * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or 
+ * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or
  *            timeout
  *          - E1000_SUCCESS for success.
  ****************************************************************************/
@@ -6820,7 +6821,7 @@ e1000_mng_enable_host_if(struct e1000_hw * hw)
         msec_delay_irq(1);
     }
 
-    if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { 
+    if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
         DEBUGOUT("Previous command timeout failed .\n");
         return -E1000_ERR_HOST_INTERFACE_COMMAND;
     }
index 150e45e30f87a7f85e53d67909cd35618e57b1f8..467c9ed944f84a935aeeec20ebe8d52ec1222326 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
@@ -374,7 +375,7 @@ struct e1000_host_mng_dhcp_cookie{
 };
 #endif
 
-int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer, 
+int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer,
                                                        uint16_t length);
 boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
 boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
@@ -1801,7 +1802,7 @@ struct e1000_hw {
  *       value2 = [0..64512],    default=4096
  *       value3 = [0..64512],    default=0
  */
-    
+
 #define E1000_PSRCTL_BSIZE0_MASK   0x0000007F
 #define E1000_PSRCTL_BSIZE1_MASK   0x00003F00
 #define E1000_PSRCTL_BSIZE2_MASK   0x003F0000
index c99e87838f92913ce277c9a2494955551cb79f04..a373ccb308d8d3281298bee38c1a5dcbfcc8ca7f 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
 
 #include "e1000.h"
 
-/* Change Log
- * 7.0.33      3-Feb-2006
- *   o Added another fix for the pass false carrier bit
- * 7.0.32      24-Jan-2006
- *   o Need to rebuild with noew version number for the pass false carrier 
- *     fix in e1000_hw.c
- * 7.0.30      18-Jan-2006
- *   o fixup for tso workaround to disable it for pci-x
- *   o fix mem leak on 82542
- *   o fixes for 10 Mb/s connections and incorrect stats
- * 7.0.28      01/06/2006
- *   o hardware workaround to only set "speed mode" bit for 1G link.
- * 7.0.26      12/23/2005
- *   o wake on lan support modified for device ID 10B5
- *   o fix dhcp + vlan issue not making it to the iAMT firmware
- * 7.0.24      12/9/2005
- *   o New hardware support for the Gigabit NIC embedded in the south bridge
- *   o Fixes to the recycling logic (skb->tail) from IBM LTC
- * 6.3.9       12/16/2005
- *   o incorporate fix for recycled skbs from IBM LTC
- * 6.3.7       11/18/2005
- *   o Honor eeprom setting for enabling/disabling Wake On Lan
- * 6.3.5       11/17/2005
- *   o Fix memory leak in rx ring handling for PCI Express adapters
- * 6.3.4       11/8/05
- *   o Patch from Jesper Juhl to remove redundant NULL checks for kfree
- * 6.3.2       9/20/05
- *   o Render logic that sets/resets DRV_LOAD as inline functions to 
- *     avoid code replication. If f/w is AMT then set DRV_LOAD only when
- *     network interface is open.
- *   o Handle DRV_LOAD set/reset in cases where AMT uses VLANs.
- *   o Adjust PBA partioning for Jumbo frames using MTU size and not
- *     rx_buffer_len
- * 6.3.1       9/19/05
- *   o Use adapter->tx_timeout_factor in Tx Hung Detect logic 
- *      (e1000_clean_tx_irq)
- *   o Support for 8086:10B5 device (Quad Port)
- */
-
 char e1000_driver_name[] = "e1000";
 static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
 #ifndef CONFIG_E1000_NAPI
@@ -74,9 +36,9 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION "7.0.33-k2"DRIVERNAPI
+#define DRV_VERSION "7.0.38-k4"DRIVERNAPI
 char e1000_driver_version[] = DRV_VERSION;
-static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
  *
@@ -208,8 +170,8 @@ 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_smartspeed(struct e1000_adapter *adapter);
-static inline int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
-                                             struct sk_buff *skb);
+static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
+                                       struct sk_buff *skb);
 
 static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
 static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
@@ -220,12 +182,23 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter);
 static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
 static int e1000_resume(struct pci_dev *pdev);
 #endif
+static void e1000_shutdown(struct pci_dev *pdev);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /* for netdump / net console */
 static void e1000_netpoll (struct net_device *netdev);
 #endif
 
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
+                     pci_channel_state_t state);
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
+static void e1000_io_resume(struct pci_dev *pdev);
+
+static struct pci_error_handlers e1000_err_handler = {
+       .error_detected = e1000_io_error_detected,
+       .slot_reset = e1000_io_slot_reset,
+       .resume = e1000_io_resume,
+};
 
 static struct pci_driver e1000_driver = {
        .name     = e1000_driver_name,
@@ -235,8 +208,10 @@ static struct pci_driver e1000_driver = {
        /* Power Managment Hooks */
 #ifdef CONFIG_PM
        .suspend  = e1000_suspend,
-       .resume   = e1000_resume
+       .resume   = e1000_resume,
 #endif
+       .shutdown = e1000_shutdown,
+       .err_handler = &e1000_err_handler
 };
 
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@@ -291,7 +266,7 @@ module_exit(e1000_exit_module);
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_disable(struct e1000_adapter *adapter)
 {
        atomic_inc(&adapter->irq_sem);
@@ -305,7 +280,7 @@ e1000_irq_disable(struct e1000_adapter *adapter)
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_enable(struct e1000_adapter *adapter)
 {
        if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
@@ -346,10 +321,10 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
  * For ASF and Pass Through versions of f/w this means that the
  * driver is no longer loaded. For AMT version (only with 82573) i
  * of the f/w this means that the netowrk i/f is closed.
- * 
+ *
  **/
 
-static inline void 
+static void
 e1000_release_hw_control(struct e1000_adapter *adapter)
 {
        uint32_t ctrl_ext;
@@ -359,6 +334,7 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
        switch (adapter->hw.mac_type) {
        case e1000_82571:
        case e1000_82572:
+       case e1000_80003es2lan:
                ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
                E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
                                ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
@@ -377,13 +353,13 @@ e1000_release_hw_control(struct e1000_adapter *adapter)
  * @adapter: address of board private structure
  *
  * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit.
- * For ASF and Pass Through versions of f/w this means that 
- * the driver is loaded. For AMT version (only with 82573) 
+ * For ASF and Pass Through versions of f/w this means that
+ * the driver is loaded. For AMT version (only with 82573)
  * of the f/w this means that the netowrk i/f is open.
- * 
+ *
  **/
 
-static inline void 
+static void
 e1000_get_hw_control(struct e1000_adapter *adapter)
 {
        uint32_t ctrl_ext;
@@ -392,6 +368,7 @@ e1000_get_hw_control(struct e1000_adapter *adapter)
        switch (adapter->hw.mac_type) {
        case e1000_82571:
        case e1000_82572:
+       case e1000_80003es2lan:
                ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
                E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
                                ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
@@ -419,7 +396,7 @@ e1000_up(struct e1000_adapter *adapter)
                uint16_t mii_reg;
                e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
                if (mii_reg & MII_CR_POWER_DOWN)
-                       e1000_phy_reset(&adapter->hw);
+                       e1000_phy_hw_reset(&adapter->hw);
        }
 
        e1000_set_multi(netdev);
@@ -709,8 +686,8 @@ e1000_probe(struct pci_dev *pdev,
                DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
 
        /* if ksp3, indicate if it's port a being setup */
-       if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 && 
-                       e1000_ksp3_port_a == 0) 
+       if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 &&
+                       e1000_ksp3_port_a == 0)
                adapter->ksp3_port_a = 1;
        e1000_ksp3_port_a++;
        /* Reset for multiple KP3 adapters */
@@ -738,9 +715,9 @@ e1000_probe(struct pci_dev *pdev,
        if (pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
 
-       /* hard_start_xmit is safe against parallel locking */
-       netdev->features |= NETIF_F_LLTX; 
+       /* hard_start_xmit is safe against parallel locking */
+       netdev->features |= NETIF_F_LLTX;
+
        adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
 
        /* before reading the EEPROM, reset the controller to
@@ -970,8 +947,8 @@ e1000_sw_init(struct e1000_adapter *adapter)
 
        pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
 
-       adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-       adapter->rx_ps_bsize0 = E1000_RXBUFFER_256;
+       adapter->rx_buffer_len = MAXIMUM_ETHERNET_FRAME_SIZE;
+       adapter->rx_ps_bsize0 = E1000_RXBUFFER_128;
        hw->max_frame_size = netdev->mtu +
                             ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
        hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
@@ -1179,7 +1156,7 @@ e1000_close(struct net_device *netdev)
  * @start: address of beginning of memory
  * @len: length of memory
  **/
-static inline boolean_t
+static boolean_t
 e1000_check_64k_bound(struct e1000_adapter *adapter,
                      void *start, unsigned long len)
 {
@@ -1597,14 +1574,21 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
                rctl |= E1000_RCTL_LPE;
 
        /* Setup buffer sizes */
-       if (adapter->hw.mac_type >= e1000_82571) {
-               /* We can now specify buffers in 1K increments.
-                * BSIZE and BSEX are ignored in this case. */
-               rctl |= adapter->rx_buffer_len << 0x11;
-       } else {
-               rctl &= ~E1000_RCTL_SZ_4096;
-               rctl |= E1000_RCTL_BSEX; 
-               switch (adapter->rx_buffer_len) {
+       rctl &= ~E1000_RCTL_SZ_4096;
+       rctl |= E1000_RCTL_BSEX;
+       switch (adapter->rx_buffer_len) {
+               case E1000_RXBUFFER_256:
+                       rctl |= E1000_RCTL_SZ_256;
+                       rctl &= ~E1000_RCTL_BSEX;
+                       break;
+               case E1000_RXBUFFER_512:
+                       rctl |= E1000_RCTL_SZ_512;
+                       rctl &= ~E1000_RCTL_BSEX;
+                       break;
+               case E1000_RXBUFFER_1024:
+                       rctl |= E1000_RCTL_SZ_1024;
+                       rctl &= ~E1000_RCTL_BSEX;
+                       break;
                case E1000_RXBUFFER_2048:
                default:
                        rctl |= E1000_RCTL_SZ_2048;
@@ -1619,7 +1603,6 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
                case E1000_RXBUFFER_16384:
                        rctl |= E1000_RCTL_SZ_16384;
                        break;
-               }
        }
 
 #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
@@ -1713,7 +1696,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
        if (hw->mac_type >= e1000_82571) {
                ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
                /* Reset delay timers after every interrupt */
-               ctrl_ext |= E1000_CTRL_EXT_CANC;
+               ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR;
 #ifdef CONFIG_E1000_NAPI
                /* Auto-Mask interrupts upon ICR read. */
                ctrl_ext |= E1000_CTRL_EXT_IAME;
@@ -1805,7 +1788,7 @@ e1000_free_all_tx_resources(struct e1000_adapter *adapter)
                e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
 }
 
-static inline void
+static void
 e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
                        struct e1000_buffer *buffer_info)
 {
@@ -2245,6 +2228,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
 
        if (link) {
                if (!netif_carrier_ok(netdev)) {
+                       boolean_t txb2b = 1;
                        e1000_get_speed_and_duplex(&adapter->hw,
                                                   &adapter->link_speed,
                                                   &adapter->link_duplex);
@@ -2258,23 +2242,22 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
                         * and adjust the timeout factor */
                        netdev->tx_queue_len = adapter->tx_queue_len;
                        adapter->tx_timeout_factor = 1;
-                       adapter->txb2b = 1;
                        switch (adapter->link_speed) {
                        case SPEED_10:
-                               adapter->txb2b = 0;
+                               txb2b = 0;
                                netdev->tx_queue_len = 10;
                                adapter->tx_timeout_factor = 8;
                                break;
                        case SPEED_100:
-                               adapter->txb2b = 0;
+                               txb2b = 0;
                                netdev->tx_queue_len = 100;
                                /* maybe add some timeout factor ? */
                                break;
                        }
 
-                       if ((adapter->hw.mac_type == e1000_82571 || 
+                       if ((adapter->hw.mac_type == e1000_82571 ||
                             adapter->hw.mac_type == e1000_82572) &&
-                           adapter->txb2b == 0) {
+                           txb2b == 0) {
 #define SPEED_MODE_BIT (1 << 21)
                                uint32_t tarc0;
                                tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
@@ -2398,7 +2381,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
 #define E1000_TX_FLAGS_VLAN_MASK       0xffff0000
 #define E1000_TX_FLAGS_VLAN_SHIFT      16
 
-static inline int
+static int
 e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
           struct sk_buff *skb)
 {
@@ -2420,7 +2403,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
 
                hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
                mss = skb_shinfo(skb)->tso_size;
-               if (skb->protocol == ntohs(ETH_P_IP)) {
+               if (skb->protocol == htons(ETH_P_IP)) {
                        skb->nh.iph->tot_len = 0;
                        skb->nh.iph->check = 0;
                        skb->h.th->check =
@@ -2478,7 +2461,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
        return FALSE;
 }
 
-static inline boolean_t
+static boolean_t
 e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
               struct sk_buff *skb)
 {
@@ -2514,7 +2497,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
 #define E1000_MAX_TXD_PWR      12
 #define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
 
-static inline int
+static int
 e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
              struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
              unsigned int nr_frags, unsigned int mss)
@@ -2623,7 +2606,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
        return count;
 }
 
-static inline void
+static void
 e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
                int tx_flags, int count)
 {
@@ -2687,7 +2670,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
 #define E1000_FIFO_HDR                 0x10
 #define E1000_82547_PAD_LEN            0x3E0
 
-static inline int
+static int
 e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
        uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
@@ -2714,7 +2697,7 @@ no_fifo_stall_required:
 }
 
 #define MINIMUM_DHCP_PACKET_SIZE 282
-static inline int
+static int
 e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
        struct e1000_hw *hw =  &adapter->hw;
@@ -2762,7 +2745,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        unsigned int nr_frags = 0;
        unsigned int mss = 0;
        int count = 0;
-       int tso;
+       int tso;
        unsigned int f;
        len -= skb->data_len;
 
@@ -2775,7 +2758,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
 #ifdef NETIF_F_TSO
        mss = skb_shinfo(skb)->tso_size;
-       /* The controller does a simple calculation to 
+       /* The controller does a simple calculation to
         * make sure there is enough room in the FIFO before
         * initiating the DMA for each buffer.  The calc is:
         * 4 = ceil(buffer len/mss).  To make sure we don't
@@ -2798,7 +2781,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                        case e1000_82573:
                                pull_size = min((unsigned int)4, skb->data_len);
                                if (!__pskb_pull_tail(skb, pull_size)) {
-                                       printk(KERN_ERR 
+                                       printk(KERN_ERR
                                                "__pskb_pull_tail failed.\n");
                                        dev_kfree_skb_any(skb);
                                        return NETDEV_TX_OK;
@@ -2899,7 +2882,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        /* Old method was to assume IPv4 packet by default if TSO was enabled.
         * 82571 hardware supports TSO capabilities for IPv6 as well...
         * no longer assume, we must. */
-       if (likely(skb->protocol == ntohs(ETH_P_IP)))
+       if (likely(skb->protocol == htons(ETH_P_IP)))
                tx_flags |= E1000_TX_FLAGS_IPV4;
 
        e1000_tx_queue(adapter, tx_ring, tx_flags,
@@ -2980,8 +2963,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
 
        /* Adapter-specific max frame size limits. */
        switch (adapter->hw.mac_type) {
-       case e1000_82542_rev2_0:
-       case e1000_82542_rev2_1:
+       case e1000_undefined ... e1000_82542_rev2_1:
                if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
                        DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
                        return -EINVAL;
@@ -3015,27 +2997,32 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
                break;
        }
 
-
-       if (adapter->hw.mac_type > e1000_82547_rev_2) {
-               adapter->rx_buffer_len = max_frame;
-               E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
-       } else {
-               if(unlikely((adapter->hw.mac_type < e1000_82543) &&
-                  (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
-                       DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
-                                           "on 82542\n");
-                       return -EINVAL;
-               } else {
-                       if(max_frame <= E1000_RXBUFFER_2048)
-                               adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-                       else if(max_frame <= E1000_RXBUFFER_4096)
-                               adapter->rx_buffer_len = E1000_RXBUFFER_4096;
-                       else if(max_frame <= E1000_RXBUFFER_8192)
-                               adapter->rx_buffer_len = E1000_RXBUFFER_8192;
-                       else if(max_frame <= E1000_RXBUFFER_16384)
-                               adapter->rx_buffer_len = E1000_RXBUFFER_16384;
-               }
-       }
+       /* NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+        * means we reserve 2 more, this pushes us to allocate from the next
+        * larger slab size
+        * i.e. RXBUFFER_2048 --> size-4096 slab */
+
+       if (max_frame <= E1000_RXBUFFER_256)
+               adapter->rx_buffer_len = E1000_RXBUFFER_256;
+       else if (max_frame <= E1000_RXBUFFER_512)
+               adapter->rx_buffer_len = E1000_RXBUFFER_512;
+       else if (max_frame <= E1000_RXBUFFER_1024)
+               adapter->rx_buffer_len = E1000_RXBUFFER_1024;
+       else if (max_frame <= E1000_RXBUFFER_2048)
+               adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+       else if (max_frame <= E1000_RXBUFFER_4096)
+               adapter->rx_buffer_len = E1000_RXBUFFER_4096;
+       else if (max_frame <= E1000_RXBUFFER_8192)
+               adapter->rx_buffer_len = E1000_RXBUFFER_8192;
+       else if (max_frame <= E1000_RXBUFFER_16384)
+               adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+
+       /* adjust allocation if LPE protects us, and we aren't using SBP */
+#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
+       if (!adapter->hw.tbi_compatibility_on &&
+           ((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) ||
+            (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
+               adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
 
        netdev->mtu = new_mtu;
 
@@ -3058,11 +3045,21 @@ void
 e1000_update_stats(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
+       struct pci_dev *pdev = adapter->pdev;
        unsigned long flags;
        uint16_t phy_tmp;
 
 #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
 
+       /*
+        * Prevent stats update while adapter is being reset, or if the pci
+        * connection is down.
+        */
+       if (adapter->link_speed == 0)
+               return;
+       if (pdev->error_state && pdev->error_state != pci_channel_io_normal)
+               return;
+
        spin_lock_irqsave(&adapter->stats_lock, flags);
 
        /* these counters are modified from e1000_adjust_tbi_stats,
@@ -3163,7 +3160,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
                adapter->stats.crcerrs + adapter->stats.algnerrc +
                adapter->stats.ruc + adapter->stats.roc +
                adapter->stats.cexterr;
-       adapter->net_stats.rx_dropped = 0;
        adapter->net_stats.rx_length_errors = adapter->stats.ruc +
                                              adapter->stats.roc;
        adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
@@ -3389,13 +3385,15 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
 
        tx_ring->next_to_clean = i;
 
-       spin_lock(&tx_ring->tx_lock);
-
+#define TX_WAKE_THRESHOLD 32
        if (unlikely(cleaned && netif_queue_stopped(netdev) &&
-                   netif_carrier_ok(netdev)))
-               netif_wake_queue(netdev);
-
-       spin_unlock(&tx_ring->tx_lock);
+                    netif_carrier_ok(netdev))) {
+               spin_lock(&tx_ring->tx_lock);
+               if (netif_queue_stopped(netdev) &&
+                   (E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))
+                       netif_wake_queue(netdev);
+               spin_unlock(&tx_ring->tx_lock);
+       }
 
        if (adapter->detect_tx_hung) {
                /* Detect a transmit hang in hardware, this serializes the
@@ -3443,7 +3441,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
  * @sk_buff:     socket buffer with received data
  **/
 
-static inline void
+static void
 e1000_rx_checksum(struct e1000_adapter *adapter,
                  uint32_t status_err, uint32_t csum,
                  struct sk_buff *skb)
@@ -3517,7 +3515,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
        buffer_info = &rx_ring->buffer_info[i];
 
        while (rx_desc->status & E1000_RXD_STAT_DD) {
-               struct sk_buff *skb, *next_skb;
+               struct sk_buff *skb;
                u8 status;
 #ifdef CONFIG_E1000_NAPI
                if (*work_done >= work_to_do)
@@ -3535,8 +3533,6 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
                prefetch(next_rxd);
 
                next_buffer = &rx_ring->buffer_info[i];
-               next_skb = next_buffer->skb;
-               prefetch(next_skb->data - NET_IP_ALIGN);
 
                cleaned = TRUE;
                cleaned_count++;
@@ -3567,7 +3563,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
                                                       flags);
                                length--;
                        } else {
-                               dev_kfree_skb_irq(skb);
+                               /* recycle */
+                               buffer_info->skb = skb;
                                goto next_desc;
                        }
                }
@@ -3666,7 +3663,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
        struct e1000_buffer *buffer_info, *next_buffer;
        struct e1000_ps_page *ps_page;
        struct e1000_ps_page_dma *ps_page_dma;
-       struct sk_buff *skb, *next_skb;
+       struct sk_buff *skb;
        unsigned int i, j;
        uint32_t length, staterr;
        int cleaned_count = 0;
@@ -3675,6 +3672,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
        i = rx_ring->next_to_clean;
        rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
        staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+       buffer_info = &rx_ring->buffer_info[i];
 
        while (staterr & E1000_RXD_STAT_DD) {
                buffer_info = &rx_ring->buffer_info[i];
@@ -3695,8 +3693,6 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
                prefetch(next_rxd);
 
                next_buffer = &rx_ring->buffer_info[i];
-               next_skb = next_buffer->skb;
-               prefetch(next_skb->data - NET_IP_ALIGN);
 
                cleaned = TRUE;
                cleaned_count++;
@@ -3735,9 +3731,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
 
                /* page alloc/put takes too long and effects small packet
                 * throughput, so unsplit small packets and save the alloc/put*/
-               if (l1 && ((length + l1) < E1000_CB_LENGTH)) {
+               if (l1 && ((length + l1) <= adapter->rx_ps_bsize0)) {
                        u8 *vaddr;
-                       /* there is no documentation about how to call 
+                       /* there is no documentation about how to call
                         * kmap_atomic, so we can't hold the mapping
                         * very long */
                        pci_dma_sync_single_for_cpu(pdev,
@@ -4157,7 +4153,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
                        spin_unlock_irqrestore(&adapter->stats_lock, flags);
                        return -EIO;
                }
-               if (adapter->hw.phy_type == e1000_media_type_copper) {
+               if (adapter->hw.media_type == e1000_media_type_copper) {
                        switch (data->reg_num) {
                        case PHY_CTRL:
                                if (mii_reg & MII_CR_POWER_DOWN)
@@ -4516,21 +4512,13 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
 
                E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
                E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
-               retval = pci_enable_wake(pdev, PCI_D3hot, 1);
-               if (retval)
-                       DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-               retval = pci_enable_wake(pdev, PCI_D3cold, 1);
-               if (retval)
-                       DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
+               pci_enable_wake(pdev, PCI_D3hot, 1);
+               pci_enable_wake(pdev, PCI_D3cold, 1);
        } else {
                E1000_WRITE_REG(&adapter->hw, WUC, 0);
                E1000_WRITE_REG(&adapter->hw, WUFC, 0);
-               retval = pci_enable_wake(pdev, PCI_D3hot, 0);
-               if (retval)
-                       DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-               retval = pci_enable_wake(pdev, PCI_D3cold, 0);
-               if (retval)
-                       DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
+               pci_enable_wake(pdev, PCI_D3hot, 0);
+               pci_enable_wake(pdev, PCI_D3cold, 0);
        }
 
        if (adapter->hw.mac_type >= e1000_82540 &&
@@ -4539,13 +4527,8 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
                if (manc & E1000_MANC_SMBUS_EN) {
                        manc |= E1000_MANC_ARP_EN;
                        E1000_WRITE_REG(&adapter->hw, MANC, manc);
-                       retval = pci_enable_wake(pdev, PCI_D3hot, 1);
-                       if (retval)
-                               DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-                       retval = pci_enable_wake(pdev, PCI_D3cold, 1);
-                       if (retval)
-                               DPRINTK(PROBE, ERR,
-                                       "Error enabling D3 cold wake\n");
+                       pci_enable_wake(pdev, PCI_D3hot, 1);
+                       pci_enable_wake(pdev, PCI_D3cold, 1);
                }
        }
 
@@ -4555,9 +4538,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
 
        pci_disable_device(pdev);
 
-       retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
-       if (retval)
-               DPRINTK(PROBE, ERR, "Error in setting power state\n");
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
        return 0;
 }
@@ -4568,22 +4549,15 @@ e1000_resume(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
-       int retval;
        uint32_t manc, ret_val;
 
-       retval = pci_set_power_state(pdev, PCI_D0);
-       if (retval)
-               DPRINTK(PROBE, ERR, "Error in setting power state\n");
+       pci_set_power_state(pdev, PCI_D0);
        e1000_pci_restore_state(adapter);
        ret_val = pci_enable_device(pdev);
        pci_set_master(pdev);
 
-       retval = pci_enable_wake(pdev, PCI_D3hot, 0);
-       if (retval)
-               DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-       retval = pci_enable_wake(pdev, PCI_D3cold, 0);
-       if (retval)
-               DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
+       pci_enable_wake(pdev, PCI_D3hot, 0);
+       pci_enable_wake(pdev, PCI_D3cold, 0);
 
        e1000_reset(adapter);
        E1000_WRITE_REG(&adapter->hw, WUS, ~0);
@@ -4611,6 +4585,12 @@ e1000_resume(struct pci_dev *pdev)
        return 0;
 }
 #endif
+
+static void e1000_shutdown(struct pci_dev *pdev)
+{
+       e1000_suspend(pdev, PMSG_SUSPEND);
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /*
  * Polling 'interrupt' - used by things like netconsole to send skbs
@@ -4631,4 +4611,101 @@ e1000_netpoll(struct net_device *netdev)
 }
 #endif
 
+/**
+ * e1000_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci conneection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct e1000_adapter *adapter = netdev->priv;
+
+       netif_device_detach(netdev);
+
+       if (netif_running(netdev))
+               e1000_down(adapter);
+
+       /* Request a slot slot reset. */
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * e1000_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot. Implementation
+ * resembles the first-half of the e1000_resume routine.
+ */
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct e1000_adapter *adapter = netdev->priv;
+
+       if (pci_enable_device(pdev)) {
+               printk(KERN_ERR "e1000: Cannot re-enable PCI device after reset.\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+       pci_set_master(pdev);
+
+       pci_enable_wake(pdev, 3, 0);
+       pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+
+       /* Perform card reset only on one instance of the card */
+       if (PCI_FUNC (pdev->devfn) != 0)
+               return PCI_ERS_RESULT_RECOVERED;
+
+       e1000_reset(adapter);
+       E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+
+       return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * e1000_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation. Implementation resembles the
+ * second-half of the e1000_resume routine.
+ */
+static void e1000_io_resume(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct e1000_adapter *adapter = netdev->priv;
+       uint32_t manc, swsm;
+
+       if (netif_running(netdev)) {
+               if (e1000_up(adapter)) {
+                       printk("e1000: can't bring device back up after reset\n");
+                       return;
+               }
+       }
+
+       netif_device_attach(netdev);
+
+       if (adapter->hw.mac_type >= e1000_82540 &&
+           adapter->hw.media_type == e1000_media_type_copper) {
+               manc = E1000_READ_REG(&adapter->hw, MANC);
+               manc &= ~(E1000_MANC_ARP_EN);
+               E1000_WRITE_REG(&adapter->hw, MANC, manc);
+       }
+
+       switch (adapter->hw.mac_type) {
+       case e1000_82573:
+               swsm = E1000_READ_REG(&adapter->hw, SWSM);
+               E1000_WRITE_REG(&adapter->hw, SWSM,
+                               swsm | E1000_SWSM_DRV_LOAD);
+               break;
+       default:
+               break;
+       }
+
+       if (netif_running(netdev))
+               mod_timer(&adapter->watchdog_timer, jiffies);
+}
+
 /* e1000_main.c */
index 9790db974dc1dcc3ff8f3dfc953727d07c8e14a2..048d052be29d6a6d9a27856e2e3b7af3c142c95a 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
index e0a4d37d1b85db46779a14caeac22dd588b19b43..e55f8969a0fb0ca85f46f43ad2f9708e5bf55622 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
index 2f7b86837fe88d0ee80eef1519a0ec02f25eb40a..8d680ce600d7cb407948d32105d7c3b33d797839 100644 (file)
        http://www.scyld.com/network/epic100.html
 
        ---------------------------------------------------------------------
-       
+
        Linux kernel-specific changes:
-       
+
        LK1.1.2 (jgarzik):
        * Merge becker version 1.09 (4/08/2000)
 
        LK1.1.3:
        * Major bugfix to 1.09 driver (Francis Romieu)
-       
+
        LK1.1.4 (jgarzik):
        * Merge becker test version 1.09 (5/29/2000)
 
@@ -66,7 +66,7 @@
        LK1.1.14 (Kryzsztof Halasa):
        * fix spurious bad initializations
        * pound phy a la SMSC's app note on the subject
-       
+
        AC1.1.14ac
        * fix power up/down for ethtool that broke in 1.11
 
@@ -244,7 +244,7 @@ static struct pci_device_id epic_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE (pci, epic_pci_tbl);
 
-       
+
 #ifndef USE_IO_OPS
 #undef inb
 #undef inw
@@ -370,7 +370,7 @@ static int epic_close(struct net_device *dev);
 static struct net_device_stats *epic_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 
-\f
+
 
 static int __devinit epic_init_one (struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
@@ -392,9 +392,9 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
                printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
                        version, version2, version3);
 #endif
-       
+
        card_idx++;
-       
+
        ret = pci_enable_device(pdev);
        if (ret)
                goto out;
@@ -405,7 +405,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
                ret = -ENODEV;
                goto err_out_disable;
        }
-       
+
        pci_set_master(pdev);
 
        ret = pci_request_regions(pdev, DRV_NAME);
@@ -498,7 +498,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
        ep->pci_dev = pdev;
        ep->chip_id = chip_idx;
        ep->chip_flags = pci_id_tbl[chip_idx].drv_flags;
-       ep->irq_mask = 
+       ep->irq_mask =
                (ep->chip_flags & TYPE2_INTR ?  PCIBusErr175 : PCIBusErr170)
                 | CntFull | TxUnderrun | EpicNapiEvent;
 
@@ -587,7 +587,7 @@ err_out_disable:
        pci_disable_device(pdev);
        goto out;
 }
-\f
+
 /* Serial EEPROM section. */
 
 /*  EEPROM_Ctrl bits. */
@@ -709,7 +709,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
 
        outw(value, ioaddr + MIIData);
        outl((phy_id << 9) | (loc << 4) | MII_WRITEOP, ioaddr + MIICtrl);
-       for (i = 10000; i > 0; i--) { 
+       for (i = 10000; i > 0; i--) {
                barrier();
                if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0)
                        break;
@@ -717,7 +717,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
        return;
 }
 
-\f
+
 static int epic_open(struct net_device *dev)
 {
        struct epic_private *ep = dev->priv;
@@ -760,7 +760,7 @@ static int epic_open(struct net_device *dev)
 #endif
 
        udelay(20); /* Looks like EPII needs that if you want reliable RX init. FIXME: pci posting bug? */
-       
+
        for (i = 0; i < 3; i++)
                outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
 
@@ -803,7 +803,7 @@ static int epic_open(struct net_device *dev)
 
        /* Enable interrupts by setting the interrupt mask. */
        outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-                | CntFull | TxUnderrun 
+                | CntFull | TxUnderrun
                 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
 
        if (debug > 1)
@@ -831,7 +831,7 @@ static void epic_pause(struct net_device *dev)
        struct epic_private *ep = dev->priv;
 
        netif_stop_queue (dev);
-       
+
        /* Disable interrupts by clearing the interrupt mask. */
        outl(0x00000000, ioaddr + INTMASK);
        /* Stop the chip's Tx and Rx DMA processes. */
@@ -987,7 +987,7 @@ static void epic_init_ring(struct net_device *dev)
        for (i = 0; i < RX_RING_SIZE; i++) {
                ep->rx_ring[i].rxstatus = 0;
                ep->rx_ring[i].buflength = cpu_to_le32(ep->rx_buf_sz);
-               ep->rx_ring[i].next = ep->rx_ring_dma + 
+               ep->rx_ring[i].next = ep->rx_ring_dma +
                                      (i+1)*sizeof(struct epic_rx_desc);
                ep->rx_skbuff[i] = NULL;
        }
@@ -1002,7 +1002,7 @@ static void epic_init_ring(struct net_device *dev)
                        break;
                skb->dev = dev;                 /* Mark as being used by this device. */
                skb_reserve(skb, 2);    /* 16 byte align the IP header. */
-               ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev, 
+               ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev,
                        skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
                ep->rx_ring[i].rxstatus = cpu_to_le32(DescOwn);
        }
@@ -1013,7 +1013,7 @@ static void epic_init_ring(struct net_device *dev)
        for (i = 0; i < TX_RING_SIZE; i++) {
                ep->tx_skbuff[i] = NULL;
                ep->tx_ring[i].txstatus = 0x0000;
-               ep->tx_ring[i].next = ep->tx_ring_dma + 
+               ep->tx_ring[i].next = ep->tx_ring_dma +
                        (i+1)*sizeof(struct epic_tx_desc);
        }
        ep->tx_ring[i-1].next = ep->tx_ring_dma;
@@ -1026,7 +1026,7 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
        int entry, free_count;
        u32 ctrl_word;
        unsigned long flags;
-       
+
        if (skb->len < ETH_ZLEN) {
                skb = skb_padto(skb, ETH_ZLEN);
                if (skb == NULL)
@@ -1042,7 +1042,7 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
        entry = ep->cur_tx % TX_RING_SIZE;
 
        ep->tx_skbuff[entry] = skb;
-       ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data, 
+       ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data,
                                                    skb->len, PCI_DMA_TODEVICE);
        if (free_count < TX_QUEUE_LEN/2) {/* Typical path */
                ctrl_word = cpu_to_le32(0x100000); /* No interrupt */
@@ -1126,7 +1126,7 @@ static void epic_tx(struct net_device *dev, struct epic_private *ep)
 
                /* Free the original skb. */
                skb = ep->tx_skbuff[entry];
-               pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, 
+               pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr,
                                 skb->len, PCI_DMA_TODEVICE);
                dev_kfree_skb_irq(skb);
                ep->tx_skbuff[entry] = NULL;
@@ -1281,8 +1281,8 @@ static int epic_rx(struct net_device *dev, int budget)
                                                               ep->rx_buf_sz,
                                                               PCI_DMA_FROMDEVICE);
                        } else {
-                               pci_unmap_single(ep->pci_dev, 
-                                       ep->rx_ring[entry].bufaddr, 
+                               pci_unmap_single(ep->pci_dev,
+                                       ep->rx_ring[entry].bufaddr,
                                        ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
                                skb_put(skb = ep->rx_skbuff[entry], pkt_len);
                                ep->rx_skbuff[entry] = NULL;
@@ -1307,7 +1307,7 @@ static int epic_rx(struct net_device *dev, int budget)
                                break;
                        skb->dev = dev;                 /* Mark as being used by this device. */
                        skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
-                       ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, 
+                       ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev,
                                skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
                        work_done++;
                }
@@ -1403,7 +1403,7 @@ static int epic_close(struct net_device *dev)
                ep->rx_ring[i].rxstatus = 0;            /* Not owned by Epic chip. */
                ep->rx_ring[i].buflength = 0;
                if (skb) {
-                       pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr, 
+                       pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr,
                                         ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
                        dev_kfree_skb(skb);
                }
@@ -1414,7 +1414,7 @@ static int epic_close(struct net_device *dev)
                ep->tx_skbuff[i] = NULL;
                if (!skb)
                        continue;
-               pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr, 
+               pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr,
                                 skb->len, PCI_DMA_TODEVICE);
                dev_kfree_skb(skb);
        }
@@ -1607,7 +1607,7 @@ static void __devexit epic_remove_one (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct epic_private *ep = dev->priv;
-       
+
        pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
        pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);
        unregister_netdev(dev);
index 705e1229d89db994aa0db6e0d11a0653e19b9a84..04a53f1dfdbdb8d58b8f61767457be0b000bbc4e 100644 (file)
  *     0.52: 20 Jan 2006: Add MSI/MSIX support.
  *     0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
  *     0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
+ *     0.55: 22 Mar 2006: Add flow control (pause frame).
+ *     0.56: 22 Mar 2006: Additional ethtool config and moduleparam support.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION              "0.54"
+#define FORCEDETH_VERSION              "0.56"
 #define DRV_NAME                       "forcedeth"
 
 #include <linux/module.h>
 #define DEV_HAS_MSI             0x0040  /* device supports MSI */
 #define DEV_HAS_MSI_X           0x0080  /* device supports MSI-X */
 #define DEV_HAS_POWER_CNTRL     0x0100  /* device supports power savings */
+#define DEV_HAS_PAUSEFRAME_TX   0x0200  /* device supports tx pause frames */
+#define DEV_HAS_STATISTICS      0x0400  /* device supports hw statistics */
+#define DEV_HAS_TEST_EXTENDED   0x0800  /* device supports extended diagnostic test */
 
 enum {
        NvRegIrqStatus = 0x000,
@@ -203,6 +208,7 @@ enum {
        NvRegMSIIrqMask = 0x030,
 #define NVREG_MSI_VECTOR_0_ENABLED 0x01
        NvRegMisc1 = 0x080,
+#define NVREG_MISC1_PAUSE_TX   0x01
 #define NVREG_MISC1_HD         0x02
 #define NVREG_MISC1_FORCE      0x3b0f3c
 
@@ -214,9 +220,11 @@ enum {
 #define NVREG_XMITSTAT_BUSY    0x01
 
        NvRegPacketFilterFlags = 0x8c,
-#define NVREG_PFF_ALWAYS       0x7F0008
+#define NVREG_PFF_PAUSE_RX     0x08
+#define NVREG_PFF_ALWAYS       0x7F0000
 #define NVREG_PFF_PROMISC      0x80
 #define NVREG_PFF_MYADDR       0x20
+#define NVREG_PFF_LOOPBACK     0x10
 
        NvRegOffloadConfig = 0x90,
 #define NVREG_OFFLOAD_HOMEPHY  0x601
@@ -277,6 +285,9 @@ enum {
 #define NVREG_TXRXCTL_VLANINS  0x00080
        NvRegTxRingPhysAddrHigh = 0x148,
        NvRegRxRingPhysAddrHigh = 0x14C,
+       NvRegTxPauseFrame = 0x170,
+#define NVREG_TX_PAUSEFRAME_DISABLE    0x1ff0080
+#define NVREG_TX_PAUSEFRAME_ENABLE     0x0c00030
        NvRegMIIStatus = 0x180,
 #define NVREG_MIISTAT_ERROR            0x0001
 #define NVREG_MIISTAT_LINKCHANGE       0x0008
@@ -326,6 +337,33 @@ enum {
 #define NVREG_POWERSTATE_D1            0x0001
 #define NVREG_POWERSTATE_D2            0x0002
 #define NVREG_POWERSTATE_D3            0x0003
+       NvRegTxCnt = 0x280,
+       NvRegTxZeroReXmt = 0x284,
+       NvRegTxOneReXmt = 0x288,
+       NvRegTxManyReXmt = 0x28c,
+       NvRegTxLateCol = 0x290,
+       NvRegTxUnderflow = 0x294,
+       NvRegTxLossCarrier = 0x298,
+       NvRegTxExcessDef = 0x29c,
+       NvRegTxRetryErr = 0x2a0,
+       NvRegRxFrameErr = 0x2a4,
+       NvRegRxExtraByte = 0x2a8,
+       NvRegRxLateCol = 0x2ac,
+       NvRegRxRunt = 0x2b0,
+       NvRegRxFrameTooLong = 0x2b4,
+       NvRegRxOverflow = 0x2b8,
+       NvRegRxFCSErr = 0x2bc,
+       NvRegRxFrameAlignErr = 0x2c0,
+       NvRegRxLenErr = 0x2c4,
+       NvRegRxUnicast = 0x2c8,
+       NvRegRxMulticast = 0x2cc,
+       NvRegRxBroadcast = 0x2d0,
+       NvRegTxDef = 0x2d4,
+       NvRegTxFrame = 0x2d8,
+       NvRegRxCnt = 0x2dc,
+       NvRegTxPause = 0x2e0,
+       NvRegRxPause = 0x2e4,
+       NvRegRxDropFrame = 0x2e8,
        NvRegVlanControl = 0x300,
 #define NVREG_VLANCONTROL_ENABLE       0x2000
        NvRegMSIXMap0 = 0x3e0,
@@ -449,16 +487,18 @@ typedef union _ring_type {
 /* General driver defaults */
 #define NV_WATCHDOG_TIMEO      (5*HZ)
 
-#define RX_RING                128
-#define TX_RING                256
-/* 
- * If your nic mysteriously hangs then try to reduce the limits
- * to 1/0: It might be required to set NV_TX_LASTPACKET in the
- * last valid ring entry. But this would be impossible to
- * implement - probably a disassembly error.
+#define RX_RING_DEFAULT                128
+#define TX_RING_DEFAULT                256
+#define RX_RING_MIN            128
+#define TX_RING_MIN            64
+#define RING_MAX_DESC_VER_1    1024
+#define RING_MAX_DESC_VER_2_3  16384
+/*
+ * Difference between the get and put pointers for the tx ring.
+ * This is used to throttle the amount of data outstanding in the
+ * tx ring.
  */
-#define TX_LIMIT_STOP  255
-#define TX_LIMIT_START 254
+#define TX_LIMIT_DIFFERENCE    1
 
 /* rx/tx mac addr + type + vlan + align + slack*/
 #define NV_RX_HEADERS          (64)
@@ -472,8 +512,9 @@ typedef union _ring_type {
 #define OOM_REFILL     (1+HZ/20)
 #define POLL_WAIT      (1+HZ/100)
 #define LINK_TIMEOUT   (3*HZ)
+#define STATS_INTERVAL (10*HZ)
 
-/* 
+/*
  * desc_ver values:
  * The nic supports three different descriptor types:
  * - DESC_VER_1: Original
@@ -506,13 +547,13 @@ typedef union _ring_type {
 #define PHY_1000       0x2
 #define PHY_HALF       0x100
 
-/* FIXME: MII defines that should be added to <linux/mii.h> */
-#define MII_1000BT_CR  0x09
-#define MII_1000BT_SR  0x0a
-#define ADVERTISE_1000FULL     0x0200
-#define ADVERTISE_1000HALF     0x0100
-#define LPA_1000FULL   0x0800
-#define LPA_1000HALF   0x0400
+#define NV_PAUSEFRAME_RX_CAPABLE 0x0001
+#define NV_PAUSEFRAME_TX_CAPABLE 0x0002
+#define NV_PAUSEFRAME_RX_ENABLE  0x0004
+#define NV_PAUSEFRAME_TX_ENABLE  0x0008
+#define NV_PAUSEFRAME_RX_REQ     0x0010
+#define NV_PAUSEFRAME_TX_REQ     0x0020
+#define NV_PAUSEFRAME_AUTONEG    0x0040
 
 /* MSI/MSI-X defines */
 #define NV_MSI_X_MAX_VECTORS  8
@@ -527,15 +568,110 @@ typedef union _ring_type {
 #define NV_MSI_X_VECTOR_TX    0x1
 #define NV_MSI_X_VECTOR_OTHER 0x2
 
+/* statistics */
+struct nv_ethtool_str {
+       char name[ETH_GSTRING_LEN];
+};
+
+static const struct nv_ethtool_str nv_estats_str[] = {
+       { "tx_bytes" },
+       { "tx_zero_rexmt" },
+       { "tx_one_rexmt" },
+       { "tx_many_rexmt" },
+       { "tx_late_collision" },
+       { "tx_fifo_errors" },
+       { "tx_carrier_errors" },
+       { "tx_excess_deferral" },
+       { "tx_retry_error" },
+       { "tx_deferral" },
+       { "tx_packets" },
+       { "tx_pause" },
+       { "rx_frame_error" },
+       { "rx_extra_byte" },
+       { "rx_late_collision" },
+       { "rx_runt" },
+       { "rx_frame_too_long" },
+       { "rx_over_errors" },
+       { "rx_crc_errors" },
+       { "rx_frame_align_error" },
+       { "rx_length_error" },
+       { "rx_unicast" },
+       { "rx_multicast" },
+       { "rx_broadcast" },
+       { "rx_bytes" },
+       { "rx_pause" },
+       { "rx_drop_frame" },
+       { "rx_packets" },
+       { "rx_errors_total" }
+};
+
+struct nv_ethtool_stats {
+       u64 tx_bytes;
+       u64 tx_zero_rexmt;
+       u64 tx_one_rexmt;
+       u64 tx_many_rexmt;
+       u64 tx_late_collision;
+       u64 tx_fifo_errors;
+       u64 tx_carrier_errors;
+       u64 tx_excess_deferral;
+       u64 tx_retry_error;
+       u64 tx_deferral;
+       u64 tx_packets;
+       u64 tx_pause;
+       u64 rx_frame_error;
+       u64 rx_extra_byte;
+       u64 rx_late_collision;
+       u64 rx_runt;
+       u64 rx_frame_too_long;
+       u64 rx_over_errors;
+       u64 rx_crc_errors;
+       u64 rx_frame_align_error;
+       u64 rx_length_error;
+       u64 rx_unicast;
+       u64 rx_multicast;
+       u64 rx_broadcast;
+       u64 rx_bytes;
+       u64 rx_pause;
+       u64 rx_drop_frame;
+       u64 rx_packets;
+       u64 rx_errors_total;
+};
+
+/* diagnostics */
+#define NV_TEST_COUNT_BASE 3
+#define NV_TEST_COUNT_EXTENDED 4
+
+static const struct nv_ethtool_str nv_etests_str[] = {
+       { "link      (online/offline)" },
+       { "register  (offline)       " },
+       { "interrupt (offline)       " },
+       { "loopback  (offline)       " }
+};
+
+struct register_test {
+       u32 reg;
+       u32 mask;
+};
+
+static const struct register_test nv_registers_test[] = {
+       { NvRegUnknownSetupReg6, 0x01 },
+       { NvRegMisc1, 0x03c },
+       { NvRegOffloadConfig, 0x03ff },
+       { NvRegMulticastAddrA, 0xffffffff },
+       { NvRegUnknownSetupReg3, 0x0ff },
+       { NvRegWakeUpFlags, 0x07777 },
+       { 0,0 }
+};
+
 /*
  * SMP locking:
  * All hardware access under dev->priv->lock, except the performance
  * critical parts:
  * - rx is (pseudo-) lockless: it relies on the single-threading provided
  *     by the arch code for interrupts.
- * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission
+ * - tx setup is lockless: it relies on netif_tx_lock. Actual submission
  *     needs dev->priv->lock :-(
- * - set_multicast_list: preparation lockless, relies on dev->xmit_lock.
+ * - set_multicast_list: preparation lockless, relies on netif_tx_lock.
  */
 
 /* in dev: base, irq */
@@ -545,6 +681,7 @@ struct fe_priv {
        /* General data:
         * Locking: spin_lock(&np->lock); */
        struct net_device_stats stats;
+       struct nv_ethtool_stats estats;
        int in_shutdown;
        u32 linkspeed;
        int duplex;
@@ -554,6 +691,7 @@ struct fe_priv {
        int wolenabled;
        unsigned int phy_oui;
        u16 gigabit;
+       int intr_test;
 
        /* General data: RO fields */
        dma_addr_t ring_addr;
@@ -573,13 +711,15 @@ struct fe_priv {
         */
        ring_type rx_ring;
        unsigned int cur_rx, refill_rx;
-       struct sk_buff *rx_skbuff[RX_RING];
-       dma_addr_t rx_dma[RX_RING];
+       struct sk_buff **rx_skbuff;
+       dma_addr_t *rx_dma;
        unsigned int rx_buf_sz;
        unsigned int pkt_limit;
        struct timer_list oom_kick;
        struct timer_list nic_poll;
+       struct timer_list stats_poll;
        u32 nic_poll_irq;
+       int rx_ring_size;
 
        /* media detection workaround.
         * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
@@ -591,10 +731,13 @@ struct fe_priv {
         */
        ring_type tx_ring;
        unsigned int next_tx, nic_tx;
-       struct sk_buff *tx_skbuff[TX_RING];
-       dma_addr_t tx_dma[TX_RING];
-       unsigned int tx_dma_len[TX_RING];
+       struct sk_buff **tx_skbuff;
+       dma_addr_t *tx_dma;
+       unsigned int *tx_dma_len;
        u32 tx_flags;
+       int tx_ring_size;
+       int tx_limit_start;
+       int tx_limit_stop;
 
        /* vlan fields */
        struct vlan_group *vlangrp;
@@ -602,6 +745,9 @@ struct fe_priv {
        /* msi/msi-x fields */
        u32 msi_flags;
        struct msix_entry msi_x_entry[NV_MSI_X_MAX_VECTORS];
+
+       /* flow control */
+       u32 pause_flags;
 };
 
 /*
@@ -612,12 +758,14 @@ static int max_interrupt_work = 5;
 
 /*
  * Optimization can be either throuput mode or cpu mode
- * 
+ *
  * Throughput Mode: Every tx and rx packet will generate an interrupt.
  * CPU Mode: Interrupts are controlled by a timer.
  */
-#define NV_OPTIMIZATION_MODE_THROUGHPUT 0
-#define NV_OPTIMIZATION_MODE_CPU        1
+enum {
+       NV_OPTIMIZATION_MODE_THROUGHPUT,
+       NV_OPTIMIZATION_MODE_CPU
+};
 static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT;
 
 /*
@@ -630,14 +778,31 @@ static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT;
 static int poll_interval = -1;
 
 /*
- * Disable MSI interrupts
+ * MSI interrupts
+ */
+enum {
+       NV_MSI_INT_DISABLED,
+       NV_MSI_INT_ENABLED
+};
+static int msi = NV_MSI_INT_ENABLED;
+
+/*
+ * MSIX interrupts
  */
-static int disable_msi = 0;
+enum {
+       NV_MSIX_INT_DISABLED,
+       NV_MSIX_INT_ENABLED
+};
+static int msix = NV_MSIX_INT_ENABLED;
 
 /*
- * Disable MSIX interrupts
+ * DMA 64bit
  */
-static int disable_msix = 0;
+enum {
+       NV_DMA_64BIT_DISABLED,
+       NV_DMA_64BIT_ENABLED
+};
+static int dma_64bit = NV_DMA_64BIT_ENABLED;
 
 static inline struct fe_priv *get_nvpriv(struct net_device *dev)
 {
@@ -697,7 +862,7 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
                        writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr);
                }
                if (rxtx_flags & NV_SETUP_TX_RING) {
-                       writel((u32) cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+                       writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
                }
        } else {
                if (rxtx_flags & NV_SETUP_RX_RING) {
@@ -705,12 +870,37 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
                        writel((u32) (cpu_to_le64(np->ring_addr) >> 32), base + NvRegRxRingPhysAddrHigh);
                }
                if (rxtx_flags & NV_SETUP_TX_RING) {
-                       writel((u32) cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
-                       writel((u32) (cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh);
+                       writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
+                       writel((u32) (cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh);
                }
        }
 }
 
+static void free_rings(struct net_device *dev)
+{
+       struct fe_priv *np = get_nvpriv(dev);
+
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+               if(np->rx_ring.orig)
+                       pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),
+                                           np->rx_ring.orig, np->ring_addr);
+       } else {
+               if (np->rx_ring.ex)
+                       pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (np->rx_ring_size + np->tx_ring_size),
+                                           np->rx_ring.ex, np->ring_addr);
+       }
+       if (np->rx_skbuff)
+               kfree(np->rx_skbuff);
+       if (np->rx_dma)
+               kfree(np->rx_dma);
+       if (np->tx_skbuff)
+               kfree(np->tx_skbuff);
+       if (np->tx_dma)
+               kfree(np->tx_dma);
+       if (np->tx_dma_len)
+               kfree(np->tx_dma_len);
+}
+
 static int using_multi_irqs(struct net_device *dev)
 {
        struct fe_priv *np = get_nvpriv(dev);
@@ -860,7 +1050,7 @@ static int phy_init(struct net_device *dev)
 
        /* set advertise register */
        reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-       reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|0x800|0x400);
+       reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP);
        if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) {
                printk(KERN_INFO "%s: phy write to advertise failed.\n", pci_name(np->pci_dev));
                return PHY_ERROR;
@@ -873,14 +1063,14 @@ static int phy_init(struct net_device *dev)
        mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
        if (mii_status & PHY_GIGABIT) {
                np->gigabit = PHY_GIGABIT;
-               mii_control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+               mii_control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
                mii_control_1000 &= ~ADVERTISE_1000HALF;
                if (phyinterface & PHY_RGMII)
                        mii_control_1000 |= ADVERTISE_1000FULL;
                else
                        mii_control_1000 &= ~ADVERTISE_1000FULL;
 
-               if (mii_rw(dev, np->phyaddr, MII_1000BT_CR, mii_control_1000)) {
+               if (mii_rw(dev, np->phyaddr, MII_CTRL1000, mii_control_1000)) {
                        printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
                        return PHY_ERROR;
                }
@@ -918,6 +1108,8 @@ static int phy_init(struct net_device *dev)
                        return PHY_ERROR;
                }
        }
+       /* some phys clear out pause advertisment on reset, set it back */
+       mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
 
        /* restart auto negotiation */
        mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
@@ -1047,7 +1239,7 @@ static int nv_alloc_rx(struct net_device *dev)
        while (np->cur_rx != refill_rx) {
                struct sk_buff *skb;
 
-               nr = refill_rx % RX_RING;
+               nr = refill_rx % np->rx_ring_size;
                if (np->rx_skbuff[nr] == NULL) {
 
                        skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD);
@@ -1076,7 +1268,7 @@ static int nv_alloc_rx(struct net_device *dev)
                refill_rx++;
        }
        np->refill_rx = refill_rx;
-       if (np->cur_rx - refill_rx == RX_RING)
+       if (np->cur_rx - refill_rx == np->rx_ring_size)
                return 1;
        return 0;
 }
@@ -1110,14 +1302,14 @@ static void nv_do_rx_refill(unsigned long data)
        }
 }
 
-static void nv_init_rx(struct net_device *dev) 
+static void nv_init_rx(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        int i;
 
-       np->cur_rx = RX_RING;
+       np->cur_rx = np->rx_ring_size;
        np->refill_rx = 0;
-       for (i = 0; i < RX_RING; i++)
+       for (i = 0; i < np->rx_ring_size; i++)
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
                        np->rx_ring.orig[i].FlagLen = 0;
                else
@@ -1130,7 +1322,7 @@ static void nv_init_tx(struct net_device *dev)
        int i;
 
        np->next_tx = np->nic_tx = 0;
-       for (i = 0; i < TX_RING; i++) {
+       for (i = 0; i < np->tx_ring_size; i++) {
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
                        np->tx_ring.orig[i].FlagLen = 0;
                else
@@ -1174,8 +1366,8 @@ static void nv_drain_tx(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        unsigned int i;
-       
-       for (i = 0; i < TX_RING; i++) {
+
+       for (i = 0; i < np->tx_ring_size; i++) {
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
                        np->tx_ring.orig[i].FlagLen = 0;
                else
@@ -1189,7 +1381,7 @@ static void nv_drain_rx(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        int i;
-       for (i = 0; i < RX_RING; i++) {
+       for (i = 0; i < np->rx_ring_size; i++) {
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
                        np->rx_ring.orig[i].FlagLen = 0;
                else
@@ -1213,7 +1405,7 @@ static void drain_ring(struct net_device *dev)
 
 /*
  * nv_start_xmit: dev->hard_start_xmit function
- * Called with dev->xmit_lock held.
+ * Called with netif_tx_lock held.
  */
 static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
@@ -1221,8 +1413,8 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
        u32 tx_flags = 0;
        u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
        unsigned int fragments = skb_shinfo(skb)->nr_frags;
-       unsigned int nr = (np->next_tx - 1) % TX_RING;
-       unsigned int start_nr = np->next_tx % TX_RING;
+       unsigned int nr = (np->next_tx - 1) % np->tx_ring_size;
+       unsigned int start_nr = np->next_tx % np->tx_ring_size;
        unsigned int i;
        u32 offset = 0;
        u32 bcnt;
@@ -1238,7 +1430,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        spin_lock_irq(&np->lock);
 
-       if ((np->next_tx - np->nic_tx + entries - 1) > TX_LIMIT_STOP) {
+       if ((np->next_tx - np->nic_tx + entries - 1) > np->tx_limit_stop) {
                spin_unlock_irq(&np->lock);
                netif_stop_queue(dev);
                return NETDEV_TX_BUSY;
@@ -1247,7 +1439,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* setup the header buffer */
        do {
                bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
-               nr = (nr + 1) % TX_RING;
+               nr = (nr + 1) % np->tx_ring_size;
 
                np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
                                                PCI_DMA_TODEVICE);
@@ -1274,7 +1466,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                do {
                        bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
-                       nr = (nr + 1) % TX_RING;
+                       nr = (nr + 1) % np->tx_ring_size;
 
                        np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
                                                      PCI_DMA_TODEVICE);
@@ -1320,7 +1512,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
        } else {
                np->tx_ring.ex[start_nr].TxVlan = cpu_to_le32(tx_flags_vlan);
                np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
-       }       
+       }
 
        dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n",
                dev->name, np->next_tx, entries, tx_flags_extra);
@@ -1356,7 +1548,7 @@ static void nv_tx_done(struct net_device *dev)
        struct sk_buff *skb;
 
        while (np->nic_tx != np->next_tx) {
-               i = np->nic_tx % TX_RING;
+               i = np->nic_tx % np->tx_ring_size;
 
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
                        Flags = le32_to_cpu(np->tx_ring.orig[i].FlagLen);
@@ -1395,19 +1587,19 @@ static void nv_tx_done(struct net_device *dev)
                                } else {
                                        np->stats.tx_packets++;
                                        np->stats.tx_bytes += skb->len;
-                               }                               
+                               }
                        }
                }
                nv_release_txskb(dev, i);
                np->nic_tx++;
        }
-       if (np->next_tx - np->nic_tx < TX_LIMIT_START)
+       if (np->next_tx - np->nic_tx < np->tx_limit_start)
                netif_wake_queue(dev);
 }
 
 /*
  * nv_tx_timeout: dev->tx_timeout function
- * Called with dev->xmit_lock held.
+ * Called with netif_tx_lock held.
  */
 static void nv_tx_timeout(struct net_device *dev)
 {
@@ -1438,10 +1630,10 @@ static void nv_tx_timeout(struct net_device *dev)
                                        readl(base + i + 24), readl(base + i + 28));
                }
                printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
-               for (i=0;i<TX_RING;i+= 4) {
+               for (i=0;i<np->tx_ring_size;i+= 4) {
                        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
                                printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
-                                      i, 
+                                      i,
                                       le32_to_cpu(np->tx_ring.orig[i].PacketBuffer),
                                       le32_to_cpu(np->tx_ring.orig[i].FlagLen),
                                       le32_to_cpu(np->tx_ring.orig[i+1].PacketBuffer),
@@ -1452,7 +1644,7 @@ static void nv_tx_timeout(struct net_device *dev)
                                       le32_to_cpu(np->tx_ring.orig[i+3].FlagLen));
                        } else {
                                printk(KERN_INFO "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n",
-                                      i, 
+                                      i,
                                       le32_to_cpu(np->tx_ring.ex[i].PacketBufferHigh),
                                       le32_to_cpu(np->tx_ring.ex[i].PacketBufferLow),
                                       le32_to_cpu(np->tx_ring.ex[i].FlagLen),
@@ -1550,15 +1742,14 @@ static void nv_rx_process(struct net_device *dev)
        u32 Flags;
        u32 vlanflags = 0;
 
-
        for (;;) {
                struct sk_buff *skb;
                int len;
                int i;
-               if (np->cur_rx - np->refill_rx >= RX_RING)
+               if (np->cur_rx - np->refill_rx >= np->rx_ring_size)
                        break;  /* we scanned the whole ring - do not continue */
 
-               i = np->cur_rx % RX_RING;
+               i = np->cur_rx % np->rx_ring_size;
                if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
                        Flags = le32_to_cpu(np->rx_ring.orig[i].FlagLen);
                        len = nv_descr_getlength(&np->rx_ring.orig[i], np->desc_ver);
@@ -1665,14 +1856,16 @@ static void nv_rx_process(struct net_device *dev)
                                        }
                                }
                        }
-                       Flags &= NV_RX2_CHECKSUMMASK;
-                       if (Flags == NV_RX2_CHECKSUMOK1 ||
-                                       Flags == NV_RX2_CHECKSUMOK2 ||
-                                       Flags == NV_RX2_CHECKSUMOK3) {
-                               dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name);
-                               np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY;
-                       } else {
-                               dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name);
+                       if (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) {
+                               Flags &= NV_RX2_CHECKSUMMASK;
+                               if (Flags == NV_RX2_CHECKSUMOK1 ||
+                                   Flags == NV_RX2_CHECKSUMOK2 ||
+                                   Flags == NV_RX2_CHECKSUMOK3) {
+                                       dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name);
+                                       np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY;
+                               } else {
+                                       dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name);
+                               }
                        }
                }
                /* got a valid packet - forward it to the network core */
@@ -1737,7 +1930,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
                 * Changing the MTU is a rare event, it shouldn't matter.
                 */
                nv_disable_irq(dev);
-               spin_lock_bh(&dev->xmit_lock);
+               netif_tx_lock_bh(dev);
                spin_lock(&np->lock);
                /* stop engines */
                nv_stop_rx(dev);
@@ -1747,18 +1940,15 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
                nv_drain_rx(dev);
                nv_drain_tx(dev);
                /* reinit driver view of the rx queue */
-               nv_init_rx(dev);
-               nv_init_tx(dev);
-               /* alloc new rx buffers */
                set_bufsize(dev);
-               if (nv_alloc_rx(dev)) {
+               if (nv_init_ring(dev)) {
                        if (!np->in_shutdown)
                                mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
                }
                /* reinit nic view of the rx queue */
                writel(np->rx_buf_sz, base + NvRegOffloadConfig);
                setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
-               writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
+               writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
                        base + NvRegRingSizes);
                pci_push(base);
                writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
@@ -1768,7 +1958,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
                nv_start_rx(dev);
                nv_start_tx(dev);
                spin_unlock(&np->lock);
-               spin_unlock_bh(&dev->xmit_lock);
+               netif_tx_unlock_bh(dev);
                nv_enable_irq(dev);
        }
        return 0;
@@ -1803,7 +1993,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
        memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
 
        if (netif_running(dev)) {
-               spin_lock_bh(&dev->xmit_lock);
+               netif_tx_lock_bh(dev);
                spin_lock_irq(&np->lock);
 
                /* stop rx engine */
@@ -1815,7 +2005,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
                /* restart rx engine */
                nv_start_rx(dev);
                spin_unlock_irq(&np->lock);
-               spin_unlock_bh(&dev->xmit_lock);
+               netif_tx_unlock_bh(dev);
        } else {
                nv_copy_mac_to_hw(dev);
        }
@@ -1824,7 +2014,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
 
 /*
  * nv_set_multicast: dev->set_multicast function
- * Called with dev->xmit_lock held.
+ * Called with netif_tx_lock held.
  */
 static void nv_set_multicast(struct net_device *dev)
 {
@@ -1832,16 +2022,16 @@ static void nv_set_multicast(struct net_device *dev)
        u8 __iomem *base = get_hwbase(dev);
        u32 addr[2];
        u32 mask[2];
-       u32 pff;
+       u32 pff = readl(base + NvRegPacketFilterFlags) & NVREG_PFF_PAUSE_RX;
 
        memset(addr, 0, sizeof(addr));
        memset(mask, 0, sizeof(mask));
 
        if (dev->flags & IFF_PROMISC) {
                printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
-               pff = NVREG_PFF_PROMISC;
+               pff |= NVREG_PFF_PROMISC;
        } else {
-               pff = NVREG_PFF_MYADDR;
+               pff |= NVREG_PFF_MYADDR;
 
                if (dev->flags & IFF_ALLMULTI || dev->mc_list) {
                        u32 alwaysOff[2];
@@ -1886,6 +2076,35 @@ static void nv_set_multicast(struct net_device *dev)
        spin_unlock_irq(&np->lock);
 }
 
+void nv_update_pause(struct net_device *dev, u32 pause_flags)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+
+       np->pause_flags &= ~(NV_PAUSEFRAME_TX_ENABLE | NV_PAUSEFRAME_RX_ENABLE);
+
+       if (np->pause_flags & NV_PAUSEFRAME_RX_CAPABLE) {
+               u32 pff = readl(base + NvRegPacketFilterFlags) & ~NVREG_PFF_PAUSE_RX;
+               if (pause_flags & NV_PAUSEFRAME_RX_ENABLE) {
+                       writel(pff|NVREG_PFF_PAUSE_RX, base + NvRegPacketFilterFlags);
+                       np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+               } else {
+                       writel(pff, base + NvRegPacketFilterFlags);
+               }
+       }
+       if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE) {
+               u32 regmisc = readl(base + NvRegMisc1) & ~NVREG_MISC1_PAUSE_TX;
+               if (pause_flags & NV_PAUSEFRAME_TX_ENABLE) {
+                       writel(NVREG_TX_PAUSEFRAME_ENABLE,  base + NvRegTxPauseFrame);
+                       writel(regmisc|NVREG_MISC1_PAUSE_TX, base + NvRegMisc1);
+                       np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+               } else {
+                       writel(NVREG_TX_PAUSEFRAME_DISABLE,  base + NvRegTxPauseFrame);
+                       writel(regmisc, base + NvRegMisc1);
+               }
+       }
+}
+
 /**
  * nv_update_linkspeed: Setup the MAC according to the link partner
  * @dev: Network device to be configured
@@ -1901,12 +2120,14 @@ static int nv_update_linkspeed(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
-       int adv, lpa;
+       int adv = 0;
+       int lpa = 0;
+       int adv_lpa, adv_pause, lpa_pause;
        int newls = np->linkspeed;
        int newdup = np->duplex;
        int mii_status;
        int retval = 0;
-       u32 control_1000, status_1000, phyreg;
+       u32 control_1000, status_1000, phyreg, pause_flags;
 
        /* BMSR_LSTATUS is latched, read it twice:
         * we want the current value.
@@ -1952,10 +2173,15 @@ static int nv_update_linkspeed(struct net_device *dev)
                goto set_speed;
        }
 
+       adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
+       lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ);
+       dprintk(KERN_DEBUG "%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n",
+                               dev->name, adv, lpa);
+
        retval = 1;
        if (np->gigabit == PHY_GIGABIT) {
-               control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
-               status_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_SR, MII_READ);
+               control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
+               status_1000 = mii_rw(dev, np->phyaddr, MII_STAT1000, MII_READ);
 
                if ((control_1000 & ADVERTISE_1000FULL) &&
                        (status_1000 & LPA_1000FULL)) {
@@ -1967,27 +2193,22 @@ static int nv_update_linkspeed(struct net_device *dev)
                }
        }
 
-       adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-       lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ);
-       dprintk(KERN_DEBUG "%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n",
-                               dev->name, adv, lpa);
-
        /* FIXME: handle parallel detection properly */
-       lpa = lpa & adv;
-       if (lpa & LPA_100FULL) {
+       adv_lpa = lpa & adv;
+       if (adv_lpa & LPA_100FULL) {
                newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
                newdup = 1;
-       } else if (lpa & LPA_100HALF) {
+       } else if (adv_lpa & LPA_100HALF) {
                newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
                newdup = 0;
-       } else if (lpa & LPA_10FULL) {
+       } else if (adv_lpa & LPA_10FULL) {
                newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
                newdup = 1;
-       } else if (lpa & LPA_10HALF) {
+       } else if (adv_lpa & LPA_10HALF) {
                newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
                newdup = 0;
        } else {
-               dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, lpa);
+               dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, adv_lpa);
                newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
                newdup = 0;
        }
@@ -2030,6 +2251,46 @@ set_speed:
        writel(np->linkspeed, base + NvRegLinkSpeed);
        pci_push(base);
 
+       pause_flags = 0;
+       /* setup pause frame */
+       if (np->duplex != 0) {
+               if (np->autoneg && np->pause_flags & NV_PAUSEFRAME_AUTONEG) {
+                       adv_pause = adv & (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM);
+                       lpa_pause = lpa & (LPA_PAUSE_CAP| LPA_PAUSE_ASYM);
+
+                       switch (adv_pause) {
+                       case (ADVERTISE_PAUSE_CAP):
+                               if (lpa_pause & LPA_PAUSE_CAP) {
+                                       pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+                                       if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
+                                               pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+                               }
+                               break;
+                       case (ADVERTISE_PAUSE_ASYM):
+                               if (lpa_pause == (LPA_PAUSE_CAP| LPA_PAUSE_ASYM))
+                               {
+                                       pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+                               }
+                               break;
+                       case (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM):
+                               if (lpa_pause & LPA_PAUSE_CAP)
+                               {
+                                       pause_flags |=  NV_PAUSEFRAME_RX_ENABLE;
+                                       if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
+                                               pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+                               }
+                               if (lpa_pause == LPA_PAUSE_ASYM)
+                               {
+                                       pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+                               }
+                               break;
+                       }
+               } else {
+                       pause_flags = np->pause_flags;
+               }
+       }
+       nv_update_pause(dev, pause_flags);
+
        return retval;
 }
 
@@ -2090,7 +2351,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
                spin_lock(&np->lock);
                nv_tx_done(dev);
                spin_unlock(&np->lock);
-               
+
                nv_rx_process(dev);
                if (nv_alloc_rx(dev)) {
                        spin_lock(&np->lock);
@@ -2098,7 +2359,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
                                mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
                        spin_unlock(&np->lock);
                }
-               
+
                if (events & NVREG_IRQ_LINK) {
                        spin_lock(&np->lock);
                        nv_link_irq(dev);
@@ -2163,7 +2424,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
                spin_lock_irq(&np->lock);
                nv_tx_done(dev);
                spin_unlock_irq(&np->lock);
-               
+
                if (events & (NVREG_IRQ_TX_ERR)) {
                        dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
                                                dev->name, events);
@@ -2206,7 +2467,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
                dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events);
                if (!(events & np->irqmask))
                        break;
-               
+
                nv_rx_process(dev);
                if (nv_alloc_rx(dev)) {
                        spin_lock_irq(&np->lock);
@@ -2214,7 +2475,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
                                mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
                        spin_unlock_irq(&np->lock);
                }
-               
+
                if (i > max_interrupt_work) {
                        spin_lock_irq(&np->lock);
                        /* disable interrupts on the nic */
@@ -2253,7 +2514,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
                dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
                if (!(events & np->irqmask))
                        break;
-               
+
                if (events & NVREG_IRQ_LINK) {
                        spin_lock_irq(&np->lock);
                        nv_link_irq(dev);
@@ -2290,6 +2551,175 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
        return IRQ_RETVAL(i);
 }
 
+static irqreturn_t nv_nic_irq_test(int foo, void *data, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) data;
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       u32 events;
+
+       dprintk(KERN_DEBUG "%s: nv_nic_irq_test\n", dev->name);
+
+       if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
+               events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK;
+               writel(NVREG_IRQ_TIMER, base + NvRegIrqStatus);
+       } else {
+               events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK;
+               writel(NVREG_IRQ_TIMER, base + NvRegMSIXIrqStatus);
+       }
+       pci_push(base);
+       dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
+       if (!(events & NVREG_IRQ_TIMER))
+               return IRQ_RETVAL(0);
+
+       spin_lock(&np->lock);
+       np->intr_test = 1;
+       spin_unlock(&np->lock);
+
+       dprintk(KERN_DEBUG "%s: nv_nic_irq_test completed\n", dev->name);
+
+       return IRQ_RETVAL(1);
+}
+
+static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask)
+{
+       u8 __iomem *base = get_hwbase(dev);
+       int i;
+       u32 msixmap = 0;
+
+       /* Each interrupt bit can be mapped to a MSIX vector (4 bits).
+        * MSIXMap0 represents the first 8 interrupts and MSIXMap1 represents
+        * the remaining 8 interrupts.
+        */
+       for (i = 0; i < 8; i++) {
+               if ((irqmask >> i) & 0x1) {
+                       msixmap |= vector << (i << 2);
+               }
+       }
+       writel(readl(base + NvRegMSIXMap0) | msixmap, base + NvRegMSIXMap0);
+
+       msixmap = 0;
+       for (i = 0; i < 8; i++) {
+               if ((irqmask >> (i + 8)) & 0x1) {
+                       msixmap |= vector << (i << 2);
+               }
+       }
+       writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1);
+}
+
+static int nv_request_irq(struct net_device *dev, int intr_test)
+{
+       struct fe_priv *np = get_nvpriv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       int ret = 1;
+       int i;
+
+       if (np->msi_flags & NV_MSI_X_CAPABLE) {
+               for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+                       np->msi_x_entry[i].entry = i;
+               }
+               if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
+                       np->msi_flags |= NV_MSI_X_ENABLED;
+                       if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT && !intr_test) {
+                               /* Request irq for rx handling */
+                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
+                                       printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
+                                       pci_disable_msix(np->pci_dev);
+                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
+                                       goto out_err;
+                               }
+                               /* Request irq for tx handling */
+                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
+                                       printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
+                                       pci_disable_msix(np->pci_dev);
+                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
+                                       goto out_free_rx;
+                               }
+                               /* Request irq for link and timer handling */
+                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
+                                       printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
+                                       pci_disable_msix(np->pci_dev);
+                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
+                                       goto out_free_tx;
+                               }
+                               /* map interrupts to their respective vector */
+                               writel(0, base + NvRegMSIXMap0);
+                               writel(0, base + NvRegMSIXMap1);
+                               set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
+                               set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
+                               set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
+                       } else {
+                               /* Request irq for all interrupts */
+                               if ((!intr_test &&
+                                    request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) ||
+                                   (intr_test &&
+                                    request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq_test, SA_SHIRQ, dev->name, dev) != 0)) {
+                                       printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+                                       pci_disable_msix(np->pci_dev);
+                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
+                                       goto out_err;
+                               }
+
+                               /* map interrupts to vector 0 */
+                               writel(0, base + NvRegMSIXMap0);
+                               writel(0, base + NvRegMSIXMap1);
+                       }
+               }
+       }
+       if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
+               if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
+                       np->msi_flags |= NV_MSI_ENABLED;
+                       if ((!intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) ||
+                           (intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq_test, SA_SHIRQ, dev->name, dev) != 0)) {
+                               printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+                               pci_disable_msi(np->pci_dev);
+                               np->msi_flags &= ~NV_MSI_ENABLED;
+                               goto out_err;
+                       }
+
+                       /* map interrupts to vector 0 */
+                       writel(0, base + NvRegMSIMap0);
+                       writel(0, base + NvRegMSIMap1);
+                       /* enable msi vector 0 */
+                       writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
+               }
+       }
+       if (ret != 0) {
+               if ((!intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) ||
+                   (intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq_test, SA_SHIRQ, dev->name, dev) != 0))
+                       goto out_err;
+
+       }
+
+       return 0;
+out_free_tx:
+       free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev);
+out_free_rx:
+       free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev);
+out_err:
+       return 1;
+}
+
+static void nv_free_irq(struct net_device *dev)
+{
+       struct fe_priv *np = get_nvpriv(dev);
+       int i;
+
+       if (np->msi_flags & NV_MSI_X_ENABLED) {
+               for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+                       free_irq(np->msi_x_entry[i].vector, dev);
+               }
+               pci_disable_msix(np->pci_dev);
+               np->msi_flags &= ~NV_MSI_X_ENABLED;
+       } else {
+               free_irq(np->pci_dev->irq, dev);
+               if (np->msi_flags & NV_MSI_ENABLED) {
+                       pci_disable_msi(np->pci_dev);
+                       np->msi_flags &= ~NV_MSI_ENABLED;
+               }
+       }
+}
+
 static void nv_do_nic_poll(unsigned long data)
 {
        struct net_device *dev = (struct net_device *) data;
@@ -2326,7 +2756,7 @@ static void nv_do_nic_poll(unsigned long data)
        np->nic_poll_irq = 0;
 
        /* FIXME: Do we need synchronize_irq(dev->irq) here? */
-       
+
        writel(mask, base + NvRegIrqMask);
        pci_push(base);
 
@@ -2359,6 +2789,56 @@ static void nv_poll_controller(struct net_device *dev)
 }
 #endif
 
+static void nv_do_stats_poll(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *) data;
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+
+       np->estats.tx_bytes += readl(base + NvRegTxCnt);
+       np->estats.tx_zero_rexmt += readl(base + NvRegTxZeroReXmt);
+       np->estats.tx_one_rexmt += readl(base + NvRegTxOneReXmt);
+       np->estats.tx_many_rexmt += readl(base + NvRegTxManyReXmt);
+       np->estats.tx_late_collision += readl(base + NvRegTxLateCol);
+       np->estats.tx_fifo_errors += readl(base + NvRegTxUnderflow);
+       np->estats.tx_carrier_errors += readl(base + NvRegTxLossCarrier);
+       np->estats.tx_excess_deferral += readl(base + NvRegTxExcessDef);
+       np->estats.tx_retry_error += readl(base + NvRegTxRetryErr);
+       np->estats.tx_deferral += readl(base + NvRegTxDef);
+       np->estats.tx_packets += readl(base + NvRegTxFrame);
+       np->estats.tx_pause += readl(base + NvRegTxPause);
+       np->estats.rx_frame_error += readl(base + NvRegRxFrameErr);
+       np->estats.rx_extra_byte += readl(base + NvRegRxExtraByte);
+       np->estats.rx_late_collision += readl(base + NvRegRxLateCol);
+       np->estats.rx_runt += readl(base + NvRegRxRunt);
+       np->estats.rx_frame_too_long += readl(base + NvRegRxFrameTooLong);
+       np->estats.rx_over_errors += readl(base + NvRegRxOverflow);
+       np->estats.rx_crc_errors += readl(base + NvRegRxFCSErr);
+       np->estats.rx_frame_align_error += readl(base + NvRegRxFrameAlignErr);
+       np->estats.rx_length_error += readl(base + NvRegRxLenErr);
+       np->estats.rx_unicast += readl(base + NvRegRxUnicast);
+       np->estats.rx_multicast += readl(base + NvRegRxMulticast);
+       np->estats.rx_broadcast += readl(base + NvRegRxBroadcast);
+       np->estats.rx_bytes += readl(base + NvRegRxCnt);
+       np->estats.rx_pause += readl(base + NvRegRxPause);
+       np->estats.rx_drop_frame += readl(base + NvRegRxDropFrame);
+       np->estats.rx_packets =
+               np->estats.rx_unicast +
+               np->estats.rx_multicast +
+               np->estats.rx_broadcast;
+       np->estats.rx_errors_total =
+               np->estats.rx_crc_errors +
+               np->estats.rx_over_errors +
+               np->estats.rx_frame_error +
+               (np->estats.rx_frame_align_error - np->estats.rx_extra_byte) +
+               np->estats.rx_late_collision +
+               np->estats.rx_runt +
+               np->estats.rx_frame_too_long;
+
+       if (!np->in_shutdown)
+               mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
+}
+
 static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct fe_priv *np = netdev_priv(dev);
@@ -2382,17 +2862,19 @@ static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
 {
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
+       u32 flags = 0;
 
-       spin_lock_irq(&np->lock);
        if (wolinfo->wolopts == 0) {
-               writel(0, base + NvRegWakeUpFlags);
                np->wolenabled = 0;
-       }
-       if (wolinfo->wolopts & WAKE_MAGIC) {
-               writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags);
+       } else if (wolinfo->wolopts & WAKE_MAGIC) {
                np->wolenabled = 1;
+               flags = NVREG_WAKEUPFLAGS_ENABLE;
+       }
+       if (netif_running(dev)) {
+               spin_lock_irq(&np->lock);
+               writel(flags, base + NvRegWakeUpFlags);
+               spin_unlock_irq(&np->lock);
        }
-       spin_unlock_irq(&np->lock);
        return 0;
 }
 
@@ -2406,9 +2888,17 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        if (!netif_running(dev)) {
                /* We do not track link speed / duplex setting if the
                 * interface is disabled. Force a link check */
-               nv_update_linkspeed(dev);
+               if (nv_update_linkspeed(dev)) {
+                       if (!netif_carrier_ok(dev))
+                               netif_carrier_on(dev);
+               } else {
+                       if (netif_carrier_ok(dev))
+                               netif_carrier_off(dev);
+               }
        }
-       switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) {
+
+       if (netif_carrier_ok(dev)) {
+               switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) {
                case NVREG_LINKSPEED_10:
                        ecmd->speed = SPEED_10;
                        break;
@@ -2418,10 +2908,14 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                case NVREG_LINKSPEED_1000:
                        ecmd->speed = SPEED_1000;
                        break;
+               }
+               ecmd->duplex = DUPLEX_HALF;
+               if (np->duplex)
+                       ecmd->duplex = DUPLEX_FULL;
+       } else {
+               ecmd->speed = -1;
+               ecmd->duplex = -1;
        }
-       ecmd->duplex = DUPLEX_HALF;
-       if (np->duplex)
-               ecmd->duplex = DUPLEX_FULL;
 
        ecmd->autoneg = np->autoneg;
 
@@ -2429,23 +2923,20 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        if (np->autoneg) {
                ecmd->advertising |= ADVERTISED_Autoneg;
                adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-       } else {
-               adv = np->fixed_mode;
-       }
-       if (adv & ADVERTISE_10HALF)
-               ecmd->advertising |= ADVERTISED_10baseT_Half;
-       if (adv & ADVERTISE_10FULL)
-               ecmd->advertising |= ADVERTISED_10baseT_Full;
-       if (adv & ADVERTISE_100HALF)
-               ecmd->advertising |= ADVERTISED_100baseT_Half;
-       if (adv & ADVERTISE_100FULL)
-               ecmd->advertising |= ADVERTISED_100baseT_Full;
-       if (np->autoneg && np->gigabit == PHY_GIGABIT) {
-               adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
-               if (adv & ADVERTISE_1000FULL)
-                       ecmd->advertising |= ADVERTISED_1000baseT_Full;
-       }
-
+               if (adv & ADVERTISE_10HALF)
+                       ecmd->advertising |= ADVERTISED_10baseT_Half;
+               if (adv & ADVERTISE_10FULL)
+                       ecmd->advertising |= ADVERTISED_10baseT_Full;
+               if (adv & ADVERTISE_100HALF)
+                       ecmd->advertising |= ADVERTISED_100baseT_Half;
+               if (adv & ADVERTISE_100FULL)
+                       ecmd->advertising |= ADVERTISED_100baseT_Full;
+               if (np->gigabit == PHY_GIGABIT) {
+                       adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
+                       if (adv & ADVERTISE_1000FULL)
+                               ecmd->advertising |= ADVERTISED_1000baseT_Full;
+               }
+       }
        ecmd->supported = (SUPPORTED_Autoneg |
                SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
                SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
@@ -2497,7 +2988,18 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                return -EINVAL;
        }
 
-       spin_lock_irq(&np->lock);
+       netif_carrier_off(dev);
+       if (netif_running(dev)) {
+               nv_disable_irq(dev);
+               spin_lock_bh(&dev->xmit_lock);
+               spin_lock(&np->lock);
+               /* stop engines */
+               nv_stop_rx(dev);
+               nv_stop_tx(dev);
+               spin_unlock(&np->lock);
+               spin_unlock_bh(&dev->xmit_lock);
+       }
+
        if (ecmd->autoneg == AUTONEG_ENABLE) {
                int adv, bmcr;
 
@@ -2505,7 +3007,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 
                /* advertise only what has been requested */
                adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-               adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+               adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
                if (ecmd->advertising & ADVERTISED_10baseT_Half)
                        adv |= ADVERTISE_10HALF;
                if (ecmd->advertising & ADVERTISED_10baseT_Full)
@@ -2514,16 +3016,22 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                        adv |= ADVERTISE_100HALF;
                if (ecmd->advertising & ADVERTISED_100baseT_Full)
                        adv |= ADVERTISE_100FULL;
+               if (np->pause_flags & NV_PAUSEFRAME_RX_REQ)  /* for rx we set both advertisments but disable tx pause */
+                       adv |=  ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+               if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
+                       adv |=  ADVERTISE_PAUSE_ASYM;
                mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
 
                if (np->gigabit == PHY_GIGABIT) {
-                       adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+                       adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
                        adv &= ~ADVERTISE_1000FULL;
                        if (ecmd->advertising & ADVERTISED_1000baseT_Full)
                                adv |= ADVERTISE_1000FULL;
-                       mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv);
+                       mii_rw(dev, np->phyaddr, MII_CTRL1000, adv);
                }
 
+               if (netif_running(dev))
+                       printk(KERN_INFO "%s: link down.\n", dev->name);
                bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
                bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
                mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
@@ -2534,7 +3042,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                np->autoneg = 0;
 
                adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-               adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+               adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
                if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF)
                        adv |= ADVERTISE_10HALF;
                if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL)
@@ -2543,76 +3051,757 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                        adv |= ADVERTISE_100HALF;
                if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL)
                        adv |= ADVERTISE_100FULL;
+               np->pause_flags &= ~(NV_PAUSEFRAME_AUTONEG|NV_PAUSEFRAME_RX_ENABLE|NV_PAUSEFRAME_TX_ENABLE);
+               if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) {/* for rx we set both advertisments but disable tx pause */
+                       adv |=  ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+                       np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+               }
+               if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) {
+                       adv |=  ADVERTISE_PAUSE_ASYM;
+                       np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+               }
                mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
                np->fixed_mode = adv;
 
-               if (np->gigabit == PHY_GIGABIT) {
-                       adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
-                       adv &= ~ADVERTISE_1000FULL;
-                       mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv);
-               }
+               if (np->gigabit == PHY_GIGABIT) {
+                       adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
+                       adv &= ~ADVERTISE_1000FULL;
+                       mii_rw(dev, np->phyaddr, MII_CTRL1000, adv);
+               }
+
+               bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+               bmcr &= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_SPEED1000|BMCR_FULLDPLX);
+               if (np->fixed_mode & (ADVERTISE_10FULL|ADVERTISE_100FULL))
+                       bmcr |= BMCR_FULLDPLX;
+               if (np->fixed_mode & (ADVERTISE_100HALF|ADVERTISE_100FULL))
+                       bmcr |= BMCR_SPEED100;
+               mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+               if (np->phy_oui == PHY_OUI_MARVELL) {
+                       /* reset the phy */
+                       if (phy_reset(dev)) {
+                               printk(KERN_INFO "%s: phy reset failed\n", dev->name);
+                               return -EINVAL;
+                       }
+               } else if (netif_running(dev)) {
+                       /* Wait a bit and then reconfigure the nic. */
+                       udelay(10);
+                       nv_linkchange(dev);
+               }
+       }
+
+       if (netif_running(dev)) {
+               nv_start_rx(dev);
+               nv_start_tx(dev);
+               nv_enable_irq(dev);
+       }
+
+       return 0;
+}
+
+#define FORCEDETH_REGS_VER     1
+
+static int nv_get_regs_len(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       return np->register_size;
+}
+
+static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       u32 *rbuf = buf;
+       int i;
+
+       regs->version = FORCEDETH_REGS_VER;
+       spin_lock_irq(&np->lock);
+       for (i = 0;i <= np->register_size/sizeof(u32); i++)
+               rbuf[i] = readl(base + i*sizeof(u32));
+       spin_unlock_irq(&np->lock);
+}
+
+static int nv_nway_reset(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       int ret;
+
+       if (np->autoneg) {
+               int bmcr;
+
+               netif_carrier_off(dev);
+               if (netif_running(dev)) {
+                       nv_disable_irq(dev);
+                       spin_lock_bh(&dev->xmit_lock);
+                       spin_lock(&np->lock);
+                       /* stop engines */
+                       nv_stop_rx(dev);
+                       nv_stop_tx(dev);
+                       spin_unlock(&np->lock);
+                       spin_unlock_bh(&dev->xmit_lock);
+                       printk(KERN_INFO "%s: link down.\n", dev->name);
+               }
+
+               bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+               bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+               mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+
+               if (netif_running(dev)) {
+                       nv_start_rx(dev);
+                       nv_start_tx(dev);
+                       nv_enable_irq(dev);
+               }
+               ret = 0;
+       } else {
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int nv_set_tso(struct net_device *dev, u32 value)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       if ((np->driver_data & DEV_HAS_CHECKSUM))
+               return ethtool_op_set_tso(dev, value);
+       else
+               return -EOPNOTSUPP;
+}
+
+static void nv_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       ring->rx_max_pending = (np->desc_ver == DESC_VER_1) ? RING_MAX_DESC_VER_1 : RING_MAX_DESC_VER_2_3;
+       ring->rx_mini_max_pending = 0;
+       ring->rx_jumbo_max_pending = 0;
+       ring->tx_max_pending = (np->desc_ver == DESC_VER_1) ? RING_MAX_DESC_VER_1 : RING_MAX_DESC_VER_2_3;
+
+       ring->rx_pending = np->rx_ring_size;
+       ring->rx_mini_pending = 0;
+       ring->rx_jumbo_pending = 0;
+       ring->tx_pending = np->tx_ring_size;
+}
+
+static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       u8 *rxtx_ring, *rx_skbuff, *tx_skbuff, *rx_dma, *tx_dma, *tx_dma_len;
+       dma_addr_t ring_addr;
+
+       if (ring->rx_pending < RX_RING_MIN ||
+           ring->tx_pending < TX_RING_MIN ||
+           ring->rx_mini_pending != 0 ||
+           ring->rx_jumbo_pending != 0 ||
+           (np->desc_ver == DESC_VER_1 &&
+            (ring->rx_pending > RING_MAX_DESC_VER_1 ||
+             ring->tx_pending > RING_MAX_DESC_VER_1)) ||
+           (np->desc_ver != DESC_VER_1 &&
+            (ring->rx_pending > RING_MAX_DESC_VER_2_3 ||
+             ring->tx_pending > RING_MAX_DESC_VER_2_3))) {
+               return -EINVAL;
+       }
+
+       /* allocate new rings */
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+               rxtx_ring = pci_alloc_consistent(np->pci_dev,
+                                           sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending),
+                                           &ring_addr);
+       } else {
+               rxtx_ring = pci_alloc_consistent(np->pci_dev,
+                                           sizeof(struct ring_desc_ex) * (ring->rx_pending + ring->tx_pending),
+                                           &ring_addr);
+       }
+       rx_skbuff = kmalloc(sizeof(struct sk_buff*) * ring->rx_pending, GFP_KERNEL);
+       rx_dma = kmalloc(sizeof(dma_addr_t) * ring->rx_pending, GFP_KERNEL);
+       tx_skbuff = kmalloc(sizeof(struct sk_buff*) * ring->tx_pending, GFP_KERNEL);
+       tx_dma = kmalloc(sizeof(dma_addr_t) * ring->tx_pending, GFP_KERNEL);
+       tx_dma_len = kmalloc(sizeof(unsigned int) * ring->tx_pending, GFP_KERNEL);
+       if (!rxtx_ring || !rx_skbuff || !rx_dma || !tx_skbuff || !tx_dma || !tx_dma_len) {
+               /* fall back to old rings */
+               if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+                       if(rxtx_ring)
+                               pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending),
+                                                   rxtx_ring, ring_addr);
+               } else {
+                       if (rxtx_ring)
+                               pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (ring->rx_pending + ring->tx_pending),
+                                                   rxtx_ring, ring_addr);
+               }
+               if (rx_skbuff)
+                       kfree(rx_skbuff);
+               if (rx_dma)
+                       kfree(rx_dma);
+               if (tx_skbuff)
+                       kfree(tx_skbuff);
+               if (tx_dma)
+                       kfree(tx_dma);
+               if (tx_dma_len)
+                       kfree(tx_dma_len);
+               goto exit;
+       }
+
+       if (netif_running(dev)) {
+               nv_disable_irq(dev);
+               spin_lock_bh(&dev->xmit_lock);
+               spin_lock(&np->lock);
+               /* stop engines */
+               nv_stop_rx(dev);
+               nv_stop_tx(dev);
+               nv_txrx_reset(dev);
+               /* drain queues */
+               nv_drain_rx(dev);
+               nv_drain_tx(dev);
+               /* delete queues */
+               free_rings(dev);
+       }
+
+       /* set new values */
+       np->rx_ring_size = ring->rx_pending;
+       np->tx_ring_size = ring->tx_pending;
+       np->tx_limit_stop = ring->tx_pending - TX_LIMIT_DIFFERENCE;
+       np->tx_limit_start = ring->tx_pending - TX_LIMIT_DIFFERENCE - 1;
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+               np->rx_ring.orig = (struct ring_desc*)rxtx_ring;
+               np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size];
+       } else {
+               np->rx_ring.ex = (struct ring_desc_ex*)rxtx_ring;
+               np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size];
+       }
+       np->rx_skbuff = (struct sk_buff**)rx_skbuff;
+       np->rx_dma = (dma_addr_t*)rx_dma;
+       np->tx_skbuff = (struct sk_buff**)tx_skbuff;
+       np->tx_dma = (dma_addr_t*)tx_dma;
+       np->tx_dma_len = (unsigned int*)tx_dma_len;
+       np->ring_addr = ring_addr;
+
+       memset(np->rx_skbuff, 0, sizeof(struct sk_buff*) * np->rx_ring_size);
+       memset(np->rx_dma, 0, sizeof(dma_addr_t) * np->rx_ring_size);
+       memset(np->tx_skbuff, 0, sizeof(struct sk_buff*) * np->tx_ring_size);
+       memset(np->tx_dma, 0, sizeof(dma_addr_t) * np->tx_ring_size);
+       memset(np->tx_dma_len, 0, sizeof(unsigned int) * np->tx_ring_size);
+
+       if (netif_running(dev)) {
+               /* reinit driver view of the queues */
+               set_bufsize(dev);
+               if (nv_init_ring(dev)) {
+                       if (!np->in_shutdown)
+                               mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+               }
+
+               /* reinit nic view of the queues */
+               writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+               setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
+               writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+                       base + NvRegRingSizes);
+               pci_push(base);
+               writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+               pci_push(base);
+
+               /* restart engines */
+               nv_start_rx(dev);
+               nv_start_tx(dev);
+               spin_unlock(&np->lock);
+               spin_unlock_bh(&dev->xmit_lock);
+               nv_enable_irq(dev);
+       }
+       return 0;
+exit:
+       return -ENOMEM;
+}
+
+static void nv_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam* pause)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       pause->autoneg = (np->pause_flags & NV_PAUSEFRAME_AUTONEG) != 0;
+       pause->rx_pause = (np->pause_flags & NV_PAUSEFRAME_RX_ENABLE) != 0;
+       pause->tx_pause = (np->pause_flags & NV_PAUSEFRAME_TX_ENABLE) != 0;
+}
+
+static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam* pause)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       int adv, bmcr;
+
+       if ((!np->autoneg && np->duplex == 0) ||
+           (np->autoneg && !pause->autoneg && np->duplex == 0)) {
+               printk(KERN_INFO "%s: can not set pause settings when forced link is in half duplex.\n",
+                      dev->name);
+               return -EINVAL;
+       }
+       if (pause->tx_pause && !(np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)) {
+               printk(KERN_INFO "%s: hardware does not support tx pause frames.\n", dev->name);
+               return -EINVAL;
+       }
+
+       netif_carrier_off(dev);
+       if (netif_running(dev)) {
+               nv_disable_irq(dev);
+               spin_lock_bh(&dev->xmit_lock);
+               spin_lock(&np->lock);
+               /* stop engines */
+               nv_stop_rx(dev);
+               nv_stop_tx(dev);
+               spin_unlock(&np->lock);
+               spin_unlock_bh(&dev->xmit_lock);
+       }
+
+       np->pause_flags &= ~(NV_PAUSEFRAME_RX_REQ|NV_PAUSEFRAME_TX_REQ);
+       if (pause->rx_pause)
+               np->pause_flags |= NV_PAUSEFRAME_RX_REQ;
+       if (pause->tx_pause)
+               np->pause_flags |= NV_PAUSEFRAME_TX_REQ;
+
+       if (np->autoneg && pause->autoneg) {
+               np->pause_flags |= NV_PAUSEFRAME_AUTONEG;
+
+               adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
+               adv &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+               if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) /* for rx we set both advertisments but disable tx pause */
+                       adv |=  ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+               if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
+                       adv |=  ADVERTISE_PAUSE_ASYM;
+               mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
+
+               if (netif_running(dev))
+                       printk(KERN_INFO "%s: link down.\n", dev->name);
+               bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+               bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+               mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+       } else {
+               np->pause_flags &= ~(NV_PAUSEFRAME_AUTONEG|NV_PAUSEFRAME_RX_ENABLE|NV_PAUSEFRAME_TX_ENABLE);
+               if (pause->rx_pause)
+                       np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+               if (pause->tx_pause)
+                       np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+
+               if (!netif_running(dev))
+                       nv_update_linkspeed(dev);
+               else
+                       nv_update_pause(dev, np->pause_flags);
+       }
+
+       if (netif_running(dev)) {
+               nv_start_rx(dev);
+               nv_start_tx(dev);
+               nv_enable_irq(dev);
+       }
+       return 0;
+}
+
+static u32 nv_get_rx_csum(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       return (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) != 0;
+}
+
+static int nv_set_rx_csum(struct net_device *dev, u32 data)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       int retcode = 0;
+
+       if (np->driver_data & DEV_HAS_CHECKSUM) {
+
+               if (((np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) && data) ||
+                   (!(np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) && !data)) {
+                       /* already set or unset */
+                       return 0;
+               }
+
+               if (data) {
+                       np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
+               } else if (!(np->vlanctl_bits & NVREG_VLANCONTROL_ENABLE)) {
+                       np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK;
+               } else {
+                       printk(KERN_INFO "Can not disable rx checksum if vlan is enabled\n");
+                       return -EINVAL;
+               }
+
+               if (netif_running(dev)) {
+                       spin_lock_irq(&np->lock);
+                       writel(np->txrxctl_bits, base + NvRegTxRxControl);
+                       spin_unlock_irq(&np->lock);
+               }
+       } else {
+               return -EINVAL;
+       }
+
+       return retcode;
+}
+
+static int nv_set_tx_csum(struct net_device *dev, u32 data)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       if (np->driver_data & DEV_HAS_CHECKSUM)
+               return ethtool_op_set_tx_hw_csum(dev, data);
+       else
+               return -EOPNOTSUPP;
+}
+
+static int nv_set_sg(struct net_device *dev, u32 data)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       if (np->driver_data & DEV_HAS_CHECKSUM)
+               return ethtool_op_set_sg(dev, data);
+       else
+               return -EOPNOTSUPP;
+}
+
+static int nv_get_stats_count(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       if (np->driver_data & DEV_HAS_STATISTICS)
+               return (sizeof(struct nv_ethtool_stats)/sizeof(u64));
+       else
+               return 0;
+}
+
+static void nv_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *estats, u64 *buffer)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       /* update stats */
+       nv_do_stats_poll((unsigned long)dev);
+
+       memcpy(buffer, &np->estats, nv_get_stats_count(dev)*sizeof(u64));
+}
+
+static int nv_self_test_count(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+
+       if (np->driver_data & DEV_HAS_TEST_EXTENDED)
+               return NV_TEST_COUNT_EXTENDED;
+       else
+               return NV_TEST_COUNT_BASE;
+}
+
+static int nv_link_test(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       int mii_status;
+
+       mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
+       mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
+
+       /* check phy link status */
+       if (!(mii_status & BMSR_LSTATUS))
+               return 0;
+       else
+               return 1;
+}
+
+static int nv_register_test(struct net_device *dev)
+{
+       u8 __iomem *base = get_hwbase(dev);
+       int i = 0;
+       u32 orig_read, new_read;
+
+       do {
+               orig_read = readl(base + nv_registers_test[i].reg);
+
+               /* xor with mask to toggle bits */
+               orig_read ^= nv_registers_test[i].mask;
+
+               writel(orig_read, base + nv_registers_test[i].reg);
+
+               new_read = readl(base + nv_registers_test[i].reg);
+
+               if ((new_read & nv_registers_test[i].mask) != (orig_read & nv_registers_test[i].mask))
+                       return 0;
+
+               /* restore original value */
+               orig_read ^= nv_registers_test[i].mask;
+               writel(orig_read, base + nv_registers_test[i].reg);
+
+       } while (nv_registers_test[++i].reg != 0);
+
+       return 1;
+}
+
+static int nv_interrupt_test(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       int ret = 1;
+       int testcnt;
+       u32 save_msi_flags, save_poll_interval = 0;
+
+       if (netif_running(dev)) {
+               /* free current irq */
+               nv_free_irq(dev);
+               save_poll_interval = readl(base+NvRegPollingInterval);
+       }
+
+       /* flag to test interrupt handler */
+       np->intr_test = 0;
+
+       /* setup test irq */
+       save_msi_flags = np->msi_flags;
+       np->msi_flags &= ~NV_MSI_X_VECTORS_MASK;
+       np->msi_flags |= 0x001; /* setup 1 vector */
+       if (nv_request_irq(dev, 1))
+               return 0;
+
+       /* setup timer interrupt */
+       writel(NVREG_POLL_DEFAULT_CPU, base + NvRegPollingInterval);
+       writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
+
+       nv_enable_hw_interrupts(dev, NVREG_IRQ_TIMER);
+
+       /* wait for at least one interrupt */
+       msleep(100);
+
+       spin_lock_irq(&np->lock);
+
+       /* flag should be set within ISR */
+       testcnt = np->intr_test;
+       if (!testcnt)
+               ret = 2;
+
+       nv_disable_hw_interrupts(dev, NVREG_IRQ_TIMER);
+       if (!(np->msi_flags & NV_MSI_X_ENABLED))
+               writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+       else
+               writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
+
+       spin_unlock_irq(&np->lock);
+
+       nv_free_irq(dev);
+
+       np->msi_flags = save_msi_flags;
+
+       if (netif_running(dev)) {
+               writel(save_poll_interval, base + NvRegPollingInterval);
+               writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
+               /* restore original irq */
+               if (nv_request_irq(dev, 0))
+                       return 0;
+       }
+
+       return ret;
+}
+
+static int nv_loopback_test(struct net_device *dev)
+{
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       struct sk_buff *tx_skb, *rx_skb;
+       dma_addr_t test_dma_addr;
+       u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
+       u32 Flags;
+       int len, i, pkt_len;
+       u8 *pkt_data;
+       u32 filter_flags = 0;
+       u32 misc1_flags = 0;
+       int ret = 1;
+
+       if (netif_running(dev)) {
+               nv_disable_irq(dev);
+               filter_flags = readl(base + NvRegPacketFilterFlags);
+               misc1_flags = readl(base + NvRegMisc1);
+       } else {
+               nv_txrx_reset(dev);
+       }
+
+       /* reinit driver view of the rx queue */
+       set_bufsize(dev);
+       nv_init_ring(dev);
+
+       /* setup hardware for loopback */
+       writel(NVREG_MISC1_FORCE, base + NvRegMisc1);
+       writel(NVREG_PFF_ALWAYS | NVREG_PFF_LOOPBACK, base + NvRegPacketFilterFlags);
+
+       /* reinit nic view of the rx queue */
+       writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+       setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
+       writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+               base + NvRegRingSizes);
+       pci_push(base);
+
+       /* restart rx engine */
+       nv_start_rx(dev);
+       nv_start_tx(dev);
+
+       /* setup packet for tx */
+       pkt_len = ETH_DATA_LEN;
+       tx_skb = dev_alloc_skb(pkt_len);
+       pkt_data = skb_put(tx_skb, pkt_len);
+       for (i = 0; i < pkt_len; i++)
+               pkt_data[i] = (u8)(i & 0xff);
+       test_dma_addr = pci_map_single(np->pci_dev, tx_skb->data,
+                                      tx_skb->end-tx_skb->data, PCI_DMA_FROMDEVICE);
+
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+               np->tx_ring.orig[0].PacketBuffer = cpu_to_le32(test_dma_addr);
+               np->tx_ring.orig[0].FlagLen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
+       } else {
+               np->tx_ring.ex[0].PacketBufferHigh = cpu_to_le64(test_dma_addr) >> 32;
+               np->tx_ring.ex[0].PacketBufferLow = cpu_to_le64(test_dma_addr) & 0x0FFFFFFFF;
+               np->tx_ring.ex[0].FlagLen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
+       }
+       writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+       pci_push(get_hwbase(dev));
+
+       msleep(500);
 
-               bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
-               bmcr |= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_FULLDPLX);
-               if (adv & (ADVERTISE_10FULL|ADVERTISE_100FULL))
-                       bmcr |= BMCR_FULLDPLX;
-               if (adv & (ADVERTISE_100HALF|ADVERTISE_100FULL))
-                       bmcr |= BMCR_SPEED100;
-               mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+       /* check for rx of the packet */
+       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+               Flags = le32_to_cpu(np->rx_ring.orig[0].FlagLen);
+               len = nv_descr_getlength(&np->rx_ring.orig[0], np->desc_ver);
 
-               if (netif_running(dev)) {
-                       /* Wait a bit and then reconfigure the nic. */
-                       udelay(10);
-                       nv_linkchange(dev);
+       } else {
+               Flags = le32_to_cpu(np->rx_ring.ex[0].FlagLen);
+               len = nv_descr_getlength_ex(&np->rx_ring.ex[0], np->desc_ver);
+       }
+
+       if (Flags & NV_RX_AVAIL) {
+               ret = 0;
+       } else if (np->desc_ver == DESC_VER_1) {
+               if (Flags & NV_RX_ERROR)
+                       ret = 0;
+       } else {
+               if (Flags & NV_RX2_ERROR) {
+                       ret = 0;
                }
        }
-       spin_unlock_irq(&np->lock);
 
-       return 0;
-}
+       if (ret) {
+               if (len != pkt_len) {
+                       ret = 0;
+                       dprintk(KERN_DEBUG "%s: loopback len mismatch %d vs %d\n",
+                               dev->name, len, pkt_len);
+               } else {
+                       rx_skb = np->rx_skbuff[0];
+                       for (i = 0; i < pkt_len; i++) {
+                               if (rx_skb->data[i] != (u8)(i & 0xff)) {
+                                       ret = 0;
+                                       dprintk(KERN_DEBUG "%s: loopback pattern check failed on byte %d\n",
+                                               dev->name, i);
+                                       break;
+                               }
+                       }
+               }
+       } else {
+               dprintk(KERN_DEBUG "%s: loopback - did not receive test packet\n", dev->name);
+       }
 
-#define FORCEDETH_REGS_VER     1
+       pci_unmap_page(np->pci_dev, test_dma_addr,
+                      tx_skb->end-tx_skb->data,
+                      PCI_DMA_TODEVICE);
+       dev_kfree_skb_any(tx_skb);
 
-static int nv_get_regs_len(struct net_device *dev)
-{
-       struct fe_priv *np = netdev_priv(dev);
-       return np->register_size;
+       /* stop engines */
+       nv_stop_rx(dev);
+       nv_stop_tx(dev);
+       nv_txrx_reset(dev);
+       /* drain rx queue */
+       nv_drain_rx(dev);
+       nv_drain_tx(dev);
+
+       if (netif_running(dev)) {
+               writel(misc1_flags, base + NvRegMisc1);
+               writel(filter_flags, base + NvRegPacketFilterFlags);
+               nv_enable_irq(dev);
+       }
+
+       return ret;
 }
 
-static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 *buffer)
 {
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
-       u32 *rbuf = buf;
-       int i;
+       int result;
+       memset(buffer, 0, nv_self_test_count(dev)*sizeof(u64));
 
-       regs->version = FORCEDETH_REGS_VER;
-       spin_lock_irq(&np->lock);
-       for (i = 0;i <= np->register_size/sizeof(u32); i++)
-               rbuf[i] = readl(base + i*sizeof(u32));
-       spin_unlock_irq(&np->lock);
-}
+       if (!nv_link_test(dev)) {
+               test->flags |= ETH_TEST_FL_FAILED;
+               buffer[0] = 1;
+       }
 
-static int nv_nway_reset(struct net_device *dev)
-{
-       struct fe_priv *np = netdev_priv(dev);
-       int ret;
+       if (test->flags & ETH_TEST_FL_OFFLINE) {
+               if (netif_running(dev)) {
+                       netif_stop_queue(dev);
+                       spin_lock_bh(&dev->xmit_lock);
+                       spin_lock_irq(&np->lock);
+                       nv_disable_hw_interrupts(dev, np->irqmask);
+                       if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
+                               writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+                       } else {
+                               writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
+                       }
+                       /* stop engines */
+                       nv_stop_rx(dev);
+                       nv_stop_tx(dev);
+                       nv_txrx_reset(dev);
+                       /* drain rx queue */
+                       nv_drain_rx(dev);
+                       nv_drain_tx(dev);
+                       spin_unlock_irq(&np->lock);
+                       spin_unlock_bh(&dev->xmit_lock);
+               }
 
-       spin_lock_irq(&np->lock);
-       if (np->autoneg) {
-               int bmcr;
+               if (!nv_register_test(dev)) {
+                       test->flags |= ETH_TEST_FL_FAILED;
+                       buffer[1] = 1;
+               }
 
-               bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
-               bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
-               mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+               result = nv_interrupt_test(dev);
+               if (result != 1) {
+                       test->flags |= ETH_TEST_FL_FAILED;
+                       buffer[2] = 1;
+               }
+               if (result == 0) {
+                       /* bail out */
+                       return;
+               }
 
-               ret = 0;
-       } else {
-               ret = -EINVAL;
+               if (!nv_loopback_test(dev)) {
+                       test->flags |= ETH_TEST_FL_FAILED;
+                       buffer[3] = 1;
+               }
+
+               if (netif_running(dev)) {
+                       /* reinit driver view of the rx queue */
+                       set_bufsize(dev);
+                       if (nv_init_ring(dev)) {
+                               if (!np->in_shutdown)
+                                       mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+                       }
+                       /* reinit nic view of the rx queue */
+                       writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+                       setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
+                       writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+                               base + NvRegRingSizes);
+                       pci_push(base);
+                       writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+                       pci_push(base);
+                       /* restart rx engine */
+                       nv_start_rx(dev);
+                       nv_start_tx(dev);
+                       netif_start_queue(dev);
+                       nv_enable_hw_interrupts(dev, np->irqmask);
+               }
        }
-       spin_unlock_irq(&np->lock);
+}
 
-       return ret;
+static void nv_get_strings(struct net_device *dev, u32 stringset, u8 *buffer)
+{
+       switch (stringset) {
+       case ETH_SS_STATS:
+               memcpy(buffer, &nv_estats_str, nv_get_stats_count(dev)*sizeof(struct nv_ethtool_str));
+               break;
+       case ETH_SS_TEST:
+               memcpy(buffer, &nv_etests_str, nv_self_test_count(dev)*sizeof(struct nv_ethtool_str));
+               break;
+       }
 }
 
 static struct ethtool_ops ops = {
@@ -2626,6 +3815,23 @@ static struct ethtool_ops ops = {
        .get_regs = nv_get_regs,
        .nway_reset = nv_nway_reset,
        .get_perm_addr = ethtool_op_get_perm_addr,
+       .get_tso = ethtool_op_get_tso,
+       .set_tso = nv_set_tso,
+       .get_ringparam = nv_get_ringparam,
+       .set_ringparam = nv_set_ringparam,
+       .get_pauseparam = nv_get_pauseparam,
+       .set_pauseparam = nv_set_pauseparam,
+       .get_rx_csum = nv_get_rx_csum,
+       .set_rx_csum = nv_set_rx_csum,
+       .get_tx_csum = ethtool_op_get_tx_csum,
+       .set_tx_csum = nv_set_tx_csum,
+       .get_sg = ethtool_op_get_sg,
+       .set_sg = nv_set_sg,
+       .get_strings = nv_get_strings,
+       .get_stats_count = nv_get_stats_count,
+       .get_ethtool_stats = nv_get_ethtool_stats,
+       .self_test_count = nv_self_test_count,
+       .self_test = nv_self_test,
 };
 
 static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
@@ -2656,139 +3862,6 @@ static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        /* nothing to do */
 };
 
-static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask)
-{
-       u8 __iomem *base = get_hwbase(dev);
-       int i;
-       u32 msixmap = 0;
-
-       /* Each interrupt bit can be mapped to a MSIX vector (4 bits).
-        * MSIXMap0 represents the first 8 interrupts and MSIXMap1 represents
-        * the remaining 8 interrupts.
-        */
-       for (i = 0; i < 8; i++) {
-               if ((irqmask >> i) & 0x1) {
-                       msixmap |= vector << (i << 2);
-               }
-       }
-       writel(readl(base + NvRegMSIXMap0) | msixmap, base + NvRegMSIXMap0);
-
-       msixmap = 0;
-       for (i = 0; i < 8; i++) {
-               if ((irqmask >> (i + 8)) & 0x1) {
-                       msixmap |= vector << (i << 2);
-               }
-       }
-       writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1);
-}
-
-static int nv_request_irq(struct net_device *dev)
-{
-       struct fe_priv *np = get_nvpriv(dev);
-       u8 __iomem *base = get_hwbase(dev);
-       int ret = 1;
-       int i;
-
-       if (np->msi_flags & NV_MSI_X_CAPABLE) {
-               for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
-                       np->msi_x_entry[i].entry = i;
-               }
-               if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
-                       np->msi_flags |= NV_MSI_X_ENABLED;
-                       if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) {
-                               /* Request irq for rx handling */
-                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
-                                       printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
-                                       pci_disable_msix(np->pci_dev);
-                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
-                                       goto out_err;
-                               }
-                               /* Request irq for tx handling */
-                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
-                                       printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
-                                       pci_disable_msix(np->pci_dev);
-                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
-                                       goto out_free_rx;
-                               }
-                               /* Request irq for link and timer handling */
-                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
-                                       printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
-                                       pci_disable_msix(np->pci_dev);
-                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
-                                       goto out_free_tx;
-                               }
-                               /* map interrupts to their respective vector */
-                               writel(0, base + NvRegMSIXMap0);
-                               writel(0, base + NvRegMSIXMap1);
-                               set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
-                               set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
-                               set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
-                       } else {
-                               /* Request irq for all interrupts */
-                               if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
-                                       printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
-                                       pci_disable_msix(np->pci_dev);
-                                       np->msi_flags &= ~NV_MSI_X_ENABLED;
-                                       goto out_err;
-                               }
-
-                               /* map interrupts to vector 0 */
-                               writel(0, base + NvRegMSIXMap0);
-                               writel(0, base + NvRegMSIXMap1);
-                       }
-               }
-       }
-       if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
-               if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
-                       np->msi_flags |= NV_MSI_ENABLED;
-                       if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
-                               printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
-                               pci_disable_msi(np->pci_dev);
-                               np->msi_flags &= ~NV_MSI_ENABLED;
-                               goto out_err;
-                       }
-
-                       /* map interrupts to vector 0 */
-                       writel(0, base + NvRegMSIMap0);
-                       writel(0, base + NvRegMSIMap1);
-                       /* enable msi vector 0 */
-                       writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
-               }
-       }
-       if (ret != 0) {
-               if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0)
-                       goto out_err;
-       }
-
-       return 0;
-out_free_tx:
-       free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev);
-out_free_rx:
-       free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev);
-out_err:
-       return 1;
-}
-
-static void nv_free_irq(struct net_device *dev)
-{
-       struct fe_priv *np = get_nvpriv(dev);
-       int i;
-
-       if (np->msi_flags & NV_MSI_X_ENABLED) {
-               for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
-                       free_irq(np->msi_x_entry[i].vector, dev);
-               }
-               pci_disable_msix(np->pci_dev);
-               np->msi_flags &= ~NV_MSI_X_ENABLED;
-       } else {
-               free_irq(np->pci_dev->irq, dev);
-               if (np->msi_flags & NV_MSI_ENABLED) {
-                       pci_disable_msi(np->pci_dev);
-                       np->msi_flags &= ~NV_MSI_ENABLED;
-               }
-       }
-}
-
 static int nv_open(struct net_device *dev)
 {
        struct fe_priv *np = netdev_priv(dev);
@@ -2813,6 +3886,9 @@ static int nv_open(struct net_device *dev)
 
        writel(0, base + NvRegAdapterControl);
 
+       if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)
+               writel(NVREG_TX_PAUSEFRAME_DISABLE,  base + NvRegTxPauseFrame);
+
        /* 2) initialize descriptor rings */
        set_bufsize(dev);
        oom = nv_init_ring(dev);
@@ -2829,7 +3905,7 @@ static int nv_open(struct net_device *dev)
 
        /* 4) give hw rings */
        setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
-       writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
+       writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
                base + NvRegRingSizes);
 
        /* 5) continue setup */
@@ -2871,7 +3947,8 @@ static int nv_open(struct net_device *dev)
                        base + NvRegAdapterControl);
        writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed);
        writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4);
-       writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags);
+       if (np->wolenabled)
+               writel(NVREG_WAKEUPFLAGS_ENABLE , base + NvRegWakeUpFlags);
 
        i = readl(base + NvRegPowerState);
        if ( (i & NVREG_POWERSTATE_POWEREDUP) == 0)
@@ -2887,7 +3964,7 @@ static int nv_open(struct net_device *dev)
        writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
        pci_push(base);
 
-       if (nv_request_irq(dev)) {
+       if (nv_request_irq(dev, 0)) {
                goto out_drain;
        }
 
@@ -2924,6 +4001,11 @@ static int nv_open(struct net_device *dev)
        }
        if (oom)
                mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+
+       /* start statistics timer */
+       if (np->driver_data & DEV_HAS_STATISTICS)
+               mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
+
        spin_unlock_irq(&np->lock);
 
        return 0;
@@ -2944,6 +4026,7 @@ static int nv_close(struct net_device *dev)
 
        del_timer_sync(&np->oom_kick);
        del_timer_sync(&np->nic_poll);
+       del_timer_sync(&np->stats_poll);
 
        netif_stop_queue(dev);
        spin_lock_irq(&np->lock);
@@ -3003,6 +4086,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        init_timer(&np->nic_poll);
        np->nic_poll.data = (unsigned long) dev;
        np->nic_poll.function = &nv_do_nic_poll;        /* timer handler */
+       init_timer(&np->stats_poll);
+       np->stats_poll.data = (unsigned long) dev;
+       np->stats_poll.function = &nv_do_stats_poll;    /* timer handler */
 
        err = pci_enable_device(pci_dev);
        if (err) {
@@ -3017,7 +4103,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        if (err < 0)
                goto out_disable;
 
-       if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL))
+       if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS))
                np->register_size = NV_PCI_REGSZ_VER2;
        else
                np->register_size = NV_PCI_REGSZ_VER1;
@@ -3049,16 +4135,18 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
                /* packet format 3: supports 40-bit addressing */
                np->desc_ver = DESC_VER_3;
                np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
-               if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
-                       printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
-                                       pci_name(pci_dev));
-               } else {
-                       dev->features |= NETIF_F_HIGHDMA;
-                       printk(KERN_INFO "forcedeth: using HIGHDMA\n");
-               }
-               if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
-                       printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
-                              pci_name(pci_dev));
+               if (dma_64bit) {
+                       if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
+                               printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
+                                      pci_name(pci_dev));
+                       } else {
+                               dev->features |= NETIF_F_HIGHDMA;
+                               printk(KERN_INFO "forcedeth: using HIGHDMA\n");
+                       }
+                       if (pci_set_consistent_dma_mask(pci_dev, DMA_39BIT_MASK)) {
+                               printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed, using 32-bit ring buffers for device %s.\n",
+                                      pci_name(pci_dev));
+                       }
                }
        } else if (id->driver_data & DEV_HAS_LARGEDESC) {
                /* packet format 2: supports jumbo frames */
@@ -3091,13 +4179,19 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        }
 
        np->msi_flags = 0;
-       if ((id->driver_data & DEV_HAS_MSI) && !disable_msi) {
+       if ((id->driver_data & DEV_HAS_MSI) && msi) {
                np->msi_flags |= NV_MSI_CAPABLE;
        }
-       if ((id->driver_data & DEV_HAS_MSI_X) && !disable_msix) {
+       if ((id->driver_data & DEV_HAS_MSI_X) && msix) {
                np->msi_flags |= NV_MSI_X_CAPABLE;
        }
 
+       np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG;
+       if (id->driver_data & DEV_HAS_PAUSEFRAME_TX) {
+               np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ;
+       }
+
+
        err = -ENOMEM;
        np->base = ioremap(addr, np->register_size);
        if (!np->base)
@@ -3106,21 +4200,38 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 
        dev->irq = pci_dev->irq;
 
+       np->rx_ring_size = RX_RING_DEFAULT;
+       np->tx_ring_size = TX_RING_DEFAULT;
+       np->tx_limit_stop = np->tx_ring_size - TX_LIMIT_DIFFERENCE;
+       np->tx_limit_start = np->tx_ring_size - TX_LIMIT_DIFFERENCE - 1;
+
        if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
                np->rx_ring.orig = pci_alloc_consistent(pci_dev,
-                                       sizeof(struct ring_desc) * (RX_RING + TX_RING),
+                                       sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),
                                        &np->ring_addr);
                if (!np->rx_ring.orig)
                        goto out_unmap;
-               np->tx_ring.orig = &np->rx_ring.orig[RX_RING];
+               np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size];
        } else {
                np->rx_ring.ex = pci_alloc_consistent(pci_dev,
-                                       sizeof(struct ring_desc_ex) * (RX_RING + TX_RING),
+                                       sizeof(struct ring_desc_ex) * (np->rx_ring_size + np->tx_ring_size),
                                        &np->ring_addr);
                if (!np->rx_ring.ex)
                        goto out_unmap;
-               np->tx_ring.ex = &np->rx_ring.ex[RX_RING];
+               np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size];
        }
+       np->rx_skbuff = kmalloc(sizeof(struct sk_buff*) * np->rx_ring_size, GFP_KERNEL);
+       np->rx_dma = kmalloc(sizeof(dma_addr_t) * np->rx_ring_size, GFP_KERNEL);
+       np->tx_skbuff = kmalloc(sizeof(struct sk_buff*) * np->tx_ring_size, GFP_KERNEL);
+       np->tx_dma = kmalloc(sizeof(dma_addr_t) * np->tx_ring_size, GFP_KERNEL);
+       np->tx_dma_len = kmalloc(sizeof(unsigned int) * np->tx_ring_size, GFP_KERNEL);
+       if (!np->rx_skbuff || !np->rx_dma || !np->tx_skbuff || !np->tx_dma || !np->tx_dma_len)
+               goto out_freering;
+       memset(np->rx_skbuff, 0, sizeof(struct sk_buff*) * np->rx_ring_size);
+       memset(np->rx_dma, 0, sizeof(dma_addr_t) * np->rx_ring_size);
+       memset(np->tx_skbuff, 0, sizeof(struct sk_buff*) * np->tx_ring_size);
+       memset(np->tx_dma, 0, sizeof(dma_addr_t) * np->tx_ring_size);
+       memset(np->tx_dma_len, 0, sizeof(unsigned int) * np->tx_ring_size);
 
        dev->open = nv_open;
        dev->stop = nv_close;
@@ -3242,9 +4353,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        if (i == 33) {
                printk(KERN_INFO "%s: open: Could not find a valid PHY.\n",
                       pci_name(pci_dev));
-               goto out_freering;
+               goto out_error;
        }
-       
+
        /* reset it */
        phy_init(dev);
 
@@ -3256,7 +4367,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
        err = register_netdev(dev);
        if (err) {
                printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err);
-               goto out_freering;
+               goto out_error;
        }
        printk(KERN_INFO "%s: forcedeth.c: subsystem: %05x:%04x bound to %s\n",
                        dev->name, pci_dev->subsystem_vendor, pci_dev->subsystem_device,
@@ -3264,14 +4375,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 
        return 0;
 
-out_freering:
-       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-               pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
-                                   np->rx_ring.orig, np->ring_addr);
-       else
-               pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING),
-                                   np->rx_ring.ex, np->ring_addr);
+out_error:
        pci_set_drvdata(pci_dev, NULL);
+out_freering:
+       free_rings(dev);
 out_unmap:
        iounmap(get_hwbase(dev));
 out_relreg:
@@ -3287,15 +4394,11 @@ out:
 static void __devexit nv_remove(struct pci_dev *pci_dev)
 {
        struct net_device *dev = pci_get_drvdata(pci_dev);
-       struct fe_priv *np = netdev_priv(dev);
 
        unregister_netdev(dev);
 
        /* free all structures */
-       if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-               pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring.orig, np->ring_addr);
-       else
-               pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING), np->rx_ring.ex, np->ring_addr);
+       free_rings(dev);
        iounmap(get_hwbase(dev));
        pci_release_regions(pci_dev);
        pci_disable_device(pci_dev);
@@ -3358,11 +4461,43 @@ static struct pci_device_id pci_tbl[] = {
        },
        {       /* MCP55 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
        },
        {       /* MCP55 Ethernet Controller */
                PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
-               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+       },
+       {       /* MCP61 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+       },
+       {       /* MCP61 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+       },
+       {       /* MCP61 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+       },
+       {       /* MCP61 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+       },
+       {       /* MCP65 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+       },
+       {       /* MCP65 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+       },
+       {       /* MCP65 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+       },
+       {       /* MCP65 Ethernet Controller */
+               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
+               .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
        },
        {0,},
 };
@@ -3392,10 +4527,12 @@ module_param(optimization_mode, int, 0);
 MODULE_PARM_DESC(optimization_mode, "In throughput mode (0), every tx & rx packet will generate an interrupt. In CPU mode (1), interrupts are controlled by a timer.");
 module_param(poll_interval, int, 0);
 MODULE_PARM_DESC(poll_interval, "Interval determines how frequent timer interrupt is generated by [(time_in_micro_secs * 100) / (2^10)]. Min is 0 and Max is 65535.");
-module_param(disable_msi, int, 0);
-MODULE_PARM_DESC(disable_msi, "Disable MSI interrupts by setting to 1.");
-module_param(disable_msix, int, 0);
-MODULE_PARM_DESC(disable_msix, "Disable MSIX interrupts by setting to 1.");
+module_param(msi, int, 0);
+MODULE_PARM_DESC(msi, "MSI interrupts are enabled by setting to 1 and disabled by setting to 0.");
+module_param(msix, int, 0);
+MODULE_PARM_DESC(msix, "MSIX interrupts are enabled by setting to 1 and disabled by setting to 0.");
+module_param(dma_64bit, int, 0);
+MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0.");
 
 MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>");
 MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
index 102c1f0b90dac7a941902322dbc33cfd295c1799..d12605f0ac7c6e0f4b01ed0558d61a47c4037008 100644 (file)
@@ -308,9 +308,9 @@ static int sp_set_mac_address(struct net_device *dev, void *addr)
 {
        struct sockaddr_ax25 *sa = addr;
 
-       spin_lock_irq(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
        memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
-       spin_unlock_irq(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
 
        return 0;
 }
@@ -767,9 +767,9 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
                        break;
                }
 
-               spin_lock_irq(&dev->xmit_lock);
+               netif_tx_lock_bh(dev);
                memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
-               spin_unlock_irq(&dev->xmit_lock);
+               netif_tx_unlock_bh(dev);
 
                err = 0;
                break;
index d81a8e1eeb8d5f807fce83f5a99ef04fefd755cf..3ebbbe56b6e94be8c9fd7ec3be2b7d3486f7c51d 100644 (file)
@@ -357,9 +357,9 @@ static int ax_set_mac_address(struct net_device *dev, void *addr)
 {
        struct sockaddr_ax25 *sa = addr;
 
-       spin_lock_irq(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
        memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
-       spin_unlock_irq(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
 
        return 0;
 }
@@ -886,9 +886,9 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
                        break;
                }
 
-               spin_lock_irq(&dev->xmit_lock);
+               netif_tx_lock_bh(dev);
                memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
-               spin_unlock_irq(&dev->xmit_lock);
+               netif_tx_unlock_bh(dev);
 
                err = 0;
                break;
index 0d7a6250e3462907180190aef6c2e6fdc46c7aa4..e26a3e407d706d941c2c3f758747b8270289802d 100644 (file)
@@ -446,7 +446,7 @@ MODULE_LICENSE("GPL");
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
+int __init
 init_module(void)
 {
        struct net_device *dev;
index cf9fb3698a6bda38f8ac83f96b9cdad39b986fd8..551a71b3c5fd825de937fb56f542a7f339fae414 100644 (file)
@@ -384,7 +384,7 @@ hp_block_output(struct net_device *dev, int count,
 }
 
 /* This function resets the ethercard if something screws up. */
-static void
+static void __init
 hp_init_card(struct net_device *dev)
 {
        int irq = dev->irq;
@@ -409,7 +409,7 @@ MODULE_LICENSE("GPL");
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
+int __init
 init_module(void)
 {
        struct net_device *dev;
index 01ad904215a15f47f8dda0240350d4007dba5ed8..51fd51609ea9308af6b7e7755cc058dcd8b81905 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 net-3-driver for the IBM LAN Adapter/A
 
 This is an extension to the Linux operating system, and is covered by the
@@ -11,9 +11,9 @@ This driver is based both on the SK_MCA driver, which is itself based on the
 SK_G16 and 3C523 driver.
 
 paper sources:
-  'PC Hardware: Aufbau, Funktionsweise, Programmierung' by 
+  'PC Hardware: Aufbau, Funktionsweise, Programmierung' by
   Hans-Peter Messmer for the basic Microchannel stuff
-  
+
   'Linux Geraetetreiber' by Allesandro Rubini, Kalle Dalheimer
   for help on Ethernet driver programming
 
@@ -27,14 +27,14 @@ paper sources:
 
 special acknowledgements to:
   - Bob Eager for helping me out with documentation from IBM
-  - Jim Shorney for his endless patience with me while I was using 
+  - Jim Shorney for his endless patience with me while I was using
     him as a beta tester to trace down the address filter bug ;-)
 
   Missing things:
 
   -> set debug level via ioctl instead of compile-time switches
   -> I didn't follow the development of the 2.1.x kernels, so my
-     assumptions about which things changed with which kernel version 
+     assumptions about which things changed with which kernel version
      are probably nonsense
 
 History:
@@ -275,7 +275,7 @@ static void InitDscrs(struct net_device *dev)
        priv->rrastart = raddr = priv->txbufstart + (TXBUFCNT * PKTSIZE);
        priv->rdastart = addr = priv->rrastart + (priv->rxbufcnt * sizeof(rra_t));
        priv->rxbufstart = baddr = priv->rdastart + (priv->rxbufcnt * sizeof(rda_t));
-       
+
        for (z = 0; z < priv->rxbufcnt; z++) {
                rra.startlo = baddr;
                rra.starthi = 0;
@@ -570,7 +570,7 @@ static void irqrx_handler(struct net_device *dev)
                lrdaaddr = priv->rdastart + (priv->lastrxdescr * sizeof(rda_t));
                memcpy_fromio(&rda, priv->base + rdaaddr, sizeof(rda_t));
 
-               /* iron out upper word halves of fields we use - SONIC will duplicate 
+               /* iron out upper word halves of fields we use - SONIC will duplicate
                   bits 0..15 to 16..31 */
 
                rda.status &= 0xffff;
@@ -836,9 +836,9 @@ static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev)
        baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE);
        memcpy_toio(priv->base + baddr, skb->data, skb->len);
 
-       /* copy filler into RAM - in case we're filling up... 
+       /* copy filler into RAM - in case we're filling up...
           we're filling a bit more than necessary, but that doesn't harm
-          since the buffer is far larger... 
+          since the buffer is far larger...
           Sorry Linus for the filler string but I couldn't resist ;-) */
 
        if (tmplen > skb->len) {
@@ -952,7 +952,7 @@ static int ibmlana_probe(struct net_device *dev)
        priv->realirq = irq;
        priv->medium = medium;
        spin_lock_init(&priv->lock);
-               
+
 
        /* set base + irq for this device (irq not allocated so far) */
 
index 458ee226e5372d8250f20f733f483543e4eef259..6b58bab9e3086fd4b1826eb99d0dd3a7b00a1f93 100644 (file)
@@ -17,7 +17,7 @@
 /* media enumeration - defined in a way that it fits onto the LAN/A's
    POS registers... */
 
-typedef enum { 
+typedef enum {
        Media_10BaseT, Media_10Base5,
        Media_Unknown, Media_10Base2, Media_Count
 } ibmlana_medium;
@@ -27,7 +27,7 @@ typedef enum {
 typedef struct {
        unsigned int slot;              /* MCA-Slot-#                       */
        struct net_device_stats stat;   /* packet statistics            */
-       int realirq;                    /* memorizes actual IRQ, even when 
+       int realirq;                    /* memorizes actual IRQ, even when
                                           currently not allocated          */
        ibmlana_medium medium;          /* physical cannector               */
        u32     tdastart, txbufstart,   /* addresses                        */
@@ -41,7 +41,7 @@ typedef struct {
        spinlock_t lock;
 } ibmlana_priv;
 
-/* this card uses quite a lot of I/O ports...luckily the MCA bus decodes 
+/* this card uses quite a lot of I/O ports...luckily the MCA bus decodes
    a full 64K I/O range... */
 
 #define IBM_LANA_IORANGE 0xa0
index 52d01027d9e7c236d472af4f25b2f84e993a22bf..666346f6469e9fd314c90c838037bfb6ed9c6952 100644 (file)
@@ -24,7 +24,7 @@
 /* for use with IBM i/pSeries LPAR Linux.  It utilizes the logical LAN    */
 /* option of the RS/6000 Platform Architechture to interface with virtual */
 /* ethernet NICs that are presented to the partition by the hypervisor.   */
-/*                                                                        */ 
+/*                                                                        */
 /**************************************************************************/
 /*
   TODO:
@@ -79,7 +79,7 @@
 #else
 #define ibmveth_debug_printk_no_adapter(fmt, args...)
 #define ibmveth_debug_printk(fmt, args...)
-#define ibmveth_assert(expr) 
+#define ibmveth_assert(expr)
 #endif
 
 static int ibmveth_open(struct net_device *dev);
@@ -96,6 +96,7 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter);
 static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
+static struct kobj_type ktype_veth_pool;
 
 #ifdef CONFIG_PROC_FS
 #define IBMVETH_PROC_DIR "net/ibmveth"
@@ -133,12 +134,13 @@ static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter)
 }
 
 /* setup the initial settings for a buffer pool */
-static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size)
+static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size, u32 pool_active)
 {
        pool->size = pool_size;
        pool->index = pool_index;
        pool->buff_size = buff_size;
        pool->threshold = pool_size / 2;
+       pool->active = pool_active;
 }
 
 /* allocate and setup an buffer pool - called during open */
@@ -146,13 +148,13 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
 {
        int i;
 
-       pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); 
+       pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL);
 
        if(!pool->free_map) {
                return -1;
        }
 
-       pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); 
+       pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL);
        if(!pool->dma_addr) {
                kfree(pool->free_map);
                pool->free_map = NULL;
@@ -180,7 +182,6 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
        atomic_set(&pool->available, 0);
        pool->producer_index = 0;
        pool->consumer_index = 0;
-       pool->active = 0;
 
        return 0;
 }
@@ -214,7 +215,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
 
                free_index = pool->consumer_index++ % pool->size;
                index = pool->free_map[free_index];
-       
+
                ibmveth_assert(index != IBM_VETH_INVALID_MAP);
                ibmveth_assert(pool->skbuff[index] == NULL);
 
@@ -231,10 +232,10 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
                desc.desc = 0;
                desc.fields.valid = 1;
                desc.fields.length = pool->buff_size;
-               desc.fields.address = dma_addr; 
+               desc.fields.address = dma_addr;
 
                lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
-                   
+
                if(lpar_rc != H_SUCCESS) {
                        pool->free_map[free_index] = index;
                        pool->skbuff[index] = NULL;
@@ -250,13 +251,13 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
                        adapter->replenish_add_buff_success++;
                }
        }
-    
+
        mb();
        atomic_add(buffers_added, &(pool->available));
 }
 
 /* replenish routine */
-static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) 
+static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
 {
        int i;
 
@@ -264,7 +265,7 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
 
        for(i = 0; i < IbmVethNumBufferPools; i++)
                if(adapter->rx_buff_pool[i].active)
-                       ibmveth_replenish_buffer_pool(adapter, 
+                       ibmveth_replenish_buffer_pool(adapter,
                                                     &adapter->rx_buff_pool[i]);
 
        adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
@@ -301,7 +302,6 @@ static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibm
                kfree(pool->skbuff);
                pool->skbuff = NULL;
        }
-       pool->active = 0;
 }
 
 /* remove a buffer from a pool */
@@ -372,7 +372,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
        desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index];
 
        lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
-                   
+
        if(lpar_rc != H_SUCCESS) {
                ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc);
                ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
@@ -407,7 +407,7 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
                }
                free_page((unsigned long)adapter->buffer_list_addr);
                adapter->buffer_list_addr = NULL;
-       } 
+       }
 
        if(adapter->filter_list_addr != NULL) {
                if(!dma_mapping_error(adapter->filter_list_dma)) {
@@ -433,7 +433,9 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
        }
 
        for(i = 0; i<IbmVethNumBufferPools; i++)
-               ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]);
+               if (adapter->rx_buff_pool[i].active)
+                       ibmveth_free_buffer_pool(adapter,
+                                                &adapter->rx_buff_pool[i]);
 }
 
 static int ibmveth_open(struct net_device *netdev)
@@ -450,10 +452,10 @@ static int ibmveth_open(struct net_device *netdev)
 
        for(i = 0; i<IbmVethNumBufferPools; i++)
                rxq_entries += adapter->rx_buff_pool[i].size;
-    
+
        adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
        adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
+
        if(!adapter->buffer_list_addr || !adapter->filter_list_addr) {
                ibmveth_error_printk("unable to allocate filter or buffer list pages\n");
                ibmveth_cleanup(adapter);
@@ -489,9 +491,6 @@ static int ibmveth_open(struct net_device *netdev)
        adapter->rx_queue.num_slots = rxq_entries;
        adapter->rx_queue.toggle = 1;
 
-       /* call change_mtu to init the buffer pools based in initial mtu */
-       ibmveth_change_mtu(netdev, netdev->mtu);
-
        memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
        mac_address = mac_address >> 16;
 
@@ -504,7 +503,7 @@ static int ibmveth_open(struct net_device *netdev)
        ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
        ibmveth_debug_printk("receive q   @ 0x%p\n", adapter->rx_queue.queue_addr);
 
-    
+
        lpar_rc = h_register_logical_lan(adapter->vdev->unit_address,
                                         adapter->buffer_list_dma,
                                         rxq_desc.desc,
@@ -519,7 +518,18 @@ static int ibmveth_open(struct net_device *netdev)
                                     rxq_desc.desc,
                                     mac_address);
                ibmveth_cleanup(adapter);
-               return -ENONET; 
+               return -ENONET;
+       }
+
+       for(i = 0; i<IbmVethNumBufferPools; i++) {
+               if(!adapter->rx_buff_pool[i].active)
+                       continue;
+               if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[i])) {
+                       ibmveth_error_printk("unable to alloc pool\n");
+                       adapter->rx_buff_pool[i].active = 0;
+                       ibmveth_cleanup(adapter);
+                       return -ENOMEM ;
+               }
        }
 
        ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq);
@@ -547,10 +557,11 @@ static int ibmveth_close(struct net_device *netdev)
 {
        struct ibmveth_adapter *adapter = netdev->priv;
        long lpar_rc;
-    
+
        ibmveth_debug_printk("close starting\n");
 
-       netif_stop_queue(netdev);
+       if (!adapter->pool_config)
+               netif_stop_queue(netdev);
 
        free_irq(netdev->irq, netdev);
 
@@ -694,7 +705,7 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
                                             desc[5].desc,
                                             correlator);
        } while ((lpar_rc == H_BUSY) && (retry_count--));
-    
+
        if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
                int i;
                ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
@@ -780,7 +791,7 @@ static int ibmveth_poll(struct net_device *netdev, int *budget)
                /* more work to do - return that we are not done yet */
                netdev->quota -= frames_processed;
                *budget -= frames_processed;
-               return 1; 
+               return 1;
        }
 
        /* we think we are done - reenable interrupts, then check once more to make sure we are done */
@@ -806,7 +817,7 @@ static int ibmveth_poll(struct net_device *netdev, int *budget)
 }
 
 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
-{   
+{
        struct net_device *netdev = dev_instance;
        struct ibmveth_adapter *adapter = netdev->priv;
        unsigned long lpar_rc;
@@ -862,7 +873,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
                                ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
                        }
                }
-       
+
                /* re-enable filtering */
                lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
                                           IbmVethMcastEnableFiltering,
@@ -876,46 +887,22 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
 static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct ibmveth_adapter *adapter = dev->priv;
+       int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH;
        int i;
-       int prev_smaller = 1;
 
-       if ((new_mtu < 68) || 
-           (new_mtu > (pool_size[IbmVethNumBufferPools-1]) - IBMVETH_BUFF_OH))
+       if (new_mtu < IBMVETH_MAX_MTU)
                return -EINVAL;
 
+       /* Look for an active buffer pool that can hold the new MTU */
        for(i = 0; i<IbmVethNumBufferPools; i++) {
-               int activate = 0;
-               if (new_mtu > (pool_size[i]  - IBMVETH_BUFF_OH)) { 
-                       activate = 1;
-                       prev_smaller= 1;
-               } else {
-                       if (prev_smaller)
-                               activate = 1;
-                       prev_smaller= 0;
+               if (!adapter->rx_buff_pool[i].active)
+                       continue;
+               if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
+                       dev->mtu = new_mtu;
+                       return 0;
                }
-
-               if (activate && !adapter->rx_buff_pool[i].active) {
-                       struct ibmveth_buff_pool *pool = 
-                                               &adapter->rx_buff_pool[i];
-                       if(ibmveth_alloc_buffer_pool(pool)) {
-                               ibmveth_error_printk("unable to alloc pool\n");
-                               return -ENOMEM;
-                       }
-                       adapter->rx_buff_pool[i].active = 1;
-               } else if (!activate && adapter->rx_buff_pool[i].active) {
-                       adapter->rx_buff_pool[i].active = 0;
-                       h_free_logical_lan_buffer(adapter->vdev->unit_address,
-                                         (u64)pool_size[i]);
-               }
-
        }
-
-       /* kick the interrupt handler so that the new buffer pools get
-          replenished or deallocated */
-       ibmveth_interrupt(dev->irq, dev, NULL);
-
-       dev->mtu = new_mtu;
-       return 0;       
+       return -EINVAL;
 }
 
 static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
@@ -928,7 +915,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
        unsigned int *mcastFilterSize_p;
 
 
-       ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n", 
+       ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n",
                                        dev->unit_address);
 
        mac_addr_p = (unsigned char *) vio_get_attribute(dev, VETH_MAC_ADDR, 0);
@@ -937,7 +924,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
                                "attribute\n", __FILE__, __LINE__);
                return 0;
        }
-       
+
        mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0);
        if(!mcastFilterSize_p) {
                printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find "
@@ -945,7 +932,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
                                __FILE__, __LINE__);
                return 0;
        }
-       
+
        netdev = alloc_etherdev(sizeof(struct ibmveth_adapter));
 
        if(!netdev)
@@ -960,13 +947,14 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
        adapter->vdev = dev;
        adapter->netdev = netdev;
        adapter->mcastFilterSize= *mcastFilterSize_p;
-       
+       adapter->pool_config = 0;
+
        /*      Some older boxes running PHYP non-natively have an OF that
-               returns a 8-byte local-mac-address field (and the first 
+               returns a 8-byte local-mac-address field (and the first
                2 bytes have to be ignored) while newer boxes' OF return
-               a 6-byte field. Note that IEEE 1275 specifies that 
+               a 6-byte field. Note that IEEE 1275 specifies that
                local-mac-address must be a 6-byte field.
-               The RPA doc specifies that the first byte must be 10b, so 
+               The RPA doc specifies that the first byte must be 10b, so
                we'll just look for it to solve this 8 vs. 6 byte field issue */
 
        if ((*mac_addr_p & 0x3) != 0x02)
@@ -976,7 +964,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
        memcpy(&adapter->mac_addr, mac_addr_p, 6);
 
        adapter->liobn = dev->iommu_table->it_index;
-       
+
        netdev->irq = dev->irq;
        netdev->open               = ibmveth_open;
        netdev->poll               = ibmveth_poll;
@@ -989,14 +977,21 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
        netdev->ethtool_ops           = &netdev_ethtool_ops;
        netdev->change_mtu         = ibmveth_change_mtu;
        SET_NETDEV_DEV(netdev, &dev->dev);
-       netdev->features |= NETIF_F_LLTX; 
+       netdev->features |= NETIF_F_LLTX;
        spin_lock_init(&adapter->stats_lock);
 
        memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
 
-       for(i = 0; i<IbmVethNumBufferPools; i++)
-               ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i, 
-                                        pool_count[i], pool_size[i]);
+       for(i = 0; i<IbmVethNumBufferPools; i++) {
+               struct kobject *kobj = &adapter->rx_buff_pool[i].kobj;
+               ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i,
+                                        pool_count[i], pool_size[i],
+                                        pool_active[i]);
+               kobj->parent = &dev->dev.kobj;
+               sprintf(kobj->name, "pool%d", i);
+               kobj->ktype = &ktype_veth_pool;
+               kobject_register(kobj);
+       }
 
        ibmveth_debug_printk("adapter @ 0x%p\n", adapter);
 
@@ -1025,6 +1020,10 @@ static int __devexit ibmveth_remove(struct vio_dev *dev)
 {
        struct net_device *netdev = dev->dev.driver_data;
        struct ibmveth_adapter *adapter = netdev->priv;
+       int i;
+
+       for(i = 0; i<IbmVethNumBufferPools; i++)
+               kobject_unregister(&adapter->rx_buff_pool[i].kobj);
 
        unregister_netdev(netdev);
 
@@ -1048,7 +1047,7 @@ static void ibmveth_proc_unregister_driver(void)
        remove_proc_entry(IBMVETH_PROC_DIR, NULL);
 }
 
-static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) 
+static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos)
 {
        if (*pos == 0) {
                return (void *)1;
@@ -1063,18 +1062,18 @@ static void *ibmveth_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        return NULL;
 }
 
-static void ibmveth_seq_stop(struct seq_file *seq, void *v) 
+static void ibmveth_seq_stop(struct seq_file *seq, void *v)
 {
 }
 
-static int ibmveth_seq_show(struct seq_file *seq, void *v) 
+static int ibmveth_seq_show(struct seq_file *seq, void *v)
 {
        struct ibmveth_adapter *adapter = seq->private;
        char *current_mac = ((char*) &adapter->netdev->dev_addr);
        char *firmware_mac = ((char*) &adapter->mac_addr) ;
 
        seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version);
-       
+
        seq_printf(seq, "Unit Address:    0x%x\n", adapter->vdev->unit_address);
        seq_printf(seq, "LIOBN:           0x%lx\n", adapter->liobn);
        seq_printf(seq, "Current MAC:     %02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -1083,7 +1082,7 @@ static int ibmveth_seq_show(struct seq_file *seq, void *v)
        seq_printf(seq, "Firmware MAC:    %02X:%02X:%02X:%02X:%02X:%02X\n",
                   firmware_mac[0], firmware_mac[1], firmware_mac[2],
                   firmware_mac[3], firmware_mac[4], firmware_mac[5]);
-       
+
        seq_printf(seq, "\nAdapter Statistics:\n");
        seq_printf(seq, "  TX:  skbuffs linearized:          %ld\n", adapter->tx_linearized);
        seq_printf(seq, "       multi-descriptor sends:      %ld\n", adapter->tx_multidesc_send);
@@ -1095,7 +1094,7 @@ static int ibmveth_seq_show(struct seq_file *seq, void *v)
        seq_printf(seq, "       add buffer failures:         %ld\n", adapter->replenish_add_buff_failure);
        seq_printf(seq, "       invalid buffers:             %ld\n", adapter->rx_invalid_buffer);
        seq_printf(seq, "       no buffers:                  %ld\n", adapter->rx_no_buffer);
-       
+
        return 0;
 }
 static struct seq_operations ibmveth_seq_ops = {
@@ -1153,11 +1152,11 @@ static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
 }
 
 #else /* CONFIG_PROC_FS */
-static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) 
+static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
 {
 }
 
-static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) 
+static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
 {
 }
 static void ibmveth_proc_register_driver(void)
@@ -1169,6 +1168,132 @@ static void ibmveth_proc_unregister_driver(void)
 }
 #endif /* CONFIG_PROC_FS */
 
+static struct attribute veth_active_attr;
+static struct attribute veth_num_attr;
+static struct attribute veth_size_attr;
+
+static ssize_t veth_pool_show(struct kobject * kobj,
+                              struct attribute * attr, char * buf)
+{
+       struct ibmveth_buff_pool *pool = container_of(kobj,
+                                                     struct ibmveth_buff_pool,
+                                                     kobj);
+
+       if (attr == &veth_active_attr)
+               return sprintf(buf, "%d\n", pool->active);
+       else if (attr == &veth_num_attr)
+               return sprintf(buf, "%d\n", pool->size);
+       else if (attr == &veth_size_attr)
+               return sprintf(buf, "%d\n", pool->buff_size);
+       return 0;
+}
+
+static ssize_t veth_pool_store(struct kobject * kobj, struct attribute * attr,
+const char * buf, size_t count)
+{
+       struct ibmveth_buff_pool *pool = container_of(kobj,
+                                                     struct ibmveth_buff_pool,
+                                                     kobj);
+       struct net_device *netdev =
+           container_of(kobj->parent, struct device, kobj)->driver_data;
+       struct ibmveth_adapter *adapter = netdev->priv;
+       long value = simple_strtol(buf, NULL, 10);
+       long rc;
+
+       if (attr == &veth_active_attr) {
+               if (value && !pool->active) {
+                       if(ibmveth_alloc_buffer_pool(pool)) {
+                                ibmveth_error_printk("unable to alloc pool\n");
+                                return -ENOMEM;
+                        }
+                       pool->active = 1;
+                       adapter->pool_config = 1;
+                       ibmveth_close(netdev);
+                       adapter->pool_config = 0;
+                       if ((rc = ibmveth_open(netdev)))
+                               return rc;
+               } else if (!value && pool->active) {
+                       int mtu = netdev->mtu + IBMVETH_BUFF_OH;
+                       int i;
+                       /* Make sure there is a buffer pool with buffers that
+                          can hold a packet of the size of the MTU */
+                       for(i = 0; i<IbmVethNumBufferPools; i++) {
+                               if (pool == &adapter->rx_buff_pool[i])
+                                       continue;
+                               if (!adapter->rx_buff_pool[i].active)
+                                       continue;
+                               if (mtu < adapter->rx_buff_pool[i].buff_size) {
+                                       pool->active = 0;
+                                       h_free_logical_lan_buffer(adapter->
+                                                                 vdev->
+                                                                 unit_address,
+                                                                 pool->
+                                                                 buff_size);
+                               }
+                       }
+                       if (pool->active) {
+                               ibmveth_error_printk("no active pool >= MTU\n");
+                               return -EPERM;
+                       }
+               }
+       } else if (attr == &veth_num_attr) {
+               if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
+                       return -EINVAL;
+               else {
+                       adapter->pool_config = 1;
+                       ibmveth_close(netdev);
+                       adapter->pool_config = 0;
+                       pool->size = value;
+                       if ((rc = ibmveth_open(netdev)))
+                               return rc;
+               }
+       } else if (attr == &veth_size_attr) {
+               if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE)
+                       return -EINVAL;
+               else {
+                       adapter->pool_config = 1;
+                       ibmveth_close(netdev);
+                       adapter->pool_config = 0;
+                       pool->buff_size = value;
+                       if ((rc = ibmveth_open(netdev)))
+                               return rc;
+               }
+       }
+
+       /* kick the interrupt handler to allocate/deallocate pools */
+       ibmveth_interrupt(netdev->irq, netdev, NULL);
+       return count;
+}
+
+
+#define ATTR(_name, _mode)      \
+        struct attribute veth_##_name##_attr = {               \
+        .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \
+        };
+
+static ATTR(active, 0644);
+static ATTR(num, 0644);
+static ATTR(size, 0644);
+
+static struct attribute * veth_pool_attrs[] = {
+       &veth_active_attr,
+       &veth_num_attr,
+       &veth_size_attr,
+       NULL,
+};
+
+static struct sysfs_ops veth_pool_ops = {
+       .show   = veth_pool_show,
+       .store  = veth_pool_store,
+};
+
+static struct kobj_type ktype_veth_pool = {
+       .release        = NULL,
+       .sysfs_ops      = &veth_pool_ops,
+       .default_attrs  = veth_pool_attrs,
+};
+
+
 static struct vio_device_id ibmveth_device_table[] __devinitdata= {
        { "network", "IBM,l-lan"},
        { "", "" }
@@ -1198,7 +1323,7 @@ static void __exit ibmveth_module_exit(void)
 {
        vio_unregister_driver(&ibmveth_driver);
        ibmveth_proc_unregister_driver();
-}      
+}
 
 module_init(ibmveth_module_init);
 module_exit(ibmveth_module_exit);
index 46919a814fcac44fce8fb60b0fec6530d31e4c82..8385bf8365071af5a20dc6d85e9035002ab8b278 100644 (file)
 
 #define IbmVethNumBufferPools 5
 #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
+#define IBMVETH_MAX_MTU 68
+#define IBMVETH_MAX_POOL_COUNT 4096
+#define IBMVETH_MAX_BUF_SIZE (1024 * 128)
 
-/* pool_size should be sorted */
 static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
 static int pool_count[] = { 256, 768, 256, 256, 256 };
+static int pool_active[] = { 1, 1, 0, 0, 0};
 
 #define IBM_VETH_INVALID_MAP ((u16)0xffff)
 
@@ -94,6 +97,7 @@ struct ibmveth_buff_pool {
     dma_addr_t *dma_addr;
     struct sk_buff **skbuff;
     int active;
+    struct kobject kobj;
 };
 
 struct ibmveth_rx_q {
@@ -118,6 +122,7 @@ struct ibmveth_adapter {
     dma_addr_t filter_list_dma;
     struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools];
     struct ibmveth_rx_q rx_queue;
+    int pool_config;
 
     /* adapter specific stats */
     u64 replenish_task_cycles;
@@ -134,7 +139,7 @@ struct ibmveth_adapter {
     spinlock_t stats_lock;
 };
 
-struct ibmveth_buf_desc_fields {       
+struct ibmveth_buf_desc_fields {
     u32 valid : 1;
     u32 toggle : 1;
     u32 reserved : 6;
@@ -143,7 +148,7 @@ struct ibmveth_buf_desc_fields {
 };
 
 union ibmveth_buf_desc {
-    u64 desc;  
+    u64 desc;
     struct ibmveth_buf_desc_fields fields;
 };
 
index 31fb2d75dc447a79bffa71f86d728425b68472a1..2e222ef91e224892c675766831fddc851e40f017 100644 (file)
@@ -76,13 +76,13 @@ static void ri_tasklet(unsigned long dev)
        dp->st_task_enter++;
        if ((skb = skb_peek(&dp->tq)) == NULL) {
                dp->st_txq_refl_try++;
-               if (spin_trylock(&_dev->xmit_lock)) {
+               if (netif_tx_trylock(_dev)) {
                        dp->st_rxq_enter++;
                        while ((skb = skb_dequeue(&dp->rq)) != NULL) {
                                skb_queue_tail(&dp->tq, skb);
                                dp->st_rx2tx_tran++;
                        }
-                       spin_unlock(&_dev->xmit_lock);
+                       netif_tx_unlock(_dev);
                } else {
                        /* reschedule */
                        dp->st_rxq_notenter++;
@@ -110,7 +110,7 @@ static void ri_tasklet(unsigned long dev)
                }
        }
 
-       if (spin_trylock(&_dev->xmit_lock)) {
+       if (netif_tx_trylock(_dev)) {
                dp->st_rxq_check++;
                if ((skb = skb_peek(&dp->rq)) == NULL) {
                        dp->tasklet_pending = 0;
@@ -118,10 +118,10 @@ static void ri_tasklet(unsigned long dev)
                                netif_wake_queue(_dev);
                } else {
                        dp->st_rxq_rsch++;
-                       spin_unlock(&_dev->xmit_lock);
+                       netif_tx_unlock(_dev);
                        goto resched;
                }
-               spin_unlock(&_dev->xmit_lock);
+               netif_tx_unlock(_dev);
        } else {
 resched:
                dp->tasklet_pending = 1;
index 5e6d007529905744ce7e0f3d0e5a67b09aa469cc..d2ce4896abff24605d8b4ab37cf221f6e78f8107 100644 (file)
@@ -33,7 +33,7 @@ config DONGLE
 
 config ESI_DONGLE
        tristate "ESI JetEye PC dongle"
-       depends on DONGLE && IRDA
+       depends on IRTTY_SIR && DONGLE && IRDA
        help
          Say Y here if you want to build support for the Extended Systems
          JetEye PC dongle.  To compile it as a module, choose M here. The ESI
@@ -44,7 +44,7 @@ config ESI_DONGLE
 
 config ACTISYS_DONGLE
        tristate "ACTiSYS IR-220L and IR220L+ dongle"
-       depends on DONGLE && IRDA
+       depends on IRTTY_SIR && DONGLE && IRDA
        help
          Say Y here if you want to build support for the ACTiSYS IR-220L and
          IR220L+ dongles.  To compile it as a module, choose M here. The
@@ -55,7 +55,7 @@ config ACTISYS_DONGLE
 
 config TEKRAM_DONGLE
        tristate "Tekram IrMate 210B dongle"
-       depends on DONGLE && IRDA
+       depends on IRTTY_SIR && DONGLE && IRDA
        help
          Say Y here if you want to build support for the Tekram IrMate 210B
          dongle.  To compile it as a module, choose M here. The Tekram dongle
@@ -66,7 +66,7 @@ config TEKRAM_DONGLE
 
 config TOIM3232_DONGLE
        tristate "TOIM3232 IrDa dongle"
-       depends on DONGLE && IRDA
+       depends on IRTTY_SIR && DONGLE && IRDA
        help
          Say Y here if you want to build support for the Vishay/Temic
          TOIM3232 and TOIM4232 based dongles.
@@ -74,7 +74,7 @@ config TOIM3232_DONGLE
 
 config LITELINK_DONGLE
        tristate "Parallax LiteLink dongle"
-       depends on DONGLE && IRDA
+       depends on IRTTY_SIR && DONGLE && IRDA
        help
          Say Y here if you want to build support for the Parallax Litelink
          dongle.  To compile it as a module, choose M here.  The Parallax
@@ -85,7 +85,7 @@ config LITELINK_DONGLE
 
 config MA600_DONGLE
        tristate "Mobile Action MA600 dongle"
-       depends on DONGLE && IRDA && EXPERIMENTAL
+       depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
        help
          Say Y here if you want to build support for the Mobile Action MA600
          dongle.  To compile it as a module, choose M here. The MA600 dongle
@@ -98,7 +98,7 @@ config MA600_DONGLE
 
 config GIRBIL_DONGLE
        tristate "Greenwich GIrBIL dongle"
-       depends on DONGLE && IRDA && EXPERIMENTAL
+       depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
        help
          Say Y here if you want to build support for the Greenwich GIrBIL
          dongle.  If you want to compile it as a module, choose M here.
@@ -109,7 +109,7 @@ config GIRBIL_DONGLE
 
 config MCP2120_DONGLE
        tristate "Microchip MCP2120"
-       depends on DONGLE && IRDA && EXPERIMENTAL
+       depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
        help
          Say Y here if you want to build support for the Microchip MCP2120
          dongle.  If you want to compile it as a module, choose M here.
@@ -123,7 +123,7 @@ config MCP2120_DONGLE
 
 config OLD_BELKIN_DONGLE
        tristate "Old Belkin dongle"
-       depends on DONGLE && IRDA && EXPERIMENTAL
+       depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
        help
          Say Y here if you want to build support for the Adaptec Airport 1000
          and 2000 dongles.  If you want to compile it as a module, choose
@@ -132,7 +132,7 @@ config OLD_BELKIN_DONGLE
 
 config ACT200L_DONGLE
        tristate "ACTiSYS IR-200L dongle"
-       depends on DONGLE && IRDA && EXPERIMENTAL
+       depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
        help
          Say Y here if you want to build support for the ACTiSYS IR-200L
          dongle. If you want to compile it as a module, choose M here.
@@ -417,5 +417,20 @@ config PXA_FICP
          available capabilities may vary from one PXA2xx target to
          another.
 
+config MCS_FIR
+       tristate "MosChip MCS7780 IrDA-USB dongle"
+       depends on IRDA && USB && EXPERIMENTAL
+       help
+         Say Y or M here if you want to build support for the MosChip
+         MCS7780 IrDA-USB bridge device driver.
+
+         USB bridge based on the MosChip MCS7780 don't conform to the
+         IrDA-USB device class specification, and therefore need their
+         own specific driver. Those dongles support SIR and FIR (4Mbps)
+         speeds.
+
+         To compile it as a module, choose M here: the module will be called
+         mcs7780.
+
 endmenu
 
index c1ce2398efeaa0854f98cef201c4aa6f55144a7b..5be09f1b9ee2f4b8dc056540342955405b72b215 100644 (file)
@@ -19,6 +19,7 @@ obj-$(CONFIG_ALI_FIR)         += ali-ircc.o
 obj-$(CONFIG_VLSI_FIR)         += vlsi_ir.o
 obj-$(CONFIG_VIA_FIR)          += via-ircc.o
 obj-$(CONFIG_PXA_FICP)         += pxaficp_ir.o
+obj-$(CONFIG_MCS_FIR)          += mcs7780.o
 # Old dongle drivers for old SIR drivers
 obj-$(CONFIG_ESI_DONGLE_OLD)           += esi.o
 obj-$(CONFIG_TEKRAM_DONGLE_OLD)        += tekram.o
index 2e7882eb7d6fb02a1d980c2467e638f317a1c915..bf1fca5a3fa056b3298be53d8119c27c45dd787b 100644 (file)
 #include <linux/rtnetlink.h>
 #include <linux/serial_reg.h>
 #include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 
-#include <linux/pm.h>
-#include <linux/pm_legacy.h>
-
 #include <net/irda/wrapper.h>
 #include <net/irda/irda.h>
 #include <net/irda/irda_device.h>
 #define CHIP_IO_EXTENT 8
 #define BROKEN_DONGLE_ID
 
-static char *driver_name = "ali-ircc";
+#define ALI_IRCC_DRIVER_NAME "ali-ircc"
+
+/* Power Management */
+static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state);
+static int ali_ircc_resume(struct platform_device *dev);
+
+static struct platform_driver ali_ircc_driver = {
+       .suspend        = ali_ircc_suspend,
+       .resume         = ali_ircc_resume,
+       .driver         = {
+               .name   = ALI_IRCC_DRIVER_NAME,
+       },
+};
 
 /* Module parameters */
 static int qos_mtt_bits = 0x07;  /* 1 ms or more */
@@ -97,10 +107,7 @@ static int  ali_ircc_is_receiving(struct ali_ircc_cb *self);
 static int  ali_ircc_net_open(struct net_device *dev);
 static int  ali_ircc_net_close(struct net_device *dev);
 static int  ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static int  ali_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
 static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud);
-static void ali_ircc_suspend(struct ali_ircc_cb *self);
-static void ali_ircc_wakeup(struct ali_ircc_cb *self);
 static struct net_device_stats *ali_ircc_net_get_stats(struct net_device *dev);
 
 /* SIR function */
@@ -145,6 +152,14 @@ static int __init ali_ircc_init(void)
        int i = 0;
        
        IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
+
+       ret = platform_driver_register(&ali_ircc_driver);
+        if (ret) {
+                IRDA_ERROR("%s, Can't register driver!\n",
+                          ALI_IRCC_DRIVER_NAME);
+                return ret;
+        }
+
        
        /* Probe for all the ALi chipsets we know about */
        for (chip= chips; chip->name; chip++, i++) 
@@ -214,6 +229,10 @@ static int __init ali_ircc_init(void)
        }               
                
        IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);                                                 
+
+       if (ret)
+               platform_driver_unregister(&ali_ircc_driver);
+
        return ret;
 }
 
@@ -228,14 +247,14 @@ static void __exit ali_ircc_cleanup(void)
        int i;
 
        IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); 
-       
-       pm_unregister_all(ali_ircc_pmproc);
 
        for (i=0; i < 4; i++) {
                if (dev_self[i])
                        ali_ircc_close(dev_self[i]);
        }
        
+       platform_driver_unregister(&ali_ircc_driver);
+
        IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
 }
 
@@ -249,7 +268,6 @@ static int ali_ircc_open(int i, chipio_t *info)
 {
        struct net_device *dev;
        struct ali_ircc_cb *self;
-       struct pm_dev *pmdev;
        int dongle_id;
        int err;
                        
@@ -284,7 +302,8 @@ static int ali_ircc_open(int i, chipio_t *info)
         self->io.fifo_size = 16;               /* SIR: 16, FIR: 32 Benjamin 2000/11/1 */
        
        /* Reserve the ioports that we need */
-       if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) {
+       if (!request_region(self->io.fir_base, self->io.fir_ext,
+                           ALI_IRCC_DRIVER_NAME)) {
                IRDA_WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__,
                        self->io.fir_base);
                err = -ENODEV;
@@ -354,13 +373,10 @@ static int ali_ircc_open(int i, chipio_t *info)
 
        /* Check dongle id */
        dongle_id = ali_ircc_read_dongle_id(i, info);
-       IRDA_MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__, driver_name, dongle_types[dongle_id]);
+       IRDA_MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__,
+                    ALI_IRCC_DRIVER_NAME, dongle_types[dongle_id]);
                
        self->io.dongle_id = dongle_id;
-       
-        pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, ali_ircc_pmproc);
-        if (pmdev)
-                pmdev->data = self;
 
        IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
        
@@ -548,12 +564,11 @@ static int ali_ircc_setup(chipio_t *info)
        /* Should be 0x00 in the M1535/M1535D */
        if(version != 0x00)
        {
-               IRDA_ERROR("%s, Wrong chip version %02x\n", driver_name, version);
+               IRDA_ERROR("%s, Wrong chip version %02x\n",
+                          ALI_IRCC_DRIVER_NAME, version);
                return -1;
        }
        
-       // IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, info->cfg_base);
-       
        /* Set FIR FIFO Threshold Register */
        switch_bank(iobase, BANK1);
        outb(RX_FIFO_Threshold, iobase+FIR_FIFO_TR);
@@ -583,7 +598,8 @@ static int ali_ircc_setup(chipio_t *info)
        /* Switch to SIR space */
        FIR2SIR(iobase);
        
-       IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n", driver_name);
+       IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n",
+                    ALI_IRCC_DRIVER_NAME);
        
        /* Enable receive interrupts */ 
        // outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM
@@ -647,7 +663,8 @@ static irqreturn_t ali_ircc_interrupt(int irq, void *dev_id,
        IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
                
        if (!dev) {
-               IRDA_WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
+               IRDA_WARNING("%s: irq %d for unknown device.\n",
+                            ALI_IRCC_DRIVER_NAME, irq);
                return IRQ_NONE;
        }       
        
@@ -1328,7 +1345,8 @@ static int ali_ircc_net_open(struct net_device *dev)
        /* Request IRQ and install Interrupt Handler */
        if (request_irq(self->io.irq, ali_ircc_interrupt, 0, dev->name, dev)) 
        {
-               IRDA_WARNING("%s, unable to allocate irq=%d\n", driver_name,
+               IRDA_WARNING("%s, unable to allocate irq=%d\n",
+                            ALI_IRCC_DRIVER_NAME,
                             self->io.irq);
                return -EAGAIN;
        }
@@ -1338,7 +1356,8 @@ static int ali_ircc_net_open(struct net_device *dev)
         * failure.
         */
        if (request_dma(self->io.dma, dev->name)) {
-               IRDA_WARNING("%s, unable to allocate dma=%d\n", driver_name,
+               IRDA_WARNING("%s, unable to allocate dma=%d\n",
+                            ALI_IRCC_DRIVER_NAME,
                             self->io.dma);
                free_irq(self->io.irq, self);
                return -EAGAIN;
@@ -2108,61 +2127,38 @@ static struct net_device_stats *ali_ircc_net_get_stats(struct net_device *dev)
        return &self->stats;
 }
 
-static void ali_ircc_suspend(struct ali_ircc_cb *self)
+static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state)
 {
-       IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
+       struct ali_ircc_cb *self = platform_get_drvdata(dev);
        
-       IRDA_MESSAGE("%s, Suspending\n", driver_name);
+       IRDA_MESSAGE("%s, Suspending\n", ALI_IRCC_DRIVER_NAME);
 
        if (self->io.suspended)
-               return;
+               return 0;
 
        ali_ircc_net_close(self->netdev);
 
        self->io.suspended = 1;
        
-       IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );       
+       return 0;
 }
 
-static void ali_ircc_wakeup(struct ali_ircc_cb *self)
+static int ali_ircc_resume(struct platform_device *dev)
 {
-       IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
+       struct ali_ircc_cb *self = platform_get_drvdata(dev);
        
        if (!self->io.suspended)
-               return;
+               return 0;
        
        ali_ircc_net_open(self->netdev);
        
-       IRDA_MESSAGE("%s, Waking up\n", driver_name);
+       IRDA_MESSAGE("%s, Waking up\n", ALI_IRCC_DRIVER_NAME);
 
        self->io.suspended = 0;
-       
-       IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );       
-}
 
-static int ali_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
-        struct ali_ircc_cb *self = (struct ali_ircc_cb*) dev->data;
-        
-        IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
-       
-        if (self) {
-                switch (rqst) {
-                case PM_SUSPEND:
-                        ali_ircc_suspend(self);
-                        break;
-                case PM_RESUME:
-                        ali_ircc_wakeup(self);
-                        break;
-                }
-        }
-        
-        IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );      
-        
        return 0;
 }
 
-
 /* ALi Chip Function */
 
 static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable)
index cd87593e4e8ae6cfe464a5926c91d1db9469b5e0..844fa74ac9ec7f6544c66fa507699d2c94fede7e 100644 (file)
@@ -83,9 +83,9 @@ static struct usb_device_id dongles[] = {
        /* Extended Systems, Inc.,  XTNDAccess IrDA USB (ESI-9685) */
        { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
        /* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */
-       { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
-       { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
-       { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
+       { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR421X | IUC_SPEED_BUG },
+       { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR421X | IUC_SPEED_BUG },
+       { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR421X | IUC_SPEED_BUG },
        { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
          USB_DEVICE_ID_MATCH_INT_SUBCLASS,
          .bInterfaceClass = USB_CLASS_APP_SPEC,
@@ -154,7 +154,7 @@ static void irda_usb_build_header(struct irda_usb_cb *self,
         * and if either speed or xbofs (or both) needs
         * to be changed.
         */
-       if (self->capability & IUC_STIR_4210 &&
+       if (self->capability & IUC_STIR421X &&
            ((self->new_speed != -1) || (self->new_xbofs != -1))) {
 
                /* With STIR421x, speed and xBOFs must be set at the same
@@ -318,7 +318,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
        /* Set the new speed and xbofs in this fake frame */
        irda_usb_build_header(self, frame, 1);
 
-       if ( self->capability & IUC_STIR_4210 ) {
+       if (self->capability & IUC_STIR421X) {
                if (frame[0] == 0) return ; // do nothing if no change
                frame[1] = 0; // other parameters don't change here
                frame[2] = 0;
@@ -455,7 +455,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
 
        /* Change setting for next frame */
 
-       if ( self->capability & IUC_STIR_4210 ) {
+       if (self->capability & IUC_STIR421X) {
                __u8 turnaround_time;
                __u8* frame;
                turnaround_time = get_turnaround_time( skb );
@@ -897,10 +897,13 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
        docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);
 
        /* Allocate a new skb */
-       if ( self->capability & IUC_STIR_4210 )
-               newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER);
+       if (self->capability & IUC_STIR421X)
+               newskb = dev_alloc_skb(docopy ? urb->actual_length :
+                                      IRDA_SKB_MAX_MTU +
+                                      USB_IRDA_STIR421X_HEADER);
        else
-               newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
+               newskb = dev_alloc_skb(docopy ? urb->actual_length :
+                                      IRDA_SKB_MAX_MTU);
 
        if (!newskb)  {
                self->stats.rx_dropped++;
@@ -1022,188 +1025,140 @@ static int irda_usb_is_receiving(struct irda_usb_cb *self)
        return 0; /* For now */
 }
 
-
-#define STIR421X_PATCH_PRODUCT_VERSION_STR       "Product Version: "
-#define STIR421X_PATCH_COMPONENT_VERSION_STR     "Component Version: "
-#define STIR421X_PATCH_DATA_TAG_STR              "STMP"
-#define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET   512     /* version info is before here */
-#define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET     512     /* patch image starts before here */
-#define STIR421X_PATCH_FILE_END_OF_HEADER_TAG    0x1A    /* marks end of patch file header (PC DOS text file EOF character) */
+#define STIR421X_PATCH_PRODUCT_VER     "Product Version: "
+#define STIR421X_PATCH_STMP_TAG        "STMP"
+#define STIR421X_PATCH_CODE_OFFSET     512 /* patch image starts before here */
+/* marks end of patch file header (PC DOS text file EOF character) */
+#define STIR421X_PATCH_END_OF_HDR_TAG  0x1A
+#define STIR421X_PATCH_BLOCK_SIZE      1023
 
 /*
- * Known firmware patches for STIR421x dongles
+ * Function stir421x_fwupload (struct irda_usb_cb *self,
+ *                             unsigned char *patch,
+ *                             const unsigned int patch_len)
+ *
+ *   Upload firmware code to SigmaTel 421X IRDA-USB dongle
  */
-static char * stir421x_patches[] = {
-       "42101001.sb",
-       "42101002.sb",
-};
-
-static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len)
+static int stir421x_fw_upload(struct irda_usb_cb *self,
+                            unsigned char *patch,
+                            const unsigned int patch_len)
 {
-       unsigned int version_offset;
-       unsigned long version_major, version_minor, version_build;
-       unsigned char * version_start;
-       int version_found = 0;
-
-       for (version_offset = 0;
-            version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG;
-            version_offset++) {
-               if (!memcmp(patch + version_offset,
-                           STIR421X_PATCH_PRODUCT_VERSION_STR,
-                           sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) {
-                                   version_found = 1;
-                                   version_start = patch +
-                                           version_offset +
-                                           sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1;
-                                   break;
-               }
+        int ret = -ENOMEM;
+        int actual_len = 0;
+        unsigned int i;
+        unsigned int block_size = 0;
+        unsigned char *patch_block;
+
+        patch_block = kzalloc(STIR421X_PATCH_BLOCK_SIZE, GFP_KERNEL);
+       if (patch_block == NULL)
+               return -ENOMEM;
+
+       /* break up patch into 1023-byte sections */
+       for (i = 0; i < patch_len; i += block_size) {
+               block_size = patch_len - i;
+
+               if (block_size > STIR421X_PATCH_BLOCK_SIZE)
+                       block_size = STIR421X_PATCH_BLOCK_SIZE;
+
+               /* upload the patch section */
+               memcpy(patch_block, patch + i, block_size);
+
+               ret = usb_bulk_msg(self->usbdev,
+                                  usb_sndbulkpipe(self->usbdev,
+                                                  self->bulk_out_ep),
+                                  patch_block, block_size,
+                                  &actual_len, msecs_to_jiffies(500));
+               IRDA_DEBUG(3,"%s(): Bulk send %u bytes, ret=%d\n",
+                          __FUNCTION__, actual_len, ret);
+
+               if (ret < 0)
+                       break;
        }
 
-       /* We couldn't find a product version on this patch */
-       if (!version_found)
-               return -EINVAL;
-
-       /* Let's check if the product version is dotted */
-       if (version_start[3] != '.' ||
-           version_start[7] != '.')
-               return -EINVAL;
-
-       version_major = simple_strtoul(version_start, NULL, 10);
-       version_minor = simple_strtoul(version_start + 4, NULL, 10);
-       version_build = simple_strtoul(version_start + 8, NULL, 10);
-
-       IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n",
-                  __FUNCTION__,
-                  version_major, version_minor, version_build);
-
-       return (((version_major) << 12) +
-               ((version_minor) << 8) +
-               ((version_build / 10) << 4) +
-               (version_build % 10));
-
-}
-
-
-static int stir421x_upload_patch (struct irda_usb_cb *self,
-                                 unsigned char * patch,
-                                 const unsigned int patch_len)
-{
-    int retval = 0;
-    int actual_len;
-    unsigned int i = 0, download_amount = 0;
-    unsigned char * patch_chunk;
-
-    IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__);
-
-    patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL);
-    if (patch_chunk == NULL)
-           return -ENOMEM;
-
-    /* break up patch into 1023-byte sections */
-    for (i = 0; retval >= 0 && i < patch_len; i += download_amount) {
-           download_amount = patch_len - i;
-           if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE)
-                   download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE;
-
-           /* download the patch section */
-           memcpy(patch_chunk, patch + i, download_amount);
-
-           retval = usb_bulk_msg (self->usbdev,
-                                  usb_sndbulkpipe (self->usbdev,
-                                                   self->bulk_out_ep),
-                                  patch_chunk, download_amount,
-                                  &actual_len, msecs_to_jiffies (500));
-           IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__,
-                       actual_len);
-           if (retval == 0)
-                   mdelay(10);
-    }
-
-    kfree(patch_chunk);
-
-    if (i != patch_len) {
-           IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n",
-                      __FUNCTION__, i, patch_len);
-           retval = -EIO;
-    }
-
-    if (retval < 0)
-           /* todo - mark device as not ready */
-           IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n",
-                       __FUNCTION__, retval);
-
-    return retval;
-}
+       kfree(patch_block);
 
+        return ret;
+ }
 
+/*
+ * Function stir421x_patch_device(struct irda_usb_cb *self)
+ *
+ * Get a firmware code from userspase using hotplug request_firmware() call
+  */
 static int stir421x_patch_device(struct irda_usb_cb *self)
 {
-       unsigned int i, patch_found = 0, data_found = 0, data_offset;
-       int patch_version, ret = 0;
-       const struct firmware *fw_entry;
-
-       for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) {
-               if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) {
-                       IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]);
-                       continue;
-               }
-
-                /* We found a patch from userspace */
-               patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size);
-
-               if (patch_version < 0) {
-                       /* Couldn't fetch a version, let's move on to the next file */
-                       IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__);
-                       ret = patch_version;
-                       release_firmware(fw_entry);
-                       continue;
-               }
-
-               if (patch_version != self->usbdev->descriptor.bcdDevice) {
-                       /* Patch version and device don't match */
-                       IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n",
-                                   __FUNCTION__,
-                                   patch_version, self->usbdev->descriptor.bcdDevice);
-                       ret = -EINVAL;
-                       release_firmware(fw_entry);
-                       continue;
-               }
-
-               /* If we're here, we've found a correct patch */
-               patch_found = 1;
-               break;
-
-       }
-
-       /* We couldn't find a valid firmware, let's leave */
-       if (!patch_found)
-               return ret;
-
-       /* The actual image starts after the "STMP" keyword */
-       for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) {
-               if (!memcmp(fw_entry->data + data_offset,
-                           STIR421X_PATCH_DATA_TAG_STR,
-                           sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) {
-                       IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n",
-                                  __FUNCTION__, data_offset);
-                       data_found = 1;
-                       break;
-               }
-       }
-
-       /* We couldn't find "STMP" from the header */
-       if (!data_found)
-               return -EINVAL;
-
-       /* Let's upload the patch to the target */
-       ret = stir421x_upload_patch(self,
-                                   &fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)],
-                                   fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)));
-
-       release_firmware(fw_entry);
-
-       return ret;
-
+        unsigned int i;
+        int ret;
+        char stir421x_fw_name[11];
+        const struct firmware *fw;
+        unsigned char *fw_version_ptr; /* pointer to version string */
+       unsigned long fw_version = 0;
+
+        /*
+         * Known firmware patch file names for STIR421x dongles
+         * are "42101001.sb" or "42101002.sb"
+         */
+        sprintf(stir421x_fw_name, "4210%4X.sb",
+                self->usbdev->descriptor.bcdDevice);
+        ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev);
+        if (ret < 0)
+                return ret;
+
+        /* We get a patch from userspace */
+        IRDA_MESSAGE("%s(): Received firmware %s (%u bytes)\n",
+                     __FUNCTION__, stir421x_fw_name, fw->size);
+
+        ret = -EINVAL;
+
+       /* Get the bcd product version */
+        if (!memcmp(fw->data, STIR421X_PATCH_PRODUCT_VER,
+                    sizeof(STIR421X_PATCH_PRODUCT_VER) - 1)) {
+                fw_version_ptr = fw->data +
+                       sizeof(STIR421X_PATCH_PRODUCT_VER) - 1;
+
+                /* Let's check if the product version is dotted */
+                if (fw_version_ptr[3] == '.' &&
+                   fw_version_ptr[7] == '.') {
+                       unsigned long major, minor, build;
+                       major = simple_strtoul(fw_version_ptr, NULL, 10);
+                       minor = simple_strtoul(fw_version_ptr + 4, NULL, 10);
+                       build = simple_strtoul(fw_version_ptr + 8, NULL, 10);
+
+                       fw_version = (major << 12)
+                               + (minor << 8)
+                               + ((build / 10) << 4)
+                               + (build % 10);
+
+                       IRDA_DEBUG(3, "%s(): Firmware Product version %ld\n",
+                                   __FUNCTION__, fw_version);
+                }
+        }
+
+        if (self->usbdev->descriptor.bcdDevice == fw_version) {
+                /*
+                * If we're here, we've found a correct patch
+                 * The actual image starts after the "STMP" keyword
+                 * so forward to the firmware header tag
+                 */
+                for (i = 0; (fw->data[i] != STIR421X_PATCH_END_OF_HDR_TAG)
+                            && (i < fw->size); i++) ;
+                /* here we check for the out of buffer case */
+                if ((STIR421X_PATCH_END_OF_HDR_TAG == fw->data[i])
+                    && (i < STIR421X_PATCH_CODE_OFFSET)) {
+                        if (!memcmp(fw->data + i + 1, STIR421X_PATCH_STMP_TAG,
+                                    sizeof(STIR421X_PATCH_STMP_TAG) - 1)) {
+
+                               /* We can upload the patch to the target */
+                               i += sizeof(STIR421X_PATCH_STMP_TAG);
+                                ret = stir421x_fw_upload(self, &fw->data[i],
+                                                        fw->size - i);
+                        }
+                }
+        }
+
+        release_firmware(fw);
+
+        return ret;
 }
 
 
@@ -1702,12 +1657,12 @@ static int irda_usb_probe(struct usb_interface *intf,
        init_timer(&self->rx_defer_timer);
 
        self->capability = id->driver_info;
-       self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ;
+       self->needspatch = ((self->capability & IUC_STIR421X) != 0);
 
        /* Create all of the needed urbs */
-       if (self->capability & IUC_STIR_4210) {
+       if (self->capability & IUC_STIR421X) {
                self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS;
-               self->header_length = USB_IRDA_SIGMATEL_HEADER;
+               self->header_length = USB_IRDA_STIR421X_HEADER;
        } else {
                self->max_rx_urb = IU_MAX_RX_URBS;
                self->header_length = USB_IRDA_HEADER;
@@ -1813,8 +1768,8 @@ static int irda_usb_probe(struct usb_interface *intf,
                /* Now we fetch and upload the firmware patch */
                ret = stir421x_patch_device(self);
                self->needspatch = (ret < 0);
-               if (ret < 0) {
-                       printk("patch_device failed\n");
+               if (self->needspatch) {
+                       IRDA_ERROR("STIR421X: Couldn't upload patch\n");
                        goto err_out_5;
                }
 
index d833db52cebf2921333f9d5c19e0ceaa79063832..6b2271f18e77409576490c16b08d0d0229b90340 100644 (file)
@@ -34,9 +34,6 @@
 #include <net/irda/irda.h>
 #include <net/irda/irda_device.h>      /* struct irlap_cb */
 
-#define PATCH_FILE_SIZE_MAX     65536
-#define PATCH_FILE_SIZE_MIN     80
-
 #define RX_COPY_THRESHOLD 200
 #define IRDA_USB_MAX_MTU 2051
 #define IRDA_USB_SPEED_MTU 64          /* Weird, but work like this */
 #define IUC_SMALL_PKT  0x10    /* Device doesn't behave with big Rx packets */
 #define IUC_MAX_WINDOW 0x20    /* Device underestimate the Rx window */
 #define IUC_MAX_XBOFS  0x40    /* Device need more xbofs than advertised */
-#define IUC_STIR_4210  0x80    /* SigmaTel 4210/4220/4116 VFIR */
+#define IUC_STIR421X   0x80    /* SigmaTel 4210/4220/4116 VFIR */
 
 /* USB class definitions */
 #define USB_IRDA_HEADER            0x01
 #define USB_CLASS_IRDA             0x02 /* USB_CLASS_APP_SPEC subclass */
 #define USB_DT_IRDA                0x21
-#define USB_IRDA_SIGMATEL_HEADER   0x03
-#define IU_SIGMATEL_MAX_RX_URBS    (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER)
+#define USB_IRDA_STIR421X_HEADER   0x03
+#define IU_SIGMATEL_MAX_RX_URBS    (IU_MAX_ACTIVE_RX_URBS + \
+                                    USB_IRDA_STIR421X_HEADER)
 
 struct irda_class_desc {
        __u8  bLength;
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
new file mode 100644 (file)
index 0000000..754297f
--- /dev/null
@@ -0,0 +1,1009 @@
+/*****************************************************************************
+*
+* Filename:      mcs7780.c
+* Version:       0.4-alpha
+* Description:   Irda MosChip USB Dongle Driver
+* Authors:       Lukasz Stelmach <stlman@poczta.fm>
+*               Brian Pugh <bpugh@cs.pdx.edu>
+*               Judy Fischbach <jfisch@cs.pdx.edu>
+*
+*       Based on stir4200 driver, but some things done differently.
+*       Based on earlier driver by Paul Stewart <stewart@parc.com>
+*
+*       Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
+*       Copyright (C) 2001, Dag Brattli <dag@brattli.net>
+*       Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+*       Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+*       Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm>
+*       Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu>
+*       Copyright (C) 2005, Judy Fischbach <jfisch@cs.pdx.edu>
+*
+*       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.
+*
+*****************************************************************************/
+
+/*
+ * MCS7780 is a simple USB to IrDA bridge by MosChip. It is neither
+ * compatibile with irda-usb nor with stir4200. Although it is quite
+ * similar to the later as far as general idea of operation is concerned.
+ * That is it requires the software to do all the framing job at SIR speeds.
+ * The hardware does take care of the framing at MIR and FIR speeds.
+ * It supports all speeds from 2400 through 4Mbps
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/crc32.h>
+
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/crc.h>
+
+#include "mcs7780.h"
+
+#define MCS_VENDOR_ID 0x9710
+#define MCS_PRODUCT_ID 0x7780
+
+static struct usb_device_id mcs_table[] = {
+       /* MosChip Corp.,  MCS7780 FIR-USB Adapter */
+       {USB_DEVICE(MCS_VENDOR_ID, MCS_PRODUCT_ID)},
+       {},
+};
+
+MODULE_AUTHOR("Brian Pugh <bpugh@cs.pdx.edu>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver for MosChip MCS7780");
+MODULE_VERSION("0.3alpha");
+MODULE_LICENSE("GPL");
+
+MODULE_DEVICE_TABLE(usb, mcs_table);
+
+static int qos_mtt_bits = 0x07 /* > 1ms */ ;
+module_param(qos_mtt_bits, int, 0);
+MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
+
+static int receive_mode = 0x1;
+module_param(receive_mode, int, 0);
+MODULE_PARM_DESC(receive_mode,
+                "Receive mode of the device (1:fast, 0:slow, default:1)");
+
+static int sir_tweak = 1;
+module_param(sir_tweak, int, 0444);
+MODULE_PARM_DESC(sir_tweak,
+                "Default pulse width (1:1.6us, 0:3/16 bit, default:1).");
+
+static int transceiver_type = MCS_TSC_VISHAY;
+module_param(transceiver_type, int, 0444);
+MODULE_PARM_DESC(transceiver_type, "IR transceiver type, see mcs7780.h.");
+
+struct usb_driver mcs_driver = {
+       .name = "mcs7780",
+       .probe = mcs_probe,
+       .disconnect = mcs_disconnect,
+       .id_table = mcs_table,
+};
+
+/* speed flag selection by direct addressing.
+addr = (speed >> 8) & 0x0f
+
+0x1   57600     0x2  115200     0x4 1152000     0x5    9600
+0x6   38400     0x9    2400     0xa  576000     0xb   19200
+
+4Mbps (or 2400) must be checked separately. Since it also has
+to be programmed in a different manner that is not a big problem.
+*/
+static __u16 mcs_speed_set[16] = { 0,
+       MCS_SPEED_57600,
+       MCS_SPEED_115200,
+       0,
+       MCS_SPEED_1152000,
+       MCS_SPEED_9600,
+       MCS_SPEED_38400,
+       0, 0,
+       MCS_SPEED_2400,
+       MCS_SPEED_576000,
+       MCS_SPEED_19200,
+       0, 0, 0,
+};
+
+/* Set given 16 bit register with a 16 bit value. Send control message
+ * to set dongle register. */
+static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val)
+{
+       struct usb_device *dev = mcs->usbdev;
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
+                              MCS_WR_RTYPE, val, reg, NULL, 0,
+                              msecs_to_jiffies(MCS_CTRL_TIMEOUT));
+}
+
+/* Get 16 bit register value. Send contol message to read dongle register. */
+static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val)
+{
+       struct usb_device *dev = mcs->usbdev;
+       int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
+                                 MCS_RD_RTYPE, 0, reg, val, 2,
+                                 msecs_to_jiffies(MCS_CTRL_TIMEOUT));
+
+       return ret;
+}
+
+/* Setup a communication between mcs7780 and TFDU chips.  It is described
+ * in more detail in the data sheet.  The setup sequence puts the the
+ * vishay tranceiver into high speed mode.  It will also receive SIR speed
+ * packets but at reduced sensitivity.
+ */
+
+/* 0: OK 1:ERROR */
+static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs)
+{
+       int ret = 0;
+       __u16 rval;
+
+       /* mcs_get_reg should read exactly two bytes from the dongle */
+       ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval);
+       if (unlikely(ret != 2)) {
+               ret = -EIO;
+               goto error;
+       }
+
+       /* The MCS_XCVR_CONF bit puts the transceiver into configuration
+        * mode.  The MCS_MODE0 bit must start out high (1) and then
+        * transition to low and the MCS_STFIR and MCS_MODE1 bits must
+        * be low.
+        */
+       rval |= (MCS_MODE0 | MCS_XCVR_CONF);
+       rval &= ~MCS_STFIR;
+       rval &= ~MCS_MODE1;
+       ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+       if (unlikely(ret))
+               goto error;
+
+       rval &= ~MCS_MODE0;
+       ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+       if (unlikely(ret))
+               goto error;
+
+       rval &= ~MCS_XCVR_CONF;
+       ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+       if (unlikely(ret))
+               goto error;
+
+       ret = 0;
+       error:
+               return ret;
+}
+
+/* Setup a communication between mcs7780 and agilent chip. */
+static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs)
+{
+       IRDA_WARNING("This transceiver type is not supported yet.");
+       return 1;
+}
+
+/* Setup a communication between mcs7780 and sharp chip. */
+static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs)
+{
+       IRDA_WARNING("This transceiver type is not supported yet.");
+       return 1;
+}
+
+/* Common setup for all transceivers */
+static inline int mcs_setup_transceiver(struct mcs_cb *mcs)
+{
+       int ret = 0;
+       __u16 rval;
+       char *msg;
+
+       msg = "Basic transceiver setup error.";
+
+       /* read value of MODE Register, set the DRIVER and RESET bits
+       * and write value back out to MODE Register
+       */
+       ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+       if(unlikely(ret != 2))
+               goto error;
+       rval |= MCS_DRIVER;     /* put the mcs7780 into configuration mode. */
+       ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+       if(unlikely(ret))
+               goto error;
+
+       rval = 0;               /* set min pulse width to 0 initially. */
+       ret = mcs_set_reg(mcs, MCS_MINRXPW_REG, rval);
+       if(unlikely(ret))
+               goto error;
+
+       ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+       if(unlikely(ret != 2))
+               goto error;
+
+       rval &= ~MCS_FIR;       /* turn off fir mode. */
+       if(mcs->sir_tweak)
+               rval |= MCS_SIR16US;    /* 1.6us pulse width */
+       else
+               rval &= ~MCS_SIR16US;   /* 3/16 bit time pulse width */
+
+       /* make sure ask mode and back to back packets are off. */
+       rval &= ~(MCS_BBTG | MCS_ASK);
+
+       rval &= ~MCS_SPEED_MASK;
+       rval |= MCS_SPEED_9600;         /* make sure initial speed is 9600. */
+       mcs->speed = 9600;
+       mcs->new_speed = 0;             /* new_speed is set to 0 */
+       rval &= ~MCS_PLLPWDN;           /* disable power down. */
+
+       /* make sure device determines direction and that the auto send sip
+        * pulse are on.
+        */
+       rval |= MCS_DTD | MCS_SIPEN;
+
+       ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+       if(unlikely(ret))
+               goto error;
+
+       msg = "transceiver model specific setup error.";
+       switch (mcs->transceiver_type) {
+       case MCS_TSC_VISHAY:
+               ret = mcs_setup_transceiver_vishay(mcs);
+               break;
+
+       case MCS_TSC_SHARP:
+               ret = mcs_setup_transceiver_sharp(mcs);
+               break;
+
+       case MCS_TSC_AGILENT:
+               ret = mcs_setup_transceiver_agilent(mcs);
+               break;
+
+       default:
+               IRDA_WARNING("Unknown transceiver type: %d",
+                            mcs->transceiver_type);
+               ret = 1;
+       }
+       if (unlikely(ret))
+               goto error;
+
+       /* If transceiver is not SHARP, then if receive mode set
+       * on the RXFAST bit in the XCVR Register otherwise unset it
+       */
+       if (mcs->transceiver_type != MCS_TSC_SHARP) {
+
+               ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval);
+               if (unlikely(ret != 2))
+                       goto error;
+               if (mcs->receive_mode)
+                       rval |= MCS_RXFAST;
+               else
+                       rval &= ~MCS_RXFAST;
+               ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+               if (unlikely(ret))
+                       goto error;
+       }
+
+       msg = "transceiver reset.";
+
+       ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+       if (unlikely(ret != 2))
+               goto error;
+
+       /* reset the mcs7780 so all changes take effect. */
+       rval &= ~MCS_RESET;
+       ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+       if (unlikely(ret))
+               goto error;
+       else
+               return ret;
+
+error:
+       IRDA_ERROR("%s", msg);
+       return ret;
+}
+
+/* Wraps the data in format for SIR */
+static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf)
+{
+       int wraplen;
+
+       /* 2: full frame length, including "the length" */
+       wraplen = async_wrap_skb(skb, buf + 2, 4094);
+
+       wraplen += 2;
+       buf[0] = wraplen & 0xff;
+       buf[1] = (wraplen >> 8) & 0xff;
+
+       return wraplen;
+}
+
+/* Wraps the data in format for FIR */
+static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf)
+{
+       unsigned int len = 0;
+       __u32 fcs = ~(crc32_le(~0, skb->data, skb->len));
+
+       /* add 2 bytes for length value and 4 bytes for fcs. */
+       len = skb->len + 6;
+
+       /* The mcs7780 requires that the first two bytes are the packet
+        * length in little endian order.  Note: the length value includes
+        * the two bytes for the length value itself.
+        */
+       buf[0] = len & 0xff;
+       buf[1] = (len >> 8) & 0xff;
+       /* copy the data into the tx buffer. */
+       memcpy(buf+2, skb->data, skb->len);
+       /* put the fcs in the last four bytes in little endian order. */
+       buf[len - 4] = fcs & 0xff;
+       buf[len - 3] = (fcs >> 8) & 0xff;
+       buf[len - 2] = (fcs >> 16) & 0xff;
+       buf[len - 1] = (fcs >> 24) & 0xff;
+
+       return len;
+}
+
+/* Wraps the data in format for MIR */
+static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf)
+{
+       __u16 fcs = 0;
+       int len = skb->len + 4;
+
+       fcs = ~(irda_calc_crc16(~fcs, skb->data, skb->len));
+       /* put the total packet length in first.  Note: packet length
+        * value includes the two bytes that hold the packet length
+        * itself.
+        */
+       buf[0] = len & 0xff;
+       buf[1] = (len >> 8) & 0xff;
+       /* copy the data */
+       memcpy(buf+2, skb->data, skb->len);
+       /* put the fcs in last two bytes in little endian order. */
+       buf[len - 2] = fcs & 0xff;
+       buf[len - 1] = (fcs >> 8) & 0xff;
+
+       return len;
+}
+
+/* Unwrap received packets at MIR speed.  A 16 bit crc_ccitt checksum is
+ * used for the fcs.  When performed over the entire packet the result
+ * should be GOOD_FCS = 0xf0b8.  Hands the unwrapped data off to the IrDA
+ * layer via a sk_buff.
+ */
+static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len)
+{
+       __u16 fcs;
+       int new_len;
+       struct sk_buff *skb;
+
+       /* Assume that the frames are going to fill a single packet
+        * rather than span multiple packets.
+        */
+
+       new_len = len - 2;
+       if(unlikely(new_len <= 0)) {
+               IRDA_ERROR("%s short frame length %d\n",
+                            mcs->netdev->name, new_len);
+               ++mcs->stats.rx_errors;
+               ++mcs->stats.rx_length_errors;
+               return;
+       }
+       fcs = 0;
+       fcs = irda_calc_crc16(~fcs, buf, len);
+
+       if(fcs != GOOD_FCS) {
+               IRDA_ERROR("crc error calc 0x%x len %d\n",
+                          fcs, new_len);
+               mcs->stats.rx_errors++;
+               mcs->stats.rx_crc_errors++;
+               return;
+       }
+
+       skb = dev_alloc_skb(new_len + 1);
+       if(unlikely(!skb)) {
+               ++mcs->stats.rx_dropped;
+               return;
+       }
+
+       skb_reserve(skb, 1);
+       memcpy(skb->data, buf, new_len);
+       skb_put(skb, new_len);
+       skb->mac.raw = skb->data;
+       skb->protocol = htons(ETH_P_IRDA);
+       skb->dev = mcs->netdev;
+
+       netif_rx(skb);
+
+       mcs->stats.rx_packets++;
+       mcs->stats.rx_bytes += new_len;
+
+       return;
+}
+
+/* Unwrap received packets at FIR speed.  A 32 bit crc_ccitt checksum is
+ * used for the fcs.  Hands the unwrapped data off to the IrDA
+ * layer via a sk_buff.
+ */
+static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len)
+{
+       __u32 fcs;
+       int new_len;
+       struct sk_buff *skb;
+
+       /* Assume that the frames are going to fill a single packet
+        * rather than span multiple packets.  This is most likely a false
+        * assumption.
+        */
+
+       new_len = len - 4;
+       if(unlikely(new_len <= 0)) {
+               IRDA_ERROR("%s short frame length %d\n",
+                          mcs->netdev->name, new_len);
+               ++mcs->stats.rx_errors;
+               ++mcs->stats.rx_length_errors;
+               return;
+       }
+
+       fcs = ~(crc32_le(~0, buf, new_len));
+       if(fcs != le32_to_cpu(get_unaligned((u32 *)(buf+new_len)))) {
+               IRDA_ERROR("crc error calc 0x%x len %d\n", fcs, new_len);
+               mcs->stats.rx_errors++;
+               mcs->stats.rx_crc_errors++;
+               return;
+       }
+
+       skb = dev_alloc_skb(new_len + 1);
+       if(unlikely(!skb)) {
+               ++mcs->stats.rx_dropped;
+               return;
+       }
+
+       skb_reserve(skb, 1);
+       memcpy(skb->data, buf, new_len);
+       skb_put(skb, new_len);
+       skb->mac.raw = skb->data;
+       skb->protocol = htons(ETH_P_IRDA);
+       skb->dev = mcs->netdev;
+
+       netif_rx(skb);
+
+       mcs->stats.rx_packets++;
+       mcs->stats.rx_bytes += new_len;
+
+       return;
+}
+
+
+/* Allocates urbs for both receive and transmit.
+ * If alloc fails return error code 0 (fail) otherwise
+ * return error code 1 (success).
+ */
+static inline int mcs_setup_urbs(struct mcs_cb *mcs)
+{
+       mcs->rx_urb = NULL;
+
+       mcs->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!mcs->tx_urb)
+               return 0;
+
+       mcs->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!mcs->rx_urb)
+               return 0;
+
+       return 1;
+}
+
+/* Sets up state to be initially outside frame, gets receive urb,
+ * sets status to successful and then submits the urb to start
+ * receiving the data.
+ */
+static inline int mcs_receive_start(struct mcs_cb *mcs)
+{
+       mcs->rx_buff.in_frame = FALSE;
+       mcs->rx_buff.state = OUTSIDE_FRAME;
+
+       usb_fill_bulk_urb(mcs->rx_urb, mcs->usbdev,
+                         usb_rcvbulkpipe(mcs->usbdev, mcs->ep_in),
+                         mcs->in_buf, 4096, mcs_receive_irq, mcs);
+
+       mcs->rx_urb->status = 0;
+       return usb_submit_urb(mcs->rx_urb, GFP_KERNEL);
+}
+
+/* Finds the in and out endpoints for the mcs control block */
+static inline int mcs_find_endpoints(struct mcs_cb *mcs,
+                                    struct usb_host_endpoint *ep, int epnum)
+{
+       int i;
+       int ret = 0;
+
+       /* If no place to store the endpoints just return */
+       if (!ep)
+               return ret;
+
+       /* cycle through all endpoints, find the first two that are DIR_IN */
+       for (i = 0; i < epnum; i++) {
+               if (ep[i].desc.bEndpointAddress & USB_DIR_IN)
+                       mcs->ep_in = ep[i].desc.bEndpointAddress;
+               else
+                       mcs->ep_out = ep[i].desc.bEndpointAddress;
+
+               /* MosChip says that the chip has only two bulk
+                * endpoints. Find one for each direction and move on.
+                */
+               if ((mcs->ep_in != 0) && (mcs->ep_out != 0)) {
+                       ret = 1;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static void mcs_speed_work(void *arg)
+{
+       struct mcs_cb *mcs = arg;
+       struct net_device *netdev = mcs->netdev;
+
+       mcs_speed_change(mcs);
+       netif_wake_queue(netdev);
+}
+
+/* Function to change the speed of the mcs7780.  Fully supports SIR,
+ * MIR, and FIR speeds.
+ */
+static int mcs_speed_change(struct mcs_cb *mcs)
+{
+       int ret = 0;
+       int rst = 0;
+       int cnt = 0;
+       __u16 nspeed;
+       __u16 rval;
+
+       nspeed = mcs_speed_set[(mcs->new_speed >> 8) & 0x0f];
+
+       do {
+               mcs_get_reg(mcs, MCS_RESV_REG, &rval);
+       } while(cnt++ < 100 && (rval & MCS_IRINTX));
+
+       if(cnt >= 100) {
+               IRDA_ERROR("unable to change speed");
+               ret = -EIO;
+               goto error;
+       }
+
+       mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+
+       /* MINRXPW values recomended by MosChip */
+       if (mcs->new_speed <= 115200) {
+               rval &= ~MCS_FIR;
+
+               if ((rst = (mcs->speed > 115200)))
+                       mcs_set_reg(mcs, MCS_MINRXPW_REG, 0);
+
+       } else if (mcs->new_speed <= 1152000) {
+               rval &= ~MCS_FIR;
+
+               if ((rst = !(mcs->speed == 576000 || mcs->speed == 1152000)))
+                       mcs_set_reg(mcs, MCS_MINRXPW_REG, 5);
+
+       } else {
+               rval |= MCS_FIR;
+
+               if ((rst = (mcs->speed != 4000000)))
+                       mcs_set_reg(mcs, MCS_MINRXPW_REG, 5);
+
+       }
+
+       rval &= ~MCS_SPEED_MASK;
+       rval |= nspeed;
+
+       ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+       if (unlikely(ret))
+               goto error;
+
+       if (rst)
+               switch (mcs->transceiver_type) {
+               case MCS_TSC_VISHAY:
+                       ret = mcs_setup_transceiver_vishay(mcs);
+                       break;
+
+               case MCS_TSC_SHARP:
+                       ret = mcs_setup_transceiver_sharp(mcs);
+                       break;
+
+               case MCS_TSC_AGILENT:
+                       ret = mcs_setup_transceiver_agilent(mcs);
+                       break;
+
+               default:
+                       ret = 1;
+                       IRDA_WARNING("Unknown transceiver type: %d",
+                                    mcs->transceiver_type);
+               }
+       if (unlikely(ret))
+               goto error;
+
+       mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+       rval &= ~MCS_RESET;
+       ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+
+       mcs->speed = mcs->new_speed;
+       error:
+               mcs->new_speed = 0;
+               return ret;
+}
+
+/* Ioctl calls not supported at this time.  Can be an area of future work. */
+static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+       /* struct if_irda_req *irq = (struct if_irda_req *)rq; */
+       /* struct mcs_cb *mcs = netdev_priv(netdev); */
+       int ret = 0;
+
+       switch (cmd) {
+       default:
+               ret = -EOPNOTSUPP;
+       }
+
+       return ret;
+}
+
+/* Network device is taken down, done by "ifconfig irda0 down" */
+static int mcs_net_close(struct net_device *netdev)
+{
+       int ret = 0;
+       struct mcs_cb *mcs = netdev_priv(netdev);
+
+       /* Stop transmit processing */
+       netif_stop_queue(netdev);
+
+       /* kill and free the receive and transmit URBs */
+       usb_kill_urb(mcs->rx_urb);
+       usb_free_urb(mcs->rx_urb);
+       usb_kill_urb(mcs->tx_urb);
+       usb_free_urb(mcs->tx_urb);
+
+       /* Stop and remove instance of IrLAP */
+       if (mcs->irlap)
+               irlap_close(mcs->irlap);
+
+       mcs->irlap = NULL;
+       return ret;
+}
+
+/* Network device is taken up, done by "ifconfig irda0 up" */
+static int mcs_net_open(struct net_device *netdev)
+{
+       struct mcs_cb *mcs = netdev_priv(netdev);
+       char hwname[16];
+       int ret = 0;
+
+       ret = usb_clear_halt(mcs->usbdev,
+                            usb_sndbulkpipe(mcs->usbdev, mcs->ep_in));
+       if (ret)
+               goto error1;
+       ret = usb_clear_halt(mcs->usbdev,
+                            usb_rcvbulkpipe(mcs->usbdev, mcs->ep_out));
+       if (ret)
+               goto error1;
+
+       ret = mcs_setup_transceiver(mcs);
+       if (ret)
+               goto error1;
+
+       ret = -ENOMEM;
+
+       /* Initialize for SIR/FIR to copy data directly into skb.  */
+       mcs->receiving = 0;
+       mcs->rx_buff.truesize = IRDA_SKB_MAX_MTU;
+       mcs->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+       if (!mcs->rx_buff.skb)
+               goto error1;
+
+       skb_reserve(mcs->rx_buff.skb, 1);
+       mcs->rx_buff.head = mcs->rx_buff.skb->data;
+       do_gettimeofday(&mcs->rx_time);
+
+       /*
+        * Now that everything should be initialized properly,
+        * Open new IrLAP layer instance to take care of us...
+        * Note : will send immediately a speed change...
+        */
+       sprintf(hwname, "usb#%d", mcs->usbdev->devnum);
+       mcs->irlap = irlap_open(netdev, &mcs->qos, hwname);
+       if (!mcs->irlap) {
+               IRDA_ERROR("mcs7780: irlap_open failed");
+               goto error2;
+       }
+
+       if (!mcs_setup_urbs(mcs))
+       goto error3;
+
+       ret = mcs_receive_start(mcs);
+       if (ret)
+               goto error3;
+
+       netif_start_queue(netdev);
+       return 0;
+
+       error3:
+               irlap_close(mcs->irlap);
+       error2:
+               kfree_skb(mcs->rx_buff.skb);
+       error1:
+               return ret;
+}
+
+
+/* Get device stats for /proc/net/dev and ifconfig */
+static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev)
+{
+       struct mcs_cb *mcs = netdev_priv(netdev);
+       return &mcs->stats;
+}
+
+/* Receive callback function.  */
+static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs)
+{
+       __u8 *bytes;
+       struct mcs_cb *mcs = urb->context;
+       int i;
+       int ret;
+
+       if (!netif_running(mcs->netdev))
+               return;
+
+       if (urb->status)
+               return;
+
+       if (urb->actual_length > 0) {
+               bytes = urb->transfer_buffer;
+
+               /* MCS returns frames without BOF and EOF
+                * I assume it returns whole frames.
+                */
+               /* SIR speed */
+               if(mcs->speed < 576000) {
+                       async_unwrap_char(mcs->netdev, &mcs->stats,
+                                 &mcs->rx_buff, 0xc0);
+
+                       for (i = 0; i < urb->actual_length; i++)
+                               async_unwrap_char(mcs->netdev, &mcs->stats,
+                                         &mcs->rx_buff, bytes[i]);
+
+                       async_unwrap_char(mcs->netdev, &mcs->stats,
+                                 &mcs->rx_buff, 0xc1);
+               }
+               /* MIR speed */
+               else if(mcs->speed == 576000 || mcs->speed == 1152000) {
+                       mcs_unwrap_mir(mcs, urb->transfer_buffer,
+                               urb->actual_length);
+               }
+               /* FIR speed */
+               else {
+                       mcs_unwrap_fir(mcs, urb->transfer_buffer,
+                               urb->actual_length);
+               }
+               mcs->netdev->last_rx = jiffies;
+               do_gettimeofday(&mcs->rx_time);
+       }
+
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+/* Transmit callback funtion.  */
+static void mcs_send_irq(struct urb *urb, struct pt_regs *regs)
+{
+       struct mcs_cb *mcs = urb->context;
+       struct net_device *ndev = mcs->netdev;
+
+       if (unlikely(mcs->new_speed))
+               schedule_work(&mcs->work);
+       else
+               netif_wake_queue(ndev);
+}
+
+/* Transmit callback funtion.  */
+static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+       unsigned long flags;
+       struct mcs_cb *mcs;
+       int wraplen;
+       int ret = 0;
+
+
+       if (skb == NULL || ndev == NULL)
+               return -EINVAL;
+
+       netif_stop_queue(ndev);
+       mcs = netdev_priv(ndev);
+
+       spin_lock_irqsave(&mcs->lock, flags);
+
+       mcs->new_speed = irda_get_next_speed(skb);
+       if (likely(mcs->new_speed == mcs->speed))
+               mcs->new_speed = 0;
+
+       /* SIR speed */
+       if(mcs->speed < 576000) {
+               wraplen = mcs_wrap_sir_skb(skb, mcs->out_buf);
+       }
+       /* MIR speed */
+       else if(mcs->speed == 576000 || mcs->speed == 1152000) {
+               wraplen = mcs_wrap_mir_skb(skb, mcs->out_buf);
+       }
+       /* FIR speed */
+       else {
+               wraplen = mcs_wrap_fir_skb(skb, mcs->out_buf);
+       }
+       usb_fill_bulk_urb(mcs->tx_urb, mcs->usbdev,
+                         usb_sndbulkpipe(mcs->usbdev, mcs->ep_out),
+                         mcs->out_buf, wraplen, mcs_send_irq, mcs);
+
+       if ((ret = usb_submit_urb(mcs->tx_urb, GFP_ATOMIC))) {
+               IRDA_ERROR("failed tx_urb: %d", ret);
+               switch (ret) {
+               case -ENODEV:
+               case -EPIPE:
+                       break;
+               default:
+                       mcs->stats.tx_errors++;
+                       netif_start_queue(ndev);
+               }
+       } else {
+               mcs->stats.tx_packets++;
+               mcs->stats.tx_bytes += skb->len;
+       }
+
+       dev_kfree_skb(skb);
+       spin_unlock_irqrestore(&mcs->lock, flags);
+       return ret;
+}
+
+/*
+ * This function is called by the USB subsystem for each new device in the
+ * system.  Need to verify the device and if it is, then start handling it.
+ */
+static int mcs_probe(struct usb_interface *intf,
+                    const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct net_device *ndev = NULL;
+       struct mcs_cb *mcs;
+       int ret = -ENOMEM;
+
+       ndev = alloc_irdadev(sizeof(*mcs));
+       if (!ndev)
+               goto error1;
+
+       IRDA_DEBUG(1, "MCS7780 USB-IrDA bridge found at %d.", udev->devnum);
+
+       /* what is it realy for? */
+       SET_MODULE_OWNER(ndev);
+       SET_NETDEV_DEV(ndev, &intf->dev);
+
+       ret = usb_reset_configuration(udev);
+       if (ret != 0) {
+               IRDA_ERROR("mcs7780: usb reset configuration failed");
+               goto error2;
+       }
+
+       mcs = netdev_priv(ndev);
+       mcs->usbdev = udev;
+       mcs->netdev = ndev;
+       spin_lock_init(&mcs->lock);
+
+       /* Initialize QoS for this device */
+       irda_init_max_qos_capabilies(&mcs->qos);
+
+       /* That's the Rx capability. */
+       mcs->qos.baud_rate.bits &=
+           IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200
+               | IR_576000 | IR_1152000 | (IR_4000000 << 8);
+
+
+       mcs->qos.min_turn_time.bits &= qos_mtt_bits;
+       irda_qos_bits_to_value(&mcs->qos);
+
+       /* Speed change work initialisation*/
+       INIT_WORK(&mcs->work, mcs_speed_work, mcs);
+
+       /* Override the network functions we need to use */
+       ndev->hard_start_xmit = mcs_hard_xmit;
+       ndev->open = mcs_net_open;
+       ndev->stop = mcs_net_close;
+       ndev->get_stats = mcs_net_get_stats;
+       ndev->do_ioctl = mcs_net_ioctl;
+
+       if (!intf->cur_altsetting)
+               goto error2;
+
+       ret = mcs_find_endpoints(mcs, intf->cur_altsetting->endpoint,
+                                intf->cur_altsetting->desc.bNumEndpoints);
+       if (!ret) {
+               ret = -ENODEV;
+               goto error2;
+       }
+
+       ret = register_netdev(ndev);
+       if (ret != 0)
+               goto error2;
+
+       IRDA_DEBUG(1, "IrDA: Registered MosChip MCS7780 device as %s",
+                  ndev->name);
+
+       mcs->transceiver_type = transceiver_type;
+       mcs->sir_tweak = sir_tweak;
+       mcs->receive_mode = receive_mode;
+
+       usb_set_intfdata(intf, mcs);
+       return 0;
+
+       error2:
+               free_netdev(ndev);
+
+       error1:
+               return ret;
+}
+
+/* The current device is removed, the USB layer tells us to shut down. */
+static void mcs_disconnect(struct usb_interface *intf)
+{
+       struct mcs_cb *mcs = usb_get_intfdata(intf);
+
+       if (!mcs)
+               return;
+
+       flush_scheduled_work();
+
+       unregister_netdev(mcs->netdev);
+       free_netdev(mcs->netdev);
+
+       usb_set_intfdata(intf, NULL);
+       IRDA_DEBUG(0, "MCS7780 now disconnected.");
+}
+
+/* Module insertion */
+static int __init mcs_init(void)
+{
+       int result;
+
+       /* register this driver with the USB subsystem */
+       result = usb_register(&mcs_driver);
+       if (result)
+               IRDA_ERROR("usb_register failed. Error number %d", result);
+
+       return result;
+}
+module_init(mcs_init);
+
+/* Module removal */
+static void __exit mcs_exit(void)
+{
+       /* deregister this driver with the USB subsystem */
+       usb_deregister(&mcs_driver);
+}
+module_exit(mcs_exit);
+
diff --git a/drivers/net/irda/mcs7780.h b/drivers/net/irda/mcs7780.h
new file mode 100644 (file)
index 0000000..1a723d7
--- /dev/null
@@ -0,0 +1,167 @@
+/*****************************************************************************
+*
+* Filename:      mcs7780.h
+* Version:       0.2-alpha
+* Description:   Irda MosChip USB Dongle
+* Status:        Experimental
+* Authors:       Lukasz Stelmach <stlman@poczta.fm>
+*               Brian Pugh <bpugh@cs.pdx.edu>
+*
+*       Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm>
+*       Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu>
+*
+*       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 _MCS7780_H
+#define _MCS7780_H
+
+#define MCS_MODE_SIR           0
+#define MCS_MODE_MIR           1
+#define MCS_MODE_FIR           2
+
+#define MCS_CTRL_TIMEOUT       500
+#define MCS_XMIT_TIMEOUT       500
+/* Possible transceiver types */
+#define MCS_TSC_VISHAY         0       /* Vishay TFD, default choice */
+#define MCS_TSC_AGILENT                1       /* Agilent 3602/3600 */
+#define MCS_TSC_SHARP          2       /* Sharp GP2W1000YP */
+
+/* Requests */
+#define MCS_RD_RTYPE 0xC0
+#define MCS_WR_RTYPE 0x40
+#define MCS_RDREQ    0x0F
+#define MCS_WRREQ    0x0E
+
+/* Register 0x00 */
+#define MCS_MODE_REG   0
+#define MCS_FIR                ((__u16)0x0001)
+#define MCS_SIR16US    ((__u16)0x0002)
+#define MCS_BBTG       ((__u16)0x0004)
+#define MCS_ASK                ((__u16)0x0008)
+#define MCS_PARITY     ((__u16)0x0010)
+
+/* SIR/MIR speed constants */
+#define MCS_SPEED_SHIFT            5
+#define MCS_SPEED_MASK     ((__u16)0x00E0)
+#define MCS_SPEED(x)       ((x & MCS_SPEED_MASK) >> MCS_SPEED_SHIFT)
+#define MCS_SPEED_2400     ((0 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_9600     ((1 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_19200            ((2 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_38400            ((3 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_57600            ((4 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_115200    ((5 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_576000    ((6 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_1152000   ((7 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+
+#define MCS_PLLPWDN    ((__u16)0x0100)
+#define MCS_DRIVER     ((__u16)0x0200)
+#define MCS_DTD                ((__u16)0x0400)
+#define MCS_DIR                ((__u16)0x0800)
+#define MCS_SIPEN      ((__u16)0x1000)
+#define MCS_SENDSIP    ((__u16)0x2000)
+#define MCS_CHGDIR     ((__u16)0x4000)
+#define MCS_RESET      ((__u16)0x8000)
+
+/* Register 0x02 */
+#define MCS_XCVR_REG   2
+#define MCS_MODE0      ((__u16)0x0001)
+#define MCS_STFIR      ((__u16)0x0002)
+#define MCS_XCVR_CONF  ((__u16)0x0004)
+#define MCS_RXFAST     ((__u16)0x0008)
+/* TXCUR [6:4] */
+#define MCS_TXCUR_SHIFT        4
+#define MCS_TXCUR_MASK ((__u16)0x0070)
+#define MCS_TXCUR(x)   ((x & MCS_TXCUR_MASK) >> MCS_TXCUR_SHIFT)
+#define MCS_SETTXCUR(x,y) \
+       ((x & ~MCS_TXCUR_MASK) | (y << MCS_TXCUR_SHIFT) & MCS_TXCUR_MASK)
+
+#define MCS_MODE1      ((__u16)0x0080)
+#define MCS_SMODE0     ((__u16)0x0100)
+#define MCS_SMODE1     ((__u16)0x0200)
+#define MCS_INVTX      ((__u16)0x0400)
+#define MCS_INVRX      ((__u16)0x0800)
+
+#define MCS_MINRXPW_REG        4
+
+#define MCS_RESV_REG 7
+#define MCS_IRINTX     ((__u16)0x0001)
+#define MCS_IRINRX     ((__u16)0x0002)
+
+struct mcs_cb {
+       struct usb_device *usbdev;      /* init: probe_irda */
+       struct net_device *netdev;      /* network layer */
+       struct irlap_cb *irlap; /* The link layer we are binded to */
+       struct net_device_stats stats;  /* network statistics */
+       struct qos_info qos;
+       unsigned int speed;     /* Current speed */
+       unsigned int new_speed; /* new speed */
+
+       struct work_struct work; /* Change speed work */
+
+       struct sk_buff *tx_pending;
+       char in_buf[4096];      /* transmit/receive buffer */
+       char out_buf[4096];     /* transmit/receive buffer */
+       __u8 *fifo_status;
+
+       iobuff_t rx_buff;       /* receive unwrap state machine */
+       struct timeval rx_time;
+       spinlock_t lock;
+       int receiving;
+
+       __u8 ep_in;
+       __u8 ep_out;
+
+       struct urb *rx_urb;
+       struct urb *tx_urb;
+
+       int transceiver_type;
+       int sir_tweak;
+       int receive_mode;
+};
+
+static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val);
+static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val);
+
+static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver(struct mcs_cb *mcs);
+static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf);
+static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf);
+static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf);
+static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len);
+static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len);
+static inline int mcs_setup_urbs(struct mcs_cb *mcs);
+static inline int mcs_receive_start(struct mcs_cb *mcs);
+static inline int mcs_find_endpoints(struct mcs_cb *mcs,
+                                    struct usb_host_endpoint *ep, int epnum);
+
+static int mcs_speed_change(struct mcs_cb *mcs);
+
+static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd);
+static int mcs_net_close(struct net_device *netdev);
+static int mcs_net_open(struct net_device *netdev);
+static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev);
+
+static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs);
+static void mcs_send_irq(struct urb *urb, struct pt_regs *regs);
+static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *netdev);
+
+static int mcs_probe(struct usb_interface *intf,
+                    const struct usb_device_id *id);
+static void mcs_disconnect(struct usb_interface *intf);
+
+#endif                         /* _MCS7780_H */
index 31867e4b891b1e582e2490638cc417894337e736..d61b208b52a215d4825a72cd3929f57263c8f6d9 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/delay.h>
 #include <linux/usb.h>
 #include <linux/crc32.h>
+#include <linux/kthread.h>
 #include <net/irda/irda.h>
 #include <net/irda/irlap.h>
 #include <net/irda/irda_device.h>
@@ -173,9 +174,7 @@ struct stir_cb {
         struct qos_info   qos;
        unsigned          speed;        /* Current speed */
 
-       wait_queue_head_t thr_wait;     /* transmit thread wakeup */
-       struct completion thr_exited;
-       pid_t             thr_pid;
+        struct task_struct *thread;     /* transmit thread */
 
        struct sk_buff    *tx_pending;
        void              *io_buf;      /* transmit/receive buffer */
@@ -577,7 +576,7 @@ static int stir_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
        SKB_LINEAR_ASSERT(skb);
 
        skb = xchg(&stir->tx_pending, skb);
-       wake_up(&stir->thr_wait);
+        wake_up_process(stir->thread);
        
        /* this should never happen unless stop/wakeup problem */
        if (unlikely(skb)) {
@@ -753,13 +752,7 @@ static int stir_transmit_thread(void *arg)
        struct net_device *dev = stir->netdev;
        struct sk_buff *skb;
 
-       daemonize("%s", dev->name);
-       allow_signal(SIGTERM);
-
-       while (netif_running(dev)
-              && netif_device_present(dev)
-              && !signal_pending(current))
-       {
+        while (!kthread_should_stop()) {
 #ifdef CONFIG_PM
                /* if suspending, then power off and wait */
                if (unlikely(freezing(current))) {
@@ -813,10 +806,11 @@ static int stir_transmit_thread(void *arg)
                }
 
                /* sleep if nothing to send */
-               wait_event_interruptible(stir->thr_wait, stir->tx_pending);
-       }
+                set_current_state(TASK_INTERRUPTIBLE);
+                schedule();
 
-       complete_and_exit (&stir->thr_exited, 0);
+       }
+        return 0;
 }
 
 
@@ -859,7 +853,7 @@ static void stir_rcv_irq(struct urb *urb, struct pt_regs *regs)
                warn("%s: usb receive submit error: %d",
                        stir->netdev->name, err);
                stir->receiving = 0;
-               wake_up(&stir->thr_wait);
+               wake_up_process(stir->thread);
        }
 }
 
@@ -928,10 +922,10 @@ static int stir_net_open(struct net_device *netdev)
        }
 
        /** Start kernel thread for transmit.  */
-       stir->thr_pid = kernel_thread(stir_transmit_thread, stir,
-                                     CLONE_FS|CLONE_FILES);
-       if (stir->thr_pid < 0) {
-               err = stir->thr_pid;
+       stir->thread = kthread_run(stir_transmit_thread, stir,
+                                  "%s", stir->netdev->name);
+        if (IS_ERR(stir->thread)) {
+                err = PTR_ERR(stir->thread);
                err("stir4200: unable to start kernel thread");
                goto err_out6;
        }
@@ -968,8 +962,7 @@ static int stir_net_close(struct net_device *netdev)
        netif_stop_queue(netdev);
 
        /* Kill transmit thread */
-       kill_proc(stir->thr_pid, SIGTERM, 1);
-       wait_for_completion(&stir->thr_exited);
+       kthread_stop(stir->thread);
        kfree(stir->fifo_status);
 
        /* Mop up receive urb's */
@@ -1084,9 +1077,6 @@ static int stir_probe(struct usb_interface *intf,
        stir->qos.min_turn_time.bits   &= qos_mtt_bits;
        irda_qos_bits_to_value(&stir->qos);
 
-       init_completion (&stir->thr_exited);
-       init_waitqueue_head (&stir->thr_wait);
-
        /* Override the network functions we need to use */
        net->hard_start_xmit = stir_hard_xmit;
        net->open            = stir_net_open;
index 97a49e0be76bc6197945814639b41e1d39f6caf1..d70b9e8d6e6054208216efb7ff9f88b1e50d7970 100644 (file)
@@ -959,7 +959,7 @@ static int vlsi_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                            ||  (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec))
                                break;
                        udelay(100);
-                       /* must not sleep here - we are called under xmit_lock! */
+                       /* must not sleep here - called under netif_tx_lock! */
                }
        }
 
index 7c7aff1ea7d57234391f3b8571ae85cb5839a803..a8a2d3d03567fc9f082a64533df578e1c077d09c 100644 (file)
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # 
-# Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
+# Copyright(c) 1999 - 2006 Intel Corporation. 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 
index c83271b386215cefef859df73572f34bc535fa17..a83ef28dadb0c0832ee68e3fd7b3854fe94f4dc9 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -84,7 +84,12 @@ struct ixgb_adapter;
 #define IXGB_DBG(args...)
 #endif
 
-#define IXGB_ERR(args...) printk(KERN_ERR "ixgb: " args)
+#define PFX "ixgb: "
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+       (void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
+       printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
+               __FUNCTION__ , ## args))
+
 
 /* TX/RX descriptor defines */
 #define DEFAULT_TXD     256
@@ -175,6 +180,7 @@ struct ixgb_adapter {
        uint64_t hw_csum_tx_good;
        uint64_t hw_csum_tx_error;
        uint32_t tx_int_delay;
+       uint32_t tx_timeout_count;
        boolean_t tx_int_delay_enable;
        boolean_t detect_tx_hung;
 
@@ -192,7 +198,9 @@ struct ixgb_adapter {
 
        /* structs defined in ixgb_hw.h */
        struct ixgb_hw hw;
+       u16 msg_enable;
        struct ixgb_hw_stats stats;
+       uint32_t alloc_rx_buff_failed;
 #ifdef CONFIG_PCI_MSI
        boolean_t have_msi;
 #endif
index 661a46b95a61e4a73a88f1774d8a3cc3564d8734..8357c5590bfb8a4887250958cbb422c1241798dc 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
index 5190aa8761a29f57d4208f80b024314d182786b0..bf6fa220f38e64eabe3c0ae0ce0dce14f54d45d3 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
index d38ade5f2f4e614f30a0755958f1b64ee484de28..cf19b898ba9b7a1bc3126942f724a99626a87b97 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -44,6 +44,8 @@ extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
 extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
 extern void ixgb_update_stats(struct ixgb_adapter *adapter);
 
+#define IXGB_ALL_RAR_ENTRIES 16
+
 struct ixgb_stats {
        char stat_string[ETH_GSTRING_LEN];
        int sizeof_stat;
@@ -76,6 +78,7 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
        {"tx_heartbeat_errors", IXGB_STAT(net_stats.tx_heartbeat_errors)},
        {"tx_window_errors", IXGB_STAT(net_stats.tx_window_errors)},
        {"tx_deferred_ok", IXGB_STAT(stats.dc)},
+       {"tx_timeout_count", IXGB_STAT(tx_timeout_count) },
        {"rx_long_length_errors", IXGB_STAT(stats.roc)},
        {"rx_short_length_errors", IXGB_STAT(stats.ruc)},
 #ifdef NETIF_F_TSO
@@ -117,6 +120,16 @@ ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
        return 0;
 }
 
+static void ixgb_set_speed_duplex(struct net_device *netdev)
+{
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+       /* be optimistic about our link, since we were up before */
+       adapter->link_speed = 10000;
+       adapter->link_duplex = FULL_DUPLEX;
+       netif_carrier_on(netdev);
+       netif_wake_queue(netdev);
+}
+
 static int
 ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
@@ -130,12 +143,7 @@ ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                ixgb_down(adapter, TRUE);
                ixgb_reset(adapter);
                ixgb_up(adapter);
-               /* be optimistic about our link, since we were up before */
-               adapter->link_speed = 10000;
-               adapter->link_duplex = FULL_DUPLEX;
-               netif_carrier_on(netdev);
-               netif_wake_queue(netdev);
-               
+               ixgb_set_speed_duplex(netdev);
        } else
                ixgb_reset(adapter);
 
@@ -183,11 +191,7 @@ ixgb_set_pauseparam(struct net_device *netdev,
        if(netif_running(adapter->netdev)) {
                ixgb_down(adapter, TRUE);
                ixgb_up(adapter);
-               /* be optimistic about our link, since we were up before */
-               adapter->link_speed = 10000;
-               adapter->link_duplex = FULL_DUPLEX;
-               netif_carrier_on(netdev);
-               netif_wake_queue(netdev);
+               ixgb_set_speed_duplex(netdev);
        } else
                ixgb_reset(adapter);
                
@@ -212,11 +216,7 @@ ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
        if(netif_running(netdev)) {
                ixgb_down(adapter,TRUE);
                ixgb_up(adapter);
-               /* be optimistic about our link, since we were up before */
-               adapter->link_speed = 10000;
-               adapter->link_duplex = FULL_DUPLEX;
-               netif_carrier_on(netdev);
-               netif_wake_queue(netdev);
+               ixgb_set_speed_duplex(netdev);
        } else
                ixgb_reset(adapter);
        return 0;
@@ -251,6 +251,19 @@ ixgb_set_tso(struct net_device *netdev, uint32_t data)
 } 
 #endif /* NETIF_F_TSO */
 
+static uint32_t
+ixgb_get_msglevel(struct net_device *netdev)
+{
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+       return adapter->msg_enable;
+}
+
+static void
+ixgb_set_msglevel(struct net_device *netdev, uint32_t data)
+{
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+       adapter->msg_enable = data;
+}
 #define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
 
 static int 
@@ -303,7 +316,7 @@ ixgb_get_regs(struct net_device *netdev,
        *reg++ = IXGB_READ_REG(hw, RXCSUM);     /*  20 */
 
        /* there are 16 RAR entries in hardware, we only use 3 */
-       for(i = 0; i < 16; i++) {
+       for(i = 0; i < IXGB_ALL_RAR_ENTRIES; i++) {
                *reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
                *reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
        }
@@ -593,11 +606,7 @@ ixgb_set_ringparam(struct net_device *netdev,
                adapter->tx_ring = tx_new;
                if((err = ixgb_up(adapter)))
                        return err;
-               /* be optimistic about our link, since we were up before */
-               adapter->link_speed = 10000;
-               adapter->link_duplex = FULL_DUPLEX;
-               netif_carrier_on(netdev);
-               netif_wake_queue(netdev);
+               ixgb_set_speed_duplex(netdev);
        }
 
        return 0;
@@ -714,6 +723,8 @@ static struct ethtool_ops ixgb_ethtool_ops = {
        .set_tx_csum = ixgb_set_tx_csum,
        .get_sg = ethtool_op_get_sg,
        .set_sg = ethtool_op_set_sg,
+       .get_msglevel = ixgb_get_msglevel,
+       .set_msglevel = ixgb_set_msglevel,
 #ifdef NETIF_F_TSO
        .get_tso = ethtool_op_get_tso,
        .set_tso = ixgb_set_tso,
index 620cad48bdea98a8ab4302b6c9119b71b7a471ee..f7fa10e47fa2c8836c5d155ff1001202e1f1bbf2 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
index 382c6300ccc23901bb073f4de7591f4354c5dfc7..cb4568915ada7a363b3e6d435bc809f15f176aae 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -57,6 +57,7 @@ typedef enum {
 typedef enum {
        ixgb_media_type_unknown = 0,
        ixgb_media_type_fiber = 1,
+       ixgb_media_type_copper = 2,
        ixgb_num_media_types
 } ixgb_media_type;
 
index aee207eaa287e3eaf79fa50f76d72dfc3ceebb68..40a085f94c7b84b625e5b62d91df8832f8da478f 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -43,6 +43,8 @@
 #define IXGB_SUBDEVICE_ID_A11F      0xA11F   
 #define IXGB_SUBDEVICE_ID_A01F      0xA01F   
 
-#endif /* #ifndef _IXGB_IDS_H_ */
+#define IXGB_DEVICE_ID_82597EX_CX4   0x109E
+#define IXGB_SUBDEVICE_ID_A00C  0xA00C
 
+#endif /* #ifndef _IXGB_IDS_H_ */
 /* End of File */
index cfd67d812f0db4094fd86d35e205873d0ac5b5e6..57006fb8840e4fff5f0a7aad75fc95692d53090f 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
 
 #include "ixgb.h"
 
-/* Change Log
- * 1.0.96 04/19/05
- * - Make needlessly global code static -- bunk@stusta.de
- * - ethtool cleanup -- shemminger@osdl.org
- * - Support for MODULE_VERSION -- linville@tuxdriver.com
- * - add skb_header_cloned check to the tso path -- herbert@apana.org.au
- * 1.0.88 01/05/05
- * - include fix to the condition that determines when to quit NAPI - Robert Olsson
- * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
- * 1.0.84 10/26/04
- * - reset buffer_info->dma in Tx resource cleanup logic
- * 1.0.83 10/12/04
- * - sparse cleanup - shemminger@osdl.org
- * - fix tx resource cleanup logic
- */
-
 char ixgb_driver_name[] = "ixgb";
 static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
 
@@ -52,9 +36,9 @@ static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION            "1.0.100-k2"DRIVERNAPI
+#define DRV_VERSION            "1.0.109-k2"DRIVERNAPI
 char ixgb_driver_version[] = DRV_VERSION;
-static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+static char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
 /* ixgb_pci_tbl - PCI Device ID Table
  *
@@ -67,6 +51,8 @@ static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
 static struct pci_device_id ixgb_pci_tbl[] = {
        {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_CX4,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_LR,  
@@ -148,6 +134,11 @@ MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+#define DEFAULT_DEBUG_LEVEL_SHIFT 3
+static int debug = DEFAULT_DEBUG_LEVEL_SHIFT;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
 /* some defines for controlling descriptor fetches in h/w */
 #define RXDCTL_WTHRESH_DEFAULT 16      /* chip writes back at this many or RXT0 */
 #define RXDCTL_PTHRESH_DEFAULT 0               /* chip considers prefech below
@@ -196,7 +187,7 @@ module_exit(ixgb_exit_module);
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 ixgb_irq_disable(struct ixgb_adapter *adapter)
 {
        atomic_inc(&adapter->irq_sem);
@@ -210,7 +201,7 @@ ixgb_irq_disable(struct ixgb_adapter *adapter)
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 ixgb_irq_enable(struct ixgb_adapter *adapter)
 {
        if(atomic_dec_and_test(&adapter->irq_sem)) {
@@ -231,6 +222,7 @@ ixgb_up(struct ixgb_adapter *adapter)
 
        /* hardware has been reset, we need to reload some things */
 
+       ixgb_rar_set(hw, netdev->dev_addr, 0);
        ixgb_set_multi(netdev);
 
        ixgb_restore_vlan(adapter);
@@ -240,6 +232,9 @@ ixgb_up(struct ixgb_adapter *adapter)
        ixgb_configure_rx(adapter);
        ixgb_alloc_rx_buffers(adapter);
 
+       /* disable interrupts and get the hardware into a known state */
+       IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
+
 #ifdef CONFIG_PCI_MSI
        {
        boolean_t pcix = (IXGB_READ_REG(&adapter->hw, STATUS) & 
@@ -249,7 +244,7 @@ ixgb_up(struct ixgb_adapter *adapter)
        if (!pcix)
           adapter->have_msi = FALSE;
        else if((err = pci_enable_msi(adapter->pdev))) {
-               printk (KERN_ERR
+               DPRINTK(PROBE, ERR,
                 "Unable to allocate MSI interrupt Error: %d\n", err);
                adapter->have_msi = FALSE;
                /* proceed to try to request regular interrupt */
@@ -259,11 +254,11 @@ ixgb_up(struct ixgb_adapter *adapter)
 #endif
        if((err = request_irq(adapter->pdev->irq, &ixgb_intr,
                                  SA_SHIRQ | SA_SAMPLE_RANDOM,
-                                 netdev->name, netdev)))
+                                 netdev->name, netdev))) {
+               DPRINTK(PROBE, ERR,
+                "Unable to allocate interrupt Error: %d\n", err);
                return err;
-
-       /* disable interrupts and get the hardware into a known state */
-       IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
+       }
 
        if((hw->max_frame_size != max_frame) ||
                (hw->max_frame_size !=
@@ -285,11 +280,12 @@ ixgb_up(struct ixgb_adapter *adapter)
        }
 
        mod_timer(&adapter->watchdog_timer, jiffies);
-       ixgb_irq_enable(adapter);
 
 #ifdef CONFIG_IXGB_NAPI
        netif_poll_enable(netdev);
 #endif
+       ixgb_irq_enable(adapter);
+
        return 0;
 }
 
@@ -326,7 +322,7 @@ ixgb_reset(struct ixgb_adapter *adapter)
 
        ixgb_adapter_stop(&adapter->hw);
        if(!ixgb_init_hw(&adapter->hw))
-               IXGB_DBG("ixgb_init_hw failed.\n");
+               DPRINTK(PROBE, ERR, "ixgb_init_hw failed.\n");
 }
 
 /**
@@ -363,7 +359,8 @@ ixgb_probe(struct pci_dev *pdev,
        } else {
                if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
                   (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
-                       IXGB_ERR("No usable DMA configuration, aborting\n");
+                       printk(KERN_ERR
+                        "ixgb: No usable DMA configuration, aborting\n");
                        goto err_dma_mask;
                }
                pci_using_dac = 0;
@@ -388,6 +385,7 @@ ixgb_probe(struct pci_dev *pdev,
        adapter->netdev = netdev;
        adapter->pdev = pdev;
        adapter->hw.back = adapter;
+       adapter->msg_enable = netif_msg_init(debug, DEFAULT_DEBUG_LEVEL_SHIFT);
 
        mmio_start = pci_resource_start(pdev, BAR_0);
        mmio_len = pci_resource_len(pdev, BAR_0);
@@ -416,7 +414,7 @@ ixgb_probe(struct pci_dev *pdev,
        netdev->change_mtu = &ixgb_change_mtu;
        ixgb_set_ethtool_ops(netdev);
        netdev->tx_timeout = &ixgb_tx_timeout;
-       netdev->watchdog_timeo = HZ;
+       netdev->watchdog_timeo = 5 * HZ;
 #ifdef CONFIG_IXGB_NAPI
        netdev->poll = &ixgb_clean;
        netdev->weight = 64;
@@ -428,6 +426,7 @@ ixgb_probe(struct pci_dev *pdev,
        netdev->poll_controller = ixgb_netpoll;
 #endif
 
+       strcpy(netdev->name, pci_name(pdev));
        netdev->mem_start = mmio_start;
        netdev->mem_end = mmio_start + mmio_len;
        netdev->base_addr = adapter->hw.io_base;
@@ -449,6 +448,9 @@ ixgb_probe(struct pci_dev *pdev,
 #ifdef NETIF_F_TSO
        netdev->features |= NETIF_F_TSO;
 #endif
+#ifdef NETIF_F_LLTX
+       netdev->features |= NETIF_F_LLTX;
+#endif
 
        if(pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
@@ -456,7 +458,7 @@ ixgb_probe(struct pci_dev *pdev,
        /* make sure the EEPROM is good */
 
        if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
-               printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n");
+               DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
                err = -EIO;
                goto err_eeprom;
        }
@@ -465,6 +467,7 @@ ixgb_probe(struct pci_dev *pdev,
        memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
 
        if(!is_valid_ether_addr(netdev->perm_addr)) {
+               DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
                err = -EIO;
                goto err_eeprom;
        }
@@ -478,6 +481,7 @@ ixgb_probe(struct pci_dev *pdev,
        INIT_WORK(&adapter->tx_timeout_task,
                  (void (*)(void *))ixgb_tx_timeout_task, netdev);
 
+       strcpy(netdev->name, "eth%d");
        if((err = register_netdev(netdev)))
                goto err_register;
 
@@ -486,8 +490,7 @@ ixgb_probe(struct pci_dev *pdev,
        netif_carrier_off(netdev);
        netif_stop_queue(netdev);
 
-       printk(KERN_INFO "%s: Intel(R) PRO/10GbE Network Connection\n",
-                  netdev->name);
+       DPRINTK(PROBE, INFO, "Intel(R) PRO/10GbE Network Connection\n");
        ixgb_check_options(adapter);
        /* reset the hardware with the new settings */
 
@@ -557,17 +560,17 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
        hw->subsystem_vendor_id = pdev->subsystem_vendor;
        hw->subsystem_id = pdev->subsystem_device;
 
-       adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
-
        hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+       adapter->rx_buffer_len = hw->max_frame_size;
 
        if((hw->device_id == IXGB_DEVICE_ID_82597EX)
-          ||(hw->device_id == IXGB_DEVICE_ID_82597EX_LR)
-          ||(hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
+          || (hw->device_id == IXGB_DEVICE_ID_82597EX_CX4)
+          || (hw->device_id == IXGB_DEVICE_ID_82597EX_LR)
+          || (hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
                        hw->mac_type = ixgb_82597;
        else {
                /* should never have loaded on this device */
-               printk(KERN_ERR "ixgb: unsupported device id\n");
+               DPRINTK(PROBE, ERR, "unsupported device id\n");
        }
 
        /* enable flow control to be programmed */
@@ -665,6 +668,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
        size = sizeof(struct ixgb_buffer) * txdr->count;
        txdr->buffer_info = vmalloc(size);
        if(!txdr->buffer_info) {
+               DPRINTK(PROBE, ERR,
+                "Unable to allocate transmit descriptor ring memory\n");
                return -ENOMEM;
        }
        memset(txdr->buffer_info, 0, size);
@@ -677,6 +682,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
        txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
        if(!txdr->desc) {
                vfree(txdr->buffer_info);
+               DPRINTK(PROBE, ERR,
+                "Unable to allocate transmit descriptor memory\n");
                return -ENOMEM;
        }
        memset(txdr->desc, 0, txdr->size);
@@ -750,6 +757,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
        size = sizeof(struct ixgb_buffer) * rxdr->count;
        rxdr->buffer_info = vmalloc(size);
        if(!rxdr->buffer_info) {
+               DPRINTK(PROBE, ERR,
+                "Unable to allocate receive descriptor ring\n");
                return -ENOMEM;
        }
        memset(rxdr->buffer_info, 0, size);
@@ -763,6 +772,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
 
        if(!rxdr->desc) {
                vfree(rxdr->buffer_info);
+               DPRINTK(PROBE, ERR,
+                "Unable to allocate receive descriptors\n");
                return -ENOMEM;
        }
        memset(rxdr->desc, 0, rxdr->size);
@@ -794,21 +805,14 @@ ixgb_setup_rctl(struct ixgb_adapter *adapter)
 
        rctl |= IXGB_RCTL_SECRC;
 
-       switch (adapter->rx_buffer_len) {
-       case IXGB_RXBUFFER_2048:
-       default:
+       if (adapter->rx_buffer_len <= IXGB_RXBUFFER_2048)
                rctl |= IXGB_RCTL_BSIZE_2048;
-               break;
-       case IXGB_RXBUFFER_4096:
+       else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_4096)
                rctl |= IXGB_RCTL_BSIZE_4096;
-               break;
-       case IXGB_RXBUFFER_8192:
+       else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_8192)
                rctl |= IXGB_RCTL_BSIZE_8192;
-               break;
-       case IXGB_RXBUFFER_16384:
+       else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_16384)
                rctl |= IXGB_RCTL_BSIZE_16384;
-               break;
-       }
 
        IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
 }
@@ -898,22 +902,25 @@ ixgb_free_tx_resources(struct ixgb_adapter *adapter)
        adapter->tx_ring.desc = NULL;
 }
 
-static inline void
+static void
 ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter,
                                        struct ixgb_buffer *buffer_info)
 {
        struct pci_dev *pdev = adapter->pdev;
-       if(buffer_info->dma) {
-               pci_unmap_page(pdev,
-                          buffer_info->dma,
-                          buffer_info->length,
-                          PCI_DMA_TODEVICE);
-               buffer_info->dma = 0;
-       }
-       if(buffer_info->skb) {
+
+       if (buffer_info->dma)
+               pci_unmap_page(pdev, buffer_info->dma, buffer_info->length,
+                              PCI_DMA_TODEVICE);
+
+       if (buffer_info->skb)
                dev_kfree_skb_any(buffer_info->skb);
-               buffer_info->skb = NULL;
-       }
+
+       buffer_info->skb = NULL;
+       buffer_info->dma = 0;
+       buffer_info->time_stamp = 0;
+       /* these fields must always be initialized in tx
+        * buffer_info->length = 0;
+        * buffer_info->next_to_watch = 0; */
 }
 
 /**
@@ -1112,8 +1119,8 @@ ixgb_watchdog(unsigned long data)
 
        if(adapter->hw.link_up) {
                if(!netif_carrier_ok(netdev)) {
-                       printk(KERN_INFO "ixgb: %s NIC Link is Up %d Mbps %s\n",
-                                  netdev->name, 10000, "Full Duplex");
+                       DPRINTK(LINK, INFO,
+                               "NIC Link is Up 10000 Mbps Full Duplex\n");
                        adapter->link_speed = 10000;
                        adapter->link_duplex = FULL_DUPLEX;
                        netif_carrier_on(netdev);
@@ -1123,9 +1130,7 @@ ixgb_watchdog(unsigned long data)
                if(netif_carrier_ok(netdev)) {
                        adapter->link_speed = 0;
                        adapter->link_duplex = 0;
-                       printk(KERN_INFO
-                                  "ixgb: %s NIC Link is Down\n",
-                                  netdev->name);
+                       DPRINTK(LINK, INFO, "NIC Link is Down\n");
                        netif_carrier_off(netdev);
                        netif_stop_queue(netdev);
 
@@ -1158,7 +1163,7 @@ ixgb_watchdog(unsigned long data)
 #define IXGB_TX_FLAGS_VLAN             0x00000002
 #define IXGB_TX_FLAGS_TSO              0x00000004
 
-static inline int
+static int
 ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
 {
 #ifdef NETIF_F_TSO
@@ -1220,7 +1225,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
        return 0;
 }
 
-static inline boolean_t
+static boolean_t
 ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
 {
        struct ixgb_context_desc *context_desc;
@@ -1258,7 +1263,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
 #define IXGB_MAX_TXD_PWR       14
 #define IXGB_MAX_DATA_PER_TXD  (1<<IXGB_MAX_TXD_PWR)
 
-static inline int
+static int
 ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
            unsigned int first)
 {
@@ -1284,6 +1289,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
                                size,
                                PCI_DMA_TODEVICE);
                buffer_info->time_stamp = jiffies;
+               buffer_info->next_to_watch = 0;
 
                len -= size;
                offset += size;
@@ -1309,6 +1315,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
                                        size,
                                        PCI_DMA_TODEVICE);
                        buffer_info->time_stamp = jiffies;
+                       buffer_info->next_to_watch = 0;
 
                        len -= size;
                        offset += size;
@@ -1323,7 +1330,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
        return count;
 }
 
-static inline void
+static void
 ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
 {
        struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
@@ -1395,13 +1402,26 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                return 0;
        }
 
+#ifdef NETIF_F_LLTX
+       local_irq_save(flags);
+       if (!spin_trylock(&adapter->tx_lock)) {
+               /* Collision - tell upper layer to requeue */
+               local_irq_restore(flags);
+               return NETDEV_TX_LOCKED;
+       }
+#else
        spin_lock_irqsave(&adapter->tx_lock, flags);
+#endif
+
        if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
                netif_stop_queue(netdev);
                spin_unlock_irqrestore(&adapter->tx_lock, flags);
-               return 1;
+               return NETDEV_TX_BUSY;
        }
+
+#ifndef NETIF_F_LLTX
        spin_unlock_irqrestore(&adapter->tx_lock, flags);
+#endif
 
        if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
                tx_flags |= IXGB_TX_FLAGS_VLAN;
@@ -1413,10 +1433,13 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        tso = ixgb_tso(adapter, skb);
        if (tso < 0) {
                dev_kfree_skb_any(skb);
+#ifdef NETIF_F_LLTX
+               spin_unlock_irqrestore(&adapter->tx_lock, flags);
+#endif
                return NETDEV_TX_OK;
        }
 
-       if (tso)
+       if (likely(tso))
                tx_flags |= IXGB_TX_FLAGS_TSO;
        else if(ixgb_tx_csum(adapter, skb))
                tx_flags |= IXGB_TX_FLAGS_CSUM;
@@ -1426,7 +1449,15 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
        netdev->trans_start = jiffies;
 
-       return 0;
+#ifdef NETIF_F_LLTX
+       /* Make sure there is space in the ring for the next send. */
+       if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED))
+               netif_stop_queue(netdev);
+
+       spin_unlock_irqrestore(&adapter->tx_lock, flags);
+
+#endif
+       return NETDEV_TX_OK;
 }
 
 /**
@@ -1448,6 +1479,7 @@ ixgb_tx_timeout_task(struct net_device *netdev)
 {
        struct ixgb_adapter *adapter = netdev_priv(netdev);
 
+       adapter->tx_timeout_count++;
        ixgb_down(adapter, TRUE);
        ixgb_up(adapter);
 }
@@ -1486,28 +1518,15 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)
 
        if((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
           || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
-               IXGB_ERR("Invalid MTU setting\n");
+               DPRINTK(PROBE, ERR, "Invalid MTU setting %d\n", new_mtu);
                return -EINVAL;
        }
 
-       if((max_frame <= IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
-          || (max_frame <= IXGB_RXBUFFER_2048)) {
-               adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
-
-       } else if(max_frame <= IXGB_RXBUFFER_4096) {
-               adapter->rx_buffer_len = IXGB_RXBUFFER_4096;
-
-       } else if(max_frame <= IXGB_RXBUFFER_8192) {
-               adapter->rx_buffer_len = IXGB_RXBUFFER_8192;
-
-       } else {
-               adapter->rx_buffer_len = IXGB_RXBUFFER_16384;
-       }
+       adapter->rx_buffer_len = max_frame;
 
        netdev->mtu = new_mtu;
 
-       if(old_max_frame != max_frame && netif_running(netdev)) {
-
+       if ((old_max_frame != max_frame) && netif_running(netdev)) {
                ixgb_down(adapter, TRUE);
                ixgb_up(adapter);
        }
@@ -1765,23 +1784,43 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
 
        tx_ring->next_to_clean = i;
 
-       spin_lock(&adapter->tx_lock);
-       if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
-          (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) {
-
-               netif_wake_queue(netdev);
+       if (unlikely(netif_queue_stopped(netdev))) {
+               spin_lock(&adapter->tx_lock);
+               if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
+                   (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE))
+                       netif_wake_queue(netdev);
+               spin_unlock(&adapter->tx_lock);
        }
-       spin_unlock(&adapter->tx_lock);
 
        if(adapter->detect_tx_hung) {
                /* detect a transmit hang in hardware, this serializes the
                 * check with the clearing of time_stamp and movement of i */
                adapter->detect_tx_hung = FALSE;
-               if(tx_ring->buffer_info[i].dma &&
-                  time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+               if (tx_ring->buffer_info[eop].dma &&
+                  time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ)
                   && !(IXGB_READ_REG(&adapter->hw, STATUS) &
-                       IXGB_STATUS_TXOFF))
+                       IXGB_STATUS_TXOFF)) {
+                       /* detected Tx unit hang */
+                       DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
+                                       "  TDH                  <%x>\n"
+                                       "  TDT                  <%x>\n"
+                                       "  next_to_use          <%x>\n"
+                                       "  next_to_clean        <%x>\n"
+                                       "buffer_info[next_to_clean]\n"
+                                       "  time_stamp           <%lx>\n"
+                                       "  next_to_watch        <%x>\n"
+                                       "  jiffies              <%lx>\n"
+                                       "  next_to_watch.status <%x>\n",
+                               IXGB_READ_REG(&adapter->hw, TDH),
+                               IXGB_READ_REG(&adapter->hw, TDT),
+                               tx_ring->next_to_use,
+                               tx_ring->next_to_clean,
+                               tx_ring->buffer_info[eop].time_stamp,
+                               eop,
+                               jiffies,
+                               eop_desc->status);
                        netif_stop_queue(netdev);
+               }
        }
 
        return cleaned;
@@ -1794,7 +1833,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
  * @sk_buff: socket buffer with received data
  **/
 
-static inline void
+static void
 ixgb_rx_checksum(struct ixgb_adapter *adapter,
                 struct ixgb_rx_desc *rx_desc,
                 struct sk_buff *skb)
@@ -1858,6 +1897,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
 #endif
                status = rx_desc->status;
                skb = buffer_info->skb;
+               buffer_info->skb = NULL;
 
                prefetch(skb->data);
 
@@ -1902,6 +1942,26 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
                        goto rxdesc_done;
                }
 
+               /* code added for copybreak, this should improve
+                * performance for small packets with large amounts
+                * of reassembly being done in the stack */
+#define IXGB_CB_LENGTH 256
+               if (length < IXGB_CB_LENGTH) {
+                       struct sk_buff *new_skb =
+                           dev_alloc_skb(length + NET_IP_ALIGN);
+                       if (new_skb) {
+                               skb_reserve(new_skb, NET_IP_ALIGN);
+                               new_skb->dev = netdev;
+                               memcpy(new_skb->data - NET_IP_ALIGN,
+                                      skb->data - NET_IP_ALIGN,
+                                      length + NET_IP_ALIGN);
+                               /* save the skb in buffer_info as good */
+                               buffer_info->skb = skb;
+                               skb = new_skb;
+                       }
+               }
+               /* end copybreak code */
+
                /* Good Receive */
                skb_put(skb, length);
 
@@ -1931,7 +1991,6 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
 rxdesc_done:
                /* clean up descriptor, might be written over by hw */
                rx_desc->status = 0;
-               buffer_info->skb = NULL;
 
                /* use prefetched values */
                rx_desc = next_rxd;
@@ -1971,12 +2030,18 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
 
        /* leave three descriptors unused */
        while(--cleancount > 2) {
-               rx_desc = IXGB_RX_DESC(*rx_ring, i);
-
-               skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+               /* recycle! its good for you */
+               if (!(skb = buffer_info->skb))
+                       skb = dev_alloc_skb(adapter->rx_buffer_len
+                                           + NET_IP_ALIGN);
+               else {
+                       skb_trim(skb, 0);
+                       goto map_skb;
+               }
 
-               if(unlikely(!skb)) {
+               if (unlikely(!skb)) {
                        /* Better luck next round */
+                       adapter->alloc_rx_buff_failed++;
                        break;
                }
 
@@ -1990,33 +2055,36 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
 
                buffer_info->skb = skb;
                buffer_info->length = adapter->rx_buffer_len;
-               buffer_info->dma =
-                       pci_map_single(pdev,
-                                  skb->data,
-                                  adapter->rx_buffer_len,
-                                  PCI_DMA_FROMDEVICE);
+map_skb:
+               buffer_info->dma = pci_map_single(pdev,
+                                                 skb->data,
+                                                 adapter->rx_buffer_len,
+                                                 PCI_DMA_FROMDEVICE);
 
+               rx_desc = IXGB_RX_DESC(*rx_ring, i);
                rx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
                /* guarantee DD bit not set now before h/w gets descriptor
                 * this is the rest of the workaround for h/w double 
                 * writeback. */
                rx_desc->status = 0;
 
-               if((i & ~(num_group_tail_writes- 1)) == i) {
-                       /* Force memory writes to complete before letting h/w
-                        * know there are new descriptors to fetch.  (Only
-                        * applicable for weak-ordered memory model archs,
-                        * such as IA-64). */
-                       wmb();
-
-                       IXGB_WRITE_REG(&adapter->hw, RDT, i);
-               }
 
                if(++i == rx_ring->count) i = 0;
                buffer_info = &rx_ring->buffer_info[i];
        }
 
-       rx_ring->next_to_use = i;
+       if (likely(rx_ring->next_to_use != i)) {
+               rx_ring->next_to_use = i;
+               if (unlikely(i-- == 0))
+                       i = (rx_ring->count - 1);
+
+               /* Force memory writes to complete before letting h/w
+                * know there are new descriptors to fetch.  (Only
+                * applicable for weak-ordered memory model archs, such
+                * as IA-64). */
+               wmb();
+               IXGB_WRITE_REG(&adapter->hw, RDT, i);
+       }
 }
 
 /**
index dba20481ee80126e70d0876a5893892ce680ce27..ee982feac64db7ab296ae03158b6ec5fd05eec36 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
index 8a83dfdf746d60c7e421a7cdb9ac3ff16c3797bc..39fbed29a3dfd9fc7018db044fa204546b3cb751 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. 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 
@@ -76,7 +76,7 @@ IXGB_PARAM(RxDescriptors, "Number of receive descriptors");
  *  - 2 - Tx only, generate PAUSE frames but ignore them on receive
  *  - 3 - Full Flow Control Support
  *
- * Default Value: Read flow control settings from the EEPROM
+ * Default Value: 2 - Tx only (silicon bug avoidance)
  */
 
 IXGB_PARAM(FlowControl, "Flow Control setting");
@@ -137,7 +137,7 @@ IXGB_PARAM(RxFCLowThresh, "Receive Flow Control Low Threshold");
  *
  * Valid Range: 1 - 65535 
  *
- * Default Value:  256 (0x100)
+ * Default Value:  65535 (0xffff) (we'll send an xon if we recover)
  */
 
 IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout");
@@ -165,8 +165,6 @@ IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");
 
 #define XSUMRX_DEFAULT          OPTION_ENABLED
 
-#define FLOW_CONTROL_FULL         ixgb_fc_full
-#define FLOW_CONTROL_DEFAULT  FLOW_CONTROL_FULL
 #define DEFAULT_FCRTL                  0x28000
 #define DEFAULT_FCRTH                  0x30000
 #define MIN_FCRTL                            0
@@ -174,9 +172,9 @@ IXGB_PARAM(IntDelayEnable, "Transmit Interrupt Delay Enable");
 #define MIN_FCRTH                            8
 #define MAX_FCRTH                      0x3FFF0
 
-#define DEFAULT_FCPAUSE                        0x100   /* this may be too long */
 #define MIN_FCPAUSE                          1
 #define MAX_FCPAUSE                     0xffff
+#define DEFAULT_FCPAUSE                         0xFFFF /* this may be too long */
 
 struct ixgb_option {
        enum { enable_option, range_option, list_option } type;
@@ -336,7 +334,7 @@ ixgb_check_options(struct ixgb_adapter *adapter)
                        .type = list_option,
                        .name = "Flow Control",
                        .err  = "reading default settings from EEPROM",
-                       .def  = ixgb_fc_full,
+                       .def  = ixgb_fc_tx_pause,
                        .arg  = { .l = { .nr = LIST_LEN(fc_list),
                                         .p = fc_list }}
                };
@@ -365,8 +363,8 @@ ixgb_check_options(struct ixgb_adapter *adapter)
                } else {
                        adapter->hw.fc.high_water = opt.def;
                }
-               if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
-                       printk (KERN_INFO 
+               if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
+                       printk (KERN_INFO
                                "Ignoring RxFCHighThresh when no RxFC\n");
        }
        { /* Receive Flow Control Low Threshold */
@@ -385,8 +383,8 @@ ixgb_check_options(struct ixgb_adapter *adapter)
                } else {
                        adapter->hw.fc.low_water = opt.def;
                }
-               if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
-                       printk (KERN_INFO 
+               if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
+                       printk (KERN_INFO
                                "Ignoring RxFCLowThresh when no RxFC\n");
        }
        { /* Flow Control Pause Time Request*/
@@ -406,12 +404,12 @@ ixgb_check_options(struct ixgb_adapter *adapter)
                } else {
                        adapter->hw.fc.pause_time = opt.def;
                }
-               if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
-                       printk (KERN_INFO 
+               if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
+                       printk (KERN_INFO
                                "Ignoring FCReqTimeout when no RxFC\n");
        }
        /* high low and spacing check for rx flow control thresholds */
-       if (adapter->hw.fc.type & ixgb_fc_rx_pause) {
+       if (adapter->hw.fc.type & ixgb_fc_tx_pause) {
                /* high must be greater than low */
                if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) {
                        /* set defaults */
index 411f4d809c477d99175ee0eaa10257938a08d407..625ff61c9988e7e0519c3dda2ba82f59cbc33d53 100644 (file)
@@ -1200,7 +1200,7 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        if (has_tiny_unaligned_frags(skb)) {
-               if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
+               if (__skb_linearize(skb)) {
                        stats->tx_dropped++;
                        printk(KERN_DEBUG "%s: failed to linearize tiny "
                                        "unaligned fragment\n", dev->name);
diff --git a/drivers/net/myri10ge/Makefile b/drivers/net/myri10ge/Makefile
new file mode 100644 (file)
index 0000000..5df8916
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Myricom Myri-10G ethernet driver
+#
+
+obj-$(CONFIG_MYRI10GE) += myri10ge.o
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
new file mode 100644 (file)
index 0000000..e1feb58
--- /dev/null
@@ -0,0 +1,2869 @@
+/*************************************************************************
+ * myri10ge.c: Myricom Myri-10G Ethernet driver.
+ *
+ * Copyright (C) 2005, 2006 Myricom, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Myricom, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * If the eeprom on your board is not recent enough, you will need to get a
+ * newer firmware image at:
+ *   http://www.myri.com/scs/download-Myri10GE.html
+ *
+ * Contact Information:
+ *   <help@myri.com>
+ *   Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006
+ *************************************************************************/
+
+#include <linux/tcp.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/inet.h>
+#include <linux/in.h>
+#include <linux/ethtool.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/timer.h>
+#include <linux/vmalloc.h>
+#include <linux/crc32.h>
+#include <linux/moduleparam.h>
+#include <linux/io.h>
+#include <net/checksum.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "myri10ge_mcp.h"
+#include "myri10ge_mcp_gen_header.h"
+
+#define MYRI10GE_VERSION_STR "1.0.0"
+
+MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
+MODULE_AUTHOR("Maintainer: help@myri.com");
+MODULE_VERSION(MYRI10GE_VERSION_STR);
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define MYRI10GE_MAX_ETHER_MTU 9014
+
+#define MYRI10GE_ETH_STOPPED 0
+#define MYRI10GE_ETH_STOPPING 1
+#define MYRI10GE_ETH_STARTING 2
+#define MYRI10GE_ETH_RUNNING 3
+#define MYRI10GE_ETH_OPEN_FAILED 4
+
+#define MYRI10GE_EEPROM_STRINGS_SIZE 256
+#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
+
+#define MYRI10GE_NO_CONFIRM_DATA 0xffffffff
+#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
+
+struct myri10ge_rx_buffer_state {
+       struct sk_buff *skb;
+        DECLARE_PCI_UNMAP_ADDR(bus)
+        DECLARE_PCI_UNMAP_LEN(len)
+};
+
+struct myri10ge_tx_buffer_state {
+       struct sk_buff *skb;
+       int last;
+        DECLARE_PCI_UNMAP_ADDR(bus)
+        DECLARE_PCI_UNMAP_LEN(len)
+};
+
+struct myri10ge_cmd {
+       u32 data0;
+       u32 data1;
+       u32 data2;
+};
+
+struct myri10ge_rx_buf {
+       struct mcp_kreq_ether_recv __iomem *lanai;      /* lanai ptr for recv ring */
+       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;
+       int cnt;
+       int alloc_fail;
+       int mask;               /* number of rx slots -1 */
+};
+
+struct myri10ge_tx_buf {
+       struct mcp_kreq_ether_send __iomem *lanai;      /* lanai ptr for sendq */
+       u8 __iomem *wc_fifo;    /* w/c send fifo address */
+       struct mcp_kreq_ether_send *req_list;   /* host shadow of sendq */
+       char *req_bytes;
+       struct myri10ge_tx_buffer_state *info;
+       int mask;               /* number of transmit slots -1  */
+       int boundary;           /* boundary transmits cannot cross */
+       int req ____cacheline_aligned;  /* transmit slots submitted     */
+       int pkt_start;          /* packets started */
+       int done ____cacheline_aligned; /* transmit slots completed     */
+       int pkt_done;           /* packets completed */
+};
+
+struct myri10ge_rx_done {
+       struct mcp_slot *entry;
+       dma_addr_t bus;
+       int cnt;
+       int idx;
+};
+
+struct myri10ge_priv {
+       int running;            /* running?             */
+       int csum_flag;          /* rx_csums?            */
+       struct myri10ge_tx_buf tx;      /* transmit ring        */
+       struct myri10ge_rx_buf rx_small;
+       struct myri10ge_rx_buf rx_big;
+       struct myri10ge_rx_done rx_done;
+       int small_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;
+       char *mac_addr_string;
+       struct mcp_cmd_response *cmd;
+       dma_addr_t cmd_bus;
+       struct mcp_irq_data *fw_stats;
+       dma_addr_t fw_stats_bus;
+       struct pci_dev *pdev;
+       int msi_enabled;
+       unsigned int link_state;
+       unsigned int rdma_tags_available;
+       int intr_coal_delay;
+       u32 __iomem *intr_coal_delay_ptr;
+       int mtrr;
+       int wake_queue;
+       int stop_queue;
+       int down_cnt;
+       wait_queue_head_t down_wq;
+       struct work_struct watchdog_work;
+       struct timer_list watchdog_timer;
+       int watchdog_tx_done;
+       int watchdog_resets;
+       int tx_linearized;
+       int pause;
+       char *fw_name;
+       char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE];
+       char fw_version[128];
+       u8 mac_addr[6];         /* eeprom mac address */
+       unsigned long serial_number;
+       int vendor_specific_offset;
+       u32 devctl;
+       u16 msi_flags;
+       u32 pm_state[16];
+       u32 read_dma;
+       u32 write_dma;
+       u32 read_write_dma;
+};
+
+static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
+static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat";
+
+static char *myri10ge_fw_name = NULL;
+module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name\n");
+
+static int myri10ge_ecrc_enable = 1;
+module_param(myri10ge_ecrc_enable, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E\n");
+
+static int myri10ge_max_intr_slots = 1024;
+module_param(myri10ge_max_intr_slots, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_max_intr_slots, "Interrupt queue slots\n");
+
+static int myri10ge_small_bytes = -1;  /* -1 == auto */
+module_param(myri10ge_small_bytes, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets\n");
+
+static int myri10ge_msi = 1;   /* enable msi by default */
+module_param(myri10ge_msi, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n");
+
+static int myri10ge_intr_coal_delay = 25;
+module_param(myri10ge_intr_coal_delay, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n");
+
+static int myri10ge_flow_control = 1;
+module_param(myri10ge_flow_control, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_flow_control, "Pause parameter\n");
+
+static int myri10ge_deassert_wait = 1;
+module_param(myri10ge_deassert_wait, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_deassert_wait,
+                "Wait when deasserting legacy interrupts\n");
+
+static int myri10ge_force_firmware = 0;
+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");
+
+static int myri10ge_napi_weight = 64;
+module_param(myri10ge_napi_weight, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_napi_weight, "Set NAPI weight\n");
+
+static int myri10ge_watchdog_timeout = 1;
+module_param(myri10ge_watchdog_timeout, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_watchdog_timeout, "Set watchdog timeout\n");
+
+static int myri10ge_max_irq_loops = 1048576;
+module_param(myri10ge_max_irq_loops, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_max_irq_loops,
+                "Set stuck legacy IRQ detection threshold\n");
+
+#define MYRI10GE_FW_OFFSET 1024*1024
+#define MYRI10GE_HIGHPART_TO_U32(X) \
+(sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
+#define MYRI10GE_LOWPART_TO_U32(X) ((u32)(X))
+
+#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
+
+static int
+myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
+                 struct myri10ge_cmd *data, int atomic)
+{
+       struct mcp_cmd *buf;
+       char buf_bytes[sizeof(*buf) + 8];
+       struct mcp_cmd_response *response = mgp->cmd;
+       char __iomem *cmd_addr = mgp->sram + MXGEFW_CMD_OFFSET;
+       u32 dma_low, dma_high, result, value;
+       int sleep_total = 0;
+
+       /* ensure buf is aligned to 8 bytes */
+       buf = (struct mcp_cmd *)ALIGN((unsigned long)buf_bytes, 8);
+
+       buf->data0 = htonl(data->data0);
+       buf->data1 = htonl(data->data1);
+       buf->data2 = htonl(data->data2);
+       buf->cmd = htonl(cmd);
+       dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+       dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+       buf->response_addr.low = htonl(dma_low);
+       buf->response_addr.high = htonl(dma_high);
+       response->result = MYRI10GE_NO_RESPONSE_RESULT;
+       mb();
+       myri10ge_pio_copy(cmd_addr, buf, sizeof(*buf));
+
+       /* wait up to 15ms. Longest command is the DMA benchmark,
+        * which is capped at 5ms, but runs from a timeout handler
+        * that runs every 7.8ms. So a 15ms timeout leaves us with
+        * a 2.2ms margin
+        */
+       if (atomic) {
+               /* if atomic is set, do not sleep,
+                * and try to get the completion quickly
+                * (1ms will be enough for those commands) */
+               for (sleep_total = 0;
+                    sleep_total < 1000
+                    && response->result == 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;
+                    sleep_total++)
+                       msleep(1);
+       }
+
+       result = ntohl(response->result);
+       value = ntohl(response->data);
+       if (result != MYRI10GE_NO_RESPONSE_RESULT) {
+               if (result == 0) {
+                       data->data0 = value;
+                       return 0;
+               } else {
+                       dev_err(&mgp->pdev->dev,
+                               "command %d failed, result = %d\n",
+                               cmd, result);
+                       return -ENXIO;
+               }
+       }
+
+       dev_err(&mgp->pdev->dev, "command %d timed out, result = %d\n",
+               cmd, result);
+       return -EAGAIN;
+}
+
+/*
+ * The eeprom strings on the lanaiX have the format
+ * SN=x\0
+ * MAC=x:x:x:x:x:x\0
+ * PT:ddd mmm xx xx:xx:xx xx\0
+ * PV:ddd mmm xx xx:xx:xx xx\0
+ */
+static int myri10ge_read_mac_addr(struct myri10ge_priv *mgp)
+{
+       char *ptr, *limit;
+       int i;
+
+       ptr = mgp->eeprom_strings;
+       limit = mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE;
+
+       while (*ptr != '\0' && ptr < limit) {
+               if (memcmp(ptr, "MAC=", 4) == 0) {
+                       ptr += 4;
+                       mgp->mac_addr_string = ptr;
+                       for (i = 0; i < 6; i++) {
+                               if ((ptr + 2) > limit)
+                                       goto abort;
+                               mgp->mac_addr[i] =
+                                   simple_strtoul(ptr, &ptr, 16);
+                               ptr += 1;
+                       }
+               }
+               if (memcmp((const void *)ptr, "SN=", 3) == 0) {
+                       ptr += 3;
+                       mgp->serial_number = simple_strtoul(ptr, &ptr, 10);
+               }
+               while (ptr < limit && *ptr++) ;
+       }
+
+       return 0;
+
+abort:
+       dev_err(&mgp->pdev->dev, "failed to parse eeprom_strings\n");
+       return -ENXIO;
+}
+
+/*
+ * Enable or disable periodic RDMAs from the host to make certain
+ * chipsets resend dropped PCIe messages
+ */
+
+static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
+{
+       char __iomem *submit;
+       u32 buf[16];
+       u32 dma_low, dma_high;
+       int i;
+
+       /* clear confirmation addr */
+       mgp->cmd->data = 0;
+       mb();
+
+       /* send a rdma command to the PCIe engine, and wait for the
+        * response in the confirmation address.  The firmware should
+        * write a -1 there to indicate it is alive and well
+        */
+       dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+       dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+       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[3] = htonl(dma_high);       /* dummy addr MSW */
+       buf[4] = htonl(dma_low);        /* dummy addr LSW */
+       buf[5] = htonl(enable); /* enable? */
+
+       submit = mgp->sram + 0xfc01c0;
+
+       myri10ge_pio_copy(submit, &buf, sizeof(buf));
+       for (i = 0; mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20; i++)
+               msleep(1);
+       if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA)
+               dev_err(&mgp->pdev->dev, "dummy rdma %s failed\n",
+                       (enable ? "enable" : "disable"));
+}
+
+static int
+myri10ge_validate_firmware(struct myri10ge_priv *mgp,
+                          struct mcp_gen_header *hdr)
+{
+       struct device *dev = &mgp->pdev->dev;
+       int major, minor;
+
+       /* check firmware type */
+       if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) {
+               dev_err(dev, "Bad firmware type: 0x%x\n", ntohl(hdr->mcp_type));
+               return -EINVAL;
+       }
+
+       /* save firmware version for ethtool */
+       strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version));
+
+       sscanf(mgp->fw_version, "%d.%d", &major, &minor);
+
+       if (!(major == MXGEFW_VERSION_MAJOR && minor == MXGEFW_VERSION_MINOR)) {
+               dev_err(dev, "Found firmware version %s\n", mgp->fw_version);
+               dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR,
+                       MXGEFW_VERSION_MINOR);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size)
+{
+       unsigned crc, reread_crc;
+       const struct firmware *fw;
+       struct device *dev = &mgp->pdev->dev;
+       struct mcp_gen_header *hdr;
+       size_t hdr_offset;
+       int status;
+
+       if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) {
+               dev_err(dev, "Unable to load %s firmware image via hotplug\n",
+                       mgp->fw_name);
+               status = -EINVAL;
+               goto abort_with_nothing;
+       }
+
+       /* check size */
+
+       if (fw->size >= mgp->sram_size - MYRI10GE_FW_OFFSET ||
+           fw->size < MCP_HEADER_PTR_OFFSET + 4) {
+               dev_err(dev, "Firmware size invalid:%d\n", (int)fw->size);
+               status = -EINVAL;
+               goto abort_with_fw;
+       }
+
+       /* check id */
+       hdr_offset = ntohl(*(u32 *) (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;
+               goto abort_with_fw;
+       }
+       hdr = (void *)(fw->data + hdr_offset);
+
+       status = myri10ge_validate_firmware(mgp, hdr);
+       if (status != 0)
+               goto abort_with_fw;
+
+       crc = crc32(~0, fw->data, fw->size);
+       if (mgp->tx.boundary == 2048) {
+               /* Avoid PCI burst on chipset with unaligned completions. */
+               int i;
+               __iomem u32 *ptr = (__iomem u32 *) (mgp->sram +
+                                                   MYRI10GE_FW_OFFSET);
+               for (i = 0; i < fw->size / 4; i++) {
+                       __raw_writel(((u32 *) fw->data)[i], ptr + i);
+                       wmb();
+               }
+       } else {
+               myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET, fw->data,
+                                 fw->size);
+       }
+       /* corruption checking is good for parity recovery and buggy chipset */
+       memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size);
+       reread_crc = crc32(~0, fw->data, fw->size);
+       if (crc != reread_crc) {
+               dev_err(dev, "CRC failed(fw-len=%u), got 0x%x (expect 0x%x)\n",
+                       (unsigned)fw->size, reread_crc, crc);
+               status = -EIO;
+               goto abort_with_fw;
+       }
+       *size = (u32) fw->size;
+
+abort_with_fw:
+       release_firmware(fw);
+
+abort_with_nothing:
+       return status;
+}
+
+static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp)
+{
+       struct mcp_gen_header *hdr;
+       struct device *dev = &mgp->pdev->dev;
+       const size_t bytes = sizeof(struct mcp_gen_header);
+       size_t hdr_offset;
+       int status;
+
+       /* find running firmware header */
+       hdr_offset = ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET));
+
+       if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > mgp->sram_size) {
+               dev_err(dev, "Running firmware has bad header offset (%d)\n",
+                       (int)hdr_offset);
+               return -EIO;
+       }
+
+       /* copy header of running firmware from SRAM to host memory to
+        * validate firmware */
+       hdr = kmalloc(bytes, GFP_KERNEL);
+       if (hdr == NULL) {
+               dev_err(dev, "could not malloc firmware hdr\n");
+               return -ENOMEM;
+       }
+       memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes);
+       status = myri10ge_validate_firmware(mgp, hdr);
+       kfree(hdr);
+       return status;
+}
+
+static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
+{
+       char __iomem *submit;
+       u32 buf[16];
+       u32 dma_low, dma_high, size;
+       int status, i;
+
+       size = 0;
+       status = myri10ge_load_hotplug_firmware(mgp, &size);
+       if (status) {
+               dev_warn(&mgp->pdev->dev, "hotplug firmware loading failed\n");
+
+               /* Do not attempt to adopt firmware if there
+                * was a bad crc */
+               if (status == -EIO)
+                       return status;
+
+               status = myri10ge_adopt_running_firmware(mgp);
+               if (status != 0) {
+                       dev_err(&mgp->pdev->dev,
+                               "failed to adopt running firmware\n");
+                       return status;
+               }
+               dev_info(&mgp->pdev->dev,
+                        "Successfully adopted running firmware\n");
+               if (mgp->tx.boundary == 4096) {
+                       dev_warn(&mgp->pdev->dev,
+                                "Using firmware currently running on NIC"
+                                ".  For optimal\n");
+                       dev_warn(&mgp->pdev->dev,
+                                "performance consider loading optimized "
+                                "firmware\n");
+                       dev_warn(&mgp->pdev->dev, "via hotplug\n");
+               }
+
+               mgp->fw_name = "adopted";
+               mgp->tx.boundary = 2048;
+               return status;
+       }
+
+       /* clear confirmation addr */
+       mgp->cmd->data = 0;
+       mb();
+
+       /* send a reload command to the bootstrap MCP, and wait for the
+        *  response in the confirmation address.  The firmware should
+        * write a -1 there to indicate it is alive and well
+        */
+       dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+       dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+       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 */
+
+       /* FIX: All newest firmware should un-protect the bottom of
+        * the sram before handoff. However, the very first interfaces
+        * do not. Therefore the handoff copy must skip the first 8 bytes
+        */
+       buf[3] = htonl(MYRI10GE_FW_OFFSET + 8); /* where the code starts */
+       buf[4] = htonl(size - 8);       /* length of code */
+       buf[5] = htonl(8);      /* where to copy to */
+       buf[6] = htonl(0);      /* where to jump to */
+
+       submit = mgp->sram + 0xfc0000;
+
+       myri10ge_pio_copy(submit, &buf, sizeof(buf));
+       mb();
+       msleep(1);
+       mb();
+       i = 0;
+       while (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20) {
+               msleep(1);
+               i++;
+       }
+       if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) {
+               dev_err(&mgp->pdev->dev, "handoff failed\n");
+               return -ENXIO;
+       }
+       dev_info(&mgp->pdev->dev, "handoff confirmed\n");
+       myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096);
+
+       return 0;
+}
+
+static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, u8 * addr)
+{
+       struct myri10ge_cmd cmd;
+       int status;
+
+       cmd.data0 = ((addr[0] << 24) | (addr[1] << 16)
+                    | (addr[2] << 8) | addr[3]);
+
+       cmd.data1 = ((addr[4] << 8) | (addr[5]));
+
+       status = myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd, 0);
+       return status;
+}
+
+static int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause)
+{
+       struct myri10ge_cmd cmd;
+       int status, ctl;
+
+       ctl = pause ? MXGEFW_ENABLE_FLOW_CONTROL : MXGEFW_DISABLE_FLOW_CONTROL;
+       status = myri10ge_send_cmd(mgp, ctl, &cmd, 0);
+
+       if (status) {
+               printk(KERN_ERR
+                      "myri10ge: %s: Failed to set flow control mode\n",
+                      mgp->dev->name);
+               return status;
+       }
+       mgp->pause = pause;
+       return 0;
+}
+
+static void
+myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc, int atomic)
+{
+       struct myri10ge_cmd cmd;
+       int status, ctl;
+
+       ctl = promisc ? MXGEFW_ENABLE_PROMISC : MXGEFW_DISABLE_PROMISC;
+       status = myri10ge_send_cmd(mgp, ctl, &cmd, atomic);
+       if (status)
+               printk(KERN_ERR "myri10ge: %s: Failed to set promisc mode\n",
+                      mgp->dev->name);
+}
+
+static int myri10ge_reset(struct myri10ge_priv *mgp)
+{
+       struct myri10ge_cmd cmd;
+       int status;
+       size_t bytes;
+       u32 len;
+
+       /* try to send a reset command to the card to see if it
+        * is alive */
+       memset(&cmd, 0, sizeof(cmd));
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd, 0);
+       if (status != 0) {
+               dev_err(&mgp->pdev->dev, "failed reset\n");
+               return -ENXIO;
+       }
+
+       /* Now exchange information about interrupts  */
+
+       bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+       memset(mgp->rx_done.entry, 0, bytes);
+       cmd.data0 = (u32) bytes;
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd, 0);
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, &cmd, 0);
+
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
+       mgp->irq_claim = (__iomem u32 *) (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);
+
+       }
+       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);
+       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);
+
+       /* Run a small DMA test.
+        * The magic multipliers to the length tell the firmware
+        * to do DMA read, write, or read+write tests.  The
+        * results are returned in cmd.data0.  The upper 16
+        * bits or the return is the number of transfers completed.
+        * The lower 16 bits is the time in 0.5us ticks that the
+        * transfers took to complete.
+        */
+
+       len = mgp->tx.boundary;
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data2 = len * 0x10000;
+       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+       if (status == 0)
+               mgp->read_dma = ((cmd.data0 >> 16) * len * 2) /
+                   (cmd.data0 & 0xffff);
+       else
+               dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n",
+                        status);
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data2 = len * 0x1;
+       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+       if (status == 0)
+               mgp->write_dma = ((cmd.data0 >> 16) * len * 2) /
+                   (cmd.data0 & 0xffff);
+       else
+               dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n",
+                        status);
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+       cmd.data2 = len * 0x10001;
+       status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+       if (status == 0)
+               mgp->read_write_dma = ((cmd.data0 >> 16) * len * 2 * 2) /
+                   (cmd.data0 & 0xffff);
+       else
+               dev_warn(&mgp->pdev->dev,
+                        "DMA read/write benchmark failed: %d\n", status);
+
+       memset(mgp->rx_done.entry, 0, bytes);
+
+       /* reset mcp/driver shared state back to 0 */
+       mgp->tx.req = 0;
+       mgp->tx.done = 0;
+       mgp->tx.pkt_start = 0;
+       mgp->tx.pkt_done = 0;
+       mgp->rx_big.cnt = 0;
+       mgp->rx_small.cnt = 0;
+       mgp->rx_done.idx = 0;
+       mgp->rx_done.cnt = 0;
+       status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr);
+       myri10ge_change_promisc(mgp, 0, 0);
+       myri10ge_change_pause(mgp, mgp->pause);
+       return status;
+}
+
+static inline void
+myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
+                   struct mcp_kreq_ether_recv *src)
+{
+       u32 low;
+
+       low = src->addr_low;
+       src->addr_low = DMA_32BIT_MASK;
+       myri10ge_pio_copy(dst, src, 8 * sizeof(*src));
+       mb();
+       src->addr_low = low;
+       __raw_writel(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(int bytes)
+{
+       struct sk_buff *skb;
+       unsigned long data, roundup;
+
+       skb = dev_alloc_skb(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(unsigned int bytes)
+{
+       struct sk_buff *skb;
+       unsigned long data, boundary;
+
+       skb = dev_alloc_skb(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;
+
+       skb_reserve(skb, boundary - data);
+       return skb;
+}
+
+/* Allocate just enough space, and verify that the allocated
+ * space does not cross a 4KB boundary */
+static inline struct sk_buff *myri10ge_alloc_small(int bytes)
+{
+       struct sk_buff *skb;
+       unsigned long roundup, data, end;
+
+       skb = dev_alloc_skb(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(bytes);
+       }
+       return skb;
+}
+
+static inline int
+myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes,
+               int idx)
+{
+       struct sk_buff *skb;
+       dma_addr_t bus;
+       int len, retval = 0;
+
+       bytes += VLAN_HLEN;     /* account for 802.1q vlan tag */
+
+       if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ )
+               skb = myri10ge_alloc_big(bytes);
+       else if (myri10ge_skb_cross_4k)
+               skb = myri10ge_alloc_small_safe(bytes);
+       else
+               skb = myri10ge_alloc_small(bytes);
+
+       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);
+               }
+       }
+       return retval;
+}
+
+static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum)
+{
+       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_HW;
+       }
+}
+
+static inline unsigned long
+myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
+                int bytes, int len, int csum)
+{
+       dma_addr_t bus;
+       struct sk_buff *skb;
+       int idx, unmap_len;
+
+       idx = rx->cnt & rx->mask;
+       rx->cnt++;
+
+       /* 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);
+
+       /* try to replace the received skb */
+       if (myri10ge_getbuf(rx, mgp->pdev, bytes, idx)) {
+               /* drop the frame -- the old skbuf is re-cycled */
+               mgp->stats.rx_dropped += 1;
+               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);
+
+       skb->protocol = eth_type_trans(skb, mgp->dev);
+       skb->dev = mgp->dev;
+       if (mgp->csum_flag) {
+               if ((skb->protocol == ntohs(ETH_P_IP)) ||
+                   (skb->protocol == ntohs(ETH_P_IPV6))) {
+                       skb->csum = ntohs((u16) csum);
+                       skb->ip_summed = CHECKSUM_HW;
+               } else
+                       myri10ge_vlan_ip_csum(skb, ntohs((u16) csum));
+       }
+
+       netif_receive_skb(skb);
+       mgp->dev->last_rx = jiffies;
+       return 1;
+}
+
+static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index)
+{
+       struct pci_dev *pdev = mgp->pdev;
+       struct myri10ge_tx_buf *tx = &mgp->tx;
+       struct sk_buff *skb;
+       int idx, len;
+       int limit = 0;
+
+       while (tx->pkt_done != mcp_index) {
+               idx = tx->done & tx->mask;
+               skb = tx->info[idx].skb;
+
+               /* Mark as free */
+               tx->info[idx].skb = NULL;
+               if (tx->info[idx].last) {
+                       tx->pkt_done++;
+                       tx->info[idx].last = 0;
+               }
+               tx->done++;
+               len = pci_unmap_len(&tx->info[idx], len);
+               pci_unmap_len_set(&tx->info[idx], len, 0);
+               if (skb) {
+                       mgp->stats.tx_bytes += skb->len;
+                       mgp->stats.tx_packets++;
+                       dev_kfree_skb_irq(skb);
+                       if (len)
+                               pci_unmap_single(pdev,
+                                                pci_unmap_addr(&tx->info[idx],
+                                                               bus), len,
+                                                PCI_DMA_TODEVICE);
+               } else {
+                       if (len)
+                               pci_unmap_page(pdev,
+                                              pci_unmap_addr(&tx->info[idx],
+                                                             bus), len,
+                                              PCI_DMA_TODEVICE);
+               }
+
+               /* limit potential for livelock by only handling
+                * 2 full tx rings per call */
+               if (unlikely(++limit > 2 * tx->mask))
+                       break;
+       }
+       /* start the queue if we've stopped it */
+       if (netif_queue_stopped(mgp->dev)
+           && tx->req - tx->done < (tx->mask >> 1)) {
+               mgp->wake_queue++;
+               netif_wake_queue(mgp->dev);
+       }
+}
+
+static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
+{
+       struct myri10ge_rx_done *rx_done = &mgp->rx_done;
+       unsigned long rx_bytes = 0;
+       unsigned long rx_packets = 0;
+       unsigned long rx_ok;
+
+       int idx = rx_done->idx;
+       int cnt = rx_done->cnt;
+       u16 length;
+       u16 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);
+               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,
+                                                length, checksum);
+               rx_packets += rx_ok;
+               rx_bytes += rx_ok * (unsigned long)length;
+               cnt++;
+               idx = cnt & (myri10ge_max_intr_slots - 1);
+
+               /* limit potential for livelock by only handling a
+                * limited number of frames. */
+               (*limit)--;
+       }
+       rx_done->idx = idx;
+       rx_done->cnt = cnt;
+       mgp->stats.rx_packets += rx_packets;
+       mgp->stats.rx_bytes += rx_bytes;
+}
+
+static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
+{
+       struct mcp_irq_data *stats = mgp->fw_stats;
+
+       if (unlikely(stats->stats_updated)) {
+               if (mgp->link_state != stats->link_up) {
+                       mgp->link_state = stats->link_up;
+                       if (mgp->link_state) {
+                               printk(KERN_INFO "myri10ge: %s: link up\n",
+                                      mgp->dev->name);
+                               netif_carrier_on(mgp->dev);
+                       } else {
+                               printk(KERN_INFO "myri10ge: %s: link down\n",
+                                      mgp->dev->name);
+                               netif_carrier_off(mgp->dev);
+                       }
+               }
+               if (mgp->rdma_tags_available !=
+                   ntohl(mgp->fw_stats->rdma_tags_available)) {
+                       mgp->rdma_tags_available =
+                           ntohl(mgp->fw_stats->rdma_tags_available);
+                       printk(KERN_WARNING "myri10ge: %s: RDMA timed out! "
+                              "%d tags left\n", mgp->dev->name,
+                              mgp->rdma_tags_available);
+               }
+               mgp->down_cnt += stats->link_down;
+               if (stats->link_down)
+                       wake_up(&mgp->down_wq);
+       }
+}
+
+static int myri10ge_poll(struct net_device *netdev, int *budget)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       struct myri10ge_rx_done *rx_done = &mgp->rx_done;
+       int limit, orig_limit, work_done;
+
+       /* process as many rx events as NAPI will allow */
+       limit = min(*budget, netdev->quota);
+       orig_limit = limit;
+       myri10ge_clean_rx_done(mgp, &limit);
+       work_done = orig_limit - limit;
+       *budget -= work_done;
+       netdev->quota -= work_done;
+
+       if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) {
+               netif_rx_complete(netdev);
+               __raw_writel(htonl(3), mgp->irq_claim);
+               return 0;
+       }
+       return 1;
+}
+
+static irqreturn_t myri10ge_intr(int irq, void *arg, struct pt_regs *regs)
+{
+       struct myri10ge_priv *mgp = arg;
+       struct mcp_irq_data *stats = mgp->fw_stats;
+       struct myri10ge_tx_buf *tx = &mgp->tx;
+       u32 send_done_count;
+       int i;
+
+       /* make sure it is our IRQ, and that the DMA has finished */
+       if (unlikely(!stats->valid))
+               return (IRQ_NONE);
+
+       /* low bit indicates receives are present, so schedule
+        * napi poll handler */
+       if (stats->valid & 1)
+               netif_rx_schedule(mgp->dev);
+
+       if (!mgp->msi_enabled) {
+               __raw_writel(0, mgp->irq_deassert);
+               if (!myri10ge_deassert_wait)
+                       stats->valid = 0;
+               mb();
+       } else
+               stats->valid = 0;
+
+       /* Wait for IRQ line to go low, if using INTx */
+       i = 0;
+       while (1) {
+               i++;
+               /* check for transmit completes and receives */
+               send_done_count = ntohl(stats->send_done_count);
+               if (send_done_count != tx->pkt_done)
+                       myri10ge_tx_done(mgp, (int)send_done_count);
+               if (unlikely(i > myri10ge_max_irq_loops)) {
+                       printk(KERN_WARNING "myri10ge: %s: irq stuck?\n",
+                              mgp->dev->name);
+                       stats->valid = 0;
+                       schedule_work(&mgp->watchdog_work);
+               }
+               if (likely(stats->valid == 0))
+                       break;
+               cpu_relax();
+               barrier();
+       }
+
+       myri10ge_check_statblock(mgp);
+
+       __raw_writel(htonl(3), mgp->irq_claim + 1);
+       return (IRQ_HANDLED);
+}
+
+static int
+myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+       cmd->autoneg = AUTONEG_DISABLE;
+       cmd->speed = SPEED_10000;
+       cmd->duplex = DUPLEX_FULL;
+       return 0;
+}
+
+static void
+myri10ge_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       strlcpy(info->driver, "myri10ge", sizeof(info->driver));
+       strlcpy(info->version, MYRI10GE_VERSION_STR, sizeof(info->version));
+       strlcpy(info->fw_version, mgp->fw_version, sizeof(info->fw_version));
+       strlcpy(info->bus_info, pci_name(mgp->pdev), sizeof(info->bus_info));
+}
+
+static int
+myri10ge_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       coal->rx_coalesce_usecs = mgp->intr_coal_delay;
+       return 0;
+}
+
+static int
+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);
+       return 0;
+}
+
+static void
+myri10ge_get_pauseparam(struct net_device *netdev,
+                       struct ethtool_pauseparam *pause)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       pause->autoneg = 0;
+       pause->rx_pause = mgp->pause;
+       pause->tx_pause = mgp->pause;
+}
+
+static int
+myri10ge_set_pauseparam(struct net_device *netdev,
+                       struct ethtool_pauseparam *pause)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       if (pause->tx_pause != mgp->pause)
+               return myri10ge_change_pause(mgp, pause->tx_pause);
+       if (pause->rx_pause != mgp->pause)
+               return myri10ge_change_pause(mgp, pause->tx_pause);
+       if (pause->autoneg != 0)
+               return -EINVAL;
+       return 0;
+}
+
+static void
+myri10ge_get_ringparam(struct net_device *netdev,
+                      struct ethtool_ringparam *ring)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+       ring->rx_mini_max_pending = mgp->rx_small.mask + 1;
+       ring->rx_max_pending = mgp->rx_big.mask + 1;
+       ring->rx_jumbo_max_pending = 0;
+       ring->tx_max_pending = mgp->rx_small.mask + 1;
+       ring->rx_mini_pending = ring->rx_mini_max_pending;
+       ring->rx_pending = ring->rx_max_pending;
+       ring->rx_jumbo_pending = ring->rx_jumbo_max_pending;
+       ring->tx_pending = ring->tx_max_pending;
+}
+
+static u32 myri10ge_get_rx_csum(struct net_device *netdev)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       if (mgp->csum_flag)
+               return 1;
+       else
+               return 0;
+}
+
+static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       if (csum_enabled)
+               mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
+       else
+               mgp->csum_flag = 0;
+       return 0;
+}
+
+static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
+       "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
+       "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
+       "rx_length_errors", "rx_over_errors", "rx_crc_errors",
+       "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
+       "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
+       "tx_heartbeat_errors", "tx_window_errors",
+       /* device-specific stats */
+       "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
+       "serial_number", "tx_pkt_start", "tx_pkt_done",
+       "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt",
+       "wake_queue", "stop_queue", "watchdog_resets", "tx_linearized",
+       "link_up", "dropped_link_overflow", "dropped_link_error_or_filtered",
+       "dropped_runt", "dropped_overrun", "dropped_no_small_buffer",
+       "dropped_no_big_buffer"
+};
+
+#define MYRI10GE_NET_STATS_LEN      21
+#define MYRI10GE_STATS_LEN  sizeof(myri10ge_gstrings_stats) / ETH_GSTRING_LEN
+
+static void
+myri10ge_get_strings(struct net_device *netdev, u32 stringset, u8 * data)
+{
+       switch (stringset) {
+       case ETH_SS_STATS:
+               memcpy(data, *myri10ge_gstrings_stats,
+                      sizeof(myri10ge_gstrings_stats));
+               break;
+       }
+}
+
+static int myri10ge_get_stats_count(struct net_device *netdev)
+{
+       return MYRI10GE_STATS_LEN;
+}
+
+static void
+myri10ge_get_ethtool_stats(struct net_device *netdev,
+                          struct ethtool_stats *stats, u64 * data)
+{
+       struct myri10ge_priv *mgp = netdev_priv(netdev);
+       int i;
+
+       for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
+               data[i] = ((unsigned long *)&mgp->stats)[i];
+
+       data[i++] = (unsigned int)mgp->read_dma;
+       data[i++] = (unsigned int)mgp->write_dma;
+       data[i++] = (unsigned int)mgp->read_write_dma;
+       data[i++] = (unsigned int)mgp->serial_number;
+       data[i++] = (unsigned int)mgp->tx.pkt_start;
+       data[i++] = (unsigned int)mgp->tx.pkt_done;
+       data[i++] = (unsigned int)mgp->tx.req;
+       data[i++] = (unsigned int)mgp->tx.done;
+       data[i++] = (unsigned int)mgp->rx_small.cnt;
+       data[i++] = (unsigned int)mgp->rx_big.cnt;
+       data[i++] = (unsigned int)mgp->wake_queue;
+       data[i++] = (unsigned int)mgp->stop_queue;
+       data[i++] = (unsigned int)mgp->watchdog_resets;
+       data[i++] = (unsigned int)mgp->tx_linearized;
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->link_up);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow);
+       data[i++] =
+           (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer);
+       data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer);
+}
+
+static struct ethtool_ops myri10ge_ethtool_ops = {
+       .get_settings = myri10ge_get_settings,
+       .get_drvinfo = myri10ge_get_drvinfo,
+       .get_coalesce = myri10ge_get_coalesce,
+       .set_coalesce = myri10ge_set_coalesce,
+       .get_pauseparam = myri10ge_get_pauseparam,
+       .set_pauseparam = myri10ge_set_pauseparam,
+       .get_ringparam = myri10ge_get_ringparam,
+       .get_rx_csum = myri10ge_get_rx_csum,
+       .set_rx_csum = myri10ge_set_rx_csum,
+       .get_tx_csum = ethtool_op_get_tx_csum,
+       .set_tx_csum = ethtool_op_set_tx_hw_csum,
+       .get_sg = ethtool_op_get_sg,
+       .set_sg = ethtool_op_set_sg,
+#ifdef NETIF_F_TSO
+       .get_tso = ethtool_op_get_tso,
+       .set_tso = ethtool_op_set_tso,
+#endif
+       .get_strings = myri10ge_get_strings,
+       .get_stats_count = myri10ge_get_stats_count,
+       .get_ethtool_stats = myri10ge_get_ethtool_stats
+};
+
+static int myri10ge_allocate_rings(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct myri10ge_cmd cmd;
+       int tx_ring_size, rx_ring_size;
+       int tx_ring_entries, rx_ring_entries;
+       int i, status;
+       size_t bytes;
+
+       mgp = netdev_priv(dev);
+
+       /* get ring sizes */
+
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0);
+       tx_ring_size = cmd.data0;
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0);
+       rx_ring_size = cmd.data0;
+
+       tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send);
+       rx_ring_entries = rx_ring_size / sizeof(struct mcp_dma_addr);
+       mgp->tx.mask = tx_ring_entries - 1;
+       mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1;
+
+       /* allocate the host shadow rings */
+
+       bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4)
+           * sizeof(*mgp->tx.req_list);
+       mgp->tx.req_bytes = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->tx.req_bytes == NULL)
+               goto abort_with_nothing;
+
+       /* ensure req_list entries are aligned to 8 bytes */
+       mgp->tx.req_list = (struct mcp_kreq_ether_send *)
+           ALIGN((unsigned long)mgp->tx.req_bytes, 8);
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_small.shadow);
+       mgp->rx_small.shadow = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_small.shadow == NULL)
+               goto abort_with_tx_req_bytes;
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_big.shadow);
+       mgp->rx_big.shadow = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_big.shadow == NULL)
+               goto abort_with_rx_small_shadow;
+
+       /* allocate the host info rings */
+
+       bytes = tx_ring_entries * sizeof(*mgp->tx.info);
+       mgp->tx.info = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->tx.info == NULL)
+               goto abort_with_rx_big_shadow;
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_small.info);
+       mgp->rx_small.info = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_small.info == NULL)
+               goto abort_with_tx_info;
+
+       bytes = rx_ring_entries * sizeof(*mgp->rx_big.info);
+       mgp->rx_big.info = kzalloc(bytes, GFP_KERNEL);
+       if (mgp->rx_big.info == NULL)
+               goto abort_with_rx_small_info;
+
+       /* Fill the receive rings */
+
+       for (i = 0; i <= mgp->rx_small.mask; i++) {
+               status = myri10ge_getbuf(&mgp->rx_small, mgp->pdev,
+                                        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;
+               }
+       }
+
+       for (i = 0; i <= mgp->rx_big.mask; i++) {
+               status =
+                   myri10ge_getbuf(&mgp->rx_big, mgp->pdev,
+                                   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;
+               }
+       }
+
+       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);
+       }
+
+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);
+       }
+       kfree(mgp->rx_big.info);
+
+abort_with_rx_small_info:
+       kfree(mgp->rx_small.info);
+
+abort_with_tx_info:
+       kfree(mgp->tx.info);
+
+abort_with_rx_big_shadow:
+       kfree(mgp->rx_big.shadow);
+
+abort_with_rx_small_shadow:
+       kfree(mgp->rx_small.shadow);
+
+abort_with_tx_req_bytes:
+       kfree(mgp->tx.req_bytes);
+       mgp->tx.req_bytes = NULL;
+       mgp->tx.req_list = NULL;
+
+abort_with_nothing:
+       return status;
+}
+
+static void myri10ge_free_rings(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct sk_buff *skb;
+       struct myri10ge_tx_buf *tx;
+       int i, len, idx;
+
+       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);
+       }
+
+       tx = &mgp->tx;
+       while (tx->done != tx->req) {
+               idx = tx->done & tx->mask;
+               skb = tx->info[idx].skb;
+
+               /* Mark as free */
+               tx->info[idx].skb = NULL;
+               tx->done++;
+               len = pci_unmap_len(&tx->info[idx], len);
+               pci_unmap_len_set(&tx->info[idx], len, 0);
+               if (skb) {
+                       mgp->stats.tx_dropped++;
+                       dev_kfree_skb_any(skb);
+                       if (len)
+                               pci_unmap_single(mgp->pdev,
+                                                pci_unmap_addr(&tx->info[idx],
+                                                               bus), len,
+                                                PCI_DMA_TODEVICE);
+               } else {
+                       if (len)
+                               pci_unmap_page(mgp->pdev,
+                                              pci_unmap_addr(&tx->info[idx],
+                                                             bus), len,
+                                              PCI_DMA_TODEVICE);
+               }
+       }
+       kfree(mgp->rx_big.info);
+
+       kfree(mgp->rx_small.info);
+
+       kfree(mgp->tx.info);
+
+       kfree(mgp->rx_big.shadow);
+
+       kfree(mgp->rx_small.shadow);
+
+       kfree(mgp->tx.req_bytes);
+       mgp->tx.req_bytes = NULL;
+       mgp->tx.req_list = NULL;
+}
+
+static int myri10ge_open(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct myri10ge_cmd cmd;
+       int status, big_pow2;
+
+       mgp = netdev_priv(dev);
+
+       if (mgp->running != MYRI10GE_ETH_STOPPED)
+               return -EBUSY;
+
+       mgp->running = MYRI10GE_ETH_STARTING;
+       status = myri10ge_reset(mgp);
+       if (status != 0) {
+               printk(KERN_ERR "myri10ge: %s: failed reset\n", dev->name);
+               mgp->running = MYRI10GE_ETH_STOPPED;
+               return -ENXIO;
+       }
+
+       /* decide what small buffer size to use.  For good TCP rx
+        * performance, it is important to not receive 1514 byte
+        * frames into jumbo buffers, as it confuses the socket buffer
+        * accounting code, leading to drops and erratic performance.
+        */
+
+       if (dev->mtu <= ETH_DATA_LEN)
+               mgp->small_bytes = 128; /* enough for a TCP header */
+       else
+               mgp->small_bytes = ETH_FRAME_LEN;       /* enough for an ETH_DATA_LEN frame */
+
+       /* 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);
+       mgp->tx.lanai =
+           (struct mcp_kreq_ether_send __iomem *)(mgp->sram + cmd.data0);
+
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd, 0);
+       mgp->rx_small.lanai =
+           (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);
+
+       status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd, 0);
+       mgp->rx_big.lanai =
+           (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);
+
+       if (status != 0) {
+               printk(KERN_ERR
+                      "myri10ge: %s: failed to get ring sizes or locations\n",
+                      dev->name);
+               mgp->running = MYRI10GE_ETH_STOPPED;
+               return -ENXIO;
+       }
+
+       if (mgp->mtrr >= 0) {
+               mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + 0x200000;
+               mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + 0x300000;
+               mgp->rx_big.wc_fifo = (u8 __iomem *) mgp->sram + 0x340000;
+       } else {
+               mgp->tx.wc_fifo = NULL;
+               mgp->rx_small.wc_fifo = NULL;
+               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++;
+
+       /* now give firmware buffers sizes, and MTU */
+       cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN;
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd, 0);
+       cmd.data0 = mgp->small_bytes;
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, &cmd, 0);
+       cmd.data0 = big_pow2;
+       status |=
+           myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd, 0);
+       if (status) {
+               printk(KERN_ERR "myri10ge: %s: Couldn't set buffer sizes\n",
+                      dev->name);
+               goto abort_with_rings;
+       }
+
+       cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->fw_stats_bus);
+       cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->fw_stats_bus);
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA, &cmd, 0);
+       if (status) {
+               printk(KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n",
+                      dev->name);
+               goto abort_with_rings;
+       }
+
+       mgp->link_state = -1;
+       mgp->rdma_tags_available = 15;
+
+       netif_poll_enable(mgp->dev);    /* must happen prior to any irq */
+
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0);
+       if (status) {
+               printk(KERN_ERR "myri10ge: %s: Couldn't bring up link\n",
+                      dev->name);
+               goto abort_with_rings;
+       }
+
+       mgp->wake_queue = 0;
+       mgp->stop_queue = 0;
+       mgp->running = MYRI10GE_ETH_RUNNING;
+       mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ;
+       add_timer(&mgp->watchdog_timer);
+       netif_wake_queue(dev);
+       return 0;
+
+abort_with_rings:
+       myri10ge_free_rings(dev);
+
+abort_with_nothing:
+       mgp->running = MYRI10GE_ETH_STOPPED;
+       return -ENOMEM;
+}
+
+static int myri10ge_close(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp;
+       struct myri10ge_cmd cmd;
+       int status, old_down_cnt;
+
+       mgp = netdev_priv(dev);
+
+       if (mgp->running != MYRI10GE_ETH_RUNNING)
+               return 0;
+
+       if (mgp->tx.req_bytes == NULL)
+               return 0;
+
+       del_timer_sync(&mgp->watchdog_timer);
+       mgp->running = MYRI10GE_ETH_STOPPING;
+       netif_poll_disable(mgp->dev);
+       netif_carrier_off(dev);
+       netif_stop_queue(dev);
+       old_down_cnt = mgp->down_cnt;
+       mb();
+       status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
+       if (status)
+               printk(KERN_ERR "myri10ge: %s: Couldn't bring down link\n",
+                      dev->name);
+
+       wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt, HZ);
+       if (old_down_cnt == mgp->down_cnt)
+               printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name);
+
+       netif_tx_disable(dev);
+
+       myri10ge_free_rings(dev);
+
+       mgp->running = MYRI10GE_ETH_STOPPED;
+       return 0;
+}
+
+/* copy an array of struct mcp_kreq_ether_send's to the mcp.  Copy
+ * backwards one at a time and handle ring wraps */
+
+static inline void
+myri10ge_submit_req_backwards(struct myri10ge_tx_buf *tx,
+                             struct mcp_kreq_ether_send *src, int cnt)
+{
+       int idx, starting_slot;
+       starting_slot = tx->req;
+       while (cnt > 1) {
+               cnt--;
+               idx = (starting_slot + cnt) & tx->mask;
+               myri10ge_pio_copy(&tx->lanai[idx], &src[cnt], sizeof(*src));
+               mb();
+       }
+}
+
+/*
+ * copy an array of struct mcp_kreq_ether_send's to the mcp.  Copy
+ * at most 32 bytes at a time, so as to avoid involving the software
+ * pio handler in the nic.   We re-write the first segment's flags
+ * to mark them valid only after writing the entire chain.
+ */
+
+static inline void
+myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src,
+                   int cnt)
+{
+       int idx, i;
+       struct mcp_kreq_ether_send __iomem *dstp, *dst;
+       struct mcp_kreq_ether_send *srcp;
+       u8 last_flags;
+
+       idx = tx->req & tx->mask;
+
+       last_flags = src->flags;
+       src->flags = 0;
+       mb();
+       dst = dstp = &tx->lanai[idx];
+       srcp = src;
+
+       if ((idx + cnt) < tx->mask) {
+               for (i = 0; i < (cnt - 1); i += 2) {
+                       myri10ge_pio_copy(dstp, srcp, 2 * sizeof(*src));
+                       mb();   /* force write every 32 bytes */
+                       srcp += 2;
+                       dstp += 2;
+               }
+       } else {
+               /* submit all but the first request, and ensure
+                * that it is submitted below */
+               myri10ge_submit_req_backwards(tx, src, cnt);
+               i = 0;
+       }
+       if (i < cnt) {
+               /* submit the first request */
+               myri10ge_pio_copy(dstp, srcp, sizeof(*src));
+               mb();           /* barrier before setting valid flag */
+       }
+
+       /* re-write the last 32-bits with the valid flags */
+       src->flags = last_flags;
+       __raw_writel(*((u32 *) src + 3), (u32 __iomem *) dst + 3);
+       tx->req += cnt;
+       mb();
+}
+
+static inline void
+myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx,
+                      struct mcp_kreq_ether_send *src, int cnt)
+{
+       tx->req += cnt;
+       mb();
+       while (cnt >= 4) {
+               myri10ge_pio_copy(tx->wc_fifo, src, 64);
+               mb();
+               src += 4;
+               cnt -= 4;
+       }
+       if (cnt > 0) {
+               /* pad it to 64 bytes.  The src is 64 bytes bigger than it
+                * needs to be so that we don't overrun it */
+               myri10ge_pio_copy(tx->wc_fifo + (cnt << 18), src, 64);
+               mb();
+       }
+}
+
+/*
+ * Transmit a packet.  We need to split the packet so that a single
+ * segment does not cross myri10ge->tx.boundary, so this makes segment
+ * counting tricky.  So rather than try to count segments up front, we
+ * just give up if there are too few segments to hold a reasonably
+ * fragmented packet currently available.  If we run
+ * out of segments while preparing a packet for DMA, we just linearize
+ * it and try again.
+ */
+
+static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct myri10ge_priv *mgp = netdev_priv(dev);
+       struct mcp_kreq_ether_send *req;
+       struct myri10ge_tx_buf *tx = &mgp->tx;
+       struct skb_frag_struct *frag;
+       dma_addr_t bus;
+       u32 low, high_swapped;
+       unsigned int len;
+       int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
+       u16 pseudo_hdr_offset, cksum_offset;
+       int cum_len, seglen, boundary, rdma_count;
+       u8 flags, odd_flag;
+
+again:
+       req = tx->req_list;
+       avail = tx->mask - 1 - (tx->req - tx->done);
+
+       mss = 0;
+       max_segments = MXGEFW_MAX_SEND_DESC;
+
+#ifdef NETIF_F_TSO
+       if (skb->len > (dev->mtu + ETH_HLEN)) {
+               mss = skb_shinfo(skb)->tso_size;
+               if (mss != 0)
+                       max_segments = MYRI10GE_MAX_SEND_DESC_TSO;
+       }
+#endif                         /*NETIF_F_TSO */
+
+       if ((unlikely(avail < max_segments))) {
+               /* we are out of transmit resources */
+               mgp->stop_queue++;
+               netif_stop_queue(dev);
+               return 1;
+       }
+
+       /* Setup checksum offloading, if needed */
+       cksum_offset = 0;
+       pseudo_hdr_offset = 0;
+       odd_flag = 0;
+       flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST);
+       if (likely(skb->ip_summed == CHECKSUM_HW)) {
+               cksum_offset = (skb->h.raw - skb->data);
+               pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data;
+               /* If the headers are excessively large, then we must
+                * fall back to a software checksum */
+               if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) {
+                       if (skb_checksum_help(skb, 0))
+                               goto drop;
+                       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;
+               }
+       }
+
+       cum_len = 0;
+
+#ifdef NETIF_F_TSO
+       if (mss) {              /* TSO */
+               /* this removes any CKSUM flag from before */
+               flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST);
+
+               /* negative cum_len signifies to the
+                * send loop that we are still in the
+                * header portion of the TSO packet.
+                * TSO header must be at most 134 bytes long */
+               cum_len = -((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+
+               /* 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);
+       } else
+#endif                         /*NETIF_F_TSO */
+               /* Mark small packets, and pad out tiny packets */
+       if (skb->len <= MXGEFW_SEND_SMALL_SIZE) {
+               flags |= MXGEFW_FLAGS_SMALL;
+
+               /* pad frames to at least ETH_ZLEN bytes */
+               if (unlikely(skb->len < ETH_ZLEN)) {
+                       skb = skb_padto(skb, ETH_ZLEN);
+                       if (skb == NULL) {
+                               /* The packet is gone, so we must
+                                * return 0 */
+                               mgp->stats.tx_dropped += 1;
+                               return 0;
+                       }
+                       /* adjust the len to account for the zero pad
+                        * so that the nic can know how long it is */
+                       skb->len = ETH_ZLEN;
+               }
+       }
+
+       /* map the skb for DMA */
+       len = skb->len - skb->data_len;
+       idx = tx->req & tx->mask;
+       tx->info[idx].skb = skb;
+       bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+       pci_unmap_addr_set(&tx->info[idx], bus, bus);
+       pci_unmap_len_set(&tx->info[idx], len, len);
+
+       frag_cnt = skb_shinfo(skb)->nr_frags;
+       frag_idx = 0;
+       count = 0;
+       rdma_count = 0;
+
+       /* "rdma_count" is the number of RDMAs belonging to the
+        * current packet BEFORE the current send request. For
+        * non-TSO packets, this is equal to "count".
+        * For TSO packets, rdma_count needs to be reset
+        * to 0 after a segment cut.
+        *
+        * The rdma_count field of the send request is
+        * the number of RDMAs of the packet starting at
+        * that request. For TSO send requests with one ore more cuts
+        * in the middle, this is the number of RDMAs starting
+        * after the last cut in the request. All previous
+        * segments before the last cut implicitly have 1 RDMA.
+        *
+        * Since the number of RDMAs is not known beforehand,
+        * it must be filled-in retroactively - after each
+        * segmentation cut or at the end of the entire packet.
+        */
+
+       while (1) {
+               /* Break the SKB or Fragment up into pieces which
+                * do not cross mgp->tx.boundary */
+               low = MYRI10GE_LOWPART_TO_U32(bus);
+               high_swapped = htonl(MYRI10GE_HIGHPART_TO_U32(bus));
+               while (len) {
+                       u8 flags_next;
+                       int cum_len_next;
+
+                       if (unlikely(count == max_segments))
+                               goto abort_linearize;
+
+                       boundary = (low + tx->boundary) & ~(tx->boundary - 1);
+                       seglen = boundary - low;
+                       if (seglen > len)
+                               seglen = len;
+                       flags_next = flags & ~MXGEFW_FLAGS_FIRST;
+                       cum_len_next = cum_len + seglen;
+#ifdef NETIF_F_TSO
+                       if (mss) {      /* TSO */
+                               (req - rdma_count)->rdma_count = rdma_count + 1;
+
+                               if (likely(cum_len >= 0)) {     /* payload */
+                                       int next_is_first, chop;
+
+                                       chop = (cum_len_next > mss);
+                                       cum_len_next = cum_len_next % mss;
+                                       next_is_first = (cum_len_next == 0);
+                                       flags |= chop * MXGEFW_FLAGS_TSO_CHOP;
+                                       flags_next |= next_is_first *
+                                           MXGEFW_FLAGS_FIRST;
+                                       rdma_count |= -(chop | next_is_first);
+                                       rdma_count += chop & !next_is_first;
+                               } else if (likely(cum_len_next >= 0)) { /* header ends */
+                                       int small;
+
+                                       rdma_count = -1;
+                                       cum_len_next = 0;
+                                       seglen = -cum_len;
+                                       small = (mss <= MXGEFW_SEND_SMALL_SIZE);
+                                       flags_next = MXGEFW_FLAGS_TSO_PLD |
+                                           MXGEFW_FLAGS_FIRST |
+                                           (small * MXGEFW_FLAGS_SMALL);
+                               }
+                       }
+#endif                         /* NETIF_F_TSO */
+                       req->addr_high = high_swapped;
+                       req->addr_low = htonl(low);
+                       req->pseudo_hdr_offset = pseudo_hdr_offset;
+                       req->pad = 0;   /* complete solid 16-byte block; does this matter? */
+                       req->rdma_count = 1;
+                       req->length = htons(seglen);
+                       req->cksum_offset = cksum_offset;
+                       req->flags = flags | ((cum_len & 1) * odd_flag);
+
+                       low += seglen;
+                       len -= seglen;
+                       cum_len = cum_len_next;
+                       flags = flags_next;
+                       req++;
+                       count++;
+                       rdma_count++;
+                       if (unlikely(cksum_offset > seglen))
+                               cksum_offset -= seglen;
+                       else
+                               cksum_offset = 0;
+               }
+               if (frag_idx == frag_cnt)
+                       break;
+
+               /* map next fragment for DMA */
+               idx = (count + tx->req) & tx->mask;
+               frag = &skb_shinfo(skb)->frags[frag_idx];
+               frag_idx++;
+               len = frag->size;
+               bus = pci_map_page(mgp->pdev, frag->page, frag->page_offset,
+                                  len, PCI_DMA_TODEVICE);
+               pci_unmap_addr_set(&tx->info[idx], bus, bus);
+               pci_unmap_len_set(&tx->info[idx], len, len);
+       }
+
+       (req - rdma_count)->rdma_count = rdma_count;
+#ifdef NETIF_F_TSO
+       if (mss)
+               do {
+                       req--;
+                       req->flags |= MXGEFW_FLAGS_TSO_LAST;
+               } while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP |
+                                        MXGEFW_FLAGS_FIRST)));
+#endif
+       idx = ((count - 1) + tx->req) & tx->mask;
+       tx->info[idx].last = 1;
+       if (tx->wc_fifo == NULL)
+               myri10ge_submit_req(tx, tx->req_list, count);
+       else
+               myri10ge_submit_req_wc(tx, tx->req_list, count);
+       tx->pkt_start++;
+       if ((avail - count) < MXGEFW_MAX_SEND_DESC) {
+               mgp->stop_queue++;
+               netif_stop_queue(dev);
+       }
+       dev->trans_start = jiffies;
+       return 0;
+
+abort_linearize:
+       /* Free any DMA resources we've alloced and clear out the skb
+        * slot so as to not trip up assertions, and to avoid a
+        * double-free if linearizing fails */
+
+       last_idx = (idx + 1) & tx->mask;
+       idx = tx->req & tx->mask;
+       tx->info[idx].skb = NULL;
+       do {
+               len = pci_unmap_len(&tx->info[idx], len);
+               if (len) {
+                       if (tx->info[idx].skb != NULL)
+                               pci_unmap_single(mgp->pdev,
+                                                pci_unmap_addr(&tx->info[idx],
+                                                               bus), len,
+                                                PCI_DMA_TODEVICE);
+                       else
+                               pci_unmap_page(mgp->pdev,
+                                              pci_unmap_addr(&tx->info[idx],
+                                                             bus), len,
+                                              PCI_DMA_TODEVICE);
+                       pci_unmap_len_set(&tx->info[idx], len, 0);
+                       tx->info[idx].skb = NULL;
+               }
+               idx = (idx + 1) & tx->mask;
+       } while (idx != last_idx);
+       if (skb_shinfo(skb)->tso_size) {
+               printk(KERN_ERR
+                      "myri10ge: %s: TSO but wanted to linearize?!?!?\n",
+                      mgp->dev->name);
+               goto drop;
+       }
+
+       if (skb_linearize(skb, GFP_ATOMIC))
+               goto drop;
+
+       mgp->tx_linearized++;
+       goto again;
+
+drop:
+       dev_kfree_skb_any(skb);
+       mgp->stats.tx_dropped += 1;
+       return 0;
+
+}
+
+static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
+{
+       struct myri10ge_priv *mgp = netdev_priv(dev);
+       return &mgp->stats;
+}
+
+static void myri10ge_set_multicast_list(struct net_device *dev)
+{
+       /* can be called from atomic contexts,
+        * pass 1 to force atomicity in myri10ge_send_cmd() */
+       myri10ge_change_promisc(netdev_priv(dev), dev->flags & IFF_PROMISC, 1);
+}
+
+static int myri10ge_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct sockaddr *sa = addr;
+       struct myri10ge_priv *mgp = netdev_priv(dev);
+       int status;
+
+       if (!is_valid_ether_addr(sa->sa_data))
+               return -EADDRNOTAVAIL;
+
+       status = myri10ge_update_mac_address(mgp, sa->sa_data);
+       if (status != 0) {
+               printk(KERN_ERR
+                      "myri10ge: %s: changing mac address failed with %d\n",
+                      dev->name, status);
+               return status;
+       }
+
+       /* change the dev structure */
+       memcpy(dev->dev_addr, sa->sa_data, 6);
+       return 0;
+}
+
+static int myri10ge_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct myri10ge_priv *mgp = netdev_priv(dev);
+       int error = 0;
+
+       if ((new_mtu < 68) || (ETH_HLEN + new_mtu > MYRI10GE_MAX_ETHER_MTU)) {
+               printk(KERN_ERR "myri10ge: %s: new mtu (%d) is not valid\n",
+                      dev->name, new_mtu);
+               return -EINVAL;
+       }
+       printk(KERN_INFO "%s: changing mtu from %d to %d\n",
+              dev->name, dev->mtu, new_mtu);
+       if (mgp->running) {
+               /* if we change the mtu on an active device, we must
+                * reset the device so the firmware sees the change */
+               myri10ge_close(dev);
+               dev->mtu = new_mtu;
+               myri10ge_open(dev);
+       } else
+               dev->mtu = new_mtu;
+
+       return error;
+}
+
+/*
+ * Enable ECRC to align PCI-E Completion packets on an 8-byte boundary.
+ * Only do it if the bridge is a root port since we don't want to disturb
+ * any other device, except if forced with myri10ge_ecrc_enable > 1.
+ */
+
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_PCIE 0x005d
+
+static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
+{
+       struct pci_dev *bridge = mgp->pdev->bus->self;
+       struct device *dev = &mgp->pdev->dev;
+       unsigned cap;
+       unsigned err_cap;
+       u16 val;
+       u8 ext_type;
+       int ret;
+
+       if (!myri10ge_ecrc_enable || !bridge)
+               return;
+
+       /* check that the bridge is a root port */
+       cap = pci_find_capability(bridge, PCI_CAP_ID_EXP);
+       pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val);
+       ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
+       if (ext_type != PCI_EXP_TYPE_ROOT_PORT) {
+               if (myri10ge_ecrc_enable > 1) {
+                       struct pci_dev *old_bridge = bridge;
+
+                       /* Walk the hierarchy up to the root port
+                        * where ECRC has to be enabled */
+                       do {
+                               bridge = bridge->bus->self;
+                               if (!bridge) {
+                                       dev_err(dev,
+                                               "Failed to find root port"
+                                               " to force ECRC\n");
+                                       return;
+                               }
+                               cap =
+                                   pci_find_capability(bridge, PCI_CAP_ID_EXP);
+                               pci_read_config_word(bridge,
+                                                    cap + PCI_CAP_FLAGS, &val);
+                               ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
+                       } while (ext_type != PCI_EXP_TYPE_ROOT_PORT);
+
+                       dev_info(dev,
+                                "Forcing ECRC on non-root port %s"
+                                " (enabling on root port %s)\n",
+                                pci_name(old_bridge), pci_name(bridge));
+               } else {
+                       dev_err(dev,
+                               "Not enabling ECRC on non-root port %s\n",
+                               pci_name(bridge));
+                       return;
+               }
+       }
+
+       cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR);
+       /* nvidia ext cap is not always linked in ext cap chain */
+       if (!cap
+           && bridge->vendor == PCI_VENDOR_ID_NVIDIA
+           && bridge->device == PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_PCIE)
+               cap = 0x160;
+
+       if (!cap)
+               return;
+
+       ret = pci_read_config_dword(bridge, cap + PCI_ERR_CAP, &err_cap);
+       if (ret) {
+               dev_err(dev, "failed reading ext-conf-space of %s\n",
+                       pci_name(bridge));
+               dev_err(dev, "\t pci=nommconf in use? "
+                       "or buggy/incomplete/absent ACPI MCFG attr?\n");
+               return;
+       }
+       if (!(err_cap & PCI_ERR_CAP_ECRC_GENC))
+               return;
+
+       err_cap |= PCI_ERR_CAP_ECRC_GENE;
+       pci_write_config_dword(bridge, cap + PCI_ERR_CAP, err_cap);
+       dev_info(dev, "Enabled ECRC on upstream bridge %s\n", pci_name(bridge));
+       mgp->tx.boundary = 4096;
+       mgp->fw_name = myri10ge_fw_aligned;
+}
+
+/*
+ * The Lanai Z8E PCI-E interface achieves higher Read-DMA throughput
+ * when the PCI-E Completion packets are aligned on an 8-byte
+ * boundary.  Some PCI-E chip sets always align Completion packets; on
+ * the ones that do not, the alignment can be enforced by enabling
+ * ECRC generation (if supported).
+ *
+ * When PCI-E Completion packets are not aligned, it is actually more
+ * efficient to limit Read-DMA transactions to 2KB, rather than 4KB.
+ *
+ * If the driver can neither enable ECRC nor verify that it has
+ * already been enabled, then it must use a firmware image which works
+ * around unaligned completion packets (myri10ge_ethp_z8e.dat), and it
+ * should also ensure that it never gives the device a Read-DMA which is
+ * larger than 2KB by setting the tx.boundary to 2KB.  If ECRC is
+ * enabled, then the driver should use the aligned (myri10ge_eth_z8e.dat)
+ * firmware image, and set tx.boundary to 4KB.
+ */
+
+#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE  0x0132
+
+static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
+{
+       struct pci_dev *bridge = mgp->pdev->bus->self;
+
+       mgp->tx.boundary = 2048;
+       mgp->fw_name = myri10ge_fw_unaligned;
+
+       if (myri10ge_force_firmware == 0) {
+               myri10ge_enable_ecrc(mgp);
+
+               /* Check to see if the upstream bridge is known to
+                * provide aligned completions */
+               if (bridge
+                   /* ServerWorks HT2000/HT1000 */
+                   && bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
+                   && bridge->device ==
+                   PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) {
+                       dev_info(&mgp->pdev->dev,
+                                "Assuming aligned completions (0x%x:0x%x)\n",
+                                bridge->vendor, bridge->device);
+                       mgp->tx.boundary = 4096;
+                       mgp->fw_name = myri10ge_fw_aligned;
+               }
+       } else {
+               if (myri10ge_force_firmware == 1) {
+                       dev_info(&mgp->pdev->dev,
+                                "Assuming aligned completions (forced)\n");
+                       mgp->tx.boundary = 4096;
+                       mgp->fw_name = myri10ge_fw_aligned;
+               } else {
+                       dev_info(&mgp->pdev->dev,
+                                "Assuming unaligned completions (forced)\n");
+                       mgp->tx.boundary = 2048;
+                       mgp->fw_name = myri10ge_fw_unaligned;
+               }
+       }
+       if (myri10ge_fw_name != NULL) {
+               dev_info(&mgp->pdev->dev, "overriding firmware to %s\n",
+                        myri10ge_fw_name);
+               mgp->fw_name = myri10ge_fw_name;
+       }
+}
+
+static void myri10ge_save_state(struct myri10ge_priv *mgp)
+{
+       struct pci_dev *pdev = mgp->pdev;
+       int cap;
+
+       pci_save_state(pdev);
+       /* now save PCIe and MSI state that Linux will not
+        * save for us */
+       cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, &mgp->devctl);
+       cap = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+       pci_read_config_word(pdev, cap + PCI_MSI_FLAGS, &mgp->msi_flags);
+}
+
+static void myri10ge_restore_state(struct myri10ge_priv *mgp)
+{
+       struct pci_dev *pdev = mgp->pdev;
+       int cap;
+
+       /* restore PCIe and MSI state that linux will not */
+       cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       pci_write_config_dword(pdev, cap + PCI_CAP_ID_EXP, mgp->devctl);
+       cap = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+       pci_write_config_word(pdev, cap + PCI_MSI_FLAGS, mgp->msi_flags);
+
+       pci_restore_state(pdev);
+}
+
+#ifdef CONFIG_PM
+
+static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct myri10ge_priv *mgp;
+       struct net_device *netdev;
+
+       mgp = pci_get_drvdata(pdev);
+       if (mgp == NULL)
+               return -EINVAL;
+       netdev = mgp->dev;
+
+       netif_device_detach(netdev);
+       if (netif_running(netdev)) {
+               printk(KERN_INFO "myri10ge: closing %s\n", netdev->name);
+               rtnl_lock();
+               myri10ge_close(netdev);
+               rtnl_unlock();
+       }
+       myri10ge_dummy_rdma(mgp, 0);
+       free_irq(pdev->irq, mgp);
+       myri10ge_save_state(mgp);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       return 0;
+}
+
+static int myri10ge_resume(struct pci_dev *pdev)
+{
+       struct myri10ge_priv *mgp;
+       struct net_device *netdev;
+       int status;
+       u16 vendor;
+
+       mgp = pci_get_drvdata(pdev);
+       if (mgp == NULL)
+               return -EINVAL;
+       netdev = mgp->dev;
+       pci_set_power_state(pdev, 0);   /* zeros conf space as a side effect */
+       msleep(5);              /* give card time to respond */
+       pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor);
+       if (vendor == 0xffff) {
+               printk(KERN_ERR "myri10ge: %s: device disappeared!\n",
+                      mgp->dev->name);
+               return -EIO;
+       }
+       myri10ge_restore_state(mgp);
+       pci_enable_device(pdev);
+       pci_set_master(pdev);
+
+       status = request_irq(pdev->irq, myri10ge_intr, SA_SHIRQ,
+                            netdev->name, mgp);
+       if (status != 0) {
+               dev_err(&pdev->dev, "failed to allocate IRQ\n");
+               goto abort_with_msi;
+       }
+
+       myri10ge_reset(mgp);
+       myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096);
+
+       /* Save configuration space to be restored if the
+        * nic resets due to a parity error */
+       myri10ge_save_state(mgp);
+
+       if (netif_running(netdev)) {
+               rtnl_lock();
+               myri10ge_open(netdev);
+               rtnl_unlock();
+       }
+       netif_device_attach(netdev);
+
+       return 0;
+
+abort_with_msi:
+       return -EIO;
+
+}
+
+#endif                         /* CONFIG_PM */
+
+static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp)
+{
+       struct pci_dev *pdev = mgp->pdev;
+       int vs = mgp->vendor_specific_offset;
+       u32 reboot;
+
+       /*enter read32 mode */
+       pci_write_config_byte(pdev, vs + 0x10, 0x3);
+
+       /*read REBOOT_STATUS (0xfffffff0) */
+       pci_write_config_dword(pdev, vs + 0x18, 0xfffffff0);
+       pci_read_config_dword(pdev, vs + 0x14, &reboot);
+       return reboot;
+}
+
+/*
+ * 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)
+{
+       struct myri10ge_priv *mgp = arg;
+       u32 reboot;
+       int status;
+       u16 cmd, vendor;
+
+       mgp->watchdog_resets++;
+       pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd);
+       if ((cmd & PCI_COMMAND_MASTER) == 0) {
+               /* Bus master DMA disabled?  Check to see
+                * if the card rebooted due to a parity error
+                * For now, just report it */
+               reboot = myri10ge_read_reboot(mgp);
+               printk(KERN_ERR
+                      "myri10ge: %s: NIC rebooted (0x%x), resetting\n",
+                      mgp->dev->name, reboot);
+               /*
+                * A rebooted nic will come back with config space as
+                * it was after power was applied to PCIe bus.
+                * Attempt to restore config space which was saved
+                * when the driver was loaded, or the last time the
+                * nic was resumed from power saving mode.
+                */
+               myri10ge_restore_state(mgp);
+       } else {
+               /* if we get back -1's from our slot, perhaps somebody
+                * powered off our card.  Don't try to reset it in
+                * this case */
+               if (cmd == 0xffff) {
+                       pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor);
+                       if (vendor == 0xffff) {
+                               printk(KERN_ERR
+                                      "myri10ge: %s: device disappeared!\n",
+                                      mgp->dev->name);
+                               return;
+                       }
+               }
+               /* Perhaps it is a software error.  Try to reset */
+
+               printk(KERN_ERR "myri10ge: %s: device timeout, resetting\n",
+                      mgp->dev->name);
+               printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n",
+                      mgp->dev->name, mgp->tx.req, mgp->tx.done,
+                      mgp->tx.pkt_start, mgp->tx.pkt_done,
+                      (int)ntohl(mgp->fw_stats->send_done_count));
+               msleep(2000);
+               printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n",
+                      mgp->dev->name, mgp->tx.req, mgp->tx.done,
+                      mgp->tx.pkt_start, mgp->tx.pkt_done,
+                      (int)ntohl(mgp->fw_stats->send_done_count));
+       }
+       rtnl_lock();
+       myri10ge_close(mgp->dev);
+       status = myri10ge_load_firmware(mgp);
+       if (status != 0)
+               printk(KERN_ERR "myri10ge: %s: failed to load firmware\n",
+                      mgp->dev->name);
+       else
+               myri10ge_open(mgp->dev);
+       rtnl_unlock();
+}
+
+/*
+ * We use our own timer routine rather than relying upon
+ * netdev->tx_timeout because we have a very large hardware transmit
+ * queue.  Due to the large queue, the netdev->tx_timeout function
+ * cannot detect a NIC with a parity error in a timely fashion if the
+ * NIC is lightly loaded.
+ */
+static void myri10ge_watchdog_timer(unsigned long arg)
+{
+       struct myri10ge_priv *mgp;
+
+       mgp = (struct myri10ge_priv *)arg;
+       if (mgp->tx.req != mgp->tx.done &&
+           mgp->tx.done == mgp->watchdog_tx_done)
+               /* nic seems like it might be stuck.. */
+               schedule_work(&mgp->watchdog_work);
+       else
+               /* rearm timer */
+               mod_timer(&mgp->watchdog_timer,
+                         jiffies + myri10ge_watchdog_timeout * HZ);
+
+       mgp->watchdog_tx_done = mgp->tx.done;
+}
+
+static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       struct net_device *netdev;
+       struct myri10ge_priv *mgp;
+       struct device *dev = &pdev->dev;
+       size_t bytes;
+       int i;
+       int status = -ENXIO;
+       int cap;
+       int dac_enabled;
+       u16 val;
+
+       netdev = alloc_etherdev(sizeof(*mgp));
+       if (netdev == NULL) {
+               dev_err(dev, "Could not allocate ethernet device\n");
+               return -ENOMEM;
+       }
+
+       mgp = netdev_priv(netdev);
+       memset(mgp, 0, sizeof(*mgp));
+       mgp->dev = netdev;
+       mgp->pdev = pdev;
+       mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
+       mgp->pause = myri10ge_flow_control;
+       mgp->intr_coal_delay = myri10ge_intr_coal_delay;
+       init_waitqueue_head(&mgp->down_wq);
+
+       if (pci_enable_device(pdev)) {
+               dev_err(&pdev->dev, "pci_enable_device call failed\n");
+               status = -ENODEV;
+               goto abort_with_netdev;
+       }
+       myri10ge_select_firmware(mgp);
+
+       /* Find the vendor-specific cap so we can check
+        * the reboot register later on */
+       mgp->vendor_specific_offset
+           = pci_find_capability(pdev, PCI_CAP_ID_VNDR);
+
+       /* Set our max read request to 4KB */
+       cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       if (cap < 64) {
+               dev_err(&pdev->dev, "Bad PCI_CAP_ID_EXP location %d\n", cap);
+               goto abort_with_netdev;
+       }
+       status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val);
+       if (status != 0) {
+               dev_err(&pdev->dev, "Error %d reading PCI_EXP_DEVCTL\n",
+                       status);
+               goto abort_with_netdev;
+       }
+       val = (val & ~PCI_EXP_DEVCTL_READRQ) | (5 << 12);
+       status = pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, val);
+       if (status != 0) {
+               dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n",
+                       status);
+               goto abort_with_netdev;
+       }
+
+       pci_set_master(pdev);
+       dac_enabled = 1;
+       status = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+       if (status != 0) {
+               dac_enabled = 0;
+               dev_err(&pdev->dev,
+                       "64-bit pci address mask was refused, trying 32-bit");
+               status = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       }
+       if (status != 0) {
+               dev_err(&pdev->dev, "Error %d setting DMA mask\n", status);
+               goto abort_with_netdev;
+       }
+       mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd),
+                                     &mgp->cmd_bus, GFP_KERNEL);
+       if (mgp->cmd == NULL)
+               goto abort_with_netdev;
+
+       mgp->fw_stats = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->fw_stats),
+                                          &mgp->fw_stats_bus, GFP_KERNEL);
+       if (mgp->fw_stats == NULL)
+               goto abort_with_cmd;
+
+       mgp->board_span = pci_resource_len(pdev, 0);
+       mgp->iomem_base = pci_resource_start(pdev, 0);
+       mgp->mtrr = -1;
+#ifdef CONFIG_MTRR
+       mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span,
+                            MTRR_TYPE_WRCOMB, 1);
+#endif
+       /* Hack.  need to get rid of these magic numbers */
+       mgp->sram_size =
+           2 * 1024 * 1024 - (2 * (48 * 1024) + (32 * 1024)) - 0x100;
+       if (mgp->sram_size > mgp->board_span) {
+               dev_err(&pdev->dev, "board span %ld bytes too small\n",
+                       mgp->board_span);
+               goto abort_with_wc;
+       }
+       mgp->sram = ioremap(mgp->iomem_base, mgp->board_span);
+       if (mgp->sram == NULL) {
+               dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n",
+                       mgp->board_span, mgp->iomem_base);
+               status = -ENXIO;
+               goto abort_with_wc;
+       }
+       memcpy_fromio(mgp->eeprom_strings,
+                     mgp->sram + mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE,
+                     MYRI10GE_EEPROM_STRINGS_SIZE);
+       memset(mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE - 2, 0, 2);
+       status = myri10ge_read_mac_addr(mgp);
+       if (status)
+               goto abort_with_ioremap;
+
+       for (i = 0; i < ETH_ALEN; i++)
+               netdev->dev_addr[i] = mgp->mac_addr[i];
+
+       /* allocate rx done ring */
+       bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+       mgp->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes,
+                                               &mgp->rx_done.bus, GFP_KERNEL);
+       if (mgp->rx_done.entry == NULL)
+               goto abort_with_ioremap;
+       memset(mgp->rx_done.entry, 0, bytes);
+
+       status = myri10ge_load_firmware(mgp);
+       if (status != 0) {
+               dev_err(&pdev->dev, "failed to load firmware\n");
+               goto abort_with_rx_done;
+       }
+
+       status = myri10ge_reset(mgp);
+       if (status != 0) {
+               dev_err(&pdev->dev, "failed reset\n");
+               goto abort_with_firmware;
+       }
+
+       if (myri10ge_msi) {
+               status = pci_enable_msi(pdev);
+               if (status != 0)
+                       dev_err(&pdev->dev,
+                               "Error %d setting up MSI; falling back to xPIC\n",
+                               status);
+               else
+                       mgp->msi_enabled = 1;
+       }
+
+       status = request_irq(pdev->irq, myri10ge_intr, SA_SHIRQ,
+                            netdev->name, mgp);
+       if (status != 0) {
+               dev_err(&pdev->dev, "failed to allocate IRQ\n");
+               goto abort_with_firmware;
+       }
+
+       pci_set_drvdata(pdev, mgp);
+       if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU)
+               myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
+       if ((myri10ge_initial_mtu + ETH_HLEN) < 68)
+               myri10ge_initial_mtu = 68;
+       netdev->mtu = myri10ge_initial_mtu;
+       netdev->open = myri10ge_open;
+       netdev->stop = myri10ge_close;
+       netdev->hard_start_xmit = myri10ge_xmit;
+       netdev->get_stats = myri10ge_get_stats;
+       netdev->base_addr = mgp->iomem_base;
+       netdev->irq = pdev->irq;
+       netdev->change_mtu = myri10ge_change_mtu;
+       netdev->set_multicast_list = myri10ge_set_multicast_list;
+       netdev->set_mac_address = myri10ge_set_mac_address;
+       netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO;
+       if (dac_enabled)
+               netdev->features |= NETIF_F_HIGHDMA;
+       netdev->poll = myri10ge_poll;
+       netdev->weight = myri10ge_napi_weight;
+
+       /* Save configuration space to be restored if the
+        * nic resets due to a parity error */
+       myri10ge_save_state(mgp);
+       /* Restore state immediately since pci_save_msi_state disables MSI */
+       myri10ge_restore_state(mgp);
+
+       /* Setup the watchdog timer */
+       setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
+                   (unsigned long)mgp);
+
+       SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
+       INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog, mgp);
+       status = register_netdev(netdev);
+       if (status != 0) {
+               dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
+               goto abort_with_irq;
+       }
+
+       printk(KERN_INFO "myri10ge: %s: %s IRQ %d, tx bndry %d, fw %s, WC %s\n",
+              netdev->name, (mgp->msi_enabled ? "MSI" : "xPIC"),
+              pdev->irq, mgp->tx.boundary, mgp->fw_name,
+              (mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
+
+       return 0;
+
+abort_with_irq:
+       free_irq(pdev->irq, mgp);
+       if (mgp->msi_enabled)
+               pci_disable_msi(pdev);
+
+abort_with_firmware:
+       myri10ge_dummy_rdma(mgp, 0);
+
+abort_with_rx_done:
+       bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+       dma_free_coherent(&pdev->dev, bytes,
+                         mgp->rx_done.entry, mgp->rx_done.bus);
+
+abort_with_ioremap:
+       iounmap(mgp->sram);
+
+abort_with_wc:
+#ifdef CONFIG_MTRR
+       if (mgp->mtrr >= 0)
+               mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
+#endif
+       dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats),
+                         mgp->fw_stats, mgp->fw_stats_bus);
+
+abort_with_cmd:
+       dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
+                         mgp->cmd, mgp->cmd_bus);
+
+abort_with_netdev:
+
+       free_netdev(netdev);
+       return status;
+}
+
+/*
+ * myri10ge_remove
+ *
+ * Does what is necessary to shutdown one Myrinet device. Called
+ *   once for each Myrinet card by the kernel when a module is
+ *   unloaded.
+ */
+static void myri10ge_remove(struct pci_dev *pdev)
+{
+       struct myri10ge_priv *mgp;
+       struct net_device *netdev;
+       size_t bytes;
+
+       mgp = pci_get_drvdata(pdev);
+       if (mgp == NULL)
+               return;
+
+       flush_scheduled_work();
+       netdev = mgp->dev;
+       unregister_netdev(netdev);
+       free_irq(pdev->irq, mgp);
+       if (mgp->msi_enabled)
+               pci_disable_msi(pdev);
+
+       myri10ge_dummy_rdma(mgp, 0);
+
+       bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+       dma_free_coherent(&pdev->dev, bytes,
+                         mgp->rx_done.entry, mgp->rx_done.bus);
+
+       iounmap(mgp->sram);
+
+#ifdef CONFIG_MTRR
+       if (mgp->mtrr >= 0)
+               mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
+#endif
+       dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats),
+                         mgp->fw_stats, mgp->fw_stats_bus);
+
+       dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
+                         mgp->cmd, mgp->cmd_bus);
+
+       free_netdev(netdev);
+       pci_set_drvdata(pdev, NULL);
+}
+
+#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E     0x0008
+
+static struct pci_device_id myri10ge_pci_tbl[] = {
+       {PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)},
+       {0},
+};
+
+static struct pci_driver myri10ge_driver = {
+       .name = "myri10ge",
+       .probe = myri10ge_probe,
+       .remove = myri10ge_remove,
+       .id_table = myri10ge_pci_tbl,
+#ifdef CONFIG_PM
+       .suspend = myri10ge_suspend,
+       .resume = myri10ge_resume,
+#endif
+};
+
+static __init int myri10ge_init_module(void)
+{
+       printk(KERN_INFO "%s: Version %s\n", myri10ge_driver.name,
+              MYRI10GE_VERSION_STR);
+       return pci_register_driver(&myri10ge_driver);
+}
+
+module_init(myri10ge_init_module);
+
+static __exit void myri10ge_cleanup_module(void)
+{
+       pci_unregister_driver(&myri10ge_driver);
+}
+
+module_exit(myri10ge_cleanup_module);
diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h
new file mode 100644 (file)
index 0000000..0a6cae6
--- /dev/null
@@ -0,0 +1,205 @@
+#ifndef __MYRI10GE_MCP_H__
+#define __MYRI10GE_MCP_H__
+
+#define MXGEFW_VERSION_MAJOR   1
+#define MXGEFW_VERSION_MINOR   4
+
+/* 8 Bytes */
+struct mcp_dma_addr {
+       u32 high;
+       u32 low;
+};
+
+/* 4 Bytes */
+struct mcp_slot {
+       u16 checksum;
+       u16 length;
+};
+
+/* 64 Bytes */
+struct mcp_cmd {
+       u32 cmd;
+       u32 data0;              /* will be low portion if data > 32 bits */
+       /* 8 */
+       u32 data1;              /* will be high portion if data > 32 bits */
+       u32 data2;              /* currently unused.. */
+       /* 16 */
+       struct mcp_dma_addr response_addr;
+       /* 24 */
+       u8 pad[40];
+};
+
+/* 8 Bytes */
+struct mcp_cmd_response {
+       u32 data;
+       u32 result;
+};
+
+/*
+ * flags used in mcp_kreq_ether_send_t:
+ *
+ * The SMALL flag is only needed in the first segment. It is raised
+ * for packets that are total less or equal 512 bytes.
+ *
+ * The CKSUM flag must be set in all segments.
+ *
+ * The PADDED flags is set if the packet needs to be padded, and it
+ * must be set for all segments.
+ *
+ * The  MXGEFW_FLAGS_ALIGN_ODD must be set if the cumulative
+ * length of all previous segments was odd.
+ */
+
+#define MXGEFW_FLAGS_SMALL      0x1
+#define MXGEFW_FLAGS_TSO_HDR    0x1
+#define MXGEFW_FLAGS_FIRST      0x2
+#define MXGEFW_FLAGS_ALIGN_ODD  0x4
+#define MXGEFW_FLAGS_CKSUM      0x8
+#define MXGEFW_FLAGS_TSO_LAST   0x8
+#define MXGEFW_FLAGS_NO_TSO     0x10
+#define MXGEFW_FLAGS_TSO_CHOP   0x10
+#define MXGEFW_FLAGS_TSO_PLD    0x20
+
+#define MXGEFW_SEND_SMALL_SIZE  1520
+#define MXGEFW_MAX_MTU          9400
+
+union mcp_pso_or_cumlen {
+       u16 pseudo_hdr_offset;
+       u16 cum_len;
+};
+
+#define        MXGEFW_MAX_SEND_DESC 12
+#define MXGEFW_PAD         2
+
+/* 16 Bytes */
+struct mcp_kreq_ether_send {
+       u32 addr_high;
+       u32 addr_low;
+       u16 pseudo_hdr_offset;
+       u16 length;
+       u8 pad;
+       u8 rdma_count;
+       u8 cksum_offset;        /* where to start computing cksum */
+       u8 flags;               /* as defined above */
+};
+
+/* 8 Bytes */
+struct mcp_kreq_ether_recv {
+       u32 addr_high;
+       u32 addr_low;
+};
+
+/* Commands */
+
+#define MXGEFW_CMD_OFFSET 0xf80000
+
+enum myri10ge_mcp_cmd_type {
+       MXGEFW_CMD_NONE = 0,
+       /* Reset the mcp, it is left in a safe state, waiting
+        * for the driver to set all its parameters */
+       MXGEFW_CMD_RESET,
+
+       /* get the version number of the current firmware..
+        * (may be available in the eeprom strings..? */
+       MXGEFW_GET_MCP_VERSION,
+
+       /* Parameters which must be set by the driver before it can
+        * issue MXGEFW_CMD_ETHERNET_UP. They persist until the next
+        * MXGEFW_CMD_RESET is issued */
+
+       MXGEFW_CMD_SET_INTRQ_DMA,
+       MXGEFW_CMD_SET_BIG_BUFFER_SIZE, /* in bytes, power of 2 */
+       MXGEFW_CMD_SET_SMALL_BUFFER_SIZE,       /* in bytes */
+
+       /* Parameters which refer to lanai SRAM addresses where the
+        * driver must issue PIO writes for various things */
+
+       MXGEFW_CMD_GET_SEND_OFFSET,
+       MXGEFW_CMD_GET_SMALL_RX_OFFSET,
+       MXGEFW_CMD_GET_BIG_RX_OFFSET,
+       MXGEFW_CMD_GET_IRQ_ACK_OFFSET,
+       MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET,
+
+       /* Parameters which refer to rings stored on the MCP,
+        * and whose size is controlled by the mcp */
+
+       MXGEFW_CMD_GET_SEND_RING_SIZE,  /* in bytes */
+       MXGEFW_CMD_GET_RX_RING_SIZE,    /* in bytes */
+
+       /* Parameters which refer to rings stored in the host,
+        * and whose size is controlled by the host.  Note that
+        * all must be physically contiguous and must contain
+        * a power of 2 number of entries.  */
+
+       MXGEFW_CMD_SET_INTRQ_SIZE,      /* in bytes */
+
+       /* command to bring ethernet interface up.  Above parameters
+        * (plus mtu & mac address) must have been exchanged prior
+        * to issuing this command  */
+       MXGEFW_CMD_ETHERNET_UP,
+
+       /* command to bring ethernet interface down.  No further sends
+        * or receives may be processed until an MXGEFW_CMD_ETHERNET_UP
+        * is issued, and all interrupt queues must be flushed prior
+        * to ack'ing this command */
+
+       MXGEFW_CMD_ETHERNET_DOWN,
+
+       /* commands the driver may issue live, without resetting
+        * the nic.  Note that increasing the mtu "live" should
+        * only be done if the driver has already supplied buffers
+        * sufficiently large to handle the new mtu.  Decreasing
+        * the mtu live is safe */
+
+       MXGEFW_CMD_SET_MTU,
+       MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET,  /* in microseconds */
+       MXGEFW_CMD_SET_STATS_INTERVAL,  /* in microseconds */
+       MXGEFW_CMD_SET_STATS_DMA,
+
+       MXGEFW_ENABLE_PROMISC,
+       MXGEFW_DISABLE_PROMISC,
+       MXGEFW_SET_MAC_ADDRESS,
+
+       MXGEFW_ENABLE_FLOW_CONTROL,
+       MXGEFW_DISABLE_FLOW_CONTROL,
+
+       /* do a DMA test
+        * data0,data1 = DMA address
+        * data2       = RDMA length (MSH), WDMA length (LSH)
+        * command return data = repetitions (MSH), 0.5-ms ticks (LSH)
+        */
+       MXGEFW_DMA_TEST
+};
+
+enum myri10ge_mcp_cmd_status {
+       MXGEFW_CMD_OK = 0,
+       MXGEFW_CMD_UNKNOWN,
+       MXGEFW_CMD_ERROR_RANGE,
+       MXGEFW_CMD_ERROR_BUSY,
+       MXGEFW_CMD_ERROR_EMPTY,
+       MXGEFW_CMD_ERROR_CLOSED,
+       MXGEFW_CMD_ERROR_HASH_ERROR,
+       MXGEFW_CMD_ERROR_BAD_PORT,
+       MXGEFW_CMD_ERROR_RESOURCES
+};
+
+/* 40 Bytes */
+struct mcp_irq_data {
+       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;
+
+       u8 tx_stopped;
+       u8 link_down;
+       u8 stats_updated;
+       u8 valid;
+};
+
+#endif                         /* __MYRI10GE_MCP_H__ */
diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
new file mode 100644 (file)
index 0000000..487f779
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __MYRI10GE_MCP_GEN_HEADER_H__
+#define __MYRI10GE_MCP_GEN_HEADER_H__
+
+/* this file define a standard header used as a first entry point to
+ * exchange information between firmware/driver and driver.  The
+ * header structure can be anywhere in the mcp. It will usually be in
+ * the .data section, because some fields needs to be initialized at
+ * compile time.
+ * The 32bit word at offset MX_HEADER_PTR_OFFSET in the mcp must
+ * contains the location of the header.
+ *
+ * Typically a MCP will start with the following:
+ * .text
+ * .space 52    ! to help catch MEMORY_INT errors
+ * bt start     ! jump to real code
+ * nop
+ * .long _gen_mcp_header
+ *
+ * The source will have a definition like:
+ *
+ * mcp_gen_header_t gen_mcp_header = {
+ * .header_length = sizeof(mcp_gen_header_t),
+ * .mcp_type = MCP_TYPE_XXX,
+ * .version = "something $Id: mcp_gen_header.h,v 1.2 2006/05/13 10:04:35 bgoglin Exp $",
+ * .mcp_globals = (unsigned)&Globals
+ * };
+ */
+
+#define MCP_HEADER_PTR_OFFSET  0x3c
+
+#define MCP_TYPE_MX 0x4d582020 /* "MX  " */
+#define MCP_TYPE_PCIE 0x70636965       /* "PCIE" pcie-only MCP */
+#define MCP_TYPE_ETH 0x45544820        /* "ETH " */
+#define MCP_TYPE_MCP0 0x4d435030       /* "MCP0" */
+
+struct mcp_gen_header {
+       /* the first 4 fields are filled at compile time */
+       unsigned header_length;
+       unsigned mcp_type;
+       char version[128];
+       unsigned mcp_globals;   /* pointer to mcp-type specific structure */
+
+       /* filled by the MCP at run-time */
+       unsigned sram_size;
+       unsigned string_specs;  /* either the original STRING_SPECS or a superset */
+       unsigned string_specs_len;
+
+       /* Fields above this comment are guaranteed to be present.
+        *
+        * Fields below this comment are extensions added in later versions
+        * of this struct, drivers should compare the header_length against
+        * offsetof(field) to check wether a given MCP implements them.
+        *
+        * Never remove any field.  Keep everything naturally align.
+        */
+};
+
+#endif                         /* __MYRI10GE_MCP_GEN_HEADER_H__ */
index 90627756d6fa47bbe93ce363af1d6ced2307fba4..2e4ecedba0572cc655b3827a39c88d0ddebb139b 100644 (file)
@@ -318,12 +318,12 @@ performance critical codepaths:
 The rx process only runs in the interrupt handler. Access from outside
 the interrupt handler is only permitted after disable_irq().
 
-The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap
+The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
 is set, then access is permitted under spin_lock_irq(&np->lock).
 
 Thus configuration functions that want to access everything must call
        disable_irq(dev->irq);
-       spin_lock_bh(dev->xmit_lock);
+       netif_tx_lock_bh(dev);
        spin_lock_irq(&np->lock);
 
 IV. Notes
index b32765215f75c12d983df36349d4f6acbe4e453f..963a11fa9fe2eb7accd49bd057dbc5edcb67863d 100644 (file)
@@ -829,7 +829,7 @@ that the ne2k probe is the last 8390 based probe to take place (as it
 is at boot) and so the probe will get confused by any other 8390 cards.
 ISA device autoprobes on a running machine are not recommended anyway. */
 
-int init_module(void)
+int __init init_module(void)
 {
        int this_dev, found = 0;
 
index 2aa7b77f84f805cd0f652fca5c22ba54468457ec..eebf5f02b4763071ac50f2f343a8f6fbf7e0bcad 100644 (file)
@@ -780,7 +780,7 @@ MODULE_PARM_DESC(bad, "(ignored)");
 
 /* Module code fixed by David Weinehall */
 
-int init_module(void)
+int __init init_module(void)
 {
        struct net_device *dev;
        int this_dev, found = 0;
index 66e74f7402610f5ac9ad769457f01b5254d1b27e..bf58db29e2ed6342bd707931ccd598a3c376b07c 100644 (file)
@@ -107,7 +107,7 @@ static int init_netconsole(void)
 
        if(!configured) {
                printk("netconsole: not configured, aborting\n");
-               return -EINVAL;
+               return 0;
        }
 
        if(netpoll_setup(&np))
index 4260c2128f4722c61cc267fc6a0290ebde330be9..a8f6bfc96fd28cbdd4cb75c0c60517fa54d84709 100644 (file)
@@ -1204,7 +1204,7 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt)
 
        dev->last_rx = jiffies;
        lp->linux_stats.rx_packets++;
-       lp->linux_stats.rx_bytes += skb->len;
+       lp->linux_stats.rx_bytes += pkt_len;
        outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */
        continue;
       } else {
index d090df413049146728e3705bbe7317222643b81c..661bfe54ff5d8543f7a0d99b4ecd9adca3afd49f 100644 (file)
@@ -12,7 +12,7 @@
     Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
 
     pcnet_cs.c 1.153 2003/11/09 18:53:09
-    
+
     The network driver code is based on Donald Becker's NE2000 code:
 
     Written 1992,1993 by Donald Becker.
@@ -146,7 +146,7 @@ typedef struct hw_info_t {
 #define MII_PHYID_REG2         0x03
 
 static hw_info_t hw_info[] = {
-    { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT }, 
+    { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
     { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
     { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
     { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94,
@@ -193,7 +193,7 @@ static hw_info_t hw_info[] = {
     { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
     { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
       HAS_MISC_REG | HAS_IBM_MISC },
-    { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45, 
+    { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45,
       HAS_MISC_REG | HAS_IBM_MISC },
     { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 },
     { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 },
@@ -330,7 +330,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
        for (j = 0; j < 6; j++)
            dev->dev_addr[j] = readb(base + (j<<1));
     }
-    
+
     iounmap(virt);
     j = pcmcia_release_window(link->win);
     if (j != CS_SUCCESS)
@@ -490,7 +490,7 @@ static int try_io_port(struct pcmcia_device *link)
        if (link->io.NumPorts2 > 0) {
            /* for master/slave multifunction cards */
            link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-           link->irq.Attributes = 
+           link->irq.Attributes =
                IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
        }
     } else {
@@ -543,19 +543,19 @@ static int pcnet_config(struct pcmcia_device *link)
        manfid = le16_to_cpu(buf[0]);
        prodid = le16_to_cpu(buf[1]);
     }
-    
+
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
     tuple.Attributes = 0;
     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (last_ret == CS_SUCCESS) {
        cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
        cistpl_io_t *io = &(parse.cftable_entry.io);
-       
+
        if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
                        pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
                        cfg->index == 0 || cfg->io.nwin == 0)
                goto next_entry;
-       
+
        link->conf.ConfigIndex = cfg->index;
        /* For multifunction cards, by convention, we configure the
           network function with window 0, and serial with window 1 */
@@ -584,7 +584,7 @@ static int pcnet_config(struct pcmcia_device *link)
     }
 
     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
-    
+
     if (link->io.NumPorts2 == 8) {
        link->conf.Attributes |= CONF_ENABLE_SPKR;
        link->conf.Status = CCSR_AUDIO_ENA;
@@ -592,7 +592,7 @@ static int pcnet_config(struct pcmcia_device *link)
     if ((manfid == MANFID_IBM) &&
        (prodid == PRODID_IBM_HOME_AND_AWAY))
        link->conf.ConfigIndex |= 0x10;
-    
+
     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
@@ -614,7 +614,7 @@ static int pcnet_config(struct pcmcia_device *link)
        hw_info = get_ax88190(link);
     if (hw_info == NULL)
        hw_info = get_hwired(link);
-    
+
     if (hw_info == NULL) {
        printk(KERN_NOTICE "pcnet_cs: unable to read hardware net"
               " address for io base %#3lx\n", dev->base_addr);
@@ -631,7 +631,7 @@ static int pcnet_config(struct pcmcia_device *link)
        info->flags &= ~USE_BIG_BUF;
     if (!use_big_buf)
        info->flags &= ~USE_BIG_BUF;
-    
+
     if (info->flags & USE_BIG_BUF) {
        start_pg = SOCKET_START_PG;
        stop_pg = SOCKET_STOP_PG;
@@ -929,7 +929,7 @@ static void set_misc_reg(struct net_device *dev)
     kio_addr_t nic_base = dev->base_addr;
     pcnet_dev_t *info = PRIV(dev);
     u_char tmp;
-    
+
     if (info->flags & HAS_MISC_REG) {
        tmp = inb_p(nic_base + PCNET_MISC) & ~3;
        if (dev->if_port == 2)
@@ -1022,7 +1022,7 @@ static int pcnet_close(struct net_device *dev)
 
     ei_close(dev);
     free_irq(dev->irq, dev);
-    
+
     link->open--;
     netif_stop_queue(dev);
     del_timer_sync(&info->watchdog);
@@ -1054,12 +1054,12 @@ static void pcnet_reset_8390(struct net_device *dev)
        udelay(100);
     }
     outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
-    
+
     if (i == 100)
        printk(KERN_ERR "%s: pcnet_reset_8390() did not complete.\n",
               dev->name);
     set_misc_reg(dev);
-    
+
 } /* pcnet_reset_8390 */
 
 /*====================================================================*/
@@ -1233,7 +1233,7 @@ static void dma_get_8390_hdr(struct net_device *dev,
               dev->name, ei_status.dmaing, ei_status.irqlock);
        return;
     }
-    
+
     ei_status.dmaing |= 0x01;
     outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
     outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
@@ -1458,7 +1458,7 @@ static void shmem_get_8390_hdr(struct net_device *dev,
     void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8)
                                + (ring_page << 8)
                                - (ei_status.rx_start_page << 8);
-    
+
     copyin(hdr, xfer_start, sizeof(struct e8390_pkt_hdr));
     /* Fix for big endian systems */
     hdr->count = le16_to_cpu(hdr->count);
@@ -1473,7 +1473,7 @@ static void shmem_block_input(struct net_device *dev, int count,
     unsigned long offset = (TX_PAGES<<8) + ring_offset
                                - (ei_status.rx_start_page << 8);
     char *buf = skb->data;
-    
+
     if (offset + count > ei_status.priv) {
        /* We must wrap the input move. */
        int semi_count = ei_status.priv - offset;
@@ -1541,7 +1541,7 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
        info->base = NULL; link->win = NULL;
        goto failed;
     }
-    
+
     ei_status.mem = info->base + offset;
     ei_status.priv = req.Size;
     dev->mem_start = (u_long)ei_status.mem;
@@ -1768,6 +1768,8 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID12("PMX   ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"),
+       PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
+               0xb4be14e3, 0x43ac239b, 0x0877b627),
        PCMCIA_DEVICE_NULL
 };
 MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);
index 07c31f19c6ba40d419b2d022d069af321130f73f..fc08c4af506ca8194b7f4d3854181fdc5eed43b4 100644 (file)
@@ -1774,8 +1774,6 @@ static int pcnet32_open(struct net_device *dev)
                lp->rx_dma_addr[i] = 0;
        }
 
-       pcnet32_free_ring(dev);
-
        /*
         * Switch back to 16bit mode to avoid problems with dumb
         * DOS packet driver after a warm reboot
index fa39b944bc46a7df2eb947efea31298b4236977e..cda3e53d69176f803e471cdfad71892ad371f95b 100644 (file)
@@ -45,5 +45,11 @@ config CICADA_PHY
        ---help---
          Currently supports the cis8204
 
+config SMSC_PHY
+       tristate "Drivers for SMSC PHYs"
+       depends on PHYLIB
+       ---help---
+         Currently supports the LAN83C185 PHY
+
 endmenu
 
index e4116a5fbb4c0fea3bd396b29a749126f799a21b..d9614134cc06d674e2ef08fd01f88dcb941ab77d 100644 (file)
@@ -8,3 +8,4 @@ obj-$(CONFIG_DAVICOM_PHY)       += davicom.o
 obj-$(CONFIG_CICADA_PHY)       += cicada.o
 obj-$(CONFIG_LXT_PHY)          += lxt.o
 obj-$(CONFIG_QSEMI_PHY)                += qsemi.o
+obj-$(CONFIG_SMSC_PHY)         += smsc.o
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
new file mode 100644 (file)
index 0000000..25e31fb
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * drivers/net/phy/smsc.c
+ *
+ * Driver for SMSC PHYs
+ *
+ * Author: Herbert Valerio Riedel
+ *
+ * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.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/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+
+#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
+#define MII_LAN83C185_IM  30 /* Interrupt Mask */
+
+#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
+#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
+#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */
+#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */
+#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */
+#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */
+#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */
+
+#define MII_LAN83C185_ISF_INT_ALL (0x0e)
+
+#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \
+       (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4)
+
+
+static int lan83c185_config_intr(struct phy_device *phydev)
+{
+       int rc = phy_write (phydev, MII_LAN83C185_IM,
+                       ((PHY_INTERRUPT_ENABLED == phydev->interrupts)
+                       ? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS
+                       : 0));
+
+       return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_ack_interrupt(struct phy_device *phydev)
+{
+       int rc = phy_read (phydev, MII_LAN83C185_ISF);
+
+       return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_config_init(struct phy_device *phydev)
+{
+       return lan83c185_ack_interrupt (phydev);
+}
+
+
+static struct phy_driver lan83c185_driver = {
+       .phy_id         = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "SMSC LAN83C185",
+
+       .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+                               | SUPPORTED_Asym_Pause),
+       .flags          = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+
+       /* basic functions */
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .config_init    = lan83c185_config_init,
+
+       /* IRQ related */
+       .ack_interrupt  = lan83c185_ack_interrupt,
+       .config_intr    = lan83c185_config_intr,
+
+       .driver         = { .owner = THIS_MODULE, }
+};
+
+static int __init smsc_init(void)
+{
+       return phy_driver_register (&lan83c185_driver);
+}
+
+static void __exit smsc_exit(void)
+{
+       phy_driver_unregister (&lan83c185_driver);
+}
+
+MODULE_DESCRIPTION("SMSC PHY driver");
+MODULE_AUTHOR("Herbert Valerio Riedel");
+MODULE_LICENSE("GPL");
+
+module_init(smsc_init);
+module_exit(smsc_exit);
index b2073fce82169fa41f97a4e21bf2dde453f3ccd4..01cd8ec751ea4b7b5b6d023257776725b22f3907 100644 (file)
@@ -1609,8 +1609,6 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
                        kfree_skb(skb);
                        skb = ns;
                }
-               else if (!pskb_may_pull(skb, skb->len))
-                       goto err;
                else
                        skb->ip_summed = CHECKSUM_NONE;
 
index 475dc930380f63b6a1b0fd52b2532b43354798c5..0d101a18026a31b250a010bba4be28be45cab441 100644 (file)
@@ -861,6 +861,9 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
                 * give dev_queue_xmit something it can free.
                 */
                skb2 = skb_clone(skb, GFP_ATOMIC);
+
+               if (skb2 == NULL)
+                       goto abort;
        }
 
        ph = (struct pppoe_hdr *) skb_push(skb2, sizeof(struct pppoe_hdr));
index 0ad3310290f1e0d8b012a607894eab6668302757..9945cc6b8d90ac1fbdfca8ebad2cc6a5320c6cef 100644 (file)
@@ -184,6 +184,7 @@ static const struct {
 
 static struct pci_device_id rtl8169_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8169), },
+       { PCI_DEVICE(PCI_VENDOR_ID_REALTEK,     0x8129), },
        { PCI_DEVICE(PCI_VENDOR_ID_DLINK,       0x4300), },
        { PCI_DEVICE(0x16ec,                    0x0116), },
        { PCI_VENDOR_ID_LINKSYS,                0x1032, PCI_ANY_ID, 0x0024, },
index 00179bc3437fccea29fa780d9df5da4233d1f886..0ef525899566ed2f24bf934dcbacab16870c0778 100644 (file)
@@ -167,6 +167,7 @@ typedef struct _XENA_dev_config {
        u8 unused4[0x08];
 
        u64 gpio_int_reg;
+#define GPIO_INT_REG_DP_ERR_INT                BIT(0)
 #define GPIO_INT_REG_LINK_DOWN                 BIT(1)
 #define GPIO_INT_REG_LINK_UP                   BIT(2)
        u64 gpio_int_mask;
@@ -187,7 +188,7 @@ typedef struct _XENA_dev_config {
 /* PIC Control registers */
        u64 pic_control;
 #define PIC_CNTL_RX_ALARM_MAP_1                BIT(0)
-#define PIC_CNTL_SHARED_SPLITS(n)              vBIT(n,11,4)
+#define PIC_CNTL_SHARED_SPLITS(n)              vBIT(n,11,5)
 
        u64 swapper_ctrl;
 #define SWAPPER_CTRL_PIF_R_FE                  BIT(0)
@@ -267,6 +268,21 @@ typedef struct _XENA_dev_config {
 
        /* General Configuration */
        u64 mdio_control;
+#define MDIO_MMD_INDX_ADDR(val)                vBIT(val, 0, 16)
+#define MDIO_MMD_DEV_ADDR(val)         vBIT(val, 19, 5)
+#define MDIO_MMD_PMA_DEV_ADDR          0x1
+#define MDIO_MMD_PMD_DEV_ADDR          0x1
+#define MDIO_MMD_WIS_DEV_ADDR          0x2
+#define MDIO_MMD_PCS_DEV_ADDR          0x3
+#define MDIO_MMD_PHYXS_DEV_ADDR                0x4
+#define MDIO_MMS_PRT_ADDR(val)         vBIT(val, 27, 5)
+#define MDIO_CTRL_START_TRANS(val)     vBIT(val, 56, 4)
+#define MDIO_OP(val)                   vBIT(val, 60, 2)
+#define MDIO_OP_ADDR_TRANS             0x0
+#define MDIO_OP_WRITE_TRANS            0x1
+#define MDIO_OP_READ_POST_INC_TRANS    0x2
+#define MDIO_OP_READ_TRANS             0x3
+#define MDIO_MDIO_DATA(val)            vBIT(val, 32, 16)
 
        u64 dtx_control;
 
@@ -284,9 +300,13 @@ typedef struct _XENA_dev_config {
        u64 gpio_control;
 #define GPIO_CTRL_GPIO_0               BIT(8)
        u64 misc_control;
+#define EXT_REQ_EN                     BIT(1)
 #define MISC_LINK_STABILITY_PRD(val)   vBIT(val,29,3)
 
-       u8 unused7_1[0x240 - 0x208];
+       u8 unused7_1[0x230 - 0x208];
+
+       u64 pic_control2;
+       u64 ini_dperr_ctrl;
 
        u64 wreq_split_mask;
 #define        WREQ_SPLIT_MASK_SET_MASK(val)   vBIT(val, 52, 12)
@@ -493,6 +513,7 @@ typedef struct _XENA_dev_config {
 #define PRC_CTRL_NO_SNOOP_DESC                 BIT(22)
 #define PRC_CTRL_NO_SNOOP_BUFF                 BIT(23)
 #define PRC_CTRL_BIMODAL_INTERRUPT             BIT(37)
+#define PRC_CTRL_GROUP_READS                   BIT(38)
 #define PRC_CTRL_RXD_BACKOFF_INTERVAL(val)     vBIT(val,40,24)
 
        u64 prc_alarm_action;
@@ -541,7 +562,12 @@ typedef struct _XENA_dev_config {
 #define RX_PA_CFG_IGNORE_LLC_CTRL          BIT(3)
 #define RX_PA_CFG_IGNORE_L2_ERR            BIT(6)
 
-       u8 unused12[0x700 - 0x1D8];
+       u64 unused_11_1;
+
+       u64 ring_bump_counter1;
+       u64 ring_bump_counter2;
+
+       u8 unused12[0x700 - 0x1F0];
 
        u64 rxdma_debug_ctrl;
 
index 79208f434ac17773123c9cb92364131687c3fc64..cac9fdd2e1d5bd1b6653ccac639c62865dc6565a 100644 (file)
  *
  * The module loadable parameters that are supported by the driver and a brief
  * explaination of all the variables.
+ *
  * rx_ring_num : This can be used to program the number of receive rings used
  * in the driver.
- * rx_ring_sz: This defines the number of descriptors each ring can have. This
- * is also an array of size 8.
+ * rx_ring_sz: This defines the number of receive blocks each ring can have.
+ *     This is also an array of size 8.
  * rx_ring_mode: This defines the operation mode of all 8 rings. The valid
  *             values are 1, 2 and 3.
  * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver.
  * tx_fifo_len: This too is an array of 8. Each element defines the number of
  * Tx descriptors that can be associated with each corresponding FIFO.
+ * intr_type: This defines the type of interrupt. The values can be 0(INTA),
+ *     1(MSI), 2(MSI_X). Default value is '0(INTA)'
+ * lro: Specifies whether to enable Large Receive Offload (LRO) or not.
+ *     Possible values '1' for enable '0' for disable. Default is '0'
+ * lro_max_pkts: This parameter defines maximum number of packets can be
+ *     aggregated as a single large packet
  ************************************************************************/
 
 #include <linux/config.h>
@@ -70,7 +77,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.11.2"
+#define DRV_VERSION "2.0.14.2"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -106,18 +113,14 @@ static inline int RXD_IS_UP2DT(RxD_t *rxdp)
 #define LOW    2
 static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring)
 {
-       int level = 0;
        mac_info_t *mac_control;
 
        mac_control = &sp->mac_control;
-       if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) {
-               level = LOW;
-               if (rxb_size <= rxd_count[sp->rxd_mode]) {
-                       level = PANIC;
-               }
-       }
-
-       return level;
+       if (rxb_size <= rxd_count[sp->rxd_mode])
+               return PANIC;
+       else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16)
+               return  LOW;
+       return 0;
 }
 
 /* Ethtool related variables and Macros. */
@@ -136,7 +139,11 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        {"tmac_mcst_frms"},
        {"tmac_bcst_frms"},
        {"tmac_pause_ctrl_frms"},
+       {"tmac_ttl_octets"},
+       {"tmac_ucst_frms"},
+       {"tmac_nucst_frms"},
        {"tmac_any_err_frms"},
+       {"tmac_ttl_less_fb_octets"},
        {"tmac_vld_ip_octets"},
        {"tmac_vld_ip"},
        {"tmac_drop_ip"},
@@ -151,13 +158,27 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        {"rmac_vld_mcst_frms"},
        {"rmac_vld_bcst_frms"},
        {"rmac_in_rng_len_err_frms"},
+       {"rmac_out_rng_len_err_frms"},
        {"rmac_long_frms"},
        {"rmac_pause_ctrl_frms"},
+       {"rmac_unsup_ctrl_frms"},
+       {"rmac_ttl_octets"},
+       {"rmac_accepted_ucst_frms"},
+       {"rmac_accepted_nucst_frms"},
        {"rmac_discarded_frms"},
+       {"rmac_drop_events"},
+       {"rmac_ttl_less_fb_octets"},
+       {"rmac_ttl_frms"},
        {"rmac_usized_frms"},
        {"rmac_osized_frms"},
        {"rmac_frag_frms"},
        {"rmac_jabber_frms"},
+       {"rmac_ttl_64_frms"},
+       {"rmac_ttl_65_127_frms"},
+       {"rmac_ttl_128_255_frms"},
+       {"rmac_ttl_256_511_frms"},
+       {"rmac_ttl_512_1023_frms"},
+       {"rmac_ttl_1024_1518_frms"},
        {"rmac_ip"},
        {"rmac_ip_octets"},
        {"rmac_hdr_err_ip"},
@@ -166,12 +187,82 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {
        {"rmac_tcp"},
        {"rmac_udp"},
        {"rmac_err_drp_udp"},
+       {"rmac_xgmii_err_sym"},
+       {"rmac_frms_q0"},
+       {"rmac_frms_q1"},
+       {"rmac_frms_q2"},
+       {"rmac_frms_q3"},
+       {"rmac_frms_q4"},
+       {"rmac_frms_q5"},
+       {"rmac_frms_q6"},
+       {"rmac_frms_q7"},
+       {"rmac_full_q0"},
+       {"rmac_full_q1"},
+       {"rmac_full_q2"},
+       {"rmac_full_q3"},
+       {"rmac_full_q4"},
+       {"rmac_full_q5"},
+       {"rmac_full_q6"},
+       {"rmac_full_q7"},
        {"rmac_pause_cnt"},
+       {"rmac_xgmii_data_err_cnt"},
+       {"rmac_xgmii_ctrl_err_cnt"},
        {"rmac_accepted_ip"},
        {"rmac_err_tcp"},
+       {"rd_req_cnt"},
+       {"new_rd_req_cnt"},
+       {"new_rd_req_rtry_cnt"},
+       {"rd_rtry_cnt"},
+       {"wr_rtry_rd_ack_cnt"},
+       {"wr_req_cnt"},
+       {"new_wr_req_cnt"},
+       {"new_wr_req_rtry_cnt"},
+       {"wr_rtry_cnt"},
+       {"wr_disc_cnt"},
+       {"rd_rtry_wr_ack_cnt"},
+       {"txp_wr_cnt"},
+       {"txd_rd_cnt"},
+       {"txd_wr_cnt"},
+       {"rxd_rd_cnt"},
+       {"rxd_wr_cnt"},
+       {"txf_rd_cnt"},
+       {"rxf_wr_cnt"},
+       {"rmac_ttl_1519_4095_frms"},
+       {"rmac_ttl_4096_8191_frms"},
+       {"rmac_ttl_8192_max_frms"},
+       {"rmac_ttl_gt_max_frms"},
+       {"rmac_osized_alt_frms"},
+       {"rmac_jabber_alt_frms"},
+       {"rmac_gt_max_alt_frms"},
+       {"rmac_vlan_frms"},
+       {"rmac_len_discard"},
+       {"rmac_fcs_discard"},
+       {"rmac_pf_discard"},
+       {"rmac_da_discard"},
+       {"rmac_red_discard"},
+       {"rmac_rts_discard"},
+       {"rmac_ingm_full_discard"},
+       {"link_fault_cnt"},
        {"\n DRIVER STATISTICS"},
        {"single_bit_ecc_errs"},
        {"double_bit_ecc_errs"},
+       {"parity_err_cnt"},
+       {"serious_err_cnt"},
+       {"soft_reset_cnt"},
+       {"fifo_full_cnt"},
+       {"ring_full_cnt"},
+       ("alarm_transceiver_temp_high"),
+       ("alarm_transceiver_temp_low"),
+       ("alarm_laser_bias_current_high"),
+       ("alarm_laser_bias_current_low"),
+       ("alarm_laser_output_power_high"),
+       ("alarm_laser_output_power_low"),
+       ("warn_transceiver_temp_high"),
+       ("warn_transceiver_temp_low"),
+       ("warn_laser_bias_current_high"),
+       ("warn_laser_bias_current_low"),
+       ("warn_laser_output_power_high"),
+       ("warn_laser_output_power_low"),
        ("lro_aggregated_pkts"),
        ("lro_flush_both_count"),
        ("lro_out_of_sequence_pkts"),
@@ -220,9 +311,7 @@ static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
  * the XAUI.
  */
 
-#define SWITCH_SIGN    0xA5A5A5A5A5A5A5A5ULL
 #define        END_SIGN        0x0
-
 static const u64 herc_act_dtx_cfg[] = {
        /* Set address */
        0x8000051536750000ULL, 0x80000515367500E0ULL,
@@ -244,37 +333,19 @@ static const u64 herc_act_dtx_cfg[] = {
        END_SIGN
 };
 
-static const u64 xena_mdio_cfg[] = {
-       /* Reset PMA PLL */
-       0xC001010000000000ULL, 0xC0010100000000E0ULL,
-       0xC0010100008000E4ULL,
-       /* Remove Reset from PMA PLL */
-       0xC001010000000000ULL, 0xC0010100000000E0ULL,
-       0xC0010100000000E4ULL,
-       END_SIGN
-};
-
 static const u64 xena_dtx_cfg[] = {
+       /* Set address */
        0x8000051500000000ULL, 0x80000515000000E0ULL,
-       0x80000515D93500E4ULL, 0x8001051500000000ULL,
-       0x80010515000000E0ULL, 0x80010515001E00E4ULL,
-       0x8002051500000000ULL, 0x80020515000000E0ULL,
-       0x80020515F21000E4ULL,
-       /* Set PADLOOPBACKN */
-       0x8002051500000000ULL, 0x80020515000000E0ULL,
-       0x80020515B20000E4ULL, 0x8003051500000000ULL,
-       0x80030515000000E0ULL, 0x80030515B20000E4ULL,
-       0x8004051500000000ULL, 0x80040515000000E0ULL,
-       0x80040515B20000E4ULL, 0x8005051500000000ULL,
-       0x80050515000000E0ULL, 0x80050515B20000E4ULL,
-       SWITCH_SIGN,
-       /* Remove PADLOOPBACKN */
+       /* Write data */
+       0x80000515D9350004ULL, 0x80000515D93500E4ULL,
+       /* Set address */
+       0x8001051500000000ULL, 0x80010515000000E0ULL,
+       /* Write data */
+       0x80010515001E0004ULL, 0x80010515001E00E4ULL,
+       /* Set address */
        0x8002051500000000ULL, 0x80020515000000E0ULL,
-       0x80020515F20000E4ULL, 0x8003051500000000ULL,
-       0x80030515000000E0ULL, 0x80030515F20000E4ULL,
-       0x8004051500000000ULL, 0x80040515000000E0ULL,
-       0x80040515F20000E4ULL, 0x8005051500000000ULL,
-       0x80050515000000E0ULL, 0x80050515F20000E4ULL,
+       /* Write data */
+       0x80020515F2100004ULL, 0x80020515F21000E4ULL,
        END_SIGN
 };
 
@@ -303,15 +374,15 @@ static const u64 fix_mac[] = {
 /* Module Loadable parameters. */
 static unsigned int tx_fifo_num = 1;
 static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
-    {[0 ...(MAX_TX_FIFOS - 1)] = 0 };
+    {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN};
 static unsigned int rx_ring_num = 1;
 static unsigned int rx_ring_sz[MAX_RX_RINGS] =
-    {[0 ...(MAX_RX_RINGS - 1)] = };
+    {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT};
 static unsigned int rts_frm_len[MAX_RX_RINGS] =
     {[0 ...(MAX_RX_RINGS - 1)] = 0 };
 static unsigned int rx_ring_mode = 1;
 static unsigned int use_continuous_tx_intrs = 1;
-static unsigned int rmac_pause_time = 65535;
+static unsigned int rmac_pause_time = 0x100;
 static unsigned int mc_pause_threshold_q0q3 = 187;
 static unsigned int mc_pause_threshold_q4q7 = 187;
 static unsigned int shared_splits;
@@ -549,11 +620,6 @@ static int init_shared_mem(struct s2io_nic *nic)
                                        rx_blocks->block_dma_addr +
                                        (rxd_size[nic->rxd_mode] * l);
                        }
-
-                       mac_control->rings[i].rx_blocks[j].block_virt_addr =
-                               tmp_v_addr;
-                       mac_control->rings[i].rx_blocks[j].block_dma_addr =
-                               tmp_p_addr;
                }
                /* Interlinking all Rx Blocks */
                for (j = 0; j < blk_cnt; j++) {
@@ -772,7 +838,21 @@ static int s2io_verify_pci_mode(nic_t *nic)
        return mode;
 }
 
+#define NEC_VENID   0x1033
+#define NEC_DEVID   0x0125
+static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev)
+{
+       struct pci_dev *tdev = NULL;
+       while ((tdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) {
+               if ((tdev->vendor == NEC_VENID) && (tdev->device == NEC_DEVID)){
+                       if (tdev->bus == s2io_pdev->bus->parent)
+                               return 1;
+               }
+       }
+       return 0;
+}
 
+static int bus_speed[8] = {33, 133, 133, 200, 266, 133, 200, 266};
 /**
  * s2io_print_pci_mode -
  */
@@ -789,6 +869,14 @@ static int s2io_print_pci_mode(nic_t *nic)
        if ( val64 & PCI_MODE_UNKNOWN_MODE)
                return -1;      /* Unknown PCI mode */
 
+       config->bus_speed = bus_speed[mode];
+
+       if (s2io_on_nec_bridge(nic->pdev)) {
+               DBG_PRINT(ERR_DBG, "%s: Device is on PCI-E bus\n",
+                                                       nic->dev->name);
+               return mode;
+       }
+
        if (val64 & PCI_MODE_32_BITS) {
                DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name);
        } else {
@@ -798,35 +886,27 @@ static int s2io_print_pci_mode(nic_t *nic)
        switch(mode) {
                case PCI_MODE_PCI_33:
                        DBG_PRINT(ERR_DBG, "33MHz PCI bus\n");
-                       config->bus_speed = 33;
                        break;
                case PCI_MODE_PCI_66:
                        DBG_PRINT(ERR_DBG, "66MHz PCI bus\n");
-                       config->bus_speed = 133;
                        break;
                case PCI_MODE_PCIX_M1_66:
                        DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n");
-                       config->bus_speed = 133; /* Herc doubles the clock rate */
                        break;
                case PCI_MODE_PCIX_M1_100:
                        DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n");
-                       config->bus_speed = 200;
                        break;
                case PCI_MODE_PCIX_M1_133:
                        DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n");
-                       config->bus_speed = 266;
                        break;
                case PCI_MODE_PCIX_M2_66:
                        DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n");
-                       config->bus_speed = 133;
                        break;
                case PCI_MODE_PCIX_M2_100:
                        DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n");
-                       config->bus_speed = 200;
                        break;
                case PCI_MODE_PCIX_M2_133:
                        DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n");
-                       config->bus_speed = 266;
                        break;
                default:
                        return -1;      /* Unsupported bus speed */
@@ -854,7 +934,7 @@ static int init_nic(struct s2io_nic *nic)
        int i, j;
        mac_info_t *mac_control;
        struct config_param *config;
-       int mdio_cnt = 0, dtx_cnt = 0;
+       int dtx_cnt = 0;
        unsigned long long mem_share;
        int mem_size;
 
@@ -901,20 +981,6 @@ static int init_nic(struct s2io_nic *nic)
        val64 = dev->mtu;
        writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
 
-       /*
-        * Configuring the XAUI Interface of Xena.
-        * ***************************************
-        * To Configure the Xena's XAUI, one has to write a series
-        * of 64 bit values into two registers in a particular
-        * sequence. Hence a macro 'SWITCH_SIGN' has been defined
-        * which will be defined in the array of configuration values
-        * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places
-        * to switch writing from one regsiter to another. We continue
-        * writing these values until we encounter the 'END_SIGN' macro.
-        * For example, After making a series of 21 writes into
-        * dtx_control register the 'SWITCH_SIGN' appears and hence we
-        * start writing into mdio_control until we encounter END_SIGN.
-        */
        if (nic->device_type & XFRAME_II_DEVICE) {
                while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) {
                        SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt],
@@ -924,35 +990,11 @@ static int init_nic(struct s2io_nic *nic)
                        dtx_cnt++;
                }
        } else {
-               while (1) {
-                     dtx_cfg:
-                       while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
-                               if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
-                                       dtx_cnt++;
-                                       goto mdio_cfg;
-                               }
-                               SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
-                                                 &bar0->dtx_control, UF);
-                               val64 = readq(&bar0->dtx_control);
-                               dtx_cnt++;
-                       }
-                     mdio_cfg:
-                       while (xena_mdio_cfg[mdio_cnt] != END_SIGN) {
-                               if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
-                                       mdio_cnt++;
-                                       goto dtx_cfg;
-                               }
-                               SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt],
-                                                 &bar0->mdio_control, UF);
-                               val64 = readq(&bar0->mdio_control);
-                               mdio_cnt++;
-                       }
-                       if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) &&
-                           (xena_mdio_cfg[mdio_cnt] == END_SIGN)) {
-                               break;
-                       } else {
-                               goto dtx_cfg;
-                       }
+               while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
+                       SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
+                                         &bar0->dtx_control, UF);
+                       val64 = readq(&bar0->dtx_control);
+                       dtx_cnt++;
                }
        }
 
@@ -994,11 +1036,6 @@ static int init_nic(struct s2io_nic *nic)
                }
        }
 
-       /* Enable Tx FIFO partition 0. */
-       val64 = readq(&bar0->tx_fifo_partition_0);
-       val64 |= BIT(0);        /* To enable the FIFO partition. */
-       writeq(val64, &bar0->tx_fifo_partition_0);
-
        /*
         * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
         * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
@@ -1177,6 +1214,11 @@ static int init_nic(struct s2io_nic *nic)
                break;
        }
 
+       /* Enable Tx FIFO partition 0. */
+       val64 = readq(&bar0->tx_fifo_partition_0);
+       val64 |= (TX_FIFO_PARTITION_EN);
+       writeq(val64, &bar0->tx_fifo_partition_0);
+
        /* Filling the Rx round robin registers as per the
         * number of Rings and steering based on QoS.
          */
@@ -1545,19 +1587,26 @@ static int init_nic(struct s2io_nic *nic)
        val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits);
        writeq(val64, &bar0->pic_control);
 
+       if (nic->config.bus_speed == 266) {
+               writeq(TXREQTO_VAL(0x7f) | TXREQTO_EN, &bar0->txreqtimeout);
+               writeq(0x0, &bar0->read_retry_delay);
+               writeq(0x0, &bar0->write_retry_delay);
+       }
+
        /*
         * Programming the Herc to split every write transaction
         * that does not start on an ADB to reduce disconnects.
         */
        if (nic->device_type == XFRAME_II_DEVICE) {
-               val64 = WREQ_SPLIT_MASK_SET_MASK(255);
-               writeq(val64, &bar0->wreq_split_mask);
-       }
-
-       /* Setting Link stability period to 64 ms */ 
-       if (nic->device_type == XFRAME_II_DEVICE) {
-               val64 = MISC_LINK_STABILITY_PRD(3);
+               val64 = EXT_REQ_EN | MISC_LINK_STABILITY_PRD(3);
                writeq(val64, &bar0->misc_control);
+               val64 = readq(&bar0->pic_control2);
+               val64 &= ~(BIT(13)|BIT(14)|BIT(15));
+               writeq(val64, &bar0->pic_control2);
+       }
+       if (strstr(nic->product_name, "CX4")) {
+               val64 = TMAC_AVG_IPG(0x17);
+               writeq(val64, &bar0->tmac_avg_ipg);
        }
 
        return SUCCESS;
@@ -1948,6 +1997,10 @@ static int start_nic(struct s2io_nic *nic)
                        val64 |= PRC_CTRL_RC_ENABLED;
                else
                        val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3;
+               if (nic->device_type == XFRAME_II_DEVICE)
+                       val64 |= PRC_CTRL_GROUP_READS;
+               val64 &= ~PRC_CTRL_RXD_BACKOFF_INTERVAL(0xFFFFFF);
+               val64 |= PRC_CTRL_RXD_BACKOFF_INTERVAL(0x1000);
                writeq(val64, &bar0->prc_ctrl_n[i]);
        }
 
@@ -2018,6 +2071,13 @@ static int start_nic(struct s2io_nic *nic)
        val64 |= ADAPTER_EOI_TX_ON;
        writeq(val64, &bar0->adapter_control);
 
+       if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
+               /*
+                * Dont see link state interrupts initally on some switches,
+                * so directly scheduling the link state task here.
+                */
+               schedule_work(&nic->set_link_task);
+       }
        /* SXE-002: Initialize link and activity LED */
        subid = nic->pdev->subsystem_device;
        if (((subid & 0xFF) >= 0x07) &&
@@ -2029,12 +2089,6 @@ static int start_nic(struct s2io_nic *nic)
                writeq(val64, (void __iomem *)bar0 + 0x2700);
        }
 
-       /*
-        * Don't see link state interrupts on certain switches, so
-        * directly scheduling a link state task from here.
-        */
-       schedule_work(&nic->set_link_task);
-
        return SUCCESS;
 }
 /**
@@ -2134,7 +2188,7 @@ static void stop_nic(struct s2io_nic *nic)
 {
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        register u64 val64 = 0;
-       u16 interruptible, i;
+       u16 interruptible;
        mac_info_t *mac_control;
        struct config_param *config;
 
@@ -2147,12 +2201,10 @@ static void stop_nic(struct s2io_nic *nic)
        interruptible |= TX_MAC_INTR | RX_MAC_INTR;
        en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
 
-       /*  Disable PRCs */
-       for (i = 0; i < config->rx_ring_num; i++) {
-               val64 = readq(&bar0->prc_ctrl_n[i]);
-               val64 &= ~((u64) PRC_CTRL_RC_ENABLED);
-               writeq(val64, &bar0->prc_ctrl_n[i]);
-       }
+       /* Clearing Adapter_En bit of ADAPTER_CONTROL Register */
+       val64 = readq(&bar0->adapter_control);
+       val64 &= ~(ADAPTER_CNTL_EN);
+       writeq(val64, &bar0->adapter_control);
 }
 
 static int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb)
@@ -2231,13 +2283,12 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
        alloc_cnt = mac_control->rings[ring_no].pkt_cnt -
            atomic_read(&nic->rx_bufs_left[ring_no]);
 
+       block_no1 = mac_control->rings[ring_no].rx_curr_get_info.block_index;
+       off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
        while (alloc_tab < alloc_cnt) {
                block_no = mac_control->rings[ring_no].rx_curr_put_info.
                    block_index;
-               block_no1 = mac_control->rings[ring_no].rx_curr_get_info.
-                   block_index;
                off = mac_control->rings[ring_no].rx_curr_put_info.offset;
-               off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
 
                rxdp = mac_control->rings[ring_no].
                                rx_blocks[block_no].rxds[off].virt_addr;
@@ -2307,9 +2358,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
                        memset(rxdp, 0, sizeof(RxD1_t));
                        skb_reserve(skb, NET_IP_ALIGN);
                        ((RxD1_t*)rxdp)->Buffer0_ptr = pci_map_single
-                           (nic->pdev, skb->data, size, PCI_DMA_FROMDEVICE);
-                       rxdp->Control_2 &= (~MASK_BUFFER0_SIZE_1);
-                       rxdp->Control_2 |= SET_BUFFER0_SIZE_1(size);
+                           (nic->pdev, skb->data, size - NET_IP_ALIGN,
+                               PCI_DMA_FROMDEVICE);
+                       rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN);
 
                } else if (nic->rxd_mode >= RXD_MODE_3A) {
                        /*
@@ -2516,7 +2567,7 @@ static int s2io_poll(struct net_device *dev, int *budget)
        mac_info_t *mac_control;
        struct config_param *config;
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
-       u64 val64;
+       u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
        int i;
 
        atomic_inc(&nic->isr_cnt);
@@ -2528,8 +2579,8 @@ static int s2io_poll(struct net_device *dev, int *budget)
                nic->pkts_to_process = dev->quota;
        org_pkts_to_process = nic->pkts_to_process;
 
-       val64 = readq(&bar0->rx_traffic_int);
        writeq(val64, &bar0->rx_traffic_int);
+       val64 = readl(&bar0->rx_traffic_int);
 
        for (i = 0; i < config->rx_ring_num; i++) {
                rx_intr_handler(&mac_control->rings[i]);
@@ -2554,7 +2605,8 @@ static int s2io_poll(struct net_device *dev, int *budget)
                }
        }
        /* Re enable the Rx interrupts. */
-       en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS);
+       writeq(0x0, &bar0->rx_traffic_mask);
+       val64 = readl(&bar0->rx_traffic_mask);
        atomic_dec(&nic->isr_cnt);
        return 0;
 
@@ -2666,6 +2718,7 @@ static void rx_intr_handler(ring_info_t *ring_data)
                                         ((RxD3_t*)rxdp)->Buffer2_ptr,
                                         dev->mtu, PCI_DMA_FROMDEVICE);
                }
+               prefetch(skb->data);
                rx_osm_handler(ring_data, rxdp);
                get_info.offset++;
                ring_data->rx_curr_get_info.offset = get_info.offset;
@@ -2737,6 +2790,10 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
                if (txdlp->Control_1 & TXD_T_CODE) {
                        unsigned long long err;
                        err = txdlp->Control_1 & TXD_T_CODE;
+                       if (err & 0x1) {
+                               nic->mac_control.stats_info->sw_stat.
+                                               parity_err_cnt++;
+                       }
                        if ((err >> 48) == 0xA) {
                                DBG_PRINT(TX_DBG, "TxD returned due \
 to loss of link\n");
@@ -2760,7 +2817,8 @@ to loss of link\n");
                dev_kfree_skb_irq(skb);
 
                get_info.offset++;
-               get_info.offset %= get_info.fifo_len + 1;
+               if (get_info.offset == get_info.fifo_len + 1)
+                       get_info.offset = 0;
                txdlp = (TxD_t *) fifo_data->list_info
                    [get_info.offset].list_virt_addr;
                fifo_data->tx_curr_get_info.offset =
@@ -2773,6 +2831,256 @@ to loss of link\n");
        spin_unlock(&nic->tx_lock);
 }
 
+/**
+ *  s2io_mdio_write - Function to write in to MDIO registers
+ *  @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS)
+ *  @addr     : address value
+ *  @value    : data value
+ *  @dev      : pointer to net_device structure
+ *  Description:
+ *  This function is used to write values to the MDIO registers
+ *  NONE
+ */
+static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device *dev)
+{
+       u64 val64 = 0x0;
+       nic_t *sp = dev->priv;
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+
+       //address transaction
+       val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+                       | MDIO_MMD_DEV_ADDR(mmd_type)
+                       | MDIO_MMS_PRT_ADDR(0x0);
+       writeq(val64, &bar0->mdio_control);
+       val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+       writeq(val64, &bar0->mdio_control);
+       udelay(100);
+
+       //Data transaction
+       val64 = 0x0;
+       val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+                       | MDIO_MMD_DEV_ADDR(mmd_type)
+                       | MDIO_MMS_PRT_ADDR(0x0)
+                       | MDIO_MDIO_DATA(value)
+                       | MDIO_OP(MDIO_OP_WRITE_TRANS);
+       writeq(val64, &bar0->mdio_control);
+       val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+       writeq(val64, &bar0->mdio_control);
+       udelay(100);
+
+       val64 = 0x0;
+       val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+       | MDIO_MMD_DEV_ADDR(mmd_type)
+       | MDIO_MMS_PRT_ADDR(0x0)
+       | MDIO_OP(MDIO_OP_READ_TRANS);
+       writeq(val64, &bar0->mdio_control);
+       val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+       writeq(val64, &bar0->mdio_control);
+       udelay(100);
+
+}
+
+/**
+ *  s2io_mdio_read - Function to write in to MDIO registers
+ *  @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS)
+ *  @addr     : address value
+ *  @dev      : pointer to net_device structure
+ *  Description:
+ *  This function is used to read values to the MDIO registers
+ *  NONE
+ */
+static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
+{
+       u64 val64 = 0x0;
+       u64 rval64 = 0x0;
+       nic_t *sp = dev->priv;
+       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+
+       /* address transaction */
+       val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+                       | MDIO_MMD_DEV_ADDR(mmd_type)
+                       | MDIO_MMS_PRT_ADDR(0x0);
+       writeq(val64, &bar0->mdio_control);
+       val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+       writeq(val64, &bar0->mdio_control);
+       udelay(100);
+
+       /* Data transaction */
+       val64 = 0x0;
+       val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+                       | MDIO_MMD_DEV_ADDR(mmd_type)
+                       | MDIO_MMS_PRT_ADDR(0x0)
+                       | MDIO_OP(MDIO_OP_READ_TRANS);
+       writeq(val64, &bar0->mdio_control);
+       val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+       writeq(val64, &bar0->mdio_control);
+       udelay(100);
+
+       /* Read the value from regs */
+       rval64 = readq(&bar0->mdio_control);
+       rval64 = rval64 & 0xFFFF0000;
+       rval64 = rval64 >> 16;
+       return rval64;
+}
+/**
+ *  s2io_chk_xpak_counter - Function to check the status of the xpak counters
+ *  @counter      : couter value to be updated
+ *  @flag         : flag to indicate the status
+ *  @type         : counter type
+ *  Description:
+ *  This function is to check the status of the xpak counters value
+ *  NONE
+ */
+
+static void s2io_chk_xpak_counter(u64 *counter, u64 * regs_stat, u32 index, u16 flag, u16 type)
+{
+       u64 mask = 0x3;
+       u64 val64;
+       int i;
+       for(i = 0; i <index; i++)
+               mask = mask << 0x2;
+
+       if(flag > 0)
+       {
+               *counter = *counter + 1;
+               val64 = *regs_stat & mask;
+               val64 = val64 >> (index * 0x2);
+               val64 = val64 + 1;
+               if(val64 == 3)
+               {
+                       switch(type)
+                       {
+                       case 1:
+                               DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
+                                         "service. Excessive temperatures may "
+                                         "result in premature transceiver "
+                                         "failure \n");
+                       break;
+                       case 2:
+                               DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
+                                         "service Excessive bias currents may "
+                                         "indicate imminent laser diode "
+                                         "failure \n");
+                       break;
+                       case 3:
+                               DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
+                                         "service Excessive laser output "
+                                         "power may saturate far-end "
+                                         "receiver\n");
+                       break;
+                       default:
+                               DBG_PRINT(ERR_DBG, "Incorrect XPAK Alarm "
+                                         "type \n");
+                       }
+                       val64 = 0x0;
+               }
+               val64 = val64 << (index * 0x2);
+               *regs_stat = (*regs_stat & (~mask)) | (val64);
+
+       } else {
+               *regs_stat = *regs_stat & (~mask);
+       }
+}
+
+/**
+ *  s2io_updt_xpak_counter - Function to update the xpak counters
+ *  @dev         : pointer to net_device struct
+ *  Description:
+ *  This function is to upate the status of the xpak counters value
+ *  NONE
+ */
+static void s2io_updt_xpak_counter(struct net_device *dev)
+{
+       u16 flag  = 0x0;
+       u16 type  = 0x0;
+       u16 val16 = 0x0;
+       u64 val64 = 0x0;
+       u64 addr  = 0x0;
+
+       nic_t *sp = dev->priv;
+       StatInfo_t *stat_info = sp->mac_control.stats_info;
+
+       /* Check the communication with the MDIO slave */
+       addr = 0x0000;
+       val64 = 0x0;
+       val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+       if((val64 == 0xFFFF) || (val64 == 0x0000))
+       {
+               DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - "
+                         "Returned %llx\n", (unsigned long long)val64);
+               return;
+       }
+
+       /* Check for the expecte value of 2040 at PMA address 0x0000 */
+       if(val64 != 0x2040)
+       {
+               DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - ");
+               DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n",
+                         (unsigned long long)val64);
+               return;
+       }
+
+       /* Loading the DOM register to MDIO register */
+       addr = 0xA100;
+       s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev);
+       val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+
+       /* Reading the Alarm flags */
+       addr = 0xA070;
+       val64 = 0x0;
+       val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+
+       flag = CHECKBIT(val64, 0x7);
+       type = 1;
+       s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_transceiver_temp_high,
+                               &stat_info->xpak_stat.xpak_regs_stat,
+                               0x0, flag, type);
+
+       if(CHECKBIT(val64, 0x6))
+               stat_info->xpak_stat.alarm_transceiver_temp_low++;
+
+       flag = CHECKBIT(val64, 0x3);
+       type = 2;
+       s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_bias_current_high,
+                               &stat_info->xpak_stat.xpak_regs_stat,
+                               0x2, flag, type);
+
+       if(CHECKBIT(val64, 0x2))
+               stat_info->xpak_stat.alarm_laser_bias_current_low++;
+
+       flag = CHECKBIT(val64, 0x1);
+       type = 3;
+       s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_output_power_high,
+                               &stat_info->xpak_stat.xpak_regs_stat,
+                               0x4, flag, type);
+
+       if(CHECKBIT(val64, 0x0))
+               stat_info->xpak_stat.alarm_laser_output_power_low++;
+
+       /* Reading the Warning flags */
+       addr = 0xA074;
+       val64 = 0x0;
+       val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+
+       if(CHECKBIT(val64, 0x7))
+               stat_info->xpak_stat.warn_transceiver_temp_high++;
+
+       if(CHECKBIT(val64, 0x6))
+               stat_info->xpak_stat.warn_transceiver_temp_low++;
+
+       if(CHECKBIT(val64, 0x3))
+               stat_info->xpak_stat.warn_laser_bias_current_high++;
+
+       if(CHECKBIT(val64, 0x2))
+               stat_info->xpak_stat.warn_laser_bias_current_low++;
+
+       if(CHECKBIT(val64, 0x1))
+               stat_info->xpak_stat.warn_laser_output_power_high++;
+
+       if(CHECKBIT(val64, 0x0))
+               stat_info->xpak_stat.warn_laser_output_power_low++;
+}
+
 /**
  *  alarm_intr_handler - Alarm Interrrupt handler
  *  @nic: device private variable
@@ -2790,6 +3098,18 @@ static void alarm_intr_handler(struct s2io_nic *nic)
        struct net_device *dev = (struct net_device *) nic->dev;
        XENA_dev_config_t __iomem *bar0 = nic->bar0;
        register u64 val64 = 0, err_reg = 0;
+       u64 cnt;
+       int i;
+       nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
+       /* Handling the XPAK counters update */
+       if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
+               /* waiting for an hour */
+               nic->mac_control.stats_info->xpak_stat.xpak_timer_count++;
+       } else {
+               s2io_updt_xpak_counter(dev);
+               /* reset the count to zero */
+               nic->mac_control.stats_info->xpak_stat.xpak_timer_count = 0;
+       }
 
        /* Handling link status change error Intr */
        if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
@@ -2816,6 +3136,8 @@ static void alarm_intr_handler(struct s2io_nic *nic)
                                             MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
                                        netif_stop_queue(dev);
                                        schedule_work(&nic->rst_timer_task);
+                                       nic->mac_control.stats_info->sw_stat.
+                                                       soft_reset_cnt++;
                                }
                        }
                } else {
@@ -2827,11 +3149,13 @@ static void alarm_intr_handler(struct s2io_nic *nic)
        /* In case of a serious error, the device will be Reset. */
        val64 = readq(&bar0->serr_source);
        if (val64 & SERR_SOURCE_ANY) {
+               nic->mac_control.stats_info->sw_stat.serious_err_cnt++;
                DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
                DBG_PRINT(ERR_DBG, "serious error %llx!!\n", 
                          (unsigned long long)val64);
                netif_stop_queue(dev);
                schedule_work(&nic->rst_timer_task);
+               nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
        }
 
        /*
@@ -2849,6 +3173,35 @@ static void alarm_intr_handler(struct s2io_nic *nic)
                ac = readq(&bar0->adapter_control);
                schedule_work(&nic->set_link_task);
        }
+       /* Check for data parity error */
+       val64 = readq(&bar0->pic_int_status);
+       if (val64 & PIC_INT_GPIO) {
+               val64 = readq(&bar0->gpio_int_reg);
+               if (val64 & GPIO_INT_REG_DP_ERR_INT) {
+                       nic->mac_control.stats_info->sw_stat.parity_err_cnt++;
+                       schedule_work(&nic->rst_timer_task);
+                       nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
+               }
+       }
+
+       /* Check for ring full counter */
+       if (nic->device_type & XFRAME_II_DEVICE) {
+               val64 = readq(&bar0->ring_bump_counter1);
+               for (i=0; i<4; i++) {
+                       cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
+                       cnt >>= 64 - ((i+1)*16);
+                       nic->mac_control.stats_info->sw_stat.ring_full_cnt
+                               += cnt;
+               }
+
+               val64 = readq(&bar0->ring_bump_counter2);
+               for (i=0; i<4; i++) {
+                       cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
+                       cnt >>= 64 - ((i+1)*16);
+                       nic->mac_control.stats_info->sw_stat.ring_full_cnt
+                               += cnt;
+               }
+       }
 
        /* Other type of interrupts are not being handled now,  TODO */
 }
@@ -2864,23 +3217,26 @@ static void alarm_intr_handler(struct s2io_nic *nic)
  *   SUCCESS on success and FAILURE on failure.
  */
 
-static int wait_for_cmd_complete(nic_t * sp)
+static int wait_for_cmd_complete(void *addr, u64 busy_bit)
 {
-       XENA_dev_config_t __iomem *bar0 = sp->bar0;
        int ret = FAILURE, cnt = 0;
        u64 val64;
 
        while (TRUE) {
-               val64 = readq(&bar0->rmac_addr_cmd_mem);
-               if (!(val64 & RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
+               val64 = readq(addr);
+               if (!(val64 & busy_bit)) {
                        ret = SUCCESS;
                        break;
                }
-               msleep(50);
+
+               if(in_interrupt())
+                       mdelay(50);
+               else
+                       msleep(50);
+
                if (cnt++ > 10)
                        break;
        }
-
        return ret;
 }
 
@@ -2919,6 +3275,9 @@ static void s2io_reset(nic_t * sp)
         * PCI write to sw_reset register is done by this time.
         */
        msleep(250);
+       if (strstr(sp->product_name, "CX4")) {
+               msleep(750);
+       }
 
        /* Restore the PCI state saved during initialization. */
        pci_restore_state(sp->pdev);
@@ -3137,7 +3496,7 @@ static void restore_xmsi_data(nic_t *nic)
        u64 val64;
        int i;
 
-       for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+       for (i=0; i< nic->avail_msix_vectors; i++) {
                writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
                writeq(nic->msix_info[i].data, &bar0->xmsi_data);
                val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
@@ -3156,7 +3515,7 @@ static void store_xmsi_data(nic_t *nic)
        int i;
 
        /* Store and display */
-       for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+       for (i=0; i< nic->avail_msix_vectors; i++) {
                val64 = (BIT(15) | vBIT(i, 26, 6));
                writeq(val64, &bar0->xmsi_access);
                if (wait_for_msix_trans(nic, i)) {
@@ -3284,15 +3643,24 @@ static int s2io_enable_msi_x(nic_t *nic)
                writeq(tx_mat, &bar0->tx_mat0_n[7]);
        }
 
+       nic->avail_msix_vectors = 0;
        ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
+       /* We fail init if error or we get less vectors than min required */
+       if (ret >= (nic->config.tx_fifo_num + nic->config.rx_ring_num + 1)) {
+               nic->avail_msix_vectors = ret;
+               ret = pci_enable_msix(nic->pdev, nic->entries, ret);
+       }
        if (ret) {
                DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
                kfree(nic->entries);
                kfree(nic->s2io_entries);
                nic->entries = NULL;
                nic->s2io_entries = NULL;
+               nic->avail_msix_vectors = 0;
                return -ENOMEM;
        }
+       if (!nic->avail_msix_vectors)
+               nic->avail_msix_vectors = MAX_REQUESTED_MSI_X;
 
        /*
         * To enable MSI-X, MSI also needs to be enabled, due to a bug
@@ -3325,8 +3693,6 @@ static int s2io_open(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
        int err = 0;
-       int i;
-       u16 msi_control; /* Temp variable */
 
        /*
         * Make sure you have link off by default every time
@@ -3336,11 +3702,14 @@ static int s2io_open(struct net_device *dev)
        sp->last_link_state = 0;
 
        /* Initialize H/W and enable interrupts */
-       if (s2io_card_up(sp)) {
+       err = s2io_card_up(sp);
+       if (err) {
                DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
                          dev->name);
-               err = -ENODEV;
-               goto hw_init_failed;
+               if (err == -ENODEV)
+                       goto hw_init_failed;
+               else
+                       goto hw_enable_failed;
        }
 
        /* Store the values of the MSIX table in the nic_t structure */
@@ -3357,6 +3726,8 @@ failed\n", dev->name);
                }
        }
        if (sp->intr_type == MSI_X) {
+               int i;
+
                for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
                        if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
                                sprintf(sp->desc1, "%s:MSI-X-%d-TX",
@@ -3409,24 +3780,26 @@ setting_mac_address_failed:
 isr_registration_failed:
        del_timer_sync(&sp->alarm_timer);
        if (sp->intr_type == MSI_X) {
-               if (sp->device_type == XFRAME_II_DEVICE) {
-                       for (i=1; (sp->s2io_entries[i].in_use == 
-                               MSIX_REGISTERED_SUCCESS); i++) {
-                               int vector = sp->entries[i].vector;
-                               void *arg = sp->s2io_entries[i].arg;
+               int i;
+               u16 msi_control; /* Temp variable */
 
-                               free_irq(vector, arg);
-                       }
-                       pci_disable_msix(sp->pdev);
+               for (i=1; (sp->s2io_entries[i].in_use == 
+                               MSIX_REGISTERED_SUCCESS); i++) {
+                       int vector = sp->entries[i].vector;
+                       void *arg = sp->s2io_entries[i].arg;
 
-                       /* Temp */
-                       pci_read_config_word(sp->pdev, 0x42, &msi_control);
-                       msi_control &= 0xFFFE; /* Disable MSI */
-                       pci_write_config_word(sp->pdev, 0x42, msi_control);
+                       free_irq(vector, arg);
                }
+               pci_disable_msix(sp->pdev);
+
+               /* Temp */
+               pci_read_config_word(sp->pdev, 0x42, &msi_control);
+               msi_control &= 0xFFFE; /* Disable MSI */
+               pci_write_config_word(sp->pdev, 0x42, msi_control);
        }
        else if (sp->intr_type == MSI)
                pci_disable_msi(sp->pdev);
+hw_enable_failed:
        s2io_reset(sp);
 hw_init_failed:
        if (sp->intr_type == MSI_X) {
@@ -3454,35 +3827,12 @@ hw_init_failed:
 static int s2io_close(struct net_device *dev)
 {
        nic_t *sp = dev->priv;
-       int i;
-       u16 msi_control;
 
        flush_scheduled_work();
        netif_stop_queue(dev);
        /* Reset card, kill tasklet and free Tx and Rx buffers. */
-       s2io_card_down(sp);
-
-       if (sp->intr_type == MSI_X) {
-               if (sp->device_type == XFRAME_II_DEVICE) {
-                       for (i=1; (sp->s2io_entries[i].in_use == 
-                                       MSIX_REGISTERED_SUCCESS); i++) {
-                               int vector = sp->entries[i].vector;
-                               void *arg = sp->s2io_entries[i].arg;
+       s2io_card_down(sp, 1);
 
-                               free_irq(vector, arg);
-                       }
-                       pci_read_config_word(sp->pdev, 0x42, &msi_control);
-                       msi_control &= 0xFFFE; /* Disable MSI */
-                       pci_write_config_word(sp->pdev, 0x42, msi_control);
-
-                       pci_disable_msix(sp->pdev);
-               }
-       }
-       else {
-               free_irq(sp->pdev->irq, dev);
-               if (sp->intr_type == MSI)
-                       pci_disable_msi(sp->pdev);
-       }       
        sp->device_close_flag = TRUE;   /* Device is shut down. */
        return 0;
 }
@@ -3545,7 +3895,8 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 
        queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
        /* Avoid "put" pointer going beyond "get" pointer */
-       if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) {
+       if (txdp->Host_Control ||
+                  ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
                DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
                netif_stop_queue(dev);
                dev_kfree_skb(skb);
@@ -3655,11 +4006,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
        mmiowb();
 
        put_off++;
-       put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
+       if (put_off == mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1)
+               put_off = 0;
        mac_control->fifos[queue].tx_curr_put_info.offset = put_off;
 
        /* Avoid "put" pointer going beyond "get" pointer */
-       if (((put_off + 1) % queue_len) == get_off) {
+       if (((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
+               sp->mac_control.stats_info->sw_stat.fifo_full_cnt++;
                DBG_PRINT(TX_DBG,
                          "No free TxDs for xmit, Put: 0x%x Get:0x%x\n",
                          put_off, get_off);
@@ -3795,7 +4148,6 @@ s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
        atomic_dec(&sp->isr_cnt);
        return IRQ_HANDLED;
 }
-
 static void s2io_txpic_intr_handle(nic_t *sp)
 {
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -3806,41 +4158,56 @@ static void s2io_txpic_intr_handle(nic_t *sp)
                val64 = readq(&bar0->gpio_int_reg);
                if ((val64 & GPIO_INT_REG_LINK_DOWN) &&
                    (val64 & GPIO_INT_REG_LINK_UP)) {
+                       /*
+                        * This is unstable state so clear both up/down
+                        * interrupt and adapter to re-evaluate the link state.
+                        */
                        val64 |=  GPIO_INT_REG_LINK_DOWN;
                        val64 |= GPIO_INT_REG_LINK_UP;
                        writeq(val64, &bar0->gpio_int_reg);
-                       goto masking;
-               }
-
-               if (((sp->last_link_state == LINK_UP) &&
-                       (val64 & GPIO_INT_REG_LINK_DOWN)) ||
-               ((sp->last_link_state == LINK_DOWN) &&
-               (val64 & GPIO_INT_REG_LINK_UP))) {
                        val64 = readq(&bar0->gpio_int_mask);
-                       val64 |=  GPIO_INT_MASK_LINK_DOWN;
-                       val64 |= GPIO_INT_MASK_LINK_UP;
+                       val64 &= ~(GPIO_INT_MASK_LINK_UP |
+                                  GPIO_INT_MASK_LINK_DOWN);
                        writeq(val64, &bar0->gpio_int_mask);
-                       s2io_set_link((unsigned long)sp);
                }
-masking:
-               if (sp->last_link_state == LINK_UP) {
-                       /*enable down interrupt */
-                       val64 = readq(&bar0->gpio_int_mask);
-                       /* unmasks link down intr */
-                       val64 &=  ~GPIO_INT_MASK_LINK_DOWN;
-                       /* masks link up intr */
-                       val64 |= GPIO_INT_MASK_LINK_UP;
-                       writeq(val64, &bar0->gpio_int_mask);
-               } else {
-                       /*enable UP Interrupt */
-                       val64 = readq(&bar0->gpio_int_mask);
-                       /* unmasks link up interrupt */
-                       val64 &= ~GPIO_INT_MASK_LINK_UP;
-                       /* masks link down interrupt */
-                       val64 |=  GPIO_INT_MASK_LINK_DOWN;
-                       writeq(val64, &bar0->gpio_int_mask);
+               else if (val64 & GPIO_INT_REG_LINK_UP) {
+                       val64 = readq(&bar0->adapter_status);
+                       if (verify_xena_quiescence(sp, val64,
+                                                  sp->device_enabled_once)) {
+                               /* Enable Adapter */
+                               val64 = readq(&bar0->adapter_control);
+                               val64 |= ADAPTER_CNTL_EN;
+                               writeq(val64, &bar0->adapter_control);
+                               val64 |= ADAPTER_LED_ON;
+                               writeq(val64, &bar0->adapter_control);
+                               if (!sp->device_enabled_once)
+                                       sp->device_enabled_once = 1;
+
+                               s2io_link(sp, LINK_UP);
+                               /*
+                                * unmask link down interrupt and mask link-up
+                                * intr
+                                */
+                               val64 = readq(&bar0->gpio_int_mask);
+                               val64 &= ~GPIO_INT_MASK_LINK_DOWN;
+                               val64 |= GPIO_INT_MASK_LINK_UP;
+                               writeq(val64, &bar0->gpio_int_mask);
+
+                       }
+               }else if (val64 & GPIO_INT_REG_LINK_DOWN) {
+                       val64 = readq(&bar0->adapter_status);
+                       if (verify_xena_quiescence(sp, val64,
+                                                  sp->device_enabled_once)) {
+                               s2io_link(sp, LINK_DOWN);
+                               /* Link is down so unmaks link up interrupt */
+                               val64 = readq(&bar0->gpio_int_mask);
+                               val64 &= ~GPIO_INT_MASK_LINK_UP;
+                               val64 |= GPIO_INT_MASK_LINK_DOWN;
+                               writeq(val64, &bar0->gpio_int_mask);
+                       }
                }
        }
+       val64 = readq(&bar0->gpio_int_mask);
 }
 
 /**
@@ -3863,7 +4230,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
        nic_t *sp = dev->priv;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        int i;
-       u64 reason = 0, val64;
+       u64 reason = 0, val64, org_mask;
        mac_info_t *mac_control;
        struct config_param *config;
 
@@ -3887,43 +4254,41 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
                return IRQ_NONE;
        }
 
+       val64 = 0xFFFFFFFFFFFFFFFFULL;
+       /* Store current mask before masking all interrupts */
+       org_mask = readq(&bar0->general_int_mask);
+       writeq(val64, &bar0->general_int_mask);
+
 #ifdef CONFIG_S2IO_NAPI
        if (reason & GEN_INTR_RXTRAFFIC) {
                if (netif_rx_schedule_prep(dev)) {
-                       en_dis_able_nic_intrs(sp, RX_TRAFFIC_INTR,
-                                             DISABLE_INTRS);
+                       writeq(val64, &bar0->rx_traffic_mask);
                        __netif_rx_schedule(dev);
                }
        }
 #else
-       /* If Intr is because of Rx Traffic */
-       if (reason & GEN_INTR_RXTRAFFIC) {
-               /*
-                * rx_traffic_int reg is an R1 register, writing all 1's
-                * will ensure that the actual interrupt causing bit get's
-                * cleared and hence a read can be avoided.
-                */
-               val64 = 0xFFFFFFFFFFFFFFFFULL;
-               writeq(val64, &bar0->rx_traffic_int);
-               for (i = 0; i < config->rx_ring_num; i++) {
-                       rx_intr_handler(&mac_control->rings[i]);
-               }
+       /*
+        * Rx handler is called by default, without checking for the
+        * cause of interrupt.
+        * rx_traffic_int reg is an R1 register, writing all 1's
+        * will ensure that the actual interrupt causing bit get's
+        * cleared and hence a read can be avoided.
+        */
+       writeq(val64, &bar0->rx_traffic_int);
+       for (i = 0; i < config->rx_ring_num; i++) {
+               rx_intr_handler(&mac_control->rings[i]);
        }
 #endif
 
-       /* If Intr is because of Tx Traffic */
-       if (reason & GEN_INTR_TXTRAFFIC) {
-               /*
-                * tx_traffic_int reg is an R1 register, writing all 1's
-                * will ensure that the actual interrupt causing bit get's
-                * cleared and hence a read can be avoided.
-                */
-               val64 = 0xFFFFFFFFFFFFFFFFULL;
-               writeq(val64, &bar0->tx_traffic_int);
+       /*
+        * tx_traffic_int reg is an R1 register, writing all 1's
+        * will ensure that the actual interrupt causing bit get's
+        * cleared and hence a read can be avoided.
+        */
+       writeq(val64, &bar0->tx_traffic_int);
 
-               for (i = 0; i < config->tx_fifo_num; i++)
-                       tx_intr_handler(&mac_control->fifos[i]);
-       }
+       for (i = 0; i < config->tx_fifo_num; i++)
+               tx_intr_handler(&mac_control->fifos[i]);
 
        if (reason & GEN_INTR_TXPIC)
                s2io_txpic_intr_handle(sp);
@@ -3949,6 +4314,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
                                        DBG_PRINT(ERR_DBG, " in ISR!!\n");
                                        clear_bit(0, (&sp->tasklet_status));
                                        atomic_dec(&sp->isr_cnt);
+                                       writeq(org_mask, &bar0->general_int_mask);
                                        return IRQ_HANDLED;
                                }
                                clear_bit(0, (&sp->tasklet_status));
@@ -3964,7 +4330,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
                }
        }
 #endif
-
+       writeq(org_mask, &bar0->general_int_mask);
        atomic_dec(&sp->isr_cnt);
        return IRQ_HANDLED;
 }
@@ -4067,7 +4433,8 @@ static void s2io_set_multicast(struct net_device *dev)
                    RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET);
                writeq(val64, &bar0->rmac_addr_cmd_mem);
                /* Wait till command completes */
-               wait_for_cmd_complete(sp);
+               wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
 
                sp->m_cast_flg = 1;
                sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET;
@@ -4082,7 +4449,8 @@ static void s2io_set_multicast(struct net_device *dev)
                    RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos);
                writeq(val64, &bar0->rmac_addr_cmd_mem);
                /* Wait till command completes */
-               wait_for_cmd_complete(sp);
+               wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
 
                sp->m_cast_flg = 0;
                sp->all_multi_pos = 0;
@@ -4147,7 +4515,8 @@ static void s2io_set_multicast(struct net_device *dev)
                        writeq(val64, &bar0->rmac_addr_cmd_mem);
 
                        /* Wait for command completes */
-                       if (wait_for_cmd_complete(sp)) {
+                       if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
                                DBG_PRINT(ERR_DBG, "%s: Adding ",
                                          dev->name);
                                DBG_PRINT(ERR_DBG, "Multicasts failed\n");
@@ -4177,7 +4546,8 @@ static void s2io_set_multicast(struct net_device *dev)
                        writeq(val64, &bar0->rmac_addr_cmd_mem);
 
                        /* Wait for command completes */
-                       if (wait_for_cmd_complete(sp)) {
+                       if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+                                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
                                DBG_PRINT(ERR_DBG, "%s: Adding ",
                                          dev->name);
                                DBG_PRINT(ERR_DBG, "Multicasts failed\n");
@@ -4222,7 +4592,8 @@ static int s2io_set_mac_addr(struct net_device *dev, u8 * addr)
            RMAC_ADDR_CMD_MEM_OFFSET(0);
        writeq(val64, &bar0->rmac_addr_cmd_mem);
        /* Wait till command completes */
-       if (wait_for_cmd_complete(sp)) {
+       if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
                DBG_PRINT(ERR_DBG, "%s: set_mac_addr failed\n", dev->name);
                return FAILURE;
        }
@@ -4619,6 +4990,44 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt)
        }
        return ret;
 }
+static void s2io_vpd_read(nic_t *nic)
+{
+       u8 vpd_data[256],data;
+       int i=0, cnt, fail = 0;
+       int vpd_addr = 0x80;
+
+       if (nic->device_type == XFRAME_II_DEVICE) {
+               strcpy(nic->product_name, "Xframe II 10GbE network adapter");
+               vpd_addr = 0x80;
+       }
+       else {
+               strcpy(nic->product_name, "Xframe I 10GbE network adapter");
+               vpd_addr = 0x50;
+       }
+
+       for (i = 0; i < 256; i +=4 ) {
+               pci_write_config_byte(nic->pdev, (vpd_addr + 2), i);
+               pci_read_config_byte(nic->pdev,  (vpd_addr + 2), &data);
+               pci_write_config_byte(nic->pdev, (vpd_addr + 3), 0);
+               for (cnt = 0; cnt <5; cnt++) {
+                       msleep(2);
+                       pci_read_config_byte(nic->pdev, (vpd_addr + 3), &data);
+                       if (data == 0x80)
+                               break;
+               }
+               if (cnt >= 5) {
+                       DBG_PRINT(ERR_DBG, "Read of VPD data failed\n");
+                       fail = 1;
+                       break;
+               }
+               pci_read_config_dword(nic->pdev,  (vpd_addr + 4),
+                                     (u32 *)&vpd_data[i]);
+       }
+       if ((!fail) && (vpd_data[1] < VPD_PRODUCT_NAME_LEN)) {
+               memset(nic->product_name, 0, vpd_data[1]);
+               memcpy(nic->product_name, &vpd_data[3], vpd_data[1]);
+       }
+}
 
 /**
  *  s2io_ethtool_geeprom  - reads the value stored in the Eeprom.
@@ -4931,8 +5340,10 @@ static int s2io_link_test(nic_t * sp, uint64_t * data)
        u64 val64;
 
        val64 = readq(&bar0->adapter_status);
-       if (val64 & ADAPTER_STATUS_RMAC_LOCAL_FAULT)
+       if(!(LINK_IS_UP(val64)))
                *data = 1;
+       else
+               *data = 0;
 
        return 0;
 }
@@ -5112,7 +5523,6 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
        int i = 0;
        nic_t *sp = dev->priv;
        StatInfo_t *stat_info = sp->mac_control.stats_info;
-       u64 tmp;
 
        s2io_updt_stats(sp);
        tmp_stats[i++] =
@@ -5129,9 +5539,19 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
                (u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 |
                le32_to_cpu(stat_info->tmac_bcst_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms);
+        tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->tmac_ttl_octets_oflow) << 32 |
+                le32_to_cpu(stat_info->tmac_ttl_octets);
+       tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->tmac_ucst_frms_oflow) << 32 |
+                le32_to_cpu(stat_info->tmac_ucst_frms);
+       tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->tmac_nucst_frms_oflow) << 32 |
+                le32_to_cpu(stat_info->tmac_nucst_frms);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 |
                le32_to_cpu(stat_info->tmac_any_err_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_ttl_less_fb_octets);
        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 |
@@ -5163,11 +5583,27 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
                (u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_vld_bcst_frms);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);
+       tmp_stats[i++] = le32_to_cpu(stat_info->rmac_out_rng_len_err_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms);
+       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_unsup_ctrl_frms);
+        tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->rmac_ttl_octets_oflow) << 32 |
+               le32_to_cpu(stat_info->rmac_ttl_octets);
+        tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->rmac_accepted_ucst_frms_oflow)
+               << 32 | le32_to_cpu(stat_info->rmac_accepted_ucst_frms);
+       tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->rmac_accepted_nucst_frms_oflow)
+                 << 32 | le32_to_cpu(stat_info->rmac_accepted_nucst_frms);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_discarded_frms);
+        tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->rmac_drop_events_oflow)
+                 << 32 | le32_to_cpu(stat_info->rmac_drop_events);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_less_fb_octets);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_frms);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_usized_frms);
@@ -5180,40 +5616,129 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_jabber_frms);
-       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
+       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_64_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_65_127_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_128_255_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_256_511_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_512_1023_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1024_1518_frms);
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_ip);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip);
-       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_drop_ip);
-       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_icmp);
        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp);
-       tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
+       tmp_stats[i++] =
+               (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_udp);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_err_drp_udp);
+       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_err_sym);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q0);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q1);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q2);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q3);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q4);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q5);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q6);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q7);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q0);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q1);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q2);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q3);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q4);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q5);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q6);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q7);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_pause_cnt);
+       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_data_err_cnt);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_ctrl_err_cnt);
        tmp_stats[i++] =
                (u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 |
                le32_to_cpu(stat_info->rmac_accepted_ip);
        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp);
+       tmp_stats[i++] = le32_to_cpu(stat_info->rd_req_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_rtry_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_rd_ack_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->wr_req_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_rtry_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->wr_disc_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_wr_ack_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->txp_wr_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->txd_rd_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->txd_wr_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->rxd_rd_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->rxd_wr_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->txf_rd_cnt);
+       tmp_stats[i++] = le32_to_cpu(stat_info->rxf_wr_cnt);
+       tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1519_4095_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_4096_8191_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_8192_max_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_gt_max_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_osized_alt_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_jabber_alt_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_gt_max_alt_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_vlan_frms);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_len_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_fcs_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pf_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_da_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_red_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_rts_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ingm_full_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->link_fault_cnt);
        tmp_stats[i++] = 0;
        tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs;
        tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;
+       tmp_stats[i++] = stat_info->sw_stat.parity_err_cnt;
+       tmp_stats[i++] = stat_info->sw_stat.serious_err_cnt;
+       tmp_stats[i++] = stat_info->sw_stat.soft_reset_cnt;
+       tmp_stats[i++] = stat_info->sw_stat.fifo_full_cnt;
+       tmp_stats[i++] = stat_info->sw_stat.ring_full_cnt;
+       tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_high;
+       tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_low;
+       tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_high;
+       tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_low;
+       tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_high;
+       tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_low;
+       tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_high;
+       tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_low;
+       tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_high;
+       tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_low;
+       tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_high;
+       tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_low;
        tmp_stats[i++] = stat_info->sw_stat.clubbed_frms_cnt;
        tmp_stats[i++] = stat_info->sw_stat.sending_both;
        tmp_stats[i++] = stat_info->sw_stat.outof_sequence_pkts;
        tmp_stats[i++] = stat_info->sw_stat.flush_max_pkts;
-       tmp = 0;
        if (stat_info->sw_stat.num_aggregations) {
-               tmp = stat_info->sw_stat.sum_avg_pkts_aggregated;
-               do_div(tmp, stat_info->sw_stat.num_aggregations);
+               u64 tmp = stat_info->sw_stat.sum_avg_pkts_aggregated;
+               int count = 0;
+               /* 
+                * Since 64-bit divide does not work on all platforms,
+                * do repeated subtraction.
+                */
+               while (tmp >= stat_info->sw_stat.num_aggregations) {
+                       tmp -= stat_info->sw_stat.num_aggregations;
+                       count++;
+               }
+               tmp_stats[i++] = count;
        }
-       tmp_stats[i++] = tmp;
+       else
+               tmp_stats[i++] = 0;
 }
 
 static int s2io_ethtool_get_regs_len(struct net_device *dev)
@@ -5351,7 +5876,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
 
        dev->mtu = new_mtu;
        if (netif_running(dev)) {
-               s2io_card_down(sp);
+               s2io_card_down(sp, 0);
                netif_stop_queue(dev);
                if (s2io_card_up(sp)) {
                        DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
@@ -5489,12 +6014,172 @@ static void s2io_set_link(unsigned long data)
        clear_bit(0, &(nic->link_state));
 }
 
-static void s2io_card_down(nic_t * sp)
+static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba,
+                          struct sk_buff **skb, u64 *temp0, u64 *temp1,
+                          u64 *temp2, int size)
+{
+       struct net_device *dev = sp->dev;
+       struct sk_buff *frag_list;
+
+       if ((sp->rxd_mode == RXD_MODE_1) && (rxdp->Host_Control == 0)) {
+               /* allocate skb */
+               if (*skb) {
+                       DBG_PRINT(INFO_DBG, "SKB is not NULL\n");
+                       /*
+                        * As Rx frame are not going to be processed,
+                        * using same mapped address for the Rxd
+                        * buffer pointer
+                        */
+                       ((RxD1_t*)rxdp)->Buffer0_ptr = *temp0;
+               } else {
+                       *skb = dev_alloc_skb(size);
+                       if (!(*skb)) {
+                               DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);
+                               DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n");
+                               return -ENOMEM ;
+                       }
+                       /* storing the mapped addr in a temp variable
+                        * such it will be used for next rxd whose
+                        * Host Control is NULL
+                        */
+                       ((RxD1_t*)rxdp)->Buffer0_ptr = *temp0 =
+                               pci_map_single( sp->pdev, (*skb)->data,
+                                       size - NET_IP_ALIGN,
+                                       PCI_DMA_FROMDEVICE);
+                       rxdp->Host_Control = (unsigned long) (*skb);
+               }
+       } else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) {
+               /* Two buffer Mode */
+               if (*skb) {
+                       ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2;
+                       ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0;
+                       ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1;
+               } else {
+                       *skb = dev_alloc_skb(size);
+                       ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 =
+                               pci_map_single(sp->pdev, (*skb)->data,
+                                              dev->mtu + 4,
+                                              PCI_DMA_FROMDEVICE);
+                       ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 =
+                               pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN,
+                                               PCI_DMA_FROMDEVICE);
+                       rxdp->Host_Control = (unsigned long) (*skb);
+
+                       /* Buffer-1 will be dummy buffer not used */
+                       ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 =
+                               pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN,
+                                              PCI_DMA_FROMDEVICE);
+               }
+       } else if ((rxdp->Host_Control == 0)) {
+               /* Three buffer mode */
+               if (*skb) {
+                       ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0;
+                       ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1;
+                       ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2;
+               } else {
+                       *skb = dev_alloc_skb(size);
+
+                       ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 =
+                               pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN,
+                                              PCI_DMA_FROMDEVICE);
+                       /* Buffer-1 receives L3/L4 headers */
+                       ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 =
+                               pci_map_single( sp->pdev, (*skb)->data,
+                                               l3l4hdr_size + 4,
+                                               PCI_DMA_FROMDEVICE);
+                       /*
+                        * skb_shinfo(skb)->frag_list will have L4
+                        * data payload
+                        */
+                       skb_shinfo(*skb)->frag_list = dev_alloc_skb(dev->mtu +
+                                                                  ALIGN_SIZE);
+                       if (skb_shinfo(*skb)->frag_list == NULL) {
+                               DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb \
+                                         failed\n ", dev->name);
+                               return -ENOMEM ;
+                       }
+                       frag_list = skb_shinfo(*skb)->frag_list;
+                       frag_list->next = NULL;
+                       /*
+                        * Buffer-2 receives L4 data payload
+                        */
+                       ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 =
+                               pci_map_single( sp->pdev, frag_list->data,
+                                               dev->mtu, PCI_DMA_FROMDEVICE);
+               }
+       }
+       return 0;
+}
+static void set_rxd_buffer_size(nic_t *sp, RxD_t *rxdp, int size)
+{
+       struct net_device *dev = sp->dev;
+       if (sp->rxd_mode == RXD_MODE_1) {
+               rxdp->Control_2 = SET_BUFFER0_SIZE_1( size - NET_IP_ALIGN);
+       } else if (sp->rxd_mode == RXD_MODE_3B) {
+               rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
+               rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
+               rxdp->Control_2 |= SET_BUFFER2_SIZE_3( dev->mtu + 4);
+       } else {
+               rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
+               rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4);
+               rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu);
+       }
+}
+
+static  int rxd_owner_bit_reset(nic_t *sp)
+{
+       int i, j, k, blk_cnt = 0, size;
+       mac_info_t * mac_control = &sp->mac_control;
+       struct config_param *config = &sp->config;
+       struct net_device *dev = sp->dev;
+       RxD_t *rxdp = NULL;
+       struct sk_buff *skb = NULL;
+       buffAdd_t *ba = NULL;
+       u64 temp0_64 = 0, temp1_64 = 0, temp2_64 = 0;
+
+       /* Calculate the size based on ring mode */
+       size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +
+               HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
+       if (sp->rxd_mode == RXD_MODE_1)
+               size += NET_IP_ALIGN;
+       else if (sp->rxd_mode == RXD_MODE_3B)
+               size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4;
+       else
+               size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4;
+
+       for (i = 0; i < config->rx_ring_num; i++) {
+               blk_cnt = config->rx_cfg[i].num_rxd /
+                       (rxd_count[sp->rxd_mode] +1);
+
+               for (j = 0; j < blk_cnt; j++) {
+                       for (k = 0; k < rxd_count[sp->rxd_mode]; k++) {
+                               rxdp = mac_control->rings[i].
+                                       rx_blocks[j].rxds[k].virt_addr;
+                               if(sp->rxd_mode >= RXD_MODE_3A)
+                                       ba = &mac_control->rings[i].ba[j][k];
+                               set_rxd_buffer_pointer(sp, rxdp, ba,
+                                                      &skb,(u64 *)&temp0_64,
+                                                      (u64 *)&temp1_64,
+                                                      (u64 *)&temp2_64, size);
+
+                               set_rxd_buffer_size(sp, rxdp, size);
+                               wmb();
+                               /* flip the Ownership bit to Hardware */
+                               rxdp->Control_1 |= RXD_OWN_XENA;
+                       }
+               }
+       }
+       return 0;
+
+}
+
+static void s2io_card_down(nic_t * sp, int flag)
 {
        int cnt = 0;
        XENA_dev_config_t __iomem *bar0 = sp->bar0;
        unsigned long flags;
        register u64 val64 = 0;
+       struct net_device *dev = sp->dev;
 
        del_timer_sync(&sp->alarm_timer);
        /* If s2io_set_link task is executing, wait till it completes. */
@@ -5505,12 +6190,51 @@ static void s2io_card_down(nic_t * sp)
 
        /* disable Tx and Rx traffic on the NIC */
        stop_nic(sp);
+       if (flag) {
+               if (sp->intr_type == MSI_X) {
+                       int i;
+                       u16 msi_control;
+
+                       for (i=1; (sp->s2io_entries[i].in_use ==
+                               MSIX_REGISTERED_SUCCESS); i++) {
+                               int vector = sp->entries[i].vector;
+                               void *arg = sp->s2io_entries[i].arg;
+
+                               free_irq(vector, arg);
+                       }
+                       pci_read_config_word(sp->pdev, 0x42, &msi_control);
+                       msi_control &= 0xFFFE; /* Disable MSI */
+                       pci_write_config_word(sp->pdev, 0x42, msi_control);
+                       pci_disable_msix(sp->pdev);
+               } else {
+                       free_irq(sp->pdev->irq, dev);
+                       if (sp->intr_type == MSI)
+                               pci_disable_msi(sp->pdev);
+               }
+       }
+       /* Waiting till all Interrupt handlers are complete */
+       cnt = 0;
+       do {
+               msleep(10);
+               if (!atomic_read(&sp->isr_cnt))
+                       break;
+               cnt++;
+       } while(cnt < 5);
 
        /* Kill tasklet. */
        tasklet_kill(&sp->task);
 
        /* Check if the device is Quiescent and then Reset the NIC */
        do {
+               /* As per the HW requirement we need to replenish the
+                * receive buffer to avoid the ring bump. Since there is
+                * no intention of processing the Rx frame at this pointwe are
+                * just settting the ownership bit of rxd in Each Rx
+                * ring to HW and set the appropriate buffer size
+                * based on the ring mode
+                */
+               rxd_owner_bit_reset(sp);
+
                val64 = readq(&bar0->adapter_status);
                if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) {
                        break;
@@ -5528,15 +6252,6 @@ static void s2io_card_down(nic_t * sp)
        } while (1);
        s2io_reset(sp);
 
-       /* Waiting till all Interrupt handlers are complete */
-       cnt = 0;
-       do {
-               msleep(10);
-               if (!atomic_read(&sp->isr_cnt))
-                       break;
-               cnt++;
-       } while(cnt < 5);
-
        spin_lock_irqsave(&sp->tx_lock, flags);
        /* Free all Tx buffers */
        free_tx_buffers(sp);
@@ -5637,7 +6352,7 @@ static void s2io_restart_nic(unsigned long data)
        struct net_device *dev = (struct net_device *) data;
        nic_t *sp = dev->priv;
 
-       s2io_card_down(sp);
+       s2io_card_down(sp, 0);
        if (s2io_card_up(sp)) {
                DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
                          dev->name);
@@ -5667,6 +6382,7 @@ static void s2io_tx_watchdog(struct net_device *dev)
 
        if (netif_carrier_ok(dev)) {
                schedule_work(&sp->rst_timer_task);
+               sp->mac_control.stats_info->sw_stat.soft_reset_cnt++;
        }
 }
 
@@ -5695,18 +6411,33 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
                ((unsigned long) rxdp->Host_Control);
        int ring_no = ring_data->ring_no;
        u16 l3_csum, l4_csum;
+       unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
        lro_t *lro;
 
        skb->dev = dev;
-       if (rxdp->Control_1 & RXD_T_CODE) {
-               unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
-               DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
-                         dev->name, err);
-               dev_kfree_skb(skb);
-               sp->stats.rx_crc_errors++;
-               atomic_dec(&sp->rx_bufs_left[ring_no]);
-               rxdp->Host_Control = 0;
-               return 0;
+
+       if (err) {
+               /* Check for parity error */
+               if (err & 0x1) {
+                       sp->mac_control.stats_info->sw_stat.parity_err_cnt++;
+               }
+
+               /*
+               * Drop the packet if bad transfer code. Exception being
+               * 0x5, which could be due to unsupported IPv6 extension header.
+               * In this case, we let stack handle the packet.
+               * Note that in this case, since checksum will be incorrect,
+               * stack will validate the same.
+               */
+               if (err && ((err >> 48) != 0x5)) {
+                       DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
+                               dev->name, err);
+                       sp->stats.rx_crc_errors++;
+                       dev_kfree_skb(skb);
+                       atomic_dec(&sp->rx_bufs_left[ring_no]);
+                       rxdp->Host_Control = 0;
+                       return 0;
+               }
        }
 
        /* Updating statistics */
@@ -5792,6 +6523,9 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)
                                                clear_lro_session(lro);
                                                goto send_up;
                                        case 0: /* sessions exceeded */
+                                       case -1: /* non-TCP or not
+                                                 * L2 aggregatable
+                                                 */
                                        case 5: /*
                                                 * First pkt in session not
                                                 * L3/L4 aggregatable
@@ -5918,13 +6652,6 @@ static void s2io_init_pci(nic_t * sp)
        pci_write_config_word(sp->pdev, PCI_COMMAND,
                              (pci_cmd | PCI_COMMAND_PARITY));
        pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
-
-       /* Forcibly disabling relaxed ordering capability of the card. */
-       pcix_cmd &= 0xfffd;
-       pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-                             pcix_cmd);
-       pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-                            &(pcix_cmd));
 }
 
 MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
@@ -5954,6 +6681,55 @@ module_param(intr_type, int, 0);
 module_param(lro, int, 0);
 module_param(lro_max_pkts, int, 0);
 
+static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
+{
+       if ( tx_fifo_num > 8) {
+               DBG_PRINT(ERR_DBG, "s2io: Requested number of Tx fifos not "
+                        "supported\n");
+               DBG_PRINT(ERR_DBG, "s2io: Default to 8 Tx fifos\n");
+               tx_fifo_num = 8;
+       }
+       if ( rx_ring_num > 8) {
+               DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not "
+                        "supported\n");
+               DBG_PRINT(ERR_DBG, "s2io: Default to 8 Rx rings\n");
+               rx_ring_num = 8;
+       }
+#ifdef CONFIG_S2IO_NAPI
+       if (*dev_intr_type != INTA) {
+               DBG_PRINT(ERR_DBG, "s2io: NAPI cannot be enabled when "
+                         "MSI/MSI-X is enabled. Defaulting to INTA\n");
+               *dev_intr_type = INTA;
+       }
+#endif
+#ifndef CONFIG_PCI_MSI
+       if (*dev_intr_type != INTA) {
+               DBG_PRINT(ERR_DBG, "s2io: This kernel does not support"
+                         "MSI/MSI-X. Defaulting to INTA\n");
+               *dev_intr_type = INTA;
+       }
+#else
+       if (*dev_intr_type > MSI_X) {
+               DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. "
+                         "Defaulting to INTA\n");
+               *dev_intr_type = INTA;
+       }
+#endif
+       if ((*dev_intr_type == MSI_X) &&
+                       ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
+                       (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
+               DBG_PRINT(ERR_DBG, "s2io: Xframe I does not support MSI_X. " 
+                                       "Defaulting to INTA\n");
+               *dev_intr_type = INTA;
+       }
+       if (rx_ring_mode > 3) {
+               DBG_PRINT(ERR_DBG, "s2io: Requested ring mode not supported\n");
+               DBG_PRINT(ERR_DBG, "s2io: Defaulting to 3-buffer mode\n");
+               rx_ring_mode = 3;
+       }
+       return SUCCESS;
+}
+
 /**
  *  s2io_init_nic - Initialization of the adapter .
  *  @pdev : structure containing the PCI related information of the device.
@@ -5984,15 +6760,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        int mode;
        u8 dev_intr_type = intr_type;
 
-#ifdef CONFIG_S2IO_NAPI
-       if (dev_intr_type != INTA) {
-               DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \
-is enabled. Defaulting to INTA\n");
-               dev_intr_type = INTA;
-       }
-       else
-               DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
-#endif
+       if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
+               return ret;
 
        if ((ret = pci_enable_device(pdev))) {
                DBG_PRINT(ERR_DBG,
@@ -6017,14 +6786,6 @@ is enabled. Defaulting to INTA\n");
                pci_disable_device(pdev);
                return -ENOMEM;
        }
-
-       if ((dev_intr_type == MSI_X) && 
-                       ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
-                       (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
-               DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \
-Defaulting to INTA\n");
-               dev_intr_type = INTA;
-       }
        if (dev_intr_type != MSI_X) {
                if (pci_request_regions(pdev, s2io_driver_name)) {
                        DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
@@ -6100,8 +6861,6 @@ Defaulting to INTA\n");
        config = &sp->config;
 
        /* Tx side parameters. */
-       if (tx_fifo_len[0] == 0)
-               tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */
        config->tx_fifo_num = tx_fifo_num;
        for (i = 0; i < MAX_TX_FIFOS; i++) {
                config->tx_cfg[i].fifo_len = tx_fifo_len[i];
@@ -6125,8 +6884,6 @@ Defaulting to INTA\n");
        config->max_txds = MAX_SKB_FRAGS + 2;
 
        /* Rx side parameters. */
-       if (rx_ring_sz[0] == 0)
-               rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */
        config->rx_ring_num = rx_ring_num;
        for (i = 0; i < MAX_RX_RINGS; i++) {
                config->rx_cfg[i].num_rxd = rx_ring_sz[i] *
@@ -6267,8 +7024,8 @@ Defaulting to INTA\n");
        val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
            RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET);
        writeq(val64, &bar0->rmac_addr_cmd_mem);
-       wait_for_cmd_complete(sp);
-
+       wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+                     RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
        tmp64 = readq(&bar0->rmac_addr_data0_mem);
        mac_down = (u32) tmp64;
        mac_up = (u32) (tmp64 >> 32);
@@ -6322,82 +7079,63 @@ Defaulting to INTA\n");
                ret = -ENODEV;
                goto register_failed;
        }
-
-       if (sp->device_type & XFRAME_II_DEVICE) {
-               DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
-                         dev->name);
-               DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
+       s2io_vpd_read(sp);
+       DBG_PRINT(ERR_DBG, "%s: Neterion %s",dev->name, sp->product_name);
+       DBG_PRINT(ERR_DBG, "(rev %d), Driver version %s\n",
                                get_xena_rev_id(sp->pdev),
                                s2io_driver_version);
-               switch(sp->intr_type) {
-                       case INTA:
-                               DBG_PRINT(ERR_DBG, ", Intr type INTA");
-                               break;
-                       case MSI:
-                               DBG_PRINT(ERR_DBG, ", Intr type MSI");
-                               break;
-                       case MSI_X:
-                               DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
-                               break;
-               }
-
-               DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
-               DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+       DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2005 Neterion Inc.\n");
+       DBG_PRINT(ERR_DBG, "%s: MAC ADDR: "
+                         "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
                          sp->def_mac_addr[0].mac_addr[0],
                          sp->def_mac_addr[0].mac_addr[1],
                          sp->def_mac_addr[0].mac_addr[2],
                          sp->def_mac_addr[0].mac_addr[3],
                          sp->def_mac_addr[0].mac_addr[4],
                          sp->def_mac_addr[0].mac_addr[5]);
+       if (sp->device_type & XFRAME_II_DEVICE) {
                mode = s2io_print_pci_mode(sp);
                if (mode < 0) {
-                       DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode ");
+                       DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n");
                        ret = -EBADSLT;
+                       unregister_netdev(dev);
                        goto set_swap_failed;
                }
-       } else {
-               DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
-                         dev->name);
-               DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
-                                       get_xena_rev_id(sp->pdev),
-                                       s2io_driver_version);
-               switch(sp->intr_type) {
-                       case INTA:
-                               DBG_PRINT(ERR_DBG, ", Intr type INTA");
-                               break;
-                       case MSI:
-                               DBG_PRINT(ERR_DBG, ", Intr type MSI");
-                               break;
-                       case MSI_X:
-                               DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
-                               break;
-               }
-               DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
-               DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
-                         sp->def_mac_addr[0].mac_addr[0],
-                         sp->def_mac_addr[0].mac_addr[1],
-                         sp->def_mac_addr[0].mac_addr[2],
-                         sp->def_mac_addr[0].mac_addr[3],
-                         sp->def_mac_addr[0].mac_addr[4],
-                         sp->def_mac_addr[0].mac_addr[5]);
        }
-       if (sp->rxd_mode == RXD_MODE_3B)
-               DBG_PRINT(ERR_DBG, "%s: 2-Buffer mode support has been "
-                         "enabled\n",dev->name);
-       if (sp->rxd_mode == RXD_MODE_3A)
-               DBG_PRINT(ERR_DBG, "%s: 3-Buffer mode support has been "
-                         "enabled\n",dev->name);
-
+       switch(sp->rxd_mode) {
+               case RXD_MODE_1:
+                   DBG_PRINT(ERR_DBG, "%s: 1-Buffer receive mode enabled\n",
+                                               dev->name);
+                   break;
+               case RXD_MODE_3B:
+                   DBG_PRINT(ERR_DBG, "%s: 2-Buffer receive mode enabled\n",
+                                               dev->name);
+                   break;
+               case RXD_MODE_3A:
+                   DBG_PRINT(ERR_DBG, "%s: 3-Buffer receive mode enabled\n",
+                                               dev->name);
+                   break;
+       }
+#ifdef CONFIG_S2IO_NAPI
+       DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
+#endif
+       switch(sp->intr_type) {
+               case INTA:
+                   DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
+                   break;
+               case MSI:
+                   DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI\n", dev->name);
+                   break;
+               case MSI_X:
+                   DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
+                   break;
+       }
        if (sp->lro)
                DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
-                       dev->name);
+                         dev->name);
 
        /* Initialize device name */
-       strcpy(sp->name, dev->name);
-       if (sp->device_type & XFRAME_II_DEVICE)
-               strcat(sp->name, ": Neterion Xframe II 10GbE adapter");
-       else
-               strcat(sp->name, ": Neterion Xframe I 10GbE adapter");
+       sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name);
 
        /* Initialize bimodal Interrupts */
        sp->config.bimodal = bimodal;
index 0a0b5b29d81ead016ac0828966ad2fd6f05a1ca2..3203732a668d81357353dd0e1c19511dadeef02c 100644 (file)
@@ -31,6 +31,8 @@
 #define SUCCESS 0
 #define FAILURE -1
 
+#define CHECKBIT(value, nbit) (value & (1 << nbit))
+
 /* Maximum time to flicker LED when asked to identify NIC using ethtool */
 #define MAX_FLICKER_TIME       60000 /* 60 Secs */
 
@@ -78,6 +80,11 @@ static int debug_level = ERR_DBG;
 typedef struct {
        unsigned long long single_ecc_errs;
        unsigned long long double_ecc_errs;
+       unsigned long long parity_err_cnt;
+       unsigned long long serious_err_cnt;
+       unsigned long long soft_reset_cnt;
+       unsigned long long fifo_full_cnt;
+       unsigned long long ring_full_cnt;
        /* LRO statistics */
        unsigned long long clubbed_frms_cnt;
        unsigned long long sending_both;
@@ -87,6 +94,25 @@ typedef struct {
        unsigned long long num_aggregations;
 } swStat_t;
 
+/* Xpak releated alarm and warnings */
+typedef struct {
+       u64 alarm_transceiver_temp_high;
+       u64 alarm_transceiver_temp_low;
+       u64 alarm_laser_bias_current_high;
+       u64 alarm_laser_bias_current_low;
+       u64 alarm_laser_output_power_high;
+       u64 alarm_laser_output_power_low;
+       u64 warn_transceiver_temp_high;
+       u64 warn_transceiver_temp_low;
+       u64 warn_laser_bias_current_high;
+       u64 warn_laser_bias_current_low;
+       u64 warn_laser_output_power_high;
+       u64 warn_laser_output_power_low;
+       u64 xpak_regs_stat;
+       u32 xpak_timer_count;
+} xpakStat_t;
+
+
 /* The statistics block of Xena */
 typedef struct stat_block {
 /* Tx MAC statistics counters. */
@@ -263,7 +289,9 @@ typedef struct stat_block {
        u32 rmac_accepted_ip_oflow;
        u32 reserved_14;
        u32 link_fault_cnt;
+       u8  buffer[20];
        swStat_t sw_stat;
+       xpakStat_t xpak_stat;
 } StatInfo_t;
 
 /*
@@ -659,7 +687,8 @@ typedef struct {
 } usr_addr_t;
 
 /* Default Tunable parameters of the NIC. */
-#define DEFAULT_FIFO_LEN 4096
+#define DEFAULT_FIFO_0_LEN 4096
+#define DEFAULT_FIFO_1_7_LEN 512
 #define SMALL_BLK_CNT  30
 #define LARGE_BLK_CNT  100
 
@@ -732,7 +761,7 @@ struct s2io_nic {
        int device_close_flag;
        int device_enabled_once;
 
-       char name[50];
+       char name[60];
        struct tasklet_struct task;
        volatile unsigned long tasklet_status;
 
@@ -803,6 +832,8 @@ struct s2io_nic {
        char desc1[35];
        char desc2[35];
 
+       int avail_msix_vectors; /* No. of MSI-X vectors granted by system */
+
        struct msix_info_st msix_info[0x3f];
 
 #define XFRAME_I_DEVICE                1
@@ -824,6 +855,8 @@ struct s2io_nic {
        spinlock_t      rx_lock;
        atomic_t        isr_cnt;
        u64 *ufo_in_band_v;
+#define VPD_PRODUCT_NAME_LEN 50
+       u8  product_name[VPD_PRODUCT_NAME_LEN];
 };
 
 #define RESET_ERROR 1;
@@ -848,28 +881,32 @@ static inline void writeq(u64 val, void __iomem *addr)
        writel((u32) (val), addr);
        writel((u32) (val >> 32), (addr + 4));
 }
+#endif
 
-/* In 32 bit modes, some registers have to be written in a
- * particular order to expect correct hardware operation. The
- * macro SPECIAL_REG_WRITE is used to perform such ordered
- * writes. Defines UF (Upper First) and LF (Lower First) will
- * be used to specify the required write order.
+/* 
+ * Some registers have to be written in a particular order to 
+ * expect correct hardware operation. The macro SPECIAL_REG_WRITE 
+ * is used to perform such ordered writes. Defines UF (Upper First) 
+ * and LF (Lower First) will be used to specify the required write order.
  */
 #define UF     1
 #define LF     2
 static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order)
 {
+       u32 ret;
+
        if (order == LF) {
                writel((u32) (val), addr);
+               ret = readl(addr);
                writel((u32) (val >> 32), (addr + 4));
+               ret = readl(addr + 4);
        } else {
                writel((u32) (val >> 32), (addr + 4));
+               ret = readl(addr + 4);
                writel((u32) (val), addr);
+               ret = readl(addr);
        }
 }
-#else
-#define SPECIAL_REG_WRITE(val, addr, dummy) writeq(val, addr)
-#endif
 
 /*  Interrupt related values of Xena */
 
@@ -965,7 +1002,7 @@ static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
 static struct ethtool_ops netdev_ethtool_ops;
 static void s2io_set_link(unsigned long data);
 static int s2io_set_swapper(nic_t * sp);
-static void s2io_card_down(nic_t *nic);
+static void s2io_card_down(nic_t *nic, int flag);
 static int s2io_card_up(nic_t *nic);
 static int get_xena_rev_id(struct pci_dev *pdev);
 static void restore_xmsi_data(nic_t *nic);
index f5a3bf4d959a458f1fd1930be72d29c6f186a0d9..d058741722091c3555f1b3cf0f399c0a67b83a6e 100644 (file)
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:   1.08.09 Sep. 19 2005
+   Revision:   1.08.10 Apr. 2 2006
    
    Modified from the driver which is originally written by Donald Becker.
    
    SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
    preliminary Rev. 1.0 Jan. 18, 1998
 
+   Rev 1.08.10 Apr.  2 2006 Daniele Venzano add vlan (jumbo packets) support
    Rev 1.08.09 Sep. 19 2005 Daniele Venzano add Wake on LAN support
    Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages
-   Rev 1.08.07 Nov.  2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support
+   Rev 1.08.07 Nov.  2 2003 Daniele Venzano <venza@brownhat.org> add suspend/resume support
    Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
    Rev 1.08.05 Jun.  6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary
    Rev 1.08.04 Apr. 25 2002 Mufasa Yang <mufasa@sis.com.tw> added SiS962 support
@@ -77,7 +78,7 @@
 #include "sis900.h"
 
 #define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.09 Sep. 19 2005"
+#define SIS900_DRV_VERSION "v1.08.10 Apr. 2 2006"
 
 static char version[] __devinitdata =
 KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -1402,6 +1403,11 @@ static void sis900_set_mode (long ioaddr, int speed, int duplex)
                rx_flags |= RxATX;
        }
 
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+       /* Can accept Jumbo packet */
+       rx_flags |= RxAJAB;
+#endif
+
        outl (tx_flags, ioaddr + txcfg);
        outl (rx_flags, ioaddr + rxcfg);
 }
@@ -1714,18 +1720,26 @@ static int sis900_rx(struct net_device *net_dev)
 
        while (rx_status & OWN) {
                unsigned int rx_size;
+               unsigned int data_size;
 
                if (--rx_work_limit < 0)
                        break;
 
-               rx_size = (rx_status & DSIZE) - CRC_SIZE;
+               data_size = rx_status & DSIZE;
+               rx_size = data_size - CRC_SIZE;
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+               /* ``TOOLONG'' flag means jumbo packet recived. */
+               if ((rx_status & TOOLONG) && data_size <= MAX_FRAME_SIZE)
+                       rx_status &= (~ ((unsigned int)TOOLONG));
+#endif
 
                if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
                        /* corrupted packet received */
                        if (netif_msg_rx_err(sis_priv))
                                printk(KERN_DEBUG "%s: Corrupted packet "
-                                      "received, buffer status = 0x%8.8x.\n",
-                                      net_dev->name, rx_status);
+                                      "received, buffer status = 0x%8.8x/%d.\n",
+                                      net_dev->name, rx_status, data_size);
                        sis_priv->stats.rx_errors++;
                        if (rx_status & OVERRUN)
                                sis_priv->stats.rx_over_errors++;
index 50323941e3c0dea55d8c7357a63bc35631cae6db..4834e3a156948bc001c68ddf01735351edb6330c 100644 (file)
@@ -310,8 +310,14 @@ enum sis630_revision_id {
 #define CRC_SIZE                4
 #define MAC_HEADER_SIZE         14
 
-#define TX_BUF_SIZE     1536
-#define RX_BUF_SIZE     1536
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define MAX_FRAME_SIZE  (1518 + 4)
+#else
+#define MAX_FRAME_SIZE  1518
+#endif /* CONFIG_VLAN_802_1Q */
+
+#define TX_BUF_SIZE     (MAX_FRAME_SIZE+18)
+#define RX_BUF_SIZE     (MAX_FRAME_SIZE+18)
 
 #define NUM_TX_DESC     16             /* Number of Tx descriptor registers. */
 #define NUM_RX_DESC     16             /* Number of Rx descriptor registers. */
index 5ca5a1b546a162ed23eaf2e422fd9db21eee2537..536dd1cf7f79281e9b9d2516d4ff58ff7eeea933 100644 (file)
 #include "skge.h"
 
 #define DRV_NAME               "skge"
-#define DRV_VERSION            "1.5"
+#define DRV_VERSION            "1.6"
 #define PFX                    DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE   128
 #define DEFAULT_RX_RING_SIZE   512
 #define MAX_TX_RING_SIZE       1024
+#define TX_LOW_WATER           (MAX_SKB_FRAGS + 1)
 #define MAX_RX_RING_SIZE       4096
 #define RX_COPY_THRESHOLD      128
 #define RX_BUF_SIZE            1536
@@ -401,7 +402,7 @@ static int skge_set_ring_param(struct net_device *dev,
        int err;
 
        if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE ||
-           p->tx_pending < MAX_SKB_FRAGS+1 || p->tx_pending > MAX_TX_RING_SIZE)
+           p->tx_pending < TX_LOW_WATER || p->tx_pending > MAX_TX_RING_SIZE)
                return -EINVAL;
 
        skge->rx_ring.count = p->rx_pending;
@@ -603,7 +604,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
 
-       spin_lock_bh(&hw->phy_lock);
+       mutex_lock(&hw->phy_mutex);
        if (hw->chip_id == CHIP_ID_GENESIS) {
                switch (mode) {
                case LED_MODE_OFF:
@@ -663,7 +664,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
                                     PHY_M_LED_MO_RX(MO_LED_ON));
                }
        }
-       spin_unlock_bh(&hw->phy_lock);
+       mutex_unlock(&hw->phy_mutex);
 }
 
 /* blink LED's for finding board */
@@ -2038,7 +2039,7 @@ static void skge_phy_reset(struct skge_port *skge)
        netif_stop_queue(skge->netdev);
        netif_carrier_off(skge->netdev);
 
-       spin_lock_bh(&hw->phy_lock);
+       mutex_lock(&hw->phy_mutex);
        if (hw->chip_id == CHIP_ID_GENESIS) {
                genesis_reset(hw, port);
                genesis_mac_init(hw, port);
@@ -2046,7 +2047,7 @@ static void skge_phy_reset(struct skge_port *skge)
                yukon_reset(hw, port);
                yukon_init(hw, port);
        }
-       spin_unlock_bh(&hw->phy_lock);
+       mutex_unlock(&hw->phy_mutex);
 }
 
 /* Basic MII support */
@@ -2067,12 +2068,12 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                /* fallthru */
        case SIOCGMIIREG: {
                u16 val = 0;
-               spin_lock_bh(&hw->phy_lock);
+               mutex_lock(&hw->phy_mutex);
                if (hw->chip_id == CHIP_ID_GENESIS)
                        err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
                else
                        err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
-               spin_unlock_bh(&hw->phy_lock);
+               mutex_unlock(&hw->phy_mutex);
                data->val_out = val;
                break;
        }
@@ -2081,14 +2082,14 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
-               spin_lock_bh(&hw->phy_lock);
+               mutex_lock(&hw->phy_mutex);
                if (hw->chip_id == CHIP_ID_GENESIS)
                        err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f,
                                   data->val_in);
                else
                        err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f,
                                   data->val_in);
-               spin_unlock_bh(&hw->phy_lock);
+               mutex_unlock(&hw->phy_mutex);
                break;
        }
        return err;
@@ -2191,12 +2192,12 @@ static int skge_up(struct net_device *dev)
                goto free_rx_ring;
 
        /* Initialize MAC */
-       spin_lock_bh(&hw->phy_lock);
+       mutex_lock(&hw->phy_mutex);
        if (hw->chip_id == CHIP_ID_GENESIS)
                genesis_mac_init(hw, port);
        else
                yukon_mac_init(hw, port);
-       spin_unlock_bh(&hw->phy_lock);
+       mutex_unlock(&hw->phy_mutex);
 
        /* Configure RAMbuffers */
        chunk = hw->ram_size / ((hw->ports + 1)*2);
@@ -2302,21 +2303,20 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
 {
        struct skge_port *skge = netdev_priv(dev);
        struct skge_hw *hw = skge->hw;
-       struct skge_ring *ring = &skge->tx_ring;
        struct skge_element *e;
        struct skge_tx_desc *td;
        int i;
        u32 control, len;
        u64 map;
+       unsigned long flags;
 
        skb = skb_padto(skb, ETH_ZLEN);
        if (!skb)
                return NETDEV_TX_OK;
 
-       if (!spin_trylock(&skge->tx_lock)) {
+       if (!spin_trylock_irqsave(&skge->tx_lock, flags))
                /* Collision - tell upper layer to requeue */
                return NETDEV_TX_LOCKED;
-       }
 
        if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) {
                if (!netif_queue_stopped(dev)) {
@@ -2325,12 +2325,13 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
                        printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
                               dev->name);
                }
-               spin_unlock(&skge->tx_lock);
+               spin_unlock_irqrestore(&skge->tx_lock, flags);
                return NETDEV_TX_BUSY;
        }
 
-       e = ring->to_use;
+       e = skge->tx_ring.to_use;
        td = e->desc;
+       BUG_ON(td->control & BMU_OWN);
        e->skb = skb;
        len = skb_headlen(skb);
        map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
@@ -2371,8 +2372,10 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
                                           frag->size, PCI_DMA_TODEVICE);
 
                        e = e->next;
-                       e->skb = NULL;
+                       e->skb = skb;
                        tf = e->desc;
+                       BUG_ON(tf->control & BMU_OWN);
+
                        tf->dma_lo = map;
                        tf->dma_hi = (u64) map >> 32;
                        pci_unmap_addr_set(e, mapaddr, map);
@@ -2389,56 +2392,68 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
 
        skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START);
 
-       if (netif_msg_tx_queued(skge))
+       if (unlikely(netif_msg_tx_queued(skge)))
                printk(KERN_DEBUG "%s: tx queued, slot %td, len %d\n",
-                      dev->name, e - ring->start, skb->len);
+                      dev->name, e - skge->tx_ring.start, skb->len);
 
-       ring->to_use = e->next;
-       if (skge_avail(&skge->tx_ring) <= MAX_SKB_FRAGS + 1) {
+       skge->tx_ring.to_use = e->next;
+       if (skge_avail(&skge->tx_ring) <= TX_LOW_WATER) {
                pr_debug("%s: transmit queue full\n", dev->name);
                netif_stop_queue(dev);
        }
 
-       mmiowb();
-       spin_unlock(&skge->tx_lock);
+       spin_unlock_irqrestore(&skge->tx_lock, flags);
 
        dev->trans_start = jiffies;
 
        return NETDEV_TX_OK;
 }
 
-static void skge_tx_complete(struct skge_port *skge, struct skge_element *last)
+
+/* Free resources associated with this reing element */
+static void skge_tx_free(struct skge_port *skge, struct skge_element *e,
+                        u32 control)
 {
        struct pci_dev *pdev = skge->hw->pdev;
-       struct skge_element *e;
 
-       for (e = skge->tx_ring.to_clean; e != last; e = e->next) {
-               struct sk_buff *skb = e->skb;
-               int i;
+       BUG_ON(!e->skb);
 
-               e->skb = NULL;
+       /* skb header vs. fragment */
+       if (control & BMU_STF)
                pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr),
-                                skb_headlen(skb), PCI_DMA_TODEVICE);
+                                pci_unmap_len(e, maplen),
+                                PCI_DMA_TODEVICE);
+       else
+               pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr),
+                              pci_unmap_len(e, maplen),
+                              PCI_DMA_TODEVICE);
 
-               for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-                       e = e->next;
-                       pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr),
-                                      skb_shinfo(skb)->frags[i].size,
-                                      PCI_DMA_TODEVICE);
-               }
+       if (control & BMU_EOF) {
+               if (unlikely(netif_msg_tx_done(skge)))
+                       printk(KERN_DEBUG PFX "%s: tx done slot %td\n",
+                              skge->netdev->name, e - skge->tx_ring.start);
 
-               dev_kfree_skb(skb);
+               dev_kfree_skb_any(e->skb);
        }
-       skge->tx_ring.to_clean = e;
+       e->skb = NULL;
 }
 
+/* Free all buffers in transmit ring */
 static void skge_tx_clean(struct skge_port *skge)
 {
+       struct skge_element *e;
+       unsigned long flags;
+
+       spin_lock_irqsave(&skge->tx_lock, flags);
+       for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
+               struct skge_tx_desc *td = e->desc;
+               skge_tx_free(skge, e, td->control);
+               td->control = 0;
+       }
 
-       spin_lock_bh(&skge->tx_lock);
-       skge_tx_complete(skge, skge->tx_ring.to_use);
+       skge->tx_ring.to_clean = e;
        netif_wake_queue(skge->netdev);
-       spin_unlock_bh(&skge->tx_lock);
+       spin_unlock_irqrestore(&skge->tx_lock, flags);
 }
 
 static void skge_tx_timeout(struct net_device *dev)
@@ -2664,32 +2679,28 @@ resubmit:
        return NULL;
 }
 
-static void skge_tx_done(struct skge_port *skge)
+/* Free all buffers in Tx ring which are no longer owned by device */
+static void skge_txirq(struct net_device *dev)
 {
+       struct skge_port *skge = netdev_priv(dev);
        struct skge_ring *ring = &skge->tx_ring;
-       struct skge_element *e, *last;
+       struct skge_element *e;
+
+       rmb();
 
        spin_lock(&skge->tx_lock);
-       last = ring->to_clean;
        for (e = ring->to_clean; e != ring->to_use; e = e->next) {
                struct skge_tx_desc *td = e->desc;
 
                if (td->control & BMU_OWN)
                        break;
 
-               if (td->control & BMU_EOF) {
-                       last = e->next;
-                       if (unlikely(netif_msg_tx_done(skge)))
-                               printk(KERN_DEBUG PFX "%s: tx done slot %td\n",
-                                      skge->netdev->name, e - ring->start);
-               }
+               skge_tx_free(skge, e, td->control);
        }
+       skge->tx_ring.to_clean = e;
 
-       skge_tx_complete(skge, last);
-
-       skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
-
-       if (skge_avail(&skge->tx_ring) > MAX_SKB_FRAGS + 1)
+       if (netif_queue_stopped(skge->netdev)
+           && skge_avail(&skge->tx_ring) > TX_LOW_WATER)
                netif_wake_queue(skge->netdev);
 
        spin_unlock(&skge->tx_lock);
@@ -2704,8 +2715,6 @@ static int skge_poll(struct net_device *dev, int *budget)
        int to_do = min(dev->quota, *budget);
        int work_done = 0;
 
-       skge_tx_done(skge);
-
        for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) {
                struct skge_rx_desc *rd = e->desc;
                struct sk_buff *skb;
@@ -2737,10 +2746,12 @@ static int skge_poll(struct net_device *dev, int *budget)
                return 1; /* not done */
 
        netif_rx_complete(dev);
-       mmiowb();
 
-       hw->intr_mask |= skge->port == 0 ? (IS_R1_F|IS_XA1_F) : (IS_R2_F|IS_XA2_F);
+       spin_lock_irq(&hw->hw_lock);
+       hw->intr_mask |= rxirqmask[skge->port];
        skge_write32(hw, B0_IMSK, hw->intr_mask);
+       mmiowb();
+       spin_unlock_irq(&hw->hw_lock);
 
        return 0;
 }
@@ -2847,16 +2858,16 @@ static void skge_error_irq(struct skge_hw *hw)
 }
 
 /*
- * Interrupt from PHY are handled in tasklet (soft irq)
+ * Interrupt from PHY are handled in work queue
  * because accessing phy registers requires spin wait which might
  * cause excess interrupt latency.
  */
-static void skge_extirq(unsigned long data)
+static void skge_extirq(void *arg)
 {
-       struct skge_hw *hw = (struct skge_hw *) data;
+       struct skge_hw *hw = arg;
        int port;
 
-       spin_lock(&hw->phy_lock);
+       mutex_lock(&hw->phy_mutex);
        for (port = 0; port < hw->ports; port++) {
                struct net_device *dev = hw->dev[port];
                struct skge_port *skge = netdev_priv(dev);
@@ -2868,10 +2879,12 @@ static void skge_extirq(unsigned long data)
                                bcom_phy_intr(skge);
                }
        }
-       spin_unlock(&hw->phy_lock);
+       mutex_unlock(&hw->phy_mutex);
 
+       spin_lock_irq(&hw->hw_lock);
        hw->intr_mask |= IS_EXT_REG;
        skge_write32(hw, B0_IMSK, hw->intr_mask);
+       spin_unlock_irq(&hw->hw_lock);
 }
 
 static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
@@ -2884,54 +2897,68 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
        if (status == 0)
                return IRQ_NONE;
 
+       spin_lock(&hw->hw_lock);
+       status &= hw->intr_mask;
        if (status & IS_EXT_REG) {
                hw->intr_mask &= ~IS_EXT_REG;
-               tasklet_schedule(&hw->ext_tasklet);
+               schedule_work(&hw->phy_work);
        }
 
-       if (status & (IS_R1_F|IS_XA1_F)) {
-               skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F);
-               hw->intr_mask &= ~(IS_R1_F|IS_XA1_F);
-               netif_rx_schedule(hw->dev[0]);
+       if (status & IS_XA1_F) {
+               skge_write8(hw, Q_ADDR(Q_XA1, Q_CSR), CSR_IRQ_CL_F);
+               skge_txirq(hw->dev[0]);
        }
 
-       if (status & (IS_R2_F|IS_XA2_F)) {
-               skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F);
-               hw->intr_mask &= ~(IS_R2_F|IS_XA2_F);
-               netif_rx_schedule(hw->dev[1]);
+       if (status & IS_R1_F) {
+               skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F);
+               hw->intr_mask &= ~IS_R1_F;
+               netif_rx_schedule(hw->dev[0]);
        }
 
-       if (likely((status & hw->intr_mask) == 0))
-               return IRQ_HANDLED;
+       if (status & IS_PA_TO_TX1)
+               skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1);
 
        if (status & IS_PA_TO_RX1) {
                struct skge_port *skge = netdev_priv(hw->dev[0]);
-               ++skge->net_stats.rx_over_errors;
-               skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1);
-       }
 
-       if (status & IS_PA_TO_RX2) {
-               struct skge_port *skge = netdev_priv(hw->dev[1]);
                ++skge->net_stats.rx_over_errors;
-               skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2);
+               skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1);
        }
 
-       if (status & IS_PA_TO_TX1)
-               skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1);
-
-       if (status & IS_PA_TO_TX2)
-               skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2);
 
        if (status & IS_MAC1)
                skge_mac_intr(hw, 0);
 
-       if (status & IS_MAC2)
-               skge_mac_intr(hw, 1);
+       if (hw->dev[1]) {
+               if (status & IS_XA2_F) {
+                       skge_write8(hw, Q_ADDR(Q_XA2, Q_CSR), CSR_IRQ_CL_F);
+                       skge_txirq(hw->dev[1]);
+               }
+
+               if (status & IS_R2_F) {
+                       skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F);
+                       hw->intr_mask &= ~IS_R2_F;
+                       netif_rx_schedule(hw->dev[1]);
+               }
+
+               if (status & IS_PA_TO_RX2) {
+                       struct skge_port *skge = netdev_priv(hw->dev[1]);
+                       ++skge->net_stats.rx_over_errors;
+                       skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2);
+               }
+
+               if (status & IS_PA_TO_TX2)
+                       skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2);
+
+               if (status & IS_MAC2)
+                       skge_mac_intr(hw, 1);
+       }
 
        if (status & IS_HW_ERR)
                skge_error_irq(hw);
 
        skge_write32(hw, B0_IMSK, hw->intr_mask);
+       spin_unlock(&hw->hw_lock);
 
        return IRQ_HANDLED;
 }
@@ -2957,7 +2984,7 @@ static int skge_set_mac_address(struct net_device *dev, void *p)
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
-       spin_lock_bh(&hw->phy_lock);
+       mutex_lock(&hw->phy_mutex);
        memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
        memcpy_toio(hw->regs + B2_MAC_1 + port*8,
                    dev->dev_addr, ETH_ALEN);
@@ -2970,7 +2997,7 @@ static int skge_set_mac_address(struct net_device *dev, void *p)
                gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
                gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
        }
-       spin_unlock_bh(&hw->phy_lock);
+       mutex_unlock(&hw->phy_mutex);
 
        return 0;
 }
@@ -3082,6 +3109,7 @@ static int skge_reset(struct skge_hw *hw)
        else
                hw->ram_size = t8 * 4096;
 
+       spin_lock_init(&hw->hw_lock);
        hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
        if (hw->ports > 1)
                hw->intr_mask |= IS_PORT_2;
@@ -3150,14 +3178,14 @@ static int skge_reset(struct skge_hw *hw)
 
        skge_write32(hw, B0_IMSK, hw->intr_mask);
 
-       spin_lock_bh(&hw->phy_lock);
+       mutex_lock(&hw->phy_mutex);
        for (i = 0; i < hw->ports; i++) {
                if (hw->chip_id == CHIP_ID_GENESIS)
                        genesis_reset(hw, i);
                else
                        yukon_reset(hw, i);
        }
-       spin_unlock_bh(&hw->phy_lock);
+       mutex_unlock(&hw->phy_mutex);
 
        return 0;
 }
@@ -3305,8 +3333,8 @@ static int __devinit skge_probe(struct pci_dev *pdev,
        }
 
        hw->pdev = pdev;
-       spin_lock_init(&hw->phy_lock);
-       tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw);
+       mutex_init(&hw->phy_mutex);
+       INIT_WORK(&hw->phy_work, skge_extirq, hw);
 
        hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
        if (!hw->regs) {
@@ -3334,6 +3362,14 @@ static int __devinit skge_probe(struct pci_dev *pdev,
        if ((dev = skge_devinit(hw, 0, using_dac)) == NULL)
                goto err_out_led_off;
 
+       if (!is_valid_ether_addr(dev->dev_addr)) {
+               printk(KERN_ERR PFX "%s: bad (zero?) ethernet address in rom\n",
+                      pci_name(pdev));
+               err = -EIO;
+               goto err_out_free_netdev;
+       }
+
+
        err = register_netdev(dev);
        if (err) {
                printk(KERN_ERR PFX "%s: cannot register net device\n",
@@ -3388,11 +3424,15 @@ static void __devexit skge_remove(struct pci_dev *pdev)
        dev0 = hw->dev[0];
        unregister_netdev(dev0);
 
+       spin_lock_irq(&hw->hw_lock);
+       hw->intr_mask = 0;
        skge_write32(hw, B0_IMSK, 0);
+       spin_unlock_irq(&hw->hw_lock);
+
        skge_write16(hw, B0_LED, LED_STAT_OFF);
        skge_write8(hw, B0_CTST, CS_RST_SET);
 
-       tasklet_kill(&hw->ext_tasklet);
+       flush_scheduled_work();
 
        free_irq(pdev->irq, hw);
        pci_release_regions(pdev);
index 1f1ce88c81863ed10a7964a94936980efed56b95..ed19ff47ce1108dc0f6a3ac89935391f7c7fa961 100644 (file)
@@ -2388,6 +2388,7 @@ struct skge_ring {
 struct skge_hw {
        void __iomem         *regs;
        struct pci_dev       *pdev;
+       spinlock_t           hw_lock;
        u32                  intr_mask;
        struct net_device    *dev[2];
 
@@ -2399,9 +2400,8 @@ struct skge_hw {
        u32                  ram_size;
        u32                  ram_offset;
        u16                  phy_addr;
-
-       struct tasklet_struct ext_tasklet;
-       spinlock_t           phy_lock;
+       struct work_struct   phy_work;
+       struct mutex         phy_mutex;
 };
 
 enum {
index 959109609d852bb47c2c0fd5f3ed04c693486c88..fba1e4d4d83d053becf3da50e48577f7740f0c79 100644 (file)
@@ -187,12 +187,11 @@ static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
        return v;
 }
 
-static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
+static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
 {
        u16 power_control;
        u32 reg1;
        int vaux;
-       int ret = 0;
 
        pr_debug("sky2_set_power_state %d\n", state);
        sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
@@ -275,12 +274,10 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
                break;
        default:
                printk(KERN_ERR PFX "Unknown power state %d\n", state);
-               ret = -1;
        }
 
        sky2_pci_write16(hw, hw->pm_cap + PCI_PM_CTRL, power_control);
        sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-       return ret;
 }
 
 static void sky2_phy_reset(struct sky2_hw *hw, unsigned port)
@@ -2164,6 +2161,13 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port,
 /* If idle then force a fake soft NAPI poll once a second
  * to work around cases where sharing an edge triggered interrupt.
  */
+static inline void sky2_idle_start(struct sky2_hw *hw)
+{
+       if (idle_timeout > 0)
+               mod_timer(&hw->idle_timer,
+                         jiffies + msecs_to_jiffies(idle_timeout));
+}
+
 static void sky2_idle(unsigned long arg)
 {
        struct sky2_hw *hw = (struct sky2_hw *) arg;
@@ -2183,6 +2187,9 @@ static int sky2_poll(struct net_device *dev0, int *budget)
        int work_done = 0;
        u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
 
+       if (!~status)
+               goto out;
+
        if (status & Y2_IS_HW_ERR)
                sky2_hw_intr(hw);
 
@@ -2219,7 +2226,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
 
        if (sky2_more_work(hw))
                return 1;
-
+out:
        netif_rx_complete(dev0);
 
        sky2_read32(hw, B0_Y2_SP_LISR);
@@ -2248,8 +2255,10 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
 static void sky2_netpoll(struct net_device *dev)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
+       struct net_device *dev0 = sky2->hw->dev[0];
 
-       sky2_intr(sky2->hw->pdev->irq, sky2->hw, NULL);
+       if (netif_running(dev) && __netif_rx_schedule_prep(dev0))
+               __netif_rx_schedule(dev0);
 }
 #endif
 
@@ -3350,9 +3359,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
 
        setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw);
-       if (idle_timeout > 0)
-               mod_timer(&hw->idle_timer,
-                         jiffies + msecs_to_jiffies(idle_timeout));
+       sky2_idle_start(hw);
 
        pci_set_drvdata(pdev, hw);
 
@@ -3425,8 +3432,14 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct sky2_hw *hw = pci_get_drvdata(pdev);
        int i;
+       pci_power_t pstate = pci_choose_state(pdev, state);
+
+       if (!(pstate == PCI_D3hot || pstate == PCI_D3cold))
+               return -EINVAL;
+
+       del_timer_sync(&hw->idle_timer);
 
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
 
                if (dev) {
@@ -3435,10 +3448,14 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
 
                        sky2_down(dev);
                        netif_device_detach(dev);
+                       netif_poll_disable(dev);
                }
        }
 
-       return sky2_set_power_state(hw, pci_choose_state(pdev, state));
+       sky2_write32(hw, B0_IMSK, 0);
+       pci_save_state(pdev);
+       sky2_set_power_state(hw, pstate);
+       return 0;
 }
 
 static int sky2_resume(struct pci_dev *pdev)
@@ -3448,27 +3465,31 @@ static int sky2_resume(struct pci_dev *pdev)
 
        pci_restore_state(pdev);
        pci_enable_wake(pdev, PCI_D0, 0);
-       err = sky2_set_power_state(hw, PCI_D0);
-       if (err)
-               goto out;
+       sky2_set_power_state(hw, PCI_D0);
 
        err = sky2_reset(hw);
        if (err)
                goto out;
 
-       for (i = 0; i < 2; i++) {
+       sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+
+       for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
                if (dev && netif_running(dev)) {
                        netif_device_attach(dev);
+                       netif_poll_enable(dev);
+
                        err = sky2_up(dev);
                        if (err) {
                                printk(KERN_ERR PFX "%s: could not up: %d\n",
                                       dev->name, err);
                                dev_close(dev);
-                               break;
+                               goto out;
                        }
                }
        }
+
+       sky2_idle_start(hw);
 out:
        return err;
 }
index 3db30cd0625e5fd7151f18af72b414bebe47e054..5b4e8529d4ab756f19d46de14cb755a23801a03a 100644 (file)
@@ -553,7 +553,7 @@ MODULE_LICENSE("GPL");
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
+int __init
 init_module(void)
 {
        struct net_device *dev;
index b3e397d7ca8583ee479af720d05360deaa31f600..ff9bd97746dcb67d0a4dafeb30a782d2b025cfac 100644 (file)
@@ -421,7 +421,7 @@ static struct net_device *dev_ultra[MAX_ULTRA32_CARDS];
 MODULE_DESCRIPTION("SMC Ultra32 EISA ethernet driver");
 MODULE_LICENSE("GPL");
 
-int init_module(void)
+int __init init_module(void)
 {
        int this_dev, found = 0;
 
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
new file mode 100644 (file)
index 0000000..bdd8702
--- /dev/null
@@ -0,0 +1,2307 @@
+/*
+ * smc911x.c
+ * This is a driver for SMSC's LAN911{5,6,7,8} single-chip Ethernet devices.
+ *
+ * Copyright (C) 2005 Sensoria Corp
+ *        Derived from the unified SMC91x driver by Nicolas Pitre
+ *        and the smsc911x.c reference driver by SMSC
+ *
+ * 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
+ *
+ * Arguments:
+ *      watchdog  = TX watchdog timeout
+ *      tx_fifo_kb = Size of TX FIFO in KB
+ *
+ * History:
+ *       04/16/05      Dustin McIntire          Initial version
+ */
+static const char version[] =
+        "smc911x.c: v1.0 04-16-2005 by Dustin McIntire <dustin@sensoria.com>\n";
+
+/* Debugging options */
+#define ENABLE_SMC_DEBUG_RX            0
+#define ENABLE_SMC_DEBUG_TX            0
+#define ENABLE_SMC_DEBUG_DMA           0
+#define ENABLE_SMC_DEBUG_PKTS          0
+#define ENABLE_SMC_DEBUG_MISC          0
+#define ENABLE_SMC_DEBUG_FUNC          0
+
+#define SMC_DEBUG_RX           ((ENABLE_SMC_DEBUG_RX   ? 1 : 0) << 0)
+#define SMC_DEBUG_TX           ((ENABLE_SMC_DEBUG_TX   ? 1 : 0) << 1)
+#define SMC_DEBUG_DMA          ((ENABLE_SMC_DEBUG_DMA  ? 1 : 0) << 2)
+#define SMC_DEBUG_PKTS         ((ENABLE_SMC_DEBUG_PKTS ? 1 : 0) << 3)
+#define SMC_DEBUG_MISC         ((ENABLE_SMC_DEBUG_MISC ? 1 : 0) << 4)
+#define SMC_DEBUG_FUNC         ((ENABLE_SMC_DEBUG_FUNC ? 1 : 0) << 5)
+
+#ifndef SMC_DEBUG
+#define SMC_DEBUG       ( SMC_DEBUG_RX   | \
+                          SMC_DEBUG_TX   | \
+                          SMC_DEBUG_DMA  | \
+                          SMC_DEBUG_PKTS | \
+                          SMC_DEBUG_MISC | \
+                          SMC_DEBUG_FUNC   \
+                        )
+#endif
+
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/crc32.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/workqueue.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "smc911x.h"
+
+/*
+ * Transmit timeout, default 5 seconds.
+ */
+static int watchdog = 5000;
+module_param(watchdog, int, 0400);
+MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+
+static int tx_fifo_kb=8;
+module_param(tx_fifo_kb, int, 0400);
+MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1<x<15)(default=8)");
+
+MODULE_LICENSE("GPL");
+
+/*
+ * The internal workings of the driver.  If you are changing anything
+ * here with the SMC stuff, you should have the datasheet and know
+ * what you are doing.
+ */
+#define CARDNAME "smc911x"
+
+/*
+ * Use power-down feature of the chip
+ */
+#define POWER_DOWN              1
+
+
+/* store this information for the driver.. */
+struct smc911x_local {
+       /*
+        * If I have to wait until the DMA is finished and ready to reload a
+        * packet, I will store the skbuff here. Then, the DMA will send it
+        * out and free it.
+        */
+       struct sk_buff *pending_tx_skb;
+
+       /*
+        * these are things that the kernel wants me to keep, so users
+        * can find out semi-useless statistics of how well the card is
+        * performing
+        */
+       struct net_device_stats stats;
+
+       /* version/revision of the SMC911x chip */
+       u16 version;
+       u16 revision;
+
+       /* FIFO sizes */
+       int tx_fifo_kb;
+       int tx_fifo_size;
+       int rx_fifo_size;
+       int afc_cfg;
+
+       /* Contains the current active receive/phy mode */
+       int ctl_rfduplx;
+       int ctl_rspeed;
+
+       u32 msg_enable;
+       u32 phy_type;
+       struct mii_if_info mii;
+
+       /* work queue */
+       struct work_struct phy_configure;
+       int work_pending;
+
+       int tx_throttle;
+       spinlock_t lock;
+
+#ifdef SMC_USE_DMA
+       /* DMA needs the physical address of the chip */
+       u_long physaddr;
+       int rxdma;
+       int txdma;
+       int rxdma_active;
+       int txdma_active;
+       struct sk_buff *current_rx_skb;
+       struct sk_buff *current_tx_skb;
+       struct device *dev;
+#endif
+};
+
+#if SMC_DEBUG > 0
+#define DBG(n, args...)                                 \
+       do {                                     \
+               if (SMC_DEBUG & (n))             \
+                       printk(args);            \
+       } while (0)
+
+#define PRINTK(args...)   printk(args)
+#else
+#define DBG(n, args...)   do { } while (0)
+#define PRINTK(args...)   printk(KERN_DEBUG args)
+#endif
+
+#if SMC_DEBUG_PKTS > 0
+static void PRINT_PKT(u_char *buf, int length)
+{
+       int i;
+       int remainder;
+       int lines;
+
+       lines = length / 16;
+       remainder = length % 16;
+
+       for (i = 0; i < lines ; i ++) {
+               int cur;
+               for (cur = 0; cur < 8; cur++) {
+                       u_char a, b;
+                       a = *buf++;
+                       b = *buf++;
+                       printk("%02x%02x ", a, b);
+               }
+               printk("\n");
+       }
+       for (i = 0; i < remainder/2 ; i++) {
+               u_char a, b;
+               a = *buf++;
+               b = *buf++;
+               printk("%02x%02x ", a, b);
+       }
+       printk("\n");
+}
+#else
+#define PRINT_PKT(x...)  do { } while (0)
+#endif
+
+
+/* this enables an interrupt in the interrupt mask register */
+#define SMC_ENABLE_INT(x) do {                         \
+       unsigned int  __mask;                           \
+       unsigned long __flags;                          \
+       spin_lock_irqsave(&lp->lock, __flags);          \
+       __mask = SMC_GET_INT_EN();                      \
+       __mask |= (x);                                  \
+       SMC_SET_INT_EN(__mask);                         \
+       spin_unlock_irqrestore(&lp->lock, __flags);     \
+} while (0)
+
+/* this disables an interrupt from the interrupt mask register */
+#define SMC_DISABLE_INT(x) do {                                \
+       unsigned int  __mask;                           \
+       unsigned long __flags;                          \
+       spin_lock_irqsave(&lp->lock, __flags);          \
+       __mask = SMC_GET_INT_EN();                      \
+       __mask &= ~(x);                                 \
+       SMC_SET_INT_EN(__mask);                         \
+       spin_unlock_irqrestore(&lp->lock, __flags);     \
+} while (0)
+
+/*
+ * this does a soft reset on the device
+ */
+static void smc911x_reset(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned int reg, timeout=0, resets=1;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       /*       Take out of PM setting first */
+       if ((SMC_GET_PMT_CTRL() & PMT_CTRL_READY_) == 0) {
+               /* Write to the bytetest will take out of powerdown */
+               SMC_SET_BYTE_TEST(0);
+               timeout=10;
+               do {
+                       udelay(10);
+                       reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_;
+               } while ( timeout-- && !reg);
+               if (timeout == 0) {
+                       PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name);
+                       return;
+               }
+       }
+
+       /* Disable all interrupts */
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_SET_INT_EN(0);
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       while (resets--) {
+               SMC_SET_HW_CFG(HW_CFG_SRST_);
+               timeout=10;
+               do {
+                       udelay(10);
+                       reg = SMC_GET_HW_CFG();
+                       /* If chip indicates reset timeout then try again */
+                       if (reg & HW_CFG_SRST_TO_) {
+                               PRINTK("%s: chip reset timeout, retrying...\n", dev->name);
+                               resets++;
+                               break;
+                       }
+               } while ( timeout-- && (reg & HW_CFG_SRST_));
+       }
+       if (timeout == 0) {
+               PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name);
+               return;
+       }
+
+       /* make sure EEPROM has finished loading before setting GPIO_CFG */
+       timeout=1000;
+       while ( timeout-- && (SMC_GET_E2P_CMD() & E2P_CMD_EPC_BUSY_)) {
+               udelay(10);
+       }
+       if (timeout == 0){
+               PRINTK("%s: smc911x_reset timeout waiting for EEPROM busy\n", dev->name);
+               return;
+       }
+
+       /* Initialize interrupts */
+       SMC_SET_INT_EN(0);
+       SMC_ACK_INT(-1);
+
+       /* Reset the FIFO level and flow control settings */
+       SMC_SET_HW_CFG((lp->tx_fifo_kb & 0xF) << 16);
+//TODO: Figure out what appropriate pause time is
+       SMC_SET_FLOW(FLOW_FCPT_ | FLOW_FCEN_);
+       SMC_SET_AFC_CFG(lp->afc_cfg);
+
+
+       /* Set to LED outputs */
+       SMC_SET_GPIO_CFG(0x70070000);
+
+       /*
+        * Deassert IRQ for 1*10us for edge type interrupts
+        * and drive IRQ pin push-pull
+        */
+       SMC_SET_IRQ_CFG( (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ );
+
+       /* clear anything saved */
+       if (lp->pending_tx_skb != NULL) {
+               dev_kfree_skb (lp->pending_tx_skb);
+               lp->pending_tx_skb = NULL;
+               lp->stats.tx_errors++;
+               lp->stats.tx_aborted_errors++;
+       }
+}
+
+/*
+ * Enable Interrupts, Receive, and Transmit
+ */
+static void smc911x_enable(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned mask, cfg, cr;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       SMC_SET_MAC_ADDR(dev->dev_addr);
+
+       /* Enable TX */
+       cfg = SMC_GET_HW_CFG();
+       cfg &= HW_CFG_TX_FIF_SZ_ | 0xFFF;
+       cfg |= HW_CFG_SF_;
+       SMC_SET_HW_CFG(cfg);
+       SMC_SET_FIFO_TDA(0xFF);
+       /* Update TX stats on every 64 packets received or every 1 sec */
+       SMC_SET_FIFO_TSL(64);
+       SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
+
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_GET_MAC_CR(cr);
+       cr |= MAC_CR_TXEN_ | MAC_CR_HBDIS_;
+       SMC_SET_MAC_CR(cr);
+       SMC_SET_TX_CFG(TX_CFG_TX_ON_);
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       /* Add 2 byte padding to start of packets */
+       SMC_SET_RX_CFG((2<<8) & RX_CFG_RXDOFF_);
+
+       /* Turn on receiver and enable RX */
+       if (cr & MAC_CR_RXEN_)
+               DBG(SMC_DEBUG_RX, "%s: Receiver already enabled\n", dev->name);
+
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_SET_MAC_CR( cr | MAC_CR_RXEN_ );
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       /* Interrupt on every received packet */
+       SMC_SET_FIFO_RSA(0x01);
+       SMC_SET_FIFO_RSL(0x00);
+
+       /* now, enable interrupts */
+       mask = INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_ | INT_EN_RSFL_EN_ |
+               INT_EN_GPT_INT_EN_ | INT_EN_RXDFH_INT_EN_ | INT_EN_RXE_EN_ |
+               INT_EN_PHY_INT_EN_;
+       if (IS_REV_A(lp->revision))
+               mask|=INT_EN_RDFL_EN_;
+       else {
+               mask|=INT_EN_RDFO_EN_;
+       }
+       SMC_ENABLE_INT(mask);
+}
+
+/*
+ * this puts the device in an inactive state
+ */
+static void smc911x_shutdown(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned cr;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __FUNCTION__);
+
+       /* Disable IRQ's */
+       SMC_SET_INT_EN(0);
+
+       /* Turn of Rx and TX */
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_GET_MAC_CR(cr);
+       cr &= ~(MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_);
+       SMC_SET_MAC_CR(cr);
+       SMC_SET_TX_CFG(TX_CFG_STOP_TX_);
+       spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+static inline void smc911x_drop_pkt(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int fifo_count, timeout, reg;
+
+       DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __FUNCTION__);
+       fifo_count = SMC_GET_RX_FIFO_INF() & 0xFFFF;
+       if (fifo_count <= 4) {
+               /* Manually dump the packet data */
+               while (fifo_count--)
+                       SMC_GET_RX_FIFO();
+       } else   {
+               /* Fast forward through the bad packet */
+               SMC_SET_RX_DP_CTRL(RX_DP_CTRL_FFWD_BUSY_);
+               timeout=50;
+               do {
+                       udelay(10);
+                       reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_;
+               } while ( timeout-- && reg);
+               if (timeout == 0) {
+                       PRINTK("%s: timeout waiting for RX fast forward\n", dev->name);
+               }
+       }
+}
+
+/*
+ * This is the procedure to handle the receipt of a packet.
+ * It should be called after checking for packet presence in
+ * the RX status FIFO.  It must be called with the spin lock
+ * already held.
+ */
+static inline void      smc911x_rcv(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int pkt_len, status;
+       struct sk_buff *skb;
+       unsigned char *data;
+
+       DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n",
+               dev->name, __FUNCTION__);
+       status = SMC_GET_RX_STS_FIFO();
+       DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x \n",
+               dev->name, (status & 0x3fff0000) >> 16, status & 0xc000ffff);
+       pkt_len = (status & RX_STS_PKT_LEN_) >> 16;
+       if (status & RX_STS_ES_) {
+               /* Deal with a bad packet */
+               lp->stats.rx_errors++;
+               if (status & RX_STS_CRC_ERR_)
+                       lp->stats.rx_crc_errors++;
+               else {
+                       if (status & RX_STS_LEN_ERR_)
+                               lp->stats.rx_length_errors++;
+                       if (status & RX_STS_MCAST_)
+                               lp->stats.multicast++;
+               }
+               /* Remove the bad packet data from the RX FIFO */
+               smc911x_drop_pkt(dev);
+       } else {
+               /* Receive a valid packet */
+               /* Alloc a buffer with extra room for DMA alignment */
+               skb=dev_alloc_skb(pkt_len+32);
+               if (unlikely(skb == NULL)) {
+                       PRINTK( "%s: Low memory, rcvd packet dropped.\n",
+                               dev->name);
+                       lp->stats.rx_dropped++;
+                       smc911x_drop_pkt(dev);
+                       return;
+               }
+               /* Align IP header to 32 bits
+                * Note that the device is configured to add a 2
+                * byte padding to the packet start, so we really
+                * want to write to the orignal data pointer */
+               data = skb->data;
+               skb_reserve(skb, 2);
+               skb_put(skb,pkt_len-4);
+#ifdef SMC_USE_DMA
+               {
+               unsigned int fifo;
+               /* Lower the FIFO threshold if possible */
+               fifo = SMC_GET_FIFO_INT();
+               if (fifo & 0xFF) fifo--;
+               DBG(SMC_DEBUG_RX, "%s: Setting RX stat FIFO threshold to %d\n",
+                       dev->name, fifo & 0xff);
+               SMC_SET_FIFO_INT(fifo);
+               /* Setup RX DMA */
+               SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_));
+               lp->rxdma_active = 1;
+               lp->current_rx_skb = skb;
+               SMC_PULL_DATA(data, (pkt_len+2+15) & ~15);
+               /* Packet processing deferred to DMA RX interrupt */
+               }
+#else
+               SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_));
+               SMC_PULL_DATA(data, pkt_len+2+3);
+
+               DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name,);
+               PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64);
+               dev->last_rx = jiffies;
+               skb->dev = dev;
+               skb->protocol = eth_type_trans(skb, dev);
+               netif_rx(skb);
+               lp->stats.rx_packets++;
+               lp->stats.rx_bytes += pkt_len-4;
+#endif
+       }
+}
+
+/*
+ * This is called to actually send a packet to the chip.
+ */
+static void smc911x_hardware_send_pkt(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       struct sk_buff *skb;
+       unsigned int cmdA, cmdB, len;
+       unsigned char *buf;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __FUNCTION__);
+       BUG_ON(lp->pending_tx_skb == NULL);
+
+       skb = lp->pending_tx_skb;
+       lp->pending_tx_skb = NULL;
+
+       /* cmdA {25:24] data alignment [20:16] start offset [10:0] buffer length */
+       /* cmdB {31:16] pkt tag [10:0] length */
+#ifdef SMC_USE_DMA
+       /* 16 byte buffer alignment mode */
+       buf = (char*)((u32)(skb->data) & ~0xF);
+       len = (skb->len + 0xF + ((u32)skb->data & 0xF)) & ~0xF;
+       cmdA = (1<<24) | (((u32)skb->data & 0xF)<<16) |
+                       TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ |
+                       skb->len;
+#else
+       buf = (char*)((u32)skb->data & ~0x3);
+       len = (skb->len + 3 + ((u32)skb->data & 3)) & ~0x3;
+       cmdA = (((u32)skb->data & 0x3) << 16) |
+                       TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ |
+                       skb->len;
+#endif
+       /* tag is packet length so we can use this in stats update later */
+       cmdB = (skb->len  << 16) | (skb->len & 0x7FF);
+
+       DBG(SMC_DEBUG_TX, "%s: TX PKT LENGTH 0x%04x (%d) BUF 0x%p CMDA 0x%08x CMDB 0x%08x\n",
+                dev->name, len, len, buf, cmdA, cmdB);
+       SMC_SET_TX_FIFO(cmdA);
+       SMC_SET_TX_FIFO(cmdB);
+
+       DBG(SMC_DEBUG_PKTS, "%s: Transmitted packet\n", dev->name);
+       PRINT_PKT(buf, len <= 64 ? len : 64);
+
+       /* Send pkt via PIO or DMA */
+#ifdef SMC_USE_DMA
+       lp->current_tx_skb = skb;
+       SMC_PUSH_DATA(buf, len);
+       /* DMA complete IRQ will free buffer and set jiffies */
+#else
+       SMC_PUSH_DATA(buf, len);
+       dev->trans_start = jiffies;
+       dev_kfree_skb(skb);
+#endif
+       spin_lock_irqsave(&lp->lock, flags);
+       if (!lp->tx_throttle) {
+               netif_wake_queue(dev);
+       }
+       spin_unlock_irqrestore(&lp->lock, flags);
+       SMC_ENABLE_INT(INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_);
+}
+
+/*
+ * Since I am not sure if I will have enough room in the chip's ram
+ * to store the packet, I call this routine which either sends it
+ * now, or set the card to generates an interrupt when ready
+ * for the packet.
+ */
+static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int free;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n",
+               dev->name, __FUNCTION__);
+
+       BUG_ON(lp->pending_tx_skb != NULL);
+
+       free = SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TDFREE_;
+       DBG(SMC_DEBUG_TX, "%s: TX free space %d\n", dev->name, free);
+
+       /* Turn off the flow when running out of space in FIFO */
+       if (free <= SMC911X_TX_FIFO_LOW_THRESHOLD) {
+               DBG(SMC_DEBUG_TX, "%s: Disabling data flow due to low FIFO space (%d)\n",
+                       dev->name, free);
+               spin_lock_irqsave(&lp->lock, flags);
+               /* Reenable when at least 1 packet of size MTU present */
+               SMC_SET_FIFO_TDA((SMC911X_TX_FIFO_LOW_THRESHOLD)/64);
+               lp->tx_throttle = 1;
+               netif_stop_queue(dev);
+               spin_unlock_irqrestore(&lp->lock, flags);
+       }
+
+       /* Drop packets when we run out of space in TX FIFO
+        * Account for overhead required for:
+        *
+        *        Tx command words                       8 bytes
+        *        Start offset                           15 bytes
+        *        End padding                            15 bytes
+        */
+       if (unlikely(free < (skb->len + 8 + 15 + 15))) {
+               printk("%s: No Tx free space %d < %d\n",
+                       dev->name, free, skb->len);
+               lp->pending_tx_skb = NULL;
+               lp->stats.tx_errors++;
+               lp->stats.tx_dropped++;
+               dev_kfree_skb(skb);
+               return 0;
+       }
+
+#ifdef SMC_USE_DMA
+       {
+               /* If the DMA is already running then defer this packet Tx until
+                * the DMA IRQ starts it
+                */
+               spin_lock_irqsave(&lp->lock, flags);
+               if (lp->txdma_active) {
+                       DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Tx DMA running, deferring packet\n", dev->name);
+                       lp->pending_tx_skb = skb;
+                       netif_stop_queue(dev);
+                       spin_unlock_irqrestore(&lp->lock, flags);
+                       return 0;
+               } else {
+                       DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Activating Tx DMA\n", dev->name);
+                       lp->txdma_active = 1;
+               }
+               spin_unlock_irqrestore(&lp->lock, flags);
+       }
+#endif
+       lp->pending_tx_skb = skb;
+       smc911x_hardware_send_pkt(dev);
+
+       return 0;
+}
+
+/*
+ * This handles a TX status interrupt, which is only called when:
+ * - a TX error occurred, or
+ * - TX of a packet completed.
+ */
+static void smc911x_tx(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned int tx_status;
+
+       DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n",
+               dev->name, __FUNCTION__);
+
+       /* Collect the TX status */
+       while (((SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16) != 0) {
+               DBG(SMC_DEBUG_TX, "%s: Tx stat FIFO used 0x%04x\n",
+                       dev->name,
+                       (SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16);
+               tx_status = SMC_GET_TX_STS_FIFO();
+               lp->stats.tx_packets++;
+               lp->stats.tx_bytes+=tx_status>>16;
+               DBG(SMC_DEBUG_TX, "%s: Tx FIFO tag 0x%04x status 0x%04x\n",
+                       dev->name, (tx_status & 0xffff0000) >> 16,
+                       tx_status & 0x0000ffff);
+               /* count Tx errors, but ignore lost carrier errors when in
+                * full-duplex mode */
+               if ((tx_status & TX_STS_ES_) && !(lp->ctl_rfduplx &&
+                   !(tx_status & 0x00000306))) {
+                       lp->stats.tx_errors++;
+               }
+               if (tx_status & TX_STS_MANY_COLL_) {
+                       lp->stats.collisions+=16;
+                       lp->stats.tx_aborted_errors++;
+               } else {
+                       lp->stats.collisions+=(tx_status & TX_STS_COLL_CNT_) >> 3;
+               }
+               /* carrier error only has meaning for half-duplex communication */
+               if ((tx_status & (TX_STS_LOC_ | TX_STS_NO_CARR_)) &&
+                   !lp->ctl_rfduplx) {
+                       lp->stats.tx_carrier_errors++;
+               }
+               if (tx_status & TX_STS_LATE_COLL_) {
+                       lp->stats.collisions++;
+                       lp->stats.tx_aborted_errors++;
+               }
+       }
+}
+
+
+/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/
+/*
+ * Reads a register from the MII Management serial interface
+ */
+
+static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg)
+{
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int phydata;
+
+       SMC_GET_MII(phyreg, phyaddr, phydata);
+
+       DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%02x, phydata=0x%04x\n",
+               __FUNCTION__, phyaddr, phyreg, phydata);
+       return phydata;
+}
+
+
+/*
+ * Writes a register to the MII Management serial interface
+ */
+static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg,
+                       int phydata)
+{
+       unsigned long ioaddr = dev->base_addr;
+
+       DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+               __FUNCTION__, phyaddr, phyreg, phydata);
+
+       SMC_SET_MII(phyreg, phyaddr, phydata);
+}
+
+/*
+ * Finds and reports the PHY address (115 and 117 have external
+ * PHY interface 118 has internal only
+ */
+static void smc911x_phy_detect(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       int phyaddr;
+       unsigned int cfg, id1, id2;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       lp->phy_type = 0;
+
+       /*
+        * Scan all 32 PHY addresses if necessary, starting at
+        * PHY#1 to PHY#31, and then PHY#0 last.
+        */
+       switch(lp->version) {
+               case 0x115:
+               case 0x117:
+                       cfg = SMC_GET_HW_CFG();
+                       if (cfg & HW_CFG_EXT_PHY_DET_) {
+                               cfg &= ~HW_CFG_PHY_CLK_SEL_;
+                               cfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
+                               SMC_SET_HW_CFG(cfg);
+                               udelay(10); /* Wait for clocks to stop */
+
+                               cfg |= HW_CFG_EXT_PHY_EN_;
+                               SMC_SET_HW_CFG(cfg);
+                               udelay(10); /* Wait for clocks to stop */
+
+                               cfg &= ~HW_CFG_PHY_CLK_SEL_;
+                               cfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
+                               SMC_SET_HW_CFG(cfg);
+                               udelay(10); /* Wait for clocks to stop */
+
+                               cfg |= HW_CFG_SMI_SEL_;
+                               SMC_SET_HW_CFG(cfg);
+
+                               for (phyaddr = 1; phyaddr < 32; ++phyaddr) {
+
+                                       /* Read the PHY identifiers */
+                                       SMC_GET_PHY_ID1(phyaddr & 31, id1);
+                                       SMC_GET_PHY_ID2(phyaddr & 31, id2);
+
+                                       /* Make sure it is a valid identifier */
+                                       if (id1 != 0x0000 && id1 != 0xffff &&
+                                           id1 != 0x8000 && id2 != 0x0000 &&
+                                           id2 != 0xffff && id2 != 0x8000) {
+                                               /* Save the PHY's address */
+                                               lp->mii.phy_id = phyaddr & 31;
+                                               lp->phy_type = id1 << 16 | id2;
+                                               break;
+                                       }
+                               }
+                       }
+               default:
+                       /* Internal media only */
+                       SMC_GET_PHY_ID1(1, id1);
+                       SMC_GET_PHY_ID2(1, id2);
+                       /* Save the PHY's address */
+                       lp->mii.phy_id = 1;
+                       lp->phy_type = id1 << 16 | id2;
+       }
+
+       DBG(SMC_DEBUG_MISC, "%s: phy_id1=0x%x, phy_id2=0x%x phyaddr=0x%d\n",
+               dev->name, id1, id2, lp->mii.phy_id);
+}
+
+/*
+ * Sets the PHY to a configuration as determined by the user.
+ * Called with spin_lock held.
+ */
+static int smc911x_phy_fixed(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int phyaddr = lp->mii.phy_id;
+       int bmcr;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       /* Enter Link Disable state */
+       SMC_GET_PHY_BMCR(phyaddr, bmcr);
+       bmcr |= BMCR_PDOWN;
+       SMC_SET_PHY_BMCR(phyaddr, bmcr);
+
+       /*
+        * Set our fixed capabilities
+        * Disable auto-negotiation
+        */
+       bmcr &= ~BMCR_ANENABLE;
+       if (lp->ctl_rfduplx)
+               bmcr |= BMCR_FULLDPLX;
+
+       if (lp->ctl_rspeed == 100)
+               bmcr |= BMCR_SPEED100;
+
+       /* Write our capabilities to the phy control register */
+       SMC_SET_PHY_BMCR(phyaddr, bmcr);
+
+       /* Re-Configure the Receive/Phy Control register */
+       bmcr &= ~BMCR_PDOWN;
+       SMC_SET_PHY_BMCR(phyaddr, bmcr);
+
+       return 1;
+}
+
+/*
+ * smc911x_phy_reset - reset the phy
+ * @dev: net device
+ * @phy: phy address
+ *
+ * Issue a software reset for the specified PHY and
+ * wait up to 100ms for the reset to complete.  We should
+ * not access the PHY for 50ms after issuing the reset.
+ *
+ * The time to wait appears to be dependent on the PHY.
+ *
+ */
+static int smc911x_phy_reset(struct net_device *dev, int phy)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int timeout;
+       unsigned long flags;
+       unsigned int reg;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__);
+
+       spin_lock_irqsave(&lp->lock, flags);
+       reg = SMC_GET_PMT_CTRL();
+       reg &= ~0xfffff030;
+       reg |= PMT_CTRL_PHY_RST_;
+       SMC_SET_PMT_CTRL(reg);
+       spin_unlock_irqrestore(&lp->lock, flags);
+       for (timeout = 2; timeout; timeout--) {
+               msleep(50);
+               spin_lock_irqsave(&lp->lock, flags);
+               reg = SMC_GET_PMT_CTRL();
+               spin_unlock_irqrestore(&lp->lock, flags);
+               if (!(reg & PMT_CTRL_PHY_RST_)) {
+                       /* extra delay required because the phy may
+                        * not be completed with its reset
+                        * when PHY_BCR_RESET_ is cleared. 256us
+                        * should suffice, but use 500us to be safe
+                        */
+                       udelay(500);
+               break;
+               }
+       }
+
+       return reg & PMT_CTRL_PHY_RST_;
+}
+
+/*
+ * smc911x_phy_powerdown - powerdown phy
+ * @dev: net device
+ * @phy: phy address
+ *
+ * Power down the specified PHY
+ */
+static void smc911x_phy_powerdown(struct net_device *dev, int phy)
+{
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int bmcr;
+
+       /* Enter Link Disable state */
+       SMC_GET_PHY_BMCR(phy, bmcr);
+       bmcr |= BMCR_PDOWN;
+       SMC_SET_PHY_BMCR(phy, bmcr);
+}
+
+/*
+ * smc911x_phy_check_media - check the media status and adjust BMCR
+ * @dev: net device
+ * @init: set true for initialisation
+ *
+ * Select duplex mode depending on negotiation state.  This
+ * also updates our carrier state.
+ */
+static void smc911x_phy_check_media(struct net_device *dev, int init)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int phyaddr = lp->mii.phy_id;
+       unsigned int bmcr, cr;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
+               /* duplex state has changed */
+               SMC_GET_PHY_BMCR(phyaddr, bmcr);
+               SMC_GET_MAC_CR(cr);
+               if (lp->mii.full_duplex) {
+                       DBG(SMC_DEBUG_MISC, "%s: Configuring for full-duplex mode\n", dev->name);
+                       bmcr |= BMCR_FULLDPLX;
+                       cr |= MAC_CR_RCVOWN_;
+               } else {
+                       DBG(SMC_DEBUG_MISC, "%s: Configuring for half-duplex mode\n", dev->name);
+                       bmcr &= ~BMCR_FULLDPLX;
+                       cr &= ~MAC_CR_RCVOWN_;
+               }
+               SMC_SET_PHY_BMCR(phyaddr, bmcr);
+               SMC_SET_MAC_CR(cr);
+       }
+}
+
+/*
+ * Configures the specified PHY through the MII management interface
+ * using Autonegotiation.
+ * Calls smc911x_phy_fixed() if the user has requested a certain config.
+ * If RPC ANEG bit is set, the media selection is dependent purely on
+ * the selection by the MII (either in the MII BMCR reg or the result
+ * of autonegotiation.)  If the RPC ANEG bit is cleared, the selection
+ * is controlled by the RPC SPEED and RPC DPLX bits.
+ */
+static void smc911x_phy_configure(void *data)
+{
+       struct net_device *dev = data;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int phyaddr = lp->mii.phy_id;
+       int my_phy_caps; /* My PHY capabilities */
+       int my_ad_caps; /* My Advertised capabilities */
+       int status;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__);
+
+       /*
+        * We should not be called if phy_type is zero.
+        */
+       if (lp->phy_type == 0)
+                goto smc911x_phy_configure_exit;
+
+       if (smc911x_phy_reset(dev, phyaddr)) {
+               printk("%s: PHY reset timed out\n", dev->name);
+               goto smc911x_phy_configure_exit;
+       }
+       spin_lock_irqsave(&lp->lock, flags);
+
+       /*
+        * Enable PHY Interrupts (for register 18)
+        * Interrupts listed here are enabled
+        */
+       SMC_SET_PHY_INT_MASK(phyaddr, PHY_INT_MASK_ENERGY_ON_ |
+                PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_REMOTE_FAULT_ |
+                PHY_INT_MASK_LINK_DOWN_);
+
+       /* If the user requested no auto neg, then go set his request */
+       if (lp->mii.force_media) {
+               smc911x_phy_fixed(dev);
+               goto smc911x_phy_configure_exit;
+       }
+
+       /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */
+       SMC_GET_PHY_BMSR(phyaddr, my_phy_caps);
+       if (!(my_phy_caps & BMSR_ANEGCAPABLE)) {
+               printk(KERN_INFO "Auto negotiation NOT supported\n");
+               smc911x_phy_fixed(dev);
+               goto smc911x_phy_configure_exit;
+       }
+
+       /* CSMA capable w/ both pauses */
+       my_ad_caps = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+
+       if (my_phy_caps & BMSR_100BASE4)
+               my_ad_caps |= ADVERTISE_100BASE4;
+       if (my_phy_caps & BMSR_100FULL)
+               my_ad_caps |= ADVERTISE_100FULL;
+       if (my_phy_caps & BMSR_100HALF)
+               my_ad_caps |= ADVERTISE_100HALF;
+       if (my_phy_caps & BMSR_10FULL)
+               my_ad_caps |= ADVERTISE_10FULL;
+       if (my_phy_caps & BMSR_10HALF)
+               my_ad_caps |= ADVERTISE_10HALF;
+
+       /* Disable capabilities not selected by our user */
+       if (lp->ctl_rspeed != 100)
+               my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF);
+
+        if (!lp->ctl_rfduplx)
+               my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL);
+
+       /* Update our Auto-Neg Advertisement Register */
+       SMC_SET_PHY_MII_ADV(phyaddr, my_ad_caps);
+       lp->mii.advertising = my_ad_caps;
+
+       /*
+        * Read the register back.       Without this, it appears that when
+        * auto-negotiation is restarted, sometimes it isn't ready and
+        * the link does not come up.
+        */
+       udelay(10);
+       SMC_GET_PHY_MII_ADV(phyaddr, status);
+
+       DBG(SMC_DEBUG_MISC, "%s: phy caps=0x%04x\n", dev->name, my_phy_caps);
+       DBG(SMC_DEBUG_MISC, "%s: phy advertised caps=0x%04x\n", dev->name, my_ad_caps);
+
+       /* Restart auto-negotiation process in order to advertise my caps */
+       SMC_SET_PHY_BMCR(phyaddr, BMCR_ANENABLE | BMCR_ANRESTART);
+
+       smc911x_phy_check_media(dev, 1);
+
+smc911x_phy_configure_exit:
+       spin_unlock_irqrestore(&lp->lock, flags);
+       lp->work_pending = 0;
+}
+
+/*
+ * smc911x_phy_interrupt
+ *
+ * Purpose:  Handle interrupts relating to PHY register 18. This is
+ *      called from the "hard" interrupt handler under our private spinlock.
+ */
+static void smc911x_phy_interrupt(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int phyaddr = lp->mii.phy_id;
+       int status;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       if (lp->phy_type == 0)
+               return;
+
+       smc911x_phy_check_media(dev, 0);
+       /* read to clear status bits */
+       SMC_GET_PHY_INT_SRC(phyaddr,status);
+       DBG(SMC_DEBUG_MISC, "%s: PHY interrupt status 0x%04x\n",
+               dev->name, status & 0xffff);
+       DBG(SMC_DEBUG_MISC, "%s: AFC_CFG 0x%08x\n",
+               dev->name, SMC_GET_AFC_CFG());
+}
+
+/*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/
+
+/*
+ * This is the main routine of the driver, to handle the device when
+ * it needs some attention.
+ */
+static irqreturn_t smc911x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = dev_id;
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned int status, mask, timeout;
+       unsigned int rx_overrun=0, cr, pkts;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       spin_lock_irqsave(&lp->lock, flags);
+
+       /* Spurious interrupt check */
+       if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) !=
+               (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) {
+               return IRQ_NONE;
+       }
+
+       mask = SMC_GET_INT_EN();
+       SMC_SET_INT_EN(0);
+
+       /* set a timeout value, so I don't stay here forever */
+       timeout = 8;
+
+
+       do {
+               status = SMC_GET_INT();
+
+               DBG(SMC_DEBUG_MISC, "%s: INT 0x%08x MASK 0x%08x OUTSIDE MASK 0x%08x\n",
+                       dev->name, status, mask, status & ~mask);
+
+               status &= mask;
+               if (!status)
+                       break;
+
+               /* Handle SW interrupt condition */
+               if (status & INT_STS_SW_INT_) {
+                       SMC_ACK_INT(INT_STS_SW_INT_);
+                       mask &= ~INT_EN_SW_INT_EN_;
+               }
+               /* Handle various error conditions */
+               if (status & INT_STS_RXE_) {
+                       SMC_ACK_INT(INT_STS_RXE_);
+                       lp->stats.rx_errors++;
+               }
+               if (status & INT_STS_RXDFH_INT_) {
+                       SMC_ACK_INT(INT_STS_RXDFH_INT_);
+                       lp->stats.rx_dropped+=SMC_GET_RX_DROP();
+                }
+               /* Undocumented interrupt-what is the right thing to do here? */
+               if (status & INT_STS_RXDF_INT_) {
+                       SMC_ACK_INT(INT_STS_RXDF_INT_);
+               }
+
+               /* Rx Data FIFO exceeds set level */
+               if (status & INT_STS_RDFL_) {
+                       if (IS_REV_A(lp->revision)) {
+                               rx_overrun=1;
+                               SMC_GET_MAC_CR(cr);
+                               cr &= ~MAC_CR_RXEN_;
+                               SMC_SET_MAC_CR(cr);
+                               DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name);
+                               lp->stats.rx_errors++;
+                               lp->stats.rx_fifo_errors++;
+                       }
+                       SMC_ACK_INT(INT_STS_RDFL_);
+               }
+               if (status & INT_STS_RDFO_) {
+                       if (!IS_REV_A(lp->revision)) {
+                               SMC_GET_MAC_CR(cr);
+                               cr &= ~MAC_CR_RXEN_;
+                               SMC_SET_MAC_CR(cr);
+                               rx_overrun=1;
+                               DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name);
+                               lp->stats.rx_errors++;
+                               lp->stats.rx_fifo_errors++;
+                       }
+                       SMC_ACK_INT(INT_STS_RDFO_);
+               }
+               /* Handle receive condition */
+               if ((status & INT_STS_RSFL_) || rx_overrun) {
+                       unsigned int fifo;
+                       DBG(SMC_DEBUG_RX, "%s: RX irq\n", dev->name);
+                       fifo = SMC_GET_RX_FIFO_INF();
+                       pkts = (fifo & RX_FIFO_INF_RXSUSED_) >> 16;
+                       DBG(SMC_DEBUG_RX, "%s: Rx FIFO pkts %d, bytes %d\n",
+                               dev->name, pkts, fifo & 0xFFFF );
+                       if (pkts != 0) {
+#ifdef SMC_USE_DMA
+                               unsigned int fifo;
+                               if (lp->rxdma_active){
+                                       DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA,
+                                               "%s: RX DMA active\n", dev->name);
+                                       /* The DMA is already running so up the IRQ threshold */
+                                       fifo = SMC_GET_FIFO_INT() & ~0xFF;
+                                       fifo |= pkts & 0xFF;
+                                       DBG(SMC_DEBUG_RX,
+                                               "%s: Setting RX stat FIFO threshold to %d\n",
+                                               dev->name, fifo & 0xff);
+                                       SMC_SET_FIFO_INT(fifo);
+                               } else
+#endif
+                               smc911x_rcv(dev);
+                       }
+                       SMC_ACK_INT(INT_STS_RSFL_);
+               }
+               /* Handle transmit FIFO available */
+               if (status & INT_STS_TDFA_) {
+                       DBG(SMC_DEBUG_TX, "%s: TX data FIFO space available irq\n", dev->name);
+                       SMC_SET_FIFO_TDA(0xFF);
+                       lp->tx_throttle = 0;
+#ifdef SMC_USE_DMA
+                       if (!lp->txdma_active)
+#endif
+                               netif_wake_queue(dev);
+                       SMC_ACK_INT(INT_STS_TDFA_);
+               }
+               /* Handle transmit done condition */
+#if 1
+               if (status & (INT_STS_TSFL_ | INT_STS_GPT_INT_)) {
+                       DBG(SMC_DEBUG_TX | SMC_DEBUG_MISC,
+                               "%s: Tx stat FIFO limit (%d) /GPT irq\n",
+                               dev->name, (SMC_GET_FIFO_INT() & 0x00ff0000) >> 16);
+                       smc911x_tx(dev);
+                       SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
+                       SMC_ACK_INT(INT_STS_TSFL_);
+                       SMC_ACK_INT(INT_STS_TSFL_ | INT_STS_GPT_INT_);
+               }
+#else
+               if (status & INT_STS_TSFL_) {
+                       DBG(SMC_DEBUG_TX, "%s: TX status FIFO limit (%d) irq \n", dev->name, );
+                       smc911x_tx(dev);
+                       SMC_ACK_INT(INT_STS_TSFL_);
+               }
+
+               if (status & INT_STS_GPT_INT_) {
+                       DBG(SMC_DEBUG_RX, "%s: IRQ_CFG 0x%08x FIFO_INT 0x%08x RX_CFG 0x%08x\n",
+                               dev->name,
+                               SMC_GET_IRQ_CFG(),
+                               SMC_GET_FIFO_INT(),
+                               SMC_GET_RX_CFG());
+                       DBG(SMC_DEBUG_RX, "%s: Rx Stat FIFO Used 0x%02x "
+                               "Data FIFO Used 0x%04x Stat FIFO 0x%08x\n",
+                               dev->name,
+                               (SMC_GET_RX_FIFO_INF() & 0x00ff0000) >> 16,
+                               SMC_GET_RX_FIFO_INF() & 0xffff,
+                               SMC_GET_RX_STS_FIFO_PEEK());
+                       SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
+                       SMC_ACK_INT(INT_STS_GPT_INT_);
+               }
+#endif
+
+               /* Handle PHY interupt condition */
+               if (status & INT_STS_PHY_INT_) {
+                       DBG(SMC_DEBUG_MISC, "%s: PHY irq\n", dev->name);
+                       smc911x_phy_interrupt(dev);
+                       SMC_ACK_INT(INT_STS_PHY_INT_);
+               }
+       } while (--timeout);
+
+       /* restore mask state */
+       SMC_SET_INT_EN(mask);
+
+       DBG(SMC_DEBUG_MISC, "%s: Interrupt done (%d loops)\n",
+               dev->name, 8-timeout);
+
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout);
+
+       return IRQ_HANDLED;
+}
+
+#ifdef SMC_USE_DMA
+static void
+smc911x_tx_dma_irq(int dma, void *data, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *)data;
+       struct smc911x_local *lp = netdev_priv(dev);
+       struct sk_buff *skb = lp->current_tx_skb;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: TX DMA irq handler\n", dev->name);
+       /* Clear the DMA interrupt sources */
+       SMC_DMA_ACK_IRQ(dev, dma);
+       BUG_ON(skb == NULL);
+       dma_unmap_single(NULL, tx_dmabuf, tx_dmalen, DMA_TO_DEVICE);
+       dev->trans_start = jiffies;
+       dev_kfree_skb_irq(skb);
+       lp->current_tx_skb = NULL;
+       if (lp->pending_tx_skb != NULL)
+               smc911x_hardware_send_pkt(dev);
+       else {
+               DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA,
+                       "%s: No pending Tx packets. DMA disabled\n", dev->name);
+               spin_lock_irqsave(&lp->lock, flags);
+               lp->txdma_active = 0;
+               if (!lp->tx_throttle) {
+                       netif_wake_queue(dev);
+               }
+               spin_unlock_irqrestore(&lp->lock, flags);
+       }
+
+       DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA,
+               "%s: TX DMA irq completed\n", dev->name);
+}
+static void
+smc911x_rx_dma_irq(int dma, void *data, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *)data;
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       struct sk_buff *skb = lp->current_rx_skb;
+       unsigned long flags;
+       unsigned int pkts;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+       DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA irq handler\n", dev->name);
+       /* Clear the DMA interrupt sources */
+       SMC_DMA_ACK_IRQ(dev, dma);
+       dma_unmap_single(NULL, rx_dmabuf, rx_dmalen, DMA_FROM_DEVICE);
+       BUG_ON(skb == NULL);
+       lp->current_rx_skb = NULL;
+       PRINT_PKT(skb->data, skb->len);
+       dev->last_rx = jiffies;
+       skb->dev = dev;
+       skb->protocol = eth_type_trans(skb, dev);
+       netif_rx(skb);
+       lp->stats.rx_packets++;
+       lp->stats.rx_bytes += skb->len;
+
+       spin_lock_irqsave(&lp->lock, flags);
+       pkts = (SMC_GET_RX_FIFO_INF() & RX_FIFO_INF_RXSUSED_) >> 16;
+       if (pkts != 0) {
+               smc911x_rcv(dev);
+       }else {
+               lp->rxdma_active = 0;
+       }
+       spin_unlock_irqrestore(&lp->lock, flags);
+       DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA,
+               "%s: RX DMA irq completed. DMA RX FIFO PKTS %d\n",
+               dev->name, pkts);
+}
+#endif  /* SMC_USE_DMA */
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void smc911x_poll_controller(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       smc911x_interrupt(dev->irq, dev, NULL);
+       enable_irq(dev->irq);
+}
+#endif
+
+/* Our watchdog timed out. Called by the networking layer */
+static void smc911x_timeout(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int status, mask;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       spin_lock_irqsave(&lp->lock, flags);
+       status = SMC_GET_INT();
+       mask = SMC_GET_INT_EN();
+       spin_unlock_irqrestore(&lp->lock, flags);
+       DBG(SMC_DEBUG_MISC, "%s: INT 0x%02x MASK 0x%02x \n",
+               dev->name, status, mask);
+
+       /* Dump the current TX FIFO contents and restart */
+       mask = SMC_GET_TX_CFG();
+       SMC_SET_TX_CFG(mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_);
+       /*
+        * Reconfiguring the PHY doesn't seem like a bad idea here, but
+        * smc911x_phy_configure() calls msleep() which calls schedule_timeout()
+        * which calls schedule().       Hence we use a work queue.
+        */
+       if (lp->phy_type != 0) {
+               if (schedule_work(&lp->phy_configure)) {
+                       lp->work_pending = 1;
+               }
+       }
+
+       /* We can accept TX packets again */
+       dev->trans_start = jiffies;
+       netif_wake_queue(dev);
+}
+
+/*
+ * This routine will, depending on the values passed to it,
+ * either make it accept multicast packets, go into
+ * promiscuous mode (for TCPDUMP and cousins) or accept
+ * a select set of multicast packets
+ */
+static void smc911x_set_multicast_list(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int multicast_table[2];
+       unsigned int mcr, update_multicast = 0;
+       unsigned long flags;
+       /* table for flipping the order of 5 bits */
+       static const unsigned char invert5[] =
+               {0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C,
+                0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E,
+                0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0D, 0x1D,
+                0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F};
+
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_GET_MAC_CR(mcr);
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       if (dev->flags & IFF_PROMISC) {
+
+               DBG(SMC_DEBUG_MISC, "%s: RCR_PRMS\n", dev->name);
+               mcr |= MAC_CR_PRMS_;
+       }
+       /*
+        * Here, I am setting this to accept all multicast packets.
+        * I don't need to zero the multicast table, because the flag is
+        * checked before the table is
+        */
+       else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) {
+               DBG(SMC_DEBUG_MISC, "%s: RCR_ALMUL\n", dev->name);
+               mcr |= MAC_CR_MCPAS_;
+       }
+
+       /*
+        * This sets the internal hardware table to filter out unwanted
+        * multicast packets before they take up memory.
+        *
+        * The SMC chip uses a hash table where the high 6 bits of the CRC of
+        * address are the offset into the table.       If that bit is 1, then the
+        * multicast packet is accepted.  Otherwise, it's dropped silently.
+        *
+        * To use the 6 bits as an offset into the table, the high 1 bit is
+        * the number of the 32 bit register, while the low 5 bits are the bit
+        * within that register.
+        */
+       else if (dev->mc_count)  {
+               int i;
+               struct dev_mc_list *cur_addr;
+
+               /* Set the Hash perfec mode */
+               mcr |= MAC_CR_HPFILT_;
+
+               /* start with a table of all zeros: reject all */
+               memset(multicast_table, 0, sizeof(multicast_table));
+
+               cur_addr = dev->mc_list;
+               for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) {
+                       int position;
+
+                       /* do we have a pointer here? */
+                       if (!cur_addr)
+                               break;
+                       /* make sure this is a multicast address -
+                               shouldn't this be a given if we have it here ? */
+                       if (!(*cur_addr->dmi_addr & 1))
+                                continue;
+
+                       /* only use the low order bits */
+                       position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f;
+
+                       /* do some messy swapping to put the bit in the right spot */
+                       multicast_table[invert5[position&0x1F]&0x1] |=
+                               (1<<invert5[(position>>1)&0x1F]);
+               }
+
+               /* be sure I get rid of flags I might have set */
+               mcr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_);
+
+               /* now, the table can be loaded into the chipset */
+               update_multicast = 1;
+       } else   {
+               DBG(SMC_DEBUG_MISC, "%s: ~(MAC_CR_PRMS_|MAC_CR_MCPAS_)\n",
+                       dev->name);
+               mcr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_);
+
+               /*
+                * since I'm disabling all multicast entirely, I need to
+                * clear the multicast list
+                */
+               memset(multicast_table, 0, sizeof(multicast_table));
+               update_multicast = 1;
+       }
+
+       spin_lock_irqsave(&lp->lock, flags);
+       SMC_SET_MAC_CR(mcr);
+       if (update_multicast) {
+               DBG(SMC_DEBUG_MISC,
+                       "%s: update mcast hash table 0x%08x 0x%08x\n",
+                       dev->name, multicast_table[0], multicast_table[1]);
+               SMC_SET_HASHL(multicast_table[0]);
+               SMC_SET_HASHH(multicast_table[1]);
+       }
+       spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+
+/*
+ * Open and Initialize the board
+ *
+ * Set up everything, reset the card, etc..
+ */
+static int
+smc911x_open(struct net_device *dev)
+{
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       /*
+        * Check that the address is valid.  If its not, refuse
+        * to bring the device up.       The user must specify an
+        * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
+        */
+       if (!is_valid_ether_addr(dev->dev_addr)) {
+               PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* reset the hardware */
+       smc911x_reset(dev);
+
+       /* Configure the PHY, initialize the link state */
+       smc911x_phy_configure(dev);
+
+       /* Turn on Tx + Rx */
+       smc911x_enable(dev);
+
+       netif_start_queue(dev);
+
+       return 0;
+}
+
+/*
+ * smc911x_close
+ *
+ * this makes the board clean up everything that it can
+ * and not talk to the outside world.   Caused by
+ * an 'ifconfig ethX down'
+ */
+static int smc911x_close(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       netif_stop_queue(dev);
+       netif_carrier_off(dev);
+
+       /* clear everything */
+       smc911x_shutdown(dev);
+
+       if (lp->phy_type != 0) {
+               /* We need to ensure that no calls to
+                * smc911x_phy_configure are pending.
+
+                * flush_scheduled_work() cannot be called because we
+                * are running with the netlink semaphore held (from
+                * devinet_ioctl()) and the pending work queue
+                * contains linkwatch_event() (scheduled by
+                * netif_carrier_off() above). linkwatch_event() also
+                * wants the netlink semaphore.
+                */
+               while (lp->work_pending)
+                       schedule();
+               smc911x_phy_powerdown(dev, lp->mii.phy_id);
+       }
+
+       if (lp->pending_tx_skb) {
+               dev_kfree_skb(lp->pending_tx_skb);
+               lp->pending_tx_skb = NULL;
+       }
+
+       return 0;
+}
+
+/*
+ * Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+static struct net_device_stats *smc911x_query_statistics(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+
+       return &lp->stats;
+}
+
+/*
+ * Ethtool support
+ */
+static int
+smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long ioaddr = dev->base_addr;
+       int ret, status;
+       unsigned long flags;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+       cmd->maxtxpkt = 1;
+       cmd->maxrxpkt = 1;
+
+       if (lp->phy_type != 0) {
+               spin_lock_irqsave(&lp->lock, flags);
+               ret = mii_ethtool_gset(&lp->mii, cmd);
+               spin_unlock_irqrestore(&lp->lock, flags);
+       } else {
+               cmd->supported = SUPPORTED_10baseT_Half |
+                               SUPPORTED_10baseT_Full |
+                               SUPPORTED_TP | SUPPORTED_AUI;
+
+               if (lp->ctl_rspeed == 10)
+                       cmd->speed = SPEED_10;
+               else if (lp->ctl_rspeed == 100)
+                       cmd->speed = SPEED_100;
+
+               cmd->autoneg = AUTONEG_DISABLE;
+               if (lp->mii.phy_id==1)
+                       cmd->transceiver = XCVR_INTERNAL;
+               else
+                       cmd->transceiver = XCVR_EXTERNAL;
+               cmd->port = 0;
+               SMC_GET_PHY_SPECIAL(lp->mii.phy_id, status);
+               cmd->duplex =
+                       (status & (PHY_SPECIAL_SPD_10FULL_ | PHY_SPECIAL_SPD_100FULL_)) ?
+                               DUPLEX_FULL : DUPLEX_HALF;
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int
+smc911x_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       int ret;
+       unsigned long flags;
+
+       if (lp->phy_type != 0) {
+               spin_lock_irqsave(&lp->lock, flags);
+               ret = mii_ethtool_sset(&lp->mii, cmd);
+               spin_unlock_irqrestore(&lp->lock, flags);
+       } else {
+               if (cmd->autoneg != AUTONEG_DISABLE ||
+                       cmd->speed != SPEED_10 ||
+                       (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) ||
+                       (cmd->port != PORT_TP && cmd->port != PORT_AUI))
+                       return -EINVAL;
+
+               lp->ctl_rfduplx = cmd->duplex == DUPLEX_FULL;
+
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static void
+smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+       strncpy(info->driver, CARDNAME, sizeof(info->driver));
+       strncpy(info->version, version, sizeof(info->version));
+       strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info));
+}
+
+static int smc911x_ethtool_nwayreset(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       int ret = -EINVAL;
+       unsigned long flags;
+
+       if (lp->phy_type != 0) {
+               spin_lock_irqsave(&lp->lock, flags);
+               ret = mii_nway_restart(&lp->mii);
+               spin_unlock_irqrestore(&lp->lock, flags);
+       }
+
+       return ret;
+}
+
+static u32 smc911x_ethtool_getmsglevel(struct net_device *dev)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       return lp->msg_enable;
+}
+
+static void smc911x_ethtool_setmsglevel(struct net_device *dev, u32 level)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       lp->msg_enable = level;
+}
+
+static int smc911x_ethtool_getregslen(struct net_device *dev)
+{
+       /* System regs + MAC regs + PHY regs */
+       return (((E2P_CMD - ID_REV)/4 + 1) +
+                       (WUCSR - MAC_CR)+1 + 32) * sizeof(u32);
+}
+
+static void smc911x_ethtool_getregs(struct net_device *dev,
+                                                                                struct ethtool_regs* regs, void *buf)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct smc911x_local *lp = netdev_priv(dev);
+       unsigned long flags;
+       u32 reg,i,j=0;
+       u32 *data = (u32*)buf;
+
+       regs->version = lp->version;
+       for(i=ID_REV;i<=E2P_CMD;i+=4) {
+               data[j++] = SMC_inl(ioaddr,i);
+       }
+       for(i=MAC_CR;i<=WUCSR;i++) {
+               spin_lock_irqsave(&lp->lock, flags);
+               SMC_GET_MAC_CSR(i, reg);
+               spin_unlock_irqrestore(&lp->lock, flags);
+               data[j++] = reg;
+       }
+       for(i=0;i<=31;i++) {
+               spin_lock_irqsave(&lp->lock, flags);
+               SMC_GET_MII(i, lp->mii.phy_id, reg);
+               spin_unlock_irqrestore(&lp->lock, flags);
+               data[j++] = reg & 0xFFFF;
+       }
+}
+
+static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       unsigned int timeout;
+       int e2p_cmd;
+
+       e2p_cmd = SMC_GET_E2P_CMD();
+       for(timeout=10;(e2p_cmd & E2P_CMD_EPC_BUSY_) && timeout; timeout--) {
+               if (e2p_cmd & E2P_CMD_EPC_TIMEOUT_) {
+                       PRINTK("%s: %s timeout waiting for EEPROM to respond\n",
+                               dev->name, __FUNCTION__);
+                       return -EFAULT;
+               }
+               mdelay(1);
+               e2p_cmd = SMC_GET_E2P_CMD();
+       }
+       if (timeout == 0) {
+               PRINTK("%s: %s timeout waiting for EEPROM CMD not busy\n",
+                       dev->name, __FUNCTION__);
+               return -ETIMEDOUT;
+       }
+       return 0;
+}
+
+static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev,
+                                                                                                       int cmd, int addr)
+{
+       unsigned long ioaddr = dev->base_addr;
+       int ret;
+
+       if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
+               return ret;
+       SMC_SET_E2P_CMD(E2P_CMD_EPC_BUSY_ |
+               ((cmd) & (0x7<<28)) |
+               ((addr) & 0xFF));
+       return 0;
+}
+
+static inline int smc911x_ethtool_read_eeprom_byte(struct net_device *dev,
+                                                                                                       u8 *data)
+{
+       unsigned long ioaddr = dev->base_addr;
+       int ret;
+
+       if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
+               return ret;
+       *data = SMC_GET_E2P_DATA();
+       return 0;
+}
+
+static inline int smc911x_ethtool_write_eeprom_byte(struct net_device *dev,
+                                                                                                        u8 data)
+{
+       unsigned long ioaddr = dev->base_addr;
+       int ret;
+
+       if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
+               return ret;
+       SMC_SET_E2P_DATA(data);
+       return 0;
+}
+
+static int smc911x_ethtool_geteeprom(struct net_device *dev,
+                                                                         struct ethtool_eeprom *eeprom, u8 *data)
+{
+       u8 eebuf[SMC911X_EEPROM_LEN];
+       int i, ret;
+
+       for(i=0;i<SMC911X_EEPROM_LEN;i++) {
+               if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_READ_, i ))!=0)
+                       return ret;
+               if ((ret=smc911x_ethtool_read_eeprom_byte(dev, &eebuf[i]))!=0)
+                       return ret;
+               }
+       memcpy(data, eebuf+eeprom->offset, eeprom->len);
+       return 0;
+}
+
+static int smc911x_ethtool_seteeprom(struct net_device *dev,
+                                                                          struct ethtool_eeprom *eeprom, u8 *data)
+{
+       int i, ret;
+
+       /* Enable erase */
+       if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWEN_, 0 ))!=0)
+               return ret;
+       for(i=eeprom->offset;i<(eeprom->offset+eeprom->len);i++) {
+               /* erase byte */
+               if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_ERASE_, i ))!=0)
+                       return ret;
+               /* write byte */
+               if ((ret=smc911x_ethtool_write_eeprom_byte(dev, *data))!=0)
+                        return ret;
+               if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_WRITE_, i ))!=0)
+                       return ret;
+               }
+        return 0;
+}
+
+static int smc911x_ethtool_geteeprom_len(struct net_device *dev)
+{
+        return SMC911X_EEPROM_LEN;
+}
+
+static struct ethtool_ops smc911x_ethtool_ops = {
+       .get_settings    = smc911x_ethtool_getsettings,
+       .set_settings    = smc911x_ethtool_setsettings,
+       .get_drvinfo     = smc911x_ethtool_getdrvinfo,
+       .get_msglevel    = smc911x_ethtool_getmsglevel,
+       .set_msglevel    = smc911x_ethtool_setmsglevel,
+       .nway_reset = smc911x_ethtool_nwayreset,
+       .get_link        = ethtool_op_get_link,
+       .get_regs_len    = smc911x_ethtool_getregslen,
+       .get_regs        = smc911x_ethtool_getregs,
+       .get_eeprom_len = smc911x_ethtool_geteeprom_len,
+       .get_eeprom = smc911x_ethtool_geteeprom,
+       .set_eeprom = smc911x_ethtool_seteeprom,
+};
+
+/*
+ * smc911x_findirq
+ *
+ * This routine has a simple purpose -- make the SMC chip generate an
+ * interrupt, so an auto-detect routine can detect it, and find the IRQ,
+ */
+static int __init smc911x_findirq(unsigned long ioaddr)
+{
+       int timeout = 20;
+       unsigned long cookie;
+
+       DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+
+       cookie = probe_irq_on();
+
+       /*
+        * Force a SW interrupt
+        */
+
+       SMC_SET_INT_EN(INT_EN_SW_INT_EN_);
+
+       /*
+        * Wait until positive that the interrupt has been generated
+        */
+       do {
+               int int_status;
+               udelay(10);
+               int_status = SMC_GET_INT_EN();
+               if (int_status & INT_EN_SW_INT_EN_)
+                        break;         /* got the interrupt */
+       } while (--timeout);
+
+       /*
+        * there is really nothing that I can do here if timeout fails,
+        * as autoirq_report will return a 0 anyway, which is what I
+        * want in this case.    Plus, the clean up is needed in both
+        * cases.
+        */
+
+       /* and disable all interrupts again */
+       SMC_SET_INT_EN(0);
+
+       /* and return what I found */
+       return probe_irq_off(cookie);
+}
+
+/*
+ * Function: smc911x_probe(unsigned long ioaddr)
+ *
+ * Purpose:
+ *      Tests to see if a given ioaddr points to an SMC911x chip.
+ *      Returns a 0 on success
+ *
+ * Algorithm:
+ *      (1) see if the endian word is OK
+ *      (1) see if I recognize the chip ID in the appropriate register
+ *
+ * Here I do typical initialization tasks.
+ *
+ * o  Initialize the structure if needed
+ * o  print out my vanity message if not done so already
+ * o  print out what type of hardware is detected
+ * o  print out the ethernet address
+ * o  find the IRQ
+ * o  set up my private data
+ * o  configure the dev structure with my subroutines
+ * o  actually GRAB the irq.
+ * o  GRAB the region
+ */
+static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr)
+{
+       struct smc911x_local *lp = netdev_priv(dev);
+       int i, retval;
+       unsigned int val, chip_id, revision;
+       const char *version_string;
+
+       DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+       /* First, see if the endian word is recognized */
+       val = SMC_GET_BYTE_TEST();
+       DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val);
+       if (val != 0x87654321) {
+               printk(KERN_ERR "Invalid chip endian 0x08%x\n",val);
+               retval = -ENODEV;
+               goto err_out;
+       }
+
+       /*
+        * check if the revision register is something that I
+        * recognize.   These might need to be added to later,
+        * as future revisions could be added.
+        */
+       chip_id = SMC_GET_PN();
+       DBG(SMC_DEBUG_MISC, "%s: id probe returned 0x%04x\n", CARDNAME, chip_id);
+       for(i=0;chip_ids[i].id != 0; i++) {
+               if (chip_ids[i].id == chip_id) break;
+       }
+       if (!chip_ids[i].id) {
+               printk(KERN_ERR "Unknown chip ID %04x\n", chip_id);
+               retval = -ENODEV;
+               goto err_out;
+       }
+       version_string = chip_ids[i].name;
+
+       revision = SMC_GET_REV();
+       DBG(SMC_DEBUG_MISC, "%s: revision = 0x%04x\n", CARDNAME, revision);
+
+       /* At this point I'll assume that the chip is an SMC911x. */
+       DBG(SMC_DEBUG_MISC, "%s: Found a %s\n", CARDNAME, chip_ids[i].name);
+
+       /* Validate the TX FIFO size requested */
+       if ((tx_fifo_kb < 2) || (tx_fifo_kb > 14)) {
+               printk(KERN_ERR "Invalid TX FIFO size requested %d\n", tx_fifo_kb);
+               retval = -EINVAL;
+               goto err_out;
+       }
+
+       /* fill in some of the fields */
+       dev->base_addr = ioaddr;
+       lp->version = chip_ids[i].id;
+       lp->revision = revision;
+       lp->tx_fifo_kb = tx_fifo_kb;
+       /* Reverse calculate the RX FIFO size from the TX */
+       lp->tx_fifo_size=(lp->tx_fifo_kb<<10) - 512;
+       lp->rx_fifo_size= ((0x4000 - 512 - lp->tx_fifo_size) / 16) * 15;
+
+       /* Set the automatic flow control values */
+       switch(lp->tx_fifo_kb) {
+               /*
+                *       AFC_HI is about ((Rx Data Fifo Size)*2/3)/64
+                *       AFC_LO is AFC_HI/2
+                *       BACK_DUR is about 5uS*(AFC_LO) rounded down
+                */
+               case 2:/* 13440 Rx Data Fifo Size */
+                       lp->afc_cfg=0x008C46AF;break;
+               case 3:/* 12480 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0082419F;break;
+               case 4:/* 11520 Rx Data Fifo Size */
+                       lp->afc_cfg=0x00783C9F;break;
+               case 5:/* 10560 Rx Data Fifo Size */
+                       lp->afc_cfg=0x006E374F;break;
+               case 6:/* 9600 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0064328F;break;
+               case 7:/* 8640 Rx Data Fifo Size */
+                       lp->afc_cfg=0x005A2D7F;break;
+               case 8:/* 7680 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0050287F;break;
+               case 9:/* 6720 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0046236F;break;
+               case 10:/* 5760 Rx Data Fifo Size */
+                       lp->afc_cfg=0x003C1E6F;break;
+               case 11:/* 4800 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0032195F;break;
+               /*
+                *       AFC_HI is ~1520 bytes less than RX Data Fifo Size
+                *       AFC_LO is AFC_HI/2
+                *       BACK_DUR is about 5uS*(AFC_LO) rounded down
+                */
+               case 12:/* 3840 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0024124F;break;
+               case 13:/* 2880 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0015073F;break;
+               case 14:/* 1920 Rx Data Fifo Size */
+                       lp->afc_cfg=0x0006032F;break;
+                default:
+                        PRINTK("%s: ERROR -- no AFC_CFG setting found",
+                               dev->name);
+                        break;
+       }
+
+       DBG(SMC_DEBUG_MISC | SMC_DEBUG_TX | SMC_DEBUG_RX,
+               "%s: tx_fifo %d rx_fifo %d afc_cfg 0x%08x\n", CARDNAME,
+               lp->tx_fifo_size, lp->rx_fifo_size, lp->afc_cfg);
+
+       spin_lock_init(&lp->lock);
+
+       /* Get the MAC address */
+       SMC_GET_MAC_ADDR(dev->dev_addr);
+
+       /* now, reset the chip, and put it into a known state */
+       smc911x_reset(dev);
+
+       /*
+        * If dev->irq is 0, then the device has to be banged on to see
+        * what the IRQ is.
+        *
+        * Specifying an IRQ is done with the assumption that the user knows
+        * what (s)he is doing.  No checking is done!!!!
+        */
+       if (dev->irq < 1) {
+               int trials;
+
+               trials = 3;
+               while (trials--) {
+                       dev->irq = smc911x_findirq(ioaddr);
+                       if (dev->irq)
+                               break;
+                       /* kick the card and try again */
+                       smc911x_reset(dev);
+               }
+       }
+       if (dev->irq == 0) {
+               printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
+                       dev->name);
+               retval = -ENODEV;
+               goto err_out;
+       }
+       dev->irq = irq_canonicalize(dev->irq);
+
+       /* Fill in the fields of the device structure with ethernet values. */
+       ether_setup(dev);
+
+       dev->open = smc911x_open;
+       dev->stop = smc911x_close;
+       dev->hard_start_xmit = smc911x_hard_start_xmit;
+       dev->tx_timeout = smc911x_timeout;
+       dev->watchdog_timeo = msecs_to_jiffies(watchdog);
+       dev->get_stats = smc911x_query_statistics;
+       dev->set_multicast_list = smc911x_set_multicast_list;
+       dev->ethtool_ops = &smc911x_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller = smc911x_poll_controller;
+#endif
+
+       INIT_WORK(&lp->phy_configure, smc911x_phy_configure, dev);
+       lp->mii.phy_id_mask = 0x1f;
+       lp->mii.reg_num_mask = 0x1f;
+       lp->mii.force_media = 0;
+       lp->mii.full_duplex = 0;
+       lp->mii.dev = dev;
+       lp->mii.mdio_read = smc911x_phy_read;
+       lp->mii.mdio_write = smc911x_phy_write;
+
+       /*
+        * Locate the phy, if any.
+        */
+       smc911x_phy_detect(dev);
+
+       /* Set default parameters */
+       lp->msg_enable = NETIF_MSG_LINK;
+       lp->ctl_rfduplx = 1;
+       lp->ctl_rspeed = 100;
+
+       /* Grab the IRQ */
+       retval = request_irq(dev->irq, &smc911x_interrupt, SA_SHIRQ, dev->name, dev);
+       if (retval)
+               goto err_out;
+
+       set_irq_type(dev->irq, IRQT_FALLING);
+
+#ifdef SMC_USE_DMA
+       lp->rxdma = SMC_DMA_REQUEST(dev, smc911x_rx_dma_irq);
+       lp->txdma = SMC_DMA_REQUEST(dev, smc911x_tx_dma_irq);
+       lp->rxdma_active = 0;
+       lp->txdma_active = 0;
+       dev->dma = lp->rxdma;
+#endif
+
+       retval = register_netdev(dev);
+       if (retval == 0) {
+               /* now, print out the card info, in a short format.. */
+               printk("%s: %s (rev %d) at %#lx IRQ %d",
+                       dev->name, version_string, lp->revision,
+                       dev->base_addr, dev->irq);
+
+#ifdef SMC_USE_DMA
+               if (lp->rxdma != -1)
+                       printk(" RXDMA %d ", lp->rxdma);
+
+               if (lp->txdma != -1)
+                       printk("TXDMA %d", lp->txdma);
+#endif
+               printk("\n");
+               if (!is_valid_ether_addr(dev->dev_addr)) {
+                       printk("%s: Invalid ethernet MAC address. Please "
+                                       "set using ifconfig\n", dev->name);
+               } else {
+                       /* Print the Ethernet address */
+                       printk("%s: Ethernet addr: ", dev->name);
+                       for (i = 0; i < 5; i++)
+                               printk("%2.2x:", dev->dev_addr[i]);
+                       printk("%2.2x\n", dev->dev_addr[5]);
+               }
+
+               if (lp->phy_type == 0) {
+                       PRINTK("%s: No PHY found\n", dev->name);
+               } else if ((lp->phy_type & ~0xff) == LAN911X_INTERNAL_PHY_ID) {
+                       PRINTK("%s: LAN911x Internal PHY\n", dev->name);
+               } else {
+                       PRINTK("%s: External PHY 0x%08x\n", dev->name, lp->phy_type);
+               }
+       }
+
+err_out:
+#ifdef SMC_USE_DMA
+       if (retval) {
+               if (lp->rxdma != -1) {
+                       SMC_DMA_FREE(dev, lp->rxdma);
+               }
+               if (lp->txdma != -1) {
+                       SMC_DMA_FREE(dev, lp->txdma);
+               }
+       }
+#endif
+       return retval;
+}
+
+/*
+ * smc911x_init(void)
+ *
+ *       Output:
+ *      0 --> there is a device
+ *      anything else, error
+ */
+static int smc911x_drv_probe(struct platform_device *pdev)
+{
+       struct net_device *ndev;
+       struct resource *res;
+       unsigned int *addr;
+       int ret;
+
+       DBG(SMC_DEBUG_FUNC, "--> %s\n",  __FUNCTION__);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /*
+        * Request the regions.
+        */
+       if (!request_mem_region(res->start, SMC911X_IO_EXTENT, CARDNAME)) {
+                ret = -EBUSY;
+                goto out;
+       }
+
+       ndev = alloc_etherdev(sizeof(struct smc911x_local));
+       if (!ndev) {
+               printk("%s: could not allocate device.\n", CARDNAME);
+               ret = -ENOMEM;
+               goto release_1;
+       }
+       SET_MODULE_OWNER(ndev);
+       SET_NETDEV_DEV(ndev, &pdev->dev);
+
+       ndev->dma = (unsigned char)-1;
+       ndev->irq = platform_get_irq(pdev, 0);
+
+       addr = ioremap(res->start, SMC911X_IO_EXTENT);
+       if (!addr) {
+               ret = -ENOMEM;
+               goto release_both;
+       }
+
+       platform_set_drvdata(pdev, ndev);
+       ret = smc911x_probe(ndev, (unsigned long)addr);
+       if (ret != 0) {
+               platform_set_drvdata(pdev, NULL);
+               iounmap(addr);
+release_both:
+               free_netdev(ndev);
+release_1:
+               release_mem_region(res->start, SMC911X_IO_EXTENT);
+out:
+               printk("%s: not found (%d).\n", CARDNAME, ret);
+       }
+#ifdef SMC_USE_DMA
+       else {
+               struct smc911x_local *lp = netdev_priv(ndev);
+               lp->physaddr = res->start;
+               lp->dev = &pdev->dev;
+       }
+#endif
+
+       return ret;
+}
+
+static int smc911x_drv_remove(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+       platform_set_drvdata(pdev, NULL);
+
+       unregister_netdev(ndev);
+
+       free_irq(ndev->irq, ndev);
+
+#ifdef SMC_USE_DMA
+       {
+               struct smc911x_local *lp = netdev_priv(ndev);
+               if (lp->rxdma != -1) {
+                       SMC_DMA_FREE(dev, lp->rxdma);
+               }
+               if (lp->txdma != -1) {
+                       SMC_DMA_FREE(dev, lp->txdma);
+               }
+       }
+#endif
+       iounmap((void *)ndev->base_addr);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, SMC911X_IO_EXTENT);
+
+       free_netdev(ndev);
+       return 0;
+}
+
+static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct net_device *ndev = platform_get_drvdata(dev);
+       unsigned long ioaddr = ndev->base_addr;
+
+       DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+       if (ndev) {
+               if (netif_running(ndev)) {
+                       netif_device_detach(ndev);
+                       smc911x_shutdown(ndev);
+#if POWER_DOWN
+                       /* Set D2 - Energy detect only setting */
+                       SMC_SET_PMT_CTRL(2<<12);
+#endif
+               }
+       }
+       return 0;
+}
+
+static int smc911x_drv_resume(struct platform_device *dev)
+{
+       struct net_device *ndev = platform_get_drvdata(dev);
+
+       DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+       if (ndev) {
+               struct smc911x_local *lp = netdev_priv(ndev);
+
+               if (netif_running(ndev)) {
+                       smc911x_reset(ndev);
+                       smc911x_enable(ndev);
+                       if (lp->phy_type != 0)
+                               smc911x_phy_configure(ndev);
+                       netif_device_attach(ndev);
+               }
+       }
+       return 0;
+}
+
+static struct platform_driver smc911x_driver = {
+       .probe           = smc911x_drv_probe,
+       .remove  = smc911x_drv_remove,
+       .suspend         = smc911x_drv_suspend,
+       .resume  = smc911x_drv_resume,
+       .driver  = {
+               .name    = CARDNAME,
+       },
+};
+
+static int __init smc911x_init(void)
+{
+       return platform_driver_register(&smc911x_driver);
+}
+
+static void __exit smc911x_cleanup(void)
+{
+       platform_driver_unregister(&smc911x_driver);
+}
+
+module_init(smc911x_init);
+module_exit(smc911x_cleanup);
diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h
new file mode 100644 (file)
index 0000000..962a710
--- /dev/null
@@ -0,0 +1,835 @@
+/*------------------------------------------------------------------------
+ . smc911x.h - macros for SMSC's LAN911{5,6,7,8} single-chip Ethernet device.
+ .
+ . Copyright (C) 2005 Sensoria Corp.
+ . Derived from the unified SMC91x driver by Nicolas Pitre
+ .
+ . 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
+ .
+ . Information contained in this file was obtained from the LAN9118
+ . manual from SMC.  To get a copy, if you really want one, you can find
+ . information under www.smsc.com.
+ .
+ . Authors
+ .      Dustin McIntire                 <dustin@sensoria.com>
+ .
+ ---------------------------------------------------------------------------*/
+#ifndef _SMC911X_H_
+#define _SMC911X_H_
+
+/*
+ * Use the DMA feature on PXA chips
+ */
+#ifdef CONFIG_ARCH_PXA
+  #define SMC_USE_PXA_DMA      1
+  #define SMC_USE_16BIT                0
+  #define SMC_USE_32BIT                1
+#endif
+
+
+/*
+ * Define the bus width specific IO macros
+ */
+
+#if    SMC_USE_16BIT
+#define SMC_inb(a, r)                   readb((a) + (r))
+#define SMC_inw(a, r)                   readw((a) + (r))
+#define SMC_inl(a, r)                   ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw(a+2, r)<<16))
+#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)                       \
+       do{                                      \
+                writel(v & 0xFFFF, (a) + (r));  \
+                writel(v >> 16, (a) + (r) + 2); \
+        } while (0)
+#define SMC_insl(a, r, p, l)    readsw((short*)((a) + (r)), p, l*2)
+#define SMC_outsl(a, r, p, l)   writesw((short*)((a) + (r)), p, l*2)
+
+#elif  SMC_USE_32BIT
+#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_outl(v, a, r)       writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)    readsl((int*)((a) + (r)), p, l)
+#define SMC_outsl(a, r, p, l)   writesl((int*)((a) + (r)), p, l)
+
+#endif /* SMC_USE_16BIT */
+
+
+
+#if     SMC_USE_PXA_DMA
+#define SMC_USE_DMA
+
+/*
+ * Define the request and free functions
+ * These are unfortunately architecture specific as no generic allocation
+ * mechanism exits
+ */
+#define SMC_DMA_REQUEST(dev, handler) \
+        pxa_request_dma(dev->name, DMA_PRIO_LOW, handler, dev)
+
+#define SMC_DMA_FREE(dev, dma) \
+        pxa_free_dma(dma)
+
+#define SMC_DMA_ACK_IRQ(dev, dma)                                      \
+{                                                                      \
+       if (DCSR(dma) & DCSR_BUSERR) {                                  \
+               printk("%s: DMA %d bus error!\n", dev->name, dma);      \
+       }                                                               \
+       DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;            \
+}
+
+/*
+ * Use a DMA for RX and TX packets.
+ */
+#include <linux/dma-mapping.h>
+#include <asm/dma.h>
+#include <asm/arch/pxa-regs.h>
+
+static dma_addr_t rx_dmabuf, tx_dmabuf;
+static int rx_dmalen, tx_dmalen;
+
+#ifdef SMC_insl
+#undef SMC_insl
+#define SMC_insl(a, r, p, l) \
+       smc_pxa_dma_insl(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l)
+
+static inline void
+smc_pxa_dma_insl(struct device *dev, u_long ioaddr, u_long physaddr,
+               int reg, int dma, u_char *buf, int len)
+{
+       /* 64 bit alignment is required for memory to memory DMA */
+       if ((long)buf & 4) {
+               *((u32 *)buf) = SMC_inl(ioaddr, reg);
+               buf += 4;
+               len--;
+       }
+
+       len *= 4;
+       rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
+       rx_dmalen = len;
+       DCSR(dma) = DCSR_NODESC;
+       DTADR(dma) = rx_dmabuf;
+       DSADR(dma) = physaddr + reg;
+       DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
+               DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen));
+       DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#ifdef SMC_insw
+#undef SMC_insw
+#define SMC_insw(a, r, p, l) \
+       smc_pxa_dma_insw(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l)
+
+static inline void
+smc_pxa_dma_insw(struct device *dev, u_long ioaddr, u_long physaddr,
+               int reg, int dma, u_char *buf, int len)
+{
+       /* 64 bit alignment is required for memory to memory DMA */
+       while ((long)buf & 6) {
+               *((u16 *)buf) = SMC_inw(ioaddr, reg);
+               buf += 2;
+               len--;
+       }
+
+       len *= 2;
+       rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
+       rx_dmalen = len;
+       DCSR(dma) = DCSR_NODESC;
+       DTADR(dma) = rx_dmabuf;
+       DSADR(dma) = physaddr + reg;
+       DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
+               DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen));
+       DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#ifdef SMC_outsl
+#undef SMC_outsl
+#define SMC_outsl(a, r, p, l) \
+        smc_pxa_dma_outsl(lp->dev, a, lp->physaddr, r, lp->txdma, p, l)
+
+static inline void
+smc_pxa_dma_outsl(struct device *dev, u_long ioaddr, u_long physaddr,
+               int reg, int dma, u_char *buf, int len)
+{
+       /* 64 bit alignment is required for memory to memory DMA */
+       if ((long)buf & 4) {
+               SMC_outl(*((u32 *)buf), ioaddr, reg);
+               buf += 4;
+               len--;
+       }
+
+       len *= 4;
+       tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
+       tx_dmalen = len;
+       DCSR(dma) = DCSR_NODESC;
+       DSADR(dma) = tx_dmabuf;
+       DTADR(dma) = physaddr + reg;
+       DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 |
+               DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen));
+       DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#ifdef SMC_outsw
+#undef SMC_outsw
+#define SMC_outsw(a, r, p, l) \
+       smc_pxa_dma_outsw(lp->dev, a, lp->physaddr, r, lp->txdma, p, l)
+
+static inline void
+smc_pxa_dma_outsw(struct device *dev, u_long ioaddr, u_long physaddr,
+                 int reg, int dma, u_char *buf, int len)
+{
+       /* 64 bit alignment is required for memory to memory DMA */
+       while ((long)buf & 6) {
+               SMC_outw(*((u16 *)buf), ioaddr, reg);
+               buf += 2;
+               len--;
+       }
+
+       len *= 2;
+       tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
+       tx_dmalen = len;
+       DCSR(dma) = DCSR_NODESC;
+       DSADR(dma) = tx_dmabuf;
+       DTADR(dma) = physaddr + reg;
+       DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 |
+               DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen));
+       DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#endif  /* SMC_USE_PXA_DMA */
+
+
+/* Chip Parameters and Register Definitions */
+
+#define SMC911X_TX_FIFO_LOW_THRESHOLD  (1536*2)
+
+#define SMC911X_IO_EXTENT       0x100
+
+#define SMC911X_EEPROM_LEN      7
+
+/* Below are the register offsets and bit definitions
+ * of the Lan911x memory space
+ */
+#define RX_DATA_FIFO            (0x00)
+
+#define TX_DATA_FIFO            (0x20)
+#define        TX_CMD_A_INT_ON_COMP_           (0x80000000)
+#define        TX_CMD_A_INT_BUF_END_ALGN_      (0x03000000)
+#define        TX_CMD_A_INT_4_BYTE_ALGN_       (0x00000000)
+#define        TX_CMD_A_INT_16_BYTE_ALGN_      (0x01000000)
+#define        TX_CMD_A_INT_32_BYTE_ALGN_      (0x02000000)
+#define        TX_CMD_A_INT_DATA_OFFSET_       (0x001F0000)
+#define        TX_CMD_A_INT_FIRST_SEG_         (0x00002000)
+#define        TX_CMD_A_INT_LAST_SEG_          (0x00001000)
+#define        TX_CMD_A_BUF_SIZE_              (0x000007FF)
+#define        TX_CMD_B_PKT_TAG_               (0xFFFF0000)
+#define        TX_CMD_B_ADD_CRC_DISABLE_       (0x00002000)
+#define        TX_CMD_B_DISABLE_PADDING_       (0x00001000)
+#define        TX_CMD_B_PKT_BYTE_LENGTH_       (0x000007FF)
+
+#define RX_STATUS_FIFO         (0x40)
+#define        RX_STS_PKT_LEN_                 (0x3FFF0000)
+#define        RX_STS_ES_                      (0x00008000)
+#define        RX_STS_BCST_                    (0x00002000)
+#define        RX_STS_LEN_ERR_                 (0x00001000)
+#define        RX_STS_RUNT_ERR_                (0x00000800)
+#define        RX_STS_MCAST_                   (0x00000400)
+#define        RX_STS_TOO_LONG_                (0x00000080)
+#define        RX_STS_COLL_                    (0x00000040)
+#define        RX_STS_ETH_TYPE_                (0x00000020)
+#define        RX_STS_WDOG_TMT_                (0x00000010)
+#define        RX_STS_MII_ERR_                 (0x00000008)
+#define        RX_STS_DRIBBLING_               (0x00000004)
+#define        RX_STS_CRC_ERR_                 (0x00000002)
+#define RX_STATUS_FIFO_PEEK    (0x44)
+#define TX_STATUS_FIFO         (0x48)
+#define        TX_STS_TAG_                     (0xFFFF0000)
+#define        TX_STS_ES_                      (0x00008000)
+#define        TX_STS_LOC_                     (0x00000800)
+#define        TX_STS_NO_CARR_                 (0x00000400)
+#define        TX_STS_LATE_COLL_               (0x00000200)
+#define        TX_STS_MANY_COLL_               (0x00000100)
+#define        TX_STS_COLL_CNT_                (0x00000078)
+#define        TX_STS_MANY_DEFER_              (0x00000004)
+#define        TX_STS_UNDERRUN_                (0x00000002)
+#define        TX_STS_DEFERRED_                (0x00000001)
+#define TX_STATUS_FIFO_PEEK    (0x4C)
+#define ID_REV                 (0x50)
+#define        ID_REV_CHIP_ID_                 (0xFFFF0000)  /* RO */
+#define        ID_REV_REV_ID_                  (0x0000FFFF)  /* RO */
+
+#define INT_CFG                        (0x54)
+#define        INT_CFG_INT_DEAS_               (0xFF000000)  /* R/W */
+#define        INT_CFG_INT_DEAS_CLR_           (0x00004000)
+#define        INT_CFG_INT_DEAS_STS_           (0x00002000)
+#define        INT_CFG_IRQ_INT_                (0x00001000)  /* RO */
+#define        INT_CFG_IRQ_EN_                 (0x00000100)  /* R/W */
+#define        INT_CFG_IRQ_POL_                (0x00000010)  /* R/W Not Affected by SW Reset */
+#define        INT_CFG_IRQ_TYPE_               (0x00000001)  /* R/W Not Affected by SW Reset */
+
+#define INT_STS                        (0x58)
+#define        INT_STS_SW_INT_                 (0x80000000)  /* R/WC */
+#define        INT_STS_TXSTOP_INT_             (0x02000000)  /* R/WC */
+#define        INT_STS_RXSTOP_INT_             (0x01000000)  /* R/WC */
+#define        INT_STS_RXDFH_INT_              (0x00800000)  /* R/WC */
+#define        INT_STS_RXDF_INT_               (0x00400000)  /* R/WC */
+#define        INT_STS_TX_IOC_                 (0x00200000)  /* R/WC */
+#define        INT_STS_RXD_INT_                (0x00100000)  /* R/WC */
+#define        INT_STS_GPT_INT_                (0x00080000)  /* R/WC */
+#define        INT_STS_PHY_INT_                (0x00040000)  /* RO */
+#define        INT_STS_PME_INT_                (0x00020000)  /* R/WC */
+#define        INT_STS_TXSO_                   (0x00010000)  /* R/WC */
+#define        INT_STS_RWT_                    (0x00008000)  /* R/WC */
+#define        INT_STS_RXE_                    (0x00004000)  /* R/WC */
+#define        INT_STS_TXE_                    (0x00002000)  /* R/WC */
+//#define      INT_STS_ERX_            (0x00001000)  /* R/WC */
+#define        INT_STS_TDFU_                   (0x00000800)  /* R/WC */
+#define        INT_STS_TDFO_                   (0x00000400)  /* R/WC */
+#define        INT_STS_TDFA_                   (0x00000200)  /* R/WC */
+#define        INT_STS_TSFF_                   (0x00000100)  /* R/WC */
+#define        INT_STS_TSFL_                   (0x00000080)  /* R/WC */
+//#define      INT_STS_RXDF_           (0x00000040)  /* R/WC */
+#define        INT_STS_RDFO_                   (0x00000040)  /* R/WC */
+#define        INT_STS_RDFL_                   (0x00000020)  /* R/WC */
+#define        INT_STS_RSFF_                   (0x00000010)  /* R/WC */
+#define        INT_STS_RSFL_                   (0x00000008)  /* R/WC */
+#define        INT_STS_GPIO2_INT_              (0x00000004)  /* R/WC */
+#define        INT_STS_GPIO1_INT_              (0x00000002)  /* R/WC */
+#define        INT_STS_GPIO0_INT_              (0x00000001)  /* R/WC */
+
+#define INT_EN                 (0x5C)
+#define        INT_EN_SW_INT_EN_               (0x80000000)  /* R/W */
+#define        INT_EN_TXSTOP_INT_EN_           (0x02000000)  /* R/W */
+#define        INT_EN_RXSTOP_INT_EN_           (0x01000000)  /* R/W */
+#define        INT_EN_RXDFH_INT_EN_            (0x00800000)  /* R/W */
+//#define      INT_EN_RXDF_INT_EN_             (0x00400000)  /* R/W */
+#define        INT_EN_TIOC_INT_EN_             (0x00200000)  /* R/W */
+#define        INT_EN_RXD_INT_EN_              (0x00100000)  /* R/W */
+#define        INT_EN_GPT_INT_EN_              (0x00080000)  /* R/W */
+#define        INT_EN_PHY_INT_EN_              (0x00040000)  /* R/W */
+#define        INT_EN_PME_INT_EN_              (0x00020000)  /* R/W */
+#define        INT_EN_TXSO_EN_                 (0x00010000)  /* R/W */
+#define        INT_EN_RWT_EN_                  (0x00008000)  /* R/W */
+#define        INT_EN_RXE_EN_                  (0x00004000)  /* R/W */
+#define        INT_EN_TXE_EN_                  (0x00002000)  /* R/W */
+//#define      INT_EN_ERX_EN_                  (0x00001000)  /* R/W */
+#define        INT_EN_TDFU_EN_                 (0x00000800)  /* R/W */
+#define        INT_EN_TDFO_EN_                 (0x00000400)  /* R/W */
+#define        INT_EN_TDFA_EN_                 (0x00000200)  /* R/W */
+#define        INT_EN_TSFF_EN_                 (0x00000100)  /* R/W */
+#define        INT_EN_TSFL_EN_                 (0x00000080)  /* R/W */
+//#define      INT_EN_RXDF_EN_                 (0x00000040)  /* R/W */
+#define        INT_EN_RDFO_EN_                 (0x00000040)  /* R/W */
+#define        INT_EN_RDFL_EN_                 (0x00000020)  /* R/W */
+#define        INT_EN_RSFF_EN_                 (0x00000010)  /* R/W */
+#define        INT_EN_RSFL_EN_                 (0x00000008)  /* R/W */
+#define        INT_EN_GPIO2_INT_               (0x00000004)  /* R/W */
+#define        INT_EN_GPIO1_INT_               (0x00000002)  /* R/W */
+#define        INT_EN_GPIO0_INT_               (0x00000001)  /* R/W */
+
+#define BYTE_TEST              (0x64)
+#define FIFO_INT               (0x68)
+#define        FIFO_INT_TX_AVAIL_LEVEL_        (0xFF000000)  /* R/W */
+#define        FIFO_INT_TX_STS_LEVEL_          (0x00FF0000)  /* R/W */
+#define        FIFO_INT_RX_AVAIL_LEVEL_        (0x0000FF00)  /* R/W */
+#define        FIFO_INT_RX_STS_LEVEL_          (0x000000FF)  /* R/W */
+
+#define RX_CFG                 (0x6C)
+#define        RX_CFG_RX_END_ALGN_             (0xC0000000)  /* R/W */
+#define                RX_CFG_RX_END_ALGN4_            (0x00000000)  /* R/W */
+#define                RX_CFG_RX_END_ALGN16_           (0x40000000)  /* R/W */
+#define                RX_CFG_RX_END_ALGN32_           (0x80000000)  /* R/W */
+#define        RX_CFG_RX_DMA_CNT_              (0x0FFF0000)  /* R/W */
+#define        RX_CFG_RX_DUMP_                 (0x00008000)  /* R/W */
+#define        RX_CFG_RXDOFF_                  (0x00001F00)  /* R/W */
+//#define      RX_CFG_RXBAD_                   (0x00000001)  /* R/W */
+
+#define TX_CFG                 (0x70)
+//#define      TX_CFG_TX_DMA_LVL_              (0xE0000000)     /* R/W */
+//#define      TX_CFG_TX_DMA_CNT_              (0x0FFF0000)     /* R/W Self Clearing */
+#define        TX_CFG_TXS_DUMP_                (0x00008000)  /* Self Clearing */
+#define        TX_CFG_TXD_DUMP_                (0x00004000)  /* Self Clearing */
+#define        TX_CFG_TXSAO_                   (0x00000004)  /* R/W */
+#define        TX_CFG_TX_ON_                   (0x00000002)  /* R/W */
+#define        TX_CFG_STOP_TX_                 (0x00000001)  /* Self Clearing */
+
+#define HW_CFG                 (0x74)
+#define        HW_CFG_TTM_                     (0x00200000)  /* R/W */
+#define        HW_CFG_SF_                      (0x00100000)  /* R/W */
+#define        HW_CFG_TX_FIF_SZ_               (0x000F0000)  /* R/W */
+#define        HW_CFG_TR_                      (0x00003000)  /* R/W */
+#define        HW_CFG_PHY_CLK_SEL_             (0x00000060)  /* R/W */
+#define                 HW_CFG_PHY_CLK_SEL_INT_PHY_    (0x00000000) /* R/W */
+#define                 HW_CFG_PHY_CLK_SEL_EXT_PHY_    (0x00000020) /* R/W */
+#define                 HW_CFG_PHY_CLK_SEL_CLK_DIS_    (0x00000040) /* R/W */
+#define        HW_CFG_SMI_SEL_                 (0x00000010)  /* R/W */
+#define        HW_CFG_EXT_PHY_DET_             (0x00000008)  /* RO */
+#define        HW_CFG_EXT_PHY_EN_              (0x00000004)  /* R/W */
+#define        HW_CFG_32_16_BIT_MODE_          (0x00000004)  /* RO */
+#define        HW_CFG_SRST_TO_                 (0x00000002)  /* RO */
+#define        HW_CFG_SRST_                    (0x00000001)  /* Self Clearing */
+
+#define RX_DP_CTRL             (0x78)
+#define        RX_DP_CTRL_RX_FFWD_             (0x80000000)  /* R/W */
+#define        RX_DP_CTRL_FFWD_BUSY_           (0x80000000)  /* RO */
+
+#define RX_FIFO_INF            (0x7C)
+#define         RX_FIFO_INF_RXSUSED_           (0x00FF0000)  /* RO */
+#define         RX_FIFO_INF_RXDUSED_           (0x0000FFFF)  /* RO */
+
+#define TX_FIFO_INF            (0x80)
+#define        TX_FIFO_INF_TSUSED_             (0x00FF0000)  /* RO */
+#define        TX_FIFO_INF_TDFREE_             (0x0000FFFF)  /* RO */
+
+#define PMT_CTRL               (0x84)
+#define        PMT_CTRL_PM_MODE_               (0x00003000)  /* Self Clearing */
+#define        PMT_CTRL_PHY_RST_               (0x00000400)  /* Self Clearing */
+#define        PMT_CTRL_WOL_EN_                (0x00000200)  /* R/W */
+#define        PMT_CTRL_ED_EN_                 (0x00000100)  /* R/W */
+#define        PMT_CTRL_PME_TYPE_              (0x00000040)  /* R/W Not Affected by SW Reset */
+#define        PMT_CTRL_WUPS_                  (0x00000030)  /* R/WC */
+#define                PMT_CTRL_WUPS_NOWAKE_           (0x00000000)  /* R/WC */
+#define                PMT_CTRL_WUPS_ED_               (0x00000010)  /* R/WC */
+#define                PMT_CTRL_WUPS_WOL_              (0x00000020)  /* R/WC */
+#define                PMT_CTRL_WUPS_MULTI_            (0x00000030)  /* R/WC */
+#define        PMT_CTRL_PME_IND_               (0x00000008)  /* R/W */
+#define        PMT_CTRL_PME_POL_               (0x00000004)  /* R/W */
+#define        PMT_CTRL_PME_EN_                (0x00000002)  /* R/W Not Affected by SW Reset */
+#define        PMT_CTRL_READY_                 (0x00000001)  /* RO */
+
+#define GPIO_CFG               (0x88)
+#define        GPIO_CFG_LED3_EN_               (0x40000000)  /* R/W */
+#define        GPIO_CFG_LED2_EN_               (0x20000000)  /* R/W */
+#define        GPIO_CFG_LED1_EN_               (0x10000000)  /* R/W */
+#define        GPIO_CFG_GPIO2_INT_POL_         (0x04000000)  /* R/W */
+#define        GPIO_CFG_GPIO1_INT_POL_         (0x02000000)  /* R/W */
+#define        GPIO_CFG_GPIO0_INT_POL_         (0x01000000)  /* R/W */
+#define        GPIO_CFG_EEPR_EN_               (0x00700000)  /* R/W */
+#define        GPIO_CFG_GPIOBUF2_              (0x00040000)  /* R/W */
+#define        GPIO_CFG_GPIOBUF1_              (0x00020000)  /* R/W */
+#define        GPIO_CFG_GPIOBUF0_              (0x00010000)  /* R/W */
+#define        GPIO_CFG_GPIODIR2_              (0x00000400)  /* R/W */
+#define        GPIO_CFG_GPIODIR1_              (0x00000200)  /* R/W */
+#define        GPIO_CFG_GPIODIR0_              (0x00000100)  /* R/W */
+#define        GPIO_CFG_GPIOD4_                (0x00000010)  /* R/W */
+#define        GPIO_CFG_GPIOD3_                (0x00000008)  /* R/W */
+#define        GPIO_CFG_GPIOD2_                (0x00000004)  /* R/W */
+#define        GPIO_CFG_GPIOD1_                (0x00000002)  /* R/W */
+#define        GPIO_CFG_GPIOD0_                (0x00000001)  /* R/W */
+
+#define GPT_CFG                        (0x8C)
+#define        GPT_CFG_TIMER_EN_               (0x20000000)  /* R/W */
+#define        GPT_CFG_GPT_LOAD_               (0x0000FFFF)  /* R/W */
+
+#define GPT_CNT                        (0x90)
+#define        GPT_CNT_GPT_CNT_                (0x0000FFFF)  /* RO */
+
+#define ENDIAN                 (0x98)
+#define FREE_RUN               (0x9C)
+#define RX_DROP                        (0xA0)
+#define MAC_CSR_CMD            (0xA4)
+#define         MAC_CSR_CMD_CSR_BUSY_          (0x80000000)  /* Self Clearing */
+#define         MAC_CSR_CMD_R_NOT_W_           (0x40000000)  /* R/W */
+#define         MAC_CSR_CMD_CSR_ADDR_          (0x000000FF)  /* R/W */
+
+#define MAC_CSR_DATA           (0xA8)
+#define AFC_CFG                        (0xAC)
+#define                AFC_CFG_AFC_HI_                 (0x00FF0000)  /* R/W */
+#define                AFC_CFG_AFC_LO_                 (0x0000FF00)  /* R/W */
+#define                AFC_CFG_BACK_DUR_               (0x000000F0)  /* R/W */
+#define                AFC_CFG_FCMULT_                 (0x00000008)  /* R/W */
+#define                AFC_CFG_FCBRD_                  (0x00000004)  /* R/W */
+#define                AFC_CFG_FCADD_                  (0x00000002)  /* R/W */
+#define                AFC_CFG_FCANY_                  (0x00000001)  /* R/W */
+
+#define E2P_CMD                        (0xB0)
+#define        E2P_CMD_EPC_BUSY_               (0x80000000)  /* Self Clearing */
+#define        E2P_CMD_EPC_CMD_                        (0x70000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_READ_           (0x00000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_EWDS_           (0x10000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_EWEN_           (0x20000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_WRITE_          (0x30000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_WRAL_           (0x40000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_ERASE_          (0x50000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_ERAL_           (0x60000000)  /* R/W */
+#define                E2P_CMD_EPC_CMD_RELOAD_         (0x70000000)  /* R/W */
+#define        E2P_CMD_EPC_TIMEOUT_            (0x00000200)  /* RO */
+#define        E2P_CMD_MAC_ADDR_LOADED_        (0x00000100)  /* RO */
+#define        E2P_CMD_EPC_ADDR_               (0x000000FF)  /* R/W */
+
+#define E2P_DATA               (0xB4)
+#define        E2P_DATA_EEPROM_DATA_           (0x000000FF)  /* R/W */
+/* end of LAN register offsets and bit definitions */
+
+/*
+ ****************************************************************************
+ ****************************************************************************
+ * MAC Control and Status Register (Indirect Address)
+ * Offset (through the MAC_CSR CMD and DATA port)
+ ****************************************************************************
+ ****************************************************************************
+ *
+ */
+#define MAC_CR                 (0x01)  /* R/W */
+
+/* MAC_CR - MAC Control Register */
+#define MAC_CR_RXALL_                  (0x80000000)
+// TODO: delete this bit? It is not described in the data sheet.
+#define MAC_CR_HBDIS_                  (0x10000000)
+#define MAC_CR_RCVOWN_                 (0x00800000)
+#define MAC_CR_LOOPBK_                 (0x00200000)
+#define MAC_CR_FDPX_                   (0x00100000)
+#define MAC_CR_MCPAS_                  (0x00080000)
+#define MAC_CR_PRMS_                   (0x00040000)
+#define MAC_CR_INVFILT_                        (0x00020000)
+#define MAC_CR_PASSBAD_                        (0x00010000)
+#define MAC_CR_HFILT_                  (0x00008000)
+#define MAC_CR_HPFILT_                 (0x00002000)
+#define MAC_CR_LCOLL_                  (0x00001000)
+#define MAC_CR_BCAST_                  (0x00000800)
+#define MAC_CR_DISRTY_                 (0x00000400)
+#define MAC_CR_PADSTR_                 (0x00000100)
+#define MAC_CR_BOLMT_MASK_             (0x000000C0)
+#define MAC_CR_DFCHK_                  (0x00000020)
+#define MAC_CR_TXEN_                   (0x00000008)
+#define MAC_CR_RXEN_                   (0x00000004)
+
+#define ADDRH                  (0x02)    /* R/W mask 0x0000FFFFUL */
+#define ADDRL                  (0x03)    /* R/W mask 0xFFFFFFFFUL */
+#define HASHH                  (0x04)    /* R/W */
+#define HASHL                  (0x05)    /* R/W */
+
+#define MII_ACC                        (0x06)    /* R/W */
+#define MII_ACC_PHY_ADDR_              (0x0000F800)
+#define MII_ACC_MIIRINDA_              (0x000007C0)
+#define MII_ACC_MII_WRITE_             (0x00000002)
+#define MII_ACC_MII_BUSY_              (0x00000001)
+
+#define MII_DATA               (0x07)    /* R/W mask 0x0000FFFFUL */
+
+#define FLOW                   (0x08)    /* R/W */
+#define FLOW_FCPT_                     (0xFFFF0000)
+#define FLOW_FCPASS_                   (0x00000004)
+#define FLOW_FCEN_                     (0x00000002)
+#define FLOW_FCBSY_                    (0x00000001)
+
+#define VLAN1                  (0x09)    /* R/W mask 0x0000FFFFUL */
+#define VLAN1_VTI1_                    (0x0000ffff)
+
+#define VLAN2                  (0x0A)    /* R/W mask 0x0000FFFFUL */
+#define VLAN2_VTI2_                    (0x0000ffff)
+
+#define WUFF                   (0x0B)    /* WO */
+
+#define WUCSR                  (0x0C)    /* R/W */
+#define WUCSR_GUE_                     (0x00000200)
+#define WUCSR_WUFR_                    (0x00000040)
+#define WUCSR_MPR_                     (0x00000020)
+#define WUCSR_WAKE_EN_                 (0x00000004)
+#define WUCSR_MPEN_                    (0x00000002)
+
+/*
+ ****************************************************************************
+ * Chip Specific MII Defines
+ ****************************************************************************
+ *
+ * Phy register offsets and bit definitions
+ *
+ */
+
+#define PHY_MODE_CTRL_STS      ((u32)17)       /* Mode Control/Status Register */
+//#define MODE_CTRL_STS_FASTRIP_         ((u16)0x4000)
+#define MODE_CTRL_STS_EDPWRDOWN_        ((u16)0x2000)
+//#define MODE_CTRL_STS_LOWSQEN_          ((u16)0x0800)
+//#define MODE_CTRL_STS_MDPREBP_          ((u16)0x0400)
+//#define MODE_CTRL_STS_FARLOOPBACK_  ((u16)0x0200)
+//#define MODE_CTRL_STS_FASTEST_          ((u16)0x0100)
+//#define MODE_CTRL_STS_REFCLKEN_         ((u16)0x0010)
+//#define MODE_CTRL_STS_PHYADBP_          ((u16)0x0008)
+//#define MODE_CTRL_STS_FORCE_G_LINK_ ((u16)0x0004)
+#define MODE_CTRL_STS_ENERGYON_                ((u16)0x0002)
+
+#define PHY_INT_SRC                    ((u32)29)
+#define PHY_INT_SRC_ENERGY_ON_                 ((u16)0x0080)
+#define PHY_INT_SRC_ANEG_COMP_                 ((u16)0x0040)
+#define PHY_INT_SRC_REMOTE_FAULT_              ((u16)0x0020)
+#define PHY_INT_SRC_LINK_DOWN_                 ((u16)0x0010)
+#define PHY_INT_SRC_ANEG_LP_ACK_               ((u16)0x0008)
+#define PHY_INT_SRC_PAR_DET_FAULT_             ((u16)0x0004)
+#define PHY_INT_SRC_ANEG_PGRX_                 ((u16)0x0002)
+
+#define PHY_INT_MASK                   ((u32)30)
+#define PHY_INT_MASK_ENERGY_ON_                        ((u16)0x0080)
+#define PHY_INT_MASK_ANEG_COMP_                        ((u16)0x0040)
+#define PHY_INT_MASK_REMOTE_FAULT_             ((u16)0x0020)
+#define PHY_INT_MASK_LINK_DOWN_                        ((u16)0x0010)
+#define PHY_INT_MASK_ANEG_LP_ACK_              ((u16)0x0008)
+#define PHY_INT_MASK_PAR_DET_FAULT_            ((u16)0x0004)
+#define PHY_INT_MASK_ANEG_PGRX_                        ((u16)0x0002)
+
+#define PHY_SPECIAL                    ((u32)31)
+#define PHY_SPECIAL_ANEG_DONE_                 ((u16)0x1000)
+#define PHY_SPECIAL_RES_                       ((u16)0x0040)
+#define PHY_SPECIAL_RES_MASK_                  ((u16)0x0FE1)
+#define PHY_SPECIAL_SPD_                       ((u16)0x001C)
+#define PHY_SPECIAL_SPD_10HALF_                        ((u16)0x0004)
+#define PHY_SPECIAL_SPD_10FULL_                        ((u16)0x0014)
+#define PHY_SPECIAL_SPD_100HALF_               ((u16)0x0008)
+#define PHY_SPECIAL_SPD_100FULL_               ((u16)0x0018)
+
+#define LAN911X_INTERNAL_PHY_ID                (0x0007C000)
+
+/* Chip ID values */
+#define CHIP_9115      0x115
+#define CHIP_9116      0x116
+#define CHIP_9117      0x117
+#define CHIP_9118      0x118
+
+struct chip_id {
+       u16 id;
+       char *name;
+};
+
+static const struct chip_id chip_ids[] =  {
+       { CHIP_9115, "LAN9115" },
+       { CHIP_9116, "LAN9116" },
+       { CHIP_9117, "LAN9117" },
+       { CHIP_9118, "LAN9118" },
+       { 0, NULL },
+};
+
+#define IS_REV_A(x)    ((x & 0xFFFF)==0)
+
+/*
+ * Macros to abstract register access according to the data bus
+ * capabilities.  Please use those and not the in/out primitives.
+ */
+/* FIFO read/write macros */
+#define SMC_PUSH_DATA(p, l)    SMC_outsl( ioaddr, TX_DATA_FIFO, p, (l) >> 2 )
+#define SMC_PULL_DATA(p, l)    SMC_insl ( ioaddr, RX_DATA_FIFO, p, (l) >> 2 )
+#define SMC_SET_TX_FIFO(x)     SMC_outl( x, ioaddr, TX_DATA_FIFO )
+#define SMC_GET_RX_FIFO()      SMC_inl( ioaddr, RX_DATA_FIFO )
+
+
+/* I/O mapped register read/write macros */
+#define SMC_GET_TX_STS_FIFO()          SMC_inl( ioaddr, TX_STATUS_FIFO )
+#define SMC_GET_RX_STS_FIFO()          SMC_inl( ioaddr, RX_STATUS_FIFO )
+#define SMC_GET_RX_STS_FIFO_PEEK()     SMC_inl( ioaddr, RX_STATUS_FIFO_PEEK )
+#define SMC_GET_PN()                   (SMC_inl( ioaddr, ID_REV ) >> 16)
+#define SMC_GET_REV()                  (SMC_inl( ioaddr, ID_REV ) & 0xFFFF)
+#define SMC_GET_IRQ_CFG()              SMC_inl( ioaddr, INT_CFG )
+#define SMC_SET_IRQ_CFG(x)             SMC_outl( x, ioaddr, INT_CFG )
+#define SMC_GET_INT()                  SMC_inl( ioaddr, INT_STS )
+#define SMC_ACK_INT(x)                 SMC_outl( x, ioaddr, INT_STS )
+#define SMC_GET_INT_EN()               SMC_inl( ioaddr, INT_EN )
+#define SMC_SET_INT_EN(x)              SMC_outl( x, ioaddr, INT_EN )
+#define SMC_GET_BYTE_TEST()            SMC_inl( ioaddr, BYTE_TEST )
+#define SMC_SET_BYTE_TEST(x)           SMC_outl( x, ioaddr, BYTE_TEST )
+#define SMC_GET_FIFO_INT()             SMC_inl( ioaddr, FIFO_INT )
+#define SMC_SET_FIFO_INT(x)            SMC_outl( x, ioaddr, FIFO_INT )
+#define SMC_SET_FIFO_TDA(x)                                    \
+       do {                                                    \
+               unsigned long __flags;                          \
+               int __mask;                                     \
+               local_irq_save(__flags);                        \
+               __mask = SMC_GET_FIFO_INT() & ~(0xFF<<24);      \
+               SMC_SET_FIFO_INT( __mask | (x)<<24 );           \
+               local_irq_restore(__flags);                     \
+       } while (0)
+#define SMC_SET_FIFO_TSL(x)                                    \
+       do {                                                    \
+               unsigned long __flags;                          \
+               int __mask;                                     \
+               local_irq_save(__flags);                        \
+               __mask = SMC_GET_FIFO_INT() & ~(0xFF<<16);      \
+               SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<16)); \
+               local_irq_restore(__flags);                     \
+       } while (0)
+#define SMC_SET_FIFO_RSA(x)                                    \
+       do {                                                    \
+               unsigned long __flags;                          \
+               int __mask;                                     \
+               local_irq_save(__flags);                        \
+               __mask = SMC_GET_FIFO_INT() & ~(0xFF<<8);       \
+               SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<8));  \
+               local_irq_restore(__flags);                     \
+       } while (0)
+#define SMC_SET_FIFO_RSL(x)                                    \
+       do {                                                    \
+               unsigned long __flags;                          \
+               int __mask;                                     \
+               local_irq_save(__flags);                        \
+               __mask = SMC_GET_FIFO_INT() & ~0xFF;            \
+               SMC_SET_FIFO_INT( __mask | ((x) & 0xFF));       \
+               local_irq_restore(__flags);                     \
+       } while (0)
+#define SMC_GET_RX_CFG()               SMC_inl( ioaddr, RX_CFG )
+#define SMC_SET_RX_CFG(x)              SMC_outl( x, ioaddr, RX_CFG )
+#define SMC_GET_TX_CFG()               SMC_inl( ioaddr, TX_CFG )
+#define SMC_SET_TX_CFG(x)              SMC_outl( x, ioaddr, TX_CFG )
+#define SMC_GET_HW_CFG()               SMC_inl( ioaddr, HW_CFG )
+#define SMC_SET_HW_CFG(x)              SMC_outl( x, ioaddr, HW_CFG )
+#define SMC_GET_RX_DP_CTRL()           SMC_inl( ioaddr, RX_DP_CTRL )
+#define SMC_SET_RX_DP_CTRL(x)          SMC_outl( x, ioaddr, RX_DP_CTRL )
+#define SMC_GET_PMT_CTRL()             SMC_inl( ioaddr, PMT_CTRL )
+#define SMC_SET_PMT_CTRL(x)            SMC_outl( x, ioaddr, PMT_CTRL )
+#define SMC_GET_GPIO_CFG()             SMC_inl( ioaddr, GPIO_CFG )
+#define SMC_SET_GPIO_CFG(x)            SMC_outl( x, ioaddr, GPIO_CFG )
+#define SMC_GET_RX_FIFO_INF()          SMC_inl( ioaddr, RX_FIFO_INF )
+#define SMC_SET_RX_FIFO_INF(x)         SMC_outl( x, ioaddr, RX_FIFO_INF )
+#define SMC_GET_TX_FIFO_INF()          SMC_inl( ioaddr, TX_FIFO_INF )
+#define SMC_SET_TX_FIFO_INF(x)         SMC_outl( x, ioaddr, TX_FIFO_INF )
+#define SMC_GET_GPT_CFG()              SMC_inl( ioaddr, GPT_CFG )
+#define SMC_SET_GPT_CFG(x)             SMC_outl( x, ioaddr, GPT_CFG )
+#define SMC_GET_RX_DROP()              SMC_inl( ioaddr, RX_DROP )
+#define SMC_SET_RX_DROP(x)             SMC_outl( x, ioaddr, RX_DROP )
+#define SMC_GET_MAC_CMD()              SMC_inl( ioaddr, MAC_CSR_CMD )
+#define SMC_SET_MAC_CMD(x)             SMC_outl( x, ioaddr, MAC_CSR_CMD )
+#define SMC_GET_MAC_DATA()             SMC_inl( ioaddr, MAC_CSR_DATA )
+#define SMC_SET_MAC_DATA(x)            SMC_outl( x, ioaddr, MAC_CSR_DATA )
+#define SMC_GET_AFC_CFG()              SMC_inl( ioaddr, AFC_CFG )
+#define SMC_SET_AFC_CFG(x)             SMC_outl( x, ioaddr, AFC_CFG )
+#define SMC_GET_E2P_CMD()              SMC_inl( ioaddr, E2P_CMD )
+#define SMC_SET_E2P_CMD(x)             SMC_outl( x, ioaddr, E2P_CMD )
+#define SMC_GET_E2P_DATA()             SMC_inl( ioaddr, E2P_DATA )
+#define SMC_SET_E2P_DATA(x)            SMC_outl( x, ioaddr, E2P_DATA )
+
+/* MAC register read/write macros */
+#define SMC_GET_MAC_CSR(a,v)                                           \
+       do {                                                            \
+               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+               SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ |                 \
+                       MAC_CSR_CMD_R_NOT_W_ | (a) );                   \
+               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+               v = SMC_GET_MAC_DATA();                                 \
+       } while (0)
+#define SMC_SET_MAC_CSR(a,v)                                           \
+       do {                                                            \
+               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+               SMC_SET_MAC_DATA(v);                                    \
+               SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | (a) );          \
+               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+       } while (0)
+#define SMC_GET_MAC_CR(x)      SMC_GET_MAC_CSR( MAC_CR, x )
+#define SMC_SET_MAC_CR(x)      SMC_SET_MAC_CSR( MAC_CR, x )
+#define SMC_GET_ADDRH(x)       SMC_GET_MAC_CSR( ADDRH, x )
+#define SMC_SET_ADDRH(x)       SMC_SET_MAC_CSR( ADDRH, x )
+#define SMC_GET_ADDRL(x)       SMC_GET_MAC_CSR( ADDRL, x )
+#define SMC_SET_ADDRL(x)       SMC_SET_MAC_CSR( ADDRL, x )
+#define SMC_GET_HASHH(x)       SMC_GET_MAC_CSR( HASHH, x )
+#define SMC_SET_HASHH(x)       SMC_SET_MAC_CSR( HASHH, x )
+#define SMC_GET_HASHL(x)       SMC_GET_MAC_CSR( HASHL, x )
+#define SMC_SET_HASHL(x)       SMC_SET_MAC_CSR( HASHL, x )
+#define SMC_GET_MII_ACC(x)     SMC_GET_MAC_CSR( MII_ACC, x )
+#define SMC_SET_MII_ACC(x)     SMC_SET_MAC_CSR( MII_ACC, x )
+#define SMC_GET_MII_DATA(x)    SMC_GET_MAC_CSR( MII_DATA, x )
+#define SMC_SET_MII_DATA(x)    SMC_SET_MAC_CSR( MII_DATA, x )
+#define SMC_GET_FLOW(x)                SMC_GET_MAC_CSR( FLOW, x )
+#define SMC_SET_FLOW(x)                SMC_SET_MAC_CSR( FLOW, x )
+#define SMC_GET_VLAN1(x)       SMC_GET_MAC_CSR( VLAN1, x )
+#define SMC_SET_VLAN1(x)       SMC_SET_MAC_CSR( VLAN1, x )
+#define SMC_GET_VLAN2(x)       SMC_GET_MAC_CSR( VLAN2, x )
+#define SMC_SET_VLAN2(x)       SMC_SET_MAC_CSR( VLAN2, x )
+#define SMC_SET_WUFF(x)                SMC_SET_MAC_CSR( WUFF, x )
+#define SMC_GET_WUCSR(x)       SMC_GET_MAC_CSR( WUCSR, x )
+#define SMC_SET_WUCSR(x)       SMC_SET_MAC_CSR( WUCSR, x )
+
+/* PHY register read/write macros */
+#define SMC_GET_MII(a,phy,v)                                   \
+       do {                                                    \
+               u32 __v;                                        \
+               do {                                            \
+                       SMC_GET_MII_ACC(__v);                   \
+               } while ( __v & MII_ACC_MII_BUSY_ );            \
+               SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) |       \
+                       MII_ACC_MII_BUSY_);                     \
+               do {                                            \
+                       SMC_GET_MII_ACC(__v);                   \
+               } while ( __v & MII_ACC_MII_BUSY_ );            \
+               SMC_GET_MII_DATA(v);                            \
+       } while (0)
+#define SMC_SET_MII(a,phy,v)                                   \
+       do {                                                    \
+               u32 __v;                                        \
+               do {                                            \
+                       SMC_GET_MII_ACC(__v);                   \
+               } while ( __v & MII_ACC_MII_BUSY_ );            \
+               SMC_SET_MII_DATA(v);                            \
+               SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) |       \
+                       MII_ACC_MII_BUSY_        |              \
+                       MII_ACC_MII_WRITE_  );                  \
+               do {                                            \
+                       SMC_GET_MII_ACC(__v);                   \
+               } while ( __v & MII_ACC_MII_BUSY_ );            \
+       } while (0)
+#define SMC_GET_PHY_BMCR(phy,x)                SMC_GET_MII( MII_BMCR, phy, x )
+#define SMC_SET_PHY_BMCR(phy,x)                SMC_SET_MII( MII_BMCR, phy, x )
+#define SMC_GET_PHY_BMSR(phy,x)                SMC_GET_MII( MII_BMSR, phy, x )
+#define SMC_GET_PHY_ID1(phy,x)         SMC_GET_MII( MII_PHYSID1, phy, x )
+#define SMC_GET_PHY_ID2(phy,x)         SMC_GET_MII( MII_PHYSID2, phy, x )
+#define SMC_GET_PHY_MII_ADV(phy,x)     SMC_GET_MII( MII_ADVERTISE, phy, x )
+#define SMC_SET_PHY_MII_ADV(phy,x)     SMC_SET_MII( MII_ADVERTISE, phy, x )
+#define SMC_GET_PHY_MII_LPA(phy,x)     SMC_GET_MII( MII_LPA, phy, x )
+#define SMC_SET_PHY_MII_LPA(phy,x)     SMC_SET_MII( MII_LPA, phy, x )
+#define SMC_GET_PHY_CTRL_STS(phy,x)    SMC_GET_MII( PHY_MODE_CTRL_STS, phy, x )
+#define SMC_SET_PHY_CTRL_STS(phy,x)    SMC_SET_MII( PHY_MODE_CTRL_STS, phy, x )
+#define SMC_GET_PHY_INT_SRC(phy,x)     SMC_GET_MII( PHY_INT_SRC, phy, x )
+#define SMC_SET_PHY_INT_SRC(phy,x)     SMC_SET_MII( PHY_INT_SRC, phy, x )
+#define SMC_GET_PHY_INT_MASK(phy,x)    SMC_GET_MII( PHY_INT_MASK, phy, x )
+#define SMC_SET_PHY_INT_MASK(phy,x)    SMC_SET_MII( PHY_INT_MASK, phy, x )
+#define SMC_GET_PHY_SPECIAL(phy,x)     SMC_GET_MII( PHY_SPECIAL, phy, x )
+
+
+
+/* Misc read/write macros */
+
+#ifndef SMC_GET_MAC_ADDR
+#define SMC_GET_MAC_ADDR(addr)                                 \
+       do {                                                    \
+               unsigned int __v;                               \
+                                                               \
+               SMC_GET_MAC_CSR(ADDRL, __v);                    \
+               addr[0] = __v; addr[1] = __v >> 8;              \
+               addr[2] = __v >> 16; addr[3] = __v >> 24;       \
+               SMC_GET_MAC_CSR(ADDRH, __v);                    \
+               addr[4] = __v; addr[5] = __v >> 8;              \
+       } while (0)
+#endif
+
+#define SMC_SET_MAC_ADDR(addr)                                 \
+       do {                                                    \
+                SMC_SET_MAC_CSR(ADDRL,                         \
+                                addr[0] |                      \
+                               (addr[1] << 8) |                \
+                               (addr[2] << 16) |               \
+                               (addr[3] << 24));               \
+                SMC_SET_MAC_CSR(ADDRH, addr[4]|(addr[5] << 8));\
+       } while (0)
+
+
+#define SMC_WRITE_EEPROM_CMD(cmd, addr)                                        \
+       do {                                                            \
+               while (SMC_GET_E2P_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+               SMC_SET_MAC_CMD(MAC_CSR_CMD_R_NOT_W_ | a );             \
+               while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);      \
+       } while (0)
+
+#endif  /* _SMC911X_H_ */
index f86697da04d69f35733f684278f461852973e4cf..6cf16f322ad50df76c15c38eae08c9b1e370dd4f 100644 (file)
@@ -732,12 +732,9 @@ static int ifport;
 struct net_device * __init smc_init(int unit)
 {
        struct net_device *dev = alloc_etherdev(sizeof(struct smc_local));
-       static struct devlist *smcdev = smc_devlist;
+       struct devlist *smcdev = smc_devlist;
        int err = 0;
 
-#ifndef NO_AUTOPROBE
-       smcdev = smc_devlist;
-#endif
        if (!dev)
                return ERR_PTR(-ENODEV);
 
@@ -1607,7 +1604,7 @@ MODULE_PARM_DESC(io, "SMC 99194 I/O base address");
 MODULE_PARM_DESC(irq, "SMC 99194 IRQ number");
 MODULE_PARM_DESC(ifport, "SMC 99194 interface port (0-default, 1-TP, 2-AUI)");
 
-int init_module(void)
+int __init init_module(void)
 {
        if (io == 0)
                printk(KERN_WARNING
index e1be1af51201b67b7f72c6693ce824ca8162027d..bf776125ca38c86bab8e3468085aca9de4941194 100644 (file)
 #define SMC_insb(a, r, p, l)   readsb((a) + (r), p, (l))
 #define SMC_outsb(a, r, p, l)  writesb((a) + (r), p, (l))
 
+#elif  defined(CONFIG_MACH_LOGICPD_PXA270)
+
+#define SMC_CAN_USE_8BIT       0
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      0
+#define SMC_IO_SHIFT           0
+#define SMC_NOWAIT             1
+#define SMC_USE_PXA_DMA                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_insw(a, r, p, l)   readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)  writesw((a) + (r), p, l)
+
 #elif  defined(CONFIG_ARCH_INNOKOM) || \
        defined(CONFIG_MACH_MAINSTONE) || \
        defined(CONFIG_ARCH_PXA_IDP) || \
@@ -242,15 +260,17 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define RPC_LSA_DEFAULT                RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT                RPC_LED_100_10
 
-#elif  defined(CONFIG_MACH_LPD7A400) || defined(CONFIG_MACH_LPD7A404)
+#elif   defined(CONFIG_MACH_LPD79520) \
+     || defined(CONFIG_MACH_LPD7A400) \
+     || defined(CONFIG_MACH_LPD7A404)
 
-/* The LPD7A40X_IOBARRIER is necessary to overcome a mismatch between
- * the way that the CPU handles chip selects and the way that the SMC
- * chip expects the chip select to operate.  Refer to
+/* The LPD7X_IOBARRIER is necessary to overcome a mismatch between the
+ * way that the CPU handles chip selects and the way that the SMC chip
+ * expects the chip select to operate.  Refer to
  * Documentation/arm/Sharp-LH/IOBarrier for details.  The read from
- * IOBARRIER is a byte as a least-common denominator of possible
- * regions to use as the barrier.  It would be wasteful to read 32
- * bits from a byte oriented region.
+ * IOBARRIER is a byte, in order that we read the least-common
+ * denominator.  It would be wasteful to read 32 bits from an 8-bit
+ * accessible region.
  *
  * There is no explicit protection against interrupts intervening
  * between the writew and the IOBARRIER.  In SMC ISR there is a
@@ -269,25 +289,35 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_CAN_USE_16BIT      1
 #define SMC_CAN_USE_32BIT      0
 #define SMC_NOWAIT             0
-#define LPD7A40X_IOBARRIER     readb (IOBARRIER_VIRT)
+#define LPD7X_IOBARRIER                readb (IOBARRIER_VIRT)
 
-#define SMC_inw(a,r)           readw ((void*) ((a) + (r)))
-#define SMC_insw(a,r,p,l)      readsw ((void*) ((a) + (r)), p, l)
-#define SMC_outw(v,a,r)             ({ writew ((v), (a) + (r)); LPD7A40X_IOBARRIER; })
+#define SMC_inw(a,r)\
+   ({ unsigned short v = readw ((void*) ((a) + (r))); LPD7X_IOBARRIER; v; })
+#define SMC_outw(v,a,r)          ({ writew ((v), (a) + (r)); LPD7X_IOBARRIER; })
 
-#define SMC_outsw              LPD7A40X_SMC_outsw
+#define SMC_insw               LPD7_SMC_insw
+static inline void LPD7_SMC_insw (unsigned char* a, int r,
+                                 unsigned char* p, int l)
+{
+       unsigned short* ps = (unsigned short*) p;
+       while (l-- > 0) {
+               *ps++ = readw (a + r);
+               LPD7X_IOBARRIER;
+       }
+}
 
-static inline void LPD7A40X_SMC_outsw(unsigned long a, int r,
-                                    unsigned char* p, int l)
+#define SMC_outsw              LPD7_SMC_outsw
+static inline void LPD7_SMC_outsw (unsigned char* a, int r,
+                                  unsigned char* p, int l)
 {
        unsigned short* ps = (unsigned short*) p;
        while (l-- > 0) {
                writew (*ps++, a + r);
-               LPD7A40X_IOBARRIER;
+               LPD7X_IOBARRIER;
        }
 }
 
-#define SMC_INTERRUPT_PREAMBLE LPD7A40X_IOBARRIER
+#define SMC_INTERRUPT_PREAMBLE LPD7X_IOBARRIER
 
 #define RPC_LSA_DEFAULT                RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT                RPC_LED_100_10
index b2ddd5e793035d3fa12742a7c4b8484662fff7e4..9282b4b0c0229e0f86b6f779c02d52189e34f8e8 100644 (file)
@@ -345,9 +345,9 @@ static int bcm5421_enable_fiber(struct mii_phy* phy)
 
 static int bcm5461_enable_fiber(struct mii_phy* phy)
 {
-        phy_write(phy, MII_NCONFIG, 0xfc0c);
-        phy_write(phy, MII_BMCR, 0x4140);
-        phy_write(phy, MII_NCONFIG, 0xfc0b);
+       phy_write(phy, MII_NCONFIG, 0xfc0c);
+       phy_write(phy, MII_BMCR, 0x4140);
+       phy_write(phy, MII_NCONFIG, 0xfc0b);
        phy_write(phy, MII_BMCR, 0x0140);
 
        return 0;
index 49ad60b726579e8bdf8fdf75cafa264cae44cc2b..b2ddd4522a87b0e070952d3ab55432ccba452011 100644 (file)
@@ -69,8 +69,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.58"
-#define DRV_MODULE_RELDATE     "May 22, 2006"
+#define DRV_MODULE_VERSION     "3.60"
+#define DRV_MODULE_RELDATE     "June 17, 2006"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -229,6 +229,8 @@ static struct pci_device_id tg3_pci_tbl[] = {
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M,
@@ -2965,6 +2967,27 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
        return err;
 }
 
+/* This is called whenever we suspect that the system chipset is re-
+ * ordering the sequence of MMIO to the tx send mailbox. The symptom
+ * is bogus tx completions. We try to recover by setting the
+ * TG3_FLAG_MBOX_WRITE_REORDER flag and resetting the chip later
+ * in the workqueue.
+ */
+static void tg3_tx_recover(struct tg3 *tp)
+{
+       BUG_ON((tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) ||
+              tp->write32_tx_mbox == tg3_write_indirect_mbox);
+
+       printk(KERN_WARNING PFX "%s: The system may be re-ordering memory-"
+              "mapped I/O cycles to the network device, attempting to "
+              "recover. Please report the problem to the driver maintainer "
+              "and include system chipset information.\n", tp->dev->name);
+
+       spin_lock(&tp->lock);
+       tp->tg3_flags |= TG3_FLAG_TX_RECOVERY_PENDING;
+       spin_unlock(&tp->lock);
+}
+
 /* Tigon3 never reports partial packet sends.  So we do not
  * need special logic to handle SKBs that have not had all
  * of their frags sent yet, like SunGEM does.
@@ -2977,9 +3000,13 @@ static void tg3_tx(struct tg3 *tp)
        while (sw_idx != hw_idx) {
                struct tx_ring_info *ri = &tp->tx_buffers[sw_idx];
                struct sk_buff *skb = ri->skb;
-               int i;
+               int i, tx_bug = 0;
+
+               if (unlikely(skb == NULL)) {
+                       tg3_tx_recover(tp);
+                       return;
+               }
 
-               BUG_ON(skb == NULL);
                pci_unmap_single(tp->pdev,
                                 pci_unmap_addr(ri, mapping),
                                 skb_headlen(skb),
@@ -2990,10 +3017,9 @@ static void tg3_tx(struct tg3 *tp)
                sw_idx = NEXT_TX(sw_idx);
 
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-                       BUG_ON(sw_idx == hw_idx);
-
                        ri = &tp->tx_buffers[sw_idx];
-                       BUG_ON(ri->skb != NULL);
+                       if (unlikely(ri->skb != NULL || sw_idx == hw_idx))
+                               tx_bug = 1;
 
                        pci_unmap_page(tp->pdev,
                                       pci_unmap_addr(ri, mapping),
@@ -3004,6 +3030,11 @@ static void tg3_tx(struct tg3 *tp)
                }
 
                dev_kfree_skb(skb);
+
+               if (unlikely(tx_bug)) {
+                       tg3_tx_recover(tp);
+                       return;
+               }
        }
 
        tp->tx_cons = sw_idx;
@@ -3331,6 +3362,11 @@ static int tg3_poll(struct net_device *netdev, int *budget)
        /* run TX completion thread */
        if (sblk->idx[0].tx_consumer != tp->tx_cons) {
                tg3_tx(tp);
+               if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) {
+                       netif_rx_complete(netdev);
+                       schedule_work(&tp->reset_task);
+                       return 0;
+               }
        }
 
        /* run RX thread, within the bounds set by NAPI.
@@ -3391,12 +3427,10 @@ static inline void tg3_full_lock(struct tg3 *tp, int irq_sync)
        if (irq_sync)
                tg3_irq_quiesce(tp);
        spin_lock_bh(&tp->lock);
-       spin_lock(&tp->tx_lock);
 }
 
 static inline void tg3_full_unlock(struct tg3 *tp)
 {
-       spin_unlock(&tp->tx_lock);
        spin_unlock_bh(&tp->lock);
 }
 
@@ -3579,6 +3613,13 @@ static void tg3_reset_task(void *_data)
        restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER;
        tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
 
+       if (tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING) {
+               tp->write32_tx_mbox = tg3_write32_tx_mbox;
+               tp->write32_rx_mbox = tg3_write_flush_reg32;
+               tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
+               tp->tg3_flags &= ~TG3_FLAG_TX_RECOVERY_PENDING;
+       }
+
        tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
        tg3_init_hw(tp, 1);
 
@@ -3718,14 +3759,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        len = skb_headlen(skb);
 
-       /* No BH disabling for tx_lock here.  We are running in BH disabled
-        * context and TX reclaim runs via tp->poll inside of a software
+       /* We are running in BH disabled context with netif_tx_lock
+        * and TX reclaim runs via tp->poll inside of a software
         * interrupt.  Furthermore, IRQ processing runs lockless so we have
         * no IRQ context deadlocks to worry about either.  Rejoice!
         */
-       if (!spin_trylock(&tp->tx_lock))
-               return NETDEV_TX_LOCKED;
-
        if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
                if (!netif_queue_stopped(dev)) {
                        netif_stop_queue(dev);
@@ -3734,7 +3772,6 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
                               "queue awake!\n", dev->name);
                }
-               spin_unlock(&tp->tx_lock);
                return NETDEV_TX_BUSY;
        }
 
@@ -3817,15 +3854,16 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
        tp->tx_prod = entry;
-       if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) {
+       if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) {
+               spin_lock(&tp->tx_lock);
                netif_stop_queue(dev);
                if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
                        netif_wake_queue(tp->dev);
+               spin_unlock(&tp->tx_lock);
        }
 
 out_unlock:
        mmiowb();
-       spin_unlock(&tp->tx_lock);
 
        dev->trans_start = jiffies;
 
@@ -3844,14 +3882,11 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
 
        len = skb_headlen(skb);
 
-       /* No BH disabling for tx_lock here.  We are running in BH disabled
-        * context and TX reclaim runs via tp->poll inside of a software
+       /* We are running in BH disabled context with netif_tx_lock
+        * and TX reclaim runs via tp->poll inside of a software
         * interrupt.  Furthermore, IRQ processing runs lockless so we have
         * no IRQ context deadlocks to worry about either.  Rejoice!
         */
-       if (!spin_trylock(&tp->tx_lock))
-               return NETDEV_TX_LOCKED; 
-
        if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
                if (!netif_queue_stopped(dev)) {
                        netif_stop_queue(dev);
@@ -3860,7 +3895,6 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
                        printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
                               "queue awake!\n", dev->name);
                }
-               spin_unlock(&tp->tx_lock);
                return NETDEV_TX_BUSY;
        }
 
@@ -3998,15 +4032,16 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
        tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
        tp->tx_prod = entry;
-       if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) {
+       if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) {
+               spin_lock(&tp->tx_lock);
                netif_stop_queue(dev);
                if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
                        netif_wake_queue(tp->dev);
+               spin_unlock(&tp->tx_lock);
        }
 
 out_unlock:
        mmiowb();
-       spin_unlock(&tp->tx_lock);
 
        dev->trans_start = jiffies;
 
@@ -4485,9 +4520,8 @@ static void tg3_disable_nvram_access(struct tg3 *tp)
 /* tp->lock is held. */
 static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
 {
-       if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
-               tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
-                             NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
+       tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
+                     NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
 
        if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) {
                switch (kind) {
@@ -4568,13 +4602,12 @@ static int tg3_chip_reset(struct tg3 *tp)
        void (*write_op)(struct tg3 *, u32, u32);
        int i;
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
-               tg3_nvram_lock(tp);
-               /* No matching tg3_nvram_unlock() after this because
-                * chip reset below will undo the nvram lock.
-                */
-               tp->nvram_lock_cnt = 0;
-       }
+       tg3_nvram_lock(tp);
+
+       /* No matching tg3_nvram_unlock() after this because
+        * chip reset below will undo the nvram lock.
+        */
+       tp->nvram_lock_cnt = 0;
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
@@ -4727,20 +4760,25 @@ static int tg3_chip_reset(struct tg3 *tp)
                tw32_f(MAC_MODE, 0);
        udelay(40);
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
-               /* Wait for firmware initialization to complete. */
-               for (i = 0; i < 100000; i++) {
-                       tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
-                       if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
-                               break;
-                       udelay(10);
-               }
-               if (i >= 100000) {
-                       printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
-                              "firmware will not restart magic=%08x\n",
-                              tp->dev->name, val);
-                       return -ENODEV;
-               }
+       /* Wait for firmware initialization to complete. */
+       for (i = 0; i < 100000; i++) {
+               tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+               if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+                       break;
+               udelay(10);
+       }
+
+       /* Chip might not be fitted with firmare.  Some Sun onboard
+        * parts are configured like that.  So don't signal the timeout
+        * of the above loop as an error, but do report the lack of
+        * running firmware once.
+        */
+       if (i >= 100000 &&
+           !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) {
+               tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED;
+
+               printk(KERN_INFO PFX "%s: No firmware running.\n",
+                      tp->dev->name);
        }
 
        if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
@@ -9075,9 +9113,6 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
        int j;
 
-       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
-               return;
-
        tw32_f(GRC_EEPROM_ADDR,
             (EEPROM_ADDR_FSM_RESET |
              (EEPROM_DEFAULT_CLOCK_PERIOD <<
@@ -9210,11 +9245,6 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
 {
        int ret;
 
-       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
-               printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n");
-               return -EINVAL;
-       }
-
        if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
                return tg3_nvram_read_using_eeprom(tp, offset, val);
 
@@ -9447,11 +9477,6 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
 {
        int ret;
 
-       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
-               printk(KERN_ERR PFX "Attempt to do nvram_write on Sun 570X\n");
-               return -EINVAL;
-       }
-
        if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
                tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
                       ~GRC_LCLCTRL_GPIO_OUTPUT1);
@@ -9578,15 +9603,19 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
        pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
                               tp->misc_host_ctrl);
 
+       /* The memory arbiter has to be enabled in order for SRAM accesses
+        * to succeed.  Normally on powerup the tg3 chip firmware will make
+        * sure it is enabled, but other entities such as system netboot
+        * code might disable it.
+        */
+       val = tr32(MEMARB_MODE);
+       tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
+
        tp->phy_id = PHY_ID_INVALID;
        tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
-       /* Do not even try poking around in here on Sun parts.  */
-       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
-               /* All SUN chips are built-in LOMs. */
-               tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
-               return;
-       }
+       /* Assume an onboard device by default.  */
+       tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
 
        tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
        if (val == NIC_SRAM_DATA_SIG_MAGIC) {
@@ -9686,6 +9715,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 
                if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)
                        tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
+               else
+                       tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT;
 
                if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
                        tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
@@ -9834,16 +9865,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
        int i;
        u32 magic;
 
-       if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
-               /* Sun decided not to put the necessary bits in the
-                * NVRAM of their onboard tg3 parts :(
-                */
-               strcpy(tp->board_part_number, "Sun 570X");
-               return;
-       }
-
        if (tg3_nvram_read_swab(tp, 0x0, &magic))
-               return;
+               goto out_not_found;
 
        if (magic == TG3_EEPROM_MAGIC) {
                for (i = 0; i < 256; i += 4) {
@@ -9874,6 +9897,9 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
                                        break;
                                msleep(1);
                        }
+                       if (!(tmp16 & 0x8000))
+                               goto out_not_found;
+
                        pci_read_config_dword(tp->pdev, vpd_cap + PCI_VPD_DATA,
                                              &tmp);
                        tmp = cpu_to_le32(tmp);
@@ -9965,37 +9991,6 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
        }
 }
 
-#ifdef CONFIG_SPARC64
-static int __devinit tg3_is_sun_570X(struct tg3 *tp)
-{
-       struct pci_dev *pdev = tp->pdev;
-       struct pcidev_cookie *pcp = pdev->sysdata;
-
-       if (pcp != NULL) {
-               int node = pcp->prom_node;
-               u32 venid;
-               int err;
-
-               err = prom_getproperty(node, "subsystem-vendor-id",
-                                      (char *) &venid, sizeof(venid));
-               if (err == 0 || err == -1)
-                       return 0;
-               if (venid == PCI_VENDOR_ID_SUN)
-                       return 1;
-
-               /* TG3 chips onboard the SunBlade-2500 don't have the
-                * subsystem-vendor-id set to PCI_VENDOR_ID_SUN but they
-                * are distinguishable from non-Sun variants by being
-                * named "network" by the firmware.  Non-Sun cards will
-                * show up as being named "ethernet".
-                */
-               if (!strcmp(pcp->prom_name, "network"))
-                       return 1;
-       }
-       return 0;
-}
-#endif
-
 static int __devinit tg3_get_invariants(struct tg3 *tp)
 {
        static struct pci_device_id write_reorder_chipsets[] = {
@@ -10012,11 +10007,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        u16 pci_cmd;
        int err;
 
-#ifdef CONFIG_SPARC64
-       if (tg3_is_sun_570X(tp))
-               tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
-#endif
-
        /* Force memory write invalidate off.  If we leave it on,
         * then on 5700_BX chips we have to enable a workaround.
         * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
@@ -10312,8 +10302,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (tp->write32 == tg3_write_indirect_reg32 ||
            ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
             (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
-             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) ||
-           (tp->tg3_flags2 & TG3_FLG2_SUN_570X))
+             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)))
                tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
 
        /* Get eeprom hw config before calling tg3_set_power_state().
@@ -10594,8 +10583,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 #endif
 
        mac_offset = 0x7c;
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
-            !(tp->tg3_flags & TG3_FLG2_SUN_570X)) ||
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
            (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
                if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
                        mac_offset = 0xcc;
@@ -10622,8 +10610,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
        }
        if (!addr_ok) {
                /* Next, try NVRAM. */
-               if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
-                   !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
+               if (!tg3_nvram_read(tp, mac_offset + 0, &hi) &&
                    !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
                        dev->dev_addr[0] = ((hi >> 16) & 0xff);
                        dev->dev_addr[1] = ((hi >> 24) & 0xff);
@@ -11291,7 +11278,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
-       dev->features |= NETIF_F_LLTX;
 #if TG3_VLAN_TAG_USED
        dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
        dev->vlan_rx_register = tg3_vlan_rx_register;
index 0e29b885d449d7cafcdcbae7f8311b9df39796a6..8209da5dd15fee447c2b989a11215b2f75a8e21b 100644 (file)
@@ -2074,12 +2074,22 @@ struct tg3 {
 
        /* SMP locking strategy:
         *
-        * lock: Held during all operations except TX packet
-        *       processing.
+        * lock: Held during reset, PHY access, timer, and when
+        *       updating tg3_flags and tg3_flags2.
         *
-        * tx_lock: Held during tg3_start_xmit and tg3_tx
+        * tx_lock: Held during tg3_start_xmit and tg3_tx only
+        *          when calling netif_[start|stop]_queue.
+        *          tg3_start_xmit is protected by netif_tx_lock.
         *
         * Both of these locks are to be held with BH safety.
+        *
+        * Because the IRQ handler, tg3_poll, and tg3_start_xmit
+        * are running lockless, it is necessary to completely
+        * quiesce the chip with tg3_netif_stop and tg3_full_lock
+        * before reconfiguring the device.
+        *
+        * indirect_lock: Held when accessing registers indirectly
+        *                with IRQ disabling.
         */
        spinlock_t                      lock;
        spinlock_t                      indirect_lock;
@@ -2155,11 +2165,7 @@ struct tg3 {
 #define TG3_FLAG_ENABLE_ASF            0x00000020
 #define TG3_FLAG_5701_REG_WRITE_BUG    0x00000040
 #define TG3_FLAG_POLL_SERDES           0x00000080
-#if defined(CONFIG_X86)
 #define TG3_FLAG_MBOX_WRITE_REORDER    0x00000100
-#else
-#define TG3_FLAG_MBOX_WRITE_REORDER    0       /* disables code too */
-#endif
 #define TG3_FLAG_PCIX_TARGET_HWBUG     0x00000200
 #define TG3_FLAG_WOL_SPEED_100MB       0x00000400
 #define TG3_FLAG_WOL_ENABLE            0x00000800
@@ -2172,6 +2178,7 @@ struct tg3 {
 #define TG3_FLAG_PCI_HIGH_SPEED                0x00040000
 #define TG3_FLAG_PCI_32BIT             0x00080000
 #define TG3_FLAG_SRAM_USE_CONFIG       0x00100000
+#define TG3_FLAG_TX_RECOVERY_PENDING   0x00200000
 #define TG3_FLAG_SERDES_WOL_CAP                0x00400000
 #define TG3_FLAG_JUMBO_RING_ENABLE     0x00800000
 #define TG3_FLAG_10_100_ONLY           0x01000000
@@ -2184,7 +2191,7 @@ struct tg3 {
 #define TG3_FLAG_INIT_COMPLETE         0x80000000
        u32                             tg3_flags2;
 #define TG3_FLG2_RESTART_TIMER         0x00000001
-#define TG3_FLG2_SUN_570X              0x00000002
+/*                                     0x00000002 available */
 #define TG3_FLG2_NO_ETH_WIRE_SPEED     0x00000004
 #define TG3_FLG2_IS_5788               0x00000008
 #define TG3_FLG2_MAX_RXPEND_64         0x00000010
@@ -2216,6 +2223,7 @@ struct tg3 {
 #define TG3_FLG2_HW_TSO                        (TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2)
 #define TG3_FLG2_1SHOT_MSI             0x10000000
 #define TG3_FLG2_PHY_JITTER_BUG                0x20000000
+#define TG3_FLG2_NO_FWARE_REPORTED     0x40000000
 
        u32                             split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ                3
index e3dd144d326ba1212a81d97afd6212a9a2b1631d..5f743b972949930929335ed20fb55288d47b1dd1 100644 (file)
@@ -227,12 +227,12 @@ enum {
        SROMC0InfoLeaf          = 27,
        MediaBlockMask          = 0x3f,
        MediaCustomCSRs         = (1 << 6),
-       
+
        /* PCIPM bits */
        PM_Sleep                = (1 << 31),
        PM_Snooze               = (1 << 30),
        PM_Mask                 = PM_Sleep | PM_Snooze,
-       
+
        /* SIAStatus bits */
        NWayState               = (1 << 14) | (1 << 13) | (1 << 12),
        NWayRestart             = (1 << 12),
@@ -858,7 +858,7 @@ static void de_stop_rxtx (struct de_private *de)
                        return;
                cpu_relax();
        }
-       
+
        printk(KERN_WARNING "%s: timeout expired stopping DMA\n", de->dev->name);
 }
 
@@ -931,7 +931,7 @@ static void de_set_media (struct de_private *de)
                macmode |= FullDuplex;
        else
                macmode &= ~FullDuplex;
-       
+
        if (netif_msg_link(de)) {
                printk(KERN_INFO "%s: set link %s\n"
                       KERN_INFO "%s:    mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
@@ -966,9 +966,9 @@ static void de21040_media_timer (unsigned long data)
        u32 status = dr32(SIAStatus);
        unsigned int carrier;
        unsigned long flags;
-       
+
        carrier = (status & NetCxnErr) ? 0 : 1;
-               
+
        if (carrier) {
                if (de->media_type != DE_MEDIA_AUI && (status & LinkFailStatus))
                        goto no_link_yet;
@@ -985,7 +985,7 @@ static void de21040_media_timer (unsigned long data)
                return;
        }
 
-       de_link_down(de);       
+       de_link_down(de);
 
        if (de->media_lock)
                return;
@@ -1039,7 +1039,7 @@ static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media)
                        return 0;
                break;
        }
-       
+
        return 1;
 }
 
@@ -1050,9 +1050,9 @@ static void de21041_media_timer (unsigned long data)
        u32 status = dr32(SIAStatus);
        unsigned int carrier;
        unsigned long flags;
-       
+
        carrier = (status & NetCxnErr) ? 0 : 1;
-               
+
        if (carrier) {
                if ((de->media_type == DE_MEDIA_TP_AUTO ||
                     de->media_type == DE_MEDIA_TP ||
@@ -1072,7 +1072,7 @@ static void de21041_media_timer (unsigned long data)
                return;
        }
 
-       de_link_down(de);       
+       de_link_down(de);
 
        /* if media type locked, don't switch media */
        if (de->media_lock)
@@ -1124,7 +1124,7 @@ static void de21041_media_timer (unsigned long data)
                u32 next_states[] = { DE_MEDIA_AUI, DE_MEDIA_BNC, DE_MEDIA_TP_AUTO };
                de_next_media(de, next_states, ARRAY_SIZE(next_states));
        }
-       
+
 set_media:
        spin_lock_irqsave(&de->lock, flags);
        de_stop_rxtx(de);
@@ -1148,7 +1148,7 @@ static void de_media_interrupt (struct de_private *de, u32 status)
                mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK);
                return;
        }
-       
+
        BUG_ON(!(status & LinkFail));
 
        if (netif_carrier_ok(de->dev)) {
@@ -1227,7 +1227,7 @@ static int de_init_hw (struct de_private *de)
        int rc;
 
        de_adapter_wake(de);
-       
+
        macmode = dr32(MacMode) & ~MacModeClear;
 
        rc = de_reset_mac(de);
@@ -1413,7 +1413,7 @@ static int de_close (struct net_device *dev)
        netif_stop_queue(dev);
        netif_carrier_off(dev);
        spin_unlock_irqrestore(&de->lock, flags);
-       
+
        free_irq(dev->irq, dev);
 
        de_free_rings(de);
@@ -1441,7 +1441,7 @@ static void de_tx_timeout (struct net_device *dev)
 
        spin_unlock_irq(&de->lock);
        enable_irq(dev->irq);
-               
+
        /* Update the error counts. */
        __de_get_stats(de);
 
@@ -1451,7 +1451,7 @@ static void de_tx_timeout (struct net_device *dev)
        de_init_rings(de);
 
        de_init_hw(de);
-       
+
        netif_wake_queue(dev);
 }
 
@@ -1459,7 +1459,7 @@ static void __de_get_regs(struct de_private *de, u8 *buf)
 {
        int i;
        u32 *rbuf = (u32 *)buf;
-       
+
        /* read all CSRs */
        for (i = 0; i < DE_NUM_REGS; i++)
                rbuf[i] = dr32(i * 8);
@@ -1474,7 +1474,7 @@ static int __de_get_settings(struct de_private *de, struct ethtool_cmd *ecmd)
        ecmd->transceiver = XCVR_INTERNAL;
        ecmd->phy_address = 0;
        ecmd->advertising = de->media_advertise;
-       
+
        switch (de->media_type) {
        case DE_MEDIA_AUI:
                ecmd->port = PORT_AUI;
@@ -1489,7 +1489,7 @@ static int __de_get_settings(struct de_private *de, struct ethtool_cmd *ecmd)
                ecmd->speed = SPEED_10;
                break;
        }
-       
+
        if (dr32(MacMode) & FullDuplex)
                ecmd->duplex = DUPLEX_FULL;
        else
@@ -1529,7 +1529,7 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd)
        if (ecmd->autoneg == AUTONEG_ENABLE &&
            (!(ecmd->advertising & ADVERTISED_Autoneg)))
                return -EINVAL;
-       
+
        switch (ecmd->port) {
        case PORT_AUI:
                new_media = DE_MEDIA_AUI;
@@ -1554,22 +1554,22 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd)
                        return -EINVAL;
                break;
        }
-       
+
        media_lock = (ecmd->autoneg == AUTONEG_ENABLE) ? 0 : 1;
-       
+
        if ((new_media == de->media_type) &&
            (media_lock == de->media_lock) &&
            (ecmd->advertising == de->media_advertise))
                return 0; /* nothing to change */
-           
+
        de_link_down(de);
        de_stop_rxtx(de);
-       
+
        de->media_type = new_media;
        de->media_lock = media_lock;
        de->media_advertise = ecmd->advertising;
        de_set_media(de);
-       
+
        return 0;
 }
 
@@ -1817,7 +1817,7 @@ static void __init de21041_get_srom_info (struct de_private *de)
        case 0x0204:  de->media_type = DE_MEDIA_TP_FD; break;
        default: de->media_type = DE_MEDIA_TP_AUTO; break;
        }
-       
+
        if (netif_msg_probe(de))
                printk(KERN_INFO "de%d: SROM leaf offset %u, default media %s\n",
                       de->board_idx, ofs,
@@ -1886,7 +1886,7 @@ static void __init de21041_get_srom_info (struct de_private *de)
                                       de->media[idx].csr13,
                                       de->media[idx].csr14,
                                       de->media[idx].csr15);
-                                      
+
                } else if (netif_msg_probe(de))
                        printk("\n");
 
@@ -2118,7 +2118,7 @@ static int de_suspend (struct pci_dev *pdev, pm_message_t state)
 
                spin_unlock_irq(&de->lock);
                enable_irq(dev->irq);
-               
+
                /* Update the error counts. */
                __de_get_stats(de);
 
index f56094102042fabbe7f944b50c72fa03dfd1e438..da8bd0d62a3fcaf57540558ba487f78500a45076 100644 (file)
     Digital Semiconductor   SROM   Specification.    The  driver   currently
     recognises the following chips:
 
-        DC21040  (no SROM) 
-       DC21041[A]  
-       DC21140[A] 
-       DC21142 
-       DC21143 
+        DC21040  (no SROM)
+       DC21041[A]
+       DC21140[A]
+       DC21142
+       DC21143
 
     So far the driver is known to work with the following cards:
 
@@ -55,7 +55,7 @@
        SMC8432
        SMC9332 (w/new SROM)
        ZNYX31[45]
-       ZNYX346 10/100 4 port (can act as a 10/100 bridge!) 
+       ZNYX346 10/100 4 port (can act as a 10/100 bridge!)
 
     The driver has been tested on a relatively busy network using the DE425,
     DE434, DE435 and DE500 cards and benchmarked with 'ttcp': it transferred
     loading by:
 
                    insmod de4x5 io=0xghh           where g = bus number
-                                                       hh = device number   
+                                                       hh = device number
 
        NB: autoprobing for modules is now supported by default. You may just
            use:
     4) if you are wanting to add a new  card, goto 5. Otherwise, recompile a
     kernel with the de4x5 configuration turned off and reboot.
     5) insmod de4x5 [io=0xghh]
-    6) run the net startup bits for your new eth?? interface(s) manually 
-    (usually /etc/rc.inet[12] at boot time). 
+    6) run the net startup bits for your new eth?? interface(s) manually
+    (usually /etc/rc.inet[12] at boot time).
     7) enjoy!
 
-    To unload a module, turn off the associated interface(s) 
+    To unload a module, turn off the associated interface(s)
     'ifconfig eth?? down' then 'rmmod de4x5'.
 
     Automedia detection is included so that in  principal you can disconnect
     By  default,  the driver will  now   autodetect any  DECchip based card.
     Should you have a need to restrict the driver to DIGITAL only cards, you
     can compile with a  DEC_ONLY define, or if  loading as a module, use the
-    'dec_only=1'  parameter. 
+    'dec_only=1'  parameter.
 
     I've changed the timing routines to  use the kernel timer and scheduling
     functions  so that the  hangs  and other assorted problems that occurred
     following parameters are allowed:
 
             fdx        for full duplex
-           autosense  to set the media/speed; with the following 
+           autosense  to set the media/speed; with the following
                       sub-parameters:
                       TP, TP_NW, BNC, AUI, BNC_AUI, 100Mb, 10Mb, AUTO
 
     this  automatically  or include  #define DE4X5_FORCE_EISA  on or  before
     line 1040 in the driver.
 
-    TO DO: 
+    TO DO:
     ------
 
     Revision History
     ----------------
 
     Version   Date        Description
-  
+
       0.1     17-Nov-94   Initial writing. ALPHA code release.
       0.2     13-Jan-95   Added PCI support for DE435's.
       0.21    19-Jan-95   Added auto media detection.
                          Add request/release_region code.
                          Add loadable modules support for PCI.
                          Clean up loadable modules support.
-      0.23    28-Feb-95   Added DC21041 and DC21140 support. 
+      0.23    28-Feb-95   Added DC21041 and DC21140 support.
                           Fix missed frame counter value and initialisation.
                          Fixed EISA probe.
       0.24    11-Apr-95   Change delay routine to use <linux/udelay>.
                           Add kernel timer code (h/w is too flaky).
                          Add MII based PHY autosense.
                          Add new multicasting code.
-                         Add new autosense algorithms for media/mode 
+                         Add new autosense algorithms for media/mode
                          selection using kernel scheduling/timing.
                          Re-formatted.
                          Made changes suggested by <jeff@router.patch.net>:
                           Add Accton to the list of broken cards.
                          Fix TX under-run bug for non DC21140 chips.
                          Fix boot command probe bug in alloc_device() as
-                          reported by <koen.gadeyne@barco.com> and 
+                          reported by <koen.gadeyne@barco.com> and
                           <orava@nether.tky.hut.fi>.
                          Add cache locks to prevent a race condition as
-                          reported by <csd@microplex.com> and 
+                          reported by <csd@microplex.com> and
                           <baba@beckman.uiuc.edu>.
                          Upgraded alloc_device() code.
       0.431  28-Jun-96    Fix potential bug in queue_pkt() from discussion
                            with a loopback packet.
       0.442   9-Sep-96    Include AUI in dc21041 media printout. Bug reported
                            by <bhat@mundook.cs.mu.OZ.AU>
-      0.45    8-Dec-96    Include endian functions for PPC use, from work 
+      0.45    8-Dec-96    Include endian functions for PPC use, from work
                            by <cort@cs.nmt.edu> and <g.thomas@opengroup.org>.
       0.451  28-Dec-96    Added fix to allow autoprobe for modules after
                            suggestion from <mjacob@feral.com>.
                           <paubert@iram.es>.
       0.52   26-Apr-97    Some changes may not credit the right people -
                            a disk crash meant I lost some mail.
-                         Change RX interrupt routine to drop rather than 
-                          defer packets to avoid hang reported by 
+                         Change RX interrupt routine to drop rather than
+                          defer packets to avoid hang reported by
                           <g.thomas@opengroup.org>.
                          Fix srom_exec() to return for COMPACT and type 1
                           infoblocks.
                          Added DC21142 and DC21143 functions.
                          Added byte counters from <phil@tazenda.demon.co.uk>
-                         Added SA_INTERRUPT temporary fix from 
+                         Added SA_INTERRUPT temporary fix from
                           <mjacob@feral.com>.
       0.53   12-Nov-97    Fix the *_probe() to include 'eth??' name during
                            module load: bug reported by
                          Make above search independent of BIOS device scan
                           direction.
                          Completed DC2114[23] autosense functions.
-      0.531  21-Dec-97    Fix DE500-XA 100Mb/s bug reported by 
+      0.531  21-Dec-97    Fix DE500-XA 100Mb/s bug reported by
                            <robin@intercore.com
                          Fix type1_infoblock() bug introduced in 0.53, from
-                          problem reports by 
+                          problem reports by
                           <parmee@postecss.ncrfran.france.ncr.com> and
                           <jo@ice.dillingen.baynet.de>.
                          Added argument list to set up each board from either
                          Added generic MII PHY functionality to deal with
                           newer PHY chips.
                          Fix the mess in 2.1.67.
-      0.532   5-Jan-98    Fix bug in mii_get_phy() reported by 
+      0.532   5-Jan-98    Fix bug in mii_get_phy() reported by
                            <redhat@cococo.net>.
                           Fix bug in pci_probe() for 64 bit systems reported
                           by <belliott@accessone.com>.
                           version. I hope nothing is broken...
                          Add TX done interrupt modification from suggestion
                           by <Austin.Donnelly@cl.cam.ac.uk>.
-                         Fix is_anc_capable() bug reported by 
+                         Fix is_anc_capable() bug reported by
                           <Austin.Donnelly@cl.cam.ac.uk>.
                          Fix type[13]_infoblock() bug: during MII search, PHY
                           lp->rst not run because lp->ibn not initialised -
                          Add an_exception() for old ZYNX346 and fix compile
                           warning on PPC & SPARC, from <ecd@skynet.be>.
                          Fix lastPCI to correctly work with compiled in
-                          kernels and modules from bug report by 
+                          kernels and modules from bug report by
                           <Zlatko.Calusic@CARNet.hr> et al.
       0.542  15-Sep-98    Fix dc2114x_autoconf() to stop multiple messages
                            when media is unconnected.
       0.544   8-May-99    Fix for buggy SROM in Motorola embedded boards using
                            a 21143 by <mmporter@home.com>.
                          Change PCI/EISA bus probing order.
-      0.545  28-Nov-99    Further Moto SROM bug fix from 
+      0.545  28-Nov-99    Further Moto SROM bug fix from
                            <mporter@eng.mcd.mot.com>
                           Remove double checking for DEBUG_RX in de4x5_dbg_rx()
                           from report by <geert@linux-m68k.org>
                            variable 'pb', on a non de4x5 PCI device, in this
                            case a PCI bridge (DEC chip 21152). The value of
                            'pb' is now only initialized if a de4x5 chip is
-                           present. 
-                           <france@handhelds.org>  
+                           present.
+                           <france@handhelds.org>
       0.547  08-Nov-01    Use library crc32 functions by <Matt_Domsch@dell.com>
       0.548  30-Aug-03    Big 2.6 cleanup. Ported to PCI/EISA probing and
                            generic DMA APIs. Fixed DE425 support on Alpha.
@@ -584,7 +584,7 @@ static int de4x5_debug = (DEBUG_MEDIA | DEBUG_VERSION);
 
 /*
 ** Allow per adapter set up. For modules this is simply a command line
-** parameter, e.g.: 
+** parameter, e.g.:
 ** insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'.
 **
 ** For a compiled in driver, place e.g.
@@ -655,7 +655,7 @@ static c_char *de4x5_signatures[] = DE4X5_SIGNATURE;
 ** Memory Alignment. Each descriptor is 4 longwords long. To force a
 ** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
 ** DESC_ALIGN. ALIGN aligns the start address of the private memory area
-** and hence the RX descriptor ring's first entry. 
+** and hence the RX descriptor ring's first entry.
 */
 #define DE4X5_ALIGN4      ((u_long)4 - 1)     /* 1 longword align */
 #define DE4X5_ALIGN8      ((u_long)8 - 1)     /* 2 longword align */
@@ -1081,8 +1081,8 @@ static int (*dc_infoblock[])(struct net_device *dev, u_char, u_char *) = {
     mdelay(2);                           /* Wait for 2ms */\
 }
 
-\f
-static int __devinit 
+
+static int __devinit
 de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
 {
     char name[DE4X5_NAME_LENGTH + 1];
@@ -1102,12 +1102,12 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
     mdelay(10);
 
     RESET_DE4X5;
-    
+
     if ((inl(DE4X5_STS) & (STS_TS | STS_RS)) != 0) {
        return -ENXIO;                       /* Hardware could not reset */
     }
-    
-    /* 
+
+    /*
     ** Now find out what kind of DC21040/DC21041/DC21140 board we have.
     */
     lp->useSROM = FALSE;
@@ -1116,21 +1116,21 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
     } else {
        EISA_signature(name, gendev);
     }
-    
+
     if (*name == '\0') {                     /* Not found a board signature */
        return -ENXIO;
     }
-    
+
     dev->base_addr = iobase;
     printk ("%s: %s at 0x%04lx", gendev->bus_id, name, iobase);
-    
+
     printk(", h/w address ");
     status = get_hw_addr(dev);
     for (i = 0; i < ETH_ALEN - 1; i++) {     /* get the ethernet addr. */
        printk("%2.2x:", dev->dev_addr[i]);
     }
     printk("%2.2x,\n", dev->dev_addr[i]);
-    
+
     if (status != 0) {
        printk("      which has an Ethernet PROM CRC error.\n");
        return -ENXIO;
@@ -1171,10 +1171,10 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
        }
 
        lp->tx_ring = lp->rx_ring + NUM_RX_DESC;
-           
+
        /*
        ** Set up the RX descriptor ring (Intels)
-       ** Allocate contiguous receive buffers, long word aligned (Alphas) 
+       ** Allocate contiguous receive buffers, long word aligned (Alphas)
        */
 #if !defined(__alpha__) && !defined(__powerpc__) && !defined(__sparc_v9__) && !defined(DE4X5_DO_MEMCPY)
        for (i=0; i<NUM_RX_DESC; i++) {
@@ -1210,7 +1210,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
 
        lp->rxRingSize = NUM_RX_DESC;
        lp->txRingSize = NUM_TX_DESC;
-           
+
        /* Write the end of list marker to the descriptor lists */
        lp->rx_ring[lp->rxRingSize - 1].des1 |= cpu_to_le32(RD_RER);
        lp->tx_ring[lp->txRingSize - 1].des1 |= cpu_to_le32(TD_TER);
@@ -1219,7 +1219,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
        outl(lp->dma_rings, DE4X5_RRBA);
        outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
             DE4X5_TRBA);
-           
+
        /* Initialise the IRQ mask and Enable/Disable */
        lp->irq_mask = IMR_RIM | IMR_TIM | IMR_TUM | IMR_UNM;
        lp->irq_en   = IMR_NIM | IMR_AIM;
@@ -1252,7 +1252,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
        if ((lp->chipset != DC21040) && (lp->chipset != DC21041)) {
            mii_get_phy(dev);
        }
-       
+
 #ifndef __sparc_v9__
        printk("      and requires IRQ%d (provided by %s).\n", dev->irq,
 #else
@@ -1260,11 +1260,11 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
 #endif
               ((lp->bus == PCI) ? "PCI BIOS" : "EISA CNFG"));
     }
-    
+
     if (de4x5_debug & DEBUG_VERSION) {
        printk(version);
     }
-    
+
     /* The DE4X5-specific entries in the device structure. */
     SET_MODULE_OWNER(dev);
     SET_NETDEV_DEV(dev, gendev);
@@ -1274,23 +1274,23 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
     dev->get_stats = &de4x5_get_stats;
     dev->set_multicast_list = &set_multicast_list;
     dev->do_ioctl = &de4x5_ioctl;
-    
+
     dev->mem_start = 0;
-    
+
     /* Fill in the generic fields of the device structure. */
     if ((status = register_netdev (dev))) {
            dma_free_coherent (gendev, lp->dma_size,
                               lp->rx_ring, lp->dma_rings);
            return status;
     }
-    
+
     /* Let the adapter sleep to save power */
     yawn(dev, SLEEP);
-    
+
     return status;
 }
 
-\f
+
 static int
 de4x5_open(struct net_device *dev)
 {
@@ -1312,15 +1312,15 @@ de4x5_open(struct net_device *dev)
     */
     yawn(dev, WAKEUP);
 
-    /* 
-    ** Re-initialize the DE4X5... 
+    /*
+    ** Re-initialize the DE4X5...
     */
     status = de4x5_init(dev);
     spin_lock_init(&lp->lock);
     lp->state = OPEN;
     de4x5_dbg_open(dev);
-    
-    if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ, 
+
+    if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ,
                                                     lp->adapter_name, dev)) {
        printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq);
        if (request_irq(dev->irq, de4x5_interrupt, SA_INTERRUPT | SA_SHIRQ,
@@ -1340,11 +1340,11 @@ de4x5_open(struct net_device *dev)
 
     lp->interrupt = UNMASK_INTERRUPTS;
     dev->trans_start = jiffies;
-    
+
     START_DE4X5;
-       
+
     de4x5_setup_intr(dev);
-    
+
     if (de4x5_debug & DEBUG_OPEN) {
        printk("\tsts:  0x%08x\n", inl(DE4X5_STS));
        printk("\tbmr:  0x%08x\n", inl(DE4X5_BMR));
@@ -1355,7 +1355,7 @@ de4x5_open(struct net_device *dev)
        printk("\tstrr: 0x%08x\n", inl(DE4X5_STRR));
        printk("\tsigr: 0x%08x\n", inl(DE4X5_SIGR));
     }
-    
+
     return status;
 }
 
@@ -1369,15 +1369,15 @@ de4x5_open(struct net_device *dev)
 */
 static int
 de4x5_init(struct net_device *dev)
-{  
+{
     /* Lock out other processes whilst setting up the hardware */
     netif_stop_queue(dev);
-    
+
     de4x5_sw_reset(dev);
-    
+
     /* Autoconfigure the connected port */
     autoconf_media(dev);
-    
+
     return 0;
 }
 
@@ -1388,7 +1388,7 @@ de4x5_sw_reset(struct net_device *dev)
     u_long iobase = dev->base_addr;
     int i, j, status = 0;
     s32 bmr, omr;
-    
+
     /* Select the MII or SRL port now and RESET the MAC */
     if (!lp->useSROM) {
        if (lp->phy[lp->active].id != 0) {
@@ -1399,7 +1399,7 @@ de4x5_sw_reset(struct net_device *dev)
        de4x5_switch_mac_port(dev);
     }
 
-    /* 
+    /*
     ** Set the programmable burst length to 8 longwords for all the DC21140
     ** Fasternet chips and 4 longwords for all others: DMA errors result
     ** without these values. Cache align 16 long.
@@ -1416,23 +1416,23 @@ de4x5_sw_reset(struct net_device *dev)
     outl(lp->dma_rings, DE4X5_RRBA);
     outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
         DE4X5_TRBA);
-    
+
     lp->rx_new = lp->rx_old = 0;
     lp->tx_new = lp->tx_old = 0;
-    
+
     for (i = 0; i < lp->rxRingSize; i++) {
        lp->rx_ring[i].status = cpu_to_le32(R_OWN);
     }
-    
+
     for (i = 0; i < lp->txRingSize; i++) {
        lp->tx_ring[i].status = cpu_to_le32(0);
     }
-    
+
     barrier();
 
     /* Build the setup frame depending on filtering mode */
     SetMulticastFilter(dev);
-    
+
     load_packet(dev, lp->setup_frame, PERFECT_F|TD_SET|SETUP_FRAME_LEN, (struct sk_buff *)1);
     outl(omr|OMR_ST, DE4X5_OMR);
 
@@ -1445,18 +1445,18 @@ de4x5_sw_reset(struct net_device *dev)
     outl(omr, DE4X5_OMR);                        /* Stop everything! */
 
     if (j == 0) {
-       printk("%s: Setup frame timed out, status %08x\n", dev->name, 
+       printk("%s: Setup frame timed out, status %08x\n", dev->name,
               inl(DE4X5_STS));
        status = -EIO;
     }
-    
+
     lp->tx_new = (++lp->tx_new) % lp->txRingSize;
     lp->tx_old = lp->tx_new;
 
     return status;
 }
 
-/* 
+/*
 ** Writes a socket buffer address to the next available transmit descriptor.
 */
 static int
@@ -1469,9 +1469,9 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
 
     netif_stop_queue(dev);
     if (lp->tx_enable == NO) {                   /* Cannot send for now */
-       return -1;                                
+       return -1;
     }
-    
+
     /*
     ** Clean out the TX ring asynchronously to interrupts - sometimes the
     ** interrupts are lost by delayed descriptor status updates relative to
@@ -1482,7 +1482,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
     spin_unlock_irqrestore(&lp->lock, flags);
 
     /* Test if cache is already locked - requeue skb if so */
-    if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt) 
+    if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt)
        return -1;
 
     /* Transmit descriptor ring full or stale skb */
@@ -1509,10 +1509,10 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
            load_packet(dev, skb->data, TD_IC | TD_LS | TD_FS | skb->len, skb);
            lp->stats.tx_bytes += skb->len;
            outl(POLL_DEMAND, DE4X5_TPD);/* Start the TX */
-               
+
            lp->tx_new = (++lp->tx_new) % lp->txRingSize;
            dev->trans_start = jiffies;
-                   
+
            if (TX_BUFFS_AVAIL) {
                netif_start_queue(dev);         /* Another pkt may be queued */
            }
@@ -1521,15 +1521,15 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
        }
        if (skb) de4x5_putb_cache(dev, skb);
     }
-    
+
     lp->cache.lock = 0;
 
     return status;
 }
 
 /*
-** The DE4X5 interrupt handler. 
-** 
+** The DE4X5 interrupt handler.
+**
 ** I/O Read/Writes through intermediate PCI bridges are never 'posted',
 ** so that the asserted interrupt always has some real data to work with -
 ** if these I/O accesses are ever changed to memory accesses, ensure the
@@ -1546,7 +1546,7 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     s32 imr, omr, sts, limit;
     u_long iobase;
     unsigned int handled = 0;
-    
+
     if (dev == NULL) {
        printk ("de4x5_interrupt(): irq %d for unknown device.\n", irq);
        return IRQ_NONE;
@@ -1554,35 +1554,35 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     lp = netdev_priv(dev);
     spin_lock(&lp->lock);
     iobase = dev->base_addr;
-       
+
     DISABLE_IRQs;                        /* Ensure non re-entrancy */
 
     if (test_and_set_bit(MASK_INTERRUPTS, (void*) &lp->interrupt))
        printk("%s: Re-entering the interrupt handler.\n", dev->name);
 
     synchronize_irq(dev->irq);
-       
+
     for (limit=0; limit<8; limit++) {
        sts = inl(DE4X5_STS);            /* Read IRQ status */
        outl(sts, DE4X5_STS);            /* Reset the board interrupts */
-           
+
        if (!(sts & lp->irq_mask)) break;/* All done */
        handled = 1;
-           
+
        if (sts & (STS_RI | STS_RU))     /* Rx interrupt (packet[s] arrived) */
          de4x5_rx(dev);
-           
+
        if (sts & (STS_TI | STS_TU))     /* Tx interrupt (packet sent) */
-         de4x5_tx(dev); 
-           
+         de4x5_tx(dev);
+
        if (sts & STS_LNF) {             /* TP Link has failed */
            lp->irq_mask &= ~IMR_LFM;
        }
-           
+
        if (sts & STS_UNF) {             /* Transmit underrun */
            de4x5_txur(dev);
        }
-           
+
        if (sts & STS_SE) {              /* Bus Error */
            STOP_DE4X5;
            printk("%s: Fatal bus error occurred, sts=%#8x, device stopped.\n",
@@ -1603,7 +1603,7 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     lp->interrupt = UNMASK_INTERRUPTS;
     ENABLE_IRQs;
     spin_unlock(&lp->lock);
-    
+
     return IRQ_RETVAL(handled);
 }
 
@@ -1614,11 +1614,11 @@ de4x5_rx(struct net_device *dev)
     u_long iobase = dev->base_addr;
     int entry;
     s32 status;
-    
+
     for (entry=lp->rx_new; (s32)le32_to_cpu(lp->rx_ring[entry].status)>=0;
                                                            entry=lp->rx_new) {
        status = (s32)le32_to_cpu(lp->rx_ring[entry].status);
-       
+
        if (lp->rx_ovf) {
            if (inl(DE4X5_MFC) & MFC_FOCM) {
                de4x5_rx_ovfc(dev);
@@ -1629,7 +1629,7 @@ de4x5_rx(struct net_device *dev)
        if (status & RD_FS) {                 /* Remember the start of frame */
            lp->rx_old = entry;
        }
-       
+
        if (status & RD_LS) {                 /* Valid frame status */
            if (lp->tx_enable) lp->linkOK++;
            if (status & RD_ES) {             /* There was an error. */
@@ -1646,9 +1646,9 @@ de4x5_rx(struct net_device *dev)
                struct sk_buff *skb;
                short pkt_len = (short)(le32_to_cpu(lp->rx_ring[entry].status)
                                                                    >> 16) - 4;
-               
+
                if ((skb = de4x5_alloc_rx_buff(dev, entry, pkt_len)) == NULL) {
-                   printk("%s: Insufficient memory; nuking packet.\n", 
+                   printk("%s: Insufficient memory; nuking packet.\n",
                                                                    dev->name);
                    lp->stats.rx_dropped++;
                } else {
@@ -1658,14 +1658,14 @@ de4x5_rx(struct net_device *dev)
                    skb->protocol=eth_type_trans(skb,dev);
                    de4x5_local_stats(dev, skb->data, pkt_len);
                    netif_rx(skb);
-                   
+
                    /* Update stats */
                    dev->last_rx = jiffies;
                    lp->stats.rx_packets++;
                    lp->stats.rx_bytes += pkt_len;
                }
            }
-           
+
            /* Change buffer ownership for this frame, back to the adapter */
            for (;lp->rx_old!=entry;lp->rx_old=(++lp->rx_old)%lp->rxRingSize) {
                lp->rx_ring[lp->rx_old].status = cpu_to_le32(R_OWN);
@@ -1674,13 +1674,13 @@ de4x5_rx(struct net_device *dev)
            lp->rx_ring[entry].status = cpu_to_le32(R_OWN);
            barrier();
        }
-       
+
        /*
        ** Update entry information
        */
        lp->rx_new = (++lp->rx_new) % lp->rxRingSize;
     }
-    
+
     return 0;
 }
 
@@ -1705,20 +1705,20 @@ de4x5_tx(struct net_device *dev)
     u_long iobase = dev->base_addr;
     int entry;
     s32 status;
-    
+
     for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) {
        status = (s32)le32_to_cpu(lp->tx_ring[entry].status);
        if (status < 0) {                     /* Buffer not sent yet */
            break;
        } else if (status != 0x7fffffff) {    /* Not setup frame */
            if (status & TD_ES) {             /* An error happened */
-               lp->stats.tx_errors++; 
+               lp->stats.tx_errors++;
                if (status & TD_NC) lp->stats.tx_carrier_errors++;
                if (status & TD_LC) lp->stats.tx_window_errors++;
                if (status & TD_UF) lp->stats.tx_fifo_errors++;
                if (status & TD_EC) lp->pktStats.excessive_collisions++;
                if (status & TD_DE) lp->stats.tx_aborted_errors++;
-           
+
                if (TX_PKT_PENDING) {
                    outl(POLL_DEMAND, DE4X5_TPD);/* Restart a stalled TX */
                }
@@ -1727,14 +1727,14 @@ de4x5_tx(struct net_device *dev)
                if (lp->tx_enable) lp->linkOK++;
            }
            /* Update the collision counter */
-           lp->stats.collisions += ((status & TD_EC) ? 16 : 
+           lp->stats.collisions += ((status & TD_EC) ? 16 :
                                                      ((status & TD_CC) >> 3));
 
            /* Free the buffer. */
            if (lp->tx_skb[entry] != NULL)
                de4x5_free_tx_buff(lp, entry);
        }
-       
+
        /* Update all the pointers */
        lp->tx_old = (++lp->tx_old) % lp->txRingSize;
     }
@@ -1746,7 +1746,7 @@ de4x5_tx(struct net_device *dev)
        else
            netif_start_queue(dev);
     }
-       
+
     return 0;
 }
 
@@ -1755,9 +1755,9 @@ de4x5_ast(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
     int next_tick = DE4X5_AUTOSENSE_MS;
-    
+
     disable_ast(dev);
-    
+
     if (lp->useSROM) {
        next_tick = srom_autoconf(dev);
     } else if (lp->chipset == DC21140) {
@@ -1769,7 +1769,7 @@ de4x5_ast(struct net_device *dev)
     }
     lp->linkOK = 0;
     enable_ast(dev, next_tick);
-    
+
     return 0;
 }
 
@@ -1792,11 +1792,11 @@ de4x5_txur(struct net_device *dev)
        }
        outl(omr | OMR_ST | OMR_SR, DE4X5_OMR);
     }
-    
+
     return 0;
 }
 
-static int 
+static int
 de4x5_rx_ovfc(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -1813,7 +1813,7 @@ de4x5_rx_ovfc(struct net_device *dev)
     }
 
     outl(omr, DE4X5_OMR);
-    
+
     return 0;
 }
 
@@ -1823,22 +1823,22 @@ de4x5_close(struct net_device *dev)
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     s32 imr, omr;
-    
+
     disable_ast(dev);
 
     netif_stop_queue(dev);
-    
+
     if (de4x5_debug & DEBUG_CLOSE) {
        printk("%s: Shutting down ethercard, status was %8.8x.\n",
               dev->name, inl(DE4X5_STS));
     }
-    
-    /* 
+
+    /*
     ** We stop the DE4X5 here... mask interrupts and stop TX & RX
     */
     DISABLE_IRQs;
     STOP_DE4X5;
-    
+
     /* Free the associated irq */
     free_irq(dev->irq, dev);
     lp->state = CLOSED;
@@ -1846,10 +1846,10 @@ de4x5_close(struct net_device *dev)
     /* Free any socket buffers */
     de4x5_free_rx_buffs(dev);
     de4x5_free_tx_buffs(dev);
-    
+
     /* Put the adapter to sleep to save power */
     yawn(dev, SLEEP);
-    
+
     return 0;
 }
 
@@ -1858,9 +1858,9 @@ de4x5_get_stats(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    
+
     lp->stats.rx_missed_errors = (int)(inl(DE4X5_MFC) & (MFC_OVFL | MFC_CNTR));
-    
+
     return &lp->stats;
 }
 
@@ -1886,7 +1886,7 @@ de4x5_local_stats(struct net_device *dev, char *buf, int pkt_len)
               (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) {
         lp->pktStats.unicast++;
     }
-               
+
     lp->pktStats.bins[0]++;       /* Duplicates stats.rx_packets */
     if (lp->pktStats.bins[0] == 0) { /* Reset counters */
         memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats));
@@ -1937,11 +1937,11 @@ set_multicast_list(struct net_device *dev)
            omr = inl(DE4X5_OMR);
            omr |= OMR_PR;
            outl(omr, DE4X5_OMR);
-       } else { 
+       } else {
            SetMulticastFilter(dev);
-           load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | 
+           load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
                                                        SETUP_FRAME_LEN, (struct sk_buff *)1);
-           
+
            lp->tx_new = (++lp->tx_new) % lp->txRingSize;
            outl(POLL_DEMAND, DE4X5_TPD);       /* Start the TX */
            dev->trans_start = jiffies;
@@ -1969,20 +1969,20 @@ SetMulticastFilter(struct net_device *dev)
     omr = inl(DE4X5_OMR);
     omr &= ~(OMR_PR | OMR_PM);
     pa = build_setup_frame(dev, ALL);        /* Build the basic frame */
-    
+
     if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 14)) {
        omr |= OMR_PM;                       /* Pass all multicasts */
     } else if (lp->setup_f == HASH_PERF) {   /* Hash Filtering */
        for (i=0;i<dev->mc_count;i++) {      /* for each address in the list */
            addrs=dmi->dmi_addr;
            dmi=dmi->next;
-           if ((*addrs & 0x01) == 1) {      /* multicast address? */ 
+           if ((*addrs & 0x01) == 1) {      /* multicast address? */
                crc = ether_crc_le(ETH_ALEN, addrs);
                hashcode = crc & HASH_BITS;  /* hashcode is 9 LSb of CRC */
-               
+
                byte = hashcode >> 3;        /* bit[3-8] -> byte in filter */
                bit = 1 << (hashcode & 0x07);/* bit[0-2] -> bit in byte */
-               
+
                byte <<= 1;                  /* calc offset into setup frame */
                if (byte & 0x02) {
                    byte -= 1;
@@ -1994,14 +1994,14 @@ SetMulticastFilter(struct net_device *dev)
        for (j=0; j<dev->mc_count; j++) {
            addrs=dmi->dmi_addr;
            dmi=dmi->next;
-           for (i=0; i<ETH_ALEN; i++) { 
+           for (i=0; i<ETH_ALEN; i++) {
                *(pa + (i&1)) = *addrs++;
                if (i & 0x01) pa += 4;
            }
        }
     }
     outl(omr, DE4X5_OMR);
-    
+
     return;
 }
 
@@ -2031,18 +2031,18 @@ static int __init de4x5_eisa_probe (struct device *gendev)
                status = -EBUSY;
                goto release_reg_1;
        }
-       
+
        if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) {
                status = -ENOMEM;
                goto release_reg_2;
        }
        lp = netdev_priv(dev);
-       
+
        cfid = (u32) inl(PCI_CFID);
        lp->cfrv = (u_short) inl(PCI_CFRV);
        device = (cfid >> 8) & 0x00ffff00;
        vendor = (u_short) cfid;
-           
+
        /* Read the EISA Configuration Registers */
        regval = inb(EISA_REG0) & (ER0_INTL | ER0_INTT);
 #ifdef CONFIG_ALPHA
@@ -2050,7 +2050,7 @@ static int __init de4x5_eisa_probe (struct device *gendev)
         * care about the EISA configuration, and thus doesn't
         * configure the PLX bridge properly. Oh well... Simply mimic
         * the EISA config file to sort it out. */
-       
+
        /* EISA REG1: Assert DecChip 21040 HW Reset */
        outb (ER1_IAM | 1, EISA_REG1);
        mdelay (1);
@@ -2061,12 +2061,12 @@ static int __init de4x5_eisa_probe (struct device *gendev)
 
        /* EISA REG3: R/W Burst Transfer Enable */
        outb (ER3_BWE | ER3_BRE, EISA_REG3);
-       
+
        /* 32_bit slave/master, Preempt Time=23 bclks, Unlatched Interrupt */
        outb (ER0_BSW | ER0_BMW | ER0_EPT | regval, EISA_REG0);
 #endif
        irq = de4x5_irq[(regval >> 1) & 0x03];
-       
+
        if (is_DC2114x) {
            device = ((lp->cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
        }
@@ -2077,7 +2077,7 @@ static int __init de4x5_eisa_probe (struct device *gendev)
        outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS);
        outl(0x00006000, PCI_CFLT);
        outl(iobase, PCI_CBIO);
-           
+
        DevicePresent(dev, EISA_APROM);
 
        dev->irq = irq;
@@ -2102,7 +2102,7 @@ static int __devexit de4x5_eisa_remove (struct device *device)
 
        dev = device->driver_data;
        iobase = dev->base_addr;
-       
+
        unregister_netdev (dev);
        free_netdev (dev);
        release_region (iobase + DE4X5_EISA_IO_PORTS, DE4X5_EISA_TOTAL_SIZE);
@@ -2131,11 +2131,11 @@ MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
 
 /*
 ** This function searches the current bus (which is >0) for a DECchip with an
-** SROM, so that in multiport cards that have one SROM shared between multiple 
+** SROM, so that in multiport cards that have one SROM shared between multiple
 ** DECchips, we can find the base SROM irrespective of the BIOS scan direction.
 ** For single port cards this is a time waster...
 */
-static void __devinit 
+static void __devinit
 srom_search(struct net_device *dev, struct pci_dev *pdev)
 {
     u_char pb;
@@ -2163,7 +2163,7 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
        /* Set the device number information */
        lp->device = PCI_SLOT(this_dev->devfn);
        lp->bus_num = pb;
-           
+
        /* Set the chipset information */
        if (is_DC2114x) {
            device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
@@ -2176,7 +2176,7 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
        /* Fetch the IRQ to be used */
        irq = this_dev->irq;
        if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
-           
+
        /* Check if I/O accesses are enabled */
        pci_read_config_word(this_dev, PCI_COMMAND, &status);
        if (!(status & PCI_COMMAND_IO)) continue;
@@ -2254,7 +2254,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
        lp = netdev_priv(dev);
        lp->bus = PCI;
        lp->bus_num = 0;
-       
+
        /* Search for an SROM on this bus */
        if (lp->bus_num != pb) {
            lp->bus_num = pb;
@@ -2267,7 +2267,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
        /* Set the device number information */
        lp->device = dev_num;
        lp->bus_num = pb;
-       
+
        /* Set the chipset information */
        if (is_DC2114x) {
            device = ((lp->cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
@@ -2283,7 +2283,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
                error = -ENODEV;
                goto free_dev;
        }
-           
+
        /* Check if I/O accesses and Bus Mastering are enabled */
        pci_read_config_word(pdev, PCI_COMMAND, &status);
 #ifdef __powerpc__
@@ -2322,7 +2322,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
        }
 
        dev->irq = irq;
-       
+
        if ((error = de4x5_hw_init(dev, iobase, &pdev->dev))) {
                goto release;
        }
@@ -2377,7 +2377,7 @@ static struct pci_driver de4x5_pci_driver = {
 ** Auto configure the media here rather than setting the port at compile
 ** time. This routine is called by de4x5_init() and when a loss of media is
 ** detected (excessive collisions, loss of carrier, no carrier or link fail
-** [TP] or no recent receive activity) to check whether the user has been 
+** [TP] or no recent receive activity) to check whether the user has been
 ** sneaky and changed the port on us.
 */
 static int
@@ -2405,7 +2405,7 @@ autoconf_media(struct net_device *dev)
     }
 
     enable_ast(dev, next_tick);
-    
+
     return (lp->media);
 }
 
@@ -2428,7 +2428,7 @@ dc21040_autoconf(struct net_device *dev)
     u_long iobase = dev->base_addr;
     int next_tick = DE4X5_AUTOSENSE_MS;
     s32 imr;
-    
+
     switch (lp->media) {
     case INIT:
        DISABLE_IRQs;
@@ -2447,36 +2447,36 @@ dc21040_autoconf(struct net_device *dev)
        lp->local_state = 0;
        next_tick = dc21040_autoconf(dev);
        break;
-       
+
     case TP:
-       next_tick = dc21040_state(dev, 0x8f01, 0xffff, 0x0000, 3000, BNC_AUI, 
+       next_tick = dc21040_state(dev, 0x8f01, 0xffff, 0x0000, 3000, BNC_AUI,
                                                         TP_SUSPECT, test_tp);
        break;
-       
+
     case TP_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, TP, test_tp, dc21040_autoconf);
        break;
-       
+
     case BNC:
     case AUI:
     case BNC_AUI:
-       next_tick = dc21040_state(dev, 0x8f09, 0x0705, 0x0006, 3000, EXT_SIA, 
+       next_tick = dc21040_state(dev, 0x8f09, 0x0705, 0x0006, 3000, EXT_SIA,
                                                  BNC_AUI_SUSPECT, ping_media);
        break;
-       
+
     case BNC_AUI_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, BNC_AUI, ping_media, dc21040_autoconf);
        break;
-       
+
     case EXT_SIA:
-       next_tick = dc21040_state(dev, 0x3041, 0x0000, 0x0006, 3000, 
+       next_tick = dc21040_state(dev, 0x3041, 0x0000, 0x0006, 3000,
                                              NC, EXT_SIA_SUSPECT, ping_media);
        break;
-       
+
     case EXT_SIA_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, EXT_SIA, ping_media, dc21040_autoconf);
        break;
-       
+
     case NC:
        /* default to TP for all */
        reset_init_sia(dev, 0x8f01, 0xffff, 0x0000);
@@ -2488,13 +2488,13 @@ dc21040_autoconf(struct net_device *dev)
        lp->tx_enable = NO;
        break;
     }
-    
+
     return next_tick;
 }
 
 static int
 dc21040_state(struct net_device *dev, int csr13, int csr14, int csr15, int timeout,
-             int next_state, int suspect_state, 
+             int next_state, int suspect_state,
              int (*fn)(struct net_device *, int))
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -2507,7 +2507,7 @@ dc21040_state(struct net_device *dev, int csr13, int csr14, int csr15, int timeo
        lp->local_state++;
        next_tick = 500;
        break;
-           
+
     case 1:
        if (!lp->tx_enable) {
            linkBad = fn(dev, timeout);
@@ -2527,7 +2527,7 @@ dc21040_state(struct net_device *dev, int csr13, int csr14, int csr15, int timeo
        }
        break;
     }
-    
+
     return next_tick;
 }
 
@@ -2582,7 +2582,7 @@ dc21041_autoconf(struct net_device *dev)
     u_long iobase = dev->base_addr;
     s32 sts, irqs, irq_mask, imr, omr;
     int next_tick = DE4X5_AUTOSENSE_MS;
-    
+
     switch (lp->media) {
     case INIT:
        DISABLE_IRQs;
@@ -2603,7 +2603,7 @@ dc21041_autoconf(struct net_device *dev)
        lp->local_state = 0;
        next_tick = dc21041_autoconf(dev);
        break;
-       
+
     case TP_NW:
        if (lp->timeout < 0) {
            omr = inl(DE4X5_OMR);/* Set up full duplex for the autonegotiate */
@@ -2623,7 +2623,7 @@ dc21041_autoconf(struct net_device *dev)
            next_tick = dc21041_autoconf(dev);
        }
        break;
-       
+
     case ANS:
        if (!lp->tx_enable) {
            irqs = STS_LNP;
@@ -2645,11 +2645,11 @@ dc21041_autoconf(struct net_device *dev)
            next_tick = 3000;
        }
        break;
-       
+
     case ANS_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, ANS, test_tp, dc21041_autoconf);
        break;
-       
+
     case TP:
        if (!lp->tx_enable) {
            if (lp->timeout < 0) {
@@ -2679,11 +2679,11 @@ dc21041_autoconf(struct net_device *dev)
            next_tick = 3000;
        }
        break;
-       
+
     case TP_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, TP, test_tp, dc21041_autoconf);
        break;
-       
+
     case AUI:
        if (!lp->tx_enable) {
            if (lp->timeout < 0) {
@@ -2709,11 +2709,11 @@ dc21041_autoconf(struct net_device *dev)
            next_tick = 3000;
        }
        break;
-       
+
     case AUI_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, AUI, ping_media, dc21041_autoconf);
        break;
-       
+
     case BNC:
        switch (lp->local_state) {
        case 0:
@@ -2731,7 +2731,7 @@ dc21041_autoconf(struct net_device *dev)
                next_tick = dc21041_autoconf(dev);
            }
            break;
-           
+
        case 1:
            if (!lp->tx_enable) {
                if ((sts = ping_media(dev, 3000)) < 0) {
@@ -2751,11 +2751,11 @@ dc21041_autoconf(struct net_device *dev)
            break;
        }
        break;
-       
+
     case BNC_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, BNC, ping_media, dc21041_autoconf);
        break;
-       
+
     case NC:
        omr = inl(DE4X5_OMR);    /* Set up full duplex for the autonegotiate */
        outl(omr | OMR_FDX, DE4X5_OMR);
@@ -2768,7 +2768,7 @@ dc21041_autoconf(struct net_device *dev)
        lp->tx_enable = NO;
        break;
     }
-    
+
     return next_tick;
 }
 
@@ -2784,9 +2784,9 @@ dc21140m_autoconf(struct net_device *dev)
     int ana, anlpa, cap, cr, slnk, sr;
     int next_tick = DE4X5_AUTOSENSE_MS;
     u_long imr, omr, iobase = dev->base_addr;
-    
+
     switch(lp->media) {
-    case INIT: 
+    case INIT:
         if (lp->timeout < 0) {
            DISABLE_IRQs;
            lp->tx_enable = FALSE;
@@ -2813,7 +2813,7 @@ dc21140m_autoconf(struct net_device *dev)
                    lp->media = _100Mb;
                } else if (lp->autosense == _10Mb) {
                    lp->media = _10Mb;
-               } else if ((lp->autosense == AUTO) && 
+               } else if ((lp->autosense == AUTO) &&
                                    ((sr=is_anc_capable(dev)) & MII_SR_ANC)) {
                    ana = (((sr >> 6) & MII_ANA_TAF) | MII_ANA_CSMA);
                    ana &= (lp->fdx ? ~0 : ~MII_ANA_FDAM);
@@ -2831,7 +2831,7 @@ dc21140m_autoconf(struct net_device *dev)
            next_tick = dc21140m_autoconf(dev);
        }
        break;
-       
+
     case ANS:
        switch (lp->local_state) {
        case 0:
@@ -2851,7 +2851,7 @@ dc21140m_autoconf(struct net_device *dev)
                next_tick = dc21140m_autoconf(dev);
            }
            break;
-           
+
        case 1:
            if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
                next_tick = sr & ~TIMER_CB;
@@ -2862,7 +2862,7 @@ dc21140m_autoconf(struct net_device *dev)
                    lp->tmp = MII_SR_ASSC;
                    anlpa = mii_rd(MII_ANLPA, lp->phy[lp->active].addr, DE4X5_MII);
                    ana = mii_rd(MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
-                   if (!(anlpa & MII_ANLPA_RF) && 
+                   if (!(anlpa & MII_ANLPA_RF) &&
                         (cap = anlpa & MII_ANLPA_TAF & ana)) {
                        if (cap & MII_ANA_100M) {
                            lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
@@ -2879,10 +2879,10 @@ dc21140m_autoconf(struct net_device *dev)
            break;
        }
        break;
-       
+
     case SPD_DET:                              /* Choose 10Mb/s or 100Mb/s */
         if (lp->timeout < 0) {
-           lp->tmp = (lp->phy[lp->active].id ? MII_SR_LKS : 
+           lp->tmp = (lp->phy[lp->active].id ? MII_SR_LKS :
                                                  (~gep_rd(dev) & GEP_LNP));
            SET_100Mb_PDET;
        }
@@ -2899,7 +2899,7 @@ dc21140m_autoconf(struct net_device *dev)
            next_tick = dc21140m_autoconf(dev);
        }
        break;
-       
+
     case _100Mb:                               /* Set 100Mb/s */
         next_tick = 3000;
        if (!lp->tx_enable) {
@@ -2933,7 +2933,7 @@ dc21140m_autoconf(struct net_device *dev)
            }
        }
        break;
-       
+
     case NC:
         if (lp->media != lp->c_media) {
            de4x5_dbg_media(dev);
@@ -2943,7 +2943,7 @@ dc21140m_autoconf(struct net_device *dev)
        lp->tx_enable = FALSE;
        break;
     }
-    
+
     return next_tick;
 }
 
@@ -3002,7 +3002,7 @@ dc2114x_autoconf(struct net_device *dev)
                lp->media = AUI;
            } else {
                lp->media = SPD_DET;
-               if ((lp->infoblock_media == ANS) && 
+               if ((lp->infoblock_media == ANS) &&
                                    ((sr=is_anc_capable(dev)) & MII_SR_ANC)) {
                    ana = (((sr >> 6) & MII_ANA_TAF) | MII_ANA_CSMA);
                    ana &= (lp->fdx ? ~0 : ~MII_ANA_FDAM);
@@ -3014,7 +3014,7 @@ dc2114x_autoconf(struct net_device *dev)
            next_tick = dc2114x_autoconf(dev);
         }
        break;
-       
+
     case ANS:
        switch (lp->local_state) {
        case 0:
@@ -3034,7 +3034,7 @@ dc2114x_autoconf(struct net_device *dev)
                next_tick = dc2114x_autoconf(dev);
            }
            break;
-           
+
        case 1:
            if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
                next_tick = sr & ~TIMER_CB;
@@ -3045,7 +3045,7 @@ dc2114x_autoconf(struct net_device *dev)
                    lp->tmp = MII_SR_ASSC;
                    anlpa = mii_rd(MII_ANLPA, lp->phy[lp->active].addr, DE4X5_MII);
                    ana = mii_rd(MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
-                   if (!(anlpa & MII_ANLPA_RF) && 
+                   if (!(anlpa & MII_ANLPA_RF) &&
                         (cap = anlpa & MII_ANLPA_TAF & ana)) {
                        if (cap & MII_ANA_100M) {
                            lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
@@ -3087,11 +3087,11 @@ dc2114x_autoconf(struct net_device *dev)
            next_tick = 3000;
        }
        break;
-       
+
     case AUI_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, AUI, ping_media, dc2114x_autoconf);
        break;
-       
+
     case BNC:
        switch (lp->local_state) {
        case 0:
@@ -3109,7 +3109,7 @@ dc2114x_autoconf(struct net_device *dev)
                next_tick = dc2114x_autoconf(dev);
            }
            break;
-           
+
        case 1:
            if (!lp->tx_enable) {
                if ((sts = ping_media(dev, 3000)) < 0) {
@@ -3130,11 +3130,11 @@ dc2114x_autoconf(struct net_device *dev)
            break;
        }
        break;
-       
+
     case BNC_SUSPECT:
        next_tick = de4x5_suspect_state(dev, 1000, BNC, ping_media, dc2114x_autoconf);
        break;
-       
+
     case SPD_DET:                              /* Choose 10Mb/s or 100Mb/s */
          if (srom_map_media(dev) < 0) {
              lp->tcount++;
@@ -3161,7 +3161,7 @@ dc2114x_autoconf(struct net_device *dev)
              next_tick = dc2114x_autoconf(dev);
          } else if (((lp->media == _100Mb) && is_100_up(dev)) ||
                     (((lp->media == _10Mb) || (lp->media == TP) ||
-                      (lp->media == BNC)   || (lp->media == AUI)) && 
+                      (lp->media == BNC)   || (lp->media == AUI)) &&
                      is_10_up(dev))) {
              next_tick = dc2114x_autoconf(dev);
          } else {
@@ -3169,7 +3169,7 @@ dc2114x_autoconf(struct net_device *dev)
              lp->media = INIT;
          }
          break;
-       
+
     case _10Mb:
         next_tick = 3000;
        if (!lp->tx_enable) {
@@ -3208,7 +3208,7 @@ printk("Huh?: media:%02x\n", lp->media);
        lp->media = INIT;
        break;
     }
-    
+
     return next_tick;
 }
 
@@ -3231,7 +3231,7 @@ srom_map_media(struct net_device *dev)
     struct de4x5_private *lp = netdev_priv(dev);
 
     lp->fdx = 0;
-    if (lp->infoblock_media == lp->media) 
+    if (lp->infoblock_media == lp->media)
       return 0;
 
     switch(lp->infoblock_media) {
@@ -3270,7 +3270,7 @@ srom_map_media(struct net_device *dev)
       case SROM_100BASEFF:
        if (!lp->params.fdx) return -1;
        lp->fdx = TRUE;
-      case SROM_100BASEF: 
+      case SROM_100BASEF:
        if (lp->params.fdx && !lp->fdx) return -1;
        lp->media = _100Mb;
        break;
@@ -3280,8 +3280,8 @@ srom_map_media(struct net_device *dev)
        lp->fdx = lp->params.fdx;
        break;
 
-      default: 
-       printk("%s: Bad media code [%d] detected in SROM!\n", dev->name, 
+      default:
+       printk("%s: Bad media code [%d] detected in SROM!\n", dev->name,
                                                          lp->infoblock_media);
        return -1;
        break;
@@ -3359,7 +3359,7 @@ test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14,
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     s32 sts, csr12;
-    
+
     if (lp->timeout < 0) {
        lp->timeout = msec/100;
        if (!lp->useSROM) {      /* Already done if by SROM, else dc2104[01] */
@@ -3372,22 +3372,22 @@ test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14,
        /* clear all pending interrupts */
        sts = inl(DE4X5_STS);
        outl(sts, DE4X5_STS);
-       
+
        /* clear csr12 NRA and SRA bits */
        if ((lp->chipset == DC21041) || lp->useSROM) {
            csr12 = inl(DE4X5_SISR);
            outl(csr12, DE4X5_SISR);
        }
     }
-    
+
     sts = inl(DE4X5_STS) & ~TIMER_CB;
-    
+
     if (!(sts & irqs) && --lp->timeout) {
        sts = 100 | TIMER_CB;
     } else {
        lp->timeout = -1;
     }
-    
+
     return sts;
 }
 
@@ -3397,11 +3397,11 @@ test_tp(struct net_device *dev, s32 msec)
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     int sisr;
-    
+
     if (lp->timeout < 0) {
        lp->timeout = msec/100;
     }
-    
+
     sisr = (inl(DE4X5_SISR) & ~TIMER_CB) & (SISR_LKF | SISR_NCR);
 
     if (sisr && --lp->timeout) {
@@ -3409,7 +3409,7 @@ test_tp(struct net_device *dev, s32 msec)
     } else {
        lp->timeout = -1;
     }
-    
+
     return sisr;
 }
 
@@ -3436,7 +3436,7 @@ test_for_100Mb(struct net_device *dev, int msec)
            lp->timeout = msec/SAMPLE_INTERVAL;
        }
     }
-    
+
     if (lp->phy[lp->active].id || lp->useSROM) {
        gep = is_100_up(dev) | is_spd_100(dev);
     } else {
@@ -3447,7 +3447,7 @@ test_for_100Mb(struct net_device *dev, int msec)
     } else {
        lp->timeout = -1;
     }
-    
+
     return gep;
 }
 
@@ -3459,13 +3459,13 @@ wait_for_link(struct net_device *dev)
     if (lp->timeout < 0) {
        lp->timeout = 1;
     }
-    
+
     if (lp->timeout--) {
        return TIMER_CB;
     } else {
        lp->timeout = -1;
     }
-    
+
     return 0;
 }
 
@@ -3479,21 +3479,21 @@ test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
     struct de4x5_private *lp = netdev_priv(dev);
     int test;
     u_long iobase = dev->base_addr;
-    
+
     if (lp->timeout < 0) {
        lp->timeout = msec/100;
     }
-    
+
     if (pol) pol = ~0;
     reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask;
     test = (reg ^ pol) & mask;
-    
+
     if (test && --lp->timeout) {
        reg = 100 | TIMER_CB;
     } else {
        lp->timeout = -1;
     }
-    
+
     return reg;
 }
 
@@ -3503,7 +3503,7 @@ is_spd_100(struct net_device *dev)
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     int spd;
-    
+
     if (lp->useMII) {
        spd = mii_rd(lp->phy[lp->active].spd.reg, lp->phy[lp->active].addr, DE4X5_MII);
        spd = ~(spd ^ lp->phy[lp->active].spd.value);
@@ -3517,7 +3517,7 @@ is_spd_100(struct net_device *dev)
        spd = (lp->asBitValid & (lp->asPolarity ^ (gep_rd(dev) & lp->asBit))) |
                  (lp->linkOK & ~lp->asBitValid);
     }
-    
+
     return spd;
 }
 
@@ -3526,7 +3526,7 @@ is_100_up(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    
+
     if (lp->useMII) {
        /* Double read for sticky bits & temporary drops */
        mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
@@ -3547,7 +3547,7 @@ is_10_up(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    
+
     if (lp->useMII) {
        /* Double read for sticky bits & temporary drops */
        mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
@@ -3570,7 +3570,7 @@ is_anc_capable(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    
+
     if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
        return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII));
     } else if ((lp->chipset & ~0x00ff) == DC2114x) {
@@ -3590,24 +3590,24 @@ ping_media(struct net_device *dev, int msec)
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     int sisr;
-    
+
     if (lp->timeout < 0) {
        lp->timeout = msec/100;
-       
+
        lp->tmp = lp->tx_new;                /* Remember the ring position */
        load_packet(dev, lp->frame, TD_LS | TD_FS | sizeof(lp->frame), (struct sk_buff *)1);
        lp->tx_new = (++lp->tx_new) % lp->txRingSize;
        outl(POLL_DEMAND, DE4X5_TPD);
     }
-    
+
     sisr = inl(DE4X5_SISR);
 
-    if ((!(sisr & SISR_NCR)) && 
-       ((s32)le32_to_cpu(lp->tx_ring[lp->tmp].status) < 0) && 
+    if ((!(sisr & SISR_NCR)) &&
+       ((s32)le32_to_cpu(lp->tx_ring[lp->tmp].status) < 0) &&
         (--lp->timeout)) {
        sisr = 100 | TIMER_CB;
     } else {
-       if ((!(sisr & SISR_NCR)) && 
+       if ((!(sisr & SISR_NCR)) &&
            !(le32_to_cpu(lp->tx_ring[lp->tmp].status) & (T_OWN | TD_ES)) &&
            lp->timeout) {
            sisr = 0;
@@ -3616,7 +3616,7 @@ ping_media(struct net_device *dev, int msec)
        }
        lp->timeout = -1;
     }
-    
+
     return sisr;
 }
 
@@ -3668,7 +3668,7 @@ de4x5_alloc_rx_buff(struct net_device *dev, int index, int len)
     } else {                                           /* Linear buffer */
        memcpy(skb_put(p,len),lp->rx_bufs + lp->rx_old * RX_BUFF_SZ,len);
     }
-                   
+
     return p;
 #endif
 }
@@ -3751,23 +3751,23 @@ de4x5_rst_desc_ring(struct net_device *dev)
        outl(lp->dma_rings, DE4X5_RRBA);
        outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
             DE4X5_TRBA);
-    
+
        lp->rx_new = lp->rx_old = 0;
        lp->tx_new = lp->tx_old = 0;
-    
+
        for (i = 0; i < lp->rxRingSize; i++) {
            lp->rx_ring[i].status = cpu_to_le32(R_OWN);
        }
-    
+
        for (i = 0; i < lp->txRingSize; i++) {
            lp->tx_ring[i].status = cpu_to_le32(0);
        }
-    
+
        barrier();
        lp->cache.save_cnt--;
        START_DE4X5;
     }
-        
+
     return;
 }
 
@@ -3792,7 +3792,7 @@ de4x5_cache_state(struct net_device *dev, int flag)
            gep_wr(lp->cache.gepc, dev);
            gep_wr(lp->cache.gep, dev);
        } else {
-           reset_init_sia(dev, lp->cache.csr13, lp->cache.csr14, 
+           reset_init_sia(dev, lp->cache.csr13, lp->cache.csr14,
                                                              lp->cache.csr15);
        }
        break;
@@ -3854,25 +3854,25 @@ test_ans(struct net_device *dev, s32 irqs, s32 irq_mask, s32 msec)
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     s32 sts, ans;
-    
+
     if (lp->timeout < 0) {
        lp->timeout = msec/100;
        outl(irq_mask, DE4X5_IMR);
-       
+
        /* clear all pending interrupts */
        sts = inl(DE4X5_STS);
        outl(sts, DE4X5_STS);
     }
-    
+
     ans = inl(DE4X5_SISR) & SISR_ANS;
     sts = inl(DE4X5_STS) & ~TIMER_CB;
-    
+
     if (!(sts & irqs) && (ans ^ ANS_NWOK) && --lp->timeout) {
        sts = 100 | TIMER_CB;
     } else {
        lp->timeout = -1;
     }
-    
+
     return sts;
 }
 
@@ -3882,7 +3882,7 @@ de4x5_setup_intr(struct net_device *dev)
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     s32 imr, sts;
-    
+
     if (inl(DE4X5_OMR) & OMR_SR) {   /* Only unmask if TX/RX is enabled */
        imr = 0;
        UNMASK_IRQs;
@@ -3890,7 +3890,7 @@ de4x5_setup_intr(struct net_device *dev)
        outl(sts, DE4X5_STS);
        ENABLE_IRQs;
     }
-    
+
     return;
 }
 
@@ -3936,17 +3936,17 @@ create_packet(struct net_device *dev, char *frame, int len)
 {
     int i;
     char *buf = frame;
-    
+
     for (i=0; i<ETH_ALEN; i++) {             /* Use this source address */
        *buf++ = dev->dev_addr[i];
     }
     for (i=0; i<ETH_ALEN; i++) {             /* Use this destination address */
        *buf++ = dev->dev_addr[i];
     }
-    
+
     *buf++ = 0;                              /* Packet length (2 bytes) */
     *buf++ = 1;
-    
+
     return;
 }
 
@@ -3978,7 +3978,7 @@ static int
 PCI_signature(char *name, struct de4x5_private *lp)
 {
     int i, status = 0, siglen = sizeof(de4x5_signatures)/sizeof(c_char *);
-    
+
     if (lp->chipset == DC21040) {
        strcpy(name, "DE434/5");
        return status;
@@ -4007,7 +4007,7 @@ PCI_signature(char *name, struct de4x5_private *lp)
     } else if ((lp->chipset & ~0x00ff) == DC2114x) {
        lp->useSROM = TRUE;
     }
-    
+
     return status;
 }
 
@@ -4024,7 +4024,7 @@ DevicePresent(struct net_device *dev, u_long aprom_addr)
 {
     int i, j=0;
     struct de4x5_private *lp = netdev_priv(dev);
-    
+
     if (lp->chipset == DC21040) {
        if (lp->bus == EISA) {
            enet_addr_rst(aprom_addr); /* Reset Ethernet Address ROM Pointer */
@@ -4049,7 +4049,7 @@ DevicePresent(struct net_device *dev, u_long aprom_addr)
        }
        de4x5_dbg_srom((struct de4x5_srom *)&lp->srom);
     }
-    
+
     return;
 }
 
@@ -4071,11 +4071,11 @@ enet_addr_rst(u_long aprom_addr)
     short sigLength=0;
     s8 data;
     int i, j;
-    
+
     dev.llsig.a = ETH_PROM_SIG;
     dev.llsig.b = ETH_PROM_SIG;
     sigLength = sizeof(u32) << 1;
-    
+
     for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {
        data = inb(aprom_addr);
        if (dev.Sig[j] == data) {    /* track signature */
@@ -4088,7 +4088,7 @@ enet_addr_rst(u_long aprom_addr)
            }
        }
     }
-    
+
     return;
 }
 
@@ -4111,7 +4111,7 @@ get_hw_addr(struct net_device *dev)
     for (i=0,k=0,j=0;j<3;j++) {
        k <<= 1;
        if (k > 0xffff) k-=0xffff;
-       
+
        if (lp->bus == PCI) {
            if (lp->chipset == DC21040) {
                while ((tmp = inl(DE4X5_APROM)) < 0);
@@ -4133,11 +4133,11 @@ get_hw_addr(struct net_device *dev)
            k += (u_short) ((tmp = inb(EISA_APROM)) << 8);
            dev->dev_addr[i++] = (u_char) tmp;
        }
-       
+
        if (k > 0xffff) k-=0xffff;
     }
     if (k == 0xffff) k=0;
-    
+
     if (lp->bus == PCI) {
        if (lp->chipset == DC21040) {
            while ((tmp = inl(DE4X5_APROM)) < 0);
@@ -4156,7 +4156,7 @@ get_hw_addr(struct net_device *dev)
     srom_repair(dev, broken);
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
-    /* 
+    /*
     ** If the address starts with 00 a0, we have to bit-reverse
     ** each byte of the address.
     */
@@ -4245,7 +4245,7 @@ test_bad_enet(struct net_device *dev, int status)
 
     for (tmp=0,i=0; i<ETH_ALEN; i++) tmp += (u_char)dev->dev_addr[i];
     if ((tmp == 0) || (tmp == 0x5fa)) {
-       if ((lp->chipset == last.chipset) && 
+       if ((lp->chipset == last.chipset) &&
            (lp->bus_num == last.bus) && (lp->bus_num > 0)) {
            for (i=0; i<ETH_ALEN; i++) dev->dev_addr[i] = last.addr[i];
            for (i=ETH_ALEN-1; i>2; --i) {
@@ -4275,7 +4275,7 @@ test_bad_enet(struct net_device *dev, int status)
 static int
 an_exception(struct de4x5_private *lp)
 {
-    if ((*(u_short *)lp->srom.sub_vendor_id == 0x00c0) && 
+    if ((*(u_short *)lp->srom.sub_vendor_id == 0x00c0) &&
        (*(u_short *)lp->srom.sub_system_id == 0x95e0)) {
        return -1;
     }
@@ -4290,11 +4290,11 @@ static short
 srom_rd(u_long addr, u_char offset)
 {
     sendto_srom(SROM_RD | SROM_SR, addr);
-    
+
     srom_latch(SROM_RD | SROM_SR | DT_CS, addr);
     srom_command(SROM_RD | SROM_SR | DT_IN | DT_CS, addr);
     srom_address(SROM_RD | SROM_SR | DT_CS, addr, offset);
-    
+
     return srom_data(SROM_RD | SROM_SR | DT_CS, addr);
 }
 
@@ -4304,7 +4304,7 @@ srom_latch(u_int command, u_long addr)
     sendto_srom(command, addr);
     sendto_srom(command | DT_CLK, addr);
     sendto_srom(command, addr);
-    
+
     return;
 }
 
@@ -4314,7 +4314,7 @@ srom_command(u_int command, u_long addr)
     srom_latch(command, addr);
     srom_latch(command, addr);
     srom_latch((command & 0x0000ff00) | DT_CS, addr);
-    
+
     return;
 }
 
@@ -4322,15 +4322,15 @@ static void
 srom_address(u_int command, u_long addr, u_char offset)
 {
     int i, a;
-    
+
     a = offset << 2;
     for (i=0; i<6; i++, a <<= 1) {
        srom_latch(command | ((a & 0x80) ? DT_IN : 0), addr);
     }
     udelay(1);
-    
+
     i = (getfrom_srom(addr) >> 3) & 0x01;
-    
+
     return;
 }
 
@@ -4340,17 +4340,17 @@ srom_data(u_int command, u_long addr)
     int i;
     short word = 0;
     s32 tmp;
-    
+
     for (i=0; i<16; i++) {
        sendto_srom(command  | DT_CLK, addr);
        tmp = getfrom_srom(addr);
        sendto_srom(command, addr);
-       
+
        word = (word << 1) | ((tmp >> 3) & 0x01);
     }
-    
+
     sendto_srom(command & 0x0000ff00, addr);
-    
+
     return word;
 }
 
@@ -4359,13 +4359,13 @@ static void
 srom_busy(u_int command, u_long addr)
 {
    sendto_srom((command & 0x0000ff00) | DT_CS, addr);
-   
+
    while (!((getfrom_srom(addr) >> 3) & 0x01)) {
        mdelay(1);
    }
-   
+
    sendto_srom(command & 0x0000ff00, addr);
-   
+
    return;
 }
 */
@@ -4375,7 +4375,7 @@ sendto_srom(u_int command, u_long addr)
 {
     outl(command, addr);
     udelay(1);
-    
+
     return;
 }
 
@@ -4383,10 +4383,10 @@ static int
 getfrom_srom(u_long addr)
 {
     s32 tmp;
-    
+
     tmp = inl(addr);
     udelay(1);
-    
+
     return tmp;
 }
 
@@ -4403,7 +4403,7 @@ srom_infoleaf_info(struct net_device *dev)
     }
     if (i == INFOLEAF_SIZE) {
        lp->useSROM = FALSE;
-       printk("%s: Cannot find correct chipset for SROM decoding!\n", 
+       printk("%s: Cannot find correct chipset for SROM decoding!\n",
                                                                  dev->name);
        return -ENXIO;
     }
@@ -4420,7 +4420,7 @@ srom_infoleaf_info(struct net_device *dev)
        }
        if (i == 0) {
            lp->useSROM = FALSE;
-           printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n", 
+           printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n",
                                                       dev->name, lp->device);
            return -ENXIO;
        }
@@ -4494,9 +4494,9 @@ srom_exec(struct net_device *dev, u_char *p)
     if (((lp->ibn != 1) && (lp->ibn != 3) && (lp->ibn != 5)) || !count) return;
 
     if (lp->chipset != DC21140) RESET_SIA;
+
     while (count--) {
-       gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ? 
+       gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ?
                                                   *p++ : TWIDDLE(w++)), dev);
        mdelay(2);                          /* 2ms per action */
     }
@@ -4514,13 +4514,13 @@ srom_exec(struct net_device *dev, u_char *p)
 ** unless I implement the DC21041 SROM functions. There's no need
 ** since the existing code will be satisfactory for all boards.
 */
-static int 
+static int
 dc21041_infoleaf(struct net_device *dev)
 {
     return DE4X5_AUTOSENSE_MS;
 }
 
-static int 
+static int
 dc21140_infoleaf(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4558,7 +4558,7 @@ dc21140_infoleaf(struct net_device *dev)
     return next_tick & ~TIMER_CB;
 }
 
-static int 
+static int
 dc21142_infoleaf(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4593,7 +4593,7 @@ dc21142_infoleaf(struct net_device *dev)
     return next_tick & ~TIMER_CB;
 }
 
-static int 
+static int
 dc21143_infoleaf(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4631,7 +4631,7 @@ dc21143_infoleaf(struct net_device *dev)
 ** The compact infoblock is only designed for DC21140[A] chips, so
 ** we'll reuse the dc21140m_autoconf function. Non MII media only.
 */
-static int 
+static int
 compact_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4671,7 +4671,7 @@ compact_infoblock(struct net_device *dev, u_char count, u_char *p)
 /*
 ** This block describes non MII media for the DC21140[A] only.
 */
-static int 
+static int
 type0_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4711,7 +4711,7 @@ type0_infoblock(struct net_device *dev, u_char count, u_char *p)
 
 /* These functions are under construction! */
 
-static int 
+static int
 type1_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4750,7 +4750,7 @@ type1_infoblock(struct net_device *dev, u_char count, u_char *p)
     return dc21140m_autoconf(dev);
 }
 
-static int 
+static int
 type2_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4791,7 +4791,7 @@ type2_infoblock(struct net_device *dev, u_char count, u_char *p)
     return dc2114x_autoconf(dev);
 }
 
-static int 
+static int
 type3_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4833,7 +4833,7 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p)
     return dc2114x_autoconf(dev);
 }
 
-static int 
+static int
 type4_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4878,7 +4878,7 @@ type4_infoblock(struct net_device *dev, u_char count, u_char *p)
 ** This block type provides information for resetting external devices
 ** (chips) through the General Purpose Register.
 */
-static int 
+static int
 type5_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4916,7 +4916,7 @@ mii_rd(u_char phyreg, u_char phyaddr, u_long ioaddr)
     mii_address(phyaddr, ioaddr);          /* PHY address to be accessed     */
     mii_address(phyreg, ioaddr);           /* PHY Register to read           */
     mii_ta(MII_STRD, ioaddr);              /* Turn around time - 2 MDC       */
-    
+
     return mii_rdata(ioaddr);              /* Read data                      */
 }
 
@@ -4931,7 +4931,7 @@ mii_wr(int data, u_char phyreg, u_char phyaddr, u_long ioaddr)
     mii_ta(MII_STWR, ioaddr);              /* Turn around time - 2 MDC       */
     data = mii_swap(data, 16);             /* Swap data bit ordering         */
     mii_wdata(data, 16, ioaddr);           /* Write data                     */
-    
+
     return;
 }
 
@@ -4940,12 +4940,12 @@ mii_rdata(u_long ioaddr)
 {
     int i;
     s32 tmp = 0;
-    
+
     for (i=0; i<16; i++) {
        tmp <<= 1;
        tmp |= getfrom_mii(MII_MRD | MII_RD, ioaddr);
     }
-    
+
     return tmp;
 }
 
@@ -4953,12 +4953,12 @@ static void
 mii_wdata(int data, int len, u_long ioaddr)
 {
     int i;
-    
+
     for (i=0; i<len; i++) {
        sendto_mii(MII_MWR | MII_WR, data, ioaddr);
        data >>= 1;
     }
-    
+
     return;
 }
 
@@ -4966,13 +4966,13 @@ static void
 mii_address(u_char addr, u_long ioaddr)
 {
     int i;
-    
+
     addr = mii_swap(addr, 5);
     for (i=0; i<5; i++) {
        sendto_mii(MII_MWR | MII_WR, addr, ioaddr);
        addr >>= 1;
     }
-    
+
     return;
 }
 
@@ -4980,12 +4980,12 @@ static void
 mii_ta(u_long rw, u_long ioaddr)
 {
     if (rw == MII_STWR) {
-       sendto_mii(MII_MWR | MII_WR, 1, ioaddr);  
-       sendto_mii(MII_MWR | MII_WR, 0, ioaddr);  
+       sendto_mii(MII_MWR | MII_WR, 1, ioaddr);
+       sendto_mii(MII_MWR | MII_WR, 0, ioaddr);
     } else {
        getfrom_mii(MII_MRD | MII_RD, ioaddr);        /* Tri-state MDIO */
     }
-    
+
     return;
 }
 
@@ -4993,13 +4993,13 @@ static int
 mii_swap(int data, int len)
 {
     int i, tmp = 0;
-    
+
     for (i=0; i<len; i++) {
        tmp <<= 1;
        tmp |= (data & 1);
        data >>= 1;
     }
-    
+
     return tmp;
 }
 
@@ -5007,13 +5007,13 @@ static void
 sendto_mii(u32 command, int data, u_long ioaddr)
 {
     u32 j;
-    
+
     j = (data & 1) << 17;
     outl(command | j, ioaddr);
     udelay(1);
     outl(command | MII_MDC | j, ioaddr);
     udelay(1);
-    
+
     return;
 }
 
@@ -5024,7 +5024,7 @@ getfrom_mii(u32 command, u_long ioaddr)
     udelay(1);
     outl(command | MII_MDC, ioaddr);
     udelay(1);
-    
+
     return ((inl(ioaddr) >> 19) & 1);
 }
 
@@ -5085,7 +5085,7 @@ mii_get_phy(struct net_device *dev)
     u_long iobase = dev->base_addr;
     int i, j, k, n, limit=sizeof(phy_info)/sizeof(struct phy_table);
     int id;
-    
+
     lp->active = 0;
     lp->useMII = TRUE;
 
@@ -5094,7 +5094,7 @@ mii_get_phy(struct net_device *dev)
        lp->phy[lp->active].addr = i;
        if (i==0) n++;                             /* Count cycles */
        while (de4x5_reset_phy(dev)<0) udelay(100);/* Wait for reset */
-       id = mii_get_oui(i, DE4X5_MII); 
+       id = mii_get_oui(i, DE4X5_MII);
        if ((id == 0) || (id == 65535)) continue;  /* Valid ID? */
        for (j=0; j<limit; j++) {                  /* Search PHY table */
            if (id != phy_info[j].id) continue;    /* ID match? */
@@ -5133,7 +5133,7 @@ mii_get_phy(struct net_device *dev)
        for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++) { /*For each PHY*/
            mii_wr(MII_CR_RST, MII_CR, lp->phy[k].addr, DE4X5_MII);
            while (mii_rd(MII_CR, lp->phy[k].addr, DE4X5_MII) & MII_CR_RST);
-           
+
            de4x5_dbg_mii(dev, k);
        }
     }
@@ -5148,12 +5148,12 @@ build_setup_frame(struct net_device *dev, int mode)
     struct de4x5_private *lp = netdev_priv(dev);
     int i;
     char *pa = lp->setup_frame;
-    
+
     /* Initialise the setup frame */
     if (mode == ALL) {
        memset(lp->setup_frame, 0, SETUP_FRAME_LEN);
     }
-    
+
     if (lp->setup_f == HASH_PERF) {
        for (pa=lp->setup_frame+IMPERF_PA_OFFSET, i=0; i<ETH_ALEN; i++) {
            *(pa + i) = dev->dev_addr[i];                 /* Host address */
@@ -5170,7 +5170,7 @@ build_setup_frame(struct net_device *dev, int mode)
            if (i & 0x01) pa += 4;
        }
     }
-    
+
     return pa;                     /* Points to the next entry */
 }
 
@@ -5178,7 +5178,7 @@ static void
 enable_ast(struct net_device *dev, u32 time_out)
 {
     timeout(dev, (void *)&de4x5_ast, (u_long)dev, time_out);
-    
+
     return;
 }
 
@@ -5186,9 +5186,9 @@ static void
 disable_ast(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
-    
+
     del_timer(&lp->timer);
-    
+
     return;
 }
 
@@ -5207,10 +5207,10 @@ de4x5_switch_mac_port(struct net_device *dev)
     omr |= lp->infoblock_csr6;
     if (omr & OMR_PS) omr |= OMR_HBD;
     outl(omr, DE4X5_OMR);
-    
+
     /* Soft Reset */
     RESET_DE4X5;
-    
+
     /* Restore the GEP - especially for COMPACT and Type 0 Infoblocks */
     if (lp->chipset == DC21140) {
        gep_wr(lp->cache.gepc, dev);
@@ -5263,21 +5263,21 @@ timeout(struct net_device *dev, void (*fn)(u_long data), u_long data, u_long mse
 {
     struct de4x5_private *lp = netdev_priv(dev);
     int dt;
-    
+
     /* First, cancel any pending timer events */
     del_timer(&lp->timer);
-    
+
     /* Convert msec to ticks */
     dt = (msec * HZ) / 1000;
     if (dt==0) dt=1;
-    
+
     /* Set up timer */
     init_timer(&lp->timer);
     lp->timer.expires = jiffies + dt;
     lp->timer.function = fn;
     lp->timer.data = data;
     add_timer(&lp->timer);
-    
+
     return;
 }
 
@@ -5375,7 +5375,7 @@ de4x5_dbg_open(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
     int i;
-    
+
     if (de4x5_debug & DEBUG_OPEN) {
        printk("%s: de4x5 opening with irq %d\n",dev->name,dev->irq);
        printk("\tphysical address: ");
@@ -5413,11 +5413,11 @@ de4x5_dbg_open(struct net_device *dev)
            }
        }
        printk("...0x%8.8x\n", le32_to_cpu(lp->tx_ring[i].buf));
-       printk("Ring size: \nRX: %d\nTX: %d\n", 
-              (short)lp->rxRingSize, 
-              (short)lp->txRingSize); 
+       printk("Ring size: \nRX: %d\nTX: %d\n",
+              (short)lp->rxRingSize,
+              (short)lp->txRingSize);
     }
-    
+
     return;
 }
 
@@ -5426,7 +5426,7 @@ de4x5_dbg_mii(struct net_device *dev, int k)
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    
+
     if (de4x5_debug & DEBUG_MII) {
        printk("\nMII device address: %d\n", lp->phy[k].addr);
        printk("MII CR:  %x\n",mii_rd(MII_CR,lp->phy[k].addr,DE4X5_MII));
@@ -5445,7 +5445,7 @@ de4x5_dbg_mii(struct net_device *dev, int k)
            printk("MII 20:  %x\n",mii_rd(0x14,lp->phy[k].addr,DE4X5_MII));
        }
     }
-    
+
     return;
 }
 
@@ -5453,17 +5453,17 @@ static void
 de4x5_dbg_media(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
-    
+
     if (lp->media != lp->c_media) {
        if (de4x5_debug & DEBUG_MEDIA) {
            printk("%s: media is %s%s\n", dev->name,
                   (lp->media == NC  ? "unconnected, link down or incompatible connection" :
                    (lp->media == TP  ? "TP" :
                     (lp->media == ANS ? "TP/Nway" :
-                     (lp->media == BNC ? "BNC" : 
-                      (lp->media == AUI ? "AUI" : 
-                       (lp->media == BNC_AUI ? "BNC/AUI" : 
-                        (lp->media == EXT_SIA ? "EXT SIA" : 
+                     (lp->media == BNC ? "BNC" :
+                      (lp->media == AUI ? "AUI" :
+                       (lp->media == BNC_AUI ? "BNC/AUI" :
+                        (lp->media == EXT_SIA ? "EXT SIA" :
                          (lp->media == _100Mb  ? "100Mb/s" :
                           (lp->media == _10Mb   ? "10Mb/s" :
                            "???"
@@ -5471,7 +5471,7 @@ de4x5_dbg_media(struct net_device *dev)
        }
        lp->c_media = lp->media;
     }
-    
+
     return;
 }
 
@@ -5554,7 +5554,7 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        u32 lval[36];
     } tmp;
     u_long flags = 0;
-    
+
     switch(ioc->cmd) {
     case DE4X5_GET_HWADDR:           /* Get the hardware address */
        ioc->len = ETH_ALEN;
@@ -5575,7 +5575,7 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        }
        build_setup_frame(dev, PHYS_ADDR_ONLY);
        /* Set up the descriptor and give ownership to the card */
-       load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | 
+       load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
                                                       SETUP_FRAME_LEN, (struct sk_buff *)1);
        lp->tx_new = (++lp->tx_new) % lp->txRingSize;
        outl(POLL_DEMAND, DE4X5_TPD);                /* Start the TX */
@@ -5617,8 +5617,8 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        spin_lock_irqsave(&lp->lock, flags);
        memcpy(&statbuf, &lp->pktStats, ioc->len);
        spin_unlock_irqrestore(&lp->lock, flags);
-       if (copy_to_user(ioc->data, &statbuf, ioc->len)) 
-               return -EFAULT; 
+       if (copy_to_user(ioc->data, &statbuf, ioc->len))
+               return -EFAULT;
        break;
     }
     case DE4X5_CLR_STATS:            /* Zero out the driver statistics */
@@ -5652,9 +5652,9 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        ioc->len = j;
        if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
        break;
-       
+
 #define DE4X5_DUMP              0x0f /* Dump the DE4X5 Status */
-/*     
+/*
       case DE4X5_DUMP:
        j = 0;
        tmp.addr[j++] = dev->irq;
@@ -5664,7 +5664,7 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        tmp.addr[j++] = lp->rxRingSize;
        tmp.lval[j>>2] = (long)lp->rx_ring; j+=4;
        tmp.lval[j>>2] = (long)lp->tx_ring; j+=4;
-       
+
        for (i=0;i<lp->rxRingSize-1;i++){
            if (i < 3) {
                tmp.lval[j>>2] = (long)&lp->rx_ring[i].status; j+=4;
@@ -5677,7 +5677,7 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
            }
        }
        tmp.lval[j>>2] = (long)&lp->tx_ring[i].status; j+=4;
-       
+
        for (i=0;i<lp->rxRingSize-1;i++){
            if (i < 3) {
                tmp.lval[j>>2] = (s32)le32_to_cpu(lp->rx_ring[i].buf); j+=4;
@@ -5690,14 +5690,14 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
            }
        }
        tmp.lval[j>>2] = (s32)le32_to_cpu(lp->tx_ring[i].buf); j+=4;
-       
+
        for (i=0;i<lp->rxRingSize;i++){
            tmp.lval[j>>2] = le32_to_cpu(lp->rx_ring[i].status); j+=4;
        }
        for (i=0;i<lp->txRingSize;i++){
            tmp.lval[j>>2] = le32_to_cpu(lp->tx_ring[i].status); j+=4;
        }
-       
+
        tmp.lval[j>>2] = inl(DE4X5_BMR);  j+=4;
        tmp.lval[j>>2] = inl(DE4X5_TPD);  j+=4;
        tmp.lval[j>>2] = inl(DE4X5_RPD);  j+=4;
@@ -5706,18 +5706,18 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        tmp.lval[j>>2] = inl(DE4X5_STS);  j+=4;
        tmp.lval[j>>2] = inl(DE4X5_OMR);  j+=4;
        tmp.lval[j>>2] = inl(DE4X5_IMR);  j+=4;
-       tmp.lval[j>>2] = lp->chipset; j+=4; 
+       tmp.lval[j>>2] = lp->chipset; j+=4;
        if (lp->chipset == DC21140) {
            tmp.lval[j>>2] = gep_rd(dev);  j+=4;
        } else {
            tmp.lval[j>>2] = inl(DE4X5_SISR); j+=4;
            tmp.lval[j>>2] = inl(DE4X5_SICR); j+=4;
            tmp.lval[j>>2] = inl(DE4X5_STRR); j+=4;
-           tmp.lval[j>>2] = inl(DE4X5_SIGR); j+=4; 
+           tmp.lval[j>>2] = inl(DE4X5_SIGR); j+=4;
        }
-       tmp.lval[j>>2] = lp->phy[lp->active].id; j+=4; 
+       tmp.lval[j>>2] = lp->phy[lp->active].id; j+=4;
        if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
-           tmp.lval[j>>2] = lp->active; j+=4; 
+           tmp.lval[j>>2] = lp->active; j+=4;
            tmp.lval[j>>2]=mii_rd(MII_CR,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
            tmp.lval[j>>2]=mii_rd(MII_SR,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
            tmp.lval[j>>2]=mii_rd(MII_ID0,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
@@ -5734,10 +5734,10 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                tmp.lval[j>>2]=mii_rd(0x14,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
            }
        }
-       
+
        tmp.addr[j++] = lp->txRingSize;
        tmp.addr[j++] = netif_queue_stopped(dev);
-       
+
        ioc->len = j;
        if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
        break;
@@ -5746,7 +5746,7 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
     default:
        return -EOPNOTSUPP;
     }
-    
+
     return status;
 }
 
index ad37a4074302eb69e96b6651a622c8a7aa7b9295..57226e5eb8a680993a9f227b2e133485b244f247 100644 (file)
 /*
 ** EISA Register Address Map
 */
-#define EISA_ID      iobase+0x0c80   /* EISA ID Registers */ 
-#define EISA_ID0     iobase+0x0c80   /* EISA ID Register 0 */ 
-#define EISA_ID1     iobase+0x0c81   /* EISA ID Register 1 */ 
-#define EISA_ID2     iobase+0x0c82   /* EISA ID Register 2 */ 
-#define EISA_ID3     iobase+0x0c83   /* EISA ID Register 3 */ 
+#define EISA_ID      iobase+0x0c80   /* EISA ID Registers */
+#define EISA_ID0     iobase+0x0c80   /* EISA ID Register 0 */
+#define EISA_ID1     iobase+0x0c81   /* EISA ID Register 1 */
+#define EISA_ID2     iobase+0x0c82   /* EISA ID Register 2 */
+#define EISA_ID3     iobase+0x0c83   /* EISA ID Register 3 */
 #define EISA_CR      iobase+0x0c84   /* EISA Control Register */
 #define EISA_REG0    iobase+0x0c88   /* EISA Configuration Register 0 */
 #define EISA_REG1    iobase+0x0c89   /* EISA Configuration Register 1 */
@@ -1008,8 +1008,8 @@ struct de4x5_ioctl {
        unsigned char  __user *data;       /* Pointer to the data buffer */
 };
 
-/* 
-** Recognised commands for the driver 
+/*
+** Recognised commands for the driver
 */
 #define DE4X5_GET_HWADDR       0x01 /* Get the hardware address */
 #define DE4X5_SET_HWADDR       0x02 /* Set the hardware address */
index 74e9075d9c48edee4d5c908849025d8dfe2cb169..ba5b112093f4d6f28c9bb998749c12306c0e5be9 100644 (file)
@@ -50,7 +50,7 @@
     forget to unmap PCI mapped skbs.
 
     Alan Cox <alan@redhat.com>
-    Added new PCI identifiers provided by Clear Zhang at ALi 
+    Added new PCI identifiers provided by Clear Zhang at ALi
     for their 1563 ethernet device.
 
     TODO
index fbd9ab60b0525a2402c464ee40036bfee511fbb0..5ffbd5b300c0d524c4baefaf3b373cdce6dc2e20 100644 (file)
@@ -96,11 +96,11 @@ static const char *block_name[] __devinitdata = {
  * tulip_build_fake_mediatable - Build a fake mediatable entry.
  * @tp: Ptr to the tulip private data.
  *
- * Some cards like the 3x5 HSC cards (J3514A) do not have a standard 
+ * Some cards like the 3x5 HSC cards (J3514A) do not have a standard
  * srom and can not be handled under the fixup routine.  These cards
- * still need a valid mediatable entry for correct csr12 setup and 
+ * still need a valid mediatable entry for correct csr12 setup and
  * mii handling.
- * 
+ *
  * Since this is currently a parisc-linux specific function, the
  * #ifdef __hppa__ should completely optimize this function away for
  * non-parisc hardware.
@@ -140,7 +140,7 @@ static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
                tp->flags |= HAS_PHY_IRQ;
                tp->csr12_shadow = -1;
        }
-#endif 
+#endif
 }
 
 void __devinit tulip_parse_eeprom(struct net_device *dev)
index bb3558164a5b09b8155eb2f2c04e20742187ff9a..da4f7593c50f54111b0242f9497c9afc7a0bfa3f 100644 (file)
@@ -139,22 +139,22 @@ int tulip_poll(struct net_device *dev, int *budget)
                }
                /* Acknowledge current RX interrupt sources. */
                iowrite32((RxIntr | RxNoBuf), tp->base_addr + CSR5);
+
+
                /* If we own the next entry, it is a new packet. Send it up. */
                while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
                        s32 status = le32_to_cpu(tp->rx_ring[entry].status);
+
+
                        if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx)
                                break;
+
                        if (tulip_debug > 5)
                                printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
                                       dev->name, entry, status);
                        if (--rx_work_limit < 0)
                                goto not_done;
+
                        if ((status & 0x38008300) != 0x0300) {
                                if ((status & 0x38000300) != 0x0300) {
                                 /* Ingore earlier buffers. */
@@ -180,7 +180,7 @@ int tulip_poll(struct net_device *dev, int *budget)
                                /* Omit the four octet CRC from the length. */
                                short pkt_len = ((status >> 16) & 0x7ff) - 4;
                                struct sk_buff *skb;
-  
+
 #ifndef final_version
                                if (pkt_len > 1518) {
                                        printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
@@ -213,7 +213,7 @@ int tulip_poll(struct net_device *dev, int *budget)
                                } else {        /* Pass up the skb already on the Rx ring. */
                                        char *temp = skb_put(skb = tp->rx_buffers[entry].skb,
                                                             pkt_len);
-  
+
 #ifndef final_version
                                        if (tp->rx_buffers[entry].mapping !=
                                            le32_to_cpu(tp->rx_ring[entry].buffer1)) {
@@ -225,17 +225,17 @@ int tulip_poll(struct net_device *dev, int *budget)
                                                       skb->head, temp);
                                        }
 #endif
-  
+
                                        pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
                                                         PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
-  
+
                                        tp->rx_buffers[entry].skb = NULL;
                                        tp->rx_buffers[entry].mapping = 0;
                                }
                                skb->protocol = eth_type_trans(skb, dev);
-  
+
                                netif_receive_skb(skb);
+
                                dev->last_rx = jiffies;
                                tp->stats.rx_packets++;
                                tp->stats.rx_bytes += pkt_len;
@@ -245,12 +245,12 @@ int tulip_poll(struct net_device *dev, int *budget)
                        entry = (++tp->cur_rx) % RX_RING_SIZE;
                        if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4)
                                tulip_refill_rx(dev);
+
                 }
+
                /* New ack strategy... irq does not ack Rx any longer
                   hopefully this helps */
+
                /* Really bad things can happen here... If new packet arrives
                 * and an irq arrives (tx or just due to occasionally unset
                 * mask), it will be acked by irq handler, but new thread
@@ -259,28 +259,28 @@ int tulip_poll(struct net_device *dev, int *budget)
                 * tomorrow (night 011029). If it will not fail, we won
                 * finally: amount of IO did not increase at all. */
        } while ((ioread32(tp->base_addr + CSR5) & RxIntr));
+
 done:
+
  #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
-  
+
           /* We use this simplistic scheme for IM. It's proven by
              real life installations. We can have IM enabled
-            continuesly but this would cause unnecessary latency. 
-            Unfortunely we can't use all the NET_RX_* feedback here. 
-            This would turn on IM for devices that is not contributing 
-            to backlog congestion with unnecessary latency. 
-  
+            continuesly but this would cause unnecessary latency.
+            Unfortunely we can't use all the NET_RX_* feedback here.
+            This would turn on IM for devices that is not contributing
+            to backlog congestion with unnecessary latency.
+
              We monitor the the device RX-ring and have:
-  
+
              HW Interrupt Mitigation either ON or OFF.
-  
-            ON:  More then 1 pkt received (per intr.) OR we are dropping 
+
+            ON:  More then 1 pkt received (per intr.) OR we are dropping
              OFF: Only 1 pkt received
-            
+
              Note. We only use min and max (0, 15) settings from mit_table */
-  
-  
+
+
           if( tp->flags &  HAS_INTR_MITIGATION) {
                  if( received > 1 ) {
                          if( ! tp->mit_on ) {
@@ -297,20 +297,20 @@ done:
           }
 
 #endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */
+
          dev->quota -= received;
          *budget -= received;
+
          tulip_refill_rx(dev);
-         
+
          /* If RX ring is not full we are out of memory. */
          if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom;
+
          /* Remove us from polling list and enable RX intr. */
+
          netif_rx_complete(dev);
          iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7);
+
          /* The last op happens after poll completion. Which means the following:
           * 1. it can race with disabling irqs in irq handler
           * 2. it can race with dise/enabling irqs in other poll threads
@@ -321,9 +321,9 @@ done:
           * due to races in masking and due to too late acking of already
           * processed irqs. But it must not result in losing events.
           */
+
          return 0;
+
  not_done:
          if (!received) {
 
@@ -331,29 +331,29 @@ done:
          }
          dev->quota -= received;
          *budget -= received;
+
          if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 ||
              tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
                  tulip_refill_rx(dev);
+
          if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom;
+
          return 1;
+
+
  oom:    /* Executed with RX ints disabled */
-         
+
+
          /* Start timer, stop polling, but do not enable rx interrupts. */
          mod_timer(&tp->oom_timer, jiffies+1);
-       
+
          /* Think: timer_pending() was an explicit signature of bug.
           * Timer can be pending now but fired and completed
           * before we did netif_rx_complete(). See? We would lose it. */
+
          /* remove ourselves from the polling list */
          netif_rx_complete(dev);
+
          return 0;
 }
 
@@ -521,9 +521,9 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
        /* Let's see whether the interrupt really is for us */
        csr5 = ioread32(ioaddr + CSR5);
 
-        if (tp->flags & HAS_PHY_IRQ) 
+        if (tp->flags & HAS_PHY_IRQ)
                handled = phy_interrupt (dev);
-    
+
        if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
                return IRQ_RETVAL(handled);
 
@@ -538,17 +538,17 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                        /* Mask RX intrs and add the device to poll list. */
                        iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7);
                        netif_rx_schedule(dev);
-                       
+
                        if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass)))
                                break;
                }
-               
+
                /* Acknowledge the interrupt sources we handle here ASAP
                   the poll function does Rx and RxNoBuf acking */
-               
+
                iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5);
 
-#else 
+#else
                /* Acknowledge all of the current interrupt sources ASAP. */
                iowrite32(csr5 & 0x0001ffff, ioaddr + CSR5);
 
@@ -559,11 +559,11 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                }
 
 #endif /*  CONFIG_TULIP_NAPI */
-               
+
                if (tulip_debug > 4)
                        printk(KERN_DEBUG "%s: interrupt  csr5=%#8.8x new csr5=%#8.8x.\n",
                               dev->name, csr5, ioread32(ioaddr + CSR5));
-               
+
 
                if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) {
                        unsigned int dirty_tx;
@@ -737,17 +737,17 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 #ifdef CONFIG_TULIP_NAPI
                if (rxd)
                        csr5 &= ~RxPollInt;
-       } while ((csr5 & (TxNoBuf | 
-                         TxDied | 
-                         TxIntr | 
+       } while ((csr5 & (TxNoBuf |
+                         TxDied |
+                         TxIntr |
                          TimerInt |
                          /* Abnormal intr. */
-                         RxDied | 
-                         TxFIFOUnderflow | 
-                         TxJabber | 
-                         TPLnkFail |  
+                         RxDied |
+                         TxFIFOUnderflow |
+                         TxJabber |
+                         TPLnkFail |
                          SytemError )) != 0);
-#else 
+#else
        } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0);
 
        tulip_refill_rx(dev);
index f53396fe79c9f95d296dc3995208f0f66c3da8b8..e9bc2a958c1436e0a2b0896d873c12d12961cc43 100644 (file)
@@ -140,7 +140,7 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
                spin_unlock_irqrestore(&tp->mii_lock, flags);
                return;
        }
-               
+
        /* Establish sync by sending 32 logic ones. */
        for (i = 32; i >= 0; i--) {
                iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
index 05d2d96f7be26858c3c66a8f9fbacaf170c8e1bc..d25020da679879ab8e1539fa8f8c2b0be63ea6e9 100644 (file)
@@ -259,7 +259,7 @@ enum t21143_csr6_bits {
    There are no ill effects from too-large receive rings. */
 
 #define TX_RING_SIZE   32
-#define RX_RING_SIZE   128 
+#define RX_RING_SIZE   128
 #define MEDIA_MASK     31
 
 #define PKT_BUF_SZ             1536    /* Size of each temporary Rx buffer. */
index c67c91251d048d74bc60a01029343ba7cbd959c6..cabdf894e21e3c7e3ea39c1705b41237ca15dfa9 100644 (file)
@@ -1224,7 +1224,7 @@ out:
  *     Chips that have the MRM/reserved bit quirk and the burst quirk. That
  *     is the DM910X and the on chip ULi devices
  */
+
 static int tulip_uli_dm_quirk(struct pci_dev *pdev)
 {
        if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
@@ -1297,7 +1297,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
         */
 
        /* 1. Intel Saturn. Switch to 8 long words burst, 8 long word cache
-             aligned.  Aries might need this too. The Saturn errata are not 
+             aligned.  Aries might need this too. The Saturn errata are not
              pretty reading but thankfully it's an old 486 chipset.
 
           2. The dreaded SiS496 486 chipset. Same workaround as Intel
@@ -1483,14 +1483,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                        sa_offset = 2;          /* Grrr, damn Matrox boards. */
                        multiport_cnt = 4;
                }
-#ifdef CONFIG_DDB5476
-               if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 6)) {
-                       /* DDB5476 MAC address in first EEPROM locations. */
-                       sa_offset = 0;
-                       /* No media table either */
-                       tp->flags &= ~HAS_MEDIA_TABLE;
-               }
-#endif
 #ifdef CONFIG_DDB5477
                if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 4)) {
                        /* DDB5477 MAC address in first EEPROM locations. */
@@ -1500,7 +1492,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                }
 #endif
 #ifdef CONFIG_MIPS_COBALT
-               if ((pdev->bus->number == 0) && 
+               if ((pdev->bus->number == 0) &&
                    ((PCI_SLOT(pdev->devfn) == 7) ||
                     (PCI_SLOT(pdev->devfn) == 12))) {
                        /* Cobalt MAC address in first EEPROM locations. */
index 238e9c72cb3ab8c4f1556febafc82fb17deb2875..8b3a28f53c3d0165d096287d4a983359413d8447 100644 (file)
@@ -9,7 +9,7 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
-    
+
 */
 
 #define DRV_NAME       "uli526x"
@@ -185,7 +185,7 @@ struct uli526x_board_info {
 
        /* NIC SROM data */
        unsigned char srom[128];
-       u8 init;        
+       u8 init;
 };
 
 enum uli526x_offsets {
@@ -258,7 +258,7 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
        struct uli526x_board_info *db;  /* board information structure */
        struct net_device *dev;
        int i, err;
-       
+
        ULI526X_DBUG(0, "uli526x_init_one()", 0);
 
        if (!printed_version++)
@@ -316,7 +316,7 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
                err = -ENOMEM;
                goto err_out_nomem;
        }
-       
+
        db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
        db->first_tx_desc_dma = db->desc_pool_dma_ptr;
        db->buf_pool_start = db->buf_pool_ptr;
@@ -324,14 +324,14 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
 
        db->chip_id = ent->driver_data;
        db->ioaddr = pci_resource_start(pdev, 0);
-       
+
        db->pdev = pdev;
        db->init = 1;
-       
+
        dev->base_addr = db->ioaddr;
        dev->irq = pdev->irq;
        pci_set_drvdata(pdev, dev);
-       
+
        /* Register some necessary functions */
        dev->open = &uli526x_open;
        dev->hard_start_xmit = &uli526x_start_xmit;
@@ -341,7 +341,7 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
        dev->ethtool_ops = &netdev_ethtool_ops;
        spin_lock_init(&db->lock);
 
-               
+
        /* read 64 word srom data */
        for (i = 0; i < 64; i++)
                ((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i));
@@ -374,7 +374,7 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
                goto err_out_res;
 
        printk(KERN_INFO "%s: ULi M%04lx at pci%s,",dev->name,ent->driver_data >> 16,pci_name(pdev));
-       
+
        for (i = 0; i < 6; i++)
                printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
        printk(", irq %d.\n", dev->irq);
@@ -389,7 +389,7 @@ err_out_nomem:
        if(db->desc_pool_ptr)
                pci_free_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20,
                        db->desc_pool_ptr, db->desc_pool_dma_ptr);
-                       
+
        if(db->buf_pool_ptr != NULL)
                pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
                        db->buf_pool_ptr, db->buf_pool_dma_ptr);
@@ -433,7 +433,7 @@ static int uli526x_open(struct net_device *dev)
 {
        int ret;
        struct uli526x_board_info *db = netdev_priv(dev);
-       
+
        ULI526X_DBUG(0, "uli526x_open", 0);
 
        ret = request_irq(dev->irq, &uli526x_interrupt, SA_SHIRQ, dev->name, dev);
@@ -454,7 +454,7 @@ static int uli526x_open(struct net_device *dev)
        /* CR6 operation mode decision */
        db->cr6_data |= ULI526X_TXTH_256;
        db->cr0_data = CR0_DEFAULT;
-       
+
        /* Initialize ULI526X board */
        uli526x_init(dev);
 
@@ -604,7 +604,7 @@ static int uli526x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Restore CR7 to enable interrupt */
        spin_unlock_irqrestore(&db->lock, flags);
        outl(db->cr7_data, dev->base_addr + DCR7);
-       
+
        /* free this SKB */
        dev_kfree_skb(skb);
 
@@ -782,7 +782,7 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
        struct sk_buff *skb;
        int rxlen;
        u32 rdes0;
-       
+
        rxptr = db->rx_ready_ptr;
 
        while(db->rx_avail_cnt) {
@@ -821,7 +821,7 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
                        if ( !(rdes0 & 0x8000) ||
                                ((db->cr6_data & CR6_PM) && (rxlen>6)) ) {
                                skb = rxptr->rx_skb_ptr;
-               
+
                                /* Good packet, send to upper layer */
                                /* Shorst packet used new SKB */
                                if ( (rxlen < RX_COPY_SIZE) &&
@@ -841,7 +841,7 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
                                dev->last_rx = jiffies;
                                db->stats.rx_packets++;
                                db->stats.rx_bytes += rxlen;
-                               
+
                        } else {
                                /* Reuse SKB buffer when the packet is error */
                                ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
@@ -911,7 +911,7 @@ ULi_ethtool_gset(struct uli526x_board_info *db, struct ethtool_cmd *ecmd)
                           SUPPORTED_100baseT_Full |
                           SUPPORTED_Autoneg |
                           SUPPORTED_MII);
-               
+
        ecmd->advertising = (ADVERTISED_10baseT_Half |
                           ADVERTISED_10baseT_Full |
                           ADVERTISED_100baseT_Half |
@@ -924,13 +924,13 @@ ULi_ethtool_gset(struct uli526x_board_info *db, struct ethtool_cmd *ecmd)
        ecmd->phy_address = db->phy_addr;
 
        ecmd->transceiver = XCVR_EXTERNAL;
-               
+
        ecmd->speed = 10;
        ecmd->duplex = DUPLEX_HALF;
-       
+
        if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)
        {
-               ecmd->speed = 100;               
+               ecmd->speed = 100;
        }
        if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD)
        {
@@ -939,11 +939,11 @@ ULi_ethtool_gset(struct uli526x_board_info *db, struct ethtool_cmd *ecmd)
        if(db->link_failed)
        {
                ecmd->speed = -1;
-               ecmd->duplex = -1;      
+               ecmd->duplex = -1;
        }
-       
+
        if (db->media_mode & ULI526X_AUTO)
-       {       
+       {
                ecmd->autoneg = AUTONEG_ENABLE;
        }
 }
@@ -964,15 +964,15 @@ static void netdev_get_drvinfo(struct net_device *dev,
 
 static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) {
        struct uli526x_board_info *np = netdev_priv(dev);
-       
+
        ULi_ethtool_gset(np, cmd);
-       
+
        return 0;
 }
 
 static u32 netdev_get_link(struct net_device *dev) {
        struct uli526x_board_info *np = netdev_priv(dev);
-               
+
        if(np->link_failed)
                return 0;
        else
@@ -1005,11 +1005,11 @@ static void uli526x_timer(unsigned long data)
        struct uli526x_board_info *db = netdev_priv(dev);
        unsigned long flags;
        u8 TmpSpeed=10;
-       
+
        //ULI526X_DBUG(0, "uli526x_timer()", 0);
        spin_lock_irqsave(&db->lock, flags);
 
-       
+
        /* Dynamic reset ULI526X : system error or transmit time-out */
        tmp_cr8 = inl(db->ioaddr + DCR8);
        if ( (db->interval_rx_cnt==0) && (tmp_cr8) ) {
@@ -1021,9 +1021,9 @@ static void uli526x_timer(unsigned long data)
        /* TX polling kick monitor */
        if ( db->tx_packet_cnt &&
             time_after(jiffies, dev->trans_start + ULI526X_TX_KICK) ) {
-               outl(0x1, dev->base_addr + DCR1);   // Tx polling again 
+               outl(0x1, dev->base_addr + DCR1);   // Tx polling again
 
-               // TX Timeout 
+               // TX Timeout
                if ( time_after(jiffies, dev->trans_start + ULI526X_TX_TIMEOUT) ) {
                        db->reset_TXtimeout++;
                        db->wait_reset = 1;
@@ -1073,7 +1073,7 @@ static void uli526x_timer(unsigned long data)
                                uli526x_sense_speed(db) )
                                db->link_failed = 1;
                        uli526x_process_mode(db);
-                       
+
                        if(db->link_failed==0)
                        {
                                if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)
@@ -1404,7 +1404,7 @@ static u8 uli526x_sense_speed(struct uli526x_board_info * db)
        phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
 
        if ( (phy_mode & 0x24) == 0x24 ) {
-               
+
                phy_mode = ((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)<<7);
                if(phy_mode&0x8000)
                        phy_mode = 0x8000;
@@ -1414,7 +1414,7 @@ static u8 uli526x_sense_speed(struct uli526x_board_info * db)
                        phy_mode = 0x2000;
                else
                        phy_mode = 0x1000;
-               
+
                /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */
                switch (phy_mode) {
                case 0x1000: db->op_mode = ULI526X_10MHF; break;
@@ -1442,7 +1442,7 @@ static u8 uli526x_sense_speed(struct uli526x_board_info * db)
 static void uli526x_set_phyxcer(struct uli526x_board_info *db)
 {
        u16 phy_reg;
-       
+
        /* Phyxcer capability setting */
        phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
 
@@ -1457,7 +1457,7 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)
                case ULI526X_100MHF: phy_reg |= 0x80; break;
                case ULI526X_100MFD: phy_reg |= 0x100; break;
                }
-               
+
        }
 
        /* Write new capability to Phyxcer Reg4 */
@@ -1556,7 +1556,7 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data
        /* Write a word data to PHY controller */
        for ( i = 0x8000; i > 0; i >>= 1)
                phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
-       
+
 }
 
 
@@ -1574,7 +1574,7 @@ static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
                return phy_readby_cr10(iobase, phy_addr, offset);
        /* M5261/M5263 Chip */
        ioaddr = iobase + DCR9;
-       
+
        /* Send 33 synchronization clock to Phy controller */
        for (i = 0; i < 35; i++)
                phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
@@ -1610,7 +1610,7 @@ static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
 static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset)
 {
        unsigned long ioaddr,cr10_value;
-       
+
        ioaddr = iobase + DCR10;
        cr10_value = phy_addr;
        cr10_value = (cr10_value<<5) + offset;
@@ -1629,7 +1629,7 @@ static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset)
 static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data)
 {
        unsigned long ioaddr,cr10_value;
-       
+
        ioaddr = iobase + DCR10;
        cr10_value = phy_addr;
        cr10_value = (cr10_value<<5) + offset;
@@ -1659,7 +1659,7 @@ static void phy_write_1bit(unsigned long ioaddr, u32 phy_data, u32 chip_id)
 static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id)
 {
        u16 phy_data;
-       
+
        outl(0x50000 , ioaddr);
        udelay(1);
        phy_data = ( inl(ioaddr) >> 19 ) & 0x1;
index 136a70c4d5e4880c442cfd75bf5f6450a621cfb9..8fea2aa455d4690a10763f7a4dc070c755a9c3d0 100644 (file)
                        Copyright (C) 2001 Manfred Spraul
        * ethtool support (jgarzik)
        * Replace some MII-related magic numbers with constants (jgarzik)
-  
+
        TODO:
        * enable pci_power_off
        * Wake-On-LAN
 */
-  
+
 #define DRV_NAME       "winbond-840"
 #define DRV_VERSION    "1.01-d"
 #define DRV_RELDATE    "Nov-17-2001"
@@ -57,7 +57,7 @@ c-help-name: Winbond W89c840 PCI Ethernet support
 c-help-symbol: CONFIG_WINBOND_840
 c-help: This driver is for the Winbond W89c840 chip.  It also works with
 c-help: the TX9882 chip on the Compex RL100-ATX board.
-c-help: More specific information and updates are available from 
+c-help: More specific information and updates are available from
 c-help: http://www.scyld.com/network/drivers.html
 */
 
@@ -207,7 +207,7 @@ Test with 'ping -s 10000' on a fast computer.
 
 */
 
-\f
+
 
 /*
   PCI probe table.
@@ -374,7 +374,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct ethtool_ops netdev_ethtool_ops;
 static int  netdev_close(struct net_device *dev);
 
-\f
+
 
 static int __devinit w840_probe1 (struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
@@ -434,7 +434,7 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
        np->mii_if.mdio_read = mdio_read;
        np->mii_if.mdio_write = mdio_write;
        np->base_addr = ioaddr;
-       
+
        pci_set_drvdata(pdev, dev);
 
        if (dev->mem_start)
@@ -510,7 +510,7 @@ err_out_netdev:
        return -ENODEV;
 }
 
-\f
+
 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces.  These are
    often serial bit streams generated by the host processor.
    The example below is for the common 93c46 EEPROM, 64 16 bit words. */
@@ -660,7 +660,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
        return;
 }
 
-\f
+
 static int netdev_open(struct net_device *dev)
 {
        struct netdev_private *np = netdev_priv(dev);
@@ -731,7 +731,7 @@ static int update_link(struct net_device *dev)
                                dev->name, np->phys[0]);
                netif_carrier_on(dev);
        }
-       
+
        if ((np->mii & ~0xf) == MII_DAVICOM_DM9101) {
                /* If the link partner doesn't support autonegotiation
                 * the MII detects it's abilities with the "parallel detection".
@@ -761,7 +761,7 @@ static int update_link(struct net_device *dev)
                result |= 0x20000000;
        if (result != np->csr6 && debug)
                printk(KERN_INFO "%s: Setting %dMBit-%s-duplex based on MII#%d\n",
-                                dev->name, fasteth ? 100 : 10, 
+                                dev->name, fasteth ? 100 : 10,
                                duplex ? "full" : "half", np->phys[0]);
        return result;
 }
@@ -947,7 +947,7 @@ static void init_registers(struct net_device *dev)
        iowrite32(i, ioaddr + PCIBusCfg);
 
        np->csr6 = 0;
-       /* 128 byte Tx threshold; 
+       /* 128 byte Tx threshold;
                Transmit on; Receive on; */
        update_csr6(dev, 0x00022002 | update_link(dev) | __set_rx_mode(dev));
 
@@ -1584,7 +1584,7 @@ static int netdev_close(struct net_device *dev)
 static void __devexit w840_remove1 (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       
+
        if (dev) {
                struct netdev_private *np = netdev_priv(dev);
                unregister_netdev(dev);
@@ -1605,11 +1605,11 @@ static void __devexit w840_remove1 (struct pci_dev *pdev)
  * - get_stats:
  *     spin_lock_irq(np->lock), doesn't touch hw if not present
  * - hard_start_xmit:
- *     netif_stop_queue + spin_unlock_wait(&dev->xmit_lock);
+ *     synchronize_irq + netif_tx_disable;
  * - tx_timeout:
- *     netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
+ *     netif_device_detach + netif_tx_disable;
  * - set_multicast_list
- *     netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
+ *     netif_device_detach + netif_tx_disable;
  * - interrupt handler
  *     doesn't touch hw if not present, synchronize_irq waits for
  *     running instances of the interrupt handler.
@@ -1635,11 +1635,10 @@ static int w840_suspend (struct pci_dev *pdev, pm_message_t state)
                netif_device_detach(dev);
                update_csr6(dev, 0);
                iowrite32(0, ioaddr + IntrEnable);
-               netif_stop_queue(dev);
                spin_unlock_irq(&np->lock);
 
-               spin_unlock_wait(&dev->xmit_lock);
                synchronize_irq(dev->irq);
+               netif_tx_disable(dev);
        
                np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff;
 
index 56344103ac233add684581f3c3f30ecef45d4031..63c2175ed138bb89f496fdba3cb8b1092556771c 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * xircom_cb: A driver for the (tulip-like) Xircom Cardbus ethernet cards 
+ * xircom_cb: A driver for the (tulip-like) Xircom Cardbus ethernet cards
  *
  * This software is (C) by the respective authors, and licensed under the GPL
  * License.
  *
  * Written by Arjan van de Ven for Red Hat, Inc.
- * Based on work by Jeff Garzik, Doug Ledford and Donald Becker 
+ * Based on work by Jeff Garzik, Doug Ledford and Donald Becker
  *
  *     This software may be used and distributed according to the terms
  *      of the GNU General Public License, incorporated herein by reference.
@@ -93,7 +93,7 @@ struct xircom_private {
 
        unsigned long io_port;
        int open;
-       
+
        /* transmit_used is the rotating counter that indicates which transmit
           descriptor has to be used next */
        int transmit_used;
@@ -153,10 +153,10 @@ static struct pci_device_id xircom_pci_table[] = {
 MODULE_DEVICE_TABLE(pci, xircom_pci_table);
 
 static struct pci_driver xircom_ops = {
-       .name           = "xircom_cb", 
-       .id_table       = xircom_pci_table, 
-       .probe          = xircom_probe, 
-       .remove         = xircom_remove, 
+       .name           = "xircom_cb",
+       .id_table       = xircom_pci_table,
+       .probe          = xircom_probe,
+       .remove         = xircom_remove,
        .suspend =NULL,
        .resume =NULL
 };
@@ -174,7 +174,7 @@ static void print_binary(unsigned int number)
                        buffer[i2++]='1';
                else
                        buffer[i2++]='0';
-               if ((i&3)==0) 
+               if ((i&3)==0)
                        buffer[i2++]=' ';
        }
        printk("%s\n",buffer);
@@ -196,10 +196,10 @@ static struct ethtool_ops netdev_ethtool_ops = {
 
 /* xircom_probe is the code that gets called on device insertion.
    it sets up the hardware and registers the device to the networklayer.
-   
+
    TODO: Send 1 or 2 "dummy" packets here as the card seems to discard the
          first two packets that get send, and pump hates that.
-         
+
  */
 static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -209,7 +209,7 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
        unsigned long flags;
        unsigned short tmp16;
        enter("xircom_probe");
-       
+
        /* First do the PCI initialisation */
 
        if (pci_enable_device(pdev))
@@ -217,24 +217,24 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
 
        /* disable all powermanagement */
        pci_write_config_dword(pdev, PCI_POWERMGMT, 0x0000);
-       
+
        pci_set_master(pdev); /* Why isn't this done by pci_enable_device ?*/
 
-       /* clear PCI status, if any */ 
-       pci_read_config_word (pdev,PCI_STATUS, &tmp16); 
+       /* clear PCI status, if any */
+       pci_read_config_word (pdev,PCI_STATUS, &tmp16);
        pci_write_config_word (pdev, PCI_STATUS,tmp16);
-       
+
        pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
-       
+
        if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) {
                printk(KERN_ERR "xircom_probe: failed to allocate io-region\n");
                return -ENODEV;
        }
 
-       /* 
+       /*
           Before changing the hardware, allocate the memory.
           This way, we can fail gracefully if not enough memory
-          is available. 
+          is available.
         */
        dev = alloc_etherdev(sizeof(struct xircom_private));
        if (!dev) {
@@ -242,13 +242,13 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
                goto device_fail;
        }
        private = netdev_priv(dev);
-       
+
        /* Allocate the send/receive buffers */
        private->rx_buffer = pci_alloc_consistent(pdev,8192,&private->rx_dma_handle);
        if (private->rx_buffer == NULL) {
                printk(KERN_ERR "xircom_probe: no memory for rx buffer \n");
                goto rx_buf_fail;
-       }       
+       }
        private->tx_buffer = pci_alloc_consistent(pdev,8192,&private->tx_dma_handle);
        if (private->tx_buffer == NULL) {
                printk(KERN_ERR "xircom_probe: no memory for tx buffer \n");
@@ -265,11 +265,11 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
        spin_lock_init(&private->lock);
        dev->irq = pdev->irq;
        dev->base_addr = private->io_port;
-       
+
        initialize_card(private);
        read_mac_address(private);
        setup_descriptors(private);
-       
+
        dev->open = &xircom_open;
        dev->hard_start_xmit = &xircom_start_xmit;
        dev->stop = &xircom_close;
@@ -285,19 +285,19 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
                printk(KERN_ERR "xircom_probe: netdevice registration failed.\n");
                goto reg_fail;
        }
-               
+
        printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq);
        /* start the transmitter to get a heartbeat */
        /* TODO: send 2 dummy packets here */
        transceiver_voodoo(private);
-       
+
        spin_lock_irqsave(&private->lock,flags);
        activate_transmitter(private);
        activate_receiver(private);
        spin_unlock_irqrestore(&private->lock,flags);
-       
+
        trigger_receive(private);
-       
+
        leave("xircom_probe");
        return 0;
 
@@ -332,7 +332,7 @@ static void __devexit xircom_remove(struct pci_dev *pdev)
        free_netdev(dev);
        pci_set_drvdata(pdev, NULL);
        leave("xircom_remove");
-} 
+}
 
 static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
@@ -346,11 +346,11 @@ static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs
        spin_lock(&card->lock);
        status = inl(card->io_port+CSR5);
 
-#ifdef DEBUG   
+#ifdef DEBUG
        print_binary(status);
        printk("tx status 0x%08x 0x%08x \n",card->tx_buffer[0],card->tx_buffer[4]);
        printk("rx status 0x%08x 0x%08x \n",card->rx_buffer[0],card->rx_buffer[4]);
-#endif 
+#endif
        /* Handle shared irq and hotplug */
        if (status == 0 || status == 0xffffffff) {
                spin_unlock(&card->lock);
@@ -366,21 +366,21 @@ static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs
                        netif_carrier_on(dev);
                else
                        netif_carrier_off(dev);
-               
+
        }
 
-       /* Clear all remaining interrupts */    
+       /* Clear all remaining interrupts */
        status |= 0xffffffff; /* FIXME: make this clear only the
                                        real existing bits */
        outl(status,card->io_port+CSR5);
-       
 
-       for (i=0;i<NUMDESCRIPTORS;i++) 
+
+       for (i=0;i<NUMDESCRIPTORS;i++)
                investigate_write_descriptor(dev,card,i,bufferoffsets[i]);
-       for (i=0;i<NUMDESCRIPTORS;i++) 
+       for (i=0;i<NUMDESCRIPTORS;i++)
                investigate_read_descriptor(dev,card,i,bufferoffsets[i]);
 
-       
+
        spin_unlock(&card->lock);
        leave("xircom_interrupt");
        return IRQ_HANDLED;
@@ -393,38 +393,38 @@ static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
        int nextdescriptor;
        int desc;
        enter("xircom_start_xmit");
-       
+
        card = netdev_priv(dev);
        spin_lock_irqsave(&card->lock,flags);
-       
+
        /* First see if we can free some descriptors */
-       for (desc=0;desc<NUMDESCRIPTORS;desc++) 
+       for (desc=0;desc<NUMDESCRIPTORS;desc++)
                investigate_write_descriptor(dev,card,desc,bufferoffsets[desc]);
-       
-       
+
+
        nextdescriptor = (card->transmit_used +1) % (NUMDESCRIPTORS);
        desc = card->transmit_used;
-       
+
        /* only send the packet if the descriptor is free */
        if (card->tx_buffer[4*desc]==0) {
                        /* Copy the packet data; zero the memory first as the card
                           sometimes sends more than you ask it to. */
-                       
+
                        memset(&card->tx_buffer[bufferoffsets[desc]/4],0,1536);
                        memcpy(&(card->tx_buffer[bufferoffsets[desc]/4]),skb->data,skb->len);
-       
-       
+
+
                        /* FIXME: The specification tells us that the length we send HAS to be a multiple of
                           4 bytes. */
-                          
+
                        card->tx_buffer[4*desc+1] = skb->len;
                        if (desc == NUMDESCRIPTORS-1)
                                card->tx_buffer[4*desc+1] |= (1<<25);  /* bit 25: last descriptor of the ring */
 
                        card->tx_buffer[4*desc+1] |= 0xF0000000;
-                                                /* 0xF0... means want interrupts*/ 
+                                                /* 0xF0... means want interrupts*/
                        card->tx_skb[desc] = skb;
-                       
+
                        wmb();
                        /* This gives the descriptor to the card */
                        card->tx_buffer[4*desc] = 0x80000000;
@@ -433,18 +433,18 @@ static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                netif_stop_queue(dev);
                        }
                        card->transmit_used = nextdescriptor;
-                       leave("xircom-start_xmit - sent");      
+                       leave("xircom-start_xmit - sent");
                        spin_unlock_irqrestore(&card->lock,flags);
                        return 0;
        }
-       
+
 
 
        /* Uh oh... no free descriptor... drop the packet */
        netif_stop_queue(dev);
        spin_unlock_irqrestore(&card->lock,flags);
        trigger_transmit(card);
-       
+
        return -EIO;
 }
 
@@ -462,7 +462,7 @@ static int xircom_open(struct net_device *dev)
                leave("xircom_open - No IRQ");
                return retval;
        }
-       
+
        xircom_up(xp);
        xp->open = 1;
        leave("xircom_open");
@@ -473,31 +473,31 @@ static int xircom_close(struct net_device *dev)
 {
        struct xircom_private *card;
        unsigned long flags;
-       
+
        enter("xircom_close");
        card = netdev_priv(dev);
        netif_stop_queue(dev); /* we don't want new packets */
 
-       
+
        spin_lock_irqsave(&card->lock,flags);
-       
+
        disable_all_interrupts(card);
-#if 0  
+#if 0
        /* We can enable this again once we send dummy packets on ifconfig ethX up */
        deactivate_receiver(card);
        deactivate_transmitter(card);
-#endif 
+#endif
        remove_descriptors(card);
-       
+
        spin_unlock_irqrestore(&card->lock,flags);
-       
+
        card->open = 0;
        free_irq(dev->irq,dev);
-       
+
        leave("xircom_close");
-       
+
        return 0;
-       
+
 }
 
 
@@ -506,8 +506,8 @@ static struct net_device_stats *xircom_get_stats(struct net_device *dev)
 {
         struct xircom_private *card = netdev_priv(dev);
         return &card->stats;
-} 
-                                                 
+}
+
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void xircom_poll_controller(struct net_device *dev)
@@ -540,7 +540,7 @@ static void initialize_card(struct xircom_private *card)
        outl(val, card->io_port + CSR0);
 
 
-       val = 0;                /* Value 0x00 is a safe and conservative value 
+       val = 0;                /* Value 0x00 is a safe and conservative value
                                   for the PCI configuration settings */
        outl(val, card->io_port + CSR0);
 
@@ -617,23 +617,23 @@ static void setup_descriptors(struct xircom_private *card)
 
                /* Rx Descr2: address of the buffer
                   we store the buffer at the 2nd half of the page */
-       
+
                address = (unsigned long) card->rx_dma_handle;
                card->rx_buffer[i*4 + 2] = cpu_to_le32(address + bufferoffsets[i]);
                /* Rx Desc3: address of 2nd buffer -> 0 */
                card->rx_buffer[i*4 + 3] = 0;
        }
-       
+
        wmb();
        /* Write the receive descriptor ring address to the card */
        address = (unsigned long) card->rx_dma_handle;
-       val = cpu_to_le32(address); 
+       val = cpu_to_le32(address);
        outl(val, card->io_port + CSR3);        /* Receive descr list address */
 
 
        /* transmit descriptors */
        memset(card->tx_buffer, 0, 128);        /* clear the descriptors */
-       
+
        for (i=0;i<NUMDESCRIPTORS;i++ ) {
                /* Tx Descr0: Empty, we own it, no errors -> 0x00000000 */
                card->tx_buffer[i*4 + 0] = 0x00000000;
@@ -641,7 +641,7 @@ static void setup_descriptors(struct xircom_private *card)
                card->tx_buffer[i*4 + 1] = 1536;
                if (i==NUMDESCRIPTORS-1)
                        card->tx_buffer[i*4 + 1] |= (1 << 25); /* bit 25 is "last descriptor" */
-               
+
                /* Tx Descr2: address of the buffer
                   we store the buffer at the 2nd half of the page */
                address = (unsigned long) card->tx_dma_handle;
@@ -748,7 +748,7 @@ static int receive_active(struct xircom_private *card)
 activate_receiver enables the receiver on the card.
 Before being allowed to active the receiver, the receiver
 must be completely de-activated. To achieve this,
-this code actually disables the receiver first; then it waits for the 
+this code actually disables the receiver first; then it waits for the
 receiver to become inactive, then it activates the receiver and then
 it waits for the receiver to be active.
 
@@ -762,13 +762,13 @@ static void activate_receiver(struct xircom_private *card)
 
 
        val = inl(card->io_port + CSR6);        /* Operation mode */
-       
+
        /* If the "active" bit is set and the receiver is already
           active, no need to do the expensive thing */
        if ((val&2) && (receive_active(card)))
                return;
-       
-       
+
+
        val = val & ~2;         /* disable the receiver */
        outl(val, card->io_port + CSR6);
 
@@ -805,7 +805,7 @@ static void activate_receiver(struct xircom_private *card)
 
 /*
 deactivate_receiver disables the receiver on the card.
-To achieve this this code disables the receiver first; 
+To achieve this this code disables the receiver first;
 then it waits for the receiver to become inactive.
 
 must be called with the lock held and interrupts disabled.
@@ -840,7 +840,7 @@ static void deactivate_receiver(struct xircom_private *card)
 activate_transmitter enables the transmitter on the card.
 Before being allowed to active the transmitter, the transmitter
 must be completely de-activated. To achieve this,
-this code actually disables the transmitter first; then it waits for the 
+this code actually disables the transmitter first; then it waits for the
 transmitter to become inactive, then it activates the transmitter and then
 it waits for the transmitter to be active again.
 
@@ -856,7 +856,7 @@ static void activate_transmitter(struct xircom_private *card)
        val = inl(card->io_port + CSR6);        /* Operation mode */
 
        /* If the "active" bit is set and the receiver is already
-          active, no need to do the expensive thing */  
+          active, no need to do the expensive thing */
        if ((val&(1<<13)) && (transmit_active(card)))
                return;
 
@@ -896,7 +896,7 @@ static void activate_transmitter(struct xircom_private *card)
 
 /*
 deactivate_transmitter disables the transmitter on the card.
-To achieve this this code disables the transmitter first; 
+To achieve this this code disables the transmitter first;
 then it waits for the transmitter to become inactive.
 
 must be called with the lock held and interrupts disabled.
@@ -990,7 +990,7 @@ static void disable_all_interrupts(struct xircom_private *card)
 {
        unsigned int val;
        enter("enable_all_interrupts");
-       
+
        val = 0;                                /* disable all interrupts */
        outl(val, card->io_port + CSR7);
 
@@ -1031,8 +1031,8 @@ static int enable_promisc(struct xircom_private *card)
        unsigned int val;
        enter("enable_promisc");
 
-       val = inl(card->io_port + CSR6);        
-       val = val | (1 << 6);   
+       val = inl(card->io_port + CSR6);
+       val = val | (1 << 6);
        outl(val, card->io_port + CSR6);
 
        leave("enable_promisc");
@@ -1042,7 +1042,7 @@ static int enable_promisc(struct xircom_private *card)
 
 
 
-/* 
+/*
 link_status() checks the the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what.
 
 Must be called in locked state with interrupts disabled
@@ -1051,15 +1051,15 @@ static int link_status(struct xircom_private *card)
 {
        unsigned int val;
        enter("link_status");
-       
+
        val = inb(card->io_port + CSR12);
-       
+
        if (!(val&(1<<2)))  /* bit 2 is 0 for 10mbit link, 1 for not an 10mbit link */
                return 10;
        if (!(val&(1<<1)))  /* bit 1 is 0 for 100mbit link, 1 for not an 100mbit link */
                return 100;
-               
-       /* If we get here -> no link at all */  
+
+       /* If we get here -> no link at all */
 
        leave("link_status");
        return 0;
@@ -1071,7 +1071,7 @@ static int link_status(struct xircom_private *card)
 
 /*
   read_mac_address() reads the MAC address from the NIC and stores it in the "dev" structure.
+
   This function will take the spinlock itself and can, as a result, not be called with the lock helt.
  */
 static void read_mac_address(struct xircom_private *card)
@@ -1081,7 +1081,7 @@ static void read_mac_address(struct xircom_private *card)
        int i;
 
        enter("read_mac_address");
-               
+
        spin_lock_irqsave(&card->lock, flags);
 
        outl(1 << 12, card->io_port + CSR9);    /* enable boot rom access */
@@ -1095,7 +1095,7 @@ static void read_mac_address(struct xircom_private *card)
                outl(i + 3, card->io_port + CSR10);
                data_count = inl(card->io_port + CSR9) & 0xff;
                if ((tuple == 0x22) && (data_id == 0x04) && (data_count == 0x06)) {
-                       /* 
+                       /*
                         * This is it.  We have the data we want.
                         */
                        for (j = 0; j < 6; j++) {
@@ -1136,12 +1136,12 @@ static void transceiver_voodoo(struct xircom_private *card)
        spin_lock_irqsave(&card->lock, flags);
 
        outl(0x0008, card->io_port + CSR15);
-        udelay(25);  
+        udelay(25);
         outl(0xa8050000, card->io_port + CSR15);
         udelay(25);
         outl(0xa00f0000, card->io_port + CSR15);
         udelay(25);
-        
+
         spin_unlock_irqrestore(&card->lock, flags);
 
        netif_start_queue(card->dev);
@@ -1163,15 +1163,15 @@ static void xircom_up(struct xircom_private *card)
 
        spin_lock_irqsave(&card->lock, flags);
 
-       
+
        enable_link_interrupt(card);
        enable_transmit_interrupt(card);
        enable_receive_interrupt(card);
        enable_common_interrupts(card);
        enable_promisc(card);
-       
+
        /* The card can have received packets already, read them away now */
-       for (i=0;i<NUMDESCRIPTORS;i++) 
+       for (i=0;i<NUMDESCRIPTORS;i++)
                investigate_read_descriptor(card->dev,card,i,bufferoffsets[i]);
 
 
@@ -1185,15 +1185,15 @@ static void xircom_up(struct xircom_private *card)
 /* Bufferoffset is in BYTES */
 static void investigate_read_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset)
 {
-               int status;             
-               
+               int status;
+
                enter("investigate_read_descriptor");
                status = card->rx_buffer[4*descnr];
-               
+
                if ((status > 0)) {     /* packet received */
-               
+
                        /* TODO: discard error packets */
-                       
+
                        short pkt_len = ((status >> 16) & 0x7ff) - 4;   /* minus 4, we don't want the CRC */
                        struct sk_buff *skb;
 
@@ -1216,7 +1216,7 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri
                        dev->last_rx = jiffies;
                        card->stats.rx_packets++;
                        card->stats.rx_bytes += pkt_len;
-                       
+
                      out:
                        /* give the buffer back to the card */
                        card->rx_buffer[4*descnr] =  0x80000000;
@@ -1234,9 +1234,9 @@ static void investigate_write_descriptor(struct net_device *dev, struct xircom_p
                int status;
 
                enter("investigate_write_descriptor");
-               
+
                status = card->tx_buffer[4*descnr];
-#if 0          
+#if 0
                if (status & 0x8000) {  /* Major error */
                        printk(KERN_ERR "Major transmit error status %x \n", status);
                        card->tx_buffer[4*descnr] = 0;
@@ -1258,7 +1258,7 @@ static void investigate_write_descriptor(struct net_device *dev, struct xircom_p
                }
 
                leave("investigate_write_descriptor");
-               
+
 }
 
 
@@ -1271,8 +1271,8 @@ static int __init xircom_init(void)
 static void __exit xircom_exit(void)
 {
        pci_unregister_driver(&xircom_ops);
-} 
+}
 
-module_init(xircom_init) 
+module_init(xircom_init)
 module_exit(xircom_exit)
 
index ed1f837c8fda2274a3874855550f1d39e81f1bcd..2eb6b5f9ba0df647bd760b43abcec48216241df6 100644 (file)
@@ -1899,6 +1899,13 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
 
        int pktlen = skb->len;
 
+#ifdef VELOCITY_ZERO_COPY_SUPPORT
+       if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
+               kfree_skb(skb);
+               return 0;
+       }
+#endif
+
        spin_lock_irqsave(&vptr->lock, flags);
 
        index = vptr->td_curr[qnum];
@@ -1914,8 +1921,6 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
         */
        if (pktlen < ETH_ZLEN) {
                /* Cannot occur until ZC support */
-               if(skb_linearize(skb, GFP_ATOMIC))
-                       return 0; 
                pktlen = ETH_ZLEN;
                memcpy(tdinfo->buf, skb->data, skb->len);
                memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len);
@@ -1933,7 +1938,6 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
                int nfrags = skb_shinfo(skb)->nr_frags;
                tdinfo->skb = skb;
                if (nfrags > 6) {
-                       skb_linearize(skb, GFP_ATOMIC);
                        memcpy(tdinfo->buf, skb->data, skb->len);
                        tdinfo->skb_dma[0] = tdinfo->buf_dma;
                        td_ptr->tdesc0.pktsize = 
index d9a774b91ddcd8550b6d0caa4fbbd1f9812331b3..f1b2640ebdc660a1ce605ad3796f413339244119 100644 (file)
@@ -307,7 +307,7 @@ enum  velocity_owner {
 #define TX_QUEUE_NO         4
 
 #define MAX_HW_MIB_COUNTER  32
-#define VELOCITY_MIN_MTU    (1514-14)
+#define VELOCITY_MIN_MTU    (64)
 #define VELOCITY_MAX_MTU    (9000)
 
 /*
index eba8e5cfacc285c1d487d36e088556507fcbe26c..f485a97844ccf3f06dc4e5b6b76053e5245d7ad9 100644 (file)
@@ -50,10 +50,6 @@ static const char* devname = "PCI200SYN";
 static int pci_clock_freq = 33000000;
 #define CLOCK_BASE pci_clock_freq
 
-#define PCI_VENDOR_ID_GORAMO   0x10B5  /* uses PLX:9050 ID - this card */
-#define PCI_DEVICE_ID_PCI200SYN        0x9050  /* doesn't have its own ID      */
-
-
 /*
  *      PLX PCI9052 local configuration and shared runtime registers.
  *      This structure can be used to access 9052 registers (memory mapped).
@@ -262,7 +258,7 @@ static void pci200_pci_remove_one(struct pci_dev *pdev)
        int i;
        card_t *card = pci_get_drvdata(pdev);
 
-       for(i = 0; i < 2; i++)
+       for (i = 0; i < 2; i++)
                if (card->ports[i].card) {
                        struct net_device *dev = port_to_dev(&card->ports[i]);
                        unregister_hdlc_device(dev);
@@ -385,6 +381,15 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
               " %u RX packets rings\n", ramsize / 1024, ramphys,
               pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
 
+       if (pdev->subsystem_device == PCI_DEVICE_ID_PLX_9050) {
+               printk(KERN_ERR "Detected PCI200SYN card with old "
+                      "configuration data.\n");
+               printk(KERN_ERR "See <http://www.kernel.org/pub/"
+                      "linux/utils/net/hdlc/pci200syn/> for update.\n");
+               printk(KERN_ERR "The card will stop working with"
+                      " future versions of Linux if not updated.\n");
+       }
+
        if (card->tx_ring_buffers < 1) {
                printk(KERN_ERR "pci200syn: RAM test failed\n");
                pci200_pci_remove_one(pdev);
@@ -396,7 +401,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
        writew(readw(p) | 0x0040, p);
 
        /* Allocate IRQ */
-       if(request_irq(pdev->irq, sca_intr, SA_SHIRQ, devname, card)) {
+       if (request_irq(pdev->irq, sca_intr, SA_SHIRQ, devname, card)) {
                printk(KERN_WARNING "pci200syn: could not allocate IRQ%d.\n",
                       pdev->irq);
                pci200_pci_remove_one(pdev);
@@ -406,7 +411,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
 
        sca_init(card, 0);
 
-       for(i = 0; i < 2; i++) {
+       for (i = 0; i < 2; i++) {
                port_t *port = &card->ports[i];
                struct net_device *dev = port_to_dev(port);
                hdlc_device *hdlc = dev_to_hdlc(dev);
@@ -425,7 +430,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
                hdlc->xmit = sca_xmit;
                port->settings.clock_type = CLOCK_EXT;
                port->card = card;
-               if(register_hdlc_device(dev)) {
+               if (register_hdlc_device(dev)) {
                        printk(KERN_ERR "pci200syn: unable to register hdlc "
                               "device\n");
                        port->card = NULL;
@@ -445,8 +450,10 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
 
 
 static struct pci_device_id pci200_pci_tbl[] __devinitdata = {
-       { PCI_VENDOR_ID_GORAMO, PCI_DEVICE_ID_PCI200SYN, PCI_ANY_ID,
-         PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
+         PCI_DEVICE_ID_PLX_9050, 0, 0, 0 },
+       { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
+         PCI_DEVICE_ID_PLX_PCI200SYN, 0, 0, 0 },
        { 0, }
 };
 
index e0874cbfefea36ff0a16b8943437f9b9f2ed5a67..30ec235e6935505a13057f18617f12038e6051d6 100644 (file)
@@ -235,7 +235,35 @@ config IPW2200_MONITOR
          promiscuous mode via the Wireless Tool's Monitor mode.  While in this
          mode, no packets can be sent.
 
-config IPW_QOS
+config IPW2200_RADIOTAP
+       bool "Enable radiotap format 802.11 raw packet support"
+       depends on IPW2200_MONITOR
+
+config IPW2200_PROMISCUOUS
+       bool "Enable creation of a RF radiotap promiscuous interface"
+       depends on IPW2200_MONITOR
+       select IPW2200_RADIOTAP
+       ---help---
+          Enables the creation of a second interface prefixed 'rtap'. 
+          This second interface will provide every received in radiotap
+         format.
+
+          This is useful for performing wireless network analysis while
+          maintaining an active association.
+
+          Example usage:
+
+            % modprobe ipw2200 rtap_iface=1
+            % ifconfig rtap0 up
+            % tethereal -i rtap0
+
+          If you do not specify 'rtap_iface=1' as a module parameter then 
+          the rtap interface will not be created and you will need to turn 
+          it on via sysfs:
+       
+            % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface
+
+config IPW2200_QOS
         bool "Enable QoS support"
         depends on IPW2200 && EXPERIMENTAL
 
@@ -503,6 +531,23 @@ config PRISM54
          say M here and read <file:Documentation/modules.txt>.  The module
          will be called prism54.ko.
 
+config USB_ZD1201
+       tristate "USB ZD1201 based Wireless device support"
+       depends on USB && NET_RADIO
+       select FW_LOADER
+       ---help---
+         Say Y if you want to use wireless LAN adapters based on the ZyDAS
+         ZD1201 chip.
+
+         This driver makes the adapter appear as a normal Ethernet interface,
+         typically on wlan0.
+
+         The zd1201 device requires external firmware to be loaded.
+         This can be found at http://linux-lc100020.sourceforge.net/
+
+         To compile this driver as a module, choose M here: the
+         module will be called zd1201.
+
 source "drivers/net/wireless/hostap/Kconfig"
 source "drivers/net/wireless/bcm43xx/Kconfig"
 
index c86779879361881709f90b17abf470ea0667f5ec..512603de309a4301fa26cf81a2cfc33b6e402a5c 100644 (file)
@@ -40,3 +40,5 @@ obj-$(CONFIG_BCM43XX)         += bcm43xx/
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_PCMCIA_RAYCS)     += ray_cs.o
 obj-$(CONFIG_PCMCIA_WL3501)    += wl3501_cs.o
+
+obj-$(CONFIG_USB_ZD1201)       += zd1201.o
index 00764ddd74d8fc5593339107cd149fac3fec8ed1..4069b79d825972b4fb3ad21c7aad31d73edb07d4 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <asm/uaccess.h>
+#include <net/ieee80211.h>
 
 #include "airo.h"
 
@@ -467,6 +468,8 @@ static int do8bitIO = 0;
 #define RID_ECHOTEST_RESULTS 0xFF71
 #define RID_BSSLISTFIRST 0xFF72
 #define RID_BSSLISTNEXT  0xFF73
+#define RID_WPA_BSSLISTFIRST 0xFF74
+#define RID_WPA_BSSLISTNEXT  0xFF75
 
 typedef struct {
        u16 cmd;
@@ -739,6 +742,14 @@ typedef struct {
        u16 extSoftCap;
 } CapabilityRid;
 
+
+/* Only present on firmware >= 5.30.17 */
+typedef struct {
+  u16 unknown[4];
+  u8 fixed[12]; /* WLAN management frame */
+  u8 iep[624];
+} BSSListRidExtra;
+
 typedef struct {
   u16 len;
   u16 index; /* First is 0 and 0xffff means end of list */
@@ -767,6 +778,9 @@ typedef struct {
   } fh;
   u16 dsChannel;
   u16 atimWindow;
+
+  /* Only present on firmware >= 5.30.17 */
+  BSSListRidExtra extra;
 } BSSListRid;
 
 typedef struct {
@@ -1140,8 +1154,6 @@ struct airo_info {
        char defindex; // Used with auto wep
        struct proc_dir_entry *proc_entry;
         spinlock_t aux_lock;
-        unsigned long flags;
-#define FLAG_PROMISC   8       /* IFF_PROMISC 0x100 - include/linux/if.h */
 #define FLAG_RADIO_OFF 0       /* User disabling of MAC */
 #define FLAG_RADIO_DOWN        1       /* ifup/ifdown disabling of MAC */
 #define FLAG_RADIO_MASK 0x03
@@ -1151,6 +1163,7 @@ struct airo_info {
 #define FLAG_UPDATE_MULTI 5
 #define FLAG_UPDATE_UNI 6
 #define FLAG_802_11    7
+#define FLAG_PROMISC   8       /* IFF_PROMISC 0x100 - include/linux/if.h */
 #define FLAG_PENDING_XMIT 9
 #define FLAG_PENDING_XMIT11 10
 #define FLAG_MPI       11
@@ -1158,17 +1171,19 @@ struct airo_info {
 #define FLAG_COMMIT    13
 #define FLAG_RESET     14
 #define FLAG_FLASHING  15
-#define JOB_MASK       0x2ff0000
-#define JOB_DIE                16
-#define JOB_XMIT       17
-#define JOB_XMIT11     18
-#define JOB_STATS      19
-#define JOB_PROMISC    20
-#define JOB_MIC                21
-#define JOB_EVENT      22
-#define JOB_AUTOWEP    23
-#define JOB_WSTATS     24
-#define JOB_SCAN_RESULTS  25
+#define FLAG_WPA_CAPABLE       16
+       unsigned long flags;
+#define JOB_DIE        0
+#define JOB_XMIT       1
+#define JOB_XMIT11     2
+#define JOB_STATS      3
+#define JOB_PROMISC    4
+#define JOB_MIC        5
+#define JOB_EVENT      6
+#define JOB_AUTOWEP    7
+#define JOB_WSTATS     8
+#define JOB_SCAN_RESULTS  9
+       unsigned long jobs;
        int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
                        int whichbap);
        unsigned short *flash;
@@ -1208,6 +1223,11 @@ struct airo_info {
 #define        PCI_SHARED_LEN          2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
        char                    proc_name[IFNAMSIZ];
 
+       /* WPA-related stuff */
+       unsigned int bssListFirst;
+       unsigned int bssListNext;
+       unsigned int bssListRidLen;
+
        struct list_head network_list;
        struct list_head network_free_list;
        BSSListElement *networks;
@@ -1264,7 +1284,7 @@ static void micinit(struct airo_info *ai)
 {
        MICRid mic_rid;
 
-       clear_bit(JOB_MIC, &ai->flags);
+       clear_bit(JOB_MIC, &ai->jobs);
        PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0);
        up(&ai->sem);
 
@@ -1705,24 +1725,24 @@ static void emmh32_final(emmh32_context *context, u8 digest[4])
 static int readBSSListRid(struct airo_info *ai, int first,
                      BSSListRid *list) {
        int rc;
-                       Cmd cmd;
-                       Resp rsp;
+       Cmd cmd;
+       Resp rsp;
 
        if (first == 1) {
-                       if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
-                       memset(&cmd, 0, sizeof(cmd));
-                       cmd.cmd=CMD_LISTBSS;
-                       if (down_interruptible(&ai->sem))
-                               return -ERESTARTSYS;
-                       issuecommand(ai, &cmd, &rsp);
-                       up(&ai->sem);
-                       /* Let the command take effect */
-                       ai->task = current;
-                       ssleep(3);
-                       ai->task = NULL;
-               }
-       rc = PC4500_readrid(ai, first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT,
-                           list, sizeof(*list), 1);
+               if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
+               memset(&cmd, 0, sizeof(cmd));
+               cmd.cmd=CMD_LISTBSS;
+               if (down_interruptible(&ai->sem))
+                       return -ERESTARTSYS;
+               issuecommand(ai, &cmd, &rsp);
+               up(&ai->sem);
+               /* Let the command take effect */
+               ai->task = current;
+               ssleep(3);
+               ai->task = NULL;
+       }
+       rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext,
+                           list, ai->bssListRidLen, 1);
 
        list->len = le16_to_cpu(list->len);
        list->index = le16_to_cpu(list->index);
@@ -2112,7 +2132,7 @@ static void airo_end_xmit(struct net_device *dev) {
        int fid = priv->xmit.fid;
        u32 *fids = priv->fids;
 
-       clear_bit(JOB_XMIT, &priv->flags);
+       clear_bit(JOB_XMIT, &priv->jobs);
        clear_bit(FLAG_PENDING_XMIT, &priv->flags);
        status = transmit_802_3_packet (priv, fids[fid], skb->data);
        up(&priv->sem);
@@ -2162,7 +2182,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
        if (down_trylock(&priv->sem) != 0) {
                set_bit(FLAG_PENDING_XMIT, &priv->flags);
                netif_stop_queue(dev);
-               set_bit(JOB_XMIT, &priv->flags);
+               set_bit(JOB_XMIT, &priv->jobs);
                wake_up_interruptible(&priv->thr_wait);
        } else
                airo_end_xmit(dev);
@@ -2177,7 +2197,7 @@ static void airo_end_xmit11(struct net_device *dev) {
        int fid = priv->xmit11.fid;
        u32 *fids = priv->fids;
 
-       clear_bit(JOB_XMIT11, &priv->flags);
+       clear_bit(JOB_XMIT11, &priv->jobs);
        clear_bit(FLAG_PENDING_XMIT11, &priv->flags);
        status = transmit_802_11_packet (priv, fids[fid], skb->data);
        up(&priv->sem);
@@ -2233,7 +2253,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
        if (down_trylock(&priv->sem) != 0) {
                set_bit(FLAG_PENDING_XMIT11, &priv->flags);
                netif_stop_queue(dev);
-               set_bit(JOB_XMIT11, &priv->flags);
+               set_bit(JOB_XMIT11, &priv->jobs);
                wake_up_interruptible(&priv->thr_wait);
        } else
                airo_end_xmit11(dev);
@@ -2244,7 +2264,7 @@ static void airo_read_stats(struct airo_info *ai) {
        StatsRid stats_rid;
        u32 *vals = stats_rid.vals;
 
-       clear_bit(JOB_STATS, &ai->flags);
+       clear_bit(JOB_STATS, &ai->jobs);
        if (ai->power.event) {
                up(&ai->sem);
                return;
@@ -2272,10 +2292,10 @@ static struct net_device_stats *airo_get_stats(struct net_device *dev)
 {
        struct airo_info *local =  dev->priv;
 
-       if (!test_bit(JOB_STATS, &local->flags)) {
+       if (!test_bit(JOB_STATS, &local->jobs)) {
                /* Get stats out of the card if available */
                if (down_trylock(&local->sem) != 0) {
-                       set_bit(JOB_STATS, &local->flags);
+                       set_bit(JOB_STATS, &local->jobs);
                        wake_up_interruptible(&local->thr_wait);
                } else
                        airo_read_stats(local);
@@ -2290,7 +2310,7 @@ static void airo_set_promisc(struct airo_info *ai) {
 
        memset(&cmd, 0, sizeof(cmd));
        cmd.cmd=CMD_SETMODE;
-       clear_bit(JOB_PROMISC, &ai->flags);
+       clear_bit(JOB_PROMISC, &ai->jobs);
        cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
        issuecommand(ai, &cmd, &rsp);
        up(&ai->sem);
@@ -2302,7 +2322,7 @@ static void airo_set_multicast_list(struct net_device *dev) {
        if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
                change_bit(FLAG_PROMISC, &ai->flags);
                if (down_trylock(&ai->sem) != 0) {
-                       set_bit(JOB_PROMISC, &ai->flags);
+                       set_bit(JOB_PROMISC, &ai->jobs);
                        wake_up_interruptible(&ai->thr_wait);
                } else
                        airo_set_promisc(ai);
@@ -2380,7 +2400,7 @@ void stop_airo_card( struct net_device *dev, int freeres )
                }
                clear_bit(FLAG_REGISTERED, &ai->flags);
        }
-       set_bit(JOB_DIE, &ai->flags);
+       set_bit(JOB_DIE, &ai->jobs);
        kill_proc(ai->thr_pid, SIGTERM, 1);
        wait_for_completion(&ai->thr_exited);
 
@@ -2701,14 +2721,14 @@ static int reset_card( struct net_device *dev , int lock) {
        return 0;
 }
 
-#define MAX_NETWORK_COUNT      64
+#define AIRO_MAX_NETWORK_COUNT 64
 static int airo_networks_allocate(struct airo_info *ai)
 {
        if (ai->networks)
                return 0;
 
        ai->networks =
-           kzalloc(MAX_NETWORK_COUNT * sizeof(BSSListElement),
+           kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
                    GFP_KERNEL);
        if (!ai->networks) {
                airo_print_warn(ai->dev->name, "Out of memory allocating beacons");
@@ -2732,11 +2752,33 @@ static void airo_networks_initialize(struct airo_info *ai)
 
        INIT_LIST_HEAD(&ai->network_free_list);
        INIT_LIST_HEAD(&ai->network_list);
-       for (i = 0; i < MAX_NETWORK_COUNT; i++)
+       for (i = 0; i < AIRO_MAX_NETWORK_COUNT; i++)
                list_add_tail(&ai->networks[i].list,
                              &ai->network_free_list);
 }
 
+static int airo_test_wpa_capable(struct airo_info *ai)
+{
+       int status;
+       CapabilityRid cap_rid;
+       const char *name = ai->dev->name;
+
+       status = readCapabilityRid(ai, &cap_rid, 1);
+       if (status != SUCCESS) return 0;
+
+       /* Only firmware versions 5.30.17 or better can do WPA */
+       if ((cap_rid.softVer > 0x530)
+         || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
+               airo_print_info(name, "WPA is supported.");
+               return 1;
+       }
+
+       /* No WPA support */
+       airo_print_info(name, "WPA unsupported (only firmware versions 5.30.17"
+               " and greater support WPA.  Detected %s)", cap_rid.prodVer);
+       return 0;
+}
+
 static struct net_device *_init_airo_card( unsigned short irq, int port,
                                           int is_pcmcia, struct pci_dev *pci,
                                           struct device *dmdev )
@@ -2759,6 +2801,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        ai = dev->priv;
        ai->wifidev = NULL;
        ai->flags = 0;
+       ai->jobs = 0;
        ai->dev = dev;
        if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
                airo_print_dbg(dev->name, "Found an MPI350 card");
@@ -2838,6 +2881,18 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                set_bit(FLAG_FLASHING, &ai->flags);
        }
 
+       /* Test for WPA support */
+       if (airo_test_wpa_capable(ai)) {
+               set_bit(FLAG_WPA_CAPABLE, &ai->flags);
+               ai->bssListFirst = RID_WPA_BSSLISTFIRST;
+               ai->bssListNext = RID_WPA_BSSLISTNEXT;
+               ai->bssListRidLen = sizeof(BSSListRid);
+       } else {
+               ai->bssListFirst = RID_BSSLISTFIRST;
+               ai->bssListNext = RID_BSSLISTNEXT;
+               ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
+       }
+
        rc = register_netdev(dev);
        if (rc) {
                airo_print_err(dev->name, "Couldn't register_netdev");
@@ -2875,7 +2930,7 @@ err_out_irq:
 err_out_unlink:
        del_airo_dev(dev);
 err_out_thr:
-       set_bit(JOB_DIE, &ai->flags);
+       set_bit(JOB_DIE, &ai->jobs);
        kill_proc(ai->thr_pid, SIGTERM, 1);
        wait_for_completion(&ai->thr_exited);
 err_out_free:
@@ -2933,7 +2988,7 @@ static void airo_send_event(struct net_device *dev) {
        union iwreq_data wrqu;
        StatusRid status_rid;
 
-       clear_bit(JOB_EVENT, &ai->flags);
+       clear_bit(JOB_EVENT, &ai->jobs);
        PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0);
        up(&ai->sem);
        wrqu.data.length = 0;
@@ -2947,7 +3002,7 @@ static void airo_send_event(struct net_device *dev) {
 
 static void airo_process_scan_results (struct airo_info *ai) {
        union iwreq_data        wrqu;
-       BSSListRid BSSList;
+       BSSListRid bss;
        int rc;
        BSSListElement * loop_net;
        BSSListElement * tmp_net;
@@ -2960,15 +3015,15 @@ static void airo_process_scan_results (struct airo_info *ai) {
        }
 
        /* Try to read the first entry of the scan result */
-       rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 0);
-       if((rc) || (BSSList.index == 0xffff)) {
+       rc = PC4500_readrid(ai, ai->bssListFirst, &bss, ai->bssListRidLen, 0);
+       if((rc) || (bss.index == 0xffff)) {
                /* No scan results */
                goto out;
        }
 
        /* Read and parse all entries */
        tmp_net = NULL;
-       while((!rc) && (BSSList.index != 0xffff)) {
+       while((!rc) && (bss.index != 0xffff)) {
                /* Grab a network off the free list */
                if (!list_empty(&ai->network_free_list)) {
                        tmp_net = list_entry(ai->network_free_list.next,
@@ -2977,19 +3032,19 @@ static void airo_process_scan_results (struct airo_info *ai) {
                }
 
                if (tmp_net != NULL) {
-                       memcpy(tmp_net, &BSSList, sizeof(tmp_net->bss));
+                       memcpy(tmp_net, &bss, sizeof(tmp_net->bss));
                        list_add_tail(&tmp_net->list, &ai->network_list);
                        tmp_net = NULL;
                }
 
                /* Read next entry */
-               rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
-                                   &BSSList, sizeof(BSSList), 0);
+               rc = PC4500_readrid(ai, ai->bssListNext,
+                                   &bss, ai->bssListRidLen, 0);
        }
 
 out:
        ai->scan_timeout = 0;
-       clear_bit(JOB_SCAN_RESULTS, &ai->flags);
+       clear_bit(JOB_SCAN_RESULTS, &ai->jobs);
        up(&ai->sem);
 
        /* Send an empty event to user space.
@@ -3019,10 +3074,10 @@ static int airo_thread(void *data) {
                /* make swsusp happy with our thread */
                try_to_freeze();
 
-               if (test_bit(JOB_DIE, &ai->flags))
+               if (test_bit(JOB_DIE, &ai->jobs))
                        break;
 
-               if (ai->flags & JOB_MASK) {
+               if (ai->jobs) {
                        locked = down_interruptible(&ai->sem);
                } else {
                        wait_queue_t wait;
@@ -3031,16 +3086,16 @@ static int airo_thread(void *data) {
                        add_wait_queue(&ai->thr_wait, &wait);
                        for (;;) {
                                set_current_state(TASK_INTERRUPTIBLE);
-                               if (ai->flags & JOB_MASK)
+                               if (ai->jobs)
                                        break;
                                if (ai->expires || ai->scan_timeout) {
                                        if (ai->scan_timeout &&
                                                        time_after_eq(jiffies,ai->scan_timeout)){
-                                               set_bit(JOB_SCAN_RESULTS,&ai->flags);
+                                               set_bit(JOB_SCAN_RESULTS, &ai->jobs);
                                                break;
                                        } else if (ai->expires &&
                                                        time_after_eq(jiffies,ai->expires)){
-                                               set_bit(JOB_AUTOWEP,&ai->flags);
+                                               set_bit(JOB_AUTOWEP, &ai->jobs);
                                                break;
                                        }
                                        if (!signal_pending(current)) {
@@ -3069,7 +3124,7 @@ static int airo_thread(void *data) {
                if (locked)
                        continue;
 
-               if (test_bit(JOB_DIE, &ai->flags)) {
+               if (test_bit(JOB_DIE, &ai->jobs)) {
                        up(&ai->sem);
                        break;
                }
@@ -3079,23 +3134,23 @@ static int airo_thread(void *data) {
                        continue;
                }
 
-               if (test_bit(JOB_XMIT, &ai->flags))
+               if (test_bit(JOB_XMIT, &ai->jobs))
                        airo_end_xmit(dev);
-               else if (test_bit(JOB_XMIT11, &ai->flags))
+               else if (test_bit(JOB_XMIT11, &ai->jobs))
                        airo_end_xmit11(dev);
-               else if (test_bit(JOB_STATS, &ai->flags))
+               else if (test_bit(JOB_STATS, &ai->jobs))
                        airo_read_stats(ai);
-               else if (test_bit(JOB_WSTATS, &ai->flags))
+               else if (test_bit(JOB_WSTATS, &ai->jobs))
                        airo_read_wireless_stats(ai);
-               else if (test_bit(JOB_PROMISC, &ai->flags))
+               else if (test_bit(JOB_PROMISC, &ai->jobs))
                        airo_set_promisc(ai);
-               else if (test_bit(JOB_MIC, &ai->flags))
+               else if (test_bit(JOB_MIC, &ai->jobs))
                        micinit(ai);
-               else if (test_bit(JOB_EVENT, &ai->flags))
+               else if (test_bit(JOB_EVENT, &ai->jobs))
                        airo_send_event(dev);
-               else if (test_bit(JOB_AUTOWEP, &ai->flags))
+               else if (test_bit(JOB_AUTOWEP, &ai->jobs))
                        timer_func(dev);
-               else if (test_bit(JOB_SCAN_RESULTS, &ai->flags))
+               else if (test_bit(JOB_SCAN_RESULTS, &ai->jobs))
                        airo_process_scan_results(ai);
                else  /* Shouldn't get here, but we make sure to unlock */
                        up(&ai->sem);
@@ -3133,7 +3188,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
                if ( status & EV_MIC ) {
                        OUT4500( apriv, EVACK, EV_MIC );
                        if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
-                               set_bit(JOB_MIC, &apriv->flags);
+                               set_bit(JOB_MIC, &apriv->jobs);
                                wake_up_interruptible(&apriv->thr_wait);
                        }
                }
@@ -3187,7 +3242,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
                                set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
 
                                if (down_trylock(&apriv->sem) != 0) {
-                                       set_bit(JOB_EVENT, &apriv->flags);
+                                       set_bit(JOB_EVENT, &apriv->jobs);
                                        wake_up_interruptible(&apriv->thr_wait);
                                } else
                                        airo_send_event(dev);
@@ -5485,7 +5540,7 @@ static void timer_func( struct net_device *dev ) {
        up(&apriv->sem);
 
 /* Schedule check to see if the change worked */
-       clear_bit(JOB_AUTOWEP, &apriv->flags);
+       clear_bit(JOB_AUTOWEP, &apriv->jobs);
        apriv->expires = RUN_AT(HZ*3);
 }
 
@@ -6876,7 +6931,7 @@ static int airo_get_range(struct net_device *dev,
        }
        range->num_txpower = i;
        range->txpower_capa = IW_TXPOW_MWATT;
-       range->we_version_source = 12;
+       range->we_version_source = 19;
        range->we_version_compiled = WIRELESS_EXT;
        range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
        range->retry_flags = IW_RETRY_LIMIT;
@@ -7152,6 +7207,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
        u16                     capabilities;
        char *                  current_val;    /* For rates */
        int                     i;
+       char *          buf;
 
        /* First entry *MUST* be the AP MAC address */
        iwe.cmd = SIOCGIWAP;
@@ -7238,8 +7294,69 @@ static inline char *airo_translate_scan(struct net_device *dev,
        if((current_val - current_ev) > IW_EV_LCP_LEN)
                current_ev = current_val;
 
-       /* The other data in the scan result are not really
-        * interesting, so for now drop it - Jean II */
+       /* Beacon interval */
+       buf = kmalloc(30, GFP_KERNEL);
+       if (buf) {
+               iwe.cmd = IWEVCUSTOM;
+               sprintf(buf, "bcn_int=%d", bss->beaconInterval);
+               iwe.u.data.length = strlen(buf);
+               current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf);
+               kfree(buf);
+       }
+
+       /* Put WPA/RSN Information Elements into the event stream */
+       if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) {
+               unsigned int num_null_ies = 0;
+               u16 length = sizeof (bss->extra.iep);
+               struct ieee80211_info_element *info_element =
+                       (struct ieee80211_info_element *) &bss->extra.iep;
+
+               while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) {
+                       if (sizeof(*info_element) + info_element->len > length) {
+                               /* Invalid element, don't continue parsing IE */
+                               break;
+                       }
+
+                       switch (info_element->id) {
+                       case MFIE_TYPE_SSID:
+                               /* Two zero-length SSID elements
+                                * mean we're done parsing elements */
+                               if (!info_element->len)
+                                       num_null_ies++;
+                               break;
+
+                       case MFIE_TYPE_GENERIC:
+                               if (info_element->len >= 4 &&
+                                   info_element->data[0] == 0x00 &&
+                                   info_element->data[1] == 0x50 &&
+                                   info_element->data[2] == 0xf2 &&
+                                   info_element->data[3] == 0x01) {
+                                       iwe.cmd = IWEVGENIE;
+                                       iwe.u.data.length = min(info_element->len + 2,
+                                                                 MAX_WPA_IE_LEN);
+                                       current_ev = iwe_stream_add_point(current_ev, end_buf,
+                                                       &iwe, (char *) info_element);
+                               }
+                               break;
+
+                       case MFIE_TYPE_RSN:
+                               iwe.cmd = IWEVGENIE;
+                               iwe.u.data.length = min(info_element->len + 2,
+                                                         MAX_WPA_IE_LEN);
+                               current_ev = iwe_stream_add_point(current_ev, end_buf,
+                                               &iwe, (char *) info_element);
+                               break;
+
+                       default:
+                               break;
+                       }
+
+                       length -= sizeof(*info_element) + info_element->len;
+                       info_element =
+                           (struct ieee80211_info_element *)&info_element->
+                           data[info_element->len];
+               }
+       }
        return current_ev;
 }
 
@@ -7521,7 +7638,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
        u32 *vals = stats_rid.vals;
 
        /* Get stats out of the card */
-       clear_bit(JOB_WSTATS, &local->flags);
+       clear_bit(JOB_WSTATS, &local->jobs);
        if (local->power.event) {
                up(&local->sem);
                return;
@@ -7565,10 +7682,10 @@ static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
 {
        struct airo_info *local =  dev->priv;
 
-       if (!test_bit(JOB_WSTATS, &local->flags)) {
+       if (!test_bit(JOB_WSTATS, &local->jobs)) {
                /* Get stats out of the card if available */
                if (down_trylock(&local->sem) != 0) {
-                       set_bit(JOB_WSTATS, &local->flags);
+                       set_bit(JOB_WSTATS, &local->jobs);
                        wake_up_interruptible(&local->thr_wait);
                } else
                        airo_read_wireless_stats(local);
index 0e1ac338cac1a7283e46d4b7145ce7864550edfc..bed6823d980906908da6ecb1b608c7ec5fa32816 100644 (file)
@@ -1838,7 +1838,7 @@ struct net_device * __init arlan_probe(int unit)
 }
 
 #ifdef  MODULE
-int init_module(void)
+int __init init_module(void)
 {
        int i = 0;
 
@@ -1860,7 +1860,7 @@ int init_module(void)
 }
 
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
        int i = 0;
        struct net_device *dev;
index 2e83083935e1d9bd90570975c5cb771b62055a1e..e66fdb1f3cfdcf26d5660ccb192b90e81322a549 100644 (file)
@@ -645,7 +645,6 @@ struct bcm43xx_private {
        unsigned int irq;
 
        void __iomem *mmio_addr;
-       unsigned int mmio_len;
 
        /* Do not use the lock directly. Use the bcm43xx_lock* helper
         * functions, to be MMIO-safe. */
index 35a4fcb6d9233bc0887255ccc30ab08d336f9599..7497fb16076e4be4ed14867c6d99efe825eac204 100644 (file)
@@ -92,7 +92,7 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
        fappend("subsystem_vendor: 0x%04x   subsystem_device: 0x%04x\n",
                pci_dev->subsystem_vendor, pci_dev->subsystem_device);
        fappend("IRQ: %d\n", bcm->irq);
-       fappend("mmio_addr: 0x%p   mmio_len: %u\n", bcm->mmio_addr, bcm->mmio_len);
+       fappend("mmio_addr: 0x%p\n", bcm->mmio_addr);
        fappend("chip_id: 0x%04x   chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
        if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
                fappend("Radio disabled by hardware!\n");
index bbecba02e69775671187f84b9e19611f9c00fe19..d0318e525ba767d12016d429ab8ca967569ea57c 100644 (file)
@@ -624,25 +624,28 @@ err_destroy_tx0:
 static u16 generate_cookie(struct bcm43xx_dmaring *ring,
                           int slot)
 {
-       u16 cookie = 0x0000;
+       u16 cookie = 0xF000;
 
        /* Use the upper 4 bits of the cookie as
         * DMA controller ID and store the slot number
-        * in the lower 12 bits
+        * in the lower 12 bits.
+        * Note that the cookie must never be 0, as this
+        * is a special value used in RX path.
         */
        switch (ring->mmio_base) {
        default:
                assert(0);
        case BCM43xx_MMIO_DMA1_BASE:
+               cookie = 0xA000;
                break;
        case BCM43xx_MMIO_DMA2_BASE:
-               cookie = 0x1000;
+               cookie = 0xB000;
                break;
        case BCM43xx_MMIO_DMA3_BASE:
-               cookie = 0x2000;
+               cookie = 0xC000;
                break;
        case BCM43xx_MMIO_DMA4_BASE:
-               cookie = 0x3000;
+               cookie = 0xD000;
                break;
        }
        assert(((u16)slot & 0xF000) == 0x0000);
@@ -660,16 +663,16 @@ struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm,
        struct bcm43xx_dmaring *ring = NULL;
 
        switch (cookie & 0xF000) {
-       case 0x0000:
+       case 0xA000:
                ring = dma->tx_ring0;
                break;
-       case 0x1000:
+       case 0xB000:
                ring = dma->tx_ring1;
                break;
-       case 0x2000:
+       case 0xC000:
                ring = dma->tx_ring2;
                break;
-       case 0x3000:
+       case 0xD000:
                ring = dma->tx_ring3;
                break;
        default:
@@ -839,8 +842,18 @@ static void dma_rx(struct bcm43xx_dmaring *ring,
                /* We received an xmit status. */
                struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data;
                struct bcm43xx_xmitstatus stat;
+               int i = 0;
 
                stat.cookie = le16_to_cpu(hw->cookie);
+               while (stat.cookie == 0) {
+                       if (unlikely(++i >= 10000)) {
+                               assert(0);
+                               break;
+                       }
+                       udelay(2);
+                       barrier();
+                       stat.cookie = le16_to_cpu(hw->cookie);
+               }
                stat.flags = hw->flags;
                stat.cnt1 = hw->cnt1;
                stat.cnt2 = hw->cnt2;
index 7ed18cad29f75632b6408e72bd258ec25af05eb6..736dde96c4a38d81762bcec317bebff1bfd0b17a 100644 (file)
@@ -128,13 +128,15 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
        static struct pci_device_id bcm43xx_pci_tbl[] = {
        /* Broadcom 4303 802.11b */
        { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-               /* Broadcom 4307 802.11b */
+       /* Broadcom 4307 802.11b */
        { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-               /* Broadcom 4318 802.11b/g */
+       /* Broadcom 4318 802.11b/g */
        { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       /* Broadcom 4319 802.11a/b/g */
+       { PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        /* Broadcom 4306 802.11b/g */
        { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-               /* Broadcom 4306 802.11a */
+       /* Broadcom 4306 802.11a */
 //     { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        /* Broadcom 4309 802.11a/b/g */
        { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
@@ -3299,8 +3301,7 @@ static void bcm43xx_detach_board(struct bcm43xx_private *bcm)
 
        bcm43xx_chipset_detach(bcm);
        /* Do _not_ access the chip, after it is detached. */
-       iounmap(bcm->mmio_addr);
-       
+       pci_iounmap(pci_dev, bcm->mmio_addr);
        pci_release_regions(pci_dev);
        pci_disable_device(pci_dev);
 
@@ -3390,40 +3391,26 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
        struct net_device *net_dev = bcm->net_dev;
        int err;
        int i;
-       unsigned long mmio_start, mmio_flags, mmio_len;
        u32 coremask;
 
        err = pci_enable_device(pci_dev);
        if (err) {
-               printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err);
+               printk(KERN_ERR PFX "pci_enable_device() failed\n");
                goto out;
        }
-       mmio_start = pci_resource_start(pci_dev, 0);
-       mmio_flags = pci_resource_flags(pci_dev, 0);
-       mmio_len = pci_resource_len(pci_dev, 0);
-       if (!(mmio_flags & IORESOURCE_MEM)) {
-               printk(KERN_ERR PFX
-                      "%s, region #0 not an MMIO resource, aborting\n",
-                      pci_name(pci_dev));
-               err = -ENODEV;
-               goto err_pci_disable;
-       }
        err = pci_request_regions(pci_dev, KBUILD_MODNAME);
        if (err) {
-               printk(KERN_ERR PFX
-                      "could not access PCI resources (%i)\n", err);
+               printk(KERN_ERR PFX "pci_request_regions() failed\n");
                goto err_pci_disable;
        }
        /* enable PCI bus-mastering */
        pci_set_master(pci_dev);
-       bcm->mmio_addr = ioremap(mmio_start, mmio_len);
+       bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL);
        if (!bcm->mmio_addr) {
-               printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n",
-                      pci_name(pci_dev));
+               printk(KERN_ERR PFX "pci_iomap() failed\n");
                err = -EIO;
                goto err_pci_release;
        }
-       bcm->mmio_len = mmio_len;
        net_dev->base_addr = (unsigned long)bcm->mmio_addr;
 
        bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
@@ -3517,7 +3504,7 @@ err_80211_unwind:
 err_chipset_detach:
        bcm43xx_chipset_detach(bcm);
 err_iounmap:
-       iounmap(bcm->mmio_addr);
+       pci_iounmap(pci_dev, bcm->mmio_addr);
 err_pci_release:
        pci_release_regions(pci_dev);
 err_pci_disable:
@@ -3568,7 +3555,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
        unsigned long flags;
        int keyidx;
        
-       dprintk(KERN_INFO PFX "set security called\n");
+       dprintk(KERN_INFO PFX "set security called");
 
        bcm43xx_lock_mmio(bcm, flags);
 
@@ -3581,24 +3568,25 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
        
        if (sec->flags & SEC_ACTIVE_KEY) {
                secinfo->active_key = sec->active_key;
-               dprintk(KERN_INFO PFX "   .active_key = %d\n", sec->active_key);
+               dprintk(", .active_key = %d", sec->active_key);
        }
        if (sec->flags & SEC_UNICAST_GROUP) {
                secinfo->unicast_uses_group = sec->unicast_uses_group;
-               dprintk(KERN_INFO PFX "   .unicast_uses_group = %d\n", sec->unicast_uses_group);
+               dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group);
        }
        if (sec->flags & SEC_LEVEL) {
                secinfo->level = sec->level;
-               dprintk(KERN_INFO PFX "   .level = %d\n", sec->level);
+               dprintk(", .level = %d", sec->level);
        }
        if (sec->flags & SEC_ENABLED) {
                secinfo->enabled = sec->enabled;
-               dprintk(KERN_INFO PFX "   .enabled = %d\n", sec->enabled);
+               dprintk(", .enabled = %d", sec->enabled);
        }
        if (sec->flags & SEC_ENCRYPT) {
                secinfo->encrypt = sec->encrypt;
-               dprintk(KERN_INFO PFX "   .encrypt = %d\n", sec->encrypt);
+               dprintk(", .encrypt = %d", sec->encrypt);
        }
+       dprintk("\n");
        if (bcm->initialized && !bcm->ieee->host_encrypt) {
                if (secinfo->enabled) {
                        /* upload WEP keys to hardware */
index 346c6febb033b89e217591819727e21ae62ecc43..2aa2f389c0d5905a200921ecec2f5e4c582fe88f 100644 (file)
@@ -121,12 +121,6 @@ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
        hw->iobase = address;
        hw->reg_spacing = reg_spacing;
        hw->inten = 0x0;
-
-#ifdef HERMES_DEBUG_BUFFER
-       hw->dbufp = 0;
-       memset(&hw->dbuf, 0xff, sizeof(hw->dbuf));
-       memset(&hw->profile, 0, sizeof(hw->profile));
-#endif
 }
 
 int hermes_init(hermes_t *hw)
@@ -347,19 +341,6 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
                reg = hermes_read_reg(hw, oreg);
        }
 
-#ifdef HERMES_DEBUG_BUFFER
-       hw->profile[HERMES_BAP_BUSY_TIMEOUT - k]++;
-
-       if (k < HERMES_BAP_BUSY_TIMEOUT) {
-               struct hermes_debug_entry *e = 
-                       &hw->dbuf[(hw->dbufp++) % HERMES_DEBUG_BUFSIZE];
-               e->bap = bap;
-               e->id = id;
-               e->offset = offset;
-               e->cycles = HERMES_BAP_BUSY_TIMEOUT - k;
-       }
-#endif
-
        if (reg & HERMES_OFFSET_BUSY)
                return -ETIMEDOUT;
 
@@ -419,8 +400,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
 }
 
 /* Write a block of data to the chip's buffer, via the
- * BAP. Synchronization/serialization is the caller's problem. len
- * must be even.
+ * BAP. Synchronization/serialization is the caller's problem.
  *
  * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
  */
@@ -430,7 +410,7 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
        int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
        int err = 0;
 
-       if ( (len < 0) || (len % 2) )
+       if (len < 0)
                return -EINVAL;
 
        err = hermes_bap_seek(hw, bap, id, offset);
@@ -438,49 +418,12 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
                goto out;
        
        /* Actually do the transfer */
-       hermes_write_words(hw, dreg, buf, len/2);
+       hermes_write_bytes(hw, dreg, buf, len);
 
  out:  
        return err;
 }
 
-/* Write a block of data to the chip's buffer with padding if
- * neccessary, via the BAP. Synchronization/serialization is the
- * caller's problem. len must be even.
- *
- * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
- */
-int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, int len,
-                     u16 id, u16 offset)
-{
-       int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
-       int err = 0;
-
-       if (len < 0 || len % 2 || data_len > len)
-               return -EINVAL;
-
-       err = hermes_bap_seek(hw, bap, id, offset);
-       if (err)
-               goto out;
-
-       /* Transfer all the complete words of data */
-       hermes_write_words(hw, dreg, buf, data_len/2);
-       /* If there is an odd byte left over pad and transfer it */
-       if (data_len & 1) {
-               u8 end[2];
-               end[1] = 0;
-               end[0] = ((unsigned char *)buf)[data_len - 1];
-               hermes_write_words(hw, dreg, end, 1);
-               data_len ++;
-       }
-       /* Now send zeros for the padding */
-       if (data_len < len)
-               hermes_clear_words(hw, dreg, (len - data_len) / 2);
-       /* Complete */
- out:
-       return err;
-}
-
 /* Read a Length-Type-Value record from the card.
  *
  * If length is NULL, we ignore the length read from the card, and
@@ -553,7 +496,7 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
 
        count = length - 1;
 
-       hermes_write_words(hw, dreg, value, count);
+       hermes_write_bytes(hw, dreg, value, count << 1);
 
        err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, 
                                rid, NULL);
@@ -568,7 +511,6 @@ EXPORT_SYMBOL(hermes_allocate);
 
 EXPORT_SYMBOL(hermes_bap_pread);
 EXPORT_SYMBOL(hermes_bap_pwrite);
-EXPORT_SYMBOL(hermes_bap_pwrite_pad);
 EXPORT_SYMBOL(hermes_read_ltv);
 EXPORT_SYMBOL(hermes_write_ltv);
 
index 7644f72a9f4efd3269c40cd46b09cefbda196e85..8e3f0e3edb58f57e6a20aef2187c8317acb8ddc3 100644 (file)
@@ -328,16 +328,6 @@ struct hermes_multicast {
        u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
 } __attribute__ ((packed));
 
-// #define HERMES_DEBUG_BUFFER 1
-#define HERMES_DEBUG_BUFSIZE 4096
-struct hermes_debug_entry {
-       int bap;
-       u16 id, offset;
-       int cycles;
-};
-
-#ifdef __KERNEL__
-
 /* Timeouts */
 #define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
 
@@ -347,14 +337,7 @@ typedef struct hermes {
        int reg_spacing;
 #define HERMES_16BIT_REGSPACING        0
 #define HERMES_32BIT_REGSPACING        1
-
        u16 inten; /* Which interrupts should be enabled? */
-
-#ifdef HERMES_DEBUG_BUFFER
-       struct hermes_debug_entry dbuf[HERMES_DEBUG_BUFSIZE];
-       unsigned long dbufp;
-       unsigned long profile[HERMES_BAP_BUSY_TIMEOUT+1];
-#endif
 } hermes_t;
 
 /* Register access convenience macros */
@@ -376,8 +359,6 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
                       u16 id, u16 offset);
 int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
                        u16 id, u16 offset);
-int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf,
-                       unsigned data_len, int len, u16 id, u16 offset);
 int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
                    u16 *length, void *buf);
 int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
@@ -425,10 +406,13 @@ static inline void hermes_read_words(struct hermes *hw, int off, void *buf, unsi
        ioread16_rep(hw->iobase + off, buf, count);
 }
 
-static inline void hermes_write_words(struct hermes *hw, int off, const void *buf, unsigned count)
+static inline void hermes_write_bytes(struct hermes *hw, int off,
+                                     const char *buf, unsigned count)
 {
        off = off << hw->reg_spacing;
-       iowrite16_rep(hw->iobase + off, buf, count);
+       iowrite16_rep(hw->iobase + off, buf, count >> 1);
+       if (unlikely(count & 1))
+               iowrite8(buf[count - 1], hw->iobase + off);
 }
 
 static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count)
@@ -462,21 +446,4 @@ static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
        return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
 }
 
-#else /* ! __KERNEL__ */
-
-/* These are provided for the benefit of userspace drivers and testing programs
-   which use ioperm() or iopl() */
-
-#define hermes_read_reg(base, off) (inw((base) + (off)))
-#define hermes_write_reg(base, off, val) (outw((val), (base) + (off)))
-
-#define hermes_read_regn(base, name) (hermes_read_reg((base), HERMES_##name))
-#define hermes_write_regn(base, name, val) (hermes_write_reg((base), HERMES_##name, (val)))
-
-/* Note that for the next two, the count is in 16-bit words, not bytes */
-#define hermes_read_data(base, off, buf, count) (insw((base) + (off), (buf), (count)))
-#define hermes_write_data(base, off, buf, count) (outsw((base) + (off), (buf), (count)))
-
-#endif /* ! __KERNEL__ */
-
 #endif  /* _HERMES_H */
index 06a5214145e3124d6d7ccc738abeadb24c6d0a38..4a5be70c04195c412aca816fb796cfc4e96cb8f3 100644 (file)
@@ -534,5 +534,4 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
 }
 
 
-EXPORT_SYMBOL(hostap_dump_tx_80211);
 EXPORT_SYMBOL(hostap_master_start_xmit);
index 06c3fa32b310e41e0af0eea71fbf9fabf6a66a89..ba13125024cb35d54fa882a518d640a5f665c2c7 100644 (file)
@@ -3276,17 +3276,6 @@ EXPORT_SYMBOL(hostap_init_data);
 EXPORT_SYMBOL(hostap_init_ap_proc);
 EXPORT_SYMBOL(hostap_free_data);
 EXPORT_SYMBOL(hostap_check_sta_fw_version);
-EXPORT_SYMBOL(hostap_handle_sta_tx);
-EXPORT_SYMBOL(hostap_handle_sta_release);
 EXPORT_SYMBOL(hostap_handle_sta_tx_exc);
-EXPORT_SYMBOL(hostap_update_sta_ps);
-EXPORT_SYMBOL(hostap_handle_sta_rx);
-EXPORT_SYMBOL(hostap_is_sta_assoc);
-EXPORT_SYMBOL(hostap_is_sta_authorized);
-EXPORT_SYMBOL(hostap_add_sta);
-EXPORT_SYMBOL(hostap_update_rates);
-EXPORT_SYMBOL(hostap_add_wds_links);
-EXPORT_SYMBOL(hostap_wds_link_oper);
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
-EXPORT_SYMBOL(hostap_deauth_all_stas);
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
index 55bed923fbe9fcc6104588303166ab60111c7b70..db03dc2646dfb08d27b741f57774ca66303de609 100644 (file)
@@ -881,6 +881,12 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
        PCMCIA_DEVICE_PROD_ID12(
                "ZoomAir 11Mbps High", "Rate wireless Networking",
                0x273fe3db, 0x32a1eaee),
+       PCMCIA_DEVICE_PROD_ID123(
+               "Pretec", "CompactWLAN Card 802.11b", "2.5",
+               0x1cadd3e5, 0xe697636c, 0x7a5bfcf1),
+       PCMCIA_DEVICE_PROD_ID123(
+               "U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02",
+               0xc7b8df9d, 0x1700d087, 0x4b74baa0),
        PCMCIA_DEVICE_NULL
 };
 MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
index 8dd4c4446a640bf6b3b14f89e054f62ef47a3ec9..93786f4218f0d422092813dd17bb9b9e083d8997 100644 (file)
@@ -1125,11 +1125,9 @@ EXPORT_SYMBOL(hostap_set_auth_algs);
 EXPORT_SYMBOL(hostap_dump_rx_header);
 EXPORT_SYMBOL(hostap_dump_tx_header);
 EXPORT_SYMBOL(hostap_80211_header_parse);
-EXPORT_SYMBOL(hostap_80211_prism_header_parse);
 EXPORT_SYMBOL(hostap_80211_get_hdrlen);
 EXPORT_SYMBOL(hostap_get_stats);
 EXPORT_SYMBOL(hostap_setup_dev);
-EXPORT_SYMBOL(hostap_proc);
 EXPORT_SYMBOL(hostap_set_multicast_list_queue);
 EXPORT_SYMBOL(hostap_set_hostapd);
 EXPORT_SYMBOL(hostap_set_hostapd_sta);
index bca89cff85a63ccaf0204b349b7ab700de369dbe..39f82f21974932fc349d366620f4e3e223deffb5 100644 (file)
 #include "ipw2200.h"
 #include <linux/version.h>
 
-#define IPW2200_VERSION "git-1.1.1"
+
+#ifndef KBUILD_EXTMOD
+#define VK "k"
+#else
+#define VK
+#endif
+
+#ifdef CONFIG_IPW2200_DEBUG
+#define VD "d"
+#else
+#define VD
+#endif
+
+#ifdef CONFIG_IPW2200_MONITOR
+#define VM "m"
+#else
+#define VM
+#endif
+
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+#define VP "p"
+#else
+#define VP
+#endif
+
+#ifdef CONFIG_IPW2200_RADIOTAP
+#define VR "r"
+#else
+#define VR
+#endif
+
+#ifdef CONFIG_IPW2200_QOS
+#define VQ "q"
+#else
+#define VQ
+#endif
+
+#define IPW2200_VERSION "1.1.2" 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
@@ -46,7 +83,9 @@ MODULE_AUTHOR(DRV_COPYRIGHT);
 MODULE_LICENSE("GPL");
 
 static int cmdlog = 0;
+#ifdef CONFIG_IPW2200_DEBUG
 static int debug = 0;
+#endif
 static int channel = 0;
 static int mode = 0;
 
@@ -61,8 +100,14 @@ static int roaming = 1;
 static const char ipw_modes[] = {
        'a', 'b', 'g', '?'
 };
+static int antenna = CFG_SYS_ANTENNA_BOTH;
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+static int rtap_iface = 0;     /* def: 0 -- do not create rtap interface */
+#endif
+
+
+#ifdef CONFIG_IPW2200_QOS
 static int qos_enable = 0;
 static int qos_burst_enable = 0;
 static int qos_no_ack_mask = 0;
@@ -126,7 +171,7 @@ static int ipw_send_qos_params_command(struct ipw_priv *priv, struct ieee80211_q
                                       *qos_param);
 static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element
                                     *qos_param);
-#endif                         /* CONFIG_IPW_QOS */
+#endif                         /* CONFIG_IPW2200_QOS */
 
 static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev);
 static void ipw_remove_current_network(struct ipw_priv *priv);
@@ -1269,6 +1314,105 @@ static ssize_t show_cmd_log(struct device *d,
 
 static DEVICE_ATTR(cmd_log, S_IRUGO, show_cmd_log, NULL);
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+static void ipw_prom_free(struct ipw_priv *priv);
+static int ipw_prom_alloc(struct ipw_priv *priv);
+static ssize_t store_rtap_iface(struct device *d,
+                        struct device_attribute *attr,
+                        const char *buf, size_t count)
+{
+       struct ipw_priv *priv = dev_get_drvdata(d);
+       int rc = 0;
+
+       if (count < 1)
+               return -EINVAL;
+
+       switch (buf[0]) {
+       case '0':
+               if (!rtap_iface)
+                       return count;
+
+               if (netif_running(priv->prom_net_dev)) {
+                       IPW_WARNING("Interface is up.  Cannot unregister.\n");
+                       return count;
+               }
+
+               ipw_prom_free(priv);
+               rtap_iface = 0;
+               break;
+
+       case '1':
+               if (rtap_iface)
+                       return count;
+
+               rc = ipw_prom_alloc(priv);
+               if (!rc)
+                       rtap_iface = 1;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if (rc) {
+               IPW_ERROR("Failed to register promiscuous network "
+                         "device (error %d).\n", rc);
+       }
+
+       return count;
+}
+
+static ssize_t show_rtap_iface(struct device *d,
+                       struct device_attribute *attr,
+                       char *buf)
+{
+       struct ipw_priv *priv = dev_get_drvdata(d);
+       if (rtap_iface)
+               return sprintf(buf, "%s", priv->prom_net_dev->name);
+       else {
+               buf[0] = '-';
+               buf[1] = '1';
+               buf[2] = '\0';
+               return 3;
+       }
+}
+
+static DEVICE_ATTR(rtap_iface, S_IWUSR | S_IRUSR, show_rtap_iface,
+                  store_rtap_iface);
+
+static ssize_t store_rtap_filter(struct device *d,
+                        struct device_attribute *attr,
+                        const char *buf, size_t count)
+{
+       struct ipw_priv *priv = dev_get_drvdata(d);
+
+       if (!priv->prom_priv) {
+               IPW_ERROR("Attempting to set filter without "
+                         "rtap_iface enabled.\n");
+               return -EPERM;
+       }
+
+       priv->prom_priv->filter = simple_strtol(buf, NULL, 0);
+
+       IPW_DEBUG_INFO("Setting rtap filter to " BIT_FMT16 "\n",
+                      BIT_ARG16(priv->prom_priv->filter));
+
+       return count;
+}
+
+static ssize_t show_rtap_filter(struct device *d,
+                       struct device_attribute *attr,
+                       char *buf)
+{
+       struct ipw_priv *priv = dev_get_drvdata(d);
+       return sprintf(buf, "0x%04X",
+                      priv->prom_priv ? priv->prom_priv->filter : 0);
+}
+
+static DEVICE_ATTR(rtap_filter, S_IWUSR | S_IRUSR, show_rtap_filter,
+                  store_rtap_filter);
+#endif
+
 static ssize_t show_scan_age(struct device *d, struct device_attribute *attr,
                             char *buf)
 {
@@ -2025,16 +2169,11 @@ static int ipw_send_host_complete(struct ipw_priv *priv)
        return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE);
 }
 
-static int ipw_send_system_config(struct ipw_priv *priv,
-                                 struct ipw_sys_config *config)
+static int ipw_send_system_config(struct ipw_priv *priv)
 {
-       if (!priv || !config) {
-               IPW_ERROR("Invalid args\n");
-               return -1;
-       }
-
-       return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, sizeof(*config),
-                               config);
+       return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG,
+                               sizeof(priv->sys_config),
+                               &priv->sys_config);
 }
 
 static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len)
@@ -3104,10 +3243,10 @@ static int ipw_reset_nic(struct ipw_priv *priv)
 
 
 struct ipw_fw {
-       u32 ver;
-       u32 boot_size;
-       u32 ucode_size;
-       u32 fw_size;
+       __le32 ver;
+       __le32 boot_size;
+       __le32 ucode_size;
+       __le32 fw_size;
        u8 data[0];
 };
 
@@ -3131,8 +3270,8 @@ static int ipw_get_fw(struct ipw_priv *priv,
 
        fw = (void *)(*raw)->data;
 
-       if ((*raw)->size < sizeof(*fw) +
-           fw->boot_size + fw->ucode_size + fw->fw_size) {
+       if ((*raw)->size < sizeof(*fw) + le32_to_cpu(fw->boot_size) +
+           le32_to_cpu(fw->ucode_size) + le32_to_cpu(fw->fw_size)) {
                IPW_ERROR("%s is too small or corrupt (%zd)\n",
                          name, (*raw)->size);
                return -EINVAL;
@@ -3237,8 +3376,9 @@ static int ipw_load(struct ipw_priv *priv)
 
        fw = (void *)raw->data;
        boot_img = &fw->data[0];
-       ucode_img = &fw->data[fw->boot_size];
-       fw_img = &fw->data[fw->boot_size + fw->ucode_size];
+       ucode_img = &fw->data[le32_to_cpu(fw->boot_size)];
+       fw_img = &fw->data[le32_to_cpu(fw->boot_size) +
+                          le32_to_cpu(fw->ucode_size)];
 
        if (rc < 0)
                goto error;
@@ -3272,7 +3412,7 @@ static int ipw_load(struct ipw_priv *priv)
                        IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND);
 
        /* DMA the initial boot firmware into the device */
-       rc = ipw_load_firmware(priv, boot_img, fw->boot_size);
+       rc = ipw_load_firmware(priv, boot_img, le32_to_cpu(fw->boot_size));
        if (rc < 0) {
                IPW_ERROR("Unable to load boot firmware: %d\n", rc);
                goto error;
@@ -3294,7 +3434,7 @@ static int ipw_load(struct ipw_priv *priv)
        ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE);
 
        /* DMA the ucode into the device */
-       rc = ipw_load_ucode(priv, ucode_img, fw->ucode_size);
+       rc = ipw_load_ucode(priv, ucode_img, le32_to_cpu(fw->ucode_size));
        if (rc < 0) {
                IPW_ERROR("Unable to load ucode: %d\n", rc);
                goto error;
@@ -3304,7 +3444,7 @@ static int ipw_load(struct ipw_priv *priv)
        ipw_stop_nic(priv);
 
        /* DMA bss firmware into the device */
-       rc = ipw_load_firmware(priv, fw_img, fw->fw_size);
+       rc = ipw_load_firmware(priv, fw_img, le32_to_cpu(fw->fw_size));
        if (rc < 0) {
                IPW_ERROR("Unable to load firmware: %d\n", rc);
                goto error;
@@ -3700,7 +3840,17 @@ static void ipw_bg_disassociate(void *data)
 static void ipw_system_config(void *data)
 {
        struct ipw_priv *priv = data;
-       ipw_send_system_config(priv, &priv->sys_config);
+
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+       if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) {
+               priv->sys_config.accept_all_data_frames = 1;
+               priv->sys_config.accept_non_directed_frames = 1;
+               priv->sys_config.accept_all_mgmt_bcpr = 1;
+               priv->sys_config.accept_all_mgmt_frames = 1;
+       }
+#endif
+
+       ipw_send_system_config(priv);
 }
 
 struct ipw_status_code {
@@ -3771,6 +3921,13 @@ static void inline average_init(struct average *avg)
        memset(avg, 0, sizeof(*avg));
 }
 
+#define DEPTH_RSSI 8
+#define DEPTH_NOISE 16
+static s16 exponential_average(s16 prev_avg, s16 val, u8 depth)
+{
+       return ((depth-1)*prev_avg +  val)/depth;
+}
+
 static void average_add(struct average *avg, s16 val)
 {
        avg->sum -= avg->entries[avg->pos];
@@ -3800,8 +3957,8 @@ static void ipw_reset_stats(struct ipw_priv *priv)
        priv->quality = 0;
 
        average_init(&priv->average_missed_beacons);
-       average_init(&priv->average_rssi);
-       average_init(&priv->average_noise);
+       priv->exp_avg_rssi = -60;
+       priv->exp_avg_noise = -85 + 0x100;
 
        priv->last_rate = 0;
        priv->last_missed_beacons = 0;
@@ -4008,7 +4165,7 @@ static void ipw_gather_stats(struct ipw_priv *priv)
        IPW_DEBUG_STATS("Tx quality   : %3d%% (%u errors, %u packets)\n",
                        tx_quality, tx_failures_delta, tx_packets_delta);
 
-       rssi = average_value(&priv->average_rssi);
+       rssi = priv->exp_avg_rssi;
        signal_quality =
            (100 *
             (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) *
@@ -4185,7 +4342,7 @@ static void ipw_rx_notification(struct ipw_priv *priv,
                                        queue_work(priv->workqueue,
                                                   &priv->system_config);
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
 #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \
                         le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_ctl))
                                        if ((priv->status & STATUS_AUTH) &&
@@ -4482,6 +4639,24 @@ static void ipw_rx_notification(struct ipw_priv *priv,
                                 && priv->status & STATUS_ASSOCIATED)
                                queue_delayed_work(priv->workqueue,
                                                   &priv->request_scan, HZ);
+
+                       /* Send an empty event to user space.
+                        * We don't send the received data on the event because
+                        * it would require us to do complex transcoding, and
+                        * we want to minimise the work done in the irq handler
+                        * Use a request to extract the data.
+                        * Also, we generate this even for any scan, regardless
+                        * on how the scan was initiated. User space can just
+                        * sync on periodic scan to get fresh data...
+                        * Jean II */
+                       if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) {
+                               union iwreq_data wrqu;
+
+                               wrqu.data.length = 0;
+                               wrqu.data.flags = 0;
+                               wireless_send_event(priv->net_dev, SIOCGIWSCAN,
+                                                   &wrqu, NULL);
+                       }
                        break;
                }
 
@@ -4577,11 +4752,10 @@ static void ipw_rx_notification(struct ipw_priv *priv,
 
        case HOST_NOTIFICATION_NOISE_STATS:{
                        if (notif->size == sizeof(u32)) {
-                               priv->last_noise =
-                                   (u8) (le32_to_cpu(notif->u.noise.value) &
-                                         0xff);
-                               average_add(&priv->average_noise,
-                                           priv->last_noise);
+                               priv->exp_avg_noise =
+                                   exponential_average(priv->exp_avg_noise,
+                                   (u8) (le32_to_cpu(notif->u.noise.value) & 0xff),
+                                   DEPTH_NOISE);
                                break;
                        }
 
@@ -6170,8 +6344,6 @@ static void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie,
 {
        /* make sure WPA is enabled */
        ipw_wpa_enable(priv, 1);
-
-       ipw_disassociate(priv);
 }
 
 static int ipw_set_rsn_capa(struct ipw_priv *priv,
@@ -6365,6 +6537,7 @@ static int ipw_wx_set_auth(struct net_device *dev,
 
        case IW_AUTH_WPA_ENABLED:
                ret = ipw_wpa_enable(priv, param->value);
+               ipw_disassociate(priv);
                break;
 
        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
@@ -6506,7 +6679,7 @@ static int ipw_wx_set_mlme(struct net_device *dev,
        return 0;
 }
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
 
 /* QoS */
 /*
@@ -6853,61 +7026,55 @@ static int ipw_get_tx_queue_number(struct ipw_priv *priv, u16 priority)
        return from_priority_to_tx_queue[priority] - 1;
 }
 
-/*
-* add QoS parameter to the TX command
-*/
-static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv,
-                                       u16 priority,
-                                       struct tfd_data *tfd, u8 unicast)
+static int ipw_is_qos_active(struct net_device *dev,
+                            struct sk_buff *skb)
 {
-       int ret = 0;
-       int tx_queue_id = 0;
+       struct ipw_priv *priv = ieee80211_priv(dev);
        struct ieee80211_qos_data *qos_data = NULL;
        int active, supported;
-       unsigned long flags;
+       u8 *daddr = skb->data + ETH_ALEN;
+       int unicast = !is_multicast_ether_addr(daddr);
 
        if (!(priv->status & STATUS_ASSOCIATED))
                return 0;
 
        qos_data = &priv->assoc_network->qos_data;
 
-       spin_lock_irqsave(&priv->ieee->lock, flags);
-
        if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
                if (unicast == 0)
                        qos_data->active = 0;
                else
                        qos_data->active = qos_data->supported;
        }
-
        active = qos_data->active;
        supported = qos_data->supported;
-
-       spin_unlock_irqrestore(&priv->ieee->lock, flags);
-
        IPW_DEBUG_QOS("QoS  %d network is QoS active %d  supported %d  "
                      "unicast %d\n",
                      priv->qos_data.qos_enable, active, supported, unicast);
-       if (active && priv->qos_data.qos_enable) {
-               ret = from_priority_to_tx_queue[priority];
-               tx_queue_id = ret - 1;
-               IPW_DEBUG_QOS("QoS packet priority is %d \n", priority);
-               if (priority <= 7) {
-                       tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED;
-                       tfd->tfd.tfd_26.mchdr.qos_ctrl = priority;
-                       tfd->tfd.tfd_26.mchdr.frame_ctl |=
-                           IEEE80211_STYPE_QOS_DATA;
-
-                       if (priv->qos_data.qos_no_ack_mask &
-                           (1UL << tx_queue_id)) {
-                               tfd->tx_flags &= ~DCT_FLAG_ACK_REQD;
-                               tfd->tfd.tfd_26.mchdr.qos_ctrl |=
-                                   CTRL_QOS_NO_ACK;
-                       }
-               }
-       }
+       if (active && priv->qos_data.qos_enable)
+               return 1;
 
-       return ret;
+       return 0;
+
+}
+/*
+* add QoS parameter to the TX command
+*/
+static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv,
+                                       u16 priority,
+                                       struct tfd_data *tfd)
+{
+       int tx_queue_id = 0;
+
+
+       tx_queue_id = from_priority_to_tx_queue[priority] - 1;
+       tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED;
+
+       if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) {
+               tfd->tx_flags &= ~DCT_FLAG_ACK_REQD;
+               tfd->tfd.tfd_26.mchdr.qos_ctrl |= CTRL_QOS_NO_ACK;
+       }
+       return 0;
 }
 
 /*
@@ -6977,7 +7144,7 @@ static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos
                                qos_param);
 }
 
-#endif                         /* CONFIG_IPW_QOS */
+#endif                         /* CONFIG_IPW2200_QOS */
 
 static int ipw_associate_network(struct ipw_priv *priv,
                                 struct ieee80211_network *network,
@@ -7116,7 +7283,7 @@ static int ipw_associate_network(struct ipw_priv *priv,
        else
                priv->sys_config.answer_broadcast_ssid_probe = 0;
 
-       err = ipw_send_system_config(priv, &priv->sys_config);
+       err = ipw_send_system_config(priv);
        if (err) {
                IPW_DEBUG_HC("Attempt to send sys config command failed.\n");
                return err;
@@ -7141,7 +7308,7 @@ static int ipw_associate_network(struct ipw_priv *priv,
 
        priv->assoc_network = network;
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
        ipw_qos_association(priv, network);
 #endif
 
@@ -7415,7 +7582,7 @@ static void ipw_handle_data_packet(struct ipw_priv *priv,
        }
 }
 
-#ifdef CONFIG_IEEE80211_RADIOTAP
+#ifdef CONFIG_IPW2200_RADIOTAP
 static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
                                           struct ipw_rx_mem_buffer *rxb,
                                           struct ieee80211_rx_stats *stats)
@@ -7432,15 +7599,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
        /* Magic struct that slots into the radiotap header -- no reason
         * to build this manually element by element, we can write it much
         * more efficiently than we can parse it. ORDER MATTERS HERE */
-       struct ipw_rt_hdr {
-               struct ieee80211_radiotap_header rt_hdr;
-               u8 rt_flags;    /* radiotap packet flags */
-               u8 rt_rate;     /* rate in 500kb/s */
-               u16 rt_channel; /* channel in mhz */
-               u16 rt_chbitmask;       /* channel bitfield */
-               s8 rt_dbmsignal;        /* signal in dbM, kluged to signed */
-               u8 rt_antenna;  /* antenna number */
-       } *ipw_rt;
+       struct ipw_rt_hdr *ipw_rt;
 
        short len = le16_to_cpu(pkt->u.frame.length);
 
@@ -7494,9 +7653,11 @@ 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_RATE) |
             (1 << IEEE80211_RADIOTAP_CHANNEL) |
             (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+            (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
             (1 << IEEE80211_RADIOTAP_ANTENNA));
 
        /* Zero the flags, we'll add to them as we go */
@@ -7582,6 +7743,217 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
 }
 #endif
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+#define ieee80211_is_probe_response(fc) \
+   ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && \
+    (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP )
+
+#define ieee80211_is_management(fc) \
+   ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
+
+#define ieee80211_is_control(fc) \
+   ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL)
+
+#define ieee80211_is_data(fc) \
+   ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
+
+#define ieee80211_is_assoc_request(fc) \
+   ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ)
+
+#define ieee80211_is_reassoc_request(fc) \
+   ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
+
+static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
+                                     struct ipw_rx_mem_buffer *rxb,
+                                     struct ieee80211_rx_stats *stats)
+{
+       struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data;
+       struct ipw_rx_frame *frame = &pkt->u.frame;
+       struct ipw_rt_hdr *ipw_rt;
+
+       /* First cache any information we need before we overwrite
+        * the information provided in the skb from the hardware */
+       struct ieee80211_hdr *hdr;
+       u16 channel = frame->received_channel;
+       u8 phy_flags = frame->antennaAndPhy;
+       s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM;
+       s8 noise = frame->noise;
+       u8 rate = frame->rate;
+       short len = le16_to_cpu(pkt->u.frame.length);
+       u64 tsf = 0;
+       struct sk_buff *skb;
+       int hdr_only = 0;
+       u16 filter = priv->prom_priv->filter;
+
+       /* If the filter is set to not include Rx frames then return */
+       if (filter & IPW_PROM_NO_RX)
+               return;
+
+       /* We received data from the HW, so stop the watchdog */
+       priv->prom_net_dev->trans_start = jiffies;
+
+       if (unlikely((len + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {
+               priv->prom_priv->ieee->stats.rx_errors++;
+               IPW_DEBUG_DROP("Corruption detected! Oh no!\n");
+               return;
+       }
+
+       /* We only process data packets if the interface is open */
+       if (unlikely(!netif_running(priv->prom_net_dev))) {
+               priv->prom_priv->ieee->stats.rx_dropped++;
+               IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
+               return;
+       }
+
+       /* Libpcap 0.9.3+ can handle variable length radiotap, so we'll use
+        * that now */
+       if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) {
+               /* FIXME: Should alloc bigger skb instead */
+               priv->prom_priv->ieee->stats.rx_dropped++;
+               IPW_DEBUG_DROP("Dropping too large packet in monitor\n");
+               return;
+       }
+
+       hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE;
+       if (ieee80211_is_management(hdr->frame_ctl)) {
+               if (filter & IPW_PROM_NO_MGMT)
+                       return;
+               if (filter & IPW_PROM_MGMT_HEADER_ONLY)
+                       hdr_only = 1;
+       } else if (ieee80211_is_control(hdr->frame_ctl)) {
+               if (filter & IPW_PROM_NO_CTL)
+                       return;
+               if (filter & IPW_PROM_CTL_HEADER_ONLY)
+                       hdr_only = 1;
+       } else if (ieee80211_is_data(hdr->frame_ctl)) {
+               if (filter & IPW_PROM_NO_DATA)
+                       return;
+               if (filter & IPW_PROM_DATA_HEADER_ONLY)
+                       hdr_only = 1;
+       }
+
+       /* Copy the SKB since this is for the promiscuous side */
+       skb = skb_copy(rxb->skb, GFP_ATOMIC);
+       if (skb == NULL) {
+               IPW_ERROR("skb_clone failed for promiscuous copy.\n");
+               return;
+       }
+
+       /* copy the frame data to write after where the radiotap header goes */
+       ipw_rt = (void *)skb->data;
+
+       if (hdr_only)
+               len = ieee80211_get_hdrlen(hdr->frame_ctl);
+
+       memcpy(ipw_rt->payload, hdr, len);
+
+       /* Zero the radiotap static buffer  ...  We only need to zero the bytes
+        * NOT part of our real header, saves a little time.
+        *
+        * No longer necessary since we fill in all our data.  Purge before
+        * merging patch officially.
+        * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0,
+        *        IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr));
+        */
+
+       ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
+       ipw_rt->rt_hdr.it_pad = 0;      /* always good to zero */
+       ipw_rt->rt_hdr.it_len = sizeof(*ipw_rt);        /* total header+data */
+
+       /* Set the size of the skb to the size of the frame */
+       skb_put(skb, ipw_rt->rt_hdr.it_len + len);
+
+       /* 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_RATE) |
+            (1 << IEEE80211_RADIOTAP_CHANNEL) |
+            (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+            (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
+            (1 << IEEE80211_RADIOTAP_ANTENNA));
+
+       /* Zero the flags, we'll add to them as we go */
+       ipw_rt->rt_flags = 0;
+
+       ipw_rt->rt_tsf = tsf;
+
+       /* Convert to DBM */
+       ipw_rt->rt_dbmsignal = signal;
+       ipw_rt->rt_dbmnoise = noise;
+
+       /* Convert the channel data and set the flags */
+       ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(channel));
+       if (channel > 14) {     /* 802.11a */
+               ipw_rt->rt_chbitmask =
+                   cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
+       } else if (phy_flags & (1 << 5)) {      /* 802.11b */
+               ipw_rt->rt_chbitmask =
+                   cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
+       } else {                /* 802.11g */
+               ipw_rt->rt_chbitmask =
+                   (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ);
+       }
+
+       /* set the rate in multiples of 500k/s */
+       switch (rate) {
+       case IPW_TX_RATE_1MB:
+               ipw_rt->rt_rate = 2;
+               break;
+       case IPW_TX_RATE_2MB:
+               ipw_rt->rt_rate = 4;
+               break;
+       case IPW_TX_RATE_5MB:
+               ipw_rt->rt_rate = 10;
+               break;
+       case IPW_TX_RATE_6MB:
+               ipw_rt->rt_rate = 12;
+               break;
+       case IPW_TX_RATE_9MB:
+               ipw_rt->rt_rate = 18;
+               break;
+       case IPW_TX_RATE_11MB:
+               ipw_rt->rt_rate = 22;
+               break;
+       case IPW_TX_RATE_12MB:
+               ipw_rt->rt_rate = 24;
+               break;
+       case IPW_TX_RATE_18MB:
+               ipw_rt->rt_rate = 36;
+               break;
+       case IPW_TX_RATE_24MB:
+               ipw_rt->rt_rate = 48;
+               break;
+       case IPW_TX_RATE_36MB:
+               ipw_rt->rt_rate = 72;
+               break;
+       case IPW_TX_RATE_48MB:
+               ipw_rt->rt_rate = 96;
+               break;
+       case IPW_TX_RATE_54MB:
+               ipw_rt->rt_rate = 108;
+               break;
+       default:
+               ipw_rt->rt_rate = 0;
+               break;
+       }
+
+       /* antenna number */
+       ipw_rt->rt_antenna = (phy_flags & 3);
+
+       /* set the preamble flag if we have it */
+       if (phy_flags & (1 << 6))
+               ipw_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+
+       IPW_DEBUG_RX("Rx packet of %d bytes.\n", skb->len);
+
+       if (!ieee80211_rx(priv->prom_priv->ieee, skb, stats)) {
+               priv->prom_priv->ieee->stats.rx_errors++;
+               dev_kfree_skb_any(skb);
+       }
+}
+#endif
+
 static int is_network_packet(struct ipw_priv *priv,
                                    struct ieee80211_hdr_4addr *header)
 {
@@ -7808,15 +8180,21 @@ static void ipw_rx(struct ipw_priv *priv)
 
                                priv->rx_packets++;
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+       if (priv->prom_net_dev && netif_running(priv->prom_net_dev))
+               ipw_handle_promiscuous_rx(priv, rxb, &stats);
+#endif
+
 #ifdef CONFIG_IPW2200_MONITOR
                                if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
-#ifdef CONFIG_IEEE80211_RADIOTAP
-                                       ipw_handle_data_packet_monitor(priv,
-                                                                      rxb,
-                                                                      &stats);
+#ifdef CONFIG_IPW2200_RADIOTAP
+
+                ipw_handle_data_packet_monitor(priv,
+                                              rxb,
+                                              &stats);
 #else
-                                       ipw_handle_data_packet(priv, rxb,
-                                                              &stats);
+               ipw_handle_data_packet(priv, rxb,
+                                      &stats);
 #endif
                                        break;
                                }
@@ -7837,9 +8215,9 @@ static void ipw_rx(struct ipw_priv *priv)
                                if (network_packet && priv->assoc_network) {
                                        priv->assoc_network->stats.rssi =
                                            stats.rssi;
-                                       average_add(&priv->average_rssi,
-                                                   stats.rssi);
-                                       priv->last_rx_rssi = stats.rssi;
+                                       priv->exp_avg_rssi =
+                                           exponential_average(priv->exp_avg_rssi,
+                                           stats.rssi, DEPTH_RSSI);
                                }
 
                                IPW_DEBUG_RX("Frame: len=%u\n",
@@ -7982,10 +8360,10 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option)
                IPW_DEBUG_INFO("Bind to static channel %d\n", channel);
                /* TODO: Validate that provided channel is in range */
        }
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
        ipw_qos_init(priv, qos_enable, qos_burst_enable,
                     burst_duration_CCK, burst_duration_OFDM);
-#endif                         /* CONFIG_IPW_QOS */
+#endif                         /* CONFIG_IPW2200_QOS */
 
        switch (mode) {
        case 1:
@@ -7996,7 +8374,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option)
 #ifdef CONFIG_IPW2200_MONITOR
        case 2:
                priv->ieee->iw_mode = IW_MODE_MONITOR;
-#ifdef CONFIG_IEEE80211_RADIOTAP
+#ifdef CONFIG_IPW2200_RADIOTAP
                priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
 #else
                priv->net_dev->type = ARPHRD_IEEE80211;
@@ -8251,7 +8629,7 @@ static int ipw_wx_set_mode(struct net_device *dev,
                priv->net_dev->type = ARPHRD_ETHER;
 
        if (wrqu->mode == IW_MODE_MONITOR)
-#ifdef CONFIG_IEEE80211_RADIOTAP
+#ifdef CONFIG_IPW2200_RADIOTAP
                priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
 #else
                priv->net_dev->type = ARPHRD_IEEE80211;
@@ -8379,7 +8757,8 @@ static int ipw_wx_get_range(struct net_device *dev,
        /* Event capability (kernel + driver) */
        range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
                                IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
-                               IW_EVENT_CAPA_MASK(SIOCGIWAP));
+                               IW_EVENT_CAPA_MASK(SIOCGIWAP) |
+                               IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
        range->event_capa[1] = IW_EVENT_CAPA_K_1;
 
        range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
@@ -8734,6 +9113,7 @@ static int ipw_wx_get_rate(struct net_device *dev,
        struct ipw_priv *priv = ieee80211_priv(dev);
        mutex_lock(&priv->mutex);
        wrqu->bitrate.value = priv->last_rate;
+       wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0;
        mutex_unlock(&priv->mutex);
        IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
        return 0;
@@ -9351,7 +9731,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
        IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]);
        if (enable) {
                if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
-#ifdef CONFIG_IEEE80211_RADIOTAP
+#ifdef CONFIG_IPW2200_RADIOTAP
                        priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
 #else
                        priv->net_dev->type = ARPHRD_IEEE80211;
@@ -9579,8 +9959,8 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev)
        }
 
        wstats->qual.qual = priv->quality;
-       wstats->qual.level = average_value(&priv->average_rssi);
-       wstats->qual.noise = average_value(&priv->average_noise);
+       wstats->qual.level = priv->exp_avg_rssi;
+       wstats->qual.noise = priv->exp_avg_noise;
        wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
            IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM;
 
@@ -9608,7 +9988,9 @@ static  void init_sys_config(struct ipw_sys_config *sys_config)
        sys_config->disable_unicast_decryption = 1;
        sys_config->exclude_multicast_unencrypted = 0;
        sys_config->disable_multicast_decryption = 1;
-       sys_config->antenna_diversity = CFG_SYS_ANTENNA_SLOW_DIV;
+       if (antenna < CFG_SYS_ANTENNA_BOTH || antenna > CFG_SYS_ANTENNA_B)
+               antenna = CFG_SYS_ANTENNA_BOTH;
+       sys_config->antenna_diversity = antenna;
        sys_config->pass_crc_to_host = 0;       /* TODO: See if 1 gives us FCS */
        sys_config->dot11g_auto_detection = 0;
        sys_config->enable_cts_to_self = 0;
@@ -9647,11 +10029,11 @@ we need to heavily modify the ieee80211_skb_to_txb.
 static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
                             int pri)
 {
-       struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
+       struct ieee80211_hdr_3addrqos *hdr = (struct ieee80211_hdr_3addrqos *)
            txb->fragments[0]->data;
        int i = 0;
        struct tfd_frame *tfd;
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
        int tx_id = ipw_get_tx_queue_number(priv, pri);
        struct clx2_tx_queue *txq = &priv->txq[tx_id];
 #else
@@ -9662,9 +10044,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
        u16 remaining_bytes;
        int fc;
 
+       hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
        switch (priv->ieee->iw_mode) {
        case IW_MODE_ADHOC:
-               hdr_len = IEEE80211_3ADDR_LEN;
                unicast = !is_multicast_ether_addr(hdr->addr1);
                id = ipw_find_station(priv, hdr->addr1);
                if (id == IPW_INVALID_STATION) {
@@ -9681,7 +10063,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
        case IW_MODE_INFRA:
        default:
                unicast = !is_multicast_ether_addr(hdr->addr3);
-               hdr_len = IEEE80211_3ADDR_LEN;
                id = 0;
                break;
        }
@@ -9759,9 +10140,10 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
                /* No hardware encryption */
                tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP;
 
-#ifdef CONFIG_IPW_QOS
-       ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data), unicast);
-#endif                         /* CONFIG_IPW_QOS */
+#ifdef CONFIG_IPW2200_QOS
+       if (fc & IEEE80211_STYPE_QOS_DATA)
+               ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data));
+#endif                         /* CONFIG_IPW2200_QOS */
 
        /* payload */
        tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2),
@@ -9841,12 +10223,12 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
 static int ipw_net_is_queue_full(struct net_device *dev, int pri)
 {
        struct ipw_priv *priv = ieee80211_priv(dev);
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
        int tx_id = ipw_get_tx_queue_number(priv, pri);
        struct clx2_tx_queue *txq = &priv->txq[tx_id];
 #else
        struct clx2_tx_queue *txq = &priv->txq[0];
-#endif                         /* CONFIG_IPW_QOS */
+#endif                         /* CONFIG_IPW2200_QOS */
 
        if (ipw_queue_space(&txq->q) < txq->q.high_mark)
                return 1;
@@ -9854,6 +10236,88 @@ static int ipw_net_is_queue_full(struct net_device *dev, int pri)
        return 0;
 }
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
+                                     struct ieee80211_txb *txb)
+{
+       struct ieee80211_rx_stats dummystats;
+       struct ieee80211_hdr *hdr;
+       u8 n;
+       u16 filter = priv->prom_priv->filter;
+       int hdr_only = 0;
+
+       if (filter & IPW_PROM_NO_TX)
+               return;
+
+       memset(&dummystats, 0, sizeof(dummystats));
+
+       /* Filtering of fragment chains is done agains the first fragment */
+       hdr = (void *)txb->fragments[0]->data;
+       if (ieee80211_is_management(hdr->frame_ctl)) {
+               if (filter & IPW_PROM_NO_MGMT)
+                       return;
+               if (filter & IPW_PROM_MGMT_HEADER_ONLY)
+                       hdr_only = 1;
+       } else if (ieee80211_is_control(hdr->frame_ctl)) {
+               if (filter & IPW_PROM_NO_CTL)
+                       return;
+               if (filter & IPW_PROM_CTL_HEADER_ONLY)
+                       hdr_only = 1;
+       } else if (ieee80211_is_data(hdr->frame_ctl)) {
+               if (filter & IPW_PROM_NO_DATA)
+                       return;
+               if (filter & IPW_PROM_DATA_HEADER_ONLY)
+                       hdr_only = 1;
+       }
+
+       for(n=0; n<txb->nr_frags; ++n) {
+               struct sk_buff *src = txb->fragments[n];
+               struct sk_buff *dst;
+               struct ieee80211_radiotap_header *rt_hdr;
+               int len;
+
+               if (hdr_only) {
+                       hdr = (void *)src->data;
+                       len = ieee80211_get_hdrlen(hdr->frame_ctl);
+               } else
+                       len = src->len;
+
+               dst = alloc_skb(
+                       len + IEEE80211_RADIOTAP_HDRLEN, GFP_ATOMIC);
+               if (!dst) continue;
+
+               rt_hdr = (void *)skb_put(dst, sizeof(*rt_hdr));
+
+               rt_hdr->it_version = PKTHDR_RADIOTAP_VERSION;
+               rt_hdr->it_pad = 0;
+               rt_hdr->it_present = 0; /* after all, it's just an idea */
+               rt_hdr->it_present |=  (1 << IEEE80211_RADIOTAP_CHANNEL);
+
+               *(u16*)skb_put(dst, sizeof(u16)) = cpu_to_le16(
+                       ieee80211chan2mhz(priv->channel));
+               if (priv->channel > 14)         /* 802.11a */
+                       *(u16*)skb_put(dst, sizeof(u16)) =
+                               cpu_to_le16(IEEE80211_CHAN_OFDM |
+                                            IEEE80211_CHAN_5GHZ);
+               else if (priv->ieee->mode == IEEE_B) /* 802.11b */
+                       *(u16*)skb_put(dst, sizeof(u16)) =
+                               cpu_to_le16(IEEE80211_CHAN_CCK |
+                                            IEEE80211_CHAN_2GHZ);
+               else            /* 802.11g */
+                       *(u16*)skb_put(dst, sizeof(u16)) =
+                               cpu_to_le16(IEEE80211_CHAN_OFDM |
+                                IEEE80211_CHAN_2GHZ);
+
+               rt_hdr->it_len = dst->len;
+
+               memcpy(skb_put(dst, len), src->data, len);
+
+               if (!ieee80211_rx(priv->prom_priv->ieee, dst, &dummystats))
+                       dev_kfree_skb_any(dst);
+       }
+}
+#endif
+
 static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
                                   struct net_device *dev, int pri)
 {
@@ -9871,6 +10335,11 @@ static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
                goto fail_unlock;
        }
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+       if (rtap_iface && netif_running(priv->prom_net_dev))
+               ipw_handle_promiscuous_tx(priv, txb);
+#endif
+
        ret = ipw_tx_skb(priv, txb, pri);
        if (ret == NETDEV_TX_OK)
                __ipw_led_activity_on(priv);
@@ -10169,10 +10638,10 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv)
        INIT_WORK(&priv->merge_networks,
                  (void (*)(void *))ipw_merge_adhoc_network, priv);
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
        INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate,
                  priv);
-#endif                         /* CONFIG_IPW_QOS */
+#endif                         /* CONFIG_IPW2200_QOS */
 
        tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
                     ipw_irq_tasklet, (unsigned long)priv);
@@ -10318,12 +10787,21 @@ static int ipw_config(struct ipw_priv *priv)
                            |= CFG_BT_COEXISTENCE_OOB;
        }
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+       if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) {
+               priv->sys_config.accept_all_data_frames = 1;
+               priv->sys_config.accept_non_directed_frames = 1;
+               priv->sys_config.accept_all_mgmt_bcpr = 1;
+               priv->sys_config.accept_all_mgmt_frames = 1;
+       }
+#endif
+
        if (priv->ieee->iw_mode == IW_MODE_ADHOC)
                priv->sys_config.answer_broadcast_ssid_probe = 1;
        else
                priv->sys_config.answer_broadcast_ssid_probe = 0;
 
-       if (ipw_send_system_config(priv, &priv->sys_config))
+       if (ipw_send_system_config(priv))
                goto error;
 
        init_supported_rates(priv, &priv->rates);
@@ -10335,10 +10813,10 @@ static int ipw_config(struct ipw_priv *priv)
                if (ipw_send_rts_threshold(priv, priv->rts_threshold))
                        goto error;
        }
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
        IPW_DEBUG_QOS("QoS: call ipw_qos_activate\n");
        ipw_qos_activate(priv, NULL);
-#endif                         /* CONFIG_IPW_QOS */
+#endif                         /* CONFIG_IPW2200_QOS */
 
        if (ipw_set_random_seed(priv))
                goto error;
@@ -10639,6 +11117,7 @@ static int ipw_up(struct ipw_priv *priv)
                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;
@@ -10860,6 +11339,10 @@ static struct attribute *ipw_sysfs_entries[] = {
        &dev_attr_led.attr,
        &dev_attr_speed_scan.attr,
        &dev_attr_net_stats.attr,
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+       &dev_attr_rtap_iface.attr,
+       &dev_attr_rtap_filter.attr,
+#endif
        NULL
 };
 
@@ -10868,6 +11351,109 @@ static struct attribute_group ipw_attribute_group = {
        .attrs = ipw_sysfs_entries,
 };
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+static int ipw_prom_open(struct net_device *dev)
+{
+       struct ipw_prom_priv *prom_priv = ieee80211_priv(dev);
+       struct ipw_priv *priv = prom_priv->priv;
+
+       IPW_DEBUG_INFO("prom dev->open\n");
+       netif_carrier_off(dev);
+       netif_stop_queue(dev);
+
+       if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
+               priv->sys_config.accept_all_data_frames = 1;
+               priv->sys_config.accept_non_directed_frames = 1;
+               priv->sys_config.accept_all_mgmt_bcpr = 1;
+               priv->sys_config.accept_all_mgmt_frames = 1;
+
+               ipw_send_system_config(priv);
+       }
+
+       return 0;
+}
+
+static int ipw_prom_stop(struct net_device *dev)
+{
+       struct ipw_prom_priv *prom_priv = ieee80211_priv(dev);
+       struct ipw_priv *priv = prom_priv->priv;
+
+       IPW_DEBUG_INFO("prom dev->stop\n");
+
+       if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
+               priv->sys_config.accept_all_data_frames = 0;
+               priv->sys_config.accept_non_directed_frames = 0;
+               priv->sys_config.accept_all_mgmt_bcpr = 0;
+               priv->sys_config.accept_all_mgmt_frames = 0;
+
+               ipw_send_system_config(priv);
+       }
+
+       return 0;
+}
+
+static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       IPW_DEBUG_INFO("prom dev->xmit\n");
+       netif_stop_queue(dev);
+       return -EOPNOTSUPP;
+}
+
+static struct net_device_stats *ipw_prom_get_stats(struct net_device *dev)
+{
+       struct ipw_prom_priv *prom_priv = ieee80211_priv(dev);
+       return &prom_priv->ieee->stats;
+}
+
+static int ipw_prom_alloc(struct ipw_priv *priv)
+{
+       int rc = 0;
+
+       if (priv->prom_net_dev)
+               return -EPERM;
+
+       priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv));
+       if (priv->prom_net_dev == NULL)
+               return -ENOMEM;
+
+       priv->prom_priv = ieee80211_priv(priv->prom_net_dev);
+       priv->prom_priv->ieee = netdev_priv(priv->prom_net_dev);
+       priv->prom_priv->priv = priv;
+
+       strcpy(priv->prom_net_dev->name, "rtap%d");
+
+       priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
+       priv->prom_net_dev->open = ipw_prom_open;
+       priv->prom_net_dev->stop = ipw_prom_stop;
+       priv->prom_net_dev->get_stats = ipw_prom_get_stats;
+       priv->prom_net_dev->hard_start_xmit = ipw_prom_hard_start_xmit;
+
+       priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR;
+
+       rc = register_netdev(priv->prom_net_dev);
+       if (rc) {
+               free_ieee80211(priv->prom_net_dev);
+               priv->prom_net_dev = NULL;
+               return rc;
+       }
+
+       return 0;
+}
+
+static void ipw_prom_free(struct ipw_priv *priv)
+{
+       if (!priv->prom_net_dev)
+               return;
+
+       unregister_netdev(priv->prom_net_dev);
+       free_ieee80211(priv->prom_net_dev);
+
+       priv->prom_net_dev = NULL;
+}
+
+#endif
+
+
 static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err = 0;
@@ -10959,11 +11545,12 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        priv->ieee->set_security = shim__set_security;
        priv->ieee->is_queue_full = ipw_net_is_queue_full;
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
+       priv->ieee->is_qos_active = ipw_is_qos_active;
        priv->ieee->handle_probe_response = ipw_handle_beacon;
        priv->ieee->handle_beacon = ipw_handle_probe_response;
        priv->ieee->handle_assoc_response = ipw_handle_assoc_response;
-#endif                         /* CONFIG_IPW_QOS */
+#endif                         /* CONFIG_IPW2200_QOS */
 
        priv->ieee->perfect_rssi = -20;
        priv->ieee->worst_rssi = -85;
@@ -10997,6 +11584,18 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto out_remove_sysfs;
        }
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+       if (rtap_iface) {
+               err = ipw_prom_alloc(priv);
+               if (err) {
+                       IPW_ERROR("Failed to register promiscuous network "
+                                 "device (error %d).\n", err);
+                       unregister_netdev(priv->net_dev);
+                       goto out_remove_sysfs;
+               }
+       }
+#endif
+
        printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg "
               "channels, %d 802.11a channels)\n",
               priv->ieee->geo.name, priv->ieee->geo.bg_channels,
@@ -11076,6 +11675,10 @@ static void ipw_pci_remove(struct pci_dev *pdev)
                priv->error = NULL;
        }
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+       ipw_prom_free(priv);
+#endif
+
        free_irq(pdev->irq, priv);
        iounmap(priv->hw_base);
        pci_release_regions(pdev);
@@ -11200,7 +11803,12 @@ MODULE_PARM_DESC(debug, "debug output mask");
 module_param(channel, int, 0444);
 MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])");
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+module_param(rtap_iface, int, 0444);
+MODULE_PARM_DESC(rtap_iface, "create the rtap interface (1 - create, default 0)");
+#endif
+
+#ifdef CONFIG_IPW2200_QOS
 module_param(qos_enable, int, 0444);
 MODULE_PARM_DESC(qos_enable, "enable all QoS functionalitis");
 
@@ -11215,7 +11823,7 @@ MODULE_PARM_DESC(burst_duration_CCK, "set CCK burst value");
 
 module_param(burst_duration_OFDM, int, 0444);
 MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value");
-#endif                         /* CONFIG_IPW_QOS */
+#endif                         /* CONFIG_IPW2200_QOS */
 
 #ifdef CONFIG_IPW2200_MONITOR
 module_param(mode, int, 0444);
@@ -11238,5 +11846,8 @@ MODULE_PARM_DESC(cmdlog,
 module_param(roaming, int, 0444);
 MODULE_PARM_DESC(roaming, "enable roaming support (default on)");
 
+module_param(antenna, int, 0444);
+MODULE_PARM_DESC(antenna, "select antenna 1=Main, 3=Aux, default 0 [both], 2=slow_diversity (choose the one with lower background noise)");
+
 module_exit(ipw_exit);
 module_init(ipw_init);
index 4b9804900702875fc4d302dce052593b868df828..6044c0be2c801d6ad53ddd6a1d020aec17e5574e 100644 (file)
@@ -789,7 +789,7 @@ struct ipw_sys_config {
        u8 bt_coexist_collision_thr;
        u8 silence_threshold;
        u8 accept_all_mgmt_bcpr;
-       u8 accept_all_mgtm_frames;
+       u8 accept_all_mgmt_frames;
        u8 pass_noise_stats_to_host;
        u8 reserved3;
 } __attribute__ ((packed));
@@ -1122,6 +1122,52 @@ struct ipw_fw_error {
        u8 payload[0];
 } __attribute__ ((packed));
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+
+enum ipw_prom_filter {
+       IPW_PROM_CTL_HEADER_ONLY = (1 << 0),
+       IPW_PROM_MGMT_HEADER_ONLY = (1 << 1),
+       IPW_PROM_DATA_HEADER_ONLY = (1 << 2),
+       IPW_PROM_ALL_HEADER_ONLY = 0xf, /* bits 0..3 */
+       IPW_PROM_NO_TX = (1 << 4),
+       IPW_PROM_NO_RX = (1 << 5),
+       IPW_PROM_NO_CTL = (1 << 6),
+       IPW_PROM_NO_MGMT = (1 << 7),
+       IPW_PROM_NO_DATA = (1 << 8),
+};
+
+struct ipw_priv;
+struct ipw_prom_priv {
+       struct ipw_priv *priv;
+       struct ieee80211_device *ieee;
+       enum ipw_prom_filter filter;
+       int tx_packets;
+       int rx_packets;
+};
+#endif
+
+#if defined(CONFIG_IPW2200_RADIOTAP) || defined(CONFIG_IPW2200_PROMISCUOUS)
+/* Magic struct that slots into the radiotap header -- no reason
+ * to build this manually element by element, we can write it much
+ * more efficiently than we can parse it. ORDER MATTERS HERE
+ *
+ * When sent to us via the simulated Rx interface in sysfs, the entire
+ * structure is provided regardless of any bits unset.
+ */
+struct ipw_rt_hdr {
+       struct ieee80211_radiotap_header rt_hdr;
+       u64 rt_tsf;      /* TSF */
+       u8 rt_flags;    /* radiotap packet flags */
+       u8 rt_rate;     /* rate in 500kb/s */
+       u16 rt_channel; /* channel in mhz */
+       u16 rt_chbitmask;       /* channel bitfield */
+       s8 rt_dbmsignal;        /* signal in dbM, kluged to signed */
+       s8 rt_dbmnoise;
+       u8 rt_antenna;  /* antenna number */
+       u8 payload[0];  /* payload... */
+} __attribute__ ((packed));
+#endif
+
 struct ipw_priv {
        /* ieee device used by generic ieee processing code */
        struct ieee80211_device *ieee;
@@ -1133,6 +1179,12 @@ struct ipw_priv {
        struct pci_dev *pci_dev;
        struct net_device *net_dev;
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+       /* Promiscuous mode */
+       struct ipw_prom_priv *prom_priv;
+       struct net_device *prom_net_dev;
+#endif
+
        /* pci hardware address support */
        void __iomem *hw_base;
        unsigned long hw_len;
@@ -1153,11 +1205,9 @@ struct ipw_priv {
        u32 config;
        u32 capability;
 
-       u8 last_rx_rssi;
-       u8 last_noise;
        struct average average_missed_beacons;
-       struct average average_rssi;
-       struct average average_noise;
+       s16 exp_avg_rssi;
+       s16 exp_avg_noise;
        u32 port_type;
        int rx_bufs_min;          /**< minimum number of bufs in Rx queue */
        int rx_pend_max;          /**< maximum pending buffers for one IRQ */
@@ -1308,6 +1358,29 @@ struct ipw_priv {
 
 /* debug macros */
 
+/* Debug and printf string expansion helpers for printing bitfields */
+#define BIT_FMT8 "%c%c%c%c-%c%c%c%c"
+#define BIT_FMT16 BIT_FMT8 ":" BIT_FMT8
+#define BIT_FMT32 BIT_FMT16 " " BIT_FMT16
+
+#define BITC(x,y) (((x>>y)&1)?'1':'0')
+#define BIT_ARG8(x) \
+BITC(x,7),BITC(x,6),BITC(x,5),BITC(x,4),\
+BITC(x,3),BITC(x,2),BITC(x,1),BITC(x,0)
+
+#define BIT_ARG16(x) \
+BITC(x,15),BITC(x,14),BITC(x,13),BITC(x,12),\
+BITC(x,11),BITC(x,10),BITC(x,9),BITC(x,8),\
+BIT_ARG8(x)
+
+#define BIT_ARG32(x) \
+BITC(x,31),BITC(x,30),BITC(x,29),BITC(x,28),\
+BITC(x,27),BITC(x,26),BITC(x,25),BITC(x,24),\
+BITC(x,23),BITC(x,22),BITC(x,21),BITC(x,20),\
+BITC(x,19),BITC(x,18),BITC(x,17),BITC(x,16),\
+BIT_ARG16(x)
+
+
 #ifdef CONFIG_IPW2200_DEBUG
 #define IPW_DEBUG(level, fmt, args...) \
 do { if (ipw_debug_level & (level)) \
index c2d0b09e0418e1955c452248bb65686d8ed0d70e..8a31b591a901198f36b67eab7b4ab1612aa76992 100644 (file)
@@ -201,41 +201,12 @@ static struct {
 /* Data types                                                       */
 /********************************************************************/
 
-/* Used in Event handling.
- * We avoid nested structures as they break on ARM -- Moustafa */
-struct hermes_tx_descriptor_802_11 {
-       /* hermes_tx_descriptor */
-       __le16 status;
-       __le16 reserved1;
-       __le16 reserved2;
-       __le32 sw_support;
-       u8 retry_count;
-       u8 tx_rate;
-       __le16 tx_control;
-
-       /* ieee80211_hdr */
+/* Beginning of the Tx descriptor, used in TxExc handling */
+struct hermes_txexc_data {
+       struct hermes_tx_descriptor desc;
        __le16 frame_ctl;
        __le16 duration_id;
        u8 addr1[ETH_ALEN];
-       u8 addr2[ETH_ALEN];
-       u8 addr3[ETH_ALEN];
-       __le16 seq_ctl;
-       u8 addr4[ETH_ALEN];
-
-       __le16 data_len;
-
-       /* ethhdr */
-       u8 h_dest[ETH_ALEN];    /* destination eth addr */
-       u8 h_source[ETH_ALEN];  /* source ether addr    */
-       __be16 h_proto;         /* packet type ID field */
-
-       /* p8022_hdr */
-       u8 dsap;
-       u8 ssap;
-       u8 ctrl;
-       u8 oui[3];
-
-       __be16 ethertype;
 } __attribute__ ((packed));
 
 /* Rx frame header except compatibility 802.3 header */
@@ -450,53 +421,39 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
        hermes_t *hw = &priv->hw;
        int err = 0;
        u16 txfid = priv->txfid;
-       char *p;
        struct ethhdr *eh;
-       int len, data_len, data_off;
+       int data_off;
        struct hermes_tx_descriptor desc;
        unsigned long flags;
 
-       TRACE_ENTER(dev->name);
-
        if (! netif_running(dev)) {
                printk(KERN_ERR "%s: Tx on stopped device!\n",
                       dev->name);
-               TRACE_EXIT(dev->name);
-               return 1;
+               return NETDEV_TX_BUSY;
        }
        
        if (netif_queue_stopped(dev)) {
                printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", 
                       dev->name);
-               TRACE_EXIT(dev->name);
-               return 1;
+               return NETDEV_TX_BUSY;
        }
        
        if (orinoco_lock(priv, &flags) != 0) {
                printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
                       dev->name);
-               TRACE_EXIT(dev->name);
-               return 1;
+               return NETDEV_TX_BUSY;
        }
 
        if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {
                /* Oops, the firmware hasn't established a connection,
                    silently drop the packet (this seems to be the
                    safest approach). */
-               stats->tx_errors++;
-               orinoco_unlock(priv, &flags);
-               dev_kfree_skb(skb);
-               TRACE_EXIT(dev->name);
-               return 0;
+               goto drop;
        }
 
-       /* Length of the packet body */
-       /* FIXME: what if the skb is smaller than this? */
-       len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
-       skb = skb_padto(skb, len);
-       if (skb == NULL)
-               goto fail;
-       len -= ETH_HLEN;
+       /* Check packet length */
+       if (skb->len < ETH_HLEN)
+               goto drop;
 
        eh = (struct ethhdr *)skb->data;
 
@@ -507,8 +464,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
                if (net_ratelimit())
                        printk(KERN_ERR "%s: Error %d writing Tx descriptor "
                               "to BAP\n", dev->name, err);
-               stats->tx_errors++;
-               goto fail;
+               goto busy;
        }
 
        /* Clear the 802.11 header and data length fields - some
@@ -519,50 +475,38 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Encapsulate Ethernet-II frames */
        if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
-               struct header_struct hdr;
-               data_len = len;
-               data_off = HERMES_802_3_OFFSET + sizeof(hdr);
-               p = skb->data + ETH_HLEN;
-
-               /* 802.3 header */
-               memcpy(hdr.dest, eh->h_dest, ETH_ALEN);
-               memcpy(hdr.src, eh->h_source, ETH_ALEN);
-               hdr.len = htons(data_len + ENCAPS_OVERHEAD);
-               
-               /* 802.2 header */
-               memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));
-                       
-               hdr.ethertype = eh->h_proto;
-               err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
-                                        txfid, HERMES_802_3_OFFSET);
+               struct header_struct {
+                       struct ethhdr eth;      /* 802.3 header */
+                       u8 encap[6];            /* 802.2 header */
+               } __attribute__ ((packed)) hdr;
+
+               /* Strip destination and source from the data */
+               skb_pull(skb, 2 * ETH_ALEN);
+               data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr);
+
+               /* And move them to a separate header */
+               memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
+               hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
+               memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
+
+               err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
+                                       txfid, HERMES_802_3_OFFSET);
                if (err) {
                        if (net_ratelimit())
                                printk(KERN_ERR "%s: Error %d writing packet "
                                       "header to BAP\n", dev->name, err);
-                       stats->tx_errors++;
-                       goto fail;
+                       goto busy;
                }
-               /* Actual xfer length - allow for padding */
-               len = ALIGN(data_len, 2);
-               if (len < ETH_ZLEN - ETH_HLEN)
-                       len = ETH_ZLEN - ETH_HLEN;
        } else { /* IEEE 802.3 frame */
-               data_len = len + ETH_HLEN;
                data_off = HERMES_802_3_OFFSET;
-               p = skb->data;
-               /* Actual xfer length - round up for odd length packets */
-               len = ALIGN(data_len, 2);
-               if (len < ETH_ZLEN)
-                       len = ETH_ZLEN;
        }
 
-       err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, len,
+       err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
                                txfid, data_off);
        if (err) {
                printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
                       dev->name, err);
-               stats->tx_errors++;
-               goto fail;
+               goto busy;
        }
 
        /* Finally, we actually initiate the send */
@@ -575,25 +519,27 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
                if (net_ratelimit())
                        printk(KERN_ERR "%s: Error %d transmitting packet\n",
                                dev->name, err);
-               stats->tx_errors++;
-               goto fail;
+               goto busy;
        }
 
        dev->trans_start = jiffies;
-       stats->tx_bytes += data_off + data_len;
+       stats->tx_bytes += data_off + skb->len;
+       goto ok;
 
-       orinoco_unlock(priv, &flags);
+ drop:
+       stats->tx_errors++;
+       stats->tx_dropped++;
 
+ ok:
+       orinoco_unlock(priv, &flags);
        dev_kfree_skb(skb);
+       return NETDEV_TX_OK;
 
-       TRACE_EXIT(dev->name);
-
-       return 0;
- fail:
-       TRACE_EXIT(dev->name);
-
+ busy:
+       if (err == -EIO)
+               schedule_work(&priv->reset_work);
        orinoco_unlock(priv, &flags);
-       return err;
+       return NETDEV_TX_BUSY;
 }
 
 static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
@@ -629,7 +575,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
        struct net_device_stats *stats = &priv->stats;
        u16 fid = hermes_read_regn(hw, TXCOMPLFID);
        u16 status;
-       struct hermes_tx_descriptor_802_11 hdr;
+       struct hermes_txexc_data hdr;
        int err = 0;
 
        if (fid == DUMMY_FID)
@@ -637,8 +583,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
 
        /* Read part of the frame header - we need status and addr1 */
        err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
-                              offsetof(struct hermes_tx_descriptor_802_11,
-                                       addr2),
+                              sizeof(struct hermes_txexc_data),
                               fid, 0);
 
        hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
@@ -658,7 +603,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
         * exceeded, because that's the only status that really mean
         * that this particular node went away.
         * Other errors means that *we* screwed up. - Jean II */
-       status = le16_to_cpu(hdr.status);
+       status = le16_to_cpu(hdr.desc.status);
        if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
                union iwreq_data        wrqu;
 
@@ -1398,16 +1343,12 @@ int __orinoco_down(struct net_device *dev)
        return 0;
 }
 
-int orinoco_reinit_firmware(struct net_device *dev)
+static int orinoco_allocate_fid(struct net_device *dev)
 {
        struct orinoco_private *priv = netdev_priv(dev);
        struct hermes *hw = &priv->hw;
        int err;
 
-       err = hermes_init(hw);
-       if (err)
-               return err;
-
        err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
        if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
                /* Try workaround for old Symbol firmware bug */
@@ -1426,6 +1367,19 @@ int orinoco_reinit_firmware(struct net_device *dev)
        return err;
 }
 
+int orinoco_reinit_firmware(struct net_device *dev)
+{
+       struct orinoco_private *priv = netdev_priv(dev);
+       struct hermes *hw = &priv->hw;
+       int err;
+
+       err = hermes_init(hw);
+       if (!err)
+               err = orinoco_allocate_fid(dev);
+
+       return err;
+}
+
 static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
 {
        hermes_t *hw = &priv->hw;
@@ -1833,7 +1787,9 @@ static int __orinoco_program_rids(struct net_device *dev)
        /* Set promiscuity / multicast*/
        priv->promiscuous = 0;
        priv->mc_count = 0;
-       __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
+
+       /* FIXME: what about netif_tx_lock */
+       __orinoco_set_multicast_list(dev);
 
        return 0;
 }
@@ -2272,14 +2228,12 @@ static int orinoco_init(struct net_device *dev)
        u16 reclen;
        int len;
 
-       TRACE_ENTER(dev->name);
-
        /* No need to lock, the hw_unavailable flag is already set in
         * alloc_orinocodev() */
        priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN;
 
        /* Initialize the firmware */
-       err = orinoco_reinit_firmware(dev);
+       err = hermes_init(hw);
        if (err != 0) {
                printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n",
                       dev->name, err);
@@ -2337,6 +2291,13 @@ static int orinoco_init(struct net_device *dev)
 
        printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick);
 
+       err = orinoco_allocate_fid(dev);
+       if (err) {
+               printk(KERN_ERR "%s: failed to allocate NIC buffer!\n",
+                      dev->name);
+               goto out;
+       }
+
        /* Get allowed channels */
        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
                                  &priv->channel_mask);
@@ -2427,7 +2388,6 @@ static int orinoco_init(struct net_device *dev)
        printk(KERN_DEBUG "%s: ready\n", dev->name);
 
  out:
-       TRACE_EXIT(dev->name);
        return err;
 }
 
@@ -2795,8 +2755,6 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
        int numrates;
        int i, k;
 
-       TRACE_ENTER(dev->name);
-
        rrq->length = sizeof(struct iw_range);
        memset(range, 0, sizeof(struct iw_range));
 
@@ -2886,8 +2844,6 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev,
        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
        IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
 
-       TRACE_EXIT(dev->name);
-
        return 0;
 }
 
@@ -3069,8 +3025,6 @@ static int orinoco_ioctl_getessid(struct net_device *dev,
        int err = 0;
        unsigned long flags;
 
-       TRACE_ENTER(dev->name);
-
        if (netif_running(dev)) {
                err = orinoco_hw_get_essid(priv, &active, essidbuf);
                if (err)
@@ -3085,8 +3039,6 @@ static int orinoco_ioctl_getessid(struct net_device *dev,
        erq->flags = 1;
        erq->length = strlen(essidbuf) + 1;
 
-       TRACE_EXIT(dev->name);
-       
        return 0;
 }
 
@@ -4346,69 +4298,6 @@ static struct ethtool_ops orinoco_ethtool_ops = {
        .get_link = ethtool_op_get_link,
 };
 
-/********************************************************************/
-/* Debugging                                                        */
-/********************************************************************/
-
-#if 0
-static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
-{
-       printk(KERN_DEBUG "RX descriptor:\n");
-       printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);
-       printk(KERN_DEBUG "  time        = 0x%08x\n", frame->desc.time);
-       printk(KERN_DEBUG "  silence     = 0x%02x\n", frame->desc.silence);
-       printk(KERN_DEBUG "  signal      = 0x%02x\n", frame->desc.signal);
-       printk(KERN_DEBUG "  rate        = 0x%02x\n", frame->desc.rate);
-       printk(KERN_DEBUG "  rxflow      = 0x%02x\n", frame->desc.rxflow);
-       printk(KERN_DEBUG "  reserved    = 0x%08x\n", frame->desc.reserved);
-
-       printk(KERN_DEBUG "IEEE 802.11 header:\n");
-       printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",
-              frame->p80211.frame_ctl);
-       printk(KERN_DEBUG "  duration_id = 0x%04x\n",
-              frame->p80211.duration_id);
-       printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-              frame->p80211.addr1[0], frame->p80211.addr1[1],
-              frame->p80211.addr1[2], frame->p80211.addr1[3],
-              frame->p80211.addr1[4], frame->p80211.addr1[5]);
-       printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-              frame->p80211.addr2[0], frame->p80211.addr2[1],
-              frame->p80211.addr2[2], frame->p80211.addr2[3],
-              frame->p80211.addr2[4], frame->p80211.addr2[5]);
-       printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-              frame->p80211.addr3[0], frame->p80211.addr3[1],
-              frame->p80211.addr3[2], frame->p80211.addr3[3],
-              frame->p80211.addr3[4], frame->p80211.addr3[5]);
-       printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",
-              frame->p80211.seq_ctl);
-       printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-              frame->p80211.addr4[0], frame->p80211.addr4[1],
-              frame->p80211.addr4[2], frame->p80211.addr4[3],
-              frame->p80211.addr4[4], frame->p80211.addr4[5]);
-       printk(KERN_DEBUG "  data_len    = 0x%04x\n",
-              frame->p80211.data_len);
-
-       printk(KERN_DEBUG "IEEE 802.3 header:\n");
-       printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",
-              frame->p8023.h_dest[0], frame->p8023.h_dest[1],
-              frame->p8023.h_dest[2], frame->p8023.h_dest[3],
-              frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
-       printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",
-              frame->p8023.h_source[0], frame->p8023.h_source[1],
-              frame->p8023.h_source[2], frame->p8023.h_source[3],
-              frame->p8023.h_source[4], frame->p8023.h_source[5]);
-       printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);
-
-       printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
-       printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);
-       printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);
-       printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);
-       printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",
-              frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
-       printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
-}
-#endif /* 0 */
-
 /********************************************************************/
 /* Module initialization                                            */
 /********************************************************************/
index f5d856db92a1ce3337d18e2058831cac027f7037..16db3e14b7d2d5a115e8572543b7322593d9ed02 100644 (file)
@@ -7,7 +7,7 @@
 #ifndef _ORINOCO_H
 #define _ORINOCO_H
 
-#define DRIVER_VERSION "0.15rc3"
+#define DRIVER_VERSION "0.15"
 
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
@@ -30,20 +30,6 @@ struct orinoco_key {
        char data[ORINOCO_MAX_KEY_SIZE];
 } __attribute__ ((packed));
 
-struct header_struct {
-       /* 802.3 */
-       u8 dest[ETH_ALEN];
-       u8 src[ETH_ALEN];
-       __be16 len;
-       /* 802.2 */
-       u8 dsap;
-       u8 ssap;
-       u8 ctrl;
-       /* SNAP */
-       u8 oui[3];
-       unsigned short ethertype;
-} __attribute__ ((packed));
-
 typedef enum {
        FIRMWARE_TYPE_AGERE,
        FIRMWARE_TYPE_INTERSIL,
@@ -132,9 +118,6 @@ extern int orinoco_debug;
 #define DEBUG(n, args...) do { } while (0)
 #endif /* ORINOCO_DEBUG */
 
-#define TRACE_ENTER(devname) DEBUG(2, "%s: -> %s()\n", devname, __FUNCTION__);
-#define TRACE_EXIT(devname)  DEBUG(2, "%s: <- %s()\n", devname, __FUNCTION__);
-
 /********************************************************************/
 /* Exported prototypes                                              */
 /********************************************************************/
index 434f7d7ad8416c0f72132c8cfd90677b02afb21a..b2aec4d9fbb12b3dc759233564722ac43975daf5 100644 (file)
@@ -147,14 +147,11 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
 
+       if (link->dev_node)
+               unregister_netdev(dev);
+
        orinoco_cs_release(link);
 
-       DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
-       if (link->dev_node) {
-               DEBUG(0, PFX "About to unregister net device %p\n",
-                     dev);
-               unregister_netdev(dev);
-       }
        free_orinocodev(dev);
 }                              /* orinoco_cs_detach */
 
@@ -178,13 +175,10 @@ orinoco_cs_config(struct pcmcia_device *link)
        int last_fn, last_ret;
        u_char buf[64];
        config_info_t conf;
-       cisinfo_t info;
        tuple_t tuple;
        cisparse_t parse;
        void __iomem *mem;
 
-       CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
-
        /*
         * This reads the card's CONFIG tuple to find its
         * configuration registers.
@@ -234,12 +228,6 @@ orinoco_cs_config(struct pcmcia_device *link)
                        goto next_entry;
                link->conf.ConfigIndex = cfg->index;
 
-               /* Does this card need audio output? */
-               if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-                       link->conf.Attributes |= CONF_ENABLE_SPKR;
-                       link->conf.Status = CCSR_AUDIO_ENA;
-               }
-
                /* Use power settings for Vcc and Vpp if present */
                /* Note that the CIS values need to be rescaled */
                if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
@@ -355,19 +343,10 @@ orinoco_cs_config(struct pcmcia_device *link)
                                     net_device has been registered */
 
        /* Finally, report what we've done */
-       printk(KERN_DEBUG "%s: index 0x%02x: ",
-              dev->name, link->conf.ConfigIndex);
-       if (link->conf.Vpp)
-               printk(", Vpp %d.%d", link->conf.Vpp / 10,
-                      link->conf.Vpp % 10);
-       printk(", irq %d", link->irq.AssignedIRQ);
-       if (link->io.NumPorts1)
-               printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-                      link->io.BasePort1 + link->io.NumPorts1 - 1);
-       if (link->io.NumPorts2)
-               printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-                      link->io.BasePort2 + link->io.NumPorts2 - 1);
-       printk("\n");
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
+              "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id,
+              link->irq.AssignedIRQ, link->io.BasePort1,
+              link->io.BasePort1 + link->io.NumPorts1 - 1);
 
        return 0;
 
@@ -436,7 +415,6 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
        struct orinoco_private *priv = netdev_priv(dev);
        struct orinoco_pccard *card = priv->card;
        int err = 0;
-       unsigned long flags;
 
        if (! test_bit(0, &card->hard_reset_in_progress)) {
                err = orinoco_reinit_firmware(dev);
@@ -446,7 +424,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
                        return -EIO;
                }
 
-               spin_lock_irqsave(&priv->lock, flags);
+               spin_lock(&priv->lock);
 
                netif_device_attach(dev);
                priv->hw_unavailable--;
@@ -458,10 +436,10 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
                                       dev->name, err);
                }
 
-               spin_unlock_irqrestore(&priv->lock, flags);
+               spin_unlock(&priv->lock);
        }
 
-       return 0;
+       return err;
 }
 
 
index d1a670b35338e54eaec7548309819b1d1985eb6c..74b9d5b2ba9ee00005586938f832cf4c1f36911e 100644 (file)
@@ -1,9 +1,8 @@
 /* orinoco_nortel.c
- * 
+ *
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
  * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in
  * Nortel emobility, Symbol LA-4113 and Symbol LA-4123.
- * but are connected to the PCI bus by a Nortel PCI-PCMCIA-Adapter. 
  *
  * Copyright (C) 2002 Tobias Hoffmann
  *           (C) 2003 Christoph Jungegger <disdos@traum404.de>
 #include <pcmcia/cisreg.h>
 
 #include "orinoco.h"
+#include "orinoco_pci.h"
 
 #define COR_OFFSET    (0xe0)   /* COR attribute offset of Prism2 PC card */
 #define COR_VALUE     (COR_LEVEL_REQ | COR_FUNC_ENA)   /* Enable PC card with interrupt in level trigger */
 
 
-/* Nortel specific data */
-struct nortel_pci_card {
-       unsigned long iobase1;
-       unsigned long iobase2;
-};
-
 /*
- * Do a soft reset of the PCI card using the Configuration Option Register
+ * Do a soft reset of the card using the Configuration Option Register
  * We need this to get going...
  * This is the part of the code that is strongly inspired from wlan-ng
  *
  * Note bis : Don't try to access HERMES_CMD during the reset phase.
  * It just won't work !
  */
-static int nortel_pci_cor_reset(struct orinoco_private *priv)
+static int orinoco_nortel_cor_reset(struct orinoco_private *priv)
 {
-       struct nortel_pci_card *card = priv->card;
+       struct orinoco_pci_card *card = priv->card;
 
-       /* Assert the reset until the card notice */
-       outw_p(8, card->iobase1 + 2);
-       inw(card->iobase2 + COR_OFFSET);
-       outw_p(0x80, card->iobase2 + COR_OFFSET);
+       /* Assert the reset until the card notices */
+       iowrite16(8, card->bridge_io + 2);
+       ioread16(card->attr_io + COR_OFFSET);
+       iowrite16(0x80, card->attr_io + COR_OFFSET);
        mdelay(1);
 
        /* Give time for the card to recover from this hard effort */
-       outw_p(0, card->iobase2 + COR_OFFSET);
-       outw_p(0, card->iobase2 + COR_OFFSET);
+       iowrite16(0, card->attr_io + COR_OFFSET);
+       iowrite16(0, card->attr_io + COR_OFFSET);
        mdelay(1);
 
-       /* set COR as usual */
-       outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
-       outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+       /* Set COR as usual */
+       iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
+       iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
        mdelay(1);
 
-       outw_p(0x228, card->iobase1 + 2);
+       iowrite16(0x228, card->bridge_io + 2);
 
        return 0;
 }
 
-static int nortel_pci_hw_init(struct nortel_pci_card *card)
+static int orinoco_nortel_hw_init(struct orinoco_pci_card *card)
 {
        int i;
        u32 reg;
 
-       /* setup bridge */
-       if (inw(card->iobase1) & 1) {
+       /* Setup bridge */
+       if (ioread16(card->bridge_io) & 1) {
                printk(KERN_ERR PFX "brg1 answer1 wrong\n");
                return -EBUSY;
        }
-       outw_p(0x118, card->iobase1 + 2);
-       outw_p(0x108, card->iobase1 + 2);
+       iowrite16(0x118, card->bridge_io + 2);
+       iowrite16(0x108, card->bridge_io + 2);
        mdelay(30);
-       outw_p(0x8, card->iobase1 + 2);
+       iowrite16(0x8, card->bridge_io + 2);
        for (i = 0; i < 30; i++) {
                mdelay(30);
-               if (inw(card->iobase1) & 0x10) {
+               if (ioread16(card->bridge_io) & 0x10) {
                        break;
                }
        }
@@ -118,42 +112,42 @@ static int nortel_pci_hw_init(struct nortel_pci_card *card)
                printk(KERN_ERR PFX "brg1 timed out\n");
                return -EBUSY;
        }
-       if (inw(card->iobase2 + 0xe0) & 1) {
+       if (ioread16(card->attr_io + COR_OFFSET) & 1) {
                printk(KERN_ERR PFX "brg2 answer1 wrong\n");
                return -EBUSY;
        }
-       if (inw(card->iobase2 + 0xe2) & 1) {
+       if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) {
                printk(KERN_ERR PFX "brg2 answer2 wrong\n");
                return -EBUSY;
        }
-       if (inw(card->iobase2 + 0xe4) & 1) {
+       if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) {
                printk(KERN_ERR PFX "brg2 answer3 wrong\n");
                return -EBUSY;
        }
 
-       /* set the PCMCIA COR-Register */
-       outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+       /* Set the PCMCIA COR register */
+       iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
        mdelay(1);
-       reg = inw(card->iobase2 + COR_OFFSET);
+       reg = ioread16(card->attr_io + COR_OFFSET);
        if (reg != COR_VALUE) {
                printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
                       reg);
                return -EBUSY;
        }
 
-       /* set leds */
-       outw_p(1, card->iobase1 + 10);
+       /* Set LEDs */
+       iowrite16(1, card->bridge_io + 10);
        return 0;
 }
 
-static int nortel_pci_init_one(struct pci_dev *pdev,
-                              const struct pci_device_id *ent)
+static int orinoco_nortel_init_one(struct pci_dev *pdev,
+                                  const struct pci_device_id *ent)
 {
        int err;
        struct orinoco_private *priv;
-       struct nortel_pci_card *card;
+       struct orinoco_pci_card *card;
        struct net_device *dev;
-       void __iomem *iomem;
+       void __iomem *hermes_io, *bridge_io, *attr_io;
 
        err = pci_enable_device(pdev);
        if (err) {
@@ -162,19 +156,34 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
        }
 
        err = pci_request_regions(pdev, DRIVER_NAME);
-       if (err != 0) {
+       if (err) {
                printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
                goto fail_resources;
        }
 
-       iomem = pci_iomap(pdev, 2, 0);
-       if (!iomem) {
-               err = -ENOMEM;
-               goto fail_map_io;
+       bridge_io = pci_iomap(pdev, 0, 0);
+       if (!bridge_io) {
+               printk(KERN_ERR PFX "Cannot map bridge registers\n");
+               err = -EIO;
+               goto fail_map_bridge;
+       }
+
+       attr_io = pci_iomap(pdev, 1, 0);
+       if (!attr_io) {
+               printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
+               err = -EIO;
+               goto fail_map_attr;
+       }
+
+       hermes_io = pci_iomap(pdev, 2, 0);
+       if (!hermes_io) {
+               printk(KERN_ERR PFX "Cannot map chipset registers\n");
+               err = -EIO;
+               goto fail_map_hermes;
        }
 
        /* Allocate network device */
-       dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset);
+       dev = alloc_orinocodev(sizeof(*card), orinoco_nortel_cor_reset);
        if (!dev) {
                printk(KERN_ERR PFX "Cannot allocate network device\n");
                err = -ENOMEM;
@@ -183,16 +192,12 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
 
        priv = netdev_priv(dev);
        card = priv->card;
-       card->iobase1 = pci_resource_start(pdev, 0);
-       card->iobase2 = pci_resource_start(pdev, 1);
-       dev->base_addr = pci_resource_start(pdev, 2);
+       card->bridge_io = bridge_io;
+       card->attr_io = attr_io;
        SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
-       hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING);
-
-       printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, "
-              "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr);
+       hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
 
        err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
                          dev->name, dev);
@@ -201,21 +206,19 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
                err = -EBUSY;
                goto fail_irq;
        }
-       dev->irq = pdev->irq;
 
-       err = nortel_pci_hw_init(card);
+       err = orinoco_nortel_hw_init(card);
        if (err) {
                printk(KERN_ERR PFX "Hardware initialization failed\n");
                goto fail;
        }
 
-       err = nortel_pci_cor_reset(priv);
+       err = orinoco_nortel_cor_reset(priv);
        if (err) {
                printk(KERN_ERR PFX "Initial reset failed\n");
                goto fail;
        }
 
-
        err = register_netdev(dev);
        if (err) {
                printk(KERN_ERR PFX "Cannot register network device\n");
@@ -223,6 +226,8 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
        }
 
        pci_set_drvdata(pdev, dev);
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+              pci_name(pdev));
 
        return 0;
 
@@ -234,9 +239,15 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
        free_orinocodev(dev);
 
  fail_alloc:
-       pci_iounmap(pdev, iomem);
+       pci_iounmap(pdev, hermes_io);
 
- fail_map_io:
+ fail_map_hermes:
+       pci_iounmap(pdev, attr_io);
+
+ fail_map_attr:
+       pci_iounmap(pdev, bridge_io);
+
+ fail_map_bridge:
        pci_release_regions(pdev);
 
  fail_resources:
@@ -245,26 +256,27 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
        return err;
 }
 
-static void __devexit nortel_pci_remove_one(struct pci_dev *pdev)
+static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct orinoco_private *priv = netdev_priv(dev);
-       struct nortel_pci_card *card = priv->card;
+       struct orinoco_pci_card *card = priv->card;
 
-       /* clear leds */
-       outw_p(0, card->iobase1 + 10);
+       /* Clear LEDs */
+       iowrite16(0, card->bridge_io + 10);
 
        unregister_netdev(dev);
-       free_irq(dev->irq, dev);
+       free_irq(pdev->irq, dev);
        pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
        pci_iounmap(pdev, priv->hw.iobase);
+       pci_iounmap(pdev, card->attr_io);
+       pci_iounmap(pdev, card->bridge_io);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
 }
 
-
-static struct pci_device_id nortel_pci_id_table[] = {
+static struct pci_device_id orinoco_nortel_id_table[] = {
        /* Nortel emobility PCI */
        {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
        /* Symbol LA-4123 PCI */
@@ -272,13 +284,15 @@ static struct pci_device_id nortel_pci_id_table[] = {
        {0,},
 };
 
-MODULE_DEVICE_TABLE(pci, nortel_pci_id_table);
+MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table);
 
-static struct pci_driver nortel_pci_driver = {
-       .name = DRIVER_NAME,
-       .id_table = nortel_pci_id_table,
-       .probe = nortel_pci_init_one,
-       .remove = __devexit_p(nortel_pci_remove_one),
+static struct pci_driver orinoco_nortel_driver = {
+       .name           = DRIVER_NAME,
+       .id_table       = orinoco_nortel_id_table,
+       .probe          = orinoco_nortel_init_one,
+       .remove         = __devexit_p(orinoco_nortel_remove_one),
+       .suspend        = orinoco_pci_suspend,
+       .resume         = orinoco_pci_resume,
 };
 
 static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -288,20 +302,19 @@ MODULE_DESCRIPTION
     ("Driver for wireless LAN cards using the Nortel PCI bridge");
 MODULE_LICENSE("Dual MPL/GPL");
 
-static int __init nortel_pci_init(void)
+static int __init orinoco_nortel_init(void)
 {
        printk(KERN_DEBUG "%s\n", version);
-       return pci_module_init(&nortel_pci_driver);
+       return pci_module_init(&orinoco_nortel_driver);
 }
 
-static void __exit nortel_pci_exit(void)
+static void __exit orinoco_nortel_exit(void)
 {
-       pci_unregister_driver(&nortel_pci_driver);
-       ssleep(1);
+       pci_unregister_driver(&orinoco_nortel_driver);
 }
 
-module_init(nortel_pci_init);
-module_exit(nortel_pci_exit);
+module_init(orinoco_nortel_init);
+module_exit(orinoco_nortel_exit);
 
 /*
  * Local variables:
index 5362c214fc8e299da8bd0003f5d2bd76ab9fea6f..1c105f40f8d55f250f344f0e2427baf150bcb3d8 100644 (file)
@@ -1,11 +1,11 @@
 /* orinoco_pci.c
  * 
- * Driver for Prism II devices that have a direct PCI interface
- * (i.e., not in a Pcmcia or PLX bridge)
- *
- * Specifically here we're talking about the Linksys WMP11
+ * Driver for Prism 2.5/3 devices that have a direct PCI interface
+ * (i.e. these are not PCMCIA cards in a PCMCIA-to-PCI bridge).
+ * The card contains only one PCI region, which contains all the usual
+ * hermes registers, as well as the COR register.
  *
- * Current maintainers (as of 29 September 2003) are:
+ * Current maintainers are:
  *     Pavel Roskin <proski AT gnu.org>
  * and David Gibson <hermes AT gibson.dropbear.id.au>
  *
  * under either the MPL or the GPL.
  */
 
-/*
- * Theory of operation...
- * -------------------
- * Maybe you had a look in orinoco_plx. Well, this is totally different...
- *
- * The card contains only one PCI region, which contains all the usual
- * hermes registers.
- *
- * The driver will memory map this region in normal memory. Because
- * the hermes registers are mapped in normal memory and not in ISA I/O
- * post space, we can't use the usual inw/outw macros and we need to
- * use readw/writew.
- * This slight difference force us to compile our own version of
- * hermes.c with the register access macro changed. That's a bit
- * hackish but works fine.
- *
- * Note that the PCI region is pretty big (4K). That's much more than
- * the usual set of hermes register (0x0 -> 0x3E). I've got a strong
- * suspicion that the whole memory space of the adapter is in fact in
- * this region. Accessing directly the adapter memory instead of going
- * through the usual register would speed up significantely the
- * operations...
- *
- * Finally, the card looks like this :
------------------------
-  Bus  0, device  14, function  0:
-    Network controller: PCI device 1260:3873 (Harris Semiconductor) (rev 1).
-      IRQ 11.
-      Master Capable.  Latency=248.  
-      Prefetchable 32 bit memory at 0xffbcc000 [0xffbccfff].
------------------------
-00:0e.0 Network controller: Harris Semiconductor: Unknown device 3873 (rev 01)
-        Subsystem: Unknown device 1737:3874
-        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
-        Status: Cap+ 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
-        Latency: 248 set, cache line size 08
-        Interrupt: pin A routed to IRQ 11
-        Region 0: Memory at ffbcc000 (32-bit, prefetchable) [size=4K]
-        Capabilities: [dc] Power Management version 2
-                Flags: PMEClk- AuxPwr- DSI- D1+ D2+ PME+
-                Status: D0 PME-Enable- DSel=0 DScale=0 PME-
------------------------
- *
- * That's all..
- *
- * Jean II
- */
-
 #define DRIVER_NAME "orinoco_pci"
 #define PFX DRIVER_NAME ": "
 
 #include <linux/pci.h>
 
 #include "orinoco.h"
+#include "orinoco_pci.h"
 
-/* All the magic there is from wlan-ng */
-/* Magic offset of the reset register of the PCI card */
+/* Offset of the COR register of the PCI card */
 #define HERMES_PCI_COR         (0x26)
-/* Magic bitmask to reset the card */
+
+/* Bitmask to reset the card */
 #define HERMES_PCI_COR_MASK    (0x0080)
+
 /* Magic timeouts for doing the reset.
  * Those times are straight from wlan-ng, and it is claimed that they
  * are necessary. Alan will kill me. Take your time and grab a coffee. */
 #define HERMES_PCI_COR_OFFT    (500)           /* ms */
 #define HERMES_PCI_COR_BUSYT   (500)           /* ms */
 
-/* Orinoco PCI specific data */
-struct orinoco_pci_card {
-       void __iomem *pci_ioaddr;
-};
-
 /*
- * Do a soft reset of the PCI card using the Configuration Option Register
+ * Do a soft reset of the card using the Configuration Option Register
  * We need this to get going...
  * This is the part of the code that is strongly inspired from wlan-ng
  *
@@ -131,14 +80,13 @@ struct orinoco_pci_card {
  * Note bis : Don't try to access HERMES_CMD during the reset phase.
  * It just won't work !
  */
-static int
-orinoco_pci_cor_reset(struct orinoco_private *priv)
+static int orinoco_pci_cor_reset(struct orinoco_private *priv)
 {
        hermes_t *hw = &priv->hw;
-       unsigned long   timeout;
-       u16     reg;
+       unsigned long timeout;
+       u16 reg;
 
-       /* Assert the reset until the card notice */
+       /* Assert the reset until the card notices */
        hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK);
        mdelay(HERMES_PCI_COR_ONT);
 
@@ -163,19 +111,14 @@ orinoco_pci_cor_reset(struct orinoco_private *priv)
        return 0;
 }
 
-/*
- * Initialise a card. Mostly similar to PLX code.
- */
 static int orinoco_pci_init_one(struct pci_dev *pdev,
                                const struct pci_device_id *ent)
 {
-       int err = 0;
-       unsigned long pci_iorange;
-       u16 __iomem *pci_ioaddr = NULL;
-       unsigned long pci_iolen;
-       struct orinoco_private *priv = NULL;
+       int err;
+       struct orinoco_private *priv;
        struct orinoco_pci_card *card;
-       struct net_device *dev = NULL;
+       struct net_device *dev;
+       void __iomem *hermes_io;
 
        err = pci_enable_device(pdev);
        if (err) {
@@ -184,39 +127,32 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
        }
 
        err = pci_request_regions(pdev, DRIVER_NAME);
-       if (err != 0) {
+       if (err) {
                printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
                goto fail_resources;
        }
 
-       /* Resource 0 is mapped to the hermes registers */
-       pci_iorange = pci_resource_start(pdev, 0);
-       pci_iolen = pci_resource_len(pdev, 0);
-       pci_ioaddr = ioremap(pci_iorange, pci_iolen);
-       if (!pci_iorange) {
-               printk(KERN_ERR PFX "Cannot remap hardware registers\n");
-               goto fail_map;
+       hermes_io = pci_iomap(pdev, 0, 0);
+       if (!hermes_io) {
+               printk(KERN_ERR PFX "Cannot remap chipset registers\n");
+               err = -EIO;
+               goto fail_map_hermes;
        }
 
        /* Allocate network device */
        dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset);
-       if (! dev) {
+       if (!dev) {
+               printk(KERN_ERR PFX "Cannot allocate network device\n");
                err = -ENOMEM;
                goto fail_alloc;
        }
 
        priv = netdev_priv(dev);
        card = priv->card;
-       card->pci_ioaddr = pci_ioaddr;
-       dev->mem_start = pci_iorange;
-       dev->mem_end = pci_iorange + pci_iolen - 1;
        SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
-       hermes_struct_init(&priv->hw, pci_ioaddr, HERMES_32BIT_REGSPACING);
-
-       printk(KERN_DEBUG PFX "Detected device %s, mem:0x%lx-0x%lx, irq %d\n",
-              pci_name(pdev), dev->mem_start, dev->mem_end, pdev->irq);
+       hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING);
 
        err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
                          dev->name, dev);
@@ -225,9 +161,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
                err = -EBUSY;
                goto fail_irq;
        }
-       dev->irq = pdev->irq;
 
-       /* Perform a COR reset to start the card */
        err = orinoco_pci_cor_reset(priv);
        if (err) {
                printk(KERN_ERR PFX "Initial reset failed\n");
@@ -236,11 +170,13 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
 
        err = register_netdev(dev);
        if (err) {
-               printk(KERN_ERR PFX "Failed to register net device\n");
+               printk(KERN_ERR PFX "Cannot register network device\n");
                goto fail;
        }
 
        pci_set_drvdata(pdev, dev);
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+              pci_name(pdev));
 
        return 0;
 
@@ -252,9 +188,9 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
        free_orinocodev(dev);
 
  fail_alloc:
-       iounmap(pci_ioaddr);
+       pci_iounmap(pdev, hermes_io);
 
- fail_map:
+ fail_map_hermes:
        pci_release_regions(pdev);
 
  fail_resources:
@@ -267,87 +203,17 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct orinoco_private *priv = netdev_priv(dev);
-       struct orinoco_pci_card *card = priv->card;
 
        unregister_netdev(dev);
-       free_irq(dev->irq, dev);
+       free_irq(pdev->irq, dev);
        pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
-       iounmap(card->pci_ioaddr);
+       pci_iounmap(pdev, priv->hw.iobase);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
 }
 
-static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct orinoco_private *priv = netdev_priv(dev);
-       unsigned long flags;
-       int err;
-       
-
-       err = orinoco_lock(priv, &flags);
-       if (err) {
-               printk(KERN_ERR "%s: hw_unavailable on orinoco_pci_suspend\n",
-                      dev->name);
-               return err;
-       }
-
-       err = __orinoco_down(dev);
-       if (err)
-               printk(KERN_WARNING "%s: orinoco_pci_suspend(): Error %d downing interface\n",
-                      dev->name, err);
-       
-       netif_device_detach(dev);
-
-       priv->hw_unavailable++;
-       
-       orinoco_unlock(priv, &flags);
-
-       pci_save_state(pdev);
-       pci_set_power_state(pdev, PCI_D3hot);
-
-       return 0;
-}
-
-static int orinoco_pci_resume(struct pci_dev *pdev)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
-       struct orinoco_private *priv = netdev_priv(dev);
-       unsigned long flags;
-       int err;
-
-       printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name);
-
-       pci_set_power_state(pdev, 0);
-       pci_restore_state(pdev);
-
-       err = orinoco_reinit_firmware(dev);
-       if (err) {
-               printk(KERN_ERR "%s: Error %d re-initializing firmware on orinoco_pci_resume()\n",
-                      dev->name, err);
-               return err;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       netif_device_attach(dev);
-
-       priv->hw_unavailable--;
-
-       if (priv->open && (! priv->hw_unavailable)) {
-               err = __orinoco_up(dev);
-               if (err)
-                       printk(KERN_ERR "%s: Error %d restarting card on orinoco_pci_resume()\n",
-                              dev->name, err);
-       }
-       
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       return 0;
-}
-
-static struct pci_device_id orinoco_pci_pci_id_table[] = {
+static struct pci_device_id orinoco_pci_id_table[] = {
        /* Intersil Prism 3 */
        {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
        /* Intersil Prism 2.5 */
@@ -357,11 +223,11 @@ static struct pci_device_id orinoco_pci_pci_id_table[] = {
        {0,},
 };
 
-MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table);
+MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table);
 
 static struct pci_driver orinoco_pci_driver = {
        .name           = DRIVER_NAME,
-       .id_table       = orinoco_pci_pci_id_table,
+       .id_table       = orinoco_pci_id_table,
        .probe          = orinoco_pci_init_one,
        .remove         = __devexit_p(orinoco_pci_remove_one),
        .suspend        = orinoco_pci_suspend,
diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h
new file mode 100644 (file)
index 0000000..7eb1e08
--- /dev/null
@@ -0,0 +1,104 @@
+/* orinoco_pci.h
+ * 
+ * Common code for all Orinoco drivers for PCI devices, including
+ * both native PCI and PCMCIA-to-PCI bridges.
+ *
+ * Copyright (C) 2005, Pavel Roskin.
+ * See orinoco.c for license.
+ */
+
+#ifndef _ORINOCO_PCI_H
+#define _ORINOCO_PCI_H
+
+#include <linux/netdevice.h>
+
+/* Driver specific data */
+struct orinoco_pci_card {
+       void __iomem *bridge_io;
+       void __iomem *attr_io;
+};
+
+#ifdef CONFIG_PM
+static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct orinoco_private *priv = netdev_priv(dev);
+       unsigned long flags;
+       int err;
+
+       err = orinoco_lock(priv, &flags);
+       if (err) {
+               printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
+                      dev->name);
+               return err;
+       }
+
+       err = __orinoco_down(dev);
+       if (err)
+               printk(KERN_WARNING "%s: error %d bringing interface down "
+                      "for suspend\n", dev->name, err);
+       
+       netif_device_detach(dev);
+
+       priv->hw_unavailable++;
+       
+       orinoco_unlock(priv, &flags);
+
+       free_irq(pdev->irq, dev);
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D3hot);
+
+       return 0;
+}
+
+static int orinoco_pci_resume(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct orinoco_private *priv = netdev_priv(dev);
+       unsigned long flags;
+       int err;
+
+       pci_set_power_state(pdev, 0);
+       pci_enable_device(pdev);
+       pci_restore_state(pdev);
+
+       err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
+                         dev->name, dev);
+       if (err) {
+               printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
+                      dev->name);
+               pci_disable_device(pdev);
+               return -EBUSY;
+       }
+
+       err = orinoco_reinit_firmware(dev);
+       if (err) {
+               printk(KERN_ERR "%s: error %d re-initializing firmware "
+                      "on resume\n", dev->name, err);
+               return err;
+       }
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       netif_device_attach(dev);
+
+       priv->hw_unavailable--;
+
+       if (priv->open && (! priv->hw_unavailable)) {
+               err = __orinoco_up(dev);
+               if (err)
+                       printk(KERN_ERR "%s: Error %d restarting card on resume\n",
+                              dev->name, err);
+       }
+       
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
+}
+#else
+#define orinoco_pci_suspend NULL
+#define orinoco_pci_resume NULL
+#endif
+
+#endif /* _ORINOCO_PCI_H */
index 210e73776545d6750e0e99289ff7f023acf2b69a..84f696c77551e1ce420a6e7341e0a3f0717e73c7 100644 (file)
@@ -3,7 +3,7 @@
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
  * but are connected to the PCI bus by a PLX9052.
  *
- * Current maintainers (as of 29 September 2003) are:
+ * Current maintainers are:
  *     Pavel Roskin <proski AT gnu.org>
  * and David Gibson <hermes AT gibson.dropbear.id.au>
  *
  * other provisions required by the GPL.  If you do not delete the
  * provisions above, a recipient may use your version of this file
  * under either the MPL or the GPL.
-
- * Caution: this is experimental and probably buggy.  For success and
- * failure reports for different cards and adaptors, see
- * orinoco_plx_pci_id_table near the end of the file.  If you have a
- * card we don't have the PCI id for, and looks like it should work,
- * drop me mail with the id and "it works"/"it doesn't work".
- *
- * Note: if everything gets detected fine but it doesn't actually send
- * or receive packets, your first port of call should probably be to
- * try newer firmware in the card.  Especially if you're doing Ad-Hoc
- * modes.
- *
- * The actual driving is done by orinoco.c, this is just resource
- * allocation stuff.  The explanation below is courtesy of Ryan Niemi
- * on the linux-wlan-ng list at
- * http://archives.neohapsis.com/archives/dev/linux-wlan/2001-q1/0026.html
  *
- * The PLX9052-based cards (WL11000 and several others) are a
- * different beast than the usual PCMCIA-based PRISM2 configuration
- * expected by wlan-ng.  Here's the general details on how the WL11000
- * PCI adapter works:
+ * Here's the general details on how the PLX9052 adapter works:
  *
  * - Two PCI I/O address spaces, one 0x80 long which contains the
  * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA
  * slot I/O address space.
  *
- * - One PCI memory address space, mapped to the PCMCIA memory space
+ * - One PCI memory address space, mapped to the PCMCIA attribute space
  * (containing the CIS).
  *
- * After identifying the I/O and memory space, you can read through
- * the memory space to confirm the CIS's device ID or manufacturer ID
- * to make sure it's the expected card.  qKeep in mind that the PCMCIA
+ * Using the later, you can read through the CIS data to make sure the
+ * card is compatible with the driver. Keep in mind that the PCMCIA
  * spec specifies the CIS as the lower 8 bits of each word read from
  * the CIS, so to read the bytes of the CIS, read every other byte
  * (0,2,4,...). Passing that test, you need to enable the I/O address
@@ -71,7 +51,7 @@
  * within the PCI memory space. Write 0x41 to the COR register to
  * enable I/O mode and to select level triggered interrupts. To
  * confirm you actually succeeded, read the COR register back and make
- * sure it actually got set to 0x41, incase you have an unexpected
+ * sure it actually got set to 0x41, in case you have an unexpected
  * card inserted.
  *
  * Following that, you can treat the second PCI I/O address space (the
  * that, I've hot-swapped a number of times during debugging and
  * driver development for various reasons (stuck WAIT# line after the
  * radio card's firmware locks up).
- *
- * Hope this is enough info for someone to add PLX9052 support to the
- * wlan-ng card. In the case of the WL11000, the PCI ID's are
- * 0x1639/0x0200, with matching subsystem ID's. Other PLX9052-based
- * manufacturers other than Eumitcom (or on cards other than the
- * WL11000) may have different PCI ID's.
- *
- * If anyone needs any more specific info, let me know. I haven't had
- * time to implement support myself yet, and with the way things are
- * going, might not have time for a while..
  */
 
 #define DRIVER_NAME "orinoco_plx"
 #include <pcmcia/cisreg.h>
 
 #include "orinoco.h"
+#include "orinoco_pci.h"
 
 #define COR_OFFSET     (0x3e0) /* COR attribute offset of Prism2 PC card */
 #define COR_VALUE      (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
 #define PLX_INTCSR             0x4c /* Interrupt Control & Status Register */
 #define PLX_INTCSR_INTEN       (1<<6) /* Interrupt Enable bit */
 
-static const u8 cis_magic[] = {
-       0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
-};
-
-/* Orinoco PLX specific data */
-struct orinoco_plx_card {
-       void __iomem *attr_mem;
-};
-
 /*
  * Do a soft reset of the card using the Configuration Option Register
  */
 static int orinoco_plx_cor_reset(struct orinoco_private *priv)
 {
        hermes_t *hw = &priv->hw;
-       struct orinoco_plx_card *card = priv->card;
-       u8 __iomem *attr_mem = card->attr_mem;
+       struct orinoco_pci_card *card = priv->card;
        unsigned long timeout;
        u16 reg;
 
-       writeb(COR_VALUE | COR_RESET, attr_mem + COR_OFFSET);
+       iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET);
        mdelay(1);
 
-       writeb(COR_VALUE, attr_mem + COR_OFFSET);
+       iowrite8(COR_VALUE, card->attr_io + COR_OFFSET);
        mdelay(1);
 
        /* Just in case, wait more until the card is no longer busy */
@@ -168,7 +129,7 @@ static int orinoco_plx_cor_reset(struct orinoco_private *priv)
                reg = hermes_read_regn(hw, CMD);
        }
 
-       /* Did we timeout ? */
+       /* Still busy? */
        if (reg & HERMES_CMD_BUSY) {
                printk(KERN_ERR PFX "Busy timeout\n");
                return -ETIMEDOUT;
@@ -177,20 +138,55 @@ static int orinoco_plx_cor_reset(struct orinoco_private *priv)
        return 0;
 }
 
+static int orinoco_plx_hw_init(struct orinoco_pci_card *card)
+{
+       int i;
+       u32 csr_reg;
+       static const u8 cis_magic[] = {
+               0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
+       };
+
+       printk(KERN_DEBUG PFX "CIS: ");
+       for (i = 0; i < 16; i++) {
+               printk("%02X:", ioread8(card->attr_io + (i << 1)));
+       }
+       printk("\n");
+
+       /* Verify whether a supported PC card is present */
+       /* FIXME: we probably need to be smarted about this */
+       for (i = 0; i < sizeof(cis_magic); i++) {
+               if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) {
+                       printk(KERN_ERR PFX "The CIS value of Prism2 PC "
+                              "card is unexpected\n");
+                       return -ENODEV;
+               }
+       }
+
+       /* bjoern: We need to tell the card to enable interrupts, in
+          case the serial eprom didn't do this already.  See the
+          PLX9052 data book, p8-1 and 8-24 for reference. */
+       csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
+       if (!(csr_reg & PLX_INTCSR_INTEN)) {
+               csr_reg |= PLX_INTCSR_INTEN;
+               iowrite32(csr_reg, card->bridge_io + PLX_INTCSR);
+               csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
+               if (!(csr_reg & PLX_INTCSR_INTEN)) {
+                       printk(KERN_ERR PFX "Cannot enable interrupts\n");
+                       return -EIO;
+               }
+       }
+
+       return 0;
+}
 
 static int orinoco_plx_init_one(struct pci_dev *pdev,
                                const struct pci_device_id *ent)
 {
-       int err = 0;
-       u8 __iomem *attr_mem = NULL;
-       u32 csr_reg, plx_addr;
-       struct orinoco_private *priv = NULL;
-       struct orinoco_plx_card *card;
-       unsigned long pccard_ioaddr = 0;
-       unsigned long pccard_iolen = 0;
-       struct net_device *dev = NULL;
-       void __iomem *mem;
-       int i;
+       int err;
+       struct orinoco_private *priv;
+       struct orinoco_pci_card *card;
+       struct net_device *dev;
+       void __iomem *hermes_io, *attr_io, *bridge_io;
 
        err = pci_enable_device(pdev);
        if (err) {
@@ -199,30 +195,30 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
        }
 
        err = pci_request_regions(pdev, DRIVER_NAME);
-       if (err != 0) {
+       if (err) {
                printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
                goto fail_resources;
        }
 
-       /* Resource 1 is mapped to PLX-specific registers */
-       plx_addr = pci_resource_start(pdev, 1);
+       bridge_io = pci_iomap(pdev, 1, 0);
+       if (!bridge_io) {
+               printk(KERN_ERR PFX "Cannot map bridge registers\n");
+               err = -EIO;
+               goto fail_map_bridge;
+       }
 
-       /* Resource 2 is mapped to the PCMCIA attribute memory */
-       attr_mem = ioremap(pci_resource_start(pdev, 2),
-                          pci_resource_len(pdev, 2));
-       if (!attr_mem) {
-               printk(KERN_ERR PFX "Cannot remap PCMCIA space\n");
+       attr_io = pci_iomap(pdev, 2, 0);
+       if (!attr_io) {
+               printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
+               err = -EIO;
                goto fail_map_attr;
        }
 
-       /* Resource 3 is mapped to the PCMCIA I/O address space */
-       pccard_ioaddr = pci_resource_start(pdev, 3);
-       pccard_iolen = pci_resource_len(pdev, 3);
-
-       mem = pci_iomap(pdev, 3, 0);
-       if (!mem) {
-               err = -ENOMEM;
-               goto fail_map_io;
+       hermes_io = pci_iomap(pdev, 3, 0);
+       if (!hermes_io) {
+               printk(KERN_ERR PFX "Cannot map chipset registers\n");
+               err = -EIO;
+               goto fail_map_hermes;
        }
 
        /* Allocate network device */
@@ -235,16 +231,12 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
 
        priv = netdev_priv(dev);
        card = priv->card;
-       card->attr_mem = attr_mem;
-       dev->base_addr = pccard_ioaddr;
+       card->bridge_io = bridge_io;
+       card->attr_io = attr_io;
        SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
-       hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING);
-
-       printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device "
-              "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
-              pccard_ioaddr);
+       hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
 
        err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
                          dev->name, dev);
@@ -253,20 +245,11 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
                err = -EBUSY;
                goto fail_irq;
        }
-       dev->irq = pdev->irq;
 
-       /* bjoern: We need to tell the card to enable interrupts, in
-          case the serial eprom didn't do this already.  See the
-          PLX9052 data book, p8-1 and 8-24 for reference. */
-       csr_reg = inl(plx_addr + PLX_INTCSR);
-       if (!(csr_reg & PLX_INTCSR_INTEN)) {
-               csr_reg |= PLX_INTCSR_INTEN;
-               outl(csr_reg, plx_addr + PLX_INTCSR);
-               csr_reg = inl(plx_addr + PLX_INTCSR);
-               if (!(csr_reg & PLX_INTCSR_INTEN)) {
-                       printk(KERN_ERR PFX "Cannot enable interrupts\n");
-                       goto fail;
-               }
+       err = orinoco_plx_hw_init(card);
+       if (err) {
+               printk(KERN_ERR PFX "Hardware initialization failed\n");
+               goto fail;
        }
 
        err = orinoco_plx_cor_reset(priv);
@@ -275,23 +258,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
                goto fail;
        }
 
-       printk(KERN_DEBUG PFX "CIS: ");
-       for (i = 0; i < 16; i++) {
-               printk("%02X:", readb(attr_mem + 2*i));
-       }
-       printk("\n");
-
-       /* Verify whether a supported PC card is present */
-       /* FIXME: we probably need to be smarted about this */
-       for (i = 0; i < sizeof(cis_magic); i++) {
-               if (cis_magic[i] != readb(attr_mem +2*i)) {
-                       printk(KERN_ERR PFX "The CIS value of Prism2 PC "
-                              "card is unexpected\n");
-                       err = -EIO;
-                       goto fail;
-               }
-       }
-
        err = register_netdev(dev);
        if (err) {
                printk(KERN_ERR PFX "Cannot register network device\n");
@@ -299,6 +265,8 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
        }
 
        pci_set_drvdata(pdev, dev);
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+              pci_name(pdev));
 
        return 0;
 
@@ -310,12 +278,15 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
        free_orinocodev(dev);
 
  fail_alloc:
-       pci_iounmap(pdev, mem);
+       pci_iounmap(pdev, hermes_io);
 
- fail_map_io:
-       iounmap(attr_mem);
+ fail_map_hermes:
+       pci_iounmap(pdev, attr_io);
 
  fail_map_attr:
+       pci_iounmap(pdev, bridge_io);
+
+ fail_map_bridge:
        pci_release_regions(pdev);
 
  fail_resources:
@@ -328,23 +299,20 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct orinoco_private *priv = netdev_priv(dev);
-       struct orinoco_plx_card *card = priv->card;
-       u8 __iomem *attr_mem = card->attr_mem;
-
-       BUG_ON(! dev);
+       struct orinoco_pci_card *card = priv->card;
 
        unregister_netdev(dev);
-       free_irq(dev->irq, dev);
+       free_irq(pdev->irq, dev);
        pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
        pci_iounmap(pdev, priv->hw.iobase);
-       iounmap(attr_mem);
+       pci_iounmap(pdev, card->attr_io);
+       pci_iounmap(pdev, card->bridge_io);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
 }
 
-
-static struct pci_device_id orinoco_plx_pci_id_table[] = {
+static struct pci_device_id orinoco_plx_id_table[] = {
        {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,},      /* Siemens SpeedStream SS1023 */
        {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,},      /* Netgear MA301 */
        {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,},      /* Correga  - does this work? */
@@ -362,13 +330,15 @@ static struct pci_device_id orinoco_plx_pci_id_table[] = {
        {0,},
 };
 
-MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table);
+MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table);
 
 static struct pci_driver orinoco_plx_driver = {
        .name           = DRIVER_NAME,
-       .id_table       = orinoco_plx_pci_id_table,
+       .id_table       = orinoco_plx_id_table,
        .probe          = orinoco_plx_init_one,
        .remove         = __devexit_p(orinoco_plx_remove_one),
+       .suspend        = orinoco_pci_suspend,
+       .resume         = orinoco_pci_resume,
 };
 
 static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -388,7 +358,6 @@ static int __init orinoco_plx_init(void)
 static void __exit orinoco_plx_exit(void)
 {
        pci_unregister_driver(&orinoco_plx_driver);
-       ssleep(1);
 }
 
 module_init(orinoco_plx_init);
index 5e68b7026186bc9f497c1abbf9d14259e4a96bca..d2b4decb7a7d005cdf87c2c91d9269f7f5e8cd92 100644 (file)
@@ -1,5 +1,5 @@
 /* orinoco_tmd.c
- * 
+ *
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
  * but are connected to the PCI bus by a TMD7160. 
  *
  * other provisions required by the GPL.  If you do not delete the
  * provisions above, a recipient may use your version of this file
  * under either the MPL or the GPL.
-
- * Caution: this is experimental and probably buggy.  For success and
- * failure reports for different cards and adaptors, see
- * orinoco_tmd_pci_id_table near the end of the file.  If you have a
- * card we don't have the PCI id for, and looks like it should work,
- * drop me mail with the id and "it works"/"it doesn't work".
- *
- * Note: if everything gets detected fine but it doesn't actually send
- * or receive packets, your first port of call should probably be to   
- * try newer firmware in the card.  Especially if you're doing Ad-Hoc
- * modes
  *
  * The actual driving is done by orinoco.c, this is just resource
  * allocation stuff.
  *
  * This driver is modeled after the orinoco_plx driver. The main
- * difference is that the TMD chip has only IO port ranges and no
- * memory space, i.e.  no access to the CIS. Compared to the PLX chip,
- * the io range functionalities are exchanged.
+ * difference is that the TMD chip has only IO port ranges and doesn't
+ * provide access to the PCMCIA attribute space.
  *
  * Pheecom sells cards with the TMD chip as "ASIC version"
  */
 #include <pcmcia/cisreg.h>
 
 #include "orinoco.h"
+#include "orinoco_pci.h"
 
 #define COR_VALUE      (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
 #define COR_RESET     (0x80)   /* reset bit in the COR register */
 #define TMD_RESET_TIME (500)   /* milliseconds */
 
-/* Orinoco TMD specific data */
-struct orinoco_tmd_card {
-       u32 tmd_io;
-};
-
-
 /*
  * Do a soft reset of the card using the Configuration Option Register
  */
 static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
 {
        hermes_t *hw = &priv->hw;
-       struct orinoco_tmd_card *card = priv->card;
-       u32 addr = card->tmd_io;
+       struct orinoco_pci_card *card = priv->card;
        unsigned long timeout;
        u16 reg;
 
-       outb(COR_VALUE | COR_RESET, addr);
+       iowrite8(COR_VALUE | COR_RESET, card->bridge_io);
        mdelay(1);
 
-       outb(COR_VALUE, addr);
+       iowrite8(COR_VALUE, card->bridge_io);
        mdelay(1);
 
        /* Just in case, wait more until the card is no longer busy */
@@ -97,7 +79,7 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
                reg = hermes_read_regn(hw, CMD);
        }
 
-       /* Did we timeout ? */
+       /* Still busy? */
        if (reg & HERMES_CMD_BUSY) {
                printk(KERN_ERR PFX "Busy timeout\n");
                return -ETIMEDOUT;
@@ -110,11 +92,11 @@ static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
 static int orinoco_tmd_init_one(struct pci_dev *pdev,
                                const struct pci_device_id *ent)
 {
-       int err = 0;
-       struct orinoco_private *priv = NULL;
-       struct orinoco_tmd_card *card;
-       struct net_device *dev = NULL;
-       void __iomem *mem;
+       int err;
+       struct orinoco_private *priv;
+       struct orinoco_pci_card *card;
+       struct net_device *dev;
+       void __iomem *hermes_io, *bridge_io;
 
        err = pci_enable_device(pdev);
        if (err) {
@@ -123,20 +105,28 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
        }
 
        err = pci_request_regions(pdev, DRIVER_NAME);
-       if (err != 0) {
+       if (err) {
                printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
                goto fail_resources;
        }
 
-       mem = pci_iomap(pdev, 2, 0);
-       if (! mem) {
-               err = -ENOMEM;
-               goto fail_iomap;
+       bridge_io = pci_iomap(pdev, 1, 0);
+       if (!bridge_io) {
+               printk(KERN_ERR PFX "Cannot map bridge registers\n");
+               err = -EIO;
+               goto fail_map_bridge;
+       }
+
+       hermes_io = pci_iomap(pdev, 2, 0);
+       if (!hermes_io) {
+               printk(KERN_ERR PFX "Cannot map chipset registers\n");
+               err = -EIO;
+               goto fail_map_hermes;
        }
 
        /* Allocate network device */
        dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset);
-       if (! dev) {
+       if (!dev) {
                printk(KERN_ERR PFX "Cannot allocate network device\n");
                err = -ENOMEM;
                goto fail_alloc;
@@ -144,16 +134,11 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
 
        priv = netdev_priv(dev);
        card = priv->card;
-       card->tmd_io = pci_resource_start(pdev, 1);
-       dev->base_addr = pci_resource_start(pdev, 2);
+       card->bridge_io = bridge_io;
        SET_MODULE_OWNER(dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
-       hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING);
-
-       printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device "
-              "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
-              dev->base_addr);
+       hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
 
        err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
                          dev->name, dev);
@@ -162,7 +147,6 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
                err = -EBUSY;
                goto fail_irq;
        }
-       dev->irq = pdev->irq;
 
        err = orinoco_tmd_cor_reset(priv);
        if (err) {
@@ -177,6 +161,8 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
        }
 
        pci_set_drvdata(pdev, dev);
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+              pci_name(pdev));
 
        return 0;
 
@@ -188,9 +174,12 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
        free_orinocodev(dev);
 
  fail_alloc:
-       pci_iounmap(pdev, mem);
+       pci_iounmap(pdev, hermes_io);
+
+ fail_map_hermes:
+       pci_iounmap(pdev, bridge_io);
 
- fail_iomap:
+ fail_map_bridge:
        pci_release_regions(pdev);
 
  fail_resources:
@@ -203,31 +192,32 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct orinoco_private *priv = dev->priv;
-
-       BUG_ON(! dev);
+       struct orinoco_pci_card *card = priv->card;
 
        unregister_netdev(dev);
-       free_irq(dev->irq, dev);
+       free_irq(pdev->irq, dev);
        pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
        pci_iounmap(pdev, priv->hw.iobase);
+       pci_iounmap(pdev, card->bridge_io);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
 }
 
-
-static struct pci_device_id orinoco_tmd_pci_id_table[] = {
+static struct pci_device_id orinoco_tmd_id_table[] = {
        {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,},      /* NDC and OEMs, e.g. pheecom */
        {0,},
 };
 
-MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table);
+MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table);
 
 static struct pci_driver orinoco_tmd_driver = {
        .name           = DRIVER_NAME,
-       .id_table       = orinoco_tmd_pci_id_table,
+       .id_table       = orinoco_tmd_id_table,
        .probe          = orinoco_tmd_init_one,
        .remove         = __devexit_p(orinoco_tmd_remove_one),
+       .suspend        = orinoco_pci_suspend,
+       .resume         = orinoco_pci_resume,
 };
 
 static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -245,7 +235,6 @@ static int __init orinoco_tmd_init(void)
 static void __exit orinoco_tmd_exit(void)
 {
        pci_unregister_driver(&orinoco_tmd_driver);
-       ssleep(1);
 }
 
 module_init(orinoco_tmd_init);
index f7b77ce54d7bee77aafbbf541bfb77722593d951..7f9aa139c3475fb11e526433fd85566ada350c48 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as
- * Symbol Wireless Networker LA4100, CompactFlash cards by Socket
+ * Symbol Wireless Networker LA4137, CompactFlash cards by Socket
  * Communications and Intel PRO/Wireless 2011B.
  *
  * The driver implements Symbol firmware download.  The rest is handled
@@ -120,8 +120,8 @@ static void spectrum_cs_release(struct pcmcia_device *link);
  * Each block has the following structure.
  */
 struct dblock {
-       __le32 _addr;           /* adapter address where to write the block */
-       __le16 _len;            /* length of the data only, in bytes */
+       __le32 addr;            /* adapter address where to write the block */
+       __le16 len;             /* length of the data only, in bytes */
        char data[0];           /* data to be written */
 } __attribute__ ((packed));
 
@@ -131,9 +131,9 @@ struct dblock {
  * items with matching ID should be written.
  */
 struct pdr {
-       __le32 _id;             /* record ID */
-       __le32 _addr;           /* adapter address where to write the data */
-       __le32 _len;            /* expected length of the data, in bytes */
+       __le32 id;              /* record ID */
+       __le32 addr;            /* adapter address where to write the data */
+       __le32 len;             /* expected length of the data, in bytes */
        char next[0];           /* next PDR starts here */
 } __attribute__ ((packed));
 
@@ -144,8 +144,8 @@ struct pdr {
  * be plugged into the secondary firmware.
  */
 struct pdi {
-       __le16 _len;            /* length of ID and data, in words */
-       __le16 _id;             /* record ID */
+       __le16 len;             /* length of ID and data, in words */
+       __le16 id;              /* record ID */
        char data[0];           /* plug data */
 } __attribute__ ((packed));
 
@@ -154,44 +154,44 @@ struct pdi {
 static inline u32
 dblock_addr(const struct dblock *blk)
 {
-       return le32_to_cpu(blk->_addr);
+       return le32_to_cpu(blk->addr);
 }
 
 static inline u32
 dblock_len(const struct dblock *blk)
 {
-       return le16_to_cpu(blk->_len);
+       return le16_to_cpu(blk->len);
 }
 
 static inline u32
 pdr_id(const struct pdr *pdr)
 {
-       return le32_to_cpu(pdr->_id);
+       return le32_to_cpu(pdr->id);
 }
 
 static inline u32
 pdr_addr(const struct pdr *pdr)
 {
-       return le32_to_cpu(pdr->_addr);
+       return le32_to_cpu(pdr->addr);
 }
 
 static inline u32
 pdr_len(const struct pdr *pdr)
 {
-       return le32_to_cpu(pdr->_len);
+       return le32_to_cpu(pdr->len);
 }
 
 static inline u32
 pdi_id(const struct pdi *pdi)
 {
-       return le16_to_cpu(pdi->_id);
+       return le16_to_cpu(pdi->id);
 }
 
 /* Return length of the data only, in bytes */
 static inline u32
 pdi_len(const struct pdi *pdi)
 {
-       return 2 * (le16_to_cpu(pdi->_len) - 1);
+       return 2 * (le16_to_cpu(pdi->len) - 1);
 }
 
 
@@ -343,8 +343,7 @@ spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi)
 
        /* do the actual plugging */
        spectrum_aux_setaddr(hw, pdr_addr(pdr));
-       hermes_write_words(hw, HERMES_AUXDATA, pdi->data,
-                          pdi_len(pdi) / 2);
+       hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
 
        return 0;
 }
@@ -424,8 +423,8 @@ spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
 
        while (dblock_addr(blk) != BLOCK_END) {
                spectrum_aux_setaddr(hw, blkaddr);
-               hermes_write_words(hw, HERMES_AUXDATA, blk->data,
-                                  blklen / 2);
+               hermes_write_bytes(hw, HERMES_AUXDATA, blk->data,
+                                  blklen);
 
                blk = (struct dblock *) &blk->data[blklen];
                blkaddr = dblock_addr(blk);
@@ -626,14 +625,11 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
 
+       if (link->dev_node)
+               unregister_netdev(dev);
+
        spectrum_cs_release(link);
 
-       DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
-       if (link->dev_node) {
-               DEBUG(0, PFX "About to unregister net device %p\n",
-                     dev);
-               unregister_netdev(dev);
-       }
        free_orinocodev(dev);
 }                              /* spectrum_cs_detach */
 
@@ -653,13 +649,10 @@ spectrum_cs_config(struct pcmcia_device *link)
        int last_fn, last_ret;
        u_char buf[64];
        config_info_t conf;
-       cisinfo_t info;
        tuple_t tuple;
        cisparse_t parse;
        void __iomem *mem;
 
-       CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
-
        /*
         * This reads the card's CONFIG tuple to find its
         * configuration registers.
@@ -709,12 +702,6 @@ spectrum_cs_config(struct pcmcia_device *link)
                        goto next_entry;
                link->conf.ConfigIndex = cfg->index;
 
-               /* Does this card need audio output? */
-               if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-                       link->conf.Attributes |= CONF_ENABLE_SPKR;
-                       link->conf.Status = CCSR_AUDIO_ENA;
-               }
-
                /* Use power settings for Vcc and Vpp if present */
                /* Note that the CIS values need to be rescaled */
                if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
@@ -835,19 +822,10 @@ spectrum_cs_config(struct pcmcia_device *link)
                                     net_device has been registered */
 
        /* Finally, report what we've done */
-       printk(KERN_DEBUG "%s: index 0x%02x: ",
-              dev->name, link->conf.ConfigIndex);
-       if (link->conf.Vpp)
-               printk(", Vpp %d.%d", link->conf.Vpp / 10,
-                      link->conf.Vpp % 10);
-       printk(", irq %d", link->irq.AssignedIRQ);
-       if (link->io.NumPorts1)
-               printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-                      link->io.BasePort1 + link->io.NumPorts1 - 1);
-       if (link->io.NumPorts2)
-               printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-                      link->io.BasePort2 + link->io.NumPorts2 - 1);
-       printk("\n");
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
+              "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id,
+              link->irq.AssignedIRQ, link->io.BasePort1,
+              link->io.BasePort1 + link->io.NumPorts1 - 1);
 
        return 0;
 
@@ -888,11 +866,10 @@ spectrum_cs_suspend(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
        struct orinoco_private *priv = netdev_priv(dev);
-       unsigned long flags;
        int err = 0;
 
        /* Mark the device as stopped, to block IO until later */
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock(&priv->lock);
 
        err = __orinoco_down(dev);
        if (err)
@@ -902,9 +879,9 @@ spectrum_cs_suspend(struct pcmcia_device *link)
        netif_device_detach(dev);
        priv->hw_unavailable++;
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock(&priv->lock);
 
-       return 0;
+       return err;
 }
 
 static int
@@ -932,7 +909,7 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
        " David Gibson <hermes@gibson.dropbear.id.au>, et al)";
 
 static struct pcmcia_device_id spectrum_cs_ids[] = {
-       PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
+       PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */
        PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
        PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
        PCMCIA_DEVICE_NULL,
index ff192e96268a1c69519a3c35aac6386bec35ed10..dade4b903579fe2d8f06f03cd3d9fe9c590d48fa 100644 (file)
@@ -4306,7 +4306,7 @@ out:
  * Insertion of the module
  * I'm now quite proud of the multi-device support.
  */
-int init_module(void)
+int __init init_module(void)
 {
        int ret = -EIO;         /* Return error if no cards found */
        int i;
similarity index 97%
rename from drivers/usb/net/zd1201.c
rename to drivers/net/wireless/zd1201.c
index 9b1e4ed1d07e7ab7afda3617406a846ef7fb6fc7..662ecc8a33ff9f6559a32c8dff38d25ff5b793ad 100644 (file)
@@ -33,7 +33,7 @@ static struct usb_device_id zd1201_table[] = {
        {}
 };
 
-static int ap = 0;     /* Are we an AP or a normal station? */
+static int ap; /* Are we an AP or a normal station? */
 
 #define ZD1201_VERSION "0.15"
 
@@ -49,7 +49,7 @@ MODULE_DEVICE_TABLE(usb, zd1201_table);
 static int zd1201_fw_upload(struct usb_device *dev, int apfw)
 {
        const struct firmware *fw_entry;
-       chardata;
+       char *data;
        unsigned long len;
        int err;
        unsigned char ret;
@@ -65,7 +65,7 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
        if (err) {
                dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile);
                dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n");
-               dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info\n");
+               dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n");
                return err;
        }
 
@@ -94,12 +94,12 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
            USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT);
        if (err < 0)
                goto exit;
-                                                                                                                                                                
+
        err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
            USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
        if (err < 0)
                goto exit;
-                                                                                                                                                                                                                                                                                        
+
        if (ret & 0x80) {
                err = -EIO;
                goto exit;
@@ -166,13 +166,13 @@ static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0,
                return -ENOMEM;
        }
        usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
-            command, 16, zd1201_usbfree, zd);
+                         command, 16, zd1201_usbfree, zd);
        ret = usb_submit_urb(urb, GFP_ATOMIC);
        if (ret) {
                kfree(command);
                usb_free_urb(urb);
        }
-       
+
        return ret;
 }
 
@@ -316,7 +316,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
                fc = le16_to_cpu(*(__le16 *)&data[datalen-16]);
                seq = le16_to_cpu(*(__le16 *)&data[datalen-24]);
 
-               if(zd->monitor) {
+               if (zd->monitor) {
                        if (datalen < 24)
                                goto resubmit;
                        if (!(skb = dev_alloc_skb(datalen+24)))
@@ -364,7 +364,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
                                goto resubmit;
                        }
                        hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
-                               if(frag->seq == (seq&IEEE80211_SCTL_SEQ))
+                               if (frag->seq == (seq&IEEE80211_SCTL_SEQ))
                                        break;
                        if (!frag)
                                goto resubmit;
@@ -376,7 +376,6 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
                                goto resubmit;
                        hlist_del_init(&frag->fnode);
                        kfree(frag);
-                       /* Fallthrough */
                } else {
                        if (datalen<14)
                                goto resubmit;
@@ -422,7 +421,7 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
        int rid_fid;
        int length;
        unsigned char *pdata;
-       
+
        zd->rxdatas = 0;
        err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0);
        if (err)
@@ -471,11 +470,11 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
        length = zd->rxlen;
 
        do {
-               int  actual_length;
+               int actual_length;
 
                actual_length = (length > 64) ? 64 : length;
 
-               if(pdata[0] != 0x3) {
+               if (pdata[0] != 0x3) {
                        dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n",
                            pdata[0]);
                        return -EINVAL;
@@ -487,11 +486,10 @@ static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
                }
 
                /* Skip the 4 bytes header (RID length and RID) */
-               if(i == 0) {
+               if (i == 0) {
                        pdata += 8;
                        actual_length -= 8;
-               }
-               else {
+               } else {
                        pdata += 4;
                        actual_length -= 4;
                }
@@ -620,7 +618,7 @@ static int zd1201_drvr_start(struct zd1201 *zd)
        short max;
        __le16 zdmax;
        unsigned char *buffer;
-       
+
        buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL);
        if (!buffer)
                return -ENOMEM;
@@ -632,7 +630,7 @@ static int zd1201_drvr_start(struct zd1201 *zd)
        err = usb_submit_urb(zd->rx_urb, GFP_KERNEL);
        if (err)
                goto err_buffer;
-       
+
        err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
        if (err)
                goto err_urb;
@@ -684,7 +682,7 @@ static int zd1201_enable(struct zd1201 *zd)
 static int zd1201_disable(struct zd1201 *zd)
 {
        int err;
-       
+
        if (!zd->mac_enabled)
                return 0;
        if (zd->monitor) {
@@ -764,7 +762,6 @@ static int zd1201_net_open(struct net_device *dev)
 static int zd1201_net_stop(struct net_device *dev)
 {
        netif_stop_queue(dev);
-       
        return 0;
 }
 
@@ -915,7 +912,6 @@ static int zd1201_get_name(struct net_device *dev,
     struct iw_request_info *info, char *name, char *extra)
 {
        strcpy(name, "IEEE 802.11b");
-
        return 0;
 }
 
@@ -1013,11 +1009,10 @@ static int zd1201_set_mode(struct net_device *dev,
                        if (err)
                                return err;
        }
-       zd->monitor=monitor;
+       zd->monitor = monitor;
        /* If monitor mode is set we don't actually turn it on here since it
         * is done during mac reset anyway (see zd1201_mac_enable).
         */
-
        zd1201_mac_reset(zd);
 
        return 0;
@@ -1117,7 +1112,7 @@ static int zd1201_get_wap(struct net_device *dev,
                zd->iwstats.qual.updated = 2;
        }
 
-       return zd1201_getconfig(zd,ZD1201_RID_CURRENTBSSID,ap_addr->sa_data,6);
+       return zd1201_getconfig(zd, ZD1201_RID_CURRENTBSSID, ap_addr->sa_data, 6);
 }
 
 static int zd1201_set_scan(struct net_device *dev,
@@ -1275,7 +1270,7 @@ static int zd1201_set_rate(struct net_device *dev,
        if (!rrq->fixed) { /* Also enable all lower bitrates */
                rate |= rate-1;
        }
-       
+
        err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate);
        if (err)
                return err;
@@ -1486,7 +1481,7 @@ static int zd1201_get_encode(struct net_device *dev,
                return -EINVAL;
 
        erq->flags |= i+1;
-       
+
        erq->length = zd->encode_keylen[i];
        memcpy(key, zd->encode_keys[i], erq->length);
 
@@ -1529,11 +1524,7 @@ static int zd1201_set_power(struct net_device *dev,
                return -EINVAL;
        }
 out:
-       err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
-       if (err)
-               return err;
-
-       return 0;
+       return zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
 }
 
 static int zd1201_get_power(struct net_device *dev,
@@ -1627,15 +1618,11 @@ static int zd1201_set_hostauth(struct net_device *dev,
     struct iw_request_info *info, struct iw_param *rrq, char *extra)
 {
        struct zd1201 *zd = (struct zd1201 *)dev->priv;
-       int err;
 
        if (!zd->ap)
                return -EOPNOTSUPP;
 
-       err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
-       if (err)
-               return err;
-       return 0;
+       return zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
 }
 
 static int zd1201_get_hostauth(struct net_device *dev,
@@ -1744,7 +1731,7 @@ static int zd1201_probe(struct usb_interface *interface,
 {
        struct zd1201 *zd;
        struct usb_device *usb;
-       int i, err;
+       int err;
        short porttype;
        char buf[IW_ESSID_MAX_SIZE+2];
 
@@ -1773,9 +1760,7 @@ static int zd1201_probe(struct usb_interface *interface,
        if (!zd->rx_urb || !zd->tx_urb)
                goto err_zd;
 
-       for(i = 0; i<100; i++)
-               udelay(1000);
-
+       mdelay(100);
        err = zd1201_drvr_start(zd);
        if (err)
                goto err_zd;
@@ -1833,7 +1818,7 @@ static int zd1201_probe(struct usb_interface *interface,
                goto err_net;
        dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n",
            zd->dev->name);
-       
+
        usb_set_intfdata(interface, zd);
        return 0;
 
index f63c387976cf378a6f8ce78491a3d8de0f9a1c7c..6c8452ede0e113c4c50c6a29620ba7adbb9391db 100644 (file)
@@ -48,7 +48,7 @@ config PARPORT_PC
 
 config PARPORT_SERIAL
        tristate "Multi-IO cards (parallel and serial)"
-       depends on SERIAL_8250 && PARPORT_PC && PCI
+       depends on SERIAL_8250_PCI && PARPORT_PC && PCI
        help
          This adds support for multi-IO PCI cards that have parallel and
          serial ports.  You should say Y or M here.  If you say M, the module
index 1456759936c59410f0af1aaab1d91d81c4e5f34f..10e1a905c1444a8463b998e80e3930ff97034192 100644 (file)
@@ -285,9 +285,9 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
  * Default resume method for devices that have no driver provided resume,
  * or not even a driver at all.
  */
-static void pci_default_resume(struct pci_dev *pci_dev)
+static int pci_default_resume(struct pci_dev *pci_dev)
 {
-       int retval;
+       int retval = 0;
 
        /* restore the PCI config space */
        pci_restore_state(pci_dev);
@@ -297,18 +297,21 @@ static void pci_default_resume(struct pci_dev *pci_dev)
        /* if the device was busmaster before the suspend, make it busmaster again */
        if (pci_dev->is_busmaster)
                pci_set_master(pci_dev);
+
+       return retval;
 }
 
 static int pci_device_resume(struct device * dev)
 {
+       int error;
        struct pci_dev * pci_dev = to_pci_dev(dev);
        struct pci_driver * drv = pci_dev->driver;
 
        if (drv && drv->resume)
-               drv->resume(pci_dev);
+               error = drv->resume(pci_dev);
        else
-               pci_default_resume(pci_dev);
-       return 0;
+               error = pci_default_resume(pci_dev);
+       return error;
 }
 
 static void pci_device_shutdown(struct device *dev)
index 2329f941a0dcd11fa1f18c13f5129347c91581f7..fde41cc147344d3faf1bca11078dc951062e01be 100644 (file)
@@ -164,7 +164,6 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
        return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap);
 }
 
-#if 0
 /**
  * pci_find_ext_capability - Find an extended capability
  * @dev: PCI device to query
@@ -212,7 +211,7 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
 
        return 0;
 }
-#endif  /*  0  */
+EXPORT_SYMBOL_GPL(pci_find_ext_capability);
 
 /**
  * pci_find_parent_resource - return resource region of parent bus of given region
@@ -461,9 +460,23 @@ int
 pci_restore_state(struct pci_dev *dev)
 {
        int i;
+       int val;
 
-       for (i = 0; i < 16; i++)
-               pci_write_config_dword(dev,i * 4, dev->saved_config_space[i]);
+       /*
+        * The Base Address register should be programmed before the command
+        * register(s)
+        */
+       for (i = 15; i >= 0; i--) {
+               pci_read_config_dword(dev, i * 4, &val);
+               if (val != dev->saved_config_space[i]) {
+                       printk(KERN_DEBUG "PM: Writing back config space on "
+                               "device %s at offset %x (was %x, writing %x)\n",
+                               pci_name(dev), i,
+                               val, (int)dev->saved_config_space[i]);
+                       pci_write_config_dword(dev,i * 4,
+                               dev->saved_config_space[i]);
+               }
+       }
        pci_restore_msi_state(dev);
        pci_restore_msix_state(dev);
        return 0;
index 48d3b3d30c2169231d6749f7478bab8a0d3b50b9..74b3124e8247e444fd2911eecfe0de1ca5597063 100644 (file)
@@ -1143,6 +1143,12 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
 {
        struct pcmcia_socket *s = pcmcia_get_socket(skt);
 
+       if (!s) {
+               printk(KERN_ERR "PCMCIA obtaining reference to socket %p " \
+                       "failed, event 0x%x lost!\n", skt, event);
+               return -ENODEV;
+       }
+
        ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
               event, priority, skt);
 
index f6e7ee04f3dc634002383f84438db3ad937b91c5..8c0d1a6739adb23012a1c92bf9a102898b9a94cf 100644 (file)
@@ -48,33 +48,33 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
        struct platform_device *pdev = to_platform_device(dev);
        struct m48t86_ops *ops = pdev->dev.platform_data;
 
-       reg = ops->readb(M48T86_REG_B);
+       reg = ops->readbyte(M48T86_REG_B);
 
        if (reg & M48T86_REG_B_DM) {
                /* data (binary) mode */
-               tm->tm_sec      = ops->readb(M48T86_REG_SEC);
-               tm->tm_min      = ops->readb(M48T86_REG_MIN);
-               tm->tm_hour     = ops->readb(M48T86_REG_HOUR) & 0x3F;
-               tm->tm_mday     = ops->readb(M48T86_REG_DOM);
+               tm->tm_sec      = ops->readbyte(M48T86_REG_SEC);
+               tm->tm_min      = ops->readbyte(M48T86_REG_MIN);
+               tm->tm_hour     = ops->readbyte(M48T86_REG_HOUR) & 0x3F;
+               tm->tm_mday     = ops->readbyte(M48T86_REG_DOM);
                /* tm_mon is 0-11 */
-               tm->tm_mon      = ops->readb(M48T86_REG_MONTH) - 1;
-               tm->tm_year     = ops->readb(M48T86_REG_YEAR) + 100;
-               tm->tm_wday     = ops->readb(M48T86_REG_DOW);
+               tm->tm_mon      = ops->readbyte(M48T86_REG_MONTH) - 1;
+               tm->tm_year     = ops->readbyte(M48T86_REG_YEAR) + 100;
+               tm->tm_wday     = ops->readbyte(M48T86_REG_DOW);
        } else {
                /* bcd mode */
-               tm->tm_sec      = BCD2BIN(ops->readb(M48T86_REG_SEC));
-               tm->tm_min      = BCD2BIN(ops->readb(M48T86_REG_MIN));
-               tm->tm_hour     = BCD2BIN(ops->readb(M48T86_REG_HOUR) & 0x3F);
-               tm->tm_mday     = BCD2BIN(ops->readb(M48T86_REG_DOM));
+               tm->tm_sec      = BCD2BIN(ops->readbyte(M48T86_REG_SEC));
+               tm->tm_min      = BCD2BIN(ops->readbyte(M48T86_REG_MIN));
+               tm->tm_hour     = BCD2BIN(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
+               tm->tm_mday     = BCD2BIN(ops->readbyte(M48T86_REG_DOM));
                /* tm_mon is 0-11 */
-               tm->tm_mon      = BCD2BIN(ops->readb(M48T86_REG_MONTH)) - 1;
-               tm->tm_year     = BCD2BIN(ops->readb(M48T86_REG_YEAR)) + 100;
-               tm->tm_wday     = BCD2BIN(ops->readb(M48T86_REG_DOW));
+               tm->tm_mon      = BCD2BIN(ops->readbyte(M48T86_REG_MONTH)) - 1;
+               tm->tm_year     = BCD2BIN(ops->readbyte(M48T86_REG_YEAR)) + 100;
+               tm->tm_wday     = BCD2BIN(ops->readbyte(M48T86_REG_DOW));
        }
 
        /* correct the hour if the clock is in 12h mode */
        if (!(reg & M48T86_REG_B_H24))
-               if (ops->readb(M48T86_REG_HOUR) & 0x80)
+               if (ops->readbyte(M48T86_REG_HOUR) & 0x80)
                        tm->tm_hour += 12;
 
        return 0;
@@ -86,35 +86,35 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
        struct platform_device *pdev = to_platform_device(dev);
        struct m48t86_ops *ops = pdev->dev.platform_data;
 
-       reg = ops->readb(M48T86_REG_B);
+       reg = ops->readbyte(M48T86_REG_B);
 
        /* update flag and 24h mode */
        reg |= M48T86_REG_B_SET | M48T86_REG_B_H24;
-       ops->writeb(reg, M48T86_REG_B);
+       ops->writebyte(reg, M48T86_REG_B);
 
        if (reg & M48T86_REG_B_DM) {
                /* data (binary) mode */
-               ops->writeb(tm->tm_sec, M48T86_REG_SEC);
-               ops->writeb(tm->tm_min, M48T86_REG_MIN);
-               ops->writeb(tm->tm_hour, M48T86_REG_HOUR);
-               ops->writeb(tm->tm_mday, M48T86_REG_DOM);
-               ops->writeb(tm->tm_mon + 1, M48T86_REG_MONTH);
-               ops->writeb(tm->tm_year % 100, M48T86_REG_YEAR);
-               ops->writeb(tm->tm_wday, M48T86_REG_DOW);
+               ops->writebyte(tm->tm_sec, M48T86_REG_SEC);
+               ops->writebyte(tm->tm_min, M48T86_REG_MIN);
+               ops->writebyte(tm->tm_hour, M48T86_REG_HOUR);
+               ops->writebyte(tm->tm_mday, M48T86_REG_DOM);
+               ops->writebyte(tm->tm_mon + 1, M48T86_REG_MONTH);
+               ops->writebyte(tm->tm_year % 100, M48T86_REG_YEAR);
+               ops->writebyte(tm->tm_wday, M48T86_REG_DOW);
        } else {
                /* bcd mode */
-               ops->writeb(BIN2BCD(tm->tm_sec), M48T86_REG_SEC);
-               ops->writeb(BIN2BCD(tm->tm_min), M48T86_REG_MIN);
-               ops->writeb(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR);
-               ops->writeb(BIN2BCD(tm->tm_mday), M48T86_REG_DOM);
-               ops->writeb(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH);
-               ops->writeb(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR);
-               ops->writeb(BIN2BCD(tm->tm_wday), M48T86_REG_DOW);
+               ops->writebyte(BIN2BCD(tm->tm_sec), M48T86_REG_SEC);
+               ops->writebyte(BIN2BCD(tm->tm_min), M48T86_REG_MIN);
+               ops->writebyte(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR);
+               ops->writebyte(BIN2BCD(tm->tm_mday), M48T86_REG_DOM);
+               ops->writebyte(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH);
+               ops->writebyte(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR);
+               ops->writebyte(BIN2BCD(tm->tm_wday), M48T86_REG_DOW);
        }
 
        /* update ended */
        reg &= ~M48T86_REG_B_SET;
-       ops->writeb(reg, M48T86_REG_B);
+       ops->writebyte(reg, M48T86_REG_B);
 
        return 0;
 }
@@ -125,12 +125,12 @@ static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
        struct platform_device *pdev = to_platform_device(dev);
        struct m48t86_ops *ops = pdev->dev.platform_data;
 
-       reg = ops->readb(M48T86_REG_B);
+       reg = ops->readbyte(M48T86_REG_B);
 
        seq_printf(seq, "mode\t\t: %s\n",
                 (reg & M48T86_REG_B_DM) ? "binary" : "bcd");
 
-       reg = ops->readb(M48T86_REG_D);
+       reg = ops->readbyte(M48T86_REG_D);
 
        seq_printf(seq, "battery\t\t: %s\n",
                 (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
@@ -157,7 +157,7 @@ static int __devinit m48t86_rtc_probe(struct platform_device *dev)
        platform_set_drvdata(dev, rtc);
 
        /* read battery status */
-       reg = ops->readb(M48T86_REG_D);
+       reg = ops->readbyte(M48T86_REG_D);
        dev_info(&dev->dev, "battery %s\n",
                (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
 
index 74a257b23383abb94c8d1e011e896e97a50c1265..e210f89a24499c65f9bedea44df54d3e299c96d4 100644 (file)
@@ -45,11 +45,11 @@ struct pgid {
        union {
                __u8 fc;        /* SPID function code */
                struct path_state ps;   /* SNID path state */
-       } inf;
+       } __attribute__ ((packed)) inf;
        union {
                __u32 cpu_addr  : 16;   /* CPU address */
                struct extended_cssid ext_cssid;
-       } pgid_high;
+       } __attribute__ ((packed)) pgid_high;
        __u32 cpu_id    : 24;   /* CPU identification */
        __u32 cpu_model : 16;   /* CPU model */
        __u32 tod_high;         /* high word TOD clock */
index 180b3bf8b90ded2eeef4f004fb8d5e4926299076..49ec562d7f60b7d9d5d3c7658851394c11020d8d 100644 (file)
@@ -749,7 +749,7 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event)
                        /* Unit check but no sense data. Need basic sense. */
                        if (ccw_device_do_sense(cdev, irb) != 0)
                                goto call_handler_unsol;
-                       memcpy(irb, &cdev->private->irb, sizeof(struct irb));
+                       memcpy(&cdev->private->irb, irb, sizeof(struct irb));
                        cdev->private->state = DEV_STATE_W4SENSE;
                        cdev->private->intparm = 0;
                        return;
index 5e6b1f535f625b700496fdc909328a25b39dd6e1..0ca1d126ccb665007bdd2aae98ab61743800cef9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/s390/crypto/z90crypt.h
  *
- *  z90crypt 1.3.3
+ *  z90crypt 1.3.3 (kernel-private header)
  *
  *  Copyright (C)  2001, 2005 IBM Corporation
  *  Author(s): Robert Burroughs (burrough@us.ibm.com)
 #ifndef _Z90CRYPT_H_
 #define _Z90CRYPT_H_
 
-#include <linux/ioctl.h>
-
-#define z90crypt_VERSION 1
-#define z90crypt_RELEASE 3     // 2 = PCIXCC, 3 = rewrite for coding standards
-#define z90crypt_VARIANT 3     // 3 = CEX2A support
-
-/**
- * struct ica_rsa_modexpo
- *
- * Requirements:
- * - outputdatalength is at least as large as inputdatalength.
- * - All key parts are right justified in their fields, padded on
- *   the left with zeroes.
- * - length(b_key) = inputdatalength
- * - length(n_modulus) = inputdatalength
- */
-struct ica_rsa_modexpo {
-       char __user *   inputdata;
-       unsigned int    inputdatalength;
-       char __user *   outputdata;
-       unsigned int    outputdatalength;
-       char __user *   b_key;
-       char __user *   n_modulus;
-};
-
-/**
- * struct ica_rsa_modexpo_crt
- *
- * Requirements:
- * - inputdatalength is even.
- * - outputdatalength is at least as large as inputdatalength.
- * - All key parts are right justified in their fields, padded on
- *   the left with zeroes.
- * - length(bp_key)    = inputdatalength/2 + 8
- * - length(bq_key)    = inputdatalength/2
- * - length(np_key)    = inputdatalength/2 + 8
- * - length(nq_key)    = inputdatalength/2
- * - length(u_mult_inv) = inputdatalength/2 + 8
- */
-struct ica_rsa_modexpo_crt {
-       char __user *   inputdata;
-       unsigned int    inputdatalength;
-       char __user *   outputdata;
-       unsigned int    outputdatalength;
-       char __user *   bp_key;
-       char __user *   bq_key;
-       char __user *   np_prime;
-       char __user *   nq_prime;
-       char __user *   u_mult_inv;
-};
-
-#define Z90_IOCTL_MAGIC 'z'  // NOTE:  Need to allocate from linux folks
-
-/**
- * Interface notes:
- *
- * The ioctl()s which are implemented (along with relevant details)
- * are:
- *
- *   ICARSAMODEXPO
- *     Perform an RSA operation using a Modulus-Exponent pair
- *     This takes an ica_rsa_modexpo struct as its arg.
- *
- *     NOTE: please refer to the comments preceding this structure
- *           for the implementation details for the contents of the
- *           block
- *
- *   ICARSACRT
- *     Perform an RSA operation using a Chinese-Remainder Theorem key
- *     This takes an ica_rsa_modexpo_crt struct as its arg.
- *
- *     NOTE: please refer to the comments preceding this structure
- *           for the implementation details for the contents of the
- *           block
- *
- *   Z90STAT_TOTALCOUNT
- *     Return an integer count of all device types together.
- *
- *   Z90STAT_PCICACOUNT
- *     Return an integer count of all PCICAs.
- *
- *   Z90STAT_PCICCCOUNT
- *     Return an integer count of all PCICCs.
- *
- *   Z90STAT_PCIXCCMCL2COUNT
- *     Return an integer count of all MCL2 PCIXCCs.
- *
- *   Z90STAT_PCIXCCMCL3COUNT
- *     Return an integer count of all MCL3 PCIXCCs.
- *
- *   Z90STAT_CEX2CCOUNT
- *     Return an integer count of all CEX2Cs.
- *
- *   Z90STAT_CEX2ACOUNT
- *     Return an integer count of all CEX2As.
- *
- *   Z90STAT_REQUESTQ_COUNT
- *     Return an integer count of the number of entries waiting to be
- *     sent to a device.
- *
- *   Z90STAT_PENDINGQ_COUNT
- *     Return an integer count of the number of entries sent to a
- *     device awaiting the reply.
- *
- *   Z90STAT_TOTALOPEN_COUNT
- *     Return an integer count of the number of open file handles.
- *
- *   Z90STAT_DOMAIN_INDEX
- *     Return the integer value of the Cryptographic Domain.
- *
- *   Z90STAT_STATUS_MASK
- *     Return an 64 element array of unsigned chars for the status of
- *     all devices.
- *       0x01: PCICA
- *       0x02: PCICC
- *       0x03: PCIXCC_MCL2
- *       0x04: PCIXCC_MCL3
- *       0x05: CEX2C
- *       0x06: CEX2A
- *       0x0d: device is disabled via the proc filesystem
- *
- *   Z90STAT_QDEPTH_MASK
- *     Return an 64 element array of unsigned chars for the queue
- *     depth of all devices.
- *
- *   Z90STAT_PERDEV_REQCNT
- *     Return an 64 element array of unsigned integers for the number
- *     of successfully completed requests per device since the device
- *     was detected and made available.
- *
- *   ICAZ90STATUS (deprecated)
- *     Return some device driver status in a ica_z90_status struct
- *     This takes an ica_z90_status struct as its arg.
- *
- *     NOTE: this ioctl() is deprecated, and has been replaced with
- *           single ioctl()s for each type of status being requested
- *
- *   Z90STAT_PCIXCCCOUNT (deprecated)
- *     Return an integer count of all PCIXCCs (MCL2 + MCL3).
- *     This is DEPRECATED now that MCL3 PCIXCCs are treated differently from
- *     MCL2 PCIXCCs.
- *
- *   Z90QUIESCE (not recommended)
- *     Quiesce the driver.  This is intended to stop all new
- *     requests from being processed.  Its use is NOT recommended,
- *     except in circumstances where there is no other way to stop
- *     callers from accessing the driver.  Its original use was to
- *     allow the driver to be "drained" of work in preparation for
- *     a system shutdown.
- *
- *     NOTE: once issued, this ban on new work cannot be undone
- *           except by unloading and reloading the driver.
- */
-
-/**
- * Supported ioctl calls
- */
-#define ICARSAMODEXPO  _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0)
-#define ICARSACRT      _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0)
-
-/* DEPRECATED status calls (bound for removal at some point) */
-#define ICAZ90STATUS   _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status)
-#define Z90STAT_PCIXCCCOUNT    _IOR(Z90_IOCTL_MAGIC, 0x43, int)
-
-/* unrelated to ICA callers */
-#define Z90QUIESCE     _IO(Z90_IOCTL_MAGIC, 0x11)
-
-/* New status calls */
-#define Z90STAT_TOTALCOUNT     _IOR(Z90_IOCTL_MAGIC, 0x40, int)
-#define Z90STAT_PCICACOUNT     _IOR(Z90_IOCTL_MAGIC, 0x41, int)
-#define Z90STAT_PCICCCOUNT     _IOR(Z90_IOCTL_MAGIC, 0x42, int)
-#define Z90STAT_PCIXCCMCL2COUNT        _IOR(Z90_IOCTL_MAGIC, 0x4b, int)
-#define Z90STAT_PCIXCCMCL3COUNT        _IOR(Z90_IOCTL_MAGIC, 0x4c, int)
-#define Z90STAT_CEX2CCOUNT     _IOR(Z90_IOCTL_MAGIC, 0x4d, int)
-#define Z90STAT_CEX2ACOUNT     _IOR(Z90_IOCTL_MAGIC, 0x4e, int)
-#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int)
-#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int)
-#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
-#define Z90STAT_DOMAIN_INDEX   _IOR(Z90_IOCTL_MAGIC, 0x47, int)
-#define Z90STAT_STATUS_MASK    _IOR(Z90_IOCTL_MAGIC, 0x48, char[64])
-#define Z90STAT_QDEPTH_MASK    _IOR(Z90_IOCTL_MAGIC, 0x49, char[64])
-#define Z90STAT_PERDEV_REQCNT  _IOR(Z90_IOCTL_MAGIC, 0x4a, int[64])
+#include <asm/z90crypt.h>
 
 /**
  * local errno definitions
index 90d4d0ef3dd4d54f5b6563e24c68118c654aa74f..6775a837d6461b1be0e2e537e660b3e9f833b3b9 100644 (file)
@@ -2,7 +2,7 @@
 # S/390 network devices
 #
 
-ctc-objs := ctcmain.o ctctty.o ctcdbug.o
+ctc-objs := ctcmain.o ctcdbug.o
 
 obj-$(CONFIG_IUCV) += iucv.o
 obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
@@ -10,6 +10,7 @@ obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
 obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
 obj-$(CONFIG_LCS) += lcs.o cu3088.o
 obj-$(CONFIG_CLAW) += claw.o cu3088.o
+obj-$(CONFIG_MPC) += ctcmpc.o fsm.o cu3088.o
 qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o 
 qeth-$(CONFIG_PROC_FS) += qeth_proc.o
 obj-$(CONFIG_QETH) += qeth.o
index af9f212314b3a3c00cf5e298daba5f95d9b1acce..20c8eb16f4646ace31a883144947c14179353eb3 100644 (file)
@@ -6,7 +6,7 @@
  * Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
  *            Arnaldo Carvalho de Melo <acme@conectiva.com.br>
              Peter Tiedemann (ptiedem@de.ibm.com)
- * Driver Model stuff by : Cornelia Huck <huckc@de.ibm.com>
+ * Driver Model stuff by : Cornelia Huck <cornelia.huck@de.ibm.com>
  *
  * Documentation used:
  *  - Principles of Operation (IBM doc#: SA22-7201-06)
@@ -65,7 +65,6 @@
 
 #include <asm/idals.h>
 
-#include "ctctty.h"
 #include "fsm.h"
 #include "cu3088.h"
 
@@ -479,10 +478,7 @@ ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
                skb->dev = pskb->dev;
                skb->protocol = pskb->protocol;
                pskb->ip_summed = CHECKSUM_UNNECESSARY;
-               if (ch->protocol == CTC_PROTO_LINUX_TTY)
-                       ctc_tty_netif_rx(skb);
-               else
-                       netif_rx_ni(skb);
+               netif_rx_ni(skb);
                /**
                 * Successful rx; reset logflags
                 */
@@ -557,8 +553,7 @@ ccw_unit_check(struct channel *ch, unsigned char sense)
        DBF_TEXT(trace, 5, __FUNCTION__);
        if (sense & SNS0_INTERVENTION_REQ) {
                if (sense & 0x01) {
-                       if (ch->protocol != CTC_PROTO_LINUX_TTY)
-                               ctc_pr_debug("%s: Interface disc. or Sel. reset "
+                       ctc_pr_debug("%s: Interface disc. or Sel. reset "
                                        "(remote)\n", ch->id);
                        fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch);
                } else {
@@ -1486,13 +1481,13 @@ ch_action_iofatal(fsm_instance * fi, int event, void *arg)
        }
 }
 
-static void 
+static void
 ch_action_reinit(fsm_instance *fi, int event, void *arg)
 {
        struct channel *ch = (struct channel *)arg;
        struct net_device *dev = ch->netdev;
        struct ctc_priv *privptr = dev->priv;
+
        DBF_TEXT(trace, 4, __FUNCTION__);
        ch_action_iofatal(fi, event, arg);
        fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
@@ -1624,7 +1619,7 @@ less_than(char *id1, char *id2)
        }
        dev1 = simple_strtoul(id1, &id1, 16);
        dev2 = simple_strtoul(id2, &id2, 16);
-       
+
        return (dev1 < dev2);
 }
 
@@ -1895,7 +1890,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                            irb->scsw.dstat);
                return;
        }
-       
+
        priv = ((struct ccwgroup_device *)cdev->dev.driver_data)
                ->dev.driver_data;
 
@@ -1909,7 +1904,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                           "device %s\n", cdev->dev.bus_id);
                return;
        }
-       
+
        dev = (struct net_device *) (ch->netdev);
        if (dev == NULL) {
                ctc_pr_crit("ctc: ctc_irq_handler dev=NULL bus_id=%s, ch=0x%p\n",
@@ -2008,12 +2003,12 @@ dev_action_stop(fsm_instance * fi, int event, void *arg)
                fsm_event(ch->fsm, CH_EVENT_STOP, ch);
        }
 }
-static void 
+static void
 dev_action_restart(fsm_instance *fi, int event, void *arg)
 {
        struct net_device *dev = (struct net_device *)arg;
        struct ctc_priv *privptr = dev->priv;
-       
+
        DBF_TEXT(trace, 3, __FUNCTION__);
        ctc_pr_debug("%s: Restarting\n", dev->name);
        dev_action_stop(fi, event, arg);
@@ -2034,7 +2029,6 @@ static void
 dev_action_chup(fsm_instance * fi, int event, void *arg)
 {
        struct net_device *dev = (struct net_device *) arg;
-       struct ctc_priv *privptr = dev->priv;
 
        DBF_TEXT(trace, 3, __FUNCTION__);
        switch (fsm_getstate(fi)) {
@@ -2049,8 +2043,6 @@ dev_action_chup(fsm_instance * fi, int event, void *arg)
                                fsm_newstate(fi, DEV_STATE_RUNNING);
                                ctc_pr_info("%s: connected with remote side\n",
                                            dev->name);
-                               if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                                       ctc_tty_setcarrier(dev, 1);
                                ctc_clear_busy(dev);
                        }
                        break;
@@ -2059,8 +2051,6 @@ dev_action_chup(fsm_instance * fi, int event, void *arg)
                                fsm_newstate(fi, DEV_STATE_RUNNING);
                                ctc_pr_info("%s: connected with remote side\n",
                                            dev->name);
-                               if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                                       ctc_tty_setcarrier(dev, 1);
                                ctc_clear_busy(dev);
                        }
                        break;
@@ -2086,14 +2076,10 @@ dev_action_chup(fsm_instance * fi, int event, void *arg)
 static void
 dev_action_chdown(fsm_instance * fi, int event, void *arg)
 {
-       struct net_device *dev = (struct net_device *) arg;
-       struct ctc_priv *privptr = dev->priv;
 
        DBF_TEXT(trace, 3, __FUNCTION__);
        switch (fsm_getstate(fi)) {
                case DEV_STATE_RUNNING:
-                       if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                               ctc_tty_setcarrier(dev, 0);
                        if (event == DEV_EVENT_TXDOWN)
                                fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
                        else
@@ -2193,7 +2179,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
 
        DBF_TEXT(trace, 5, __FUNCTION__);
        /* we need to acquire the lock for testing the state
-        * otherwise we can have an IRQ changing the state to 
+        * otherwise we can have an IRQ changing the state to
         * TXIDLE after the test but before acquiring the lock.
         */
        spin_lock_irqsave(&ch->collect_lock, saveflags);
@@ -2393,12 +2379,10 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev)
 
        /**
         * If channels are not running, try to restart them
-        * and throw away packet. 
+        * and throw away packet.
         */
        if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
                fsm_event(privptr->fsm, DEV_EVENT_START, dev);
-               if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                       return -EBUSY;
                dev_kfree_skb(skb);
                privptr->stats.tx_dropped++;
                privptr->stats.tx_errors++;
@@ -2608,20 +2592,13 @@ ctc_netdev_unregister(struct net_device * dev)
        if (!dev)
                return;
        privptr = (struct ctc_priv *) dev->priv;
-       if (privptr->protocol != CTC_PROTO_LINUX_TTY)
-               unregister_netdev(dev);
-       else
-               ctc_tty_unregister_netdev(dev);
+       unregister_netdev(dev);
 }
 
 static int
 ctc_netdev_register(struct net_device * dev)
 {
-       struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
-       if (privptr->protocol != CTC_PROTO_LINUX_TTY)
-               return register_netdev(dev);
-       else
-               return ctc_tty_register_netdev(dev);
+       return register_netdev(dev);
 }
 
 static void
@@ -2667,7 +2644,9 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b
        if (!priv)
                return -ENODEV;
        sscanf(buf, "%u", &value);
-       if ((value < 0) || (value > CTC_PROTO_MAX))
+       if (!((value == CTC_PROTO_S390)  ||
+             (value == CTC_PROTO_LINUX) ||
+             (value == CTC_PROTO_OS390)))
                return -EINVAL;
        priv->protocol = value;
 
@@ -2738,7 +2717,7 @@ ctc_remove_files(struct device *dev)
 /**
  * Add ctc specific attributes.
  * Add ctc private data.
- * 
+ *
  * @param cgdev pointer to ccwgroup_device just added
  *
  * @returns 0 on success, !0 on failure.
@@ -2869,7 +2848,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
        DBF_TEXT(setup, 3, buffer);
 
        type = get_channel_type(&cgdev->cdev[0]->id);
-       
+
        snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
        snprintf(write_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
 
@@ -2897,17 +2876,14 @@ ctc_new_device(struct ccwgroup_device *cgdev)
                goto out;
        }
 
-       if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-               strlcpy(dev->name, "ctctty%d", IFNAMSIZ);
-       else
-               strlcpy(dev->name, "ctc%d", IFNAMSIZ);
+       strlcpy(dev->name, "ctc%d", IFNAMSIZ);
 
        for (direction = READ; direction <= WRITE; direction++) {
                privptr->channel[direction] =
                    channel_get(type, direction == READ ? read_id : write_id,
                                direction);
                if (privptr->channel[direction] == NULL) {
-                       if (direction == WRITE) 
+                       if (direction == WRITE)
                                channel_free(privptr->channel[READ]);
 
                        ctc_free_netdevice(dev, 1);
@@ -2955,7 +2931,7 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
 {
        struct ctc_priv *priv;
        struct net_device *ndev;
-               
+
        DBF_TEXT(setup, 3, __FUNCTION__);
        pr_debug("%s() called\n", __FUNCTION__);
 
@@ -3046,7 +3022,6 @@ ctc_exit(void)
 {
        DBF_TEXT(setup, 3, __FUNCTION__);
        unregister_cu3088_discipline(&ctc_group_driver);
-       ctc_tty_cleanup();
        ctc_unregister_dbf_views();
        ctc_pr_info("CTC driver unloaded\n");
 }
@@ -3073,10 +3048,8 @@ ctc_init(void)
                ctc_pr_crit("ctc_init failed with ctc_register_dbf_views rc = %d\n", ret);
                return ret;
        }
-       ctc_tty_init();
        ret = register_cu3088_discipline(&ctc_group_driver);
        if (ret) {
-               ctc_tty_cleanup();
                ctc_unregister_dbf_views();
        }
        return ret;
index d2e835c0c1344296de249deeb11e804c691534c1..7f305d119f3d4b0a085dd9b08faf3593df6ffa09 100644 (file)
@@ -35,7 +35,9 @@
 #include <asm/ccwdev.h>
 #include <asm/ccwgroup.h>
 
-#include "ctctty.h"
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
 #include "fsm.h"
 #include "cu3088.h"
 
@@ -50,9 +52,7 @@
 
 #define CTC_PROTO_S390          0
 #define CTC_PROTO_LINUX         1
-#define CTC_PROTO_LINUX_TTY     2
 #define CTC_PROTO_OS390         3
-#define CTC_PROTO_MAX           3
 
 #define CTC_BUFSIZE_LIMIT       65535
 #define CTC_BUFSIZE_DEFAULT     32768
@@ -257,15 +257,13 @@ static __inline__ void
 ctc_clear_busy(struct net_device * dev)
 {
        clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
-       if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
-               netif_wake_queue(dev);
+       netif_wake_queue(dev);
 }
 
 static __inline__ int
 ctc_test_and_set_busy(struct net_device * dev)
 {
-       if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
-               netif_stop_queue(dev);
+       netif_stop_queue(dev);
        return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
 }
 
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
deleted file mode 100644 (file)
index 5cdcdbf..0000000
+++ /dev/null
@@ -1,1259 +0,0 @@
-/*
- * CTC / ESCON network driver, tty interface.
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-#include <linux/devfs_fs_kernel.h>
-#include "ctctty.h"
-#include "ctcdbug.h"
-
-#define CTC_TTY_MAJOR       43
-#define CTC_TTY_MAX_DEVICES 64
-
-#define CTC_ASYNC_MAGIC          0x49344C01 /* for paranoia-checking        */
-#define CTC_ASYNC_INITIALIZED    0x80000000 /* port was initialized         */
-#define CTC_ASYNC_NORMAL_ACTIVE  0x20000000 /* Normal device active         */
-#define CTC_ASYNC_CLOSING        0x08000000 /* Serial port is closing       */
-#define CTC_ASYNC_CTS_FLOW       0x04000000 /* Do CTS flow control          */
-#define CTC_ASYNC_CHECK_CD       0x02000000 /* i.e., CLOCAL                 */
-#define CTC_ASYNC_HUP_NOTIFY         0x0001 /* Notify tty on hangups/closes */
-#define CTC_ASYNC_NETDEV_OPEN        0x0002 /* Underlying netdev is open    */
-#define CTC_ASYNC_TX_LINESTAT        0x0004 /* Must send line status        */
-#define CTC_ASYNC_SPLIT_TERMIOS      0x0008 /* Sep. termios for dialin/out  */
-#define CTC_TTY_XMIT_SIZE              1024 /* Default bufsize for write    */
-#define CTC_SERIAL_XMIT_MAX            4000 /* Maximum bufsize for write    */
-
-/* Private data (similar to async_struct in <linux/serial.h>) */
-typedef struct {
-  int                  magic;
-  int                  flags;           /* defined in tty.h               */
-  int                  mcr;             /* Modem control register         */
-  int                   msr;             /* Modem status register          */
-  int                   lsr;             /* Line status register           */
-  int                  line;
-  int                  count;           /* # of fd on device              */
-  int                  blocked_open;    /* # of blocked opens             */
-  struct net_device     *netdev;
-  struct sk_buff_head   tx_queue;        /* transmit queue                 */
-  struct sk_buff_head   rx_queue;        /* receive queue                  */
-  struct tty_struct    *tty;            /* Pointer to corresponding tty   */
-  wait_queue_head_t    open_wait;
-  wait_queue_head_t    close_wait;
-  struct semaphore      write_sem;
-  struct tasklet_struct tasklet;
-  struct timer_list     stoptimer;
-} ctc_tty_info;
-
-/* Description of one CTC-tty */
-typedef struct {
-  struct tty_driver  *ctc_tty_device;             /* tty-device             */
-  ctc_tty_info       info[CTC_TTY_MAX_DEVICES];           /* Private data           */
-} ctc_tty_driver;
-
-static ctc_tty_driver *driver;
-
-/* Leave this unchanged unless you know what you do! */
-#define MODEM_PARANOIA_CHECK
-#define MODEM_DO_RESTART
-
-#define CTC_TTY_NAME "ctctty"
-
-static __u32 ctc_tty_magic = CTC_ASYNC_MAGIC;
-static int ctc_tty_shuttingdown = 0;
-
-static spinlock_t ctc_tty_lock;
-
-/* ctc_tty_try_read() is called from within ctc_tty_rcv_skb()
- * to stuff incoming data directly into a tty's flip-buffer. If the
- * flip buffer is full, the packet gets queued up.
- *
- * Return:
- *  1 = Success
- *  0 = Failure, data has to be buffered and later processed by
- *      ctc_tty_readmodem().
- */
-static int
-ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb)
-{
-       int len;
-       struct tty_struct *tty;
-
-       DBF_TEXT(trace, 5, __FUNCTION__);
-       if ((tty = info->tty)) {
-               if (info->mcr & UART_MCR_RTS) {
-                       len = skb->len;
-                       tty_insert_flip_string(tty, skb->data, len);
-                       tty_flip_buffer_push(tty);
-                       kfree_skb(skb);
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/* ctc_tty_readmodem() is called periodically from within timer-interrupt.
- * It tries getting received data from the receive queue an stuff it into
- * the tty's flip-buffer.
- */
-static int
-ctc_tty_readmodem(ctc_tty_info *info)
-{
-       int ret = 1;
-       struct tty_struct *tty;
-
-       DBF_TEXT(trace, 5, __FUNCTION__);
-       if ((tty = info->tty)) {
-               if (info->mcr & UART_MCR_RTS) {
-                       struct sk_buff *skb;
-                       
-                       if ((skb = skb_dequeue(&info->rx_queue))) {
-                               int len = skb->len;
-                               tty_insert_flip_string(tty, skb->data, len);
-                               skb_pull(skb, len);
-                               tty_flip_buffer_push(tty);
-                               if (skb->len > 0)
-                                       skb_queue_head(&info->rx_queue, skb);
-                               else {
-                                       kfree_skb(skb);
-                                       ret = !skb_queue_empty(&info->rx_queue);
-                               }
-                       }
-               }
-       }
-       return ret;
-}
-
-void
-ctc_tty_setcarrier(struct net_device *netdev, int on)
-{
-       int i;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if ((!driver) || ctc_tty_shuttingdown)
-               return;
-       for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
-               if (driver->info[i].netdev == netdev) {
-                       ctc_tty_info *info = &driver->info[i];
-                       if (on)
-                               info->msr |= UART_MSR_DCD;
-                       else
-                               info->msr &= ~UART_MSR_DCD;
-                       if ((info->flags & CTC_ASYNC_CHECK_CD) && (!on))
-                               tty_hangup(info->tty);
-               }
-}
-
-void
-ctc_tty_netif_rx(struct sk_buff *skb)
-{
-       int i;
-       ctc_tty_info *info = NULL;
-
-       DBF_TEXT(trace, 5, __FUNCTION__);
-       if (!skb)
-               return;
-       if ((!skb->dev) || (!driver) || ctc_tty_shuttingdown) {
-               dev_kfree_skb(skb);
-               return;
-       }
-       for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
-               if (driver->info[i].netdev == skb->dev) {
-                       info = &driver->info[i];
-                       break;
-               }
-       if (!info) {
-               dev_kfree_skb(skb);
-               return;
-       }
-       if (skb->len < 6) {
-               dev_kfree_skb(skb);
-               return;
-       }
-       if (memcmp(skb->data, &ctc_tty_magic, sizeof(__u32))) {
-               dev_kfree_skb(skb);
-               return;
-       }
-       skb_pull(skb, sizeof(__u32));
-
-       i = *((int *)skb->data);
-       skb_pull(skb, sizeof(info->mcr));
-       if (i & UART_MCR_RTS) {
-               info->msr |= UART_MSR_CTS;
-               if (info->flags & CTC_ASYNC_CTS_FLOW)
-                       info->tty->hw_stopped = 0;
-       } else {
-               info->msr &= ~UART_MSR_CTS;
-               if (info->flags & CTC_ASYNC_CTS_FLOW)
-                       info->tty->hw_stopped = 1;
-       }
-       if (i & UART_MCR_DTR)
-               info->msr |= UART_MSR_DSR;
-       else
-               info->msr &= ~UART_MSR_DSR;
-       if (skb->len <= 0) {
-               kfree_skb(skb);
-               return;
-       }
-       /* Try to deliver directly via tty-flip-buf if queue is empty */
-       if (skb_queue_empty(&info->rx_queue))
-               if (ctc_tty_try_read(info, skb))
-                       return;
-       /* Direct deliver failed or queue wasn't empty.
-        * Queue up for later dequeueing via timer-irq.
-        */
-       skb_queue_tail(&info->rx_queue, skb);
-       /* Schedule dequeuing */
-       tasklet_schedule(&info->tasklet);
-}
-
-static int
-ctc_tty_tint(ctc_tty_info * info)
-{
-       struct sk_buff *skb = skb_dequeue(&info->tx_queue);
-       int stopped = (info->tty->hw_stopped || info->tty->stopped);
-       int wake = 1;
-       int rc;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (!info->netdev) {
-               if (skb)
-                       kfree_skb(skb);
-               return 0;
-       }
-       if (info->flags & CTC_ASYNC_TX_LINESTAT) {
-               int skb_res = info->netdev->hard_header_len +
-                       sizeof(info->mcr) + sizeof(__u32);
-               /* If we must update line status,
-                * create an empty dummy skb and insert it.
-                */
-               if (skb)
-                       skb_queue_head(&info->tx_queue, skb);
-
-               skb = dev_alloc_skb(skb_res);
-               if (!skb) {
-                       printk(KERN_WARNING
-                              "ctc_tty: Out of memory in %s%d tint\n",
-                              CTC_TTY_NAME, info->line);
-                       return 1;
-               }
-               skb_reserve(skb, skb_res);
-               stopped = 0;
-               wake = 0;
-       }
-       if (!skb)
-               return 0;
-       if (stopped) {
-               skb_queue_head(&info->tx_queue, skb);
-               return 1;
-       }
-#if 0
-       if (skb->len > 0)
-               printk(KERN_DEBUG "tint: %d %02x\n", skb->len, *(skb->data));
-       else
-               printk(KERN_DEBUG "tint: %d STAT\n", skb->len);
-#endif
-       memcpy(skb_push(skb, sizeof(info->mcr)), &info->mcr, sizeof(info->mcr));
-       memcpy(skb_push(skb, sizeof(__u32)), &ctc_tty_magic, sizeof(__u32));
-       rc = info->netdev->hard_start_xmit(skb, info->netdev);
-       if (rc) {
-               skb_pull(skb, sizeof(info->mcr) + sizeof(__u32));
-               if (skb->len > 0)
-                       skb_queue_head(&info->tx_queue, skb);
-               else
-                       kfree_skb(skb);
-       } else {
-               struct tty_struct *tty = info->tty;
-
-               info->flags &= ~CTC_ASYNC_TX_LINESTAT;
-               if (tty) {
-                       tty_wakeup(tty);
-               }
-       }
-       return (skb_queue_empty(&info->tx_queue) ? 0 : 1);
-}
-
-/************************************************************
- *
- * Modem-functions
- *
- * mostly "stolen" from original Linux-serial.c and friends.
- *
- ************************************************************/
-
-static inline int
-ctc_tty_paranoia_check(ctc_tty_info * info, char *name, const char *routine)
-{
-#ifdef MODEM_PARANOIA_CHECK
-       if (!info) {
-               printk(KERN_WARNING "ctc_tty: null info_struct for %s in %s\n",
-                      name, routine);
-               return 1;
-       }
-       if (info->magic != CTC_ASYNC_MAGIC) {
-               printk(KERN_WARNING "ctc_tty: bad magic for info struct %s in %s\n",
-                      name, routine);
-               return 1;
-       }
-#endif
-       return 0;
-}
-
-static void
-ctc_tty_inject(ctc_tty_info *info, char c)
-{
-       int skb_res;
-       struct sk_buff *skb;
-       
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_shuttingdown)
-               return;
-       skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
-               sizeof(__u32) + 1;
-       skb = dev_alloc_skb(skb_res);
-       if (!skb) {
-               printk(KERN_WARNING
-                      "ctc_tty: Out of memory in %s%d tx_inject\n",
-                      CTC_TTY_NAME, info->line);
-               return;
-       }
-       skb_reserve(skb, skb_res);
-       *(skb_put(skb, 1)) = c;
-       skb_queue_head(&info->tx_queue, skb);
-       tasklet_schedule(&info->tasklet);
-}
-
-static void
-ctc_tty_transmit_status(ctc_tty_info *info)
-{
-       DBF_TEXT(trace, 5, __FUNCTION__);
-       if (ctc_tty_shuttingdown)
-               return;
-       info->flags |= CTC_ASYNC_TX_LINESTAT;
-       tasklet_schedule(&info->tasklet);
-}
-
-static void
-ctc_tty_change_speed(ctc_tty_info * info)
-{
-       unsigned int cflag;
-       unsigned int quot;
-       int i;
-
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       if (!info->tty || !info->tty->termios)
-               return;
-       cflag = info->tty->termios->c_cflag;
-
-       quot = i = cflag & CBAUD;
-       if (i & CBAUDEX) {
-               i &= ~CBAUDEX;
-               if (i < 1 || i > 2)
-                       info->tty->termios->c_cflag &= ~CBAUDEX;
-               else
-                       i += 15;
-       }
-       if (quot) {
-               info->mcr |= UART_MCR_DTR;
-               info->mcr |= UART_MCR_RTS;
-               ctc_tty_transmit_status(info);
-       } else {
-               info->mcr &= ~UART_MCR_DTR;
-               info->mcr &= ~UART_MCR_RTS;
-               ctc_tty_transmit_status(info);
-               return;
-       }
-
-       /* CTS flow control flag and modem status interrupts */
-       if (cflag & CRTSCTS) {
-               info->flags |= CTC_ASYNC_CTS_FLOW;
-       } else
-               info->flags &= ~CTC_ASYNC_CTS_FLOW;
-       if (cflag & CLOCAL)
-               info->flags &= ~CTC_ASYNC_CHECK_CD;
-       else {
-               info->flags |= CTC_ASYNC_CHECK_CD;
-       }
-}
-
-static int
-ctc_tty_startup(ctc_tty_info * info)
-{
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       if (info->flags & CTC_ASYNC_INITIALIZED)
-               return 0;
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "starting up %s%d ...\n", CTC_TTY_NAME, info->line);
-#endif
-       /*
-        * Now, initialize the UART
-        */
-       info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
-       if (info->tty)
-               clear_bit(TTY_IO_ERROR, &info->tty->flags);
-       /*
-        * and set the speed of the serial port
-        */
-       ctc_tty_change_speed(info);
-
-       info->flags |= CTC_ASYNC_INITIALIZED;
-       if (!(info->flags & CTC_ASYNC_NETDEV_OPEN))
-               info->netdev->open(info->netdev);
-       info->flags |= CTC_ASYNC_NETDEV_OPEN;
-       return 0;
-}
-
-static void
-ctc_tty_stopdev(unsigned long data)
-{
-       ctc_tty_info *info = (ctc_tty_info *)data;
-
-       if ((!info) || (!info->netdev) ||
-           (info->flags & CTC_ASYNC_INITIALIZED))
-               return;
-       info->netdev->stop(info->netdev);
-       info->flags &= ~CTC_ASYNC_NETDEV_OPEN;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void
-ctc_tty_shutdown(ctc_tty_info * info)
-{
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       if (!(info->flags & CTC_ASYNC_INITIALIZED))
-               return;
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "Shutting down %s%d ....\n", CTC_TTY_NAME, info->line);
-#endif
-       info->msr &= ~UART_MSR_RI;
-       if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
-               info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
-       if (info->tty)
-               set_bit(TTY_IO_ERROR, &info->tty->flags);
-       mod_timer(&info->stoptimer, jiffies + (10 * HZ));
-       skb_queue_purge(&info->tx_queue);
-       skb_queue_purge(&info->rx_queue);
-       info->flags &= ~CTC_ASYNC_INITIALIZED;
-}
-
-/* ctc_tty_write() is the main send-routine. It is called from the upper
- * levels within the kernel to perform sending data. Depending on the
- * online-flag it either directs output to the at-command-interpreter or
- * to the lower level. Additional tasks done here:
- *  - If online, check for escape-sequence (+++)
- *  - If sending audio-data, call ctc_tty_DLEdown() to parse DLE-codes.
- *  - If receiving audio-data, call ctc_tty_end_vrx() to abort if needed.
- *  - If dialing, abort dial.
- */
-static int
-ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count)
-{
-       int c;
-       int total = 0;
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       DBF_TEXT(trace, 5, __FUNCTION__);
-       if (ctc_tty_shuttingdown)
-               goto ex;
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write"))
-               goto ex;
-       if (!tty)
-               goto ex;
-       if (!info->netdev) {
-               total = -ENODEV;
-               goto ex;
-       }
-       while (1) {
-               struct sk_buff *skb;
-               int skb_res;
-
-               c = (count < CTC_TTY_XMIT_SIZE) ? count : CTC_TTY_XMIT_SIZE;
-               if (c <= 0)
-                       break;
-               
-               skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
-                       + sizeof(__u32);
-               skb = dev_alloc_skb(skb_res + c);
-               if (!skb) {
-                       printk(KERN_WARNING
-                              "ctc_tty: Out of memory in %s%d write\n",
-                              CTC_TTY_NAME, info->line);
-                       break;
-               }
-               skb_reserve(skb, skb_res);
-               memcpy(skb_put(skb, c), buf, c);
-               skb_queue_tail(&info->tx_queue, skb);
-               buf += c;
-               total += c;
-               count -= c;
-       }
-       if (!skb_queue_empty(&info->tx_queue)) {
-               info->lsr &= ~UART_LSR_TEMT;
-               tasklet_schedule(&info->tasklet);
-       }
-ex:
-       DBF_TEXT(trace, 6, __FUNCTION__);
-       return total;
-}
-
-static int
-ctc_tty_write_room(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write_room"))
-               return 0;
-       return CTC_TTY_XMIT_SIZE;
-}
-
-static int
-ctc_tty_chars_in_buffer(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_chars_in_buffer"))
-               return 0;
-       return 0;
-}
-
-static void
-ctc_tty_flush_buffer(struct tty_struct *tty)
-{
-       ctc_tty_info *info;
-       unsigned long flags;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (!tty)
-               goto ex;
-       spin_lock_irqsave(&ctc_tty_lock, flags);
-       info = (ctc_tty_info *) tty->driver_data;
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_buffer")) {
-               spin_unlock_irqrestore(&ctc_tty_lock, flags);
-               goto ex;
-       }
-       skb_queue_purge(&info->tx_queue);
-       info->lsr |= UART_LSR_TEMT;
-       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-       wake_up_interruptible(&tty->write_wait);
-       tty_wakeup(tty);
-ex:
-       DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__);
-       return;
-}
-
-static void
-ctc_tty_flush_chars(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_shuttingdown)
-               return;
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_chars"))
-               return;
-       if (tty->stopped || tty->hw_stopped || skb_queue_empty(&info->tx_queue))
-               return;
-       tasklet_schedule(&info->tasklet);
-}
-
-/*
- * ------------------------------------------------------------
- * ctc_tty_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void
-ctc_tty_throttle(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_throttle"))
-               return;
-       info->mcr &= ~UART_MCR_RTS;
-       if (I_IXOFF(tty))
-               ctc_tty_inject(info, STOP_CHAR(tty));
-       ctc_tty_transmit_status(info);
-}
-
-static void
-ctc_tty_unthrottle(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_unthrottle"))
-               return;
-       info->mcr |= UART_MCR_RTS;
-       if (I_IXOFF(tty))
-               ctc_tty_inject(info, START_CHAR(tty));
-       ctc_tty_transmit_status(info);
-}
-
-/*
- * ------------------------------------------------------------
- * ctc_tty_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-/*
- * ctc_tty_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 RS485 driver to be written in user space.
- */
-static int
-ctc_tty_get_lsr_info(ctc_tty_info * info, uint __user *value)
-{
-       u_char status;
-       uint result;
-       ulong flags;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       spin_lock_irqsave(&ctc_tty_lock, flags);
-       status = info->lsr;
-       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-       result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-       put_user(result, value);
-       return 0;
-}
-
-
-static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-       u_char control,
-        status;
-       uint result;
-       ulong flags;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
-               return -ENODEV;
-       if (tty->flags & (1 << TTY_IO_ERROR))
-               return -EIO;
-
-       control = info->mcr;
-       spin_lock_irqsave(&ctc_tty_lock, flags);
-       status = info->msr;
-       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-       result = ((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);
-       return result;
-}
-
-static int
-ctc_tty_tiocmset(struct tty_struct *tty, struct file *file,
-                unsigned int set, unsigned int clear)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
-               return -ENODEV;
-       if (tty->flags & (1 << TTY_IO_ERROR))
-               return -EIO;
-
-       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;
-
-       if ((set | clear) & (TIOCM_RTS|TIOCM_DTR))
-               ctc_tty_transmit_status(info);
-       return 0;
-}
-
-static int
-ctc_tty_ioctl(struct tty_struct *tty, struct file *file,
-              uint cmd, ulong arg)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-       int error;
-       int retval;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
-               return -ENODEV;
-       if (tty->flags & (1 << TTY_IO_ERROR))
-               return -EIO;
-       switch (cmd) {
-               case TCSBRK:   /* SVID version: non-zero arg --> no break */
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "%s%d ioctl TCSBRK\n", CTC_TTY_NAME, info->line);
-#endif
-                       retval = tty_check_change(tty);
-                       if (retval)
-                               return retval;
-                       tty_wait_until_sent(tty, 0);
-                       return 0;
-               case TCSBRKP:  /* support for POSIX tcsendbreak() */
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "%s%d ioctl TCSBRKP\n", CTC_TTY_NAME, info->line);
-#endif
-                       retval = tty_check_change(tty);
-                       if (retval)
-                               return retval;
-                       tty_wait_until_sent(tty, 0);
-                       return 0;
-               case TIOCGSOFTCAR:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "%s%d ioctl TIOCGSOFTCAR\n", CTC_TTY_NAME,
-                              info->line);
-#endif
-                       error = put_user(C_CLOCAL(tty) ? 1 : 0, (ulong __user *) arg);
-                       return error;
-               case TIOCSSOFTCAR:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "%s%d ioctl TIOCSSOFTCAR\n", CTC_TTY_NAME,
-                              info->line);
-#endif
-                       error = get_user(arg, (ulong __user *) arg);
-                       if (error)
-                               return error;
-                       tty->termios->c_cflag =
-                           ((tty->termios->c_cflag & ~CLOCAL) |
-                            (arg ? CLOCAL : 0));
-                       return 0;
-               case TIOCSERGETLSR:     /* Get line status register */
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME,
-                              info->line);
-#endif
-                       if (access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(uint)))
-                               return ctc_tty_get_lsr_info(info, (uint __user *) arg);
-                       else
-                               return -EFAULT;
-               default:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on %s%d\n", cmd,
-                              CTC_TTY_NAME, info->line);
-#endif
-                       return -ENOIOCTLCMD;
-       }
-       return 0;
-}
-
-static void
-ctc_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-       unsigned int cflag = tty->termios->c_cflag;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       ctc_tty_change_speed(info);
-
-       /* Handle transition to B0 */
-       if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) {
-               info->mcr &= ~(UART_MCR_DTR|UART_MCR_RTS);
-               ctc_tty_transmit_status(info);
-       }
-
-       /* Handle transition from B0 to other */
-       if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
-               info->mcr |= UART_MCR_DTR;
-               if (!(tty->termios->c_cflag & CRTSCTS) ||
-                    !test_bit(TTY_THROTTLED, &tty->flags)) {
-                        info->mcr |= UART_MCR_RTS;
-                }
-               ctc_tty_transmit_status(info);
-       }
-
-       /* Handle turning off CRTSCTS */
-       if ((old_termios->c_cflag & CRTSCTS) &&
-            !(tty->termios->c_cflag & CRTSCTS))
-                tty->hw_stopped = 0;
-}
-
-/*
- * ------------------------------------------------------------
- * ctc_tty_open() and friends
- * ------------------------------------------------------------
- */
-static int
-ctc_tty_block_til_ready(struct tty_struct *tty, struct file *filp, ctc_tty_info *info)
-{
-       DECLARE_WAITQUEUE(wait, NULL);
-       int do_clocal = 0;
-       unsigned long flags;
-       int retval;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       /*
-        * 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 & CTC_ASYNC_CLOSING)) {
-               if (info->flags & CTC_ASYNC_CLOSING)
-                       wait_event(info->close_wait, 
-                                  !(info->flags & CTC_ASYNC_CLOSING));
-#ifdef MODEM_DO_RESTART
-               if (info->flags & CTC_ASYNC_HUP_NOTIFY)
-                       return -EAGAIN;
-               else
-                       return -ERESTARTSYS;
-#else
-               return -EAGAIN;
-#endif
-       }
-       /*
-        * 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 |= CTC_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, info->count is dropped by one, so that
-        * ctc_tty_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 CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "ctc_tty_block_til_ready before block: %s%d, count = %d\n",
-              CTC_TTY_NAME, info->line, info->count);
-#endif
-       spin_lock_irqsave(&ctc_tty_lock, flags);
-       if (!(tty_hung_up_p(filp)))
-               info->count--;
-       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-       info->blocked_open++;
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (tty_hung_up_p(filp) ||
-                   !(info->flags & CTC_ASYNC_INITIALIZED)) {
-#ifdef MODEM_DO_RESTART
-                       if (info->flags & CTC_ASYNC_HUP_NOTIFY)
-                               retval = -EAGAIN;
-                       else
-                               retval = -ERESTARTSYS;
-#else
-                       retval = -EAGAIN;
-#endif
-                       break;
-               }
-               if (!(info->flags & CTC_ASYNC_CLOSING) &&
-                   (do_clocal || (info->msr & UART_MSR_DCD))) {
-                       break;
-               }
-               if (signal_pending(current)) {
-                       retval = -ERESTARTSYS;
-                       break;
-               }
-#ifdef CTC_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "ctc_tty_block_til_ready blocking: %s%d, count = %d\n",
-                      CTC_TTY_NAME, info->line, info->count);
-#endif
-               schedule();
-       }
-       current->state = TASK_RUNNING;
-       remove_wait_queue(&info->open_wait, &wait);
-       if (!tty_hung_up_p(filp))
-               info->count++;
-       info->blocked_open--;
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "ctc_tty_block_til_ready after blocking: %s%d, count = %d\n",
-              CTC_TTY_NAME, info->line, info->count);
-#endif
-       if (retval)
-               return retval;
-       info->flags |= CTC_ASYNC_NORMAL_ACTIVE;
-       return 0;
-}
-
-/*
- * 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
-ctc_tty_open(struct tty_struct *tty, struct file *filp)
-{
-       ctc_tty_info *info;
-       unsigned long saveflags;
-       int retval,
-        line;
-
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       line = tty->index;
-       if (line < 0 || line > CTC_TTY_MAX_DEVICES)
-               return -ENODEV;
-       info = &driver->info[line];
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_open"))
-               return -ENODEV;
-       if (!info->netdev)
-               return -ENODEV;
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "ctc_tty_open %s, count = %d\n", tty->name,
-              info->count);
-#endif
-       spin_lock_irqsave(&ctc_tty_lock, saveflags);
-       info->count++;
-       tty->driver_data = info;
-       info->tty = tty;
-       spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-       /*
-        * Start up serial port
-        */
-       retval = ctc_tty_startup(info);
-       if (retval) {
-#ifdef CTC_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "ctc_tty_open return after startup\n");
-#endif
-               return retval;
-       }
-       retval = ctc_tty_block_til_ready(tty, filp, info);
-       if (retval) {
-#ifdef CTC_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "ctc_tty_open return after ctc_tty_block_til_ready \n");
-#endif
-               return retval;
-       }
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "ctc_tty_open %s successful...\n", tty->name);
-#endif
-       return 0;
-}
-
-static void
-ctc_tty_close(struct tty_struct *tty, struct file *filp)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-       ulong flags;
-       ulong timeout;
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       if (!info || ctc_tty_paranoia_check(info, tty->name, "ctc_tty_close"))
-               return;
-       spin_lock_irqsave(&ctc_tty_lock, flags);
-       if (tty_hung_up_p(filp)) {
-               spin_unlock_irqrestore(&ctc_tty_lock, flags);
-#ifdef CTC_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "ctc_tty_close return after tty_hung_up_p\n");
-#endif
-               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 "ctc_tty_close: bad port count; tty->count is 1, "
-                      "info->count is %d\n", info->count);
-               info->count = 1;
-       }
-       if (--info->count < 0) {
-               printk(KERN_ERR "ctc_tty_close: bad port count for %s%d: %d\n",
-                      CTC_TTY_NAME, info->line, info->count);
-               info->count = 0;
-       }
-       if (info->count) {
-               local_irq_restore(flags);
-#ifdef CTC_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "ctc_tty_close after info->count != 0\n");
-#endif
-               return;
-       }
-       info->flags |= CTC_ASYNC_CLOSING;
-       tty->closing = 1;
-       /*
-        * 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.
-        */
-       if (info->flags & CTC_ASYNC_INITIALIZED) {
-               tty_wait_until_sent(tty, 30*HZ); /* 30 seconds timeout */
-               /*
-                * 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 (!(info->lsr & UART_LSR_TEMT)) {
-                       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-                       msleep(500);
-                       spin_lock_irqsave(&ctc_tty_lock, flags);
-                       if (time_after(jiffies,timeout))
-                               break;
-               }
-       }
-       ctc_tty_shutdown(info);
-       if (tty->driver->flush_buffer) {
-               skb_queue_purge(&info->tx_queue);
-               info->lsr |= UART_LSR_TEMT;
-       }
-       tty_ldisc_flush(tty);
-       info->tty = 0;
-       tty->closing = 0;
-       if (info->blocked_open) {
-               msleep_interruptible(500);
-               wake_up_interruptible(&info->open_wait);
-       }
-       info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING);
-       wake_up_interruptible(&info->close_wait);
-       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "ctc_tty_close normal exit\n");
-#endif
-}
-
-/*
- * ctc_tty_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void
-ctc_tty_hangup(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *)tty->driver_data;
-       unsigned long saveflags;
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_hangup"))
-               return;
-       ctc_tty_shutdown(info);
-       info->count = 0;
-       info->flags &= ~CTC_ASYNC_NORMAL_ACTIVE;
-       spin_lock_irqsave(&ctc_tty_lock, saveflags);
-       info->tty = 0;
-       spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-       wake_up_interruptible(&info->open_wait);
-}
-
-
-/*
- * For all online tty's, try sending data to
- * the lower levels.
- */
-static void
-ctc_tty_task(unsigned long arg)
-{
-       ctc_tty_info *info = (void *)arg;
-       unsigned long saveflags;
-       int again;
-
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       spin_lock_irqsave(&ctc_tty_lock, saveflags);
-       if ((!ctc_tty_shuttingdown) && info) {
-               again = ctc_tty_tint(info);
-               if (!again)
-                       info->lsr |= UART_LSR_TEMT;
-               again |= ctc_tty_readmodem(info);
-               if (again) {
-                       tasklet_schedule(&info->tasklet);
-               }
-       }
-       spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-}
-
-static struct tty_operations ctc_ops = {
-       .open = ctc_tty_open,
-       .close = ctc_tty_close,
-       .write = ctc_tty_write,
-       .flush_chars = ctc_tty_flush_chars,
-       .write_room = ctc_tty_write_room,
-       .chars_in_buffer = ctc_tty_chars_in_buffer,
-       .flush_buffer = ctc_tty_flush_buffer,
-       .ioctl = ctc_tty_ioctl,
-       .throttle = ctc_tty_throttle,
-       .unthrottle = ctc_tty_unthrottle,
-       .set_termios = ctc_tty_set_termios,
-       .hangup = ctc_tty_hangup,
-       .tiocmget = ctc_tty_tiocmget,
-       .tiocmset = ctc_tty_tiocmset,
-};
-
-int
-ctc_tty_init(void)
-{
-       int i;
-       ctc_tty_info *info;
-       struct tty_driver *device;
-
-       DBF_TEXT(trace, 2, __FUNCTION__);
-       driver = kmalloc(sizeof(ctc_tty_driver), GFP_KERNEL);
-       if (driver == NULL) {
-               printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
-               return -ENOMEM;
-       }
-       memset(driver, 0, sizeof(ctc_tty_driver));
-       device = alloc_tty_driver(CTC_TTY_MAX_DEVICES);
-       if (!device) {
-               kfree(driver);
-               printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
-               return -ENOMEM;
-       }
-
-       device->devfs_name = "ctc/" CTC_TTY_NAME;
-       device->name = CTC_TTY_NAME;
-       device->major = CTC_TTY_MAJOR;
-       device->minor_start = 0;
-       device->type = TTY_DRIVER_TYPE_SERIAL;
-       device->subtype = SERIAL_TYPE_NORMAL;
-       device->init_termios = tty_std_termios;
-       device->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-       device->flags = TTY_DRIVER_REAL_RAW;
-       device->driver_name = "ctc_tty",
-       tty_set_operations(device, &ctc_ops);
-       if (tty_register_driver(device)) {
-               printk(KERN_WARNING "ctc_tty: Couldn't register serial-device\n");
-               put_tty_driver(device);
-               kfree(driver);
-               return -1;
-       }
-       driver->ctc_tty_device = device;
-       for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) {
-               info = &driver->info[i];
-               init_MUTEX(&info->write_sem);
-               tasklet_init(&info->tasklet, ctc_tty_task,
-                               (unsigned long) info);
-               info->magic = CTC_ASYNC_MAGIC;
-               info->line = i;
-               info->tty = 0;
-               info->count = 0;
-               info->blocked_open = 0;
-               init_waitqueue_head(&info->open_wait);
-               init_waitqueue_head(&info->close_wait);
-               skb_queue_head_init(&info->tx_queue);
-               skb_queue_head_init(&info->rx_queue);
-               init_timer(&info->stoptimer);
-               info->stoptimer.function = ctc_tty_stopdev;
-               info->stoptimer.data = (unsigned long)info;
-               info->mcr = UART_MCR_RTS;
-       }
-       return 0;
-}
-
-int
-ctc_tty_register_netdev(struct net_device *dev) {
-       int ttynum;
-       char *err;
-       char *p;
-
-       DBF_TEXT(trace, 2, __FUNCTION__);
-       if ((!dev) || (!dev->name)) {
-               printk(KERN_WARNING
-                      "ctc_tty_register_netdev called "
-                      "with NULL dev or NULL dev-name\n");
-               return -1;
-       }
-
-       /*
-        *      If the name is a format string the caller wants us to
-        *      do a name allocation : format string must end with %d
-        */
-       if (strchr(dev->name, '%'))
-       {
-               int err = dev_alloc_name(dev, dev->name);       // dev->name is changed by this
-               if (err < 0) {
-                       printk(KERN_DEBUG "dev_alloc returned error %d\n", err);
-                       return err;
-               }
-
-       }
-
-       for (p = dev->name; p && ((*p < '0') || (*p > '9')); p++);
-       ttynum = simple_strtoul(p, &err, 0);
-       if ((ttynum < 0) || (ttynum >= CTC_TTY_MAX_DEVICES) ||
-           (err && *err)) {
-               printk(KERN_WARNING
-                      "ctc_tty_register_netdev called "
-                      "with number in name '%s'\n", dev->name);
-               return -1;
-       }
-       if (driver->info[ttynum].netdev) {
-               printk(KERN_WARNING
-                      "ctc_tty_register_netdev called "
-                      "for already registered device '%s'\n",
-                      dev->name);
-               return -1;
-       }
-       driver->info[ttynum].netdev = dev;
-       return 0;
-}
-
-void
-ctc_tty_unregister_netdev(struct net_device *dev) {
-       int i;
-       unsigned long saveflags;
-       ctc_tty_info *info = NULL;
-
-       DBF_TEXT(trace, 2, __FUNCTION__);
-       spin_lock_irqsave(&ctc_tty_lock, saveflags);
-       for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
-               if (driver->info[i].netdev == dev) {
-                       info = &driver->info[i];
-                       break;
-               }
-       if (info) {
-               info->netdev = NULL;
-               skb_queue_purge(&info->tx_queue);
-               skb_queue_purge(&info->rx_queue);
-       }
-       spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-}
-
-void
-ctc_tty_cleanup(void) {
-       unsigned long saveflags;
-       
-       DBF_TEXT(trace, 2, __FUNCTION__);
-       spin_lock_irqsave(&ctc_tty_lock, saveflags);
-       ctc_tty_shuttingdown = 1;
-       spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-       tty_unregister_driver(driver->ctc_tty_device);
-       put_tty_driver(driver->ctc_tty_device);
-       kfree(driver);
-       driver = NULL;
-}
diff --git a/drivers/s390/net/ctctty.h b/drivers/s390/net/ctctty.h
deleted file mode 100644 (file)
index 7254dc0..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * CTC / ESCON network driver, tty interface.
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _CTCTTY_H_
-#define _CTCTTY_H_
-
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-extern int  ctc_tty_register_netdev(struct net_device *);
-extern void ctc_tty_unregister_netdev(struct net_device *);
-extern void ctc_tty_netif_rx(struct sk_buff *);
-extern int  ctc_tty_init(void);
-extern void ctc_tty_cleanup(void);
-extern void ctc_tty_setcarrier(struct net_device *, int);
-
-#endif
index b12533104c1ff5b38242791d22d0e94c0f0293de..e965f03a7291659a8384998e57eb30748a9b422a 100644 (file)
@@ -20,7 +20,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
-\f
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/err.h>
@@ -77,7 +77,7 @@ group_write(struct device_driver *drv, const char *buf, size_t count)
                int len;
 
                if (!(end = strchr(start, delim[i])))
-                       return count;
+                       return -EINVAL;
                len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start + 1);
                strlcpy (bus_ids[i], start, len);
                argv[i] = bus_ids[i];
@@ -94,7 +94,7 @@ static DRIVER_ATTR(group, 0200, NULL, group_write);
 
 /* Register-unregister for ctc&lcs */
 int
-register_cu3088_discipline(struct ccwgroup_driver *dcp) 
+register_cu3088_discipline(struct ccwgroup_driver *dcp)
 {
        int rc;
 
@@ -109,7 +109,7 @@ register_cu3088_discipline(struct ccwgroup_driver *dcp)
        rc = driver_create_file(&dcp->driver, &driver_attr_group);
        if (rc)
                ccwgroup_driver_unregister(dcp);
-               
+
        return rc;
 
 }
@@ -137,7 +137,7 @@ static int __init
 cu3088_init (void)
 {
        int rc;
-       
+
        cu3088_root_dev = s390_root_dev_register("cu3088");
        if (IS_ERR(cu3088_root_dev))
                return PTR_ERR(cu3088_root_dev);
index 6190be9dca991b7502aa9e60761b459014fa3ae2..e0c7deb9883189f012d0b27d67c83db08317b01e 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * IUCV network driver
  *
  * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -28,7 +28,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
-\f
+
 /* #define DEBUG */
 
 #include <linux/module.h>
@@ -81,7 +81,7 @@ iucv_bus_match (struct device *dev, struct device_driver *drv)
 struct bus_type iucv_bus = {
        .name = "iucv",
        .match = iucv_bus_match,
-};     
+};
 
 struct device *iucv_root;
 
@@ -297,7 +297,7 @@ MODULE_LICENSE("GPL");
 /*
  * Debugging stuff
  *******************************************************************************/
-\f
+
 
 #ifdef DEBUG
 static int debuglevel = 0;
@@ -344,7 +344,7 @@ do { \
 /*
  * Internal functions
  *******************************************************************************/
-\f
+
 /**
  * print start banner
  */
@@ -810,7 +810,7 @@ iucv_register_program (__u8 pgmname[16],
                        sizeof (new_handler->id.userid));
                EBC_TOUPPER (new_handler->id.userid,
                             sizeof (new_handler->id.userid));
-               
+
                if (pgmmask) {
                        memcpy (new_handler->id.mask, pgmmask,
                                sizeof (new_handler->id.mask));
@@ -1229,7 +1229,7 @@ iucv_purge (__u16 pathid, __u32 msgid, __u32 srccls, __u32 *audit)
                /* parm->ipaudit has only 3 bytes */
                *audit >>= 8;
        }
-       
+
        release_param(parm);
 
        iucv_debug(1, "b2f0_result = %ld", b2f0_result);
@@ -2330,14 +2330,14 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
                                        temp_buff1[j] &= (h->id.mask)[j];
                                        temp_buff2[j] &= (h->id.mask)[j];
                                }
-                               
+
                                iucv_dumpit("temp_buff1:",
                                            temp_buff1, sizeof(temp_buff1));
                                iucv_dumpit("temp_buff2",
                                            temp_buff2, sizeof(temp_buff2));
-                               
+
                                if (!memcmp (temp_buff1, temp_buff2, 24)) {
-                                       
+
                                        iucv_debug(2,
                                                   "found a matching handler");
                                        break;
@@ -2368,7 +2368,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
                        } else
                                iucv_sever(int_buf->ippathid, no_listener);
                        break;
-                       
+
                case 0x02:              /*connection complete */
                        if (messagesDisabled) {
                            iucv_setmask(~0);
@@ -2387,7 +2387,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
                        } else
                                iucv_sever(int_buf->ippathid, no_listener);
                        break;
-                       
+
                case 0x03:              /* connection severed */
                        if (messagesDisabled) {
                            iucv_setmask(~0);
@@ -2398,13 +2398,13 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
                                        interrupt->ConnectionSevered(
                                                (iucv_ConnectionSevered *)int_buf,
                                                h->pgm_data);
-                               
+
                                else
                                        iucv_sever (int_buf->ippathid, no_listener);
                        } else
                                iucv_sever(int_buf->ippathid, no_listener);
                        break;
-                       
+
                case 0x04:              /* connection quiesced */
                        if (messagesDisabled) {
                            iucv_setmask(~0);
@@ -2420,7 +2420,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
                                                   "ConnectionQuiesced not called");
                        }
                        break;
-                       
+
                case 0x05:              /* connection resumed */
                        if (messagesDisabled) {
                            iucv_setmask(~0);
@@ -2436,7 +2436,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
                                                   "ConnectionResumed not called");
                        }
                        break;
-                       
+
                case 0x06:              /* priority message complete */
                case 0x07:              /* nonpriority message complete */
                        if (h) {
@@ -2449,7 +2449,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
                                                   "MessageComplete not called");
                        }
                        break;
-                       
+
                case 0x08:              /* priority message pending  */
                case 0x09:              /* nonpriority message pending  */
                        if (h) {
@@ -2467,7 +2467,7 @@ iucv_do_int(iucv_GeneralInterrupt * int_buf)
                               __FUNCTION__);
                        break;
        }                       /* end switch */
-       
+
        iucv_debug(2, "exiting pathid %d, type %02X",
                 int_buf->ippathid, int_buf->iptype);
 
index 0c4644d3d2f35e76a3529284b9a9b0aeceaf7b06..5b6b1b7241c96452345694a7b76d98dd69150a8b 100644 (file)
@@ -4,7 +4,7 @@
  *
  *  S390 version
  *    Copyright (C) 2000 IBM Corporation
- *    Author(s):Alan Altmark (Alan_Altmark@us.ibm.com) 
+ *    Author(s):Alan Altmark (Alan_Altmark@us.ibm.com)
  *             Xenia Tkatschow (xenia@us.ibm.com)
  *
  *
  * CP Programming Services book, also available on the web
  * thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
  *
- *      Definition of Return Codes                                    
- *      -All positive return codes including zero are reflected back  
- *       from CP except for iucv_register_program. The definition of each 
- *       return code can be found in CP Programming Services book.    
- *       Also available on the web thru www.ibm.com/s390/vm/pubs, manual # SC24-5760          
- *      - Return Code of:         
- *             (-EINVAL) Invalid value       
- *             (-ENOMEM) storage allocation failed              
+ *      Definition of Return Codes
+ *      -All positive return codes including zero are reflected back
+ *       from CP except for iucv_register_program. The definition of each
+ *       return code can be found in CP Programming Services book.
+ *       Also available on the web thru www.ibm.com/s390/vm/pubs, manual # SC24-5760
+ *      - Return Code of:
+ *             (-EINVAL) Invalid value
+ *             (-ENOMEM) storage allocation failed
  *     pgmask defined in iucv_register_program will be set depending on input
- *     paramters. 
- *     
+ *     paramters.
+ *
  */
 
 #include <linux/types.h>
@@ -124,13 +124,13 @@ iucv_hex_dump(unsigned char *buf, size_t len)
 #define iucv_handle_t void *
 
 /* flags1:
- * All flags are defined in the field IPFLAGS1 of each function   
- * and can be found in CP Programming Services.                  
- * IPLOCAL  - Indicates the connect can only be satisfied on the 
- *            local system                                       
- * IPPRTY   - Indicates a priority message                       
- * IPQUSCE  - Indicates you do not want to receive messages on a 
- *            path until an iucv_resume is issued                
+ * All flags are defined in the field IPFLAGS1 of each function
+ * and can be found in CP Programming Services.
+ * IPLOCAL  - Indicates the connect can only be satisfied on the
+ *            local system
+ * IPPRTY   - Indicates a priority message
+ * IPQUSCE  - Indicates you do not want to receive messages on a
+ *            path until an iucv_resume is issued
  * IPRMDATA - Indicates that the message is in the parameter list
  */
 #define IPLOCAL        0x01
@@ -154,14 +154,14 @@ iucv_hex_dump(unsigned char *buf, size_t len)
 #define AllInterrupts                                    0xf8
 /*
  * Mapping of external interrupt buffers should be used with the corresponding
- * interrupt types.                  
- * Names: iucv_ConnectionPending    ->  connection pending 
+ * interrupt types.
+ * Names: iucv_ConnectionPending    ->  connection pending
  *        iucv_ConnectionComplete   ->  connection complete
- *        iucv_ConnectionSevered    ->  connection severed 
- *        iucv_ConnectionQuiesced   ->  connection quiesced 
- *        iucv_ConnectionResumed    ->  connection resumed 
- *        iucv_MessagePending       ->  message pending    
- *        iucv_MessageComplete      ->  message complete   
+ *        iucv_ConnectionSevered    ->  connection severed
+ *        iucv_ConnectionQuiesced   ->  connection quiesced
+ *        iucv_ConnectionResumed    ->  connection resumed
+ *        iucv_MessagePending       ->  message pending
+ *        iucv_MessageComplete      ->  message complete
  */
 typedef struct {
        u16 ippathid;
@@ -260,16 +260,16 @@ typedef struct {
        uchar res2[3];
 } iucv_MessageComplete;
 
-/* 
- * iucv_interrupt_ops_t: Is a vector of functions that handle 
- * IUCV interrupts.                                          
- * Parameter list:                                           
- *         eib - is a pointer to a 40-byte area described    
- *               with one of the structures above.           
- *         pgm_data - this data is strictly for the          
- *                    interrupt handler that is passed by    
- *                    the application. This may be an address 
- *                    or token.                              
+/*
+ * iucv_interrupt_ops_t: Is a vector of functions that handle
+ * IUCV interrupts.
+ * Parameter list:
+ *         eib - is a pointer to a 40-byte area described
+ *               with one of the structures above.
+ *         pgm_data - this data is strictly for the
+ *                    interrupt handler that is passed by
+ *                    the application. This may be an address
+ *                    or token.
 */
 typedef struct {
        void (*ConnectionPending) (iucv_ConnectionPending * eib,
@@ -287,8 +287,8 @@ typedef struct {
 } iucv_interrupt_ops_t;
 
 /*
- *iucv_array_t : Defines buffer array.                      
- * Inside the array may be 31- bit addresses and 31-bit lengths. 
+ *iucv_array_t : Defines buffer array.
+ * Inside the array may be 31- bit addresses and 31-bit lengths.
 */
 typedef struct {
        u32 address;
@@ -299,19 +299,19 @@ extern struct bus_type iucv_bus;
 extern struct device *iucv_root;
 
 /*   -prototypes-    */
-/*                                                                
- * Name: iucv_register_program                                    
- * Purpose: Registers an application with IUCV                    
- * Input: prmname - user identification                           
+/*
+ * Name: iucv_register_program
+ * Purpose: Registers an application with IUCV
+ * Input: prmname - user identification
  *        userid  - machine identification
  *        pgmmask - indicates which bits in the prmname and userid combined will be
  *                 used to determine who is given control
- *        ops     - address of vector of interrupt handlers       
- *        pgm_data- application data passed to interrupt handlers 
- * Output: NA                                                     
- * Return: address of handler                                     
+ *        ops     - address of vector of interrupt handlers
+ *        pgm_data- application data passed to interrupt handlers
+ * Output: NA
+ * Return: address of handler
  *         (0) - Error occurred, registration not completed.
- * NOTE: Exact cause of failure will be recorded in syslog.                        
+ * NOTE: Exact cause of failure will be recorded in syslog.
 */
 iucv_handle_t iucv_register_program (uchar pgmname[16],
                                     uchar userid[8],
@@ -319,13 +319,13 @@ iucv_handle_t iucv_register_program (uchar pgmname[16],
                                     iucv_interrupt_ops_t * ops,
                                     void *pgm_data);
 
-/*                                                
- * Name: iucv_unregister_program                  
- * Purpose: Unregister application with IUCV      
- * Input: address of handler                      
- * Output: NA                                     
- * Return: (0) - Normal return                    
- *         (-EINVAL) - Internal error, wild pointer     
+/*
+ * Name: iucv_unregister_program
+ * Purpose: Unregister application with IUCV
+ * Input: address of handler
+ * Output: NA
+ * Return: (0) - Normal return
+ *         (-EINVAL) - Internal error, wild pointer
 */
 int iucv_unregister_program (iucv_handle_t handle);
 
@@ -333,7 +333,7 @@ int iucv_unregister_program (iucv_handle_t handle);
  * Name: iucv_accept
  * Purpose: This function is issued after the user receives a Connection Pending external
  *          interrupt and now wishes to complete the IUCV communication path.
- * Input:  pathid - u16 , Path identification number   
+ * Input:  pathid - u16 , Path identification number
  *         msglim_reqstd - u16, The number of outstanding messages requested.
  *         user_data - uchar[16], Data specified by the iucv_connect function.
  *        flags1 - int, Contains options for this path.
@@ -358,34 +358,34 @@ int iucv_accept (u16 pathid,
                 void *pgm_data, int *flags1_out, u16 * msglim);
 
 /*
- * Name: iucv_connect                                         
+ * Name: iucv_connect
  * Purpose: This function establishes an IUCV path. Although the connect may complete
- *         successfully, you are not able to use the path until you receive an IUCV 
- *          Connection Complete external interrupt.            
- * Input: pathid - u16 *, Path identification number          
- *        msglim_reqstd - u16, Number of outstanding messages requested       
- *        user_data - uchar[16], 16-byte user data                    
+ *         successfully, you are not able to use the path until you receive an IUCV
+ *          Connection Complete external interrupt.
+ * Input: pathid - u16 *, Path identification number
+ *        msglim_reqstd - u16, Number of outstanding messages requested
+ *        user_data - uchar[16], 16-byte user data
  *       userid - uchar[8], User identification
- *        system_name - uchar[8], 8-byte identifying the system name 
+ *        system_name - uchar[8], 8-byte identifying the system name
  *       flags1 - int, Contains options for this path.
  *          -IPPRTY -   0x20, Specifies if you want to send priority message.
  *          -IPRMDATA - 0x80, Specifies whether your program can handle a message
  *              in  the parameter list.
- *          -IPQUSCE -  0x40, Specifies whether you want to quiesce the path being      
+ *          -IPQUSCE -  0x40, Specifies whether you want to quiesce the path being
  *             established.
- *          -IPLOCAL -  0X01, Allows an application to force the partner to be on 
+ *          -IPLOCAL -  0X01, Allows an application to force the partner to be on
  *             the local system. If local is specified then target class cannot be
- *             specified.                       
+ *             specified.
  *        flags1_out - int * Contains information about the path
  *           - IPPRTY - 0x20, Indicates you may send priority messages.
  *        msglim - * u16, Number of outstanding messages
- *        handle - iucv_handle_t, Address of handler                         
- *        pgm_data - void *, Application data passed to interrupt handlers              
+ *        handle - iucv_handle_t, Address of handler
+ *        pgm_data - void *, Application data passed to interrupt handlers
  * Output: return code from CP IUCV call
  *         rc - return code from iucv_declare_buffer
- *         -EINVAL - Invalid handle passed by application 
- *         -EINVAL - Pathid address is NULL 
- *         add_pathid_result - Return code from internal function add_pathid         
+ *         -EINVAL - Invalid handle passed by application
+ *         -EINVAL - Pathid address is NULL
+ *         add_pathid_result - Return code from internal function add_pathid
 */
 int
     iucv_connect (u16 * pathid,
@@ -397,16 +397,16 @@ int
                  int *flags1_out,
                  u16 * msglim, iucv_handle_t handle, void *pgm_data);
 
-/*                                                                     
- * Name: iucv_purge                                                    
- * Purpose: This function cancels a message that you have sent.        
- * Input: pathid - Path identification number.                          
+/*
+ * Name: iucv_purge
+ * Purpose: This function cancels a message that you have sent.
+ * Input: pathid - Path identification number.
  *        msgid - Specifies the message ID of the message to be purged.
- *        srccls - Specifies the source message class.                  
- * Output: audit - Contains information about asynchronous error       
- *                 that may have affected the normal completion        
- *                 of this message.                                    
- * Return: Return code from CP IUCV call.                           
+ *        srccls - Specifies the source message class.
+ * Output: audit - Contains information about asynchronous error
+ *                 that may have affected the normal completion
+ *                 of this message.
+ * Return: Return code from CP IUCV call.
 */
 int iucv_purge (u16 pathid, u32 msgid, u32 srccls, __u32 *audit);
 /*
@@ -426,38 +426,38 @@ ulong iucv_query_maxconn (void);
  */
 ulong iucv_query_bufsize (void);
 
-/*                                                                     
- * Name: iucv_quiesce                                                  
- * Purpose: This function temporarily suspends incoming messages on an 
- *          IUCV path. You can later reactivate the path by invoking   
- *          the iucv_resume function.                                  
- * Input: pathid - Path identification number                          
- *        user_data  - 16-bytes of user data                           
- * Output: NA                                                          
- * Return: Return code from CP IUCV call.                           
+/*
+ * Name: iucv_quiesce
+ * Purpose: This function temporarily suspends incoming messages on an
+ *          IUCV path. You can later reactivate the path by invoking
+ *          the iucv_resume function.
+ * Input: pathid - Path identification number
+ *        user_data  - 16-bytes of user data
+ * Output: NA
+ * Return: Return code from CP IUCV call.
 */
 int iucv_quiesce (u16 pathid, uchar user_data[16]);
 
-/*                                                                     
- * Name: iucv_receive                                                  
- * Purpose: This function receives messages that are being sent to you 
+/*
+ * Name: iucv_receive
+ * Purpose: This function receives messages that are being sent to you
  *          over established paths. Data will be returned in buffer for length of
  *          buflen.
- * Input: 
- *       pathid - Path identification number.                          
- *       buffer - Address of buffer to receive.                        
- *       buflen - Length of buffer to receive.                         
- *       msgid - Specifies the message ID.          
- *       trgcls - Specifies target class.                       
- * Output: 
+ * Input:
+ *       pathid - Path identification number.
+ *       buffer - Address of buffer to receive.
+ *       buflen - Length of buffer to receive.
+ *       msgid - Specifies the message ID.
+ *       trgcls - Specifies target class.
+ * Output:
  *      flags1_out: int *, Contains information about this path.
  *         IPNORPY - 0x10 Specifies this is a one-way message and no reply is
- *        expected.      
- *         IPPRTY  - 0x20 Specifies if you want to send priority message.       
+ *        expected.
+ *         IPPRTY  - 0x20 Specifies if you want to send priority message.
  *         IPRMDATA - 0x80 specifies the data is contained in the parameter list
  *       residual_buffer - address of buffer updated by the number
  *                         of bytes you have received.
- *       residual_length -      
+ *       residual_length -
  *              Contains one of the following values, if the receive buffer is:
  *               The same length as the message, this field is zero.
  *               Longer than the message, this field contains the number of
@@ -466,8 +466,8 @@ int iucv_quiesce (u16 pathid, uchar user_data[16]);
  *                count (that is, the number of bytes remaining in the
  *                message that does not fit into the buffer. In this
  *                case b2f0_result = 5.
- * Return: Return code from CP IUCV call.                           
- *         (-EINVAL) - buffer address is pointing to NULL                   
+ * Return: Return code from CP IUCV call.
+ *         (-EINVAL) - buffer address is pointing to NULL
 */
 int iucv_receive (u16 pathid,
                  u32 msgid,
@@ -477,16 +477,16 @@ int iucv_receive (u16 pathid,
                  int *flags1_out,
                  ulong * residual_buffer, ulong * residual_length);
 
- /*                                                                     
-  * Name: iucv_receive_array                                            
-  * Purpose: This function receives messages that are being sent to you 
+ /*
+  * Name: iucv_receive_array
+  * Purpose: This function receives messages that are being sent to you
   *          over established paths. Data will be returned in first buffer for
   *          length of first buffer.
-  * Input: pathid - Path identification number.                          
+  * Input: pathid - Path identification number.
   *        msgid - specifies the message ID.
   *        trgcls - Specifies target class.
-  *        buffer - Address of array of buffers.                         
-  *        buflen - Total length of buffers.                             
+  *        buffer - Address of array of buffers.
+  *        buflen - Total length of buffers.
   * Output:
   *        flags1_out: int *, Contains information about this path.
   *          IPNORPY - 0x10 Specifies this is a one-way message and no reply is
@@ -504,8 +504,8 @@ int iucv_receive (u16 pathid,
   *                count (that is, the number of bytes remaining in the
   *                message that does not fit into the buffer. In this
   *                case b2f0_result = 5.
-  * Return: Return code from CP IUCV call.                           
-  *         (-EINVAL) - Buffer address is NULL.       
+  * Return: Return code from CP IUCV call.
+  *         (-EINVAL) - Buffer address is NULL.
   */
 int iucv_receive_array (u16 pathid,
                        u32 msgid,
@@ -515,44 +515,44 @@ int iucv_receive_array (u16 pathid,
                        int *flags1_out,
                        ulong * residual_buffer, ulong * residual_length);
 
-/*                                                                       
- * Name: iucv_reject                                                     
- * Purpose: The reject function refuses a specified message. Between the 
- *          time you are notified of a message and the time that you     
- *          complete the message, the message may be rejected.           
- * Input: pathid - Path identification number.                            
- *        msgid - Specifies the message ID.                   
- *        trgcls - Specifies target class.                                
- * Output: NA                                                            
- * Return: Return code from CP IUCV call.                             
+/*
+ * Name: iucv_reject
+ * Purpose: The reject function refuses a specified message. Between the
+ *          time you are notified of a message and the time that you
+ *          complete the message, the message may be rejected.
+ * Input: pathid - Path identification number.
+ *        msgid - Specifies the message ID.
+ *        trgcls - Specifies target class.
+ * Output: NA
+ * Return: Return code from CP IUCV call.
 */
 int iucv_reject (u16 pathid, u32 msgid, u32 trgcls);
 
-/*                                                                     
- * Name: iucv_reply                                                    
- * Purpose: This function responds to the two-way messages that you    
- *          receive. You must identify completely the message to       
- *          which you wish to reply. ie, pathid, msgid, and trgcls.    
- * Input: pathid - Path identification number.                          
- *        msgid - Specifies the message ID.                
- *        trgcls - Specifies target class.                              
+/*
+ * Name: iucv_reply
+ * Purpose: This function responds to the two-way messages that you
+ *          receive. You must identify completely the message to
+ *          which you wish to reply. ie, pathid, msgid, and trgcls.
+ * Input: pathid - Path identification number.
+ *        msgid - Specifies the message ID.
+ *        trgcls - Specifies target class.
  *        flags1 - Option for path.
- *          IPPRTY- 0x20, Specifies if you want to send priority message.        
- *        buffer - Address of reply buffer.                             
- *        buflen - Length of reply buffer.                              
- * Output: residual_buffer - Address of buffer updated by the number 
- *                    of bytes you have moved.              
+ *          IPPRTY- 0x20, Specifies if you want to send priority message.
+ *        buffer - Address of reply buffer.
+ *        buflen - Length of reply buffer.
+ * Output: residual_buffer - Address of buffer updated by the number
+ *                    of bytes you have moved.
  *         residual_length - Contains one of the following values:
  *             If the answer buffer is the same length as the reply, this field
  *              contains zero.
  *             If the answer buffer is longer than the reply, this field contains
- *              the number of bytes remaining in the buffer.  
+ *              the number of bytes remaining in the buffer.
  *             If the answer buffer is shorter than the reply, this field contains
  *              a residual count (that is, the number of bytes remianing in the
  *              reply that does not fit into the buffer. In this
  *               case b2f0_result = 5.
- * Return: Return code from CP IUCV call.                           
- *         (-EINVAL) - Buffer address is NULL.                               
+ * Return: Return code from CP IUCV call.
+ *         (-EINVAL) - Buffer address is NULL.
 */
 int iucv_reply (u16 pathid,
                u32 msgid,
@@ -561,20 +561,20 @@ int iucv_reply (u16 pathid,
                void *buffer, ulong buflen, ulong * residual_buffer,
                ulong * residual_length);
 
-/*                                                                       
- * Name: iucv_reply_array                                                
- * Purpose: This function responds to the two-way messages that you      
- *          receive. You must identify completely the message to         
- *          which you wish to reply. ie, pathid, msgid, and trgcls.      
- *          The array identifies a list of addresses and lengths of      
- *          discontiguous buffers that contains the reply data.          
- * Input: pathid - Path identification number                            
- *        msgid - Specifies the message ID. 
- *        trgcls - Specifies target class.                                
+/*
+ * Name: iucv_reply_array
+ * Purpose: This function responds to the two-way messages that you
+ *          receive. You must identify completely the message to
+ *          which you wish to reply. ie, pathid, msgid, and trgcls.
+ *          The array identifies a list of addresses and lengths of
+ *          discontiguous buffers that contains the reply data.
+ * Input: pathid - Path identification number
+ *        msgid - Specifies the message ID.
+ *        trgcls - Specifies target class.
  *        flags1 - Option for path.
  *          IPPRTY- 0x20, Specifies if you want to send priority message.
- *        buffer - Address of array of reply buffers.                     
- *        buflen - Total length of reply buffers.                         
+ *        buffer - Address of array of reply buffers.
+ *        buflen - Total length of reply buffers.
  * Output: residual_buffer - Address of buffer which IUCV is currently working on.
  *         residual_length - Contains one of the following values:
  *              If the answer buffer is the same length as the reply, this field
@@ -585,8 +585,8 @@ int iucv_reply (u16 pathid,
  *               a residual count (that is, the number of bytes remianing in the
  *               reply that does not fit into the buffer. In this
  *               case b2f0_result = 5.
- * Return: Return code from CP IUCV call.                             
- *         (-EINVAL) - Buffer address is NULL.              
+ * Return: Return code from CP IUCV call.
+ *         (-EINVAL) - Buffer address is NULL.
 */
 int iucv_reply_array (u16 pathid,
                      u32 msgid,
@@ -596,77 +596,77 @@ int iucv_reply_array (u16 pathid,
                      ulong buflen, ulong * residual_address,
                      ulong * residual_length);
 
-/*                                                                  
- * Name: iucv_reply_prmmsg                                          
- * Purpose: This function responds to the two-way messages that you 
- *          receive. You must identify completely the message to    
- *          which you wish to reply. ie, pathid, msgid, and trgcls. 
- *          Prmmsg signifies the data is moved into the             
- *          parameter list.                                         
- * Input: pathid - Path identification number.                       
- *        msgid - Specifies the message ID.              
- *        trgcls - Specifies target class.                           
+/*
+ * Name: iucv_reply_prmmsg
+ * Purpose: This function responds to the two-way messages that you
+ *          receive. You must identify completely the message to
+ *          which you wish to reply. ie, pathid, msgid, and trgcls.
+ *          Prmmsg signifies the data is moved into the
+ *          parameter list.
+ * Input: pathid - Path identification number.
+ *        msgid - Specifies the message ID.
+ *        trgcls - Specifies target class.
  *        flags1 - Option for path.
  *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed into the parameter.  
- *                 list.                                            
- * Output: NA                                                       
- * Return: Return code from CP IUCV call.                        
+ *        prmmsg - 8-bytes of data to be placed into the parameter.
+ *                 list.
+ * Output: NA
+ * Return: Return code from CP IUCV call.
 */
 int iucv_reply_prmmsg (u16 pathid,
                       u32 msgid, u32 trgcls, int flags1, uchar prmmsg[8]);
 
-/*                                                                     
- * Name: iucv_resume                                                   
- * Purpose: This function restores communications over a quiesced path 
- * Input: pathid - Path identification number.                          
- *        user_data  - 16-bytes of user data.                           
- * Output: NA                                                          
- * Return: Return code from CP IUCV call.                           
+/*
+ * Name: iucv_resume
+ * Purpose: This function restores communications over a quiesced path
+ * Input: pathid - Path identification number.
+ *        user_data  - 16-bytes of user data.
+ * Output: NA
+ * Return: Return code from CP IUCV call.
 */
 int iucv_resume (u16 pathid, uchar user_data[16]);
 
-/*                                                                   
- * Name: iucv_send                                                   
- * Purpose: This function transmits data to another application.     
- *          Data to be transmitted is in a buffer and this is a      
- *          one-way message and the receiver will not reply to the   
- *          message.                                                 
- * Input: pathid - Path identification number.                        
- *        trgcls - Specifies target class.                            
- *        srccls - Specifies the source message class.                
- *        msgtag - Specifies a tag to be associated with the message. 
+/*
+ * Name: iucv_send
+ * Purpose: This function transmits data to another application.
+ *          Data to be transmitted is in a buffer and this is a
+ *          one-way message and the receiver will not reply to the
+ *          message.
+ * Input: pathid - Path identification number.
+ *        trgcls - Specifies target class.
+ *        srccls - Specifies the source message class.
+ *        msgtag - Specifies a tag to be associated with the message.
  *        flags1 - Option for path.
  *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        buffer - Address of send buffer.                            
- *        buflen - Length of send buffer.                             
- * Output: msgid - Specifies the message ID.                         
- * Return: Return code from CP IUCV call.                         
- *         (-EINVAL) - Buffer address is NULL.                             
+ *        buffer - Address of send buffer.
+ *        buflen - Length of send buffer.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ *         (-EINVAL) - Buffer address is NULL.
 */
 int iucv_send (u16 pathid,
               u32 * msgid,
               u32 trgcls,
               u32 srccls, u32 msgtag, int flags1, void *buffer, ulong buflen);
 
-/*                                                                   
- * Name: iucv_send_array                                             
- * Purpose: This function transmits data to another application.     
- *          The contents of buffer is the address of the array of    
- *          addresses and lengths of discontiguous buffers that hold 
- *          the message text. This is a one-way message and the      
- *          receiver will not reply to the message.                  
- * Input: pathid - Path identification number.                        
- *        trgcls - Specifies target class.                            
- *        srccls - Specifies the source message class.                
+/*
+ * Name: iucv_send_array
+ * Purpose: This function transmits data to another application.
+ *          The contents of buffer is the address of the array of
+ *          addresses and lengths of discontiguous buffers that hold
+ *          the message text. This is a one-way message and the
+ *          receiver will not reply to the message.
+ * Input: pathid - Path identification number.
+ *        trgcls - Specifies target class.
+ *        srccls - Specifies the source message class.
  *        msgtag - Specifies a tag to be associated witht the message.
  *        flags1 - Option for path.
- *          IPPRTY- specifies if you want to send priority message. 
- *        buffer - Address of array of send buffers.                  
- *        buflen - Total length of send buffers.                      
- * Output: msgid - Specifies the message ID.                         
- * Return: Return code from CP IUCV call.                         
- *         (-EINVAL) - Buffer address is NULL.                             
+ *          IPPRTY- specifies if you want to send priority message.
+ *        buffer - Address of array of send buffers.
+ *        buflen - Total length of send buffers.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ *         (-EINVAL) - Buffer address is NULL.
 */
 int iucv_send_array (u16 pathid,
                     u32 * msgid,
@@ -675,48 +675,48 @@ int iucv_send_array (u16 pathid,
                     u32 msgtag,
                     int flags1, iucv_array_t * buffer, ulong buflen);
 
-/*                                                                     
- * Name: iucv_send_prmmsg                                              
- * Purpose: This function transmits data to another application.       
- *          Prmmsg specifies that the 8-bytes of data are to be moved  
- *          into the parameter list. This is a one-way message and the 
- *          receiver will not reply to the message.                    
- * Input: pathid - Path identification number.                          
- *        trgcls - Specifies target class.                              
- *        srccls - Specifies the source message class.                  
- *        msgtag - Specifies a tag to be associated with the message.   
+/*
+ * Name: iucv_send_prmmsg
+ * Purpose: This function transmits data to another application.
+ *          Prmmsg specifies that the 8-bytes of data are to be moved
+ *          into the parameter list. This is a one-way message and the
+ *          receiver will not reply to the message.
+ * Input: pathid - Path identification number.
+ *        trgcls - Specifies target class.
+ *        srccls - Specifies the source message class.
+ *        msgtag - Specifies a tag to be associated with the message.
  *        flags1 - Option for path.
  *          IPPRTY- 0x20 specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed into parameter list.    
- * Output: msgid - Specifies the message ID.                           
- * Return: Return code from CP IUCV call.                           
+ *        prmmsg - 8-bytes of data to be placed into parameter list.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
 */
 int iucv_send_prmmsg (u16 pathid,
                      u32 * msgid,
                      u32 trgcls,
                      u32 srccls, u32 msgtag, int flags1, uchar prmmsg[8]);
 
-/*                                                                
- * Name: iucv_send2way                                            
- * Purpose: This function transmits data to another application.  
- *          Data to be transmitted is in a buffer. The receiver   
- *          of the send is expected to reply to the message and   
- *          a buffer is provided into which IUCV moves the reply  
- *          to this message.                                      
- * Input: pathid - Path identification number.                     
- *        trgcls - Specifies target class.                         
- *        srccls - Specifies the source message class.             
- *        msgtag - Specifies a tag associated with the message.    
+/*
+ * Name: iucv_send2way
+ * Purpose: This function transmits data to another application.
+ *          Data to be transmitted is in a buffer. The receiver
+ *          of the send is expected to reply to the message and
+ *          a buffer is provided into which IUCV moves the reply
+ *          to this message.
+ * Input: pathid - Path identification number.
+ *        trgcls - Specifies target class.
+ *        srccls - Specifies the source message class.
+ *        msgtag - Specifies a tag associated with the message.
  *        flags1 - Option for path.
  *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        buffer - Address of send buffer.                         
- *        buflen - Length of send buffer.                          
- *        ansbuf - Address of buffer into which IUCV moves the reply of 
- *                 this message.        
- *        anslen - Address of length of buffer.          
- * Output: msgid - Specifies the message ID.                      
- * Return: Return code from CP IUCV call.                      
- *         (-EINVAL) - Buffer or ansbuf address is NULL.    
+ *        buffer - Address of send buffer.
+ *        buflen - Length of send buffer.
+ *        ansbuf - Address of buffer into which IUCV moves the reply of
+ *                 this message.
+ *        anslen - Address of length of buffer.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ *         (-EINVAL) - Buffer or ansbuf address is NULL.
 */
 int iucv_send2way (u16 pathid,
                   u32 * msgid,
@@ -726,28 +726,28 @@ int iucv_send2way (u16 pathid,
                   int flags1,
                   void *buffer, ulong buflen, void *ansbuf, ulong anslen);
 
-/*                                                                    
- * Name: iucv_send2way_array                                          
- * Purpose: This function transmits data to another application.      
- *          The contents of buffer is the address of the array of     
- *          addresses and lengths of discontiguous buffers that hold  
- *          the message text. The receiver of the send is expected to 
- *          reply to the message and a buffer is provided into which  
- *          IUCV moves the reply to this message.                     
- * Input: pathid - Path identification number.                         
- *        trgcls - Specifies target class.                             
- *        srccls - Specifies the source message class.                 
- *        msgtag - Specifies a tag to be associated with the message.   
+/*
+ * Name: iucv_send2way_array
+ * Purpose: This function transmits data to another application.
+ *          The contents of buffer is the address of the array of
+ *          addresses and lengths of discontiguous buffers that hold
+ *          the message text. The receiver of the send is expected to
+ *          reply to the message and a buffer is provided into which
+ *          IUCV moves the reply to this message.
+ * Input: pathid - Path identification number.
+ *        trgcls - Specifies target class.
+ *        srccls - Specifies the source message class.
+ *        msgtag - Specifies a tag to be associated with the message.
  *        flags1 - Option for path.
  *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        buffer - Sddress of array of send buffers.                   
- *        buflen - Total length of send buffers.                       
- *        ansbuf - Address of array of buffer into which IUCV moves the reply            
- *                 of this message.                         
- *        anslen - Address of length reply buffers.              
- * Output: msgid - Specifies the message ID.                          
- * Return: Return code from CP IUCV call.                          
- *         (-EINVAL) - Buffer address is NULL.                              
+ *        buffer - Sddress of array of send buffers.
+ *        buflen - Total length of send buffers.
+ *        ansbuf - Address of array of buffer into which IUCV moves the reply
+ *                 of this message.
+ *        anslen - Address of length reply buffers.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ *         (-EINVAL) - Buffer address is NULL.
 */
 int iucv_send2way_array (u16 pathid,
                         u32 * msgid,
@@ -758,27 +758,27 @@ int iucv_send2way_array (u16 pathid,
                         iucv_array_t * buffer,
                         ulong buflen, iucv_array_t * ansbuf, ulong anslen);
 
-/*                                                                     
- * Name: iucv_send2way_prmmsg                                          
- * Purpose: This function transmits data to another application.       
- *          Prmmsg specifies that the 8-bytes of data are to be moved  
- *          into the parameter list. This is a two-way message and the 
- *          receiver of the message is expected to reply. A buffer     
- *          is provided into which IUCV moves the reply to this        
- *          message.                                                   
- * Input: pathid - Rath identification number.                          
- *        trgcls - Specifies target class.                              
- *        srccls - Specifies the source message class.                  
- *        msgtag - Specifies a tag to be associated with the message.   
+/*
+ * Name: iucv_send2way_prmmsg
+ * Purpose: This function transmits data to another application.
+ *          Prmmsg specifies that the 8-bytes of data are to be moved
+ *          into the parameter list. This is a two-way message and the
+ *          receiver of the message is expected to reply. A buffer
+ *          is provided into which IUCV moves the reply to this
+ *          message.
+ * Input: pathid - Rath identification number.
+ *        trgcls - Specifies target class.
+ *        srccls - Specifies the source message class.
+ *        msgtag - Specifies a tag to be associated with the message.
  *        flags1 - Option for path.
  *          IPPRTY- 0x20 Specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed in parameter list.      
- *        ansbuf - Address of buffer into which IUCV moves the reply of    
+ *        prmmsg - 8-bytes of data to be placed in parameter list.
+ *        ansbuf - Address of buffer into which IUCV moves the reply of
  *                 this message.
- *        anslen - Address of length of buffer.               
- * Output: msgid - Specifies the message ID.                           
- * Return: Return code from CP IUCV call.                           
- *         (-EINVAL) - Buffer address is NULL.         
+ *        anslen - Address of length of buffer.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ *         (-EINVAL) - Buffer address is NULL.
 */
 int iucv_send2way_prmmsg (u16 pathid,
                          u32 * msgid,
@@ -788,29 +788,29 @@ int iucv_send2way_prmmsg (u16 pathid,
                          ulong flags1,
                          uchar prmmsg[8], void *ansbuf, ulong anslen);
 
-/*                                                                      
- * Name: iucv_send2way_prmmsg_array                                     
- * Purpose: This function transmits data to another application.        
- *          Prmmsg specifies that the 8-bytes of data are to be moved   
- *          into the parameter list. This is a two-way message and the  
- *          receiver of the message is expected to reply. A buffer      
- *          is provided into which IUCV moves the reply to this         
- *          message. The contents of ansbuf is the address of the       
- *          array of addresses and lengths of discontiguous buffers     
- *          that contain the reply.                                     
- * Input: pathid - Path identification number.                           
- *        trgcls - Specifies target class.                               
- *        srccls - Specifies the source message class.                   
- *        msgtag - Specifies a tag to be associated with the message.    
+/*
+ * Name: iucv_send2way_prmmsg_array
+ * Purpose: This function transmits data to another application.
+ *          Prmmsg specifies that the 8-bytes of data are to be moved
+ *          into the parameter list. This is a two-way message and the
+ *          receiver of the message is expected to reply. A buffer
+ *          is provided into which IUCV moves the reply to this
+ *          message. The contents of ansbuf is the address of the
+ *          array of addresses and lengths of discontiguous buffers
+ *          that contain the reply.
+ * Input: pathid - Path identification number.
+ *        trgcls - Specifies target class.
+ *        srccls - Specifies the source message class.
+ *        msgtag - Specifies a tag to be associated with the message.
  *        flags1 - Option for path.
  *          IPPRTY- 0x20 specifies if you want to send priority message.
- *        prmmsg - 8-bytes of data to be placed into the parameter list. 
+ *        prmmsg - 8-bytes of data to be placed into the parameter list.
  *        ansbuf - Address of array of buffer into which IUCV moves the reply
- *                 of this message.  
- *        anslen - Address of length of reply buffers.                
- * Output: msgid - Specifies the message ID.      
- * Return: Return code from CP IUCV call.      
- *         (-EINVAL) - Ansbuf address is NULL.          
+ *                 of this message.
+ *        anslen - Address of length of reply buffers.
+ * Output: msgid - Specifies the message ID.
+ * Return: Return code from CP IUCV call.
+ *         (-EINVAL) - Ansbuf address is NULL.
 */
 int iucv_send2way_prmmsg_array (u16 pathid,
                                u32 * msgid,
@@ -821,29 +821,29 @@ int iucv_send2way_prmmsg_array (u16 pathid,
                                uchar prmmsg[8],
                                iucv_array_t * ansbuf, ulong anslen);
 
-/*                                                                   
- * Name: iucv_setmask                                                
- * Purpose: This function enables or disables the following IUCV     
- *          external interruptions: Nonpriority and priority message 
- *          interrupts, nonpriority and priority reply interrupts.   
+/*
+ * Name: iucv_setmask
+ * Purpose: This function enables or disables the following IUCV
+ *          external interruptions: Nonpriority and priority message
+ *          interrupts, nonpriority and priority reply interrupts.
  * Input: SetMaskFlag - options for interrupts
- *           0x80 - Nonpriority_MessagePendingInterruptsFlag         
- *           0x40 - Priority_MessagePendingInterruptsFlag            
- *           0x20 - Nonpriority_MessageCompletionInterruptsFlag      
- *           0x10 - Priority_MessageCompletionInterruptsFlag         
+ *           0x80 - Nonpriority_MessagePendingInterruptsFlag
+ *           0x40 - Priority_MessagePendingInterruptsFlag
+ *           0x20 - Nonpriority_MessageCompletionInterruptsFlag
+ *           0x10 - Priority_MessageCompletionInterruptsFlag
  *           0x08 - IUCVControlInterruptsFlag
- * Output: NA                                                        
- * Return: Return code from CP IUCV call.                         
+ * Output: NA
+ * Return: Return code from CP IUCV call.
 */
 int iucv_setmask (int SetMaskFlag);
 
-/*                                                  
- * Name: iucv_sever                                 
- * Purpose: This function terminates an IUCV path.  
- * Input: pathid - Path identification number.       
- *        user_data - 16-bytes of user data.         
- * Output: NA       
- * Return: Return code from CP IUCV call.                                
- *         (-EINVAL) - Interal error, wild pointer.       
+/*
+ * Name: iucv_sever
+ * Purpose: This function terminates an IUCV path.
+ * Input: pathid - Path identification number.
+ *        user_data - 16-bytes of user data.
+ * Output: NA
+ * Return: Return code from CP IUCV call.
+ *         (-EINVAL) - Interal error, wild pointer.
 */
 int iucv_sever (u16 pathid, uchar user_data[16]);
index e65da921a827da68fb941b1f90aa4025e666636e..f94419b334f7c064c840c831adf9c77eac15e82d 100644 (file)
@@ -68,6 +68,7 @@ static void lcs_tasklet(unsigned long);
 static void lcs_start_kernel_thread(struct lcs_card *card);
 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);
 
 /**
  * Debug Facility Stuff
@@ -429,12 +430,6 @@ lcs_setup_card(struct lcs_card *card)
        card->tx_buffer = NULL;
        card->tx_emitted = 0;
 
-       /* Initialize kernel thread task used for LGW commands. */
-       INIT_WORK(&card->kernel_thread_starter,
-                 (void *)lcs_start_kernel_thread,card);
-       card->thread_start_mask = 0;
-       card->thread_allowed_mask = 0;
-       card->thread_running_mask = 0;
        init_waitqueue_head(&card->wait_q);
        spin_lock_init(&card->lock);
        spin_lock_init(&card->ipm_lock);
@@ -675,8 +670,9 @@ lcs_ready_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
        int index, rc;
 
        LCS_DBF_TEXT(5, trace, "rdybuff");
-       BUG_ON(buffer->state != BUF_STATE_LOCKED &&
-               buffer->state != BUF_STATE_PROCESSED);
+       if (buffer->state != BUF_STATE_LOCKED &&
+           buffer->state != BUF_STATE_PROCESSED)
+               BUG();
        spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
        buffer->state = BUF_STATE_READY;
        index = buffer - channel->iob;
@@ -700,7 +696,8 @@ __lcs_processed_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
        int index, prev, next;
 
        LCS_DBF_TEXT(5, trace, "prcsbuff");
-       BUG_ON(buffer->state != BUF_STATE_READY);
+       if (buffer->state != BUF_STATE_READY)
+               BUG();
        buffer->state = BUF_STATE_PROCESSED;
        index = buffer - channel->iob;
        prev = (index - 1) & (LCS_NUM_BUFFS - 1);
@@ -732,8 +729,9 @@ lcs_release_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
        unsigned long flags;
 
        LCS_DBF_TEXT(5, trace, "relbuff");
-       BUG_ON(buffer->state != BUF_STATE_LOCKED &&
-               buffer->state != BUF_STATE_PROCESSED);
+       if (buffer->state != BUF_STATE_LOCKED &&
+           buffer->state != BUF_STATE_PROCESSED)
+               BUG();
        spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
        buffer->state = BUF_STATE_EMPTY;
        spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
@@ -1147,8 +1145,6 @@ list_modified:
                list_add_tail(&ipm->list, &card->ipm_list);
        }
        spin_unlock_irqrestore(&card->ipm_lock, flags);
-       if (card->state == DEV_STATE_UP)
-               netif_wake_queue(card->dev);
 }
 
 /**
@@ -1231,17 +1227,17 @@ lcs_set_mc_addresses(struct lcs_card *card, struct in_device *in4_dev)
                if (ipm != NULL)
                        continue;       /* Address already in list. */
                ipm = (struct lcs_ipm_list *)
-                       kmalloc(sizeof(struct lcs_ipm_list), GFP_ATOMIC);
+                       kzalloc(sizeof(struct lcs_ipm_list), GFP_ATOMIC);
                if (ipm == NULL) {
                        PRINT_INFO("Not enough memory to add "
                                   "new multicast entry!\n");
                        break;
                }
-               memset(ipm, 0, sizeof(struct lcs_ipm_list));
                memcpy(&ipm->ipm.mac_addr, buf, LCS_MAC_LENGTH);
                ipm->ipm.ip_addr = im4->multiaddr;
                ipm->ipm_state = LCS_IPM_STATE_SET_REQUIRED;
                spin_lock_irqsave(&card->ipm_lock, flags);
+               LCS_DBF_HEX(2,trace,&ipm->ipm.ip_addr,4);
                list_add(&ipm->list, &card->ipm_list);
                spin_unlock_irqrestore(&card->ipm_lock, flags);
        }
@@ -1269,7 +1265,15 @@ lcs_register_mc_addresses(void *data)
        read_unlock(&in4_dev->mc_list_lock);
        in_dev_put(in4_dev);
 
+       netif_carrier_off(card->dev);
+       netif_tx_disable(card->dev);
+       wait_event(card->write.wait_q,
+                       (card->write.state != CH_STATE_RUNNING));
        lcs_fix_multicast_list(card);
+       if (card->state == DEV_STATE_UP) {
+               netif_carrier_on(card->dev);
+               netif_wake_queue(card->dev);
+       }
 out:
        lcs_clear_thread_running_bit(card, LCS_SET_MC_THREAD);
        return 0;
@@ -1286,7 +1290,7 @@ lcs_set_multicast_list(struct net_device *dev)
         LCS_DBF_TEXT(4, trace, "setmulti");
         card = (struct lcs_card *) dev->priv;
 
-        if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) 
+        if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD))
                schedule_work(&card->kernel_thread_starter);
 }
 
@@ -1318,6 +1322,53 @@ lcs_check_irb_error(struct ccw_device *cdev, struct irb *irb)
        return PTR_ERR(irb);
 }
 
+static int
+lcs_get_problem(struct ccw_device *cdev, struct irb *irb)
+{
+       int dstat, cstat;
+       char *sense;
+
+       sense = (char *) irb->ecw;
+       cstat = irb->scsw.cstat;
+       dstat = irb->scsw.dstat;
+
+       if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
+                    SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
+                    SCHN_STAT_PROT_CHECK   | SCHN_STAT_PROG_CHECK)) {
+               LCS_DBF_TEXT(2, trace, "CGENCHK");
+               return 1;
+       }
+       if (dstat & DEV_STAT_UNIT_CHECK) {
+               if (sense[LCS_SENSE_BYTE_1] &
+                   LCS_SENSE_RESETTING_EVENT) {
+                       LCS_DBF_TEXT(2, trace, "REVIND");
+                       return 1;
+               }
+               if (sense[LCS_SENSE_BYTE_0] &
+                   LCS_SENSE_CMD_REJECT) {
+                       LCS_DBF_TEXT(2, trace, "CMDREJ");
+                       return 0;
+               }
+               if ((!sense[LCS_SENSE_BYTE_0]) &&
+                   (!sense[LCS_SENSE_BYTE_1]) &&
+                   (!sense[LCS_SENSE_BYTE_2]) &&
+                   (!sense[LCS_SENSE_BYTE_3])) {
+                       LCS_DBF_TEXT(2, trace, "ZEROSEN");
+                       return 0;
+               }
+               LCS_DBF_TEXT(2, trace, "DGENCHK");
+               return 1;
+       }
+       return 0;
+}
+
+void
+lcs_schedule_recovery(struct lcs_card *card)
+{
+       LCS_DBF_TEXT(2, trace, "startrec");
+       if (!lcs_set_thread_start_bit(card, LCS_RECOVERY_THREAD))
+               schedule_work(&card->kernel_thread_starter);
+}
 
 /**
  * IRQ Handler for LCS channels
@@ -1327,7 +1378,8 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
 {
        struct lcs_card *card;
        struct lcs_channel *channel;
-       int index;
+       int rc, index;
+       int cstat, dstat;
 
        if (lcs_check_irb_error(cdev, irb))
                return;
@@ -1338,14 +1390,27 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
        else
                channel = &card->write;
 
+       cstat = irb->scsw.cstat;
+       dstat = irb->scsw.dstat;
        LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id);
        LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.cstat, irb->scsw.dstat);
        LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.fctl, irb->scsw.actl);
 
+       /* Check for channel and device errors presented */
+       rc = lcs_get_problem(cdev, irb);
+       if (rc || (dstat & DEV_STAT_UNIT_EXCEP)) {
+               PRINT_WARN("check on device %s, dstat=0x%X, cstat=0x%X \n",
+                           cdev->dev.bus_id, dstat, cstat);
+               if (rc) {
+                       lcs_schedule_recovery(card);
+                       wake_up(&card->wait_q);
+                       return;
+               }
+       }
        /* How far in the ccw chain have we processed? */
        if ((channel->state != CH_STATE_INIT) &&
            (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
-               index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa) 
+               index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa)
                        - channel->ccws;
                if ((irb->scsw.actl & SCSW_ACTL_SUSPENDED) ||
                    (irb->scsw.cstat & SCHN_STAT_PCI))
@@ -1367,7 +1432,6 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
        else if (irb->scsw.actl & SCSW_ACTL_SUSPENDED)
                /* CCW execution stopped on a suspend bit. */
                channel->state = CH_STATE_SUSPENDED;
-
        if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
                if (irb->scsw.cc != 0) {
                        ccw_device_halt(channel->ccwdev, (addr_t) channel);
@@ -1376,7 +1440,6 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                /* The channel has been stopped by halt_IO. */
                channel->state = CH_STATE_HALTED;
        }
-
        if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
                channel->state = CH_STATE_CLEARED;
        }
@@ -1452,7 +1515,7 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer)
        lcs_release_buffer(channel, buffer);
        card = (struct lcs_card *)
                ((char *) channel - offsetof(struct lcs_card, write));
-       if (netif_queue_stopped(card->dev))
+       if (netif_queue_stopped(card->dev) && netif_carrier_ok(card->dev))
                netif_wake_queue(card->dev);
        spin_lock(&card->lock);
        card->tx_emitted--;
@@ -1488,6 +1551,10 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
                card->stats.tx_carrier_errors++;
                return 0;
        }
+       if (skb->protocol == htons(ETH_P_IPV6)) {
+               dev_kfree_skb(skb);
+               return 0;
+       }
        netif_stop_queue(card->dev);
        spin_lock(&card->lock);
        if (card->tx_buffer != NULL &&
@@ -1632,30 +1699,6 @@ lcs_detect(struct lcs_card *card)
        return rc;
 }
 
-/**
- * reset card
- */
-static int
-lcs_resetcard(struct lcs_card *card)
-{
-       int retries;
-
-       LCS_DBF_TEXT(2, trace, "rescard");
-       for (retries = 0; retries < 10; retries++) {
-               if (lcs_detect(card) == 0) {
-                       netif_wake_queue(card->dev);
-                       card->state = DEV_STATE_UP;
-                       PRINT_INFO("LCS device %s successfully restarted!\n",
-                                  card->dev->name);
-                       return 0;
-               }
-               msleep(3000);
-       }
-       PRINT_ERR("Error in Reseting LCS card!\n");
-       return -EIO;
-}
-
-
 /**
  * LCS Stop card
  */
@@ -1679,111 +1722,6 @@ lcs_stopcard(struct lcs_card *card)
        return rc;
 }
 
-/**
- * LGW initiated commands
- */
-static int
-lcs_lgw_startlan_thread(void *data)
-{
-       struct lcs_card *card;
-
-       card = (struct lcs_card *) data;
-       daemonize("lgwstpln");
-
-       if (!lcs_do_run_thread(card, LCS_STARTLAN_THREAD))
-               return 0;
-       LCS_DBF_TEXT(4, trace, "lgwstpln");
-       if (card->dev)
-               netif_stop_queue(card->dev);
-       if (lcs_startlan(card) == 0) {
-               netif_wake_queue(card->dev);
-               card->state = DEV_STATE_UP;
-               PRINT_INFO("LCS Startlan for device %s succeeded!\n",
-                          card->dev->name);
-
-       } else
-               PRINT_ERR("LCS Startlan for device %s failed!\n",
-                         card->dev->name);
-       lcs_clear_thread_running_bit(card, LCS_STARTLAN_THREAD);
-       return 0;
-}
-
-/**
- * Send startup command initiated by Lan Gateway
- */
-static int
-lcs_lgw_startup_thread(void *data)
-{
-       int rc;
-
-       struct lcs_card *card;
-
-       card = (struct lcs_card *) data;
-       daemonize("lgwstaln");
-
-       if (!lcs_do_run_thread(card, LCS_STARTUP_THREAD))
-               return 0;
-       LCS_DBF_TEXT(4, trace, "lgwstaln");
-       if (card->dev)
-               netif_stop_queue(card->dev);
-       rc = lcs_send_startup(card, LCS_INITIATOR_LGW);
-       if (rc != 0) {
-               PRINT_ERR("Startup for LCS device %s initiated " \
-                         "by LGW failed!\nReseting card ...\n",
-                         card->dev->name);
-               /* do a card reset */
-               rc = lcs_resetcard(card);
-               if (rc == 0)
-                       goto Done;
-       }
-       rc = lcs_startlan(card);
-       if (rc == 0) {
-               netif_wake_queue(card->dev);
-               card->state = DEV_STATE_UP;
-       }
-Done:
-       if (rc == 0)
-               PRINT_INFO("LCS Startup for device %s succeeded!\n",
-                          card->dev->name);
-       else
-               PRINT_ERR("LCS Startup for device %s failed!\n",
-                         card->dev->name);
-       lcs_clear_thread_running_bit(card, LCS_STARTUP_THREAD);
-       return 0;
-}
-
-
-/**
- * send stoplan command initiated by Lan Gateway
- */
-static int
-lcs_lgw_stoplan_thread(void *data)
-{
-       struct lcs_card *card;
-       int rc;
-
-       card = (struct lcs_card *) data;
-       daemonize("lgwstop");
-
-       if (!lcs_do_run_thread(card, LCS_STOPLAN_THREAD))
-               return 0;
-       LCS_DBF_TEXT(4, trace, "lgwstop");
-       if (card->dev)
-               netif_stop_queue(card->dev);
-       if (lcs_send_stoplan(card, LCS_INITIATOR_LGW) == 0)
-               PRINT_INFO("Stoplan for %s initiated by LGW succeeded!\n",
-                          card->dev->name);
-       else
-               PRINT_ERR("Stoplan %s initiated by LGW failed!\n",
-                         card->dev->name);
-       /*Try to reset the card, stop it on failure */
-        rc = lcs_resetcard(card);
-        if (rc != 0)
-                rc = lcs_stopcard(card);
-       lcs_clear_thread_running_bit(card, LCS_STOPLAN_THREAD);
-        return rc;
-}
-
 /**
  * Kernel Thread helper functions for LGW initiated commands
  */
@@ -1791,15 +1729,12 @@ static void
 lcs_start_kernel_thread(struct lcs_card *card)
 {
        LCS_DBF_TEXT(5, trace, "krnthrd");
-       if (lcs_do_start_thread(card, LCS_STARTUP_THREAD))
-               kernel_thread(lcs_lgw_startup_thread, (void *) card, SIGCHLD);
-       if (lcs_do_start_thread(card, LCS_STARTLAN_THREAD))
-               kernel_thread(lcs_lgw_startlan_thread, (void *) card, SIGCHLD);
-       if (lcs_do_start_thread(card, LCS_STOPLAN_THREAD))
-               kernel_thread(lcs_lgw_stoplan_thread, (void *) card, SIGCHLD);
+       if (lcs_do_start_thread(card, LCS_RECOVERY_THREAD))
+               kernel_thread(lcs_recovery, (void *) card, SIGCHLD);
 #ifdef CONFIG_IP_MULTICAST
        if (lcs_do_start_thread(card, LCS_SET_MC_THREAD))
-               kernel_thread(lcs_register_mc_addresses, (void *) card, SIGCHLD);
+               kernel_thread(lcs_register_mc_addresses,
+                               (void *) card, SIGCHLD);
 #endif
 }
 
@@ -1813,19 +1748,14 @@ lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd)
        if (cmd->initiator == LCS_INITIATOR_LGW) {
                switch(cmd->cmd_code) {
                case LCS_CMD_STARTUP:
-                       if (!lcs_set_thread_start_bit(card,
-                                                     LCS_STARTUP_THREAD))
-                               schedule_work(&card->kernel_thread_starter);
-                       break;
                case LCS_CMD_STARTLAN:
-                       if (!lcs_set_thread_start_bit(card,
-                                                     LCS_STARTLAN_THREAD))
-                               schedule_work(&card->kernel_thread_starter);
+                       lcs_schedule_recovery(card);
                        break;
                case LCS_CMD_STOPLAN:
-                       if (!lcs_set_thread_start_bit(card,
-                                                     LCS_STOPLAN_THREAD))
-                               schedule_work(&card->kernel_thread_starter);
+                       PRINT_WARN("Stoplan for %s initiated by LGW.\n",
+                                       card->dev->name);
+                       if (card->dev)
+                               netif_carrier_off(card->dev);
                        break;
                default:
                        PRINT_INFO("UNRECOGNIZED LGW COMMAND\n");
@@ -1941,8 +1871,11 @@ lcs_stop_device(struct net_device *dev)
 
        LCS_DBF_TEXT(2, trace, "stopdev");
        card   = (struct lcs_card *) dev->priv;
-       netif_stop_queue(dev);
+       netif_carrier_off(dev);
+       netif_tx_disable(dev);
        dev->flags &= ~IFF_UP;
+       wait_event(card->write.wait_q,
+               (card->write.state != CH_STATE_RUNNING));
        rc = lcs_stopcard(card);
        if (rc)
                PRINT_ERR("Try it again!\n ");
@@ -1968,6 +1901,7 @@ lcs_open_device(struct net_device *dev)
 
        } else {
                dev->flags |= IFF_UP;
+               netif_carrier_on(dev);
                netif_wake_queue(dev);
                card->state = DEV_STATE_UP;
        }
@@ -2059,10 +1993,31 @@ lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char
 
 DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store);
 
+static ssize_t
+lcs_dev_recover_store(struct device *dev, struct device_attribute *attr,
+                     const char *buf, size_t count)
+{
+       struct lcs_card *card = dev->driver_data;
+       char *tmp;
+       int i;
+
+       if (!card)
+               return -EINVAL;
+       if (card->state != DEV_STATE_UP)
+               return -EPERM;
+       i = simple_strtoul(buf, &tmp, 16);
+       if (i == 1)
+               lcs_schedule_recovery(card);
+       return count;
+}
+
+static DEVICE_ATTR(recover, 0200, NULL, lcs_dev_recover_store);
+
 static struct attribute * lcs_attrs[] = {
        &dev_attr_portno.attr,
        &dev_attr_type.attr,
        &dev_attr_lancmd_timeout.attr,
+       &dev_attr_recover.attr,
        NULL,
 };
 
@@ -2099,6 +2054,12 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
        ccwgdev->dev.driver_data = card;
        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);
+       card->thread_start_mask = 0;
+       card->thread_allowed_mask = 0;
+       card->thread_running_mask = 0;
         return 0;
 }
 
@@ -2200,6 +2161,7 @@ netdev_out:
        if (recover_state == DEV_STATE_RECOVER) {
                lcs_set_multicast_list(card->dev);
                card->dev->flags |= IFF_UP;
+               netif_carrier_on(card->dev);
                netif_wake_queue(card->dev);
                card->state = DEV_STATE_UP;
        } else {
@@ -2229,7 +2191,7 @@ out:
  * lcs_shutdown_device, called when setting the group device offline.
  */
 static int
-lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
+__lcs_shutdown_device(struct ccwgroup_device *ccwgdev, int recovery_mode)
 {
        struct lcs_card *card;
        enum lcs_dev_states recover_state;
@@ -2239,9 +2201,11 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
        card = (struct lcs_card *)ccwgdev->dev.driver_data;
        if (!card)
                return -ENODEV;
-       lcs_set_allowed_threads(card, 0);
-       if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD))
-               return -ERESTARTSYS;
+       if (recovery_mode == 0) {
+               lcs_set_allowed_threads(card, 0);
+               if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD))
+                       return -ERESTARTSYS;
+       }
        LCS_DBF_HEX(3, setup, &card, sizeof(void*));
        recover_state = card->state;
 
@@ -2256,6 +2220,43 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
        return 0;
 }
 
+static int
+lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
+{
+       return __lcs_shutdown_device(ccwgdev, 0);
+}
+
+/**
+ * drive lcs recovery after startup and startlan initiated by Lan Gateway
+ */
+static int
+lcs_recovery(void *ptr)
+{
+       struct lcs_card *card;
+       struct ccwgroup_device *gdev;
+        int rc;
+
+       card = (struct lcs_card *) ptr;
+       daemonize("lcs_recover");
+
+       LCS_DBF_TEXT(4, trace, "recover1");
+       if (!lcs_do_run_thread(card, LCS_RECOVERY_THREAD))
+               return 0;
+       LCS_DBF_TEXT(4, trace, "recover2");
+       gdev = card->gdev;
+       PRINT_WARN("Recovery of device %s started...\n", gdev->dev.bus_id);
+       rc = __lcs_shutdown_device(gdev, 1);
+       rc = lcs_new_device(gdev);
+       if (!rc)
+               PRINT_INFO("Device %s successfully recovered!\n",
+                               card->dev->name);
+       else
+               PRINT_INFO("Device %s could not be recovered!\n",
+                               card->dev->name);
+       lcs_clear_thread_running_bit(card, LCS_RECOVERY_THREAD);
+       return 0;
+}
+
 /**
  * lcs_remove_device, free buffers and card
  */
index 2fad5e40c2e4e7d19ee567ccb28a4fbcd682878c..93143932983b4be1be7ed814147c4d26acbaf376 100644 (file)
@@ -73,13 +73,17 @@ do {                                       \
 /**
  * LCS sense byte definitions
  */
+#define LCS_SENSE_BYTE_0               0
+#define LCS_SENSE_BYTE_1               1
+#define LCS_SENSE_BYTE_2               2
+#define LCS_SENSE_BYTE_3               3
 #define LCS_SENSE_INTERFACE_DISCONNECT 0x01
 #define LCS_SENSE_EQUIPMENT_CHECK      0x10
 #define LCS_SENSE_BUS_OUT_CHECK                0x20
 #define LCS_SENSE_INTERVENTION_REQUIRED 0x40
 #define LCS_SENSE_CMD_REJECT           0x80
-#define LCS_SENSE_RESETTING_EVENT      0x0080
-#define LCS_SENSE_DEVICE_ONLINE                0x0020
+#define LCS_SENSE_RESETTING_EVENT      0x80
+#define LCS_SENSE_DEVICE_ONLINE                0x20
 
 /**
  * LCS packet type definitions
@@ -152,10 +156,9 @@ enum lcs_dev_states {
 
 enum lcs_threads {
        LCS_SET_MC_THREAD       = 1,
-       LCS_STARTLAN_THREAD     = 2,
-       LCS_STOPLAN_THREAD      = 4,
-       LCS_STARTUP_THREAD      = 8,
+       LCS_RECOVERY_THREAD     = 2,
 };
+
 /**
  * LCS struct declarations
  */
@@ -286,6 +289,7 @@ struct lcs_card {
        struct net_device_stats stats;
        unsigned short (*lan_type_trans)(struct sk_buff *skb,
                                         struct net_device *dev);
+       struct ccwgroup_device *gdev;
        struct lcs_channel read;
        struct lcs_channel write;
        struct lcs_buffer *tx_buffer;
index 260a93c8c442b6a882a520e07a4a13820bf97806..b452cc1afd550a5c7c24ed4bde87db498539952c 100644 (file)
@@ -30,7 +30,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  */
-\f
+
 #undef DEBUG
 
 #include <linux/module.h>
@@ -65,7 +65,7 @@ MODULE_AUTHOR
     ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
 MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
 
-\f
+
 #define PRINTK_HEADER " iucv: "       /* for debugging */
 
 static struct device_driver netiucv_driver = {
@@ -202,7 +202,7 @@ netiucv_printname(char *name)
        *p = '\0';
        return tmp;
 }
-\f
+
 /**
  * States of the interface statemachine.
  */
@@ -244,7 +244,7 @@ static const char *dev_event_names[] = {
        "Connection up",
        "Connection down",
 };
-\f
+
 /**
  * Events of the connection statemachine
  */
@@ -364,7 +364,7 @@ static const char *conn_state_names[] = {
        "Connect error",
 };
 
-\f
+
 /**
  * Debug Facility Stuff
  */
@@ -516,7 +516,7 @@ static void
 fsm_action_nop(fsm_instance *fi, int event, void *arg)
 {
 }
-\f
+
 /**
  * Actions of the connection statemachine
  *****************************************************************************/
@@ -993,7 +993,7 @@ static const fsm_node conn_fsm[] = {
 
 static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
 
-\f
+
 /**
  * Actions for interface - statemachine.
  *****************************************************************************/
@@ -1182,7 +1182,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
 
                fsm_newstate(conn->fsm, CONN_STATE_TX);
                conn->prof.send_stamp = xtime;
-               
+
                rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */,
                        0, nskb->data, nskb->len);
                               /* Shut up, gcc! nskb is always below 2G. */
@@ -1220,7 +1220,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
 
        return rc;
 }
-\f
+
 /**
  * Interface API for upper network layers
  *****************************************************************************/
@@ -1291,7 +1291,7 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
 
        /**
         * If connection is not running, try to restart it
-        * and throw away packet. 
+        * and throw away packet.
         */
        if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
                fsm_event(privptr->fsm, DEV_EVENT_START, dev);
@@ -1538,7 +1538,7 @@ static ssize_t
 maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct netiucv_priv *priv = dev->driver_data;
-       
+
        IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
        priv->conn->prof.maxcqueue = 0;
        return count;
@@ -1559,7 +1559,7 @@ static ssize_t
 sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct netiucv_priv *priv = dev->driver_data;
-       
+
        IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
        priv->conn->prof.doios_single = 0;
        return count;
@@ -1580,7 +1580,7 @@ static ssize_t
 mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct netiucv_priv *priv = dev->driver_data;
-       
+
        IUCV_DBF_TEXT(trace, 5, __FUNCTION__);
        priv->conn->prof.doios_multi = 0;
        return count;
@@ -1601,7 +1601,7 @@ static ssize_t
 txlen_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct netiucv_priv *priv = dev->driver_data;
-       
+
        IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
        priv->conn->prof.txlen = 0;
        return count;
@@ -1622,7 +1622,7 @@ static ssize_t
 txtime_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
        struct netiucv_priv *priv = dev->driver_data;
-       
+
        IUCV_DBF_TEXT(trace, 4, __FUNCTION__);
        priv->conn->prof.tx_time = 0;
        return count;
@@ -2000,7 +2000,7 @@ conn_write(struct device_driver *drv, const char *buf, size_t count)
        }
 
        PRINT_INFO("%s: '%s'\n", dev->name, netiucv_printname(username));
-       
+
        return count;
 
 out_free_ndev:
@@ -2099,7 +2099,7 @@ static int __init
 netiucv_init(void)
 {
        int ret;
-       
+
        ret = iucv_register_dbf_views();
        if (ret) {
                PRINT_WARN("netiucv_init failed, "
@@ -2128,7 +2128,7 @@ netiucv_init(void)
        }
        return ret;
 }
-       
+
 module_init(netiucv_init);
 module_exit(netiucv_exit);
 MODULE_LICENSE("GPL");
index 4df0fcd7b10b18a092aaeba16d6e1f80b120b9e4..619f4a0c7160d5692d09ede8b3b705a6d74790c8 100644 (file)
@@ -376,7 +376,7 @@ struct qeth_hdr_osn {
        __u8 reserved3[18];
        __u32 ccid;
 } __attribute__ ((packed));
-                                           
+
 struct qeth_hdr {
        union {
                struct qeth_hdr_layer2 l2;
@@ -825,7 +825,7 @@ struct qeth_card {
        int use_hard_stop;
        int (*orig_hard_header)(struct sk_buff *,struct net_device *,
                                unsigned short,void *,void *,unsigned);
-       struct qeth_osn_info osn_info; 
+       struct qeth_osn_info osn_info;
 };
 
 struct qeth_card_list_struct {
@@ -944,7 +944,7 @@ qeth_get_netdev_flags(struct qeth_card *card)
                return 0;
        switch (card->info.type) {
        case QETH_CARD_TYPE_IQD:
-       case QETH_CARD_TYPE_OSN:        
+       case QETH_CARD_TYPE_OSN:
                return IFF_NOARP;
 #ifdef CONFIG_QETH_IPV6
        default:
@@ -981,7 +981,7 @@ static inline int
 qeth_get_max_mtu_for_card(int cardtype)
 {
        switch (cardtype) {
-               
+
        case QETH_CARD_TYPE_UNKNOWN:
        case QETH_CARD_TYPE_OSAE:
        case QETH_CARD_TYPE_OSN:
@@ -1097,9 +1097,9 @@ qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
        int count = 0, rc = 0;
        int in[4];
 
-       rc = sscanf(buf, "%d.%d.%d.%d%n", 
+       rc = sscanf(buf, "%d.%d.%d.%d%n",
                    &in[0], &in[1], &in[2], &in[3], &count);
-       if (rc != 4  || count
+       if (rc != 4  || count<=0)
                return -EINVAL;
        for (count = 0; count < 4; count++) {
                if (in[count] > 255)
@@ -1131,7 +1131,7 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
 
        cnt = out = found = save_cnt = num2 = 0;
         end = start = (char *) buf;
-       in = (__u16 *) addr;    
+       in = (__u16 *) addr;
        memset(in, 0, 16);
         while (end) {
                 end = strchr(end,':');
@@ -1139,7 +1139,7 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr)
                         end = (char *)buf + (strlen(buf));
                         out = 1;
                 }
-                if ((end - start)) { 
+                if ((end - start)) {
                         memset(num, 0, 5);
                         memcpy(num, start, end - start);
                        if (!qeth_isxdigit(num))
@@ -1241,5 +1241,5 @@ qeth_osn_register(unsigned char *read_dev_no,
 
 extern void
 qeth_osn_deregister(struct net_device *);
-               
+
 #endif /* __QETH_H__ */
index 44e226f211e7b1cb2ab7baf182230720242f65c9..0bab60a203094239b6e4893533aa473f4b3d269e 100644 (file)
@@ -81,7 +81,7 @@ void
 qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
 {
        struct qeth_eddp_context_reference *ref;
-       
+
        QETH_DBF_TEXT(trace, 6, "eddprctx");
        while (!list_empty(&buf->ctx_list)){
                ref = list_entry(buf->ctx_list.next,
@@ -135,7 +135,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
                                           "buffer!\n");
                                goto out;
                        }
-               }               
+               }
                /* check if the whole next skb fits into current buffer */
                if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
                                        buf->next_element_to_fill)
@@ -148,7 +148,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
                         * and increment ctx's refcnt */
                        must_refcnt = 1;
                        continue;
-               }       
+               }
                if (must_refcnt){
                        must_refcnt = 0;
                        if (qeth_eddp_buf_ref_context(buf, ctx)){
@@ -266,7 +266,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
        int left_in_frag;
        int copy_len;
        u8 *src;
-       
+
        QETH_DBF_TEXT(trace, 5, "eddpcdtc");
        if (skb_shinfo(eddp->skb)->nr_frags == 0) {
                memcpy(dst, eddp->skb->data + eddp->skb_offset, len);
@@ -408,7 +408,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
        struct tcphdr *tcph;
        int data_len;
        u32 hcsum;
-       
+
        QETH_DBF_TEXT(trace, 5, "eddpftcp");
        eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
        if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
@@ -465,13 +465,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
                eddp->th.tcp.h.seq += data_len;
        }
 }
-                          
+
 static inline int
 qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
                           struct sk_buff *skb, struct qeth_hdr *qhdr)
 {
        struct qeth_eddp_data *eddp = NULL;
-       
+
        QETH_DBF_TEXT(trace, 5, "eddpficx");
        /* create our segmentation headers and copy original headers */
        if (skb->protocol == ETH_P_IP)
@@ -512,7 +512,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
                         int hdr_len)
 {
        int skbs_per_page;
-       
+
        QETH_DBF_TEXT(trace, 5, "eddpcanp");
        /* can we put multiple skbs in one page? */
        skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
@@ -588,7 +588,7 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
                             struct qeth_hdr *qhdr)
 {
        struct qeth_eddp_context *ctx = NULL;
-       
+
        QETH_DBF_TEXT(trace, 5, "creddpct");
        if (skb->protocol == ETH_P_IP)
                ctx = qeth_eddp_create_context_generic(card, skb,
index e422b41c656e26ba11185c225f350c0113d9cd38..61faf05517d63bdb3071856e0383c485c4148858 100644 (file)
@@ -42,7 +42,7 @@ qeth_create_device_attributes_osn(struct device *dev);
 
 extern void
 qeth_remove_device_attributes_osn(struct device *dev);
-                   
+
 extern int
 qeth_create_driver_attributes(void);
 
index cb14642d97aa8300a12e37238933b91271077d9c..9e671a48cd2f1368460bc49935e5905a0c86f7f6 100644 (file)
@@ -513,7 +513,7 @@ __qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
 
        QETH_DBF_TEXT(setup, 3, "setoffl");
        QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
-       
+
        if (card->dev && netif_carrier_ok(card->dev))
                netif_carrier_off(card->dev);
        recover_flag = card->state;
@@ -604,13 +604,13 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
        list_for_each_entry(addr, &card->ip_list, entry) {
                if (card->options.layer2) {
                        if ((addr->type == todo->type) &&
-                           (memcmp(&addr->mac, &todo->mac, 
+                           (memcmp(&addr->mac, &todo->mac,
                                    OSA_ADDR_LEN) == 0)) {
                                found = 1;
                                break;
                        }
                        continue;
-               } 
+               }
                if ((addr->proto     == QETH_PROT_IPV4)  &&
                    (todo->proto     == QETH_PROT_IPV4)  &&
                    (addr->type      == todo->type)      &&
@@ -694,13 +694,13 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
                if (card->options.layer2) {
                        if ((tmp->type  == addr->type)  &&
                            (tmp->is_multicast == addr->is_multicast) &&
-                           (memcmp(&tmp->mac, &addr->mac, 
+                           (memcmp(&tmp->mac, &addr->mac,
                                    OSA_ADDR_LEN) == 0)) {
                                found = 1;
                                break;
                        }
                        continue;
-               }        
+               }
                if ((tmp->proto        == QETH_PROT_IPV4)     &&
                    (addr->proto       == QETH_PROT_IPV4)     &&
                    (tmp->type         == addr->type)         &&
@@ -1173,7 +1173,7 @@ qeth_determine_card_type(struct qeth_card *card)
                                           "due to hardware limitations!\n");
                                card->qdio.no_out_queues = 1;
                                card->qdio.default_out_queue = 0;
-                       } 
+                       }
                        return 0;
                }
                i++;
@@ -1198,7 +1198,7 @@ qeth_probe_device(struct ccwgroup_device *gdev)
                return -ENODEV;
 
        QETH_DBF_TEXT_(setup, 2, "%s", gdev->dev.bus_id);
-       
+
        card = qeth_alloc_card();
        if (!card) {
                put_device(dev);
@@ -1220,7 +1220,7 @@ qeth_probe_device(struct ccwgroup_device *gdev)
                put_device(dev);
                qeth_free_card(card);
                return rc;
-       }                           
+       }
        if ((rc = qeth_setup_card(card))){
                QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
                put_device(dev);
@@ -1843,7 +1843,7 @@ struct qeth_cmd_buffer *iob)
               &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH);
        QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
 }
-                                                   
+
 static int
 qeth_send_control_data(struct qeth_card *card, int len,
                       struct qeth_cmd_buffer *iob,
@@ -1937,7 +1937,7 @@ qeth_osn_send_control_data(struct qeth_card *card, int len,
                wake_up(&card->wait_q);
        }
        return rc;
-}                                      
+}
 
 static inline void
 qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
@@ -1966,7 +1966,7 @@ qeth_osn_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
        memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
        return qeth_osn_send_control_data(card, s1, iob);
 }
-                                                           
+
 static int
 qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
                  int (*reply_cb)
@@ -2579,7 +2579,7 @@ qeth_process_inbound_buffer(struct qeth_card *card,
                skb->dev = card->dev;
                if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
                        vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
-               else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)     
+               else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3)
                        qeth_rebuild_skb(card, skb, hdr);
                else { /*in case of OSN*/
                        skb_push(skb, sizeof(struct qeth_hdr));
@@ -2763,7 +2763,7 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
                index = i % QDIO_MAX_BUFFERS_PER_Q;
                buffer = &card->qdio.in_q->bufs[index];
                if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
-                     qeth_check_qdio_errors(buffer->buffer, 
+                     qeth_check_qdio_errors(buffer->buffer,
                                             qdio_err, siga_err,"qinerr")))
                        qeth_process_inbound_buffer(card, buffer, index);
                /* clear buffer and give back to hardware */
@@ -3187,7 +3187,7 @@ qeth_alloc_qdio_buffers(struct qeth_card *card)
        if (card->qdio.state == QETH_QDIO_ALLOCATED)
                return 0;
 
-       card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), 
+       card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q),
                                  GFP_KERNEL|GFP_DMA);
        if (!card->qdio.in_q)
                return - ENOMEM;
@@ -3476,7 +3476,7 @@ qeth_halt_channels(struct qeth_card *card)
        rc3 = qeth_halt_channel(&card->data);
        if (rc1)
                return rc1;
-       if (rc2) 
+       if (rc2)
                return rc2;
        return rc3;
 }
@@ -3491,7 +3491,7 @@ qeth_clear_channels(struct qeth_card *card)
        rc3 = qeth_clear_channel(&card->data);
        if (rc1)
                return rc1;
-       if (rc2) 
+       if (rc2)
                return rc2;
        return rc3;
 }
@@ -3798,10 +3798,10 @@ qeth_open(struct net_device *dev)
                QETH_DBF_TEXT(trace,4,"nomacadr");
                return -EPERM;
        }
-       card->dev->flags |= IFF_UP;
-       netif_start_queue(dev);
        card->data.state = CH_STATE_UP;
        card->state = CARD_STATE_UP;
+       card->dev->flags |= IFF_UP;
+       netif_start_queue(dev);
 
        if (!card->lan_online && netif_carrier_ok(dev))
                netif_carrier_off(dev);
@@ -3817,7 +3817,7 @@ qeth_stop(struct net_device *dev)
 
        card = (struct qeth_card *) dev->priv;
 
-       netif_stop_queue(dev);
+       netif_tx_disable(dev);
        card->dev->flags &= ~IFF_UP;
        if (card->state == CARD_STATE_UP)
                card->state = CARD_STATE_SOFTSETUP;
@@ -3958,7 +3958,7 @@ qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
 #endif
        *hdr = (struct qeth_hdr *)
                qeth_push_skb(card, skb, sizeof(struct qeth_hdr));
-       if (hdr == NULL)
+       if (*hdr == NULL)
                return -EINVAL;
        return 0;
 }
@@ -4098,7 +4098,7 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
                }
        } else { /* passthrough */
                 if((skb->dev->type == ARPHRD_IEEE802_TR) &&
-                   !memcmp(skb->data + sizeof(struct qeth_hdr) + 
+                   !memcmp(skb->data + sizeof(struct qeth_hdr) +
                    sizeof(__u16), skb->dev->broadcast, 6)) {
                        hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
                                                QETH_HDR_PASSTHRU;
@@ -4385,7 +4385,7 @@ out:
 }
 
 static inline int
-qeth_get_elements_no(struct qeth_card *card, void *hdr, 
+qeth_get_elements_no(struct qeth_card *card, void *hdr,
                     struct sk_buff *skb, int elems)
 {
        int elements_needed = 0;
@@ -4416,6 +4416,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
        enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
        struct qeth_eddp_context *ctx = NULL;
        int tx_bytes = skb->len;
+       unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
+       unsigned short tso_size = skb_shinfo(skb)->tso_size;
        int rc;
 
        QETH_DBF_TEXT(trace, 6, "sendpkt");
@@ -4441,7 +4443,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
                return 0;
        }
        cast_type = qeth_get_cast_type(card, skb);
-       if ((cast_type == RTN_BROADCAST) && 
+       if ((cast_type == RTN_BROADCAST) &&
            (card->info.broadcast_capable == 0)){
                card->stats.tx_dropped++;
                card->stats.tx_errors++;
@@ -4463,7 +4465,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
                        card->stats.tx_errors++;
                        dev_kfree_skb_any(skb);
                        return NETDEV_TX_OK;
-               } 
+               }
                elements_needed++;
        } else {
                if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) {
@@ -4498,16 +4500,16 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
                card->stats.tx_packets++;
                card->stats.tx_bytes += tx_bytes;
 #ifdef CONFIG_QETH_PERF_STATS
-               if (skb_shinfo(skb)->tso_size &&
+               if (tso_size &&
                   !(large_send == QETH_LARGE_SEND_NO)) {
-                       card->perf_stats.large_send_bytes += skb->len;
+                       card->perf_stats.large_send_bytes += tx_bytes;
                        card->perf_stats.large_send_cnt++;
                }
-               if (skb_shinfo(skb)->nr_frags > 0){
+               if (nr_frags > 0){
                        card->perf_stats.sg_skbs_sent++;
                        /* nr_frags + skb->data */
                        card->perf_stats.sg_frags_sent +=
-                               skb_shinfo(skb)->nr_frags + 1;
+                               nr_frags + 1;
                }
 #endif /* CONFIG_QETH_PERF_STATS */
        }
@@ -5373,7 +5375,7 @@ qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
         cmd = (struct qeth_ipa_cmd *) data;
         if (cmd->hdr.return_code) {
                PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
-                         "Continuing\n",cmd->data.setdelvlan.vlan_id, 
+                         "Continuing\n",cmd->data.setdelvlan.vlan_id,
                          QETH_CARD_IFNAME(card), cmd->hdr.return_code);
                QETH_DBF_TEXT_(trace, 2, "L2VL%4x", cmd->hdr.command);
                QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
@@ -5393,7 +5395,7 @@ qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
        iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
        cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
         cmd->data.setdelvlan.vlan_id = i;
-       return qeth_send_ipa_cmd(card, iob, 
+       return qeth_send_ipa_cmd(card, iob,
                                 qeth_layer2_send_setdelvlan_cb, NULL);
 }
 
@@ -5457,7 +5459,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
  * Examine hardware response to SET_PROMISC_MODE
  */
 static int
-qeth_setadp_promisc_mode_cb(struct qeth_card *card, 
+qeth_setadp_promisc_mode_cb(struct qeth_card *card,
                            struct qeth_reply *reply,
                            unsigned long data)
 {
@@ -5468,10 +5470,10 @@ qeth_setadp_promisc_mode_cb(struct qeth_card *card,
 
        cmd = (struct qeth_ipa_cmd *) data;
        setparms = &(cmd->data.setadapterparms);
-       
+
         qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
-       if (cmd->hdr.return_code) { 
-               QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);      
+       if (cmd->hdr.return_code) {
+               QETH_DBF_TEXT_(trace,4,"prmrc%2.2x",cmd->hdr.return_code);
                setparms->data.mode = SET_PROMISC_MODE_OFF;
        }
        card->info.promisc_mode = setparms->data.mode;
@@ -5517,7 +5519,7 @@ qeth_set_multicast_list(struct net_device *dev)
 
        if (card->info.type == QETH_CARD_TYPE_OSN)
                return ;
-        
+
        QETH_DBF_TEXT(trace, 3, "setmulti");
        qeth_delete_mc_addresses(card);
        if (card->options.layer2) {
@@ -5575,7 +5577,7 @@ qeth_osn_assist(struct net_device *dev,
        struct qeth_cmd_buffer *iob;
        struct qeth_card *card;
        int rc;
-       
+
        QETH_DBF_TEXT(trace, 2, "osnsdmc");
        if (!dev)
                return -ENODEV;
@@ -5654,7 +5656,7 @@ qeth_osn_deregister(struct net_device * dev)
        card->osn_info.data_cb = NULL;
        return;
 }
-                                          
+
 static void
 qeth_delete_mc_addresses(struct qeth_card *card)
 {
@@ -5818,7 +5820,7 @@ qeth_add_multicast_ipv6(struct qeth_card *card)
        struct inet6_dev *in6_dev;
 
        QETH_DBF_TEXT(trace,4,"chkmcv6");
-       if (!qeth_is_supported(card, IPA_IPV6)) 
+       if (!qeth_is_supported(card, IPA_IPV6))
                return ;
        in6_dev = in6_dev_get(card->dev);
        if (in6_dev == NULL)
@@ -6359,12 +6361,9 @@ qeth_netdev_init(struct net_device *dev)
        dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
        dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
 #endif
-       dev->hard_header = card->orig_hard_header;
        if (qeth_get_netdev_flags(card) & IFF_NOARP) {
                dev->rebuild_header = NULL;
                dev->hard_header = NULL;
-               if (card->options.fake_ll)
-                       dev->hard_header = qeth_fake_header;
                dev->header_cache_update = NULL;
                dev->hard_header_cache = NULL;
        }
@@ -6373,6 +6372,9 @@ qeth_netdev_init(struct net_device *dev)
        if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
                card->dev->dev_id = card->info.unique_id & 0xffff;
 #endif
+       if (card->options.fake_ll &&
+               (qeth_get_netdev_flags(card) & IFF_NOARP))
+                       dev->hard_header = qeth_fake_header;
        dev->hard_header_parse = NULL;
        dev->set_mac_address = qeth_layer2_set_mac_address;
        dev->flags |= qeth_get_netdev_flags(card);
@@ -6477,6 +6479,9 @@ retry:
        /*network device will be recovered*/
        if (card->dev) {
                card->dev->hard_header = card->orig_hard_header;
+               if (card->options.fake_ll &&
+                   (qeth_get_netdev_flags(card) & IFF_NOARP))
+                       card->dev->hard_header = qeth_fake_header;
                return 0;
        }
        /* at first set_online allocate netdev */
@@ -6584,7 +6589,7 @@ qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
 
        cmd = (struct qeth_ipa_cmd *) data;
        if (!card->options.layer2 || card->info.guestlan ||
-           !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {    
+           !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
                memcpy(card->dev->dev_addr,
                       &cmd->data.setadapterparms.data.change_addr.addr,
                       OSA_ADDR_LEN);
@@ -7031,14 +7036,12 @@ qeth_softsetup_ipv6(struct qeth_card *card)
 
        QETH_DBF_TEXT(trace,3,"softipv6");
 
-       netif_stop_queue(card->dev);
        rc = qeth_send_startlan(card, QETH_PROT_IPV6);
        if (rc) {
                PRINT_ERR("IPv6 startlan failed on %s\n",
                          QETH_CARD_IFNAME(card));
                return rc;
        }
-       netif_wake_queue(card->dev);
        rc = qeth_query_ipassists(card,QETH_PROT_IPV6);
        if (rc) {
                PRINT_ERR("IPv6 query ipassist failed on %s\n",
@@ -7352,7 +7355,8 @@ qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
                card->options.large_send = type;
                return 0;
        }
-       netif_stop_queue(card->dev);
+       if (card->state == CARD_STATE_UP)
+               netif_tx_disable(card->dev);
        card->options.large_send = type;
        switch (card->options.large_send) {
        case QETH_LARGE_SEND_EDDP:
@@ -7374,7 +7378,8 @@ qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
                card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
                break;
        }
-       netif_wake_queue(card->dev);
+       if (card->state == CARD_STATE_UP)
+               netif_wake_queue(card->dev);
        return rc;
 }
 
@@ -7427,7 +7432,7 @@ qeth_softsetup_card(struct qeth_card *card)
        if ((rc = qeth_setrouting_v6(card)))
                QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
 out:
-       netif_stop_queue(card->dev);
+       netif_tx_disable(card->dev);
        return 0;
 }
 
@@ -7567,7 +7572,7 @@ qeth_stop_card(struct qeth_card *card, int recovery_mode)
        if (card->read.state == CH_STATE_UP &&
            card->write.state == CH_STATE_UP &&
            (card->state == CARD_STATE_UP)) {
-               if (recovery_mode && 
+               if (recovery_mode &&
                    card->info.type != QETH_CARD_TYPE_OSN) {
                        qeth_stop(card->dev);
                } else {
@@ -7736,10 +7741,8 @@ static int
 qeth_register_netdev(struct qeth_card *card)
 {
        QETH_DBF_TEXT(setup, 3, "regnetd");
-       if (card->dev->reg_state != NETREG_UNINITIALIZED) {
-               qeth_netdev_init(card->dev);
+       if (card->dev->reg_state != NETREG_UNINITIALIZED)
                return 0;
-       }
        /* sysfs magic */
        SET_NETDEV_DEV(card->dev, &card->gdev->dev);
        return register_netdev(card->dev);
@@ -7750,7 +7753,7 @@ qeth_start_again(struct qeth_card *card, int recovery_mode)
 {
        QETH_DBF_TEXT(setup ,2, "startag");
 
-       if (recovery_mode && 
+       if (recovery_mode &&
            card->info.type != QETH_CARD_TYPE_OSN) {
                qeth_open(card->dev);
        } else {
index 011c41041029addb84d96eb478bd533780f261e2..0477c47471c5a7ccb60c00bbd4179ee73a5f47c6 100644 (file)
@@ -445,7 +445,7 @@ enum qeth_ipa_arp_return_codes {
 /* Helper functions */
 #define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
                           (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
-       
+
 /*****************************************************************************/
 /* END OF   IP Assist related definitions                                    */
 /*****************************************************************************/
@@ -490,7 +490,7 @@ extern unsigned char ULP_ENABLE[];
 /* Layer 2 defintions */
 #define QETH_PROT_LAYER2 0x08
 #define QETH_PROT_TCPIP  0x03
-#define QETH_PROT_OSN2   0x0a     
+#define QETH_PROT_OSN2   0x0a
 #define QETH_ULP_ENABLE_PROT_TYPE(buffer) (buffer+0x50)
 #define QETH_IPA_CMD_PROT_TYPE(buffer) (buffer+0x19)
 
index 360d782c7adacbc22e5fa074e6306dcde29fd810..66f2da14e6e3a0bd2bbd5250a9b25efa585637b2 100644 (file)
@@ -36,7 +36,7 @@ qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
 {
        struct device *dev = NULL;
        loff_t nr = 0;
-       
+
        down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
        if (*offset == 0)
                return SEQ_START_TOKEN;
@@ -60,8 +60,8 @@ static void *
 qeth_procfile_seq_next(struct seq_file *s, void *it, loff_t *offset)
 {
        struct device *prev, *next;
-       
-       if (it == SEQ_START_TOKEN) 
+
+       if (it == SEQ_START_TOKEN)
                prev = NULL;
        else
                prev = (struct device *) it;
@@ -180,7 +180,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
        struct device *device;
        struct qeth_card *card;
 
-       
+
        if (it == SEQ_START_TOKEN)
                return 0;
 
index 882d419e41603ed065dd319ae190527821ab1a52..185a9cfbcbdc76cff6128a60f1be96fb4bf6d743 100644 (file)
@@ -785,7 +785,7 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con
        }
        if (card->options.large_send == type)
                return count;
-       if ((rc = qeth_set_large_send(card, type)))     
+       if ((rc = qeth_set_large_send(card, type)))
                return rc;
        return count;
 }
@@ -1682,7 +1682,7 @@ qeth_create_device_attributes(struct device *dev)
        if (card->info.type == QETH_CARD_TYPE_OSN)
                return sysfs_create_group(&dev->kobj,
                                          &qeth_osn_device_attr_group);
-       
+
        if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group)))
                return ret;
        if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_ipato_group))){
@@ -1713,7 +1713,7 @@ qeth_remove_device_attributes(struct device *dev)
        if (card->info.type == QETH_CARD_TYPE_OSN)
                return sysfs_remove_group(&dev->kobj,
                                          &qeth_osn_device_attr_group);
-                     
+
        sysfs_remove_group(&dev->kobj, &qeth_device_attr_group);
        sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
        sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
index 1286ddea450b9e5b83d7642e9caed26c9817bc16..24ef40ca956276158d6852d72aff055cc0d26a46 100644 (file)
@@ -117,11 +117,11 @@ __qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
        int fragno;
        unsigned long addr;
        int element, cnt, dlen;
-       
+
        fragno = skb_shinfo(skb)->nr_frags;
        element = *next_element_to_fill;
        dlen = 0;
-       
+
        if (is_tso)
                buffer->element[element].flags =
                        SBAL_FLAGS_MIDDLE_FRAG;
index fa476e7e0a480c52f2808b721e3c465eb1ba5fc3..de9ba7890b5adceeea4c909062de63e9afeb6f71 100644 (file)
@@ -4297,6 +4297,8 @@ static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
 int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
 {
        if (ap->flags & ATA_FLAG_SUSPENDED) {
+               ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+               ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 200000);
                ap->flags &= ~ATA_FLAG_SUSPENDED;
                ata_set_mode(ap);
        }
index fee843fab1c7d5a0760285f9b4472da260efb8b7..108910f512e477c14bc083c8922b31c1b1640e82 100644 (file)
@@ -982,6 +982,12 @@ static int device_check(ppa_struct *dev)
        return -ENODEV;
 }
 
+static int ppa_adjust_queue(struct scsi_device *device)
+{
+       blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH);
+       return 0;
+}
+
 static struct scsi_host_template ppa_template = {
        .module                 = THIS_MODULE,
        .proc_name              = "ppa",
@@ -997,6 +1003,7 @@ static struct scsi_host_template ppa_template = {
        .cmd_per_lun            = 1,
        .use_clustering         = ENABLE_CLUSTERING,
        .can_queue              = 1,
+       .slave_alloc            = ppa_adjust_queue,
 };
 
 /***************************************************************************
index 9b8bca1ac1f01ae6a7a61166235c385e118ffc44..f16f92a6ec0fe468da2c87363227015e0f27a061 100644 (file)
@@ -2035,6 +2035,7 @@ static void mv_phy_reset(struct ata_port *ap)
 static void mv_eng_timeout(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc;
+       unsigned long flags;
 
        printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
        DPRINTK("All regs @ start of eng_timeout\n");
@@ -2046,8 +2047,10 @@ static void mv_eng_timeout(struct ata_port *ap)
               ap->host_set->mmio_base, ap, qc, qc->scsicmd,
               &qc->scsicmd->cmnd);
 
+       spin_lock_irqsave(&ap->host_set->lock, flags);
        mv_err_intr(ap, 0);
        mv_stop_and_reset(ap);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
        WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
        if (qc->flags & ATA_QCFLAG_ACTIVE) {
index f7264fd611c2226bc71e6d8e552478a8eaaf2748..cb9082fd7e2fd7ff2afaec77e0f36fbbdf8c430b 100644 (file)
@@ -454,7 +454,7 @@ static int sil24_softreset(struct ata_port *ap, int verbose,
         */
        msleep(10);
 
-       prb->ctrl = PRB_CTRL_SRST;
+       prb->ctrl = cpu_to_le16(PRB_CTRL_SRST);
        prb->fis[1] = 0; /* no PM yet */
 
        writel((u32)paddr, port + PORT_CMD_ACTIVATE);
@@ -551,9 +551,9 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
 
                if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
                        if (qc->tf.flags & ATA_TFLAG_WRITE)
-                               prb->ctrl = PRB_CTRL_PACKET_WRITE;
+                               prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_WRITE);
                        else
-                               prb->ctrl = PRB_CTRL_PACKET_READ;
+                               prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_READ);
                } else
                        prb->ctrl = 0;
 
index 941c1e15c8992cfe19a3fdeb2deddbc424afafa7..62f8cb7b3d2bac60319fd7b9017537345b445c0f 100644 (file)
@@ -165,6 +165,7 @@ static struct {
        {"HP", "HSV100", NULL, BLIST_REPORTLUN2 | BLIST_NOSTARTONADD},
        {"HP", "C1557A", NULL, BLIST_FORCELUN},
        {"HP", "C3323-300", "4269", BLIST_NOTQ},
+       {"HP", "C5713A", NULL, BLIST_NOREPORTLUN},
        {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
        {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
        {"IBM", "2105", NULL, BLIST_RETRY_HWERROR},
index 764a8b375ead1005ff2a49e130f1f80418748be7..faee4757c03adb712363eb09527c5af357c0bef3 100644 (file)
@@ -367,7 +367,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
                           int nsegs, unsigned bufflen, gfp_t gfp)
 {
        struct request_queue *q = rq->q;
-       int nr_pages = (bufflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
        unsigned int data_len = 0, len, bytes, off;
        struct page *page;
        struct bio *bio = NULL;
index 8b6d65e21bae3a23ac362d65ac9b95d57732b6f3..f3b16066387cf210ddc4b37246558ef18e8c92a8 100644 (file)
@@ -955,7 +955,8 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
        list_for_each_entry(rphy, &sas_host->rphy_list, list) {
                struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
 
-               if (rphy->scsi_target_id == -1)
+               if (rphy->identify.device_type != SAS_END_DEVICE ||
+                   rphy->scsi_target_id == -1)
                        continue;
 
                if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
@@ -977,7 +978,6 @@ static int sas_user_scan(struct Scsi_Host *shost, uint channel,
 #define SETUP_TEMPLATE(attrb, field, perm, test)                               \
        i->private_##attrb[count] = class_device_attr_##field;          \
        i->private_##attrb[count].attr.mode = perm;                     \
-       i->private_##attrb[count].store = NULL;                         \
        i->attrb[count] = &i->private_##attrb[count];                   \
        if (test)                                                       \
                count++
index 969f949004318b1080f16643fd0b07d41f280d53..5cba59ad7dc5a38eff874cbc735ec140bdb2829c 100644 (file)
@@ -1164,14 +1164,16 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
        struct fs_uart_platform_info *pdata;
        struct platform_device* pdev = early_uart_get_pdev(co->index);
 
-       port =
-           (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
-       pinfo = (struct uart_cpm_port *)port;
        if (!pdev) {
                pr_info("cpm_uart: console: compat mode\n");
                /* compatibility - will be cleaned up */
                cpm_uart_init_portdesc();
+       }
 
+       port =
+           (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
+       pinfo = (struct uart_cpm_port *)port;
+       if (!pdev) {
                if (pinfo->set_lineif)
                        pinfo->set_lineif(pinfo);
        } else {
index 4b2de08f46d0ef7f58462e3144326743c3a6390f..cdba128250a96e5f2f98a07c5dcbf2318c65ff92 100644 (file)
@@ -213,7 +213,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
            L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
        if (is_con) {
                mem_addr = alloc_bootmem(memsz);
-               dma_addr = mem_addr;
+               dma_addr = virt_to_bus(mem_addr);
        }
        else
                mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
index f5aac92fb7981b673250f8099c2b1dc7f0616ebe..53c2465bad2d37117e121ee78e5967f2c5cfc67a 100644 (file)
@@ -1365,7 +1365,7 @@ static inline void s3c2410_serial_exit(void)
 
 #endif /* CONFIG_CPU_S3C2410 */
 
-#ifdef CONFIG_CPU_S3C2440
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
 
 static int s3c2440_serial_setsource(struct uart_port *port,
                                     struct s3c24xx_uart_clksrc *clk)
index aa521b8e0d4e3a06a3c0c53ca7929a72d0b96763..776d4ff060840b62ac3758097f671a8b523d9bd1 100644 (file)
@@ -145,14 +145,15 @@ lh7a40xuart_rx_chars (struct uart_port* port)
 {
        struct tty_struct* tty = port->info->tty;
        int cbRxMax = 256;      /* (Gross) limit on receive */
-       unsigned int data, flag;/* Received data and status */
+       unsigned int data;      /* Received data and status */
+       unsigned int flag;
 
        while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
                data = UR (port, UART_R_DATA);
                flag = TTY_NORMAL;
                ++port->icount.rx;
 
-               if (unlikely(data & RxError)) { /* Quick check, short-circuit */
+               if (unlikely(data & RxError)) {
                        if (data & RxBreak) {
                                data &= ~(RxFramingError | RxParityError);
                                ++port->icount.brk;
@@ -303,7 +304,7 @@ static void lh7a40xuart_set_mctrl (struct uart_port* port, unsigned int mctrl)
        /* Note, kernel appears to be setting DTR and RTS on console. */
 
        /* *** FIXME: this deserves more work.  There's some work in
-               tracing all of the IO pins. */
+              tracing all of the IO pins. */
 #if 0
        if( port->mapbase == UART1_PHYS) {
                gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS);
@@ -662,9 +663,13 @@ static int __init lh7a40xuart_init(void)
        if (ret == 0) {
                int i;
 
-               for (i = 0; i < DEV_NR; i++)
+               for (i = 0; i < DEV_NR; i++) {
+                       /* UART3, when used, requires GPIO pin reallocation */
+                       if (lh7a40x_ports[i].port.mapbase == UART3_PHYS)
+                               GPIO_PINMUX |= 1<<3;
                        uart_add_one_port (&lh7a40x_reg,
                                           &lh7a40x_ports[i].port);
+               }
        }
        return ret;
 }
index 9de4b5a04d70f20d34698a7750544467e0ef31ff..5fc14563ee3a98f523c277be23246074d2407849 100644 (file)
@@ -405,7 +405,7 @@ static int s3c24xx_spi_remove(struct platform_device *dev)
 
 static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
 {
-       struct s3c24xx_spi *hw = platform_get_drvdata(dev);
+       struct s3c24xx_spi *hw = platform_get_drvdata(pdev);
 
        clk_disable(hw->clk);
        return 0;
@@ -413,7 +413,7 @@ static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
 
 static int s3c24xx_spi_resume(struct platform_device *pdev)
 {
-       struct s3c24xx_spi *hw = platform_get_drvdata(dev);
+       struct s3c24xx_spi *hw = platform_get_drvdata(pdev);
 
        clk_enable(hw->clk);
        return 0;
index acde8868da21f959cf36a9ea28df3901434ade18..fafe7c1265b31f9e719dadc9a7fbb3bebefbc89d 100644 (file)
@@ -185,6 +185,9 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
        /* Select Power Management Mode */
        pxa27x_ohci_select_pmm(inf->port_mode);
 
+       if (inf->power_budget)
+               hcd->power_budget = inf->power_budget;
+
        ohci_hcd_init(hcd_to_ohci(hcd));
 
        retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
index efd6ca7e4ac55eecc6e82cf1e9acd26ed30d3ded..054059632a219e54d2217486df8da039a7a0bff9 100644 (file)
@@ -301,21 +301,4 @@ config USB_NET_ZAURUS
          some cases CDC MDLM) protocol, not "g_ether".
 
 
-config USB_ZD1201
-       tristate "USB ZD1201 based Wireless device support"
-       depends on NET_RADIO
-       select FW_LOADER
-       ---help---
-         Say Y if you want to use wireless LAN adapters based on the ZyDAS
-         ZD1201 chip.
-
-         This driver makes the adapter appear as a normal Ethernet interface,
-         typically on wlan0.
-         
-         The zd1201 device requires external firmware to be loaded.
-         This can be found at http://linux-lc100020.sourceforge.net/
-         
-         To compile this driver as a module, choose M here: the
-         module will be called zd1201.
-
 endmenu
index a21e6eaabaf67f2f678404b48217741e8f453a8f..160f19dbdf121253ad360e8d64313aff8253d25d 100644 (file)
@@ -15,7 +15,6 @@ obj-$(CONFIG_USB_NET_RNDIS_HOST)      += rndis_host.o
 obj-$(CONFIG_USB_NET_CDC_SUBSET)       += cdc_subset.o
 obj-$(CONFIG_USB_NET_ZAURUS)   += zaurus.o
 obj-$(CONFIG_USB_USBNET)       += usbnet.o
-obj-$(CONFIG_USB_ZD1201)       += zd1201.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
index 4587087d777ab6a69edb66fd4f661b5017b08404..5a2840aeb547d26170557c03f531e592391e3091 100644 (file)
@@ -167,6 +167,69 @@ config FB_ARMCLCD
          here and read <file:Documentation/modules.txt>.  The module
          will be called amba-clcd.
 
+choice
+
+       depends on FB_ARMCLCD && (ARCH_LH7A40X || ARCH_LH7952X)
+       prompt "LCD Panel"
+       default FB_ARMCLCD_SHARP_LQ035Q7DB02
+
+config FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
+       bool "LogicPD LCD 3.5\" QVGA w/HRTFT IC"
+       help
+         This is an implementation of the Sharp LQ035Q7DB02, a 3.5"
+         color QVGA, HRTFT panel.  The LogicPD device includes an
+         an integrated HRTFT controller IC.
+         The native resolution is 240x320.
+
+config FB_ARMCLCD_SHARP_LQ057Q3DC02
+       bool "LogicPD LCD 5.7\" QVGA"
+       help
+         This is an implementation of the Sharp LQ057Q3DC02, a 5.7"
+         color QVGA, TFT panel.  The LogicPD device includes an
+         The native resolution is 320x240.
+
+config FB_ARMCLCD_SHARP_LQ64D343
+       bool "LogicPD LCD 6.4\" VGA"
+       help
+         This is an implementation of the Sharp LQ64D343, a 6.4"
+         color VGA, TFT panel.  The LogicPD device includes an
+         The native resolution is 640x480.
+
+config FB_ARMCLCD_SHARP_LQ10D368
+       bool "LogicPD LCD 10.4\" VGA"
+       help
+         This is an implementation of the Sharp LQ10D368, a 10.4"
+         color VGA, TFT panel.  The LogicPD device includes an
+         The native resolution is 640x480.
+
+
+config FB_ARMCLCD_SHARP_LQ121S1DG41
+       bool "LogicPD LCD 12.1\" SVGA"
+       help
+         This is an implementation of the Sharp LQ121S1DG41, a 12.1"
+         color SVGA, TFT panel.  The LogicPD device includes an
+         The native resolution is 800x600.
+
+         This panel requires a clock rate may be an integer fraction
+         of the base LCDCLK frequency.  The driver will select the
+         highest frequency available that is lower than the maximum
+         allowed.  The panel may flicker if the clock rate is
+         slower than the recommended minimum.
+
+config FB_ARMCLCD_AUO_A070VW01_WIDE
+       bool "AU Optronics A070VW01 LCD 7.0\" WIDE"
+       help
+         This is an implementation of the AU Optronics, a 7.0"
+         WIDE Color.  The native resolution is 234x480.
+
+config FB_ARMCLCD_HITACHI
+       bool "Hitachi Wide Screen 800x480"
+       help
+         This is an implementation of the Hitachi 800x480.
+
+endchoice
+
+
 config FB_ACORN
        bool "Acorn VIDC support"
        depends on (FB = y) && ARM && (ARCH_ACORN || ARCH_CLPS7500)
@@ -743,7 +806,7 @@ config FB_I810_I2C
 
 config FB_INTEL
        tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)"
-       depends on FB && EXPERIMENTAL && PCI && X86_32
+       depends on FB && EXPERIMENTAL && PCI && X86
        select AGP
        select AGP_INTEL
        select FB_MODE_HELPERS
index 3d04b2def0f165d5ab7cbc2afadace2fa7896eb8..789450bb0bc9c020aec0320bf6125a85417a7bb5 100644 (file)
@@ -214,10 +214,13 @@ int au1100fb_setmode(struct au1100fb_device *fbdev)
  */
 int au1100fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fbi)
 {
-       struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
-       u32 *palette = fbdev->regs->lcd_pallettebase;
+       struct au1100fb_device *fbdev;
+       u32 *palette;
        u32 value;
 
+       fbdev = to_au1100fb_device(fbi);
+       palette = fbdev->regs->lcd_pallettebase;
+
        if (regno > (AU1100_LCD_NBR_PALETTE_ENTRIES - 1))
                return -EINVAL;
 
@@ -316,9 +319,11 @@ int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi)
  */
 int au1100fb_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fbi)
 {
-       struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+       struct au1100fb_device *fbdev;
        int dy;
 
+       fbdev = to_au1100fb_device(fbi);
+
        print_dbg("fb_pan_display %p %p", var, fbi);
 
        if (!var || !fbdev) {
@@ -382,10 +387,12 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle)
  */
 int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 {
-       struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
+       struct au1100fb_device *fbdev;
        unsigned int len;
        unsigned long start=0, off;
 
+       fbdev = to_au1100fb_device(fbi);
+
        if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
                return -EINVAL;
        }
@@ -467,7 +474,7 @@ int au1100fb_drv_probe(struct device *dev)
 
        if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len,
                                DRIVER_NAME)) {
-               print_err("fail to lock memory region at 0x%08x",
+               print_err("fail to lock memory region at 0x%08lx",
                                au1100fb_fix.mmio_start);
                return -EBUSY;
        }
@@ -595,13 +602,13 @@ int au1100fb_drv_remove(struct device *dev)
        return 0;
 }
 
-int au1100fb_drv_suspend(struct device *dev, u32 state, u32 level)
+int au1100fb_drv_suspend(struct device *dev, pm_message_t state)
 {
        /* TODO */
        return 0;
 }
 
-int au1100fb_drv_resume(struct device *dev, u32 level)
+int au1100fb_drv_resume(struct device *dev)
 {
        /* TODO */
        return 0;
index ca020719d20b14959b3d1daa31d4e1c91742df2e..47ba1a79adcd350e6487b42d1d5e6b1a4e1b6c7a 100644 (file)
@@ -1745,7 +1745,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
                                        fbcon_redraw_move(vc, p, 0, t, count);
                                ypan_up_redraw(vc, t, count);
                                if (vc->vc_rows - b > 0)
-                                       fbcon_redraw_move(vc, p, b - count,
+                                       fbcon_redraw_move(vc, p, b,
                                                          vc->vc_rows - b, b);
                        } else
                                fbcon_redraw_move(vc, p, t + count, b - t - count, t);
@@ -2631,7 +2631,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
                                        scr_memcpyw((u16 *) q, (u16 *) p,
                                                    vc->vc_size_row);
                                }
-                               softback_in = p;
+                               softback_in = softback_curr = p;
                                update_region(vc, vc->vc_origin,
                                              logo_lines * vc->vc_cols);
                        }
index da29d007f215d33103f2c9ea641c333df6704774..469b06c2918044f302a71c45ab30d201283fdad6 100644 (file)
@@ -8,9 +8,9 @@
 
 
 /*** Version/name ***/
-#define INTELFB_VERSION                        "0.9.2"
+#define INTELFB_VERSION                        "0.9.4"
 #define INTELFB_MODULE_NAME            "intelfb"
-#define SUPPORTED_CHIPSETS             "830M/845G/852GM/855GM/865G/915G/915GM"
+#define SUPPORTED_CHIPSETS             "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM"
 
 
 /*** Debug/feature defines ***/
 #define PCI_DEVICE_ID_INTEL_865G       0x2572
 #define PCI_DEVICE_ID_INTEL_915G       0x2582
 #define PCI_DEVICE_ID_INTEL_915GM      0x2592
+#define PCI_DEVICE_ID_INTEL_945G       0x2772
+#define PCI_DEVICE_ID_INTEL_945GM      0x27A2
 
 /* Size of MMIO region */
 #define INTEL_REG_SIZE                 0x80000
 
 #define STRIDE_ALIGNMENT               16
+#define STRIDE_ALIGNMENT_I9XX          64
 
 #define PALETTE_8_ENTRIES              256
 
@@ -125,7 +128,9 @@ enum intel_chips {
        INTEL_855GME,
        INTEL_865G,
        INTEL_915G,
-       INTEL_915GM
+       INTEL_915GM,
+       INTEL_945G,
+       INTEL_945GM,
 };
 
 struct intelfb_hwstate {
@@ -277,8 +282,13 @@ struct intelfb_info {
 
        /* driver registered */
        int registered;
+       
+       /* index into plls */
+       int pll_index;
 };
 
+#define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM))
+
 /*** function prototypes ***/
 
 extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);
index 995b47c165a71cbb93c9bc05ec3c133cdeaea098..076fa56be192a3df28d06f7ad41903f8ba54ad86 100644 (file)
@@ -1,11 +1,12 @@
 /*
  * intelfb
  *
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM
- * integrated graphics chips.
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
+ * 945G/945GM integrated graphics chips.
  *
  * Copyright Â© 2002, 2003 David Dawes <dawes@xfree86.org>
  *                   2004 Sylvain Meyer
+ *                   2006 David Airlie
  *
  * This driver consists of two parts.  The first part (intelfbdrv.c) provides
  * the basic fbdev interfaces, is derived in part from the radeonfb and
 
 #include "intelfb.h"
 #include "intelfbhw.h"
+#include "../edid.h"
 
 static void __devinit get_initial_mode(struct intelfb_info *dinfo);
 static void update_dinfo(struct intelfb_info *dinfo,
@@ -182,6 +184,8 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
        { 0, }
 };
 
@@ -261,7 +265,7 @@ MODULE_PARM_DESC(mode,
 
 #ifndef MODULE
 #define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
-#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name), NULL, 0)
+#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)
 #define OPT_STRVAL(opt, name) (opt + strlen(name))
 
 static __inline__ char *
@@ -546,11 +550,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* Set base addresses. */
        if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
-                       (ent->device == PCI_DEVICE_ID_INTEL_915GM)) {
+           (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
+           (ent->device == PCI_DEVICE_ID_INTEL_945G)  ||
+           (ent->device == PCI_DEVICE_ID_INTEL_945GM)) {
                aperture_bar = 2;
                mmio_bar = 0;
-               /* Disable HW cursor on 915G/M (not implemented yet) */
-               hwcursor = 0;
        }
        dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
        dinfo->aperture.size     = pci_resource_len(pdev, aperture_bar);
@@ -584,8 +588,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* Get the chipset info. */
        dinfo->pci_chipset = pdev->device;
 
-       if (intelfbhw_get_chipset(pdev, &dinfo->name, &dinfo->chipset,
-                                 &dinfo->mobile)) {
+       if (intelfbhw_get_chipset(pdev, dinfo)) {
                cleanup(dinfo);
                return -ENODEV;
        }
@@ -1029,17 +1032,44 @@ intelfb_init_var(struct intelfb_info *dinfo)
                       sizeof(struct fb_var_screeninfo));
                msrc = 5;
        } else {
+               const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev);
+               u8 *edid_d = NULL;
+
+               if (edid_s) {
+                       edid_d = kmalloc(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);
+                       }
+               }
+
                if (mode) {
+                       printk("intelfb: Looking for mode in private "
+                              "database\n");
                        msrc = fb_find_mode(var, dinfo->info, mode,
-                                           vesa_modes, VESA_MODEDB_SIZE,
+                                           dinfo->info->monspecs.modedb,
+                                           dinfo->info->monspecs.modedb_len,
                                            NULL, 0);
-                       if (msrc)
-                               msrc |= 8;
+
+                       if (msrc && msrc > 1) {
+                               printk("intelfb: No mode in private database, "
+                                      "intelfb: looking for mode in global "
+                                      "database ");
+                               msrc = fb_find_mode(var, dinfo->info, mode,
+                                                   NULL, 0, NULL, 0);
+
+                               if (msrc)
+                                       msrc |= 8;
+                       }
+
                }
+
                if (!msrc) {
                        msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
-                                           vesa_modes, VESA_MODEDB_SIZE,
-                                           NULL, 0);
+                                           NULL, 0, NULL, 0);
                }
        }
 
@@ -1139,7 +1169,10 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
        }
 
        /* Make sure the line length is a aligned correctly. */
-       dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
+       if (IS_I9XX(dinfo))
+               dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX);
+       else
+               dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
 
        if (FIXED_MODE(dinfo))
                dinfo->pitch = dinfo->initial_pitch;
@@ -1162,16 +1195,33 @@ intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        struct fb_var_screeninfo v;
        struct intelfb_info *dinfo;
        static int first = 1;
+       int i;
+       /* Good pitches to allow tiling.  Don't care about pitches < 1024. */
+       static const int pitches[] = {
+               128 * 8,
+               128 * 16,
+               128 * 32,
+               128 * 64,
+               0
+       };
 
        DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
 
        dinfo = GET_DINFO(info);
 
+       /* update the pitch */
        if (intelfbhw_validate_mode(dinfo, var) != 0)
                return -EINVAL;
 
        v = *var;
 
+       for (i = 0; pitches[i] != 0; i++) {
+               if (pitches[i] >= v.xres_virtual) {
+                       v.xres_virtual = pitches[i];
+                       break;
+               }
+       }
+
        /* Check for a supported bpp. */
        if (v.bits_per_pixel <= 8) {
                v.bits_per_pixel = 8;
@@ -1467,7 +1517,7 @@ static int
 intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
         struct intelfb_info *dinfo = GET_DINFO(info);
-
+       u32 physical;
 #if VERBOSE > 0
        DBG_MSG("intelfb_cursor\n");
 #endif
@@ -1478,7 +1528,10 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
        intelfbhw_cursor_hide(dinfo);
 
        /* If XFree killed the cursor - restore it */
-       if (INREG(CURSOR_A_BASEADDR) != dinfo->cursor.offset << 12) {
+       physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical :
+                  (dinfo->cursor.offset << 12);
+
+       if (INREG(CURSOR_A_BASEADDR) != physical) {
                u32 fg, bg;
 
                DBG_MSG("the cursor was killed - restore it !!\n");
index 624c4bc96f0d2a904447d588c88e34344845c7b4..426b7430b125491e501260f50d1d87ff8f522d04 100644 (file)
 #include "intelfb.h"
 #include "intelfbhw.h"
 
+struct pll_min_max {
+       int min_m, max_m, min_m1, max_m1;
+       int min_m2, max_m2, min_n, max_n;
+       int min_p, max_p, min_p1, max_p1;
+       int min_vco, max_vco, p_transition_clk, ref_clk;
+       int p_inc_lo, p_inc_hi;
+};
+
+#define PLLS_I8xx 0
+#define PLLS_I9xx 1
+#define PLLS_MAX 2
+
+static struct pll_min_max plls[PLLS_MAX] = {
+       { 108, 140, 18, 26,
+         6, 16, 3, 16,
+         4, 128, 0, 31,
+         930000, 1400000, 165000, 48000,
+         4, 2 }, //I8xx
+
+       { 75, 120, 10, 20,
+         5, 9, 4, 7,
+         5, 80, 1, 8,
+         1400000, 2800000, 200000, 96000,
+         10, 5 }  //I9xx
+};
+
 int
-intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset,
-                     int *mobile)
+intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
 {
        u32 tmp;
-
-       if (!pdev || !name || !chipset || !mobile)
+       if (!pdev || !dinfo)
                return 1;
 
        switch (pdev->device) {
        case PCI_DEVICE_ID_INTEL_830M:
-               *name = "Intel(R) 830M";
-               *chipset = INTEL_830M;
-               *mobile = 1;
+               dinfo->name = "Intel(R) 830M";
+               dinfo->chipset = INTEL_830M;
+               dinfo->mobile = 1;
+               dinfo->pll_index = PLLS_I8xx;
                return 0;
        case PCI_DEVICE_ID_INTEL_845G:
-               *name = "Intel(R) 845G";
-               *chipset = INTEL_845G;
-               *mobile = 0;
+               dinfo->name = "Intel(R) 845G";
+               dinfo->chipset = INTEL_845G;
+               dinfo->mobile = 0;
+               dinfo->pll_index = PLLS_I8xx;
                return 0;
        case PCI_DEVICE_ID_INTEL_85XGM:
                tmp = 0;
-               *mobile = 1;
+               dinfo->mobile = 1;
+               dinfo->pll_index = PLLS_I8xx;
                pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);
                switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &
                        INTEL_85X_VARIANT_MASK) {
                case INTEL_VAR_855GME:
-                       *name = "Intel(R) 855GME";
-                       *chipset = INTEL_855GME;
+                       dinfo->name = "Intel(R) 855GME";
+                       dinfo->chipset = INTEL_855GME;
                        return 0;
                case INTEL_VAR_855GM:
-                       *name = "Intel(R) 855GM";
-                       *chipset = INTEL_855GM;
+                       dinfo->name = "Intel(R) 855GM";
+                       dinfo->chipset = INTEL_855GM;
                        return 0;
                case INTEL_VAR_852GME:
-                       *name = "Intel(R) 852GME";
-                       *chipset = INTEL_852GME;
+                       dinfo->name = "Intel(R) 852GME";
+                       dinfo->chipset = INTEL_852GME;
                        return 0;
                case INTEL_VAR_852GM:
-                       *name = "Intel(R) 852GM";
-                       *chipset = INTEL_852GM;
+                       dinfo->name = "Intel(R) 852GM";
+                       dinfo->chipset = INTEL_852GM;
                        return 0;
                default:
-                       *name = "Intel(R) 852GM/855GM";
-                       *chipset = INTEL_85XGM;
+                       dinfo->name = "Intel(R) 852GM/855GM";
+                       dinfo->chipset = INTEL_85XGM;
                        return 0;
                }
                break;
        case PCI_DEVICE_ID_INTEL_865G:
-               *name = "Intel(R) 865G";
-               *chipset = INTEL_865G;
-               *mobile = 0;
+               dinfo->name = "Intel(R) 865G";
+               dinfo->chipset = INTEL_865G;
+               dinfo->mobile = 0;
+               dinfo->pll_index = PLLS_I8xx;
                return 0;
        case PCI_DEVICE_ID_INTEL_915G:
-               *name = "Intel(R) 915G";
-               *chipset = INTEL_915G;
-               *mobile = 0;
+               dinfo->name = "Intel(R) 915G";
+               dinfo->chipset = INTEL_915G;
+               dinfo->mobile = 0;
+               dinfo->pll_index = PLLS_I9xx;
                return 0;
        case PCI_DEVICE_ID_INTEL_915GM:
-               *name = "Intel(R) 915GM";
-               *chipset = INTEL_915GM;
-               *mobile = 1;
+               dinfo->name = "Intel(R) 915GM";
+               dinfo->chipset = INTEL_915GM;
+               dinfo->mobile = 1;
+               dinfo->pll_index = PLLS_I9xx;
+               return 0;
+       case PCI_DEVICE_ID_INTEL_945G:
+               dinfo->name = "Intel(R) 945G";
+               dinfo->chipset = INTEL_945G;
+               dinfo->mobile = 0;
+               dinfo->pll_index = PLLS_I9xx;
+               return 0;
+       case PCI_DEVICE_ID_INTEL_945GM:
+               dinfo->name = "Intel(R) 945GM";
+               dinfo->chipset = INTEL_945GM;
+               dinfo->mobile = 1;
+               dinfo->pll_index = PLLS_I9xx;
                return 0;
        default:
                return 1;
@@ -114,6 +156,7 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
 {
        struct pci_dev *bridge_dev;
        u16 tmp;
+       int stolen_overhead;
 
        if (!pdev || !aperture_size || !stolen_size)
                return 1;
@@ -128,21 +171,41 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
        tmp = 0;
        pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
        switch (pdev->device) {
-       case PCI_DEVICE_ID_INTEL_830M:
-       case PCI_DEVICE_ID_INTEL_845G:
+       case PCI_DEVICE_ID_INTEL_915G:
+       case PCI_DEVICE_ID_INTEL_915GM:
+       case PCI_DEVICE_ID_INTEL_945G:
+       case PCI_DEVICE_ID_INTEL_945GM:
+               /* 915 and 945 chipsets support a 256MB aperture.
+                  Aperture size is determined by inspected the
+                  base address of the aperture. */
+               if (pci_resource_start(pdev, 2) & 0x08000000)
+                       *aperture_size = MB(128);
+               else
+                       *aperture_size = MB(256);
+               break;
+       default:
                if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
                        *aperture_size = MB(64);
                else
                        *aperture_size = MB(128);
+               break;
+       }
+
+       /* Stolen memory size is reduced by the GTT and the popup.
+          GTT is 1K per MB of aperture size, and popup is 4K. */
+       stolen_overhead = (*aperture_size / MB(1)) + 4;
+       switch(pdev->device) {
+       case PCI_DEVICE_ID_INTEL_830M:
+       case PCI_DEVICE_ID_INTEL_845G:
                switch (tmp & INTEL_830_GMCH_GMS_MASK) {
                case INTEL_830_GMCH_GMS_STOLEN_512:
-                       *stolen_size = KB(512) - KB(132);
+                       *stolen_size = KB(512) - KB(stolen_overhead);
                        return 0;
                case INTEL_830_GMCH_GMS_STOLEN_1024:
-                       *stolen_size = MB(1) - KB(132);
+                       *stolen_size = MB(1) - KB(stolen_overhead);
                        return 0;
                case INTEL_830_GMCH_GMS_STOLEN_8192:
-                       *stolen_size = MB(8) - KB(132);
+                       *stolen_size = MB(8) - KB(stolen_overhead);
                        return 0;
                case INTEL_830_GMCH_GMS_LOCAL:
                        ERR_MSG("only local memory found\n");
@@ -157,28 +220,27 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
                }
                break;
        default:
-               *aperture_size = MB(128);
                switch (tmp & INTEL_855_GMCH_GMS_MASK) {
                case INTEL_855_GMCH_GMS_STOLEN_1M:
-                       *stolen_size = MB(1) - KB(132);
+                       *stolen_size = MB(1) - KB(stolen_overhead);
                        return 0;
                case INTEL_855_GMCH_GMS_STOLEN_4M:
-                       *stolen_size = MB(4) - KB(132);
+                       *stolen_size = MB(4) - KB(stolen_overhead);
                        return 0;
                case INTEL_855_GMCH_GMS_STOLEN_8M:
-                       *stolen_size = MB(8) - KB(132);
+                       *stolen_size = MB(8) - KB(stolen_overhead);
                        return 0;
                case INTEL_855_GMCH_GMS_STOLEN_16M:
-                       *stolen_size = MB(16) - KB(132);
+                       *stolen_size = MB(16) - KB(stolen_overhead);
                        return 0;
                case INTEL_855_GMCH_GMS_STOLEN_32M:
-                       *stolen_size = MB(32) - KB(132);
+                       *stolen_size = MB(32) - KB(stolen_overhead);
                        return 0;
                case INTEL_915G_GMCH_GMS_STOLEN_48M:
-                       *stolen_size = MB(48) - KB(132);
+                       *stolen_size = MB(48) - KB(stolen_overhead);
                        return 0;
                case INTEL_915G_GMCH_GMS_STOLEN_64M:
-                       *stolen_size = MB(64) - KB(132);
+                       *stolen_size = MB(64) - KB(stolen_overhead);
                        return 0;
                case INTEL_855_GMCH_GMS_DISABLED:
                        ERR_MSG("video memory is disabled\n");
@@ -529,12 +591,63 @@ intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
 }
 
 
+static int calc_vclock3(int index, int m, int n, int p)
+{
+       if (p == 0 || n == 0)
+               return 0;
+       return plls[index].ref_clk * m / n / p;
+}
+
+static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvds)
+{
+       struct pll_min_max *pll = &plls[index];
+       u32 m, vco, p;
+
+       m = (5 * (m1 + 2)) + (m2 + 2);
+       n += 2;
+       vco = pll->ref_clk * m / n;
+
+       if (index == PLLS_I8xx) {
+               p = ((p1 + 2) * (1 << (p2 + 1)));
+       } else {
+               p = ((p1) * (p2 ? 5 : 10));
+       }
+       return vco / p;
+}
+
+static void
+intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2)
+{
+       int p1, p2;
+
+       if (IS_I9XX(dinfo)) {
+               if (dpll & DPLL_P1_FORCE_DIV2)
+                       p1 = 1;
+               else
+                       p1 = (dpll >> DPLL_P1_SHIFT) & 0xff;
+               
+               p1 = ffs(p1);
+
+               p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK;
+       } else {
+               if (dpll & DPLL_P1_FORCE_DIV2)
+                       p1 = 0;
+               else
+                       p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
+               p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
+       }
+
+       *o_p1 = p1;
+       *o_p2 = p2;
+}
+
+
 void
 intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
 {
 #if REGDUMP
        int i, m1, m2, n, p1, p2;
-
+       int index = dinfo->pll_index;
        DBG_MSG("intelfbhw_print_hw_state\n");
 
        if (!hw || !dinfo)
@@ -547,26 +660,22 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
        n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
        m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
        m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-       if (hw->vga_pd & VGAPD_0_P1_FORCE_DIV2)
-               p1 = 0;
-       else
-               p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK;
-       p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK;
+
+       intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
+
        printk("        VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-               m1, m2, n, p1, p2);
-       printk("        VGA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+              m1, m2, n, p1, p2);
+       printk("        VGA0: clock is %d\n",
+              calc_vclock(index, m1, m2, n, p1, p2, 0));
 
        n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
        m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
        m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-       if (hw->vga_pd & VGAPD_1_P1_FORCE_DIV2)
-               p1 = 0;
-       else
-               p1 = (hw->vga_pd >> VGAPD_1_P1_SHIFT) & DPLL_P1_MASK;
-       p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK;
+
+       intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
        printk("        VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-               m1, m2, n, p1, p2);
-       printk("        VGA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+              m1, m2, n, p1, p2);
+       printk("        VGA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
 
        printk("        DPLL_A:                 0x%08x\n", hw->dpll_a);
        printk("        DPLL_B:                 0x%08x\n", hw->dpll_b);
@@ -578,34 +687,30 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
        n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
        m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
        m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-       if (hw->dpll_a & DPLL_P1_FORCE_DIV2)
-               p1 = 0;
-       else
-               p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
-       p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
+
+       intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
+
        printk("        PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-               m1, m2, n, p1, p2);
-       printk("        PLLA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+              m1, m2, n, p1, p2);
+       printk("        PLLA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
 
        n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
        m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
        m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-       if (hw->dpll_a & DPLL_P1_FORCE_DIV2)
-               p1 = 0;
-       else
-               p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
-       p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
+
+       intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
+
        printk("        PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-               m1, m2, n, p1, p2);
-       printk("        PLLA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+              m1, m2, n, p1, p2);
+       printk("        PLLA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
 
 #if 0
        printk("        PALETTE_A:\n");
        for (i = 0; i < PALETTE_8_ENTRIES)
-               printk("        %3d:    0x%08x\n", i, hw->palette_a[i];
+               printk("        %3d:    0x%08x\n", i, hw->palette_a[i]);
        printk("        PALETTE_B:\n");
        for (i = 0; i < PALETTE_8_ENTRIES)
-               printk("        %3d:    0x%08x\n", i, hw->palette_b[i];
+               printk("        %3d:    0x%08x\n", i, hw->palette_b[i]);
 #endif
 
        printk("        HTOTAL_A:               0x%08x\n", hw->htotal_a);
@@ -680,11 +785,11 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
        }
        for (i = 0; i < 3; i++) {
                printk("        SWF3%d                  0x%08x\n", i,
-                       hw->swf3x[i]);
+                      hw->swf3x[i]);
        }
        for (i = 0; i < 8; i++)
                printk("        FENCE%d                 0x%08x\n", i,
-                       hw->fence[i]);
+                      hw->fence[i]);
 
        printk("        INSTPM                  0x%08x\n", hw->instpm);
        printk("        MEM_MODE                0x%08x\n", hw->mem_mode);
@@ -695,43 +800,58 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
 #endif
 }
 
+
+
 /* Split the M parameter into M1 and M2. */
 static int
-splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2)
+splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2)
 {
        int m1, m2;
-
-       m1 = (m - 2 - (MIN_M2 + MAX_M2) / 2) / 5 - 2;
-       if (m1 < MIN_M1)
-               m1 = MIN_M1;
-       if (m1 > MAX_M1)
-               m1 = MAX_M1;
-       m2 = m - 5 * (m1 + 2) - 2;
-       if (m2 < MIN_M2 || m2 > MAX_M2 || m2 >= m1) {
-               return 1;
-       } else {
-               *retm1 = (unsigned int)m1;
-               *retm2 = (unsigned int)m2;
-               return 0;
+       int testm;
+       struct pll_min_max *pll = &plls[index];
+
+       /* no point optimising too much - brute force m */
+       for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) {
+               for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) {
+                       testm = (5 * (m1 + 2)) + (m2 + 2);
+                       if (testm == m) {
+                               *retm1 = (unsigned int)m1;
+                               *retm2 = (unsigned int)m2;
+                               return 0;
+                       }
+               }
        }
+       return 1;
 }
 
 /* Split the P parameter into P1 and P2. */
 static int
-splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2)
+splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2)
 {
        int p1, p2;
+       struct pll_min_max *pll = &plls[index];
+
+       if (index == PLLS_I9xx) {
+               p2 = (p % 10) ? 1 : 0;
+
+               p1 = p / (p2 ? 5 : 10);
+
+               *retp1 = (unsigned int)p1;
+               *retp2 = (unsigned int)p2;
+               return 0;
+       }
 
        if (p % 4 == 0)
                p2 = 1;
        else
                p2 = 0;
        p1 = (p / (1 << (p2 + 1))) - 2;
-       if (p % 4 == 0 && p1 < MIN_P1) {
+       if (p % 4 == 0 && p1 < pll->min_p1) {
                p2 = 0;
                p1 = (p / (1 << (p2 + 1))) - 2;
        }
-       if (p1  < MIN_P1 || p1 > MAX_P1 || (p1 + 2) * (1 << (p2 + 1)) != p) {
+       if (p1 < pll->min_p1 || p1 > pll->max_p1 ||
+           (p1 + 2) * (1 << (p2 + 1)) != p) {
                return 1;
        } else {
                *retp1 = (unsigned int)p1;
@@ -741,14 +861,15 @@ splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2)
 }
 
 static int
-calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
+calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
                u32 *retp2, u32 *retclock)
 {
-       u32 m1, m2, n, p1, p2, n1;
-       u32 f_vco, p, p_best = 0, m, f_out;
+       u32 m1, m2, n, p1, p2, n1, testm;
+       u32 f_vco, p, p_best = 0, m, f_out = 0;
        u32 err_max, err_target, err_best = 10000000;
        u32 n_best = 0, m_best = 0, f_best, f_err;
-       u32 p_min, p_max, p_inc, div_min, div_max;
+       u32 p_min, p_max, p_inc, div_max;
+       struct pll_min_max *pll = &plls[index];
 
        /* Accept 0.5% difference, but aim for 0.1% */
        err_max = 5 * clock / 1000;
@@ -756,58 +877,56 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
 
        DBG_MSG("Clock is %d\n", clock);
 
-       div_max = MAX_VCO_FREQ / clock;
-       div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock;
+       div_max = pll->max_vco / clock;
 
-       if (clock <= P_TRANSITION_CLOCK)
-               p_inc = 4;
-       else
-               p_inc = 2;
-       p_min = ROUND_UP_TO(div_min, p_inc);
+       p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi;
+       p_min = p_inc;
        p_max = ROUND_DOWN_TO(div_max, p_inc);
-       if (p_min < MIN_P)
-               p_min = 4;
-       if (p_max > MAX_P)
-               p_max = 128;
+       if (p_min < pll->min_p)
+               p_min = pll->min_p;
+       if (p_max > pll->max_p)
+               p_max = pll->max_p;
 
        DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);
 
        p = p_min;
        do {
-               if (splitp(p, &p1, &p2)) {
+               if (splitp(index, p, &p1, &p2)) {
                        WRN_MSG("cannot split p = %d\n", p);
                        p += p_inc;
                        continue;
                }
-               n = MIN_N;
+               n = pll->min_n;
                f_vco = clock * p;
 
                do {
-                       m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK;
-                       if (m < MIN_M)
-                               m = MIN_M;
-                       if (m > MAX_M)
-                               m = MAX_M;
-                       f_out = CALC_VCLOCK3(m, n, p);
-                       if (splitm(m, &m1, &m2)) {
-                               WRN_MSG("cannot split m = %d\n", m);
-                               n++;
-                               continue;
-                       }
-                       if (clock > f_out)
-                               f_err = clock - f_out;
-                       else
-                               f_err = f_out - clock;
-
-                       if (f_err < err_best) {
-                               m_best = m;
-                               n_best = n;
-                               p_best = p;
-                               f_best = f_out;
-                               err_best = f_err;
+                       m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk;
+                       if (m < pll->min_m)
+                               m = pll->min_m + 1;
+                       if (m > pll->max_m)
+                               m = pll->max_m - 1;
+                       for (testm = m - 1; testm <= m; testm++) {
+                               f_out = calc_vclock3(index, m, n, p);
+                               if (splitm(index, testm, &m1, &m2)) {
+                                       WRN_MSG("cannot split m = %d\n", m);
+                                       n++;
+                                       continue;
+                               }
+                               if (clock > f_out)
+                                       f_err = clock - f_out;
+                               else/* slightly bias the error for bigger clocks */
+                                       f_err = f_out - clock + 1;
+
+                               if (f_err < err_best) {
+                                       m_best = testm;
+                                       n_best = n;
+                                       p_best = p;
+                                       f_best = f_out;
+                                       err_best = f_err;
+                               }
                        }
                        n++;
-               } while ((n <= MAX_N) && (f_out >= clock));
+               } while ((n <= pll->max_n) && (f_out >= clock));
                p += p_inc;
        } while ((p <= p_max));
 
@@ -818,21 +937,22 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
        m = m_best;
        n = n_best;
        p = p_best;
-       splitm(m, &m1, &m2);
-       splitp(p, &p1, &p2);
+       splitm(index, m, &m1, &m2);
+       splitp(index, p, &p1, &p2);
        n1 = n - 2;
 
        DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
                "f: %d (%d), VCO: %d\n",
                m, m1, m2, n, n1, p, p1, p2,
-               CALC_VCLOCK3(m, n, p), CALC_VCLOCK(m1, m2, n1, p1, p2),
-               CALC_VCLOCK3(m, n, p) * p);
+               calc_vclock3(index, m, n, p),
+               calc_vclock(index, m1, m2, n1, p1, p2, 0),
+               calc_vclock3(index, m, n, p) * p);
        *retm1 = m1;
        *retm2 = m2;
        *retn = n1;
        *retp1 = p1;
        *retp2 = p2;
-       *retclock = CALC_VCLOCK(m1, m2, n1, p1, p2);
+       *retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0);
 
        return 0;
 }
@@ -860,6 +980,7 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
        u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
        u32 vsync_pol, hsync_pol;
        u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
+       u32 stride_alignment;
 
        DBG_MSG("intelfbhw_mode_to_hw\n");
 
@@ -929,7 +1050,8 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
        /* Desired clock in kHz */
        clock_target = 1000000000 / var->pixclock;
 
-       if (calc_pll_params(clock_target, &m1, &m2, &n, &p1, &p2, &clock)) {
+       if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2,
+                           &n, &p1, &p2, &clock)) {
                WRN_MSG("calc_pll_params failed\n");
                return 1;
        }
@@ -949,7 +1071,14 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
        *dpll &= ~DPLL_P1_FORCE_DIV2;
        *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
                   (DPLL_P1_MASK << DPLL_P1_SHIFT));
-       *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
+
+       if (IS_I9XX(dinfo)) {
+               *dpll |= (p2 << DPLL_I9XX_P2_SHIFT);
+               *dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT;
+       } else {
+               *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
+       }
+
        *fp0 = (n << FP_N_DIVISOR_SHIFT) |
               (m1 << FP_M1_DIVISOR_SHIFT) |
               (m2 << FP_M2_DIVISOR_SHIFT);
@@ -1054,7 +1183,7 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
        *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
              (vactive << SRC_SIZE_VERT_SHIFT);
 
-       hw->disp_a_stride = var->xres_virtual * var->bits_per_pixel / 8;
+       hw->disp_a_stride = dinfo->pitch;
        DBG_MSG("pitch is %d\n", hw->disp_a_stride);
 
        hw->disp_a_base = hw->disp_a_stride * var->yoffset +
@@ -1063,9 +1192,11 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
        hw->disp_a_base += dinfo->fb.offset << 12;
 
        /* Check stride alignment. */
-       if (hw->disp_a_stride % STRIDE_ALIGNMENT != 0) {
+       stride_alignment = IS_I9XX(dinfo) ? STRIDE_ALIGNMENT_I9XX :
+                                           STRIDE_ALIGNMENT;
+       if (hw->disp_a_stride % stride_alignment != 0) {
                WRN_MSG("display stride %d has bad alignment %d\n",
-                       hw->disp_a_stride, STRIDE_ALIGNMENT);
+                       hw->disp_a_stride, stride_alignment);
                return 1;
        }
 
@@ -1087,6 +1218,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
        u32 hsync_reg, htotal_reg, hblank_reg;
        u32 vsync_reg, vtotal_reg, vblank_reg;
        u32 src_size_reg;
+       u32 count, tmp_val[3];
 
        /* Assume single pipe, display plane A, analog CRT. */
 
@@ -1155,6 +1287,27 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
                src_size_reg = SRC_SIZE_A;
        }
 
+       /* turn off pipe */
+       tmp = INREG(pipe_conf_reg);
+       tmp &= ~PIPECONF_ENABLE;
+       OUTREG(pipe_conf_reg, tmp);
+
+       count = 0;
+       do {
+               tmp_val[count%3] = INREG(0x70000);
+               if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1]==tmp_val[2]))
+                       break;
+               count++;
+               udelay(1);
+               if (count % 200 == 0) {
+                       tmp = INREG(pipe_conf_reg);
+                       tmp &= ~PIPECONF_ENABLE;
+                       OUTREG(pipe_conf_reg, tmp);
+               }
+       } while(count < 2000);
+
+       OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
+
        /* Disable planes A and B. */
        tmp = INREG(DSPACNTR);
        tmp &= ~DISPPLANE_PLANE_ENABLE;
@@ -1163,19 +1316,21 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
        tmp &= ~DISPPLANE_PLANE_ENABLE;
        OUTREG(DSPBCNTR, tmp);
 
-       /* Wait for vblank.  For now, just wait for a 50Hz cycle (20ms)) */
+       /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
        mdelay(20);
 
+       OUTREG(DVOB, INREG(DVOB) & ~PORT_ENABLE);
+       OUTREG(DVOC, INREG(DVOC) & ~PORT_ENABLE);
+       OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
+
        /* Disable Sync */
        tmp = INREG(ADPA);
        tmp &= ~ADPA_DPMS_CONTROL_MASK;
        tmp |= ADPA_DPMS_D3;
        OUTREG(ADPA, tmp);
 
-       /* turn off pipe */
-       tmp = INREG(pipe_conf_reg);
-       tmp &= ~PIPECONF_ENABLE;
-       OUTREG(pipe_conf_reg, tmp);
+       /* do some funky magic - xyzzy */
+       OUTREG(0x61204, 0xabcd0000);
 
        /* turn off PLL */
        tmp = INREG(dpll_reg);
@@ -1183,30 +1338,31 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
        OUTREG(dpll_reg, tmp);
 
        /* Set PLL parameters */
-       OUTREG(dpll_reg, *dpll & ~DPLL_VCO_ENABLE);
        OUTREG(fp0_reg, *fp0);
        OUTREG(fp1_reg, *fp1);
 
-       /* Set pipe parameters */
-       OUTREG(hsync_reg, *hs);
-       OUTREG(hblank_reg, *hb);
-       OUTREG(htotal_reg, *ht);
-       OUTREG(vsync_reg, *vs);
-       OUTREG(vblank_reg, *vb);
-       OUTREG(vtotal_reg, *vt);
-       OUTREG(src_size_reg, *ss);
+       /* Enable PLL */
+       OUTREG(dpll_reg, *dpll);
 
        /* Set DVOs B/C */
        OUTREG(DVOB, hw->dvob);
        OUTREG(DVOC, hw->dvoc);
 
+       /* undo funky magic */
+       OUTREG(0x61204, 0x00000000);
+
        /* Set ADPA */
+       OUTREG(ADPA, INREG(ADPA) | ADPA_DAC_ENABLE);
        OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
 
-       /* Enable PLL */
-       tmp = INREG(dpll_reg);
-       tmp |= DPLL_VCO_ENABLE;
-       OUTREG(dpll_reg, tmp);
+       /* Set pipe parameters */
+       OUTREG(hsync_reg, *hs);
+       OUTREG(hblank_reg, *hb);
+       OUTREG(htotal_reg, *ht);
+       OUTREG(vsync_reg, *vs);
+       OUTREG(vblank_reg, *vb);
+       OUTREG(vtotal_reg, *vt);
+       OUTREG(src_size_reg, *ss);
 
        /* Enable pipe */
        OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
@@ -1231,7 +1387,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo,
                        OUTREG(DSPACNTR,
                               hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE);
                        mdelay(1);
-              }
+               }
        }
 
        OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE);
@@ -1616,7 +1772,7 @@ intelfbhw_cursor_init(struct intelfb_info *dinfo)
        DBG_MSG("intelfbhw_cursor_init\n");
 #endif
 
-       if (dinfo->mobile) {
+       if (dinfo->mobile || IS_I9XX(dinfo)) {
                if (!dinfo->cursor.physical)
                        return;
                tmp = INREG(CURSOR_A_CONTROL);
@@ -1649,7 +1805,7 @@ intelfbhw_cursor_hide(struct intelfb_info *dinfo)
 #endif
 
        dinfo->cursor_on = 0;
-       if (dinfo->mobile) {
+       if (dinfo->mobile || IS_I9XX(dinfo)) {
                if (!dinfo->cursor.physical)
                        return;
                tmp = INREG(CURSOR_A_CONTROL);
@@ -1679,7 +1835,7 @@ intelfbhw_cursor_show(struct intelfb_info *dinfo)
        if (dinfo->cursor_blanked)
                return;
 
-       if (dinfo->mobile) {
+       if (dinfo->mobile || IS_I9XX(dinfo)) {
                if (!dinfo->cursor.physical)
                        return;
                tmp = INREG(CURSOR_A_CONTROL);
@@ -1705,14 +1861,18 @@ intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
 #endif
 
        /*
-        * Sets the position.  The coordinates are assumed to already
-        * have any offset adjusted.  Assume that the cursor is never
+        * Sets the position. The coordinates are assumed to already
+        * have any offset adjusted. Assume that the cursor is never
         * completely off-screen, and that x, y are always >= 0.
         */
 
        tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
              ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
        OUTREG(CURSOR_A_POSITION, tmp);
+
+       if (IS_I9XX(dinfo)) {
+               OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
+       }
 }
 
 void
index ba1920159f5268ed82d1c3f9468ad03ee5ecd9eb..10acda098b71e5c5685c739d105f2c12d90598c4 100644 (file)
 #define DPLL_VGA_MODE_DISABLE          (1 << 28)
 #define DPLL_P2_MASK                   1
 #define DPLL_P2_SHIFT                  23
+#define DPLL_I9XX_P2_SHIFT              24
 #define DPLL_P1_FORCE_DIV2             (1 << 21)
 #define DPLL_P1_MASK                   0x1f
 #define DPLL_P1_SHIFT                  16
 /* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */
 /* Clock values are in units of kHz */
 #define PLL_REFCLK             48000
-#define MIN_VCO_FREQ           930000
-#define MAX_VCO_FREQ           1400000
 #define MIN_CLOCK              25000
 #define MAX_CLOCK              350000
-#define P_TRANSITION_CLOCK     165000
-#define MIN_M                  108
-#define MAX_M                  140
-#define MIN_M1                 18
-#define MAX_M1                 26
-#define MIN_M2                 6
-#define MAX_M2                 16
-#define MIN_P                  4
-#define MAX_P                  128
-#define MIN_P1                 0
-#define MAX_P1                 31
-#define MIN_N                  3
-#define MAX_N                  16
-
-#define CALC_VCLOCK(m1, m2, n, p1, p2) \
-        ((PLL_REFCLK * (5 * ((m1) + 2) + ((m2) + 2)) / ((n) + 2)) / \
-        (((p1) + 2) * (1 << (p2 + 1))))
-
-#define CALC_VCLOCK3(m, n, p)  ((PLL_REFCLK * (m) / (n)) / (p))
 
 /* Two pipes */
 #define PIPE_A                 0
 
 
 /* function protoypes */
-extern int intelfbhw_get_chipset(struct pci_dev *pdev, const char **name,
-                                int *chipset, int *mobile);
+extern int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo);
 extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
                                int *stolen_size);
 extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo);
index 743e7ad26acc3299f32e5903b9c4bc474a249fcb..f85421bf7cb5365319d8de5076a5dbed38fe4cfb 100644 (file)
@@ -55,7 +55,7 @@ static struct fb_var_screeninfo maxinefb_defined = {
 };
 
 static struct fb_fix_screeninfo maxinefb_fix = {
-       .id =           "Maxine onboard graphics 1024x768x8",
+       .id =           "Maxine",
        .smem_len =     (1024*768),
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
@@ -107,8 +107,6 @@ static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green,
 
 static struct fb_ops maxinefb_ops = {
        .owner          = THIS_MODULE,
-       .fb_get_fix     = gen_get_fix,
-       .fb_get_var     = gen_get_var,
        .fb_setcolreg   = maxinefb_setcolreg,
        .fb_fillrect    = cfb_fillrect,
        .fb_copyarea    = cfb_copyarea,
index f9b5842c8d2de67e6f9258f65fad1fc6207b9242..20f9b557732d2c9faf031d275878d13602131922 100644 (file)
@@ -393,18 +393,30 @@ config INOTIFY
        bool "Inotify file change notification support"
        default y
        ---help---
-         Say Y here to enable inotify support and the associated system
-         calls.  Inotify is a file change notification system and a
-         replacement for dnotify.  Inotify fixes numerous shortcomings in
-         dnotify and introduces several new features.  It allows monitoring
-         of both files and directories via a single open fd.  Other features
-         include multiple file events, one-shot support, and unmount
+         Say Y here to enable inotify support.  Inotify is a file change
+         notification system and a replacement for dnotify.  Inotify fixes
+         numerous shortcomings in dnotify and introduces several new features
+         including multiple file events, one-shot support, and unmount
          notification.
 
          For more information, see Documentation/filesystems/inotify.txt
 
          If unsure, say Y.
 
+config INOTIFY_USER
+       bool "Inotify support for userspace"
+       depends on INOTIFY
+       default y
+       ---help---
+         Say Y here to enable inotify support for userspace, including the
+         associated system calls.  Inotify allows monitoring of both files and
+         directories via a single open fd.  Events are read from the file
+         descriptor, which is also select()- and poll()-able.
+
+         For more information, see Documentation/filesystems/inotify.txt
+
+         If unsure, say Y.
+
 config QUOTA
        bool "Quota support"
        help
@@ -1101,6 +1113,44 @@ config JFFS2_SUMMARY
 
          If unsure, say 'N'.
 
+config JFFS2_FS_XATTR
+       bool "JFFS2 XATTR support (EXPERIMENTAL)"
+       depends on JFFS2_FS && EXPERIMENTAL && !JFFS2_FS_WRITEBUFFER
+       default n
+       help
+         Extended attributes are name:value pairs associated with inodes by
+         the kernel or by users (see the attr(5) manual page, or visit
+         <http://acl.bestbits.at/> for details).
+         
+         If unsure, say N.
+
+config JFFS2_FS_POSIX_ACL
+       bool "JFFS2 POSIX Access Control Lists"
+       depends on JFFS2_FS_XATTR
+       default y
+       select FS_POSIX_ACL
+       help
+         Posix Access Control Lists (ACLs) support permissions for users and
+         groups beyond the owner/group/world scheme.
+         
+         To learn more about Access Control Lists, visit the Posix ACLs for
+         Linux website <http://acl.bestbits.at/>.
+         
+         If you don't know what Access Control Lists are, say N
+
+config JFFS2_FS_SECURITY
+       bool "JFFS2 Security Labels"
+       depends on JFFS2_FS_XATTR
+       default y
+       help
+         Security labels support alternative access control models
+         implemented by security modules like SELinux.  This option
+         enables an extended attribute handler for file security
+         labels in the jffs2 filesystem.
+         
+         If you are not using a security module that requires using
+         extended attributes for file security labels, say N.
+
 config JFFS2_COMPRESSION_OPTIONS
        bool "Advanced compression options for JFFS2"
        depends on JFFS2_FS
index 078d3d1191a511f3ad88ac0167142fda8c10c5a9..d0ea6bfccf29a6071144919b44e3b31f064ed879 100644 (file)
@@ -13,6 +13,7 @@ obj-y :=      open.o read_write.o file_table.o buffer.o  bio.o super.o \
                ioprio.o pnode.o drop_caches.o splice.o sync.o
 
 obj-$(CONFIG_INOTIFY)          += inotify.o
+obj-$(CONFIG_INOTIFY_USER)     += inotify_user.o
 obj-$(CONFIG_EPOLL)            += eventpoll.o
 obj-$(CONFIG_COMPAT)           += compat.o compat_ioctl.o
 
index d4c2d636c479dc2aaaa986656a8659424aac56a6..a42143ca01698e1ba64769d5d9eb1bc0aa095320 100644 (file)
@@ -416,10 +416,9 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        return retval;
        }
 
-       retval = -EIO;
        bh = affs_bread(sb, old_dentry->d_inode->i_ino);
        if (!bh)
-               goto done;
+               return -EIO;
 
        /* Remove header from its parent directory. */
        affs_lock_dir(old_dir);
index 098c12b2d60a9d8028a6a8fbdb2b03ecca84e3ba..6a0b9ad8f8c9d031d4c32fb32e1c53e0677d1ef2 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -654,9 +654,10 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
                                     write_to_vm, 0, &pages[cur_page], NULL);
                up_read(&current->mm->mmap_sem);
 
-               if (ret < local_nr_pages)
+               if (ret < local_nr_pages) {
+                       ret = -EFAULT;
                        goto out_unmap;
-
+               }
 
                offset = uaddr & ~PAGE_MASK;
                for (j = cur_page; j < page_limit; j++) {
index 1a27ecb46c9a71d7458b9119b345a8a4f6ec104c..7271bb0257f64f149d1fd3f9857416c1513787ae 100644 (file)
@@ -1,3 +1,10 @@
+Version 1.43
+------------
+POSIX locking to servers which support CIFS POSIX Extensions
+(disabled by default controlled by proc/fs/cifs/Experimental).
+Handle conversion of long share names (especially Asian languages)
+to Unicode during mount. 
+
 Version 1.42
 ------------
 Fix slow oplock break when mounted to different servers at the same time and
index 4e829dc672a645622c078466244a71d611c1e8c9..c98755dca868743c25822124c1bc06d8b225a9ed 100644 (file)
@@ -99,5 +99,5 @@ extern ssize_t        cifs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
                       unsigned int command, unsigned long arg);
-#define CIFS_VERSION   "1.42"
+#define CIFS_VERSION   "1.43"
 #endif                         /* _CIFSFS_H */
index 2879ba343ca7acf5a4c4372c16a6ef3a7237ad9e..310ea2f0e0bfd27d6eacd91ffe0f695a0ca89322 100644 (file)
@@ -267,7 +267,7 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
                        const int waitFlag);
 extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
                        const __u16 smb_file_id, const int get_flag,
-                       const __u64 len, const __u64 offset
+                       const __u64 len, struct file_lock *
                        const __u16 lock_type, const int waitFlag);
 extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
 extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
index fd36892eda55a282fc207842e0ff62787c746703..925881e00ff210e08822cc456337be1734f801d8 100644 (file)
@@ -1355,7 +1355,8 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
 int
 CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
                const __u16 smb_file_id, const int get_flag, const __u64 len,
-               const __u64 lkoffset, const __u16 lock_type, const int waitFlag)
+               struct file_lock *pLockData, const __u16 lock_type, 
+               const int waitFlag)
 {
        struct smb_com_transaction2_sfi_req *pSMB  = NULL;
        struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
@@ -1366,6 +1367,10 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
        __u16 params, param_offset, offset, byte_count, count;
 
        cFYI(1, ("Posix Lock"));
+
+       if(pLockData == NULL)
+               return EINVAL;
+
        rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
 
        if (rc)
@@ -1404,10 +1409,10 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
 
        parm_data->lock_type = cpu_to_le16(lock_type);
        if(waitFlag)
-               parm_data->lock_flags = 1;
+               parm_data->lock_flags = cpu_to_le16(1);
        parm_data->pid = cpu_to_le32(current->tgid);
-       parm_data->start = lkoffset;
-       parm_data->length = len;  /* normalize negative numbers */
+       parm_data->start = cpu_to_le64(pLockData->fl_start);
+       parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
 
        pSMB->DataOffset = cpu_to_le16(offset);
        pSMB->Fid = smb_file_id;
@@ -1419,8 +1424,33 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
                cFYI(1, ("Send error in Posix Lock = %d", rc));
-       }
+       } else if (get_flag) {
+               /* lock structure can be returned on get */
+               __u16 data_offset;
+               __u16 data_count;
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
 
+               if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) {
+                       rc = -EIO;      /* bad smb */
+                       goto plk_err_exit;
+               }
+               if(pLockData == NULL) {
+                       rc = -EINVAL;
+                       goto plk_err_exit;
+               }
+               data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+               data_count  = le16_to_cpu(pSMBr->t2.DataCount);
+               if(data_count < sizeof(struct cifs_posix_lock)) {
+                       rc = -EIO;
+                       goto plk_err_exit;
+               }
+               parm_data = (struct cifs_posix_lock *)
+                       ((char *)&pSMBr->hdr.Protocol + data_offset);
+               if(parm_data->lock_type == cpu_to_le16(CIFS_UNLCK))
+                       pLockData->fl_type = F_UNLCK;
+       }
+plk_err_exit:
        if (pSMB)
                cifs_small_buf_release(pSMB);
 
index d2ec806a4f32b516cc7a320b39fb3974bc5dd2e2..bae1479318d10fc6fd34a141a564aeb49252ba80 100644 (file)
@@ -2148,6 +2148,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
+                               if(ses->serverOS)
+                                       kfree(ses->serverOS);
                                ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
                                if(ses->serverOS == NULL)
                                        goto sesssetup_nomem;
@@ -2160,6 +2162,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                if (remaining_words > 0) {
                                        len = UniStrnlen((wchar_t *)bcc_ptr,
                                                         remaining_words-1);
+                                       if(ses->serverNOS)
+                                               kfree(ses->serverNOS);
                                        ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
                                        if(ses->serverNOS == NULL)
                                                goto sesssetup_nomem;
@@ -2177,6 +2181,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        if (remaining_words > 0) {
                                                len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
           /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain =
                                                    kzalloc(2*(len+1),GFP_KERNEL);
                                                if(ses->serverDomain == NULL)
@@ -2187,15 +2193,22 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                ses->serverDomain[2*len] = 0;
                                                ses->serverDomain[1+(2*len)] = 0;
                                        } /* else no more room so create dummy domain string */
-                                       else
+                                       else {
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain = 
                                                        kzalloc(2, GFP_KERNEL);
+                                       }
                                } else {        /* no room so create dummy domain and NOS string */
                                        /* if these kcallocs fail not much we
                                           can do, but better to not fail the
                                           sesssetup itself */
+                                       if(ses->serverDomain)
+                                               kfree(ses->serverDomain);
                                        ses->serverDomain =
                                            kzalloc(2, GFP_KERNEL);
+                                       if(ses->serverNOS)
+                                               kfree(ses->serverNOS);
                                        ses->serverNOS =
                                            kzalloc(2, GFP_KERNEL);
                                }
@@ -2204,6 +2217,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                if (((long) bcc_ptr + len) - (long)
                                    pByteArea(smb_buffer_response)
                                            <= BCC(smb_buffer_response)) {
+                                       if(ses->serverOS)
+                                               kfree(ses->serverOS);
                                        ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
                                        if(ses->serverOS == NULL)
                                                goto sesssetup_nomem;
@@ -2214,6 +2229,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        bcc_ptr++;
 
                                        len = strnlen(bcc_ptr, 1024);
+                                       if(ses->serverNOS)
+                                               kfree(ses->serverNOS);
                                        ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
                                        if(ses->serverNOS == NULL)
                                                goto sesssetup_nomem;
@@ -2223,6 +2240,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        bcc_ptr++;
 
                                        len = strnlen(bcc_ptr, 1024);
+                                       if(ses->serverDomain)
+                                               kfree(ses->serverDomain);
                                        ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
                                        if(ses->serverDomain == NULL)
                                                goto sesssetup_nomem;
@@ -2427,6 +2446,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
+                                       if(ses->serverOS)
+                                               kfree(ses->serverOS);
                                        ses->serverOS =
                                            kzalloc(2 * (len + 1), GFP_KERNEL);
                                        cifs_strfromUCS_le(ses->serverOS,
@@ -2441,6 +2462,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                len = UniStrnlen((wchar_t *)bcc_ptr,
                                                                 remaining_words
                                                                 - 1);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS =
                                                    kzalloc(2 * (len + 1),
                                                            GFP_KERNEL);
@@ -2454,7 +2477,9 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                remaining_words -= len + 1;
                                                if (remaining_words > 0) {
                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
-                            /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+                     /* last string not null terminated (e.g.Windows XP/2000) */
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
                                                        cifs_strfromUCS_le(ses->serverDomain,
                                                             (__le16 *)bcc_ptr, 
@@ -2463,11 +2488,18 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                        ses->serverDomain[2*len] = 0;
                                                        ses->serverDomain[1+(2*len)] = 0;
                                                } /* else no more room so create dummy domain string */
-                                               else
+                                               else {
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain =
                                                            kzalloc(2,GFP_KERNEL);
-                                       } else {        /* no room so create dummy domain and NOS string */
+                                               }
+                                       } else {/* no room use dummy domain&NOS */
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain = kzalloc(2, GFP_KERNEL);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS = kzalloc(2, GFP_KERNEL);
                                        }
                                } else {        /* ASCII */
@@ -2476,6 +2508,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        if (((long) bcc_ptr + len) - (long)
                                            pByteArea(smb_buffer_response)
                                            <= BCC(smb_buffer_response)) {
+                                               if(ses->serverOS)
+                                                       kfree(ses->serverOS);
                                                ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
                                                strncpy(ses->serverOS, bcc_ptr, len);
 
@@ -2484,6 +2518,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
                                                strncpy(ses->serverNOS, bcc_ptr, len);
                                                bcc_ptr += len;
@@ -2491,6 +2527,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
                                                strncpy(ses->serverDomain, bcc_ptr, len);
                                                bcc_ptr += len;
@@ -2728,6 +2766,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
+                                       if(ses->serverOS)
+                                               kfree(ses->serverOS);
                                        ses->serverOS =
                                            kzalloc(2 * (len + 1), GFP_KERNEL);
                                        cifs_strfromUCS_le(ses->serverOS,
@@ -2743,6 +2783,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                                 bcc_ptr,
                                                                 remaining_words
                                                                 - 1);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS =
                                                    kzalloc(2 * (len + 1),
                                                            GFP_KERNEL);
@@ -2760,6 +2802,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                if (remaining_words > 0) {
                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
            /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain =
                                                            kzalloc(2 *
                                                                    (len +
@@ -2777,13 +2821,20 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                                [1 + (2 * len)]
                                                            = 0;
                                                } /* else no more room so create dummy domain string */
-                                               else
+                                               else {
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain =
                                                            kzalloc(2,
                                                                    GFP_KERNEL);
+                                               }
                                        } else {        /* no room so create dummy domain and NOS string */
+                                               if(ses->serverDomain);
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain =
                                                    kzalloc(2, GFP_KERNEL);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS =
                                                    kzalloc(2, GFP_KERNEL);
                                        }
@@ -2792,6 +2843,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                        if (((long) bcc_ptr + len) - (long)
                                            pByteArea(smb_buffer_response)
                                            <= BCC(smb_buffer_response)) {
+                                               if(ses->serverOS)
+                                                       kfree(ses->serverOS);
                                                ses->serverOS =
                                                    kzalloc(len + 1,
                                                            GFP_KERNEL);
@@ -2803,6 +2856,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS =
                                                    kzalloc(len + 1,
                                                            GFP_KERNEL);
@@ -2812,6 +2867,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain =
                                                    kzalloc(len + 1,
                                                            GFP_KERNEL);
@@ -3116,6 +3173,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /* We look for obvious messed up bcc or strings in response so we do not go off
   the end since (at least) WIN2K and Windows XP have a major bug in not null
   terminating last Unicode string in response  */
+                                       if(ses->serverOS)
+                                               kfree(ses->serverOS);
                                        ses->serverOS =
                                            kzalloc(2 * (len + 1), GFP_KERNEL);
                                        cifs_strfromUCS_le(ses->serverOS,
@@ -3131,6 +3190,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                                 bcc_ptr,
                                                                 remaining_words
                                                                 - 1);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS =
                                                    kzalloc(2 * (len + 1),
                                                            GFP_KERNEL);
@@ -3147,6 +3208,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                if (remaining_words > 0) {
                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); 
      /* last string not always null terminated (e.g. for Windows XP & 2000) */
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain =
                                                            kzalloc(2 *
                                                                    (len +
@@ -3172,10 +3235,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                                          len)]
                                                            = 0;
                                                } /* else no more room so create dummy domain string */
-                                               else
+                                               else {
+                                                       if(ses->serverDomain)
+                                                               kfree(ses->serverDomain);
                                                        ses->serverDomain = kzalloc(2,GFP_KERNEL);
+                                               }
                                        } else {  /* no room so create dummy domain and NOS string */
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain = kzalloc(2, GFP_KERNEL);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS = kzalloc(2, GFP_KERNEL);
                                        }
                                } else {        /* ASCII */
@@ -3183,6 +3253,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                        if (((long) bcc_ptr + len) - 
                         (long) pByteArea(smb_buffer_response) 
                             <= BCC(smb_buffer_response)) {
+                                               if(ses->serverOS)
+                                                       kfree(ses->serverOS);
                                                ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
                                                strncpy(ses->serverOS,bcc_ptr, len);
 
@@ -3191,6 +3263,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverNOS)
+                                                       kfree(ses->serverNOS);
                                                ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
                                                strncpy(ses->serverNOS, bcc_ptr, len);  
                                                bcc_ptr += len;
@@ -3198,6 +3272,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
                                                bcc_ptr++;
 
                                                len = strnlen(bcc_ptr, 1024);
+                                               if(ses->serverDomain)
+                                                       kfree(ses->serverDomain);
                                                ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
                                                strncpy(ses->serverDomain, bcc_ptr, len);
                                                bcc_ptr += len;
@@ -3282,7 +3358,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                bcc_ptr++; /* align */
        }
 
-       if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+       if(ses->server->secMode & 
+                       (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
        if (ses->capabilities & CAP_STATUS32) {
@@ -3294,8 +3371,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
        if (ses->capabilities & CAP_UNICODE) {
                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
                length =
-                   cifs_strtoUCS((__le16 *) bcc_ptr, tree, 100, nls_codepage);
-               bcc_ptr += 2 * length;  /* convert num of 16 bit words to bytes */
+                   cifs_strtoUCS((__le16 *) bcc_ptr, tree, 
+                       6 /* max utf8 char length in bytes */ * 
+                       (/* server len*/ + 256 /* share len */), nls_codepage);
+               bcc_ptr += 2 * length;  /* convert num 16 bit words to bytes */
                bcc_ptr += 2;   /* skip trailing null */
        } else {                /* ASCII */
                strcpy(bcc_ptr, tree);
index e152bf6afa60fadc91c2080231858d9b5653f0fb..e2b4ce1dad6680cc54d8af516e7cf876533361fd 100644 (file)
@@ -84,6 +84,8 @@ static inline int cifs_get_disposition(unsigned int flags)
                return FILE_OVERWRITE_IF;
        else if ((flags & O_CREAT) == O_CREAT)
                return FILE_OPEN_IF;
+       else if ((flags & O_TRUNC) == O_TRUNC)
+               return FILE_OVERWRITE;
        else
                return FILE_OPEN;
 }
@@ -656,7 +658,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                        else
                                posix_lock_type = CIFS_WRLCK;
                        rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */,
-                                       length, pfLock->fl_start,
+                                       length, pfLock,
                                        posix_lock_type, wait_flag);
                        FreeXid(xid);
                        return rc;
@@ -704,7 +706,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
                        return -EOPNOTSUPP;
                }
                rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
-                                     length, pfLock->fl_start,
+                                     length, pfLock,
                                      posix_lock_type, wait_flag);
        } else
                rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
@@ -904,8 +906,10 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
                                if (rc != 0)
                                        break;
                        }
-                       if(experimEnabled || (pTcon->ses->server->secMode & 
-                        (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
+                       if(experimEnabled || (pTcon->ses->server &&
+                               ((pTcon->ses->server->secMode & 
+                               (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+                               == 0))) {
                                struct kvec iov[2];
                                unsigned int len;
 
index 85d166cdcae4908e8916b4e66a1dd30722b00f1c..b55b4ea9a67675a92377ffeb4a12ab9542ed8ca6 100644 (file)
@@ -67,12 +67,13 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
 static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
                         int mode, dev_t dev)
 {
-       struct inode *inode = debugfs_get_inode(dir->i_sb, mode, dev);
+       struct inode *inode;
        int error = -EPERM;
 
        if (dentry->d_inode)
                return -EEXIST;
 
+       inode = debugfs_get_inode(dir->i_sb, mode, dev);
        if (inode) {
                d_instantiate(dentry, inode);
                dget(dentry);
index 1b4491cdd11581235564f6aaaf3a545f71df1f93..2695337d4d6444de725372d6250e082d3acbf8a4 100644 (file)
@@ -337,20 +337,20 @@ static inline int ep_cmp_ffd(struct epoll_filefd *p1,
 /* Special initialization for the rb-tree node to detect linkage */
 static inline void ep_rb_initnode(struct rb_node *n)
 {
-       n->rb_parent = n;
+       rb_set_parent(n, n);
 }
 
 /* Removes a node from the rb-tree and marks it for a fast is-linked check */
 static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r)
 {
        rb_erase(n, r);
-       n->rb_parent = n;
+       rb_set_parent(n, n);
 }
 
 /* Fast check to verify that the item is linked to the main rb-tree */
 static inline int ep_rb_linked(struct rb_node *n)
 {
-       return n->rb_parent != n;
+       return rb_parent(n) != n;
 }
 
 /*
index 3a79d97ac234422c353ad6c37ab973d3363471bd..d07858c0b7c4e3885c2d6b31521f3e5668b94007 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -49,6 +49,7 @@
 #include <linux/rmap.h>
 #include <linux/acct.h>
 #include <linux/cn_proc.h>
+#include <linux/audit.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -1085,6 +1086,11 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
        /* kernel module loader fixup */
        /* so we don't try to load run modprobe in kernel space. */
        set_fs(USER_DS);
+
+       retval = audit_bprm(bprm);
+       if (retval)
+               return retval;
+
        retval = -ENOENT;
        for (try=0; try<2; try++) {
                read_lock(&binfmt_lock);
index f37528ed222e82ed419762b9839ca6546eab85f5..fbb0d4ed07d4322e947f081f1af4dd6fd025ce33 100644 (file)
@@ -284,7 +284,7 @@ static void free_rb_tree_fname(struct rb_root *root)
                 * beginning of the loop and try to free the parent
                 * node.
                 */
-               parent = n->rb_parent;
+               parent = rb_parent(n);
                fname = rb_entry(n, struct fname, rb_hash);
                while (fname) {
                        struct fname * old = fname;
index 8aac5334680d18603b987cd1afb759d1b59cf574..34b39e9a1e5a01588db869c02c85f2407d12221a 100644 (file)
@@ -767,7 +767,6 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
        if (input->group != sbi->s_groups_count) {
                ext3_warning(sb, __FUNCTION__,
                             "multiple resizers run on filesystem!");
-               unlock_super(sb);
                err = -EBUSY;
                goto exit_journal;
        }
index 732ec4bd5774507f8c06c6e05cc90d4d2004a84b..723836a1f71896a5406b7ca6e066dc42ca5a6286 100644 (file)
@@ -5,7 +5,10 @@
  *     John McCutchan  <ttb@tentacle.dhs.org>
  *     Robert Love     <rml@novell.com>
  *
+ * Kernel API added by: Amy Griffis <amy.griffis@hp.com>
+ *
  * Copyright (C) 2005 John McCutchan
+ * Copyright 2006 Hewlett-Packard Development Company, L.P.
  *
  * 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
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/idr.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/mount.h>
-#include <linux/namei.h>
-#include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/writeback.h>
 #include <linux/inotify.h>
-#include <linux/syscalls.h>
-
-#include <asm/ioctls.h>
 
 static atomic_t inotify_cookie;
 
-static kmem_cache_t *watch_cachep __read_mostly;
-static kmem_cache_t *event_cachep __read_mostly;
-
-static struct vfsmount *inotify_mnt __read_mostly;
-
-/* these are configurable via /proc/sys/fs/inotify/ */
-int inotify_max_user_instances __read_mostly;
-int inotify_max_user_watches __read_mostly;
-int inotify_max_queued_events __read_mostly;
-
 /*
  * Lock ordering:
  *
@@ -56,327 +41,108 @@ int inotify_max_queued_events __read_mostly;
  * iprune_mutex (synchronize shrink_icache_memory())
  *     inode_lock (protects the super_block->s_inodes list)
  *     inode->inotify_mutex (protects inode->inotify_watches and watches->i_list)
- *             inotify_dev->mutex (protects inotify_device and watches->d_list)
+ *             inotify_handle->mutex (protects inotify_handle and watches->h_list)
+ *
+ * The inode->inotify_mutex and inotify_handle->mutex and held during execution
+ * of a caller's event handler.  Thus, the caller must not hold any locks
+ * taken in their event handler while calling any of the published inotify
+ * interfaces.
  */
 
 /*
- * Lifetimes of the three main data structures--inotify_device, inode, and
+ * Lifetimes of the three main data structures--inotify_handle, inode, and
  * inotify_watch--are managed by reference count.
  *
- * inotify_device: Lifetime is from inotify_init() until release.  Additional
- * references can bump the count via get_inotify_dev() and drop the count via
- * put_inotify_dev().
+ * inotify_handle: Lifetime is from inotify_init() to inotify_destroy().
+ * Additional references can bump the count via get_inotify_handle() and drop
+ * the count via put_inotify_handle().
  *
- * inotify_watch: Lifetime is from create_watch() to destory_watch().
- * Additional references can bump the count via get_inotify_watch() and drop
- * the count via put_inotify_watch().
+ * inotify_watch: for inotify's purposes, lifetime is from inotify_add_watch()
+ * to remove_watch_no_event().  Additional references can bump the count via
+ * get_inotify_watch() and drop the count via put_inotify_watch().  The caller
+ * is reponsible for the final put after receiving IN_IGNORED, or when using
+ * IN_ONESHOT after receiving the first event.  Inotify does the final put if
+ * inotify_destroy() is called.
  *
  * inode: Pinned so long as the inode is associated with a watch, from
- * create_watch() to put_inotify_watch().
+ * inotify_add_watch() to the final put_inotify_watch().
  */
 
 /*
- * struct inotify_device - represents an inotify instance
+ * struct inotify_handle - represents an inotify instance
  *
  * This structure is protected by the mutex 'mutex'.
  */
-struct inotify_device {
-       wait_queue_head_t       wq;             /* wait queue for i/o */
+struct inotify_handle {
        struct idr              idr;            /* idr mapping wd -> watch */
        struct mutex            mutex;          /* protects this bad boy */
-       struct list_head        events;         /* list of queued events */
        struct list_head        watches;        /* list of watches */
        atomic_t                count;          /* reference count */
-       struct user_struct      *user;          /* user who opened this dev */
-       unsigned int            queue_size;     /* size of the queue (bytes) */
-       unsigned int            event_count;    /* number of pending events */
-       unsigned int            max_events;     /* maximum number of events */
        u32                     last_wd;        /* the last wd allocated */
+       const struct inotify_operations *in_ops; /* inotify caller operations */
 };
 
-/*
- * struct inotify_kernel_event - An inotify event, originating from a watch and
- * queued for user-space.  A list of these is attached to each instance of the
- * device.  In read(), this list is walked and all events that can fit in the
- * buffer are returned.
- *
- * Protected by dev->mutex of the device in which we are queued.
- */
-struct inotify_kernel_event {
-       struct inotify_event    event;  /* the user-space event */
-       struct list_head        list;   /* entry in inotify_device's list */
-       char                    *name;  /* filename, if any */
-};
-
-/*
- * struct inotify_watch - represents a watch request on a specific inode
- *
- * d_list is protected by dev->mutex of the associated watch->dev.
- * i_list and mask are protected by inode->inotify_mutex of the associated inode.
- * dev, inode, and wd are never written to once the watch is created.
- */
-struct inotify_watch {
-       struct list_head        d_list; /* entry in inotify_device's list */
-       struct list_head        i_list; /* entry in inode's list */
-       atomic_t                count;  /* reference count */
-       struct inotify_device   *dev;   /* associated device */
-       struct inode            *inode; /* associated inode */
-       s32                     wd;     /* watch descriptor */
-       u32                     mask;   /* event mask for this watch */
-};
-
-#ifdef CONFIG_SYSCTL
-
-#include <linux/sysctl.h>
-
-static int zero;
-
-ctl_table inotify_table[] = {
-       {
-               .ctl_name       = INOTIFY_MAX_USER_INSTANCES,
-               .procname       = "max_user_instances",
-               .data           = &inotify_max_user_instances,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec,
-               .extra1         = &zero,
-       },
-       {
-               .ctl_name       = INOTIFY_MAX_USER_WATCHES,
-               .procname       = "max_user_watches",
-               .data           = &inotify_max_user_watches,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec,
-               .extra1         = &zero, 
-       },
-       {
-               .ctl_name       = INOTIFY_MAX_QUEUED_EVENTS,
-               .procname       = "max_queued_events",
-               .data           = &inotify_max_queued_events,
-               .maxlen         = sizeof(int),
-               .mode           = 0644, 
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec, 
-               .extra1         = &zero
-       },
-       { .ctl_name = 0 }
-};
-#endif /* CONFIG_SYSCTL */
-
-static inline void get_inotify_dev(struct inotify_device *dev)
+static inline void get_inotify_handle(struct inotify_handle *ih)
 {
-       atomic_inc(&dev->count);
+       atomic_inc(&ih->count);
 }
 
-static inline void put_inotify_dev(struct inotify_device *dev)
+static inline void put_inotify_handle(struct inotify_handle *ih)
 {
-       if (atomic_dec_and_test(&dev->count)) {
-               atomic_dec(&dev->user->inotify_devs);
-               free_uid(dev->user);
-               idr_destroy(&dev->idr);
-               kfree(dev);
+       if (atomic_dec_and_test(&ih->count)) {
+               idr_destroy(&ih->idr);
+               kfree(ih);
        }
 }
 
-static inline void get_inotify_watch(struct inotify_watch *watch)
+/**
+ * get_inotify_watch - grab a reference to an inotify_watch
+ * @watch: watch to grab
+ */
+void get_inotify_watch(struct inotify_watch *watch)
 {
        atomic_inc(&watch->count);
 }
+EXPORT_SYMBOL_GPL(get_inotify_watch);
 
-/*
+/**
  * put_inotify_watch - decrements the ref count on a given watch.  cleans up
- * the watch and its references if the count reaches zero.
+ * watch references if the count reaches zero.  inotify_watch is freed by
+ * inotify callers via the destroy_watch() op.
+ * @watch: watch to release
  */
-static inline void put_inotify_watch(struct inotify_watch *watch)
+void put_inotify_watch(struct inotify_watch *watch)
 {
        if (atomic_dec_and_test(&watch->count)) {
-               put_inotify_dev(watch->dev);
-               iput(watch->inode);
-               kmem_cache_free(watch_cachep, watch);
-       }
-}
-
-/*
- * kernel_event - create a new kernel event with the given parameters
- *
- * This function can sleep.
- */
-static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
-                                                 const char *name)
-{
-       struct inotify_kernel_event *kevent;
-
-       kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL);
-       if (unlikely(!kevent))
-               return NULL;
-
-       /* we hand this out to user-space, so zero it just in case */
-       memset(&kevent->event, 0, sizeof(struct inotify_event));
-
-       kevent->event.wd = wd;
-       kevent->event.mask = mask;
-       kevent->event.cookie = cookie;
-
-       INIT_LIST_HEAD(&kevent->list);
-
-       if (name) {
-               size_t len, rem, event_size = sizeof(struct inotify_event);
-
-               /*
-                * We need to pad the filename so as to properly align an
-                * array of inotify_event structures.  Because the structure is
-                * small and the common case is a small filename, we just round
-                * up to the next multiple of the structure's sizeof.  This is
-                * simple and safe for all architectures.
-                */
-               len = strlen(name) + 1;
-               rem = event_size - len;
-               if (len > event_size) {
-                       rem = event_size - (len % event_size);
-                       if (len % event_size == 0)
-                               rem = 0;
-               }
-
-               kevent->name = kmalloc(len + rem, GFP_KERNEL);
-               if (unlikely(!kevent->name)) {
-                       kmem_cache_free(event_cachep, kevent);
-                       return NULL;
-               }
-               memcpy(kevent->name, name, len);
-               if (rem)
-                       memset(kevent->name + len, 0, rem);             
-               kevent->event.len = len + rem;
-       } else {
-               kevent->event.len = 0;
-               kevent->name = NULL;
-       }
-
-       return kevent;
-}
-
-/*
- * inotify_dev_get_event - return the next event in the given dev's queue
- *
- * Caller must hold dev->mutex.
- */
-static inline struct inotify_kernel_event *
-inotify_dev_get_event(struct inotify_device *dev)
-{
-       return list_entry(dev->events.next, struct inotify_kernel_event, list);
-}
-
-/*
- * inotify_dev_queue_event - add a new event to the given device
- *
- * Caller must hold dev->mutex.  Can sleep (calls kernel_event()).
- */
-static void inotify_dev_queue_event(struct inotify_device *dev,
-                                   struct inotify_watch *watch, u32 mask,
-                                   u32 cookie, const char *name)
-{
-       struct inotify_kernel_event *kevent, *last;
-
-       /* coalescing: drop this event if it is a dupe of the previous */
-       last = inotify_dev_get_event(dev);
-       if (last && last->event.mask == mask && last->event.wd == watch->wd &&
-                       last->event.cookie == cookie) {
-               const char *lastname = last->name;
-
-               if (!name && !lastname)
-                       return;
-               if (name && lastname && !strcmp(lastname, name))
-                       return;
-       }
-
-       /* the queue overflowed and we already sent the Q_OVERFLOW event */
-       if (unlikely(dev->event_count > dev->max_events))
-               return;
-
-       /* if the queue overflows, we need to notify user space */
-       if (unlikely(dev->event_count == dev->max_events))
-               kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL);
-       else
-               kevent = kernel_event(watch->wd, mask, cookie, name);
-
-       if (unlikely(!kevent))
-               return;
-
-       /* queue the event and wake up anyone waiting */
-       dev->event_count++;
-       dev->queue_size += sizeof(struct inotify_event) + kevent->event.len;
-       list_add_tail(&kevent->list, &dev->events);
-       wake_up_interruptible(&dev->wq);
-}
-
-/*
- * remove_kevent - cleans up and ultimately frees the given kevent
- *
- * Caller must hold dev->mutex.
- */
-static void remove_kevent(struct inotify_device *dev,
-                         struct inotify_kernel_event *kevent)
-{
-       list_del(&kevent->list);
-
-       dev->event_count--;
-       dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len;
-
-       kfree(kevent->name);
-       kmem_cache_free(event_cachep, kevent);
-}
+               struct inotify_handle *ih = watch->ih;
 
-/*
- * inotify_dev_event_dequeue - destroy an event on the given device
- *
- * Caller must hold dev->mutex.
- */
-static void inotify_dev_event_dequeue(struct inotify_device *dev)
-{
-       if (!list_empty(&dev->events)) {
-               struct inotify_kernel_event *kevent;
-               kevent = inotify_dev_get_event(dev);
-               remove_kevent(dev, kevent);
+               iput(watch->inode);
+               ih->in_ops->destroy_watch(watch);
+               put_inotify_handle(ih);
        }
 }
+EXPORT_SYMBOL_GPL(put_inotify_watch);
 
 /*
- * inotify_dev_get_wd - returns the next WD for use by the given dev
+ * inotify_handle_get_wd - returns the next WD for use by the given handle
  *
- * Callers must hold dev->mutex.  This function can sleep.
+ * Callers must hold ih->mutex.  This function can sleep.
  */
-static int inotify_dev_get_wd(struct inotify_device *dev,
-                             struct inotify_watch *watch)
+static int inotify_handle_get_wd(struct inotify_handle *ih,
+                                struct inotify_watch *watch)
 {
        int ret;
 
        do {
-               if (unlikely(!idr_pre_get(&dev->idr, GFP_KERNEL)))
+               if (unlikely(!idr_pre_get(&ih->idr, GFP_KERNEL)))
                        return -ENOSPC;
-               ret = idr_get_new_above(&dev->idr, watch, dev->last_wd+1, &watch->wd);
+               ret = idr_get_new_above(&ih->idr, watch, ih->last_wd+1, &watch->wd);
        } while (ret == -EAGAIN);
 
-       return ret;
-}
+       if (likely(!ret))
+               ih->last_wd = watch->wd;
 
-/*
- * find_inode - resolve a user-given path to a specific inode and return a nd
- */
-static int find_inode(const char __user *dirname, struct nameidata *nd,
-                     unsigned flags)
-{
-       int error;
-
-       error = __user_walk(dirname, flags, nd);
-       if (error)
-               return error;
-       /* you can only watch an inode if you have read permissions on it */
-       error = vfs_permission(nd, MAY_READ);
-       if (error) 
-               path_release(nd);
-       return error;
+       return ret;
 }
 
 /*
@@ -422,67 +188,18 @@ static void set_dentry_child_flags(struct inode *inode, int watched)
 }
 
 /*
- * create_watch - creates a watch on the given device.
- *
- * Callers must hold dev->mutex.  Calls inotify_dev_get_wd() so may sleep.
- * Both 'dev' and 'inode' (by way of nameidata) need to be pinned.
- */
-static struct inotify_watch *create_watch(struct inotify_device *dev,
-                                         u32 mask, struct inode *inode)
-{
-       struct inotify_watch *watch;
-       int ret;
-
-       if (atomic_read(&dev->user->inotify_watches) >=
-                       inotify_max_user_watches)
-               return ERR_PTR(-ENOSPC);
-
-       watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL);
-       if (unlikely(!watch))
-               return ERR_PTR(-ENOMEM);
-
-       ret = inotify_dev_get_wd(dev, watch);
-       if (unlikely(ret)) {
-               kmem_cache_free(watch_cachep, watch);
-               return ERR_PTR(ret);
-       }
-
-       dev->last_wd = watch->wd;
-       watch->mask = mask;
-       atomic_set(&watch->count, 0);
-       INIT_LIST_HEAD(&watch->d_list);
-       INIT_LIST_HEAD(&watch->i_list);
-
-       /* save a reference to device and bump the count to make it official */
-       get_inotify_dev(dev);
-       watch->dev = dev;
-
-       /*
-        * Save a reference to the inode and bump the ref count to make it
-        * official.  We hold a reference to nameidata, which makes this safe.
-        */
-       watch->inode = igrab(inode);
-
-       /* bump our own count, corresponding to our entry in dev->watches */
-       get_inotify_watch(watch);
-
-       atomic_inc(&dev->user->inotify_watches);
-
-       return watch;
-}
-
-/*
- * inotify_find_dev - find the watch associated with the given inode and dev
+ * inotify_find_handle - find the watch associated with the given inode and
+ * handle
  *
  * Callers must hold inode->inotify_mutex.
  */
-static struct inotify_watch *inode_find_dev(struct inode *inode,
-                                           struct inotify_device *dev)
+static struct inotify_watch *inode_find_handle(struct inode *inode,
+                                              struct inotify_handle *ih)
 {
        struct inotify_watch *watch;
 
        list_for_each_entry(watch, &inode->inotify_watches, i_list) {
-               if (watch->dev == dev)
+               if (watch->ih == ih)
                        return watch;
        }
 
@@ -490,40 +207,40 @@ static struct inotify_watch *inode_find_dev(struct inode *inode,
 }
 
 /*
- * remove_watch_no_event - remove_watch() without the IN_IGNORED event.
+ * remove_watch_no_event - remove watch without the IN_IGNORED event.
+ *
+ * Callers must hold both inode->inotify_mutex and ih->mutex.
  */
 static void remove_watch_no_event(struct inotify_watch *watch,
-                                 struct inotify_device *dev)
+                                 struct inotify_handle *ih)
 {
        list_del(&watch->i_list);
-       list_del(&watch->d_list);
+       list_del(&watch->h_list);
 
        if (!inotify_inode_watched(watch->inode))
                set_dentry_child_flags(watch->inode, 0);
 
-       atomic_dec(&dev->user->inotify_watches);
-       idr_remove(&dev->idr, watch->wd);
-       put_inotify_watch(watch);
+       idr_remove(&ih->idr, watch->wd);
 }
 
-/*
- * remove_watch - Remove a watch from both the device and the inode.  Sends
- * the IN_IGNORED event to the given device signifying that the inode is no
- * longer watched.
- *
- * Callers must hold both inode->inotify_mutex and dev->mutex.  We drop a
- * reference to the inode before returning.
+/**
+ * inotify_remove_watch_locked - Remove a watch from both the handle and the
+ * inode.  Sends the IN_IGNORED event signifying that the inode is no longer
+ * watched.  May be invoked from a caller's event handler.
+ * @ih: inotify handle associated with watch
+ * @watch: watch to remove
  *
- * The inode is not iput() so as to remain atomic.  If the inode needs to be
- * iput(), the call returns one.  Otherwise, it returns zero.
+ * Callers must hold both inode->inotify_mutex and ih->mutex.
  */
-static void remove_watch(struct inotify_watch *watch,struct inotify_device *dev)
+void inotify_remove_watch_locked(struct inotify_handle *ih,
+                                struct inotify_watch *watch)
 {
-       inotify_dev_queue_event(dev, watch, IN_IGNORED, 0, NULL);
-       remove_watch_no_event(watch, dev);
+       remove_watch_no_event(watch, ih);
+       ih->in_ops->handle_event(watch, watch->wd, IN_IGNORED, 0, NULL, NULL);
 }
+EXPORT_SYMBOL_GPL(inotify_remove_watch_locked);
 
-/* Kernel API */
+/* Kernel API for producing events */
 
 /*
  * inotify_d_instantiate - instantiate dcache entry for inode
@@ -563,9 +280,10 @@ void inotify_d_move(struct dentry *entry)
  * @mask: event mask describing this event
  * @cookie: cookie for synchronization, or zero
  * @name: filename, if any
+ * @n_inode: inode associated with name
  */
 void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie,
-                              const char *name)
+                              const char *name, struct inode *n_inode)
 {
        struct inotify_watch *watch, *next;
 
@@ -576,14 +294,13 @@ void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie,
        list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) {
                u32 watch_mask = watch->mask;
                if (watch_mask & mask) {
-                       struct inotify_device *dev = watch->dev;
-                       get_inotify_watch(watch);
-                       mutex_lock(&dev->mutex);
-                       inotify_dev_queue_event(dev, watch, mask, cookie, name);
+                       struct inotify_handle *ih= watch->ih;
+                       mutex_lock(&ih->mutex);
                        if (watch_mask & IN_ONESHOT)
-                               remove_watch_no_event(watch, dev);
-                       mutex_unlock(&dev->mutex);
-                       put_inotify_watch(watch);
+                               remove_watch_no_event(watch, ih);
+                       ih->in_ops->handle_event(watch, watch->wd, mask, cookie,
+                                                name, n_inode);
+                       mutex_unlock(&ih->mutex);
                }
        }
        mutex_unlock(&inode->inotify_mutex);
@@ -613,7 +330,8 @@ void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask,
        if (inotify_inode_watched(inode)) {
                dget(parent);
                spin_unlock(&dentry->d_lock);
-               inotify_inode_queue_event(inode, mask, cookie, name);
+               inotify_inode_queue_event(inode, mask, cookie, name,
+                                         dentry->d_inode);
                dput(parent);
        } else
                spin_unlock(&dentry->d_lock);
@@ -665,7 +383,7 @@ void inotify_unmount_inodes(struct list_head *list)
 
                need_iput_tmp = need_iput;
                need_iput = NULL;
-               /* In case the remove_watch() drops a reference. */
+               /* In case inotify_remove_watch_locked() drops a reference. */
                if (inode != need_iput_tmp)
                        __iget(inode);
                else
@@ -694,11 +412,12 @@ void inotify_unmount_inodes(struct list_head *list)
                mutex_lock(&inode->inotify_mutex);
                watches = &inode->inotify_watches;
                list_for_each_entry_safe(watch, next_w, watches, i_list) {
-                       struct inotify_device *dev = watch->dev;
-                       mutex_lock(&dev->mutex);
-                       inotify_dev_queue_event(dev, watch, IN_UNMOUNT,0,NULL);
-                       remove_watch(watch, dev);
-                       mutex_unlock(&dev->mutex);
+                       struct inotify_handle *ih= watch->ih;
+                       mutex_lock(&ih->mutex);
+                       ih->in_ops->handle_event(watch, watch->wd, IN_UNMOUNT, 0,
+                                                NULL, NULL);
+                       inotify_remove_watch_locked(ih, watch);
+                       mutex_unlock(&ih->mutex);
                }
                mutex_unlock(&inode->inotify_mutex);
                iput(inode);            
@@ -718,432 +437,292 @@ void inotify_inode_is_dead(struct inode *inode)
 
        mutex_lock(&inode->inotify_mutex);
        list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) {
-               struct inotify_device *dev = watch->dev;
-               mutex_lock(&dev->mutex);
-               remove_watch(watch, dev);
-               mutex_unlock(&dev->mutex);
+               struct inotify_handle *ih = watch->ih;
+               mutex_lock(&ih->mutex);
+               inotify_remove_watch_locked(ih, watch);
+               mutex_unlock(&ih->mutex);
        }
        mutex_unlock(&inode->inotify_mutex);
 }
 EXPORT_SYMBOL_GPL(inotify_inode_is_dead);
 
-/* Device Interface */
+/* Kernel Consumer API */
 
-static unsigned int inotify_poll(struct file *file, poll_table *wait)
+/**
+ * inotify_init - allocate and initialize an inotify instance
+ * @ops: caller's inotify operations
+ */
+struct inotify_handle *inotify_init(const struct inotify_operations *ops)
 {
-       struct inotify_device *dev = file->private_data;
-       int ret = 0;
+       struct inotify_handle *ih;
 
-       poll_wait(file, &dev->wq, wait);
-       mutex_lock(&dev->mutex);
-       if (!list_empty(&dev->events))
-               ret = POLLIN | POLLRDNORM;
-       mutex_unlock(&dev->mutex);
+       ih = kmalloc(sizeof(struct inotify_handle), GFP_KERNEL);
+       if (unlikely(!ih))
+               return ERR_PTR(-ENOMEM);
 
-       return ret;
+       idr_init(&ih->idr);
+       INIT_LIST_HEAD(&ih->watches);
+       mutex_init(&ih->mutex);
+       ih->last_wd = 0;
+       ih->in_ops = ops;
+       atomic_set(&ih->count, 0);
+       get_inotify_handle(ih);
+
+       return ih;
 }
+EXPORT_SYMBOL_GPL(inotify_init);
 
-static ssize_t inotify_read(struct file *file, char __user *buf,
-                           size_t count, loff_t *pos)
+/**
+ * inotify_init_watch - initialize an inotify watch
+ * @watch: watch to initialize
+ */
+void inotify_init_watch(struct inotify_watch *watch)
 {
-       size_t event_size = sizeof (struct inotify_event);
-       struct inotify_device *dev;
-       char __user *start;
-       int ret;
-       DEFINE_WAIT(wait);
-
-       start = buf;
-       dev = file->private_data;
-
-       while (1) {
-               int events;
-
-               prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
-
-               mutex_lock(&dev->mutex);
-               events = !list_empty(&dev->events);
-               mutex_unlock(&dev->mutex);
-               if (events) {
-                       ret = 0;
-                       break;
-               }
-
-               if (file->f_flags & O_NONBLOCK) {
-                       ret = -EAGAIN;
-                       break;
-               }
-
-               if (signal_pending(current)) {
-                       ret = -EINTR;
-                       break;
-               }
-
-               schedule();
-       }
-
-       finish_wait(&dev->wq, &wait);
-       if (ret)
-               return ret;
-
-       mutex_lock(&dev->mutex);
-       while (1) {
-               struct inotify_kernel_event *kevent;
-
-               ret = buf - start;
-               if (list_empty(&dev->events))
-                       break;
-
-               kevent = inotify_dev_get_event(dev);
-               if (event_size + kevent->event.len > count)
-                       break;
-
-               if (copy_to_user(buf, &kevent->event, event_size)) {
-                       ret = -EFAULT;
-                       break;
-               }
-               buf += event_size;
-               count -= event_size;
-
-               if (kevent->name) {
-                       if (copy_to_user(buf, kevent->name, kevent->event.len)){
-                               ret = -EFAULT;
-                               break;
-                       }
-                       buf += kevent->event.len;
-                       count -= kevent->event.len;
-               }
-
-               remove_kevent(dev, kevent);
-       }
-       mutex_unlock(&dev->mutex);
-
-       return ret;
+       INIT_LIST_HEAD(&watch->h_list);
+       INIT_LIST_HEAD(&watch->i_list);
+       atomic_set(&watch->count, 0);
+       get_inotify_watch(watch); /* initial get */
 }
+EXPORT_SYMBOL_GPL(inotify_init_watch);
 
-static int inotify_release(struct inode *ignored, struct file *file)
+/**
+ * inotify_destroy - clean up and destroy an inotify instance
+ * @ih: inotify handle
+ */
+void inotify_destroy(struct inotify_handle *ih)
 {
-       struct inotify_device *dev = file->private_data;
-
        /*
-        * Destroy all of the watches on this device.  Unfortunately, not very
+        * Destroy all of the watches for this handle. Unfortunately, not very
         * pretty.  We cannot do a simple iteration over the list, because we
         * do not know the inode until we iterate to the watch.  But we need to
-        * hold inode->inotify_mutex before dev->mutex.  The following works.
+        * hold inode->inotify_mutex before ih->mutex.  The following works.
         */
        while (1) {
                struct inotify_watch *watch;
                struct list_head *watches;
                struct inode *inode;
 
-               mutex_lock(&dev->mutex);
-               watches = &dev->watches;
+               mutex_lock(&ih->mutex);
+               watches = &ih->watches;
                if (list_empty(watches)) {
-                       mutex_unlock(&dev->mutex);
+                       mutex_unlock(&ih->mutex);
                        break;
                }
-               watch = list_entry(watches->next, struct inotify_watch, d_list);
+               watch = list_entry(watches->next, struct inotify_watch, h_list);
                get_inotify_watch(watch);
-               mutex_unlock(&dev->mutex);
+               mutex_unlock(&ih->mutex);
 
                inode = watch->inode;
                mutex_lock(&inode->inotify_mutex);
-               mutex_lock(&dev->mutex);
+               mutex_lock(&ih->mutex);
 
                /* make sure we didn't race with another list removal */
-               if (likely(idr_find(&dev->idr, watch->wd)))
-                       remove_watch_no_event(watch, dev);
+               if (likely(idr_find(&ih->idr, watch->wd))) {
+                       remove_watch_no_event(watch, ih);
+                       put_inotify_watch(watch);
+               }
 
-               mutex_unlock(&dev->mutex);
+               mutex_unlock(&ih->mutex);
                mutex_unlock(&inode->inotify_mutex);
                put_inotify_watch(watch);
        }
 
-       /* destroy all of the events on this device */
-       mutex_lock(&dev->mutex);
-       while (!list_empty(&dev->events))
-               inotify_dev_event_dequeue(dev);
-       mutex_unlock(&dev->mutex);
-
-       /* free this device: the put matching the get in inotify_init() */
-       put_inotify_dev(dev);
-
-       return 0;
+       /* free this handle: the put matching the get in inotify_init() */
+       put_inotify_handle(ih);
 }
+EXPORT_SYMBOL_GPL(inotify_destroy);
 
-/*
- * inotify_ignore - remove a given wd from this inotify instance.
+/**
+ * inotify_find_watch - find an existing watch for an (ih,inode) pair
+ * @ih: inotify handle
+ * @inode: inode to watch
+ * @watchp: pointer to existing inotify_watch
  *
- * Can sleep.
+ * Caller must pin given inode (via nameidata).
  */
-static int inotify_ignore(struct inotify_device *dev, s32 wd)
+s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode,
+                      struct inotify_watch **watchp)
 {
-       struct inotify_watch *watch;
-       struct inode *inode;
-
-       mutex_lock(&dev->mutex);
-       watch = idr_find(&dev->idr, wd);
-       if (unlikely(!watch)) {
-               mutex_unlock(&dev->mutex);
-               return -EINVAL;
-       }
-       get_inotify_watch(watch);
-       inode = watch->inode;
-       mutex_unlock(&dev->mutex);
+       struct inotify_watch *old;
+       int ret = -ENOENT;
 
        mutex_lock(&inode->inotify_mutex);
-       mutex_lock(&dev->mutex);
+       mutex_lock(&ih->mutex);
 
-       /* make sure that we did not race */
-       if (likely(idr_find(&dev->idr, wd) == watch))
-               remove_watch(watch, dev);
+       old = inode_find_handle(inode, ih);
+       if (unlikely(old)) {
+               get_inotify_watch(old); /* caller must put watch */
+               *watchp = old;
+               ret = old->wd;
+       }
 
-       mutex_unlock(&dev->mutex);
+       mutex_unlock(&ih->mutex);
        mutex_unlock(&inode->inotify_mutex);
-       put_inotify_watch(watch);
 
-       return 0;
+       return ret;
 }
+EXPORT_SYMBOL_GPL(inotify_find_watch);
 
-static long inotify_ioctl(struct file *file, unsigned int cmd,
-                         unsigned long arg)
+/**
+ * inotify_find_update_watch - find and update the mask of an existing watch
+ * @ih: inotify handle
+ * @inode: inode's watch to update
+ * @mask: mask of events to watch
+ *
+ * Caller must pin given inode (via nameidata).
+ */
+s32 inotify_find_update_watch(struct inotify_handle *ih, struct inode *inode,
+                             u32 mask)
 {
-       struct inotify_device *dev;
-       void __user *p;
-       int ret = -ENOTTY;
-
-       dev = file->private_data;
-       p = (void __user *) arg;
-
-       switch (cmd) {
-       case FIONREAD:
-               ret = put_user(dev->queue_size, (int __user *) p);
-               break;
-       }
-
-       return ret;
-}
+       struct inotify_watch *old;
+       int mask_add = 0;
+       int ret;
 
-static const struct file_operations inotify_fops = {
-       .poll           = inotify_poll,
-       .read           = inotify_read,
-       .release        = inotify_release,
-       .unlocked_ioctl = inotify_ioctl,
-       .compat_ioctl   = inotify_ioctl,
-};
+       if (mask & IN_MASK_ADD)
+               mask_add = 1;
 
-asmlinkage long sys_inotify_init(void)
-{
-       struct inotify_device *dev;
-       struct user_struct *user;
-       struct file *filp;      
-       int fd, ret;
-
-       fd = get_unused_fd();
-       if (fd < 0)
-               return fd;
-
-       filp = get_empty_filp();
-       if (!filp) {
-               ret = -ENFILE;
-               goto out_put_fd;
-       }
+       /* don't allow invalid bits: we don't want flags set */
+       mask &= IN_ALL_EVENTS | IN_ONESHOT;
+       if (unlikely(!mask))
+               return -EINVAL;
 
-       user = get_uid(current->user);
-       if (unlikely(atomic_read(&user->inotify_devs) >=
-                       inotify_max_user_instances)) {
-               ret = -EMFILE;
-               goto out_free_uid;
-       }
+       mutex_lock(&inode->inotify_mutex);
+       mutex_lock(&ih->mutex);
 
-       dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
-       if (unlikely(!dev)) {
-               ret = -ENOMEM;
-               goto out_free_uid;
+       /*
+        * Handle the case of re-adding a watch on an (inode,ih) pair that we
+        * are already watching.  We just update the mask and return its wd.
+        */
+       old = inode_find_handle(inode, ih);
+       if (unlikely(!old)) {
+               ret = -ENOENT;
+               goto out;
        }
 
-       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_mode = FMODE_READ;
-       filp->f_flags = O_RDONLY;
-       filp->private_data = dev;
-
-       idr_init(&dev->idr);
-       INIT_LIST_HEAD(&dev->events);
-       INIT_LIST_HEAD(&dev->watches);
-       init_waitqueue_head(&dev->wq);
-       mutex_init(&dev->mutex);
-       dev->event_count = 0;
-       dev->queue_size = 0;
-       dev->max_events = inotify_max_queued_events;
-       dev->user = user;
-       dev->last_wd = 0;
-       atomic_set(&dev->count, 0);
-
-       get_inotify_dev(dev);
-       atomic_inc(&user->inotify_devs);
-       fd_install(fd, filp);
-
-       return fd;
-out_free_uid:
-       free_uid(user);
-       put_filp(filp);
-out_put_fd:
-       put_unused_fd(fd);
+       if (mask_add)
+               old->mask |= mask;
+       else
+               old->mask = mask;
+       ret = old->wd;
+out:
+       mutex_unlock(&ih->mutex);
+       mutex_unlock(&inode->inotify_mutex);
        return ret;
 }
+EXPORT_SYMBOL_GPL(inotify_find_update_watch);
 
-asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
+/**
+ * inotify_add_watch - add a watch to an inotify instance
+ * @ih: inotify handle
+ * @watch: caller allocated watch structure
+ * @inode: inode to watch
+ * @mask: mask of events to watch
+ *
+ * Caller must pin given inode (via nameidata).
+ * Caller must ensure it only calls inotify_add_watch() once per watch.
+ * Calls inotify_handle_get_wd() so may sleep.
+ */
+s32 inotify_add_watch(struct inotify_handle *ih, struct inotify_watch *watch,
+                     struct inode *inode, u32 mask)
 {
-       struct inotify_watch *watch, *old;
-       struct inode *inode;
-       struct inotify_device *dev;
-       struct nameidata nd;
-       struct file *filp;
-       int ret, fput_needed;
-       int mask_add = 0;
-       unsigned flags = 0;
-
-       filp = fget_light(fd, &fput_needed);
-       if (unlikely(!filp))
-               return -EBADF;
-
-       /* verify that this is indeed an inotify instance */
-       if (unlikely(filp->f_op != &inotify_fops)) {
-               ret = -EINVAL;
-               goto fput_and_out;
-       }
-
-       if (!(mask & IN_DONT_FOLLOW))
-               flags |= LOOKUP_FOLLOW;
-       if (mask & IN_ONLYDIR)
-               flags |= LOOKUP_DIRECTORY;
-
-       ret = find_inode(path, &nd, flags);
-       if (unlikely(ret))
-               goto fput_and_out;
+       int ret = 0;
 
-       /* inode held in place by reference to nd; dev by fget on fd */
-       inode = nd.dentry->d_inode;
-       dev = filp->private_data;
+       /* don't allow invalid bits: we don't want flags set */
+       mask &= IN_ALL_EVENTS | IN_ONESHOT;
+       if (unlikely(!mask))
+               return -EINVAL;
+       watch->mask = mask;
 
        mutex_lock(&inode->inotify_mutex);
-       mutex_lock(&dev->mutex);
-
-       if (mask & IN_MASK_ADD)
-               mask_add = 1;
+       mutex_lock(&ih->mutex);
 
-       /* don't let user-space set invalid bits: we don't want flags set */
-       mask &= IN_ALL_EVENTS | IN_ONESHOT;
-       if (unlikely(!mask)) {
-               ret = -EINVAL;
+       /* Initialize a new watch */
+       ret = inotify_handle_get_wd(ih, watch);
+       if (unlikely(ret))
                goto out;
-       }
+       ret = watch->wd;
+
+       /* save a reference to handle and bump the count to make it official */
+       get_inotify_handle(ih);
+       watch->ih = ih;
 
        /*
-        * Handle the case of re-adding a watch on an (inode,dev) pair that we
-        * are already watching.  We just update the mask and return its wd.
+        * Save a reference to the inode and bump the ref count to make it
+        * official.  We hold a reference to nameidata, which makes this safe.
         */
-       old = inode_find_dev(inode, dev);
-       if (unlikely(old)) {
-               if (mask_add)
-                       old->mask |= mask;
-               else
-                       old->mask = mask;
-               ret = old->wd;
-               goto out;
-       }
-
-       watch = create_watch(dev, mask, inode);
-       if (unlikely(IS_ERR(watch))) {
-               ret = PTR_ERR(watch);
-               goto out;
-       }
+       watch->inode = igrab(inode);
 
        if (!inotify_inode_watched(inode))
                set_dentry_child_flags(inode, 1);
 
-       /* Add the watch to the device's and the inode's list */
-       list_add(&watch->d_list, &dev->watches);
+       /* Add the watch to the handle's and the inode's list */
+       list_add(&watch->h_list, &ih->watches);
        list_add(&watch->i_list, &inode->inotify_watches);
-       ret = watch->wd;
 out:
-       mutex_unlock(&dev->mutex);
+       mutex_unlock(&ih->mutex);
        mutex_unlock(&inode->inotify_mutex);
-       path_release(&nd);
-fput_and_out:
-       fput_light(filp, fput_needed);
        return ret;
 }
+EXPORT_SYMBOL_GPL(inotify_add_watch);
 
-asmlinkage long sys_inotify_rm_watch(int fd, u32 wd)
+/**
+ * inotify_rm_wd - remove a watch from an inotify instance
+ * @ih: inotify handle
+ * @wd: watch descriptor to remove
+ *
+ * Can sleep.
+ */
+int inotify_rm_wd(struct inotify_handle *ih, u32 wd)
 {
-       struct file *filp;
-       struct inotify_device *dev;
-       int ret, fput_needed;
-
-       filp = fget_light(fd, &fput_needed);
-       if (unlikely(!filp))
-               return -EBADF;
+       struct inotify_watch *watch;
+       struct inode *inode;
 
-       /* verify that this is indeed an inotify instance */
-       if (unlikely(filp->f_op != &inotify_fops)) {
-               ret = -EINVAL;
-               goto out;
+       mutex_lock(&ih->mutex);
+       watch = idr_find(&ih->idr, wd);
+       if (unlikely(!watch)) {
+               mutex_unlock(&ih->mutex);
+               return -EINVAL;
        }
+       get_inotify_watch(watch);
+       inode = watch->inode;
+       mutex_unlock(&ih->mutex);
 
-       dev = filp->private_data;
-       ret = inotify_ignore(dev, wd);
+       mutex_lock(&inode->inotify_mutex);
+       mutex_lock(&ih->mutex);
 
-out:
-       fput_light(filp, fput_needed);
-       return ret;
+       /* make sure that we did not race */
+       if (likely(idr_find(&ih->idr, wd) == watch))
+               inotify_remove_watch_locked(ih, watch);
+
+       mutex_unlock(&ih->mutex);
+       mutex_unlock(&inode->inotify_mutex);
+       put_inotify_watch(watch);
+
+       return 0;
 }
+EXPORT_SYMBOL_GPL(inotify_rm_wd);
 
-static struct super_block *
-inotify_get_sb(struct file_system_type *fs_type, int flags,
-              const char *dev_name, void *data)
+/**
+ * inotify_rm_watch - remove a watch from an inotify instance
+ * @ih: inotify handle
+ * @watch: watch to remove
+ *
+ * Can sleep.
+ */
+int inotify_rm_watch(struct inotify_handle *ih,
+                    struct inotify_watch *watch)
 {
-    return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA);
+       return inotify_rm_wd(ih, watch->wd);
 }
-
-static struct file_system_type inotify_fs_type = {
-    .name           = "inotifyfs",
-    .get_sb         = inotify_get_sb,
-    .kill_sb        = kill_anon_super,
-};
+EXPORT_SYMBOL_GPL(inotify_rm_watch);
 
 /*
- * inotify_setup - Our initialization function.  Note that we cannnot return
- * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
- * must result in panic().
+ * inotify_setup - core initialization function
  */
 static int __init inotify_setup(void)
 {
-       int ret;
-
-       ret = register_filesystem(&inotify_fs_type);
-       if (unlikely(ret))
-               panic("inotify: register_filesystem returned %d!\n", ret);
-
-       inotify_mnt = kern_mount(&inotify_fs_type);
-       if (IS_ERR(inotify_mnt))
-               panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt));
-
-       inotify_max_queued_events = 16384;
-       inotify_max_user_instances = 128;
-       inotify_max_user_watches = 8192;
-
        atomic_set(&inotify_cookie, 0);
 
-       watch_cachep = kmem_cache_create("inotify_watch_cache",
-                                        sizeof(struct inotify_watch),
-                                        0, SLAB_PANIC, NULL, NULL);
-       event_cachep = kmem_cache_create("inotify_event_cache",
-                                        sizeof(struct inotify_kernel_event),
-                                        0, SLAB_PANIC, NULL, NULL);
-
        return 0;
 }
 
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
new file mode 100644 (file)
index 0000000..9e9931e
--- /dev/null
@@ -0,0 +1,719 @@
+/*
+ * fs/inotify_user.c - inotify support for userspace
+ *
+ * Authors:
+ *     John McCutchan  <ttb@tentacle.dhs.org>
+ *     Robert Love     <rml@novell.com>
+ *
+ * Copyright (C) 2005 John McCutchan
+ * Copyright 2006 Hewlett-Packard Development Company, L.P.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/inotify.h>
+#include <linux/syscalls.h>
+
+#include <asm/ioctls.h>
+
+static kmem_cache_t *watch_cachep __read_mostly;
+static kmem_cache_t *event_cachep __read_mostly;
+
+static struct vfsmount *inotify_mnt __read_mostly;
+
+/* these are configurable via /proc/sys/fs/inotify/ */
+int inotify_max_user_instances __read_mostly;
+int inotify_max_user_watches __read_mostly;
+int inotify_max_queued_events __read_mostly;
+
+/*
+ * Lock ordering:
+ *
+ * inotify_dev->up_mutex (ensures we don't re-add the same watch)
+ *     inode->inotify_mutex (protects inode's watch list)
+ *             inotify_handle->mutex (protects inotify_handle's watch list)
+ *                     inotify_dev->ev_mutex (protects device's event queue)
+ */
+
+/*
+ * Lifetimes of the main data structures:
+ *
+ * inotify_device: Lifetime is managed by reference count, from
+ * sys_inotify_init() until release.  Additional references can bump the count
+ * via get_inotify_dev() and drop the count via put_inotify_dev().
+ *
+ * inotify_user_watch: Lifetime is from create_watch() to the receipt of an
+ * IN_IGNORED event from inotify, or when using IN_ONESHOT, to receipt of the
+ * first event, or to inotify_destroy().
+ */
+
+/*
+ * struct inotify_device - represents an inotify instance
+ *
+ * This structure is protected by the mutex 'mutex'.
+ */
+struct inotify_device {
+       wait_queue_head_t       wq;             /* wait queue for i/o */
+       struct mutex            ev_mutex;       /* protects event queue */
+       struct mutex            up_mutex;       /* synchronizes watch updates */
+       struct list_head        events;         /* list of queued events */
+       atomic_t                count;          /* reference count */
+       struct user_struct      *user;          /* user who opened this dev */
+       struct inotify_handle   *ih;            /* inotify handle */
+       unsigned int            queue_size;     /* size of the queue (bytes) */
+       unsigned int            event_count;    /* number of pending events */
+       unsigned int            max_events;     /* maximum number of events */
+};
+
+/*
+ * struct inotify_kernel_event - An inotify event, originating from a watch and
+ * queued for user-space.  A list of these is attached to each instance of the
+ * device.  In read(), this list is walked and all events that can fit in the
+ * buffer are returned.
+ *
+ * Protected by dev->ev_mutex of the device in which we are queued.
+ */
+struct inotify_kernel_event {
+       struct inotify_event    event;  /* the user-space event */
+       struct list_head        list;   /* entry in inotify_device's list */
+       char                    *name;  /* filename, if any */
+};
+
+/*
+ * struct inotify_user_watch - our version of an inotify_watch, we add
+ * a reference to the associated inotify_device.
+ */
+struct inotify_user_watch {
+       struct inotify_device   *dev;   /* associated device */
+       struct inotify_watch    wdata;  /* inotify watch data */
+};
+
+#ifdef CONFIG_SYSCTL
+
+#include <linux/sysctl.h>
+
+static int zero;
+
+ctl_table inotify_table[] = {
+       {
+               .ctl_name       = INOTIFY_MAX_USER_INSTANCES,
+               .procname       = "max_user_instances",
+               .data           = &inotify_max_user_instances,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+       },
+       {
+               .ctl_name       = INOTIFY_MAX_USER_WATCHES,
+               .procname       = "max_user_watches",
+               .data           = &inotify_max_user_watches,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+       },
+       {
+               .ctl_name       = INOTIFY_MAX_QUEUED_EVENTS,
+               .procname       = "max_queued_events",
+               .data           = &inotify_max_queued_events,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero
+       },
+       { .ctl_name = 0 }
+};
+#endif /* CONFIG_SYSCTL */
+
+static inline void get_inotify_dev(struct inotify_device *dev)
+{
+       atomic_inc(&dev->count);
+}
+
+static inline void put_inotify_dev(struct inotify_device *dev)
+{
+       if (atomic_dec_and_test(&dev->count)) {
+               atomic_dec(&dev->user->inotify_devs);
+               free_uid(dev->user);
+               kfree(dev);
+       }
+}
+
+/*
+ * free_inotify_user_watch - cleans up the watch and its references
+ */
+static void free_inotify_user_watch(struct inotify_watch *w)
+{
+       struct inotify_user_watch *watch;
+       struct inotify_device *dev;
+
+       watch = container_of(w, struct inotify_user_watch, wdata);
+       dev = watch->dev;
+
+       atomic_dec(&dev->user->inotify_watches);
+       put_inotify_dev(dev);
+       kmem_cache_free(watch_cachep, watch);
+}
+
+/*
+ * kernel_event - create a new kernel event with the given parameters
+ *
+ * This function can sleep.
+ */
+static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
+                                                 const char *name)
+{
+       struct inotify_kernel_event *kevent;
+
+       kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL);
+       if (unlikely(!kevent))
+               return NULL;
+
+       /* we hand this out to user-space, so zero it just in case */
+       memset(&kevent->event, 0, sizeof(struct inotify_event));
+
+       kevent->event.wd = wd;
+       kevent->event.mask = mask;
+       kevent->event.cookie = cookie;
+
+       INIT_LIST_HEAD(&kevent->list);
+
+       if (name) {
+               size_t len, rem, event_size = sizeof(struct inotify_event);
+
+               /*
+                * We need to pad the filename so as to properly align an
+                * array of inotify_event structures.  Because the structure is
+                * small and the common case is a small filename, we just round
+                * up to the next multiple of the structure's sizeof.  This is
+                * simple and safe for all architectures.
+                */
+               len = strlen(name) + 1;
+               rem = event_size - len;
+               if (len > event_size) {
+                       rem = event_size - (len % event_size);
+                       if (len % event_size == 0)
+                               rem = 0;
+               }
+
+               kevent->name = kmalloc(len + rem, GFP_KERNEL);
+               if (unlikely(!kevent->name)) {
+                       kmem_cache_free(event_cachep, kevent);
+                       return NULL;
+               }
+               memcpy(kevent->name, name, len);
+               if (rem)
+                       memset(kevent->name + len, 0, rem);
+               kevent->event.len = len + rem;
+       } else {
+               kevent->event.len = 0;
+               kevent->name = NULL;
+       }
+
+       return kevent;
+}
+
+/*
+ * inotify_dev_get_event - return the next event in the given dev's queue
+ *
+ * Caller must hold dev->ev_mutex.
+ */
+static inline struct inotify_kernel_event *
+inotify_dev_get_event(struct inotify_device *dev)
+{
+       return list_entry(dev->events.next, struct inotify_kernel_event, list);
+}
+
+/*
+ * inotify_dev_queue_event - event handler registered with core inotify, adds
+ * a new event to the given device
+ *
+ * Can sleep (calls kernel_event()).
+ */
+static void inotify_dev_queue_event(struct inotify_watch *w, u32 wd, u32 mask,
+                                   u32 cookie, const char *name,
+                                   struct inode *ignored)
+{
+       struct inotify_user_watch *watch;
+       struct inotify_device *dev;
+       struct inotify_kernel_event *kevent, *last;
+
+       watch = container_of(w, struct inotify_user_watch, wdata);
+       dev = watch->dev;
+
+       mutex_lock(&dev->ev_mutex);
+
+       /* we can safely put the watch as we don't reference it while
+        * generating the event
+        */
+       if (mask & IN_IGNORED || mask & IN_ONESHOT)
+               put_inotify_watch(w); /* final put */
+
+       /* coalescing: drop this event if it is a dupe of the previous */
+       last = inotify_dev_get_event(dev);
+       if (last && last->event.mask == mask && last->event.wd == wd &&
+                       last->event.cookie == cookie) {
+               const char *lastname = last->name;
+
+               if (!name && !lastname)
+                       goto out;
+               if (name && lastname && !strcmp(lastname, name))
+                       goto out;
+       }
+
+       /* the queue overflowed and we already sent the Q_OVERFLOW event */
+       if (unlikely(dev->event_count > dev->max_events))
+               goto out;
+
+       /* if the queue overflows, we need to notify user space */
+       if (unlikely(dev->event_count == dev->max_events))
+               kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL);
+       else
+               kevent = kernel_event(wd, mask, cookie, name);
+
+       if (unlikely(!kevent))
+               goto out;
+
+       /* queue the event and wake up anyone waiting */
+       dev->event_count++;
+       dev->queue_size += sizeof(struct inotify_event) + kevent->event.len;
+       list_add_tail(&kevent->list, &dev->events);
+       wake_up_interruptible(&dev->wq);
+
+out:
+       mutex_unlock(&dev->ev_mutex);
+}
+
+/*
+ * remove_kevent - cleans up and ultimately frees the given kevent
+ *
+ * Caller must hold dev->ev_mutex.
+ */
+static void remove_kevent(struct inotify_device *dev,
+                         struct inotify_kernel_event *kevent)
+{
+       list_del(&kevent->list);
+
+       dev->event_count--;
+       dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len;
+
+       kfree(kevent->name);
+       kmem_cache_free(event_cachep, kevent);
+}
+
+/*
+ * inotify_dev_event_dequeue - destroy an event on the given device
+ *
+ * Caller must hold dev->ev_mutex.
+ */
+static void inotify_dev_event_dequeue(struct inotify_device *dev)
+{
+       if (!list_empty(&dev->events)) {
+               struct inotify_kernel_event *kevent;
+               kevent = inotify_dev_get_event(dev);
+               remove_kevent(dev, kevent);
+       }
+}
+
+/*
+ * find_inode - resolve a user-given path to a specific inode and return a nd
+ */
+static int find_inode(const char __user *dirname, struct nameidata *nd,
+                     unsigned flags)
+{
+       int error;
+
+       error = __user_walk(dirname, flags, nd);
+       if (error)
+               return error;
+       /* you can only watch an inode if you have read permissions on it */
+       error = vfs_permission(nd, MAY_READ);
+       if (error)
+               path_release(nd);
+       return error;
+}
+
+/*
+ * create_watch - creates a watch on the given device.
+ *
+ * Callers must hold dev->up_mutex.
+ */
+static int create_watch(struct inotify_device *dev, struct inode *inode,
+                       u32 mask)
+{
+       struct inotify_user_watch *watch;
+       int ret;
+
+       if (atomic_read(&dev->user->inotify_watches) >=
+                       inotify_max_user_watches)
+               return -ENOSPC;
+
+       watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL);
+       if (unlikely(!watch))
+               return -ENOMEM;
+
+       /* save a reference to device and bump the count to make it official */
+       get_inotify_dev(dev);
+       watch->dev = dev;
+
+       atomic_inc(&dev->user->inotify_watches);
+
+       inotify_init_watch(&watch->wdata);
+       ret = inotify_add_watch(dev->ih, &watch->wdata, inode, mask);
+       if (ret < 0)
+               free_inotify_user_watch(&watch->wdata);
+
+       return ret;
+}
+
+/* Device Interface */
+
+static unsigned int inotify_poll(struct file *file, poll_table *wait)
+{
+       struct inotify_device *dev = file->private_data;
+       int ret = 0;
+
+       poll_wait(file, &dev->wq, wait);
+       mutex_lock(&dev->ev_mutex);
+       if (!list_empty(&dev->events))
+               ret = POLLIN | POLLRDNORM;
+       mutex_unlock(&dev->ev_mutex);
+
+       return ret;
+}
+
+static ssize_t inotify_read(struct file *file, char __user *buf,
+                           size_t count, loff_t *pos)
+{
+       size_t event_size = sizeof (struct inotify_event);
+       struct inotify_device *dev;
+       char __user *start;
+       int ret;
+       DEFINE_WAIT(wait);
+
+       start = buf;
+       dev = file->private_data;
+
+       while (1) {
+               int events;
+
+               prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
+
+               mutex_lock(&dev->ev_mutex);
+               events = !list_empty(&dev->events);
+               mutex_unlock(&dev->ev_mutex);
+               if (events) {
+                       ret = 0;
+                       break;
+               }
+
+               if (file->f_flags & O_NONBLOCK) {
+                       ret = -EAGAIN;
+                       break;
+               }
+
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
+               }
+
+               schedule();
+       }
+
+       finish_wait(&dev->wq, &wait);
+       if (ret)
+               return ret;
+
+       mutex_lock(&dev->ev_mutex);
+       while (1) {
+               struct inotify_kernel_event *kevent;
+
+               ret = buf - start;
+               if (list_empty(&dev->events))
+                       break;
+
+               kevent = inotify_dev_get_event(dev);
+               if (event_size + kevent->event.len > count)
+                       break;
+
+               if (copy_to_user(buf, &kevent->event, event_size)) {
+                       ret = -EFAULT;
+                       break;
+               }
+               buf += event_size;
+               count -= event_size;
+
+               if (kevent->name) {
+                       if (copy_to_user(buf, kevent->name, kevent->event.len)){
+                               ret = -EFAULT;
+                               break;
+                       }
+                       buf += kevent->event.len;
+                       count -= kevent->event.len;
+               }
+
+               remove_kevent(dev, kevent);
+       }
+       mutex_unlock(&dev->ev_mutex);
+
+       return ret;
+}
+
+static int inotify_release(struct inode *ignored, struct file *file)
+{
+       struct inotify_device *dev = file->private_data;
+
+       inotify_destroy(dev->ih);
+
+       /* destroy all of the events on this device */
+       mutex_lock(&dev->ev_mutex);
+       while (!list_empty(&dev->events))
+               inotify_dev_event_dequeue(dev);
+       mutex_unlock(&dev->ev_mutex);
+
+       /* free this device: the put matching the get in inotify_init() */
+       put_inotify_dev(dev);
+
+       return 0;
+}
+
+static long inotify_ioctl(struct file *file, unsigned int cmd,
+                         unsigned long arg)
+{
+       struct inotify_device *dev;
+       void __user *p;
+       int ret = -ENOTTY;
+
+       dev = file->private_data;
+       p = (void __user *) arg;
+
+       switch (cmd) {
+       case FIONREAD:
+               ret = put_user(dev->queue_size, (int __user *) p);
+               break;
+       }
+
+       return ret;
+}
+
+static const struct file_operations inotify_fops = {
+       .poll           = inotify_poll,
+       .read           = inotify_read,
+       .release        = inotify_release,
+       .unlocked_ioctl = inotify_ioctl,
+       .compat_ioctl   = inotify_ioctl,
+};
+
+static const struct inotify_operations inotify_user_ops = {
+       .handle_event   = inotify_dev_queue_event,
+       .destroy_watch  = free_inotify_user_watch,
+};
+
+asmlinkage long sys_inotify_init(void)
+{
+       struct inotify_device *dev;
+       struct inotify_handle *ih;
+       struct user_struct *user;
+       struct file *filp;
+       int fd, ret;
+
+       fd = get_unused_fd();
+       if (fd < 0)
+               return fd;
+
+       filp = get_empty_filp();
+       if (!filp) {
+               ret = -ENFILE;
+               goto out_put_fd;
+       }
+
+       user = get_uid(current->user);
+       if (unlikely(atomic_read(&user->inotify_devs) >=
+                       inotify_max_user_instances)) {
+               ret = -EMFILE;
+               goto out_free_uid;
+       }
+
+       dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
+       if (unlikely(!dev)) {
+               ret = -ENOMEM;
+               goto out_free_uid;
+       }
+
+       ih = inotify_init(&inotify_user_ops);
+       if (unlikely(IS_ERR(ih))) {
+               ret = PTR_ERR(ih);
+               goto out_free_dev;
+       }
+       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_mode = FMODE_READ;
+       filp->f_flags = O_RDONLY;
+       filp->private_data = dev;
+
+       INIT_LIST_HEAD(&dev->events);
+       init_waitqueue_head(&dev->wq);
+       mutex_init(&dev->ev_mutex);
+       mutex_init(&dev->up_mutex);
+       dev->event_count = 0;
+       dev->queue_size = 0;
+       dev->max_events = inotify_max_queued_events;
+       dev->user = user;
+       atomic_set(&dev->count, 0);
+
+       get_inotify_dev(dev);
+       atomic_inc(&user->inotify_devs);
+       fd_install(fd, filp);
+
+       return fd;
+out_free_dev:
+       kfree(dev);
+out_free_uid:
+       free_uid(user);
+       put_filp(filp);
+out_put_fd:
+       put_unused_fd(fd);
+       return ret;
+}
+
+asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
+{
+       struct inode *inode;
+       struct inotify_device *dev;
+       struct nameidata nd;
+       struct file *filp;
+       int ret, fput_needed;
+       unsigned flags = 0;
+
+       filp = fget_light(fd, &fput_needed);
+       if (unlikely(!filp))
+               return -EBADF;
+
+       /* verify that this is indeed an inotify instance */
+       if (unlikely(filp->f_op != &inotify_fops)) {
+               ret = -EINVAL;
+               goto fput_and_out;
+       }
+
+       if (!(mask & IN_DONT_FOLLOW))
+               flags |= LOOKUP_FOLLOW;
+       if (mask & IN_ONLYDIR)
+               flags |= LOOKUP_DIRECTORY;
+
+       ret = find_inode(path, &nd, flags);
+       if (unlikely(ret))
+               goto fput_and_out;
+
+       /* inode held in place by reference to nd; dev by fget on fd */
+       inode = nd.dentry->d_inode;
+       dev = filp->private_data;
+
+       mutex_lock(&dev->up_mutex);
+       ret = inotify_find_update_watch(dev->ih, inode, mask);
+       if (ret == -ENOENT)
+               ret = create_watch(dev, inode, mask);
+       mutex_unlock(&dev->up_mutex);
+
+       path_release(&nd);
+fput_and_out:
+       fput_light(filp, fput_needed);
+       return ret;
+}
+
+asmlinkage long sys_inotify_rm_watch(int fd, u32 wd)
+{
+       struct file *filp;
+       struct inotify_device *dev;
+       int ret, fput_needed;
+
+       filp = fget_light(fd, &fput_needed);
+       if (unlikely(!filp))
+               return -EBADF;
+
+       /* verify that this is indeed an inotify instance */
+       if (unlikely(filp->f_op != &inotify_fops)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       dev = filp->private_data;
+
+       /* we free our watch data when we get IN_IGNORED */
+       ret = inotify_rm_wd(dev->ih, wd);
+
+out:
+       fput_light(filp, fput_needed);
+       return ret;
+}
+
+static struct super_block *
+inotify_get_sb(struct file_system_type *fs_type, int flags,
+              const char *dev_name, void *data)
+{
+    return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA);
+}
+
+static struct file_system_type inotify_fs_type = {
+    .name           = "inotifyfs",
+    .get_sb         = inotify_get_sb,
+    .kill_sb        = kill_anon_super,
+};
+
+/*
+ * inotify_user_setup - Our initialization function.  Note that we cannnot return
+ * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
+ * must result in panic().
+ */
+static int __init inotify_user_setup(void)
+{
+       int ret;
+
+       ret = register_filesystem(&inotify_fs_type);
+       if (unlikely(ret))
+               panic("inotify: register_filesystem returned %d!\n", ret);
+
+       inotify_mnt = kern_mount(&inotify_fs_type);
+       if (IS_ERR(inotify_mnt))
+               panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt));
+
+       inotify_max_queued_events = 16384;
+       inotify_max_user_instances = 128;
+       inotify_max_user_watches = 8192;
+
+       watch_cachep = kmem_cache_create("inotify_watch_cache",
+                                        sizeof(struct inotify_user_watch),
+                                        0, SLAB_PANIC, NULL, NULL);
+       event_cachep = kmem_cache_create("inotify_event_cache",
+                                        sizeof(struct inotify_kernel_event),
+                                        0, SLAB_PANIC, NULL, NULL);
+
+       return 0;
+}
+
+module_init(inotify_user_setup);
index 0ef207dfaf6f73a42adbbda400e5bb845cac3ed5..5371a403130ae2b95900bc51864e54abc0e7e4df 100644 (file)
@@ -247,7 +247,7 @@ flash_safe_read(struct mtd_info *mtd, loff_t from,
        D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n",
                  mtd, (unsigned int) from, buf, count));
 
-       res = MTD_READ(mtd, from, count, &retlen, buf);
+       res = mtd->read(mtd, from, count, &retlen, buf);
        if (retlen != count) {
                panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res);
        }
@@ -262,7 +262,7 @@ flash_read_u32(struct mtd_info *mtd, loff_t from)
        __u32 ret;
        int res;
 
-       res = MTD_READ(mtd, from, 4, &retlen, (unsigned char *)&ret);
+       res = mtd->read(mtd, from, 4, &retlen, (unsigned char *)&ret);
        if (retlen != 4) {
                printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res);
                return 0;
@@ -282,7 +282,7 @@ flash_safe_write(struct mtd_info *mtd, loff_t to,
        D3(printk(KERN_NOTICE "flash_safe_write(%p, %08x, %p, %08x)\n",
                  mtd, (unsigned int) to, buf, count));
 
-       res = MTD_WRITE(mtd, to, count, &retlen, buf);
+       res = mtd->write(mtd, to, count, &retlen, buf);
        if (retlen != count) {
                printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res);
        }
@@ -300,9 +300,9 @@ flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs,
 
        D3(printk(KERN_NOTICE "flash_safe_writev(%p, %08x, %p)\n",
                  mtd, (unsigned int) to, vecs));
-       
+
        if (mtd->writev) {
-               res = MTD_WRITEV(mtd, vecs, iovec_cnt, to, &retlen);
+               res = mtd->writev(mtd, vecs, iovec_cnt, to, &retlen);
                return res ? res : retlen;
        }
        /* Not implemented writev. Repeatedly use write - on the not so
@@ -312,7 +312,8 @@ flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs,
        retlen=0;
 
        for (i=0; !res && i<iovec_cnt; i++) {
-               res = MTD_WRITE(mtd, to, vecs[i].iov_len, &retlen_a, vecs[i].iov_base);
+               res = mtd->write(mtd, to, vecs[i].iov_len, &retlen_a,
+                                vecs[i].iov_base);
                if (retlen_a != vecs[i].iov_len) {
                        printk("Didn't write all bytes in flash_safe_writev(). Returned %d\n", res);
                        if (i != iovec_cnt-1)
@@ -393,7 +394,7 @@ flash_erase_region(struct mtd_info *mtd, loff_t start,
        set_current_state(TASK_UNINTERRUPTIBLE);
        add_wait_queue(&wait_q, &wait);
 
-       if (MTD_ERASE(mtd, erase) < 0) {
+       if (mtd->erase(mtd, erase) < 0) {
                set_current_state(TASK_RUNNING);
                remove_wait_queue(&wait_q, &wait);
                kfree(erase);
index 77dc5561a04e7def0490e1fa3af3634945726bf0..7f28ee0bd13264c264167232e0f9abfec7d6c236 100644 (file)
@@ -12,6 +12,9 @@ jffs2-y       += symlink.o build.o erase.o background.o fs.o writev.o
 jffs2-y        += super.o debug.o
 
 jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER)   += wbuf.o
+jffs2-$(CONFIG_JFFS2_FS_XATTR)         += xattr.o xattr_trusted.o xattr_user.o
+jffs2-$(CONFIG_JFFS2_FS_SECURITY)      += security.o
+jffs2-$(CONFIG_JFFS2_FS_POSIX_ACL)     += acl.o
 jffs2-$(CONFIG_JFFS2_RUBIN)    += compr_rubin.o
 jffs2-$(CONFIG_JFFS2_RTIME)    += compr_rtime.o
 jffs2-$(CONFIG_JFFS2_ZLIB)     += compr_zlib.o
index b7943439b6ec995cbe795603c91c63566526e211..c8f0bd64e53ea38e788abb87c2743aa15bcef79e 100644 (file)
@@ -150,3 +150,24 @@ the buffer.
 
 Ordering constraints:
        Lock wbuf_sem last, after the alloc_sem or and f->sem.
+
+
+       c->xattr_sem
+       ------------
+
+This read/write semaphore protects against concurrent access to the
+xattr related objects which include stuff in superblock and ic->xref.
+In read-only path, write-semaphore is too much exclusion. It's enough
+by read-semaphore. But you must hold write-semaphore when updating,
+creating or deleting any xattr related object.
+
+Once xattr_sem released, there would be no assurance for the existence
+of those objects. Thus, a series of processes is often required to retry,
+when updating such a object is necessary under holding read semaphore.
+For example, do_jffs2_getxattr() holds read-semaphore to scan xref and
+xdatum at first. But it retries this process with holding write-semaphore
+after release read-semaphore, if it's necessary to load name/value pair
+from medium.
+
+Ordering constraints:
+       Lock xattr_sem last, after the alloc_sem.
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
new file mode 100644 (file)
index 0000000..320dd48
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/crc32.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/posix_acl_xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+
+static size_t jffs2_acl_size(int count)
+{
+       if (count <= 4) {
+               return sizeof(struct jffs2_acl_header)
+                      + count * sizeof(struct jffs2_acl_entry_short);
+       } else {
+               return sizeof(struct jffs2_acl_header)
+                      + 4 * sizeof(struct jffs2_acl_entry_short)
+                      + (count - 4) * sizeof(struct jffs2_acl_entry);
+       }
+}
+
+static int jffs2_acl_count(size_t size)
+{
+       size_t s;
+
+       size -= sizeof(struct jffs2_acl_header);
+       s = size - 4 * sizeof(struct jffs2_acl_entry_short);
+       if (s < 0) {
+               if (size % sizeof(struct jffs2_acl_entry_short))
+                       return -1;
+               return size / sizeof(struct jffs2_acl_entry_short);
+       } else {
+               if (s % sizeof(struct jffs2_acl_entry))
+                       return -1;
+               return s / sizeof(struct jffs2_acl_entry) + 4;
+       }
+}
+
+static struct posix_acl *jffs2_acl_from_medium(void *value, size_t size)
+{
+       void *end = value + size;
+       struct jffs2_acl_header *header = value;
+       struct jffs2_acl_entry *entry;
+       struct posix_acl *acl;
+       uint32_t ver;
+       int i, count;
+
+       if (!value)
+               return NULL;
+       if (size < sizeof(struct jffs2_acl_header))
+               return ERR_PTR(-EINVAL);
+       ver = je32_to_cpu(header->a_version);
+       if (ver != JFFS2_ACL_VERSION) {
+               JFFS2_WARNING("Invalid ACL version. (=%u)\n", ver);
+               return ERR_PTR(-EINVAL);
+       }
+
+       value += sizeof(struct jffs2_acl_header);
+       count = jffs2_acl_count(size);
+       if (count < 0)
+               return ERR_PTR(-EINVAL);
+       if (count == 0)
+               return NULL;
+
+       acl = posix_acl_alloc(count, GFP_KERNEL);
+       if (!acl)
+               return ERR_PTR(-ENOMEM);
+
+       for (i=0; i < count; i++) {
+               entry = value;
+               if (value + sizeof(struct jffs2_acl_entry_short) > end)
+                       goto fail;
+               acl->a_entries[i].e_tag = je16_to_cpu(entry->e_tag);
+               acl->a_entries[i].e_perm = je16_to_cpu(entry->e_perm);
+               switch (acl->a_entries[i].e_tag) {
+                       case ACL_USER_OBJ:
+                       case ACL_GROUP_OBJ:
+                       case ACL_MASK:
+                       case ACL_OTHER:
+                               value += sizeof(struct jffs2_acl_entry_short);
+                               acl->a_entries[i].e_id = ACL_UNDEFINED_ID;
+                               break;
+
+                       case ACL_USER:
+                       case ACL_GROUP:
+                               value += sizeof(struct jffs2_acl_entry);
+                               if (value > end)
+                                       goto fail;
+                               acl->a_entries[i].e_id = je32_to_cpu(entry->e_id);
+                               break;
+
+                       default:
+                               goto fail;
+               }
+       }
+       if (value != end)
+               goto fail;
+       return acl;
+ fail:
+       posix_acl_release(acl);
+       return ERR_PTR(-EINVAL);
+}
+
+static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size)
+{
+       struct jffs2_acl_header *header;
+       struct jffs2_acl_entry *entry;
+       void *e;
+       size_t i;
+
+       *size = jffs2_acl_size(acl->a_count);
+       header = kmalloc(sizeof(*header) + acl->a_count * sizeof(*entry), GFP_KERNEL);
+       if (!header)
+               return ERR_PTR(-ENOMEM);
+       header->a_version = cpu_to_je32(JFFS2_ACL_VERSION);
+       e = header + 1;
+       for (i=0; i < acl->a_count; i++) {
+               entry = e;
+               entry->e_tag = cpu_to_je16(acl->a_entries[i].e_tag);
+               entry->e_perm = cpu_to_je16(acl->a_entries[i].e_perm);
+               switch(acl->a_entries[i].e_tag) {
+                       case ACL_USER:
+                       case ACL_GROUP:
+                               entry->e_id = cpu_to_je32(acl->a_entries[i].e_id);
+                               e += sizeof(struct jffs2_acl_entry);
+                               break;
+
+                       case ACL_USER_OBJ:
+                       case ACL_GROUP_OBJ:
+                       case ACL_MASK:
+                       case ACL_OTHER:
+                               e += sizeof(struct jffs2_acl_entry_short);
+                               break;
+
+                       default:
+                               goto fail;
+               }
+       }
+       return header;
+ fail:
+       kfree(header);
+       return ERR_PTR(-EINVAL);
+}
+
+static struct posix_acl *jffs2_iget_acl(struct inode *inode, struct posix_acl **i_acl)
+{
+       struct posix_acl *acl = JFFS2_ACL_NOT_CACHED;
+
+       spin_lock(&inode->i_lock);
+       if (*i_acl != JFFS2_ACL_NOT_CACHED)
+               acl = posix_acl_dup(*i_acl);
+       spin_unlock(&inode->i_lock);
+       return acl;
+}
+
+static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct posix_acl *acl)
+{
+       spin_lock(&inode->i_lock);
+       if (*i_acl != JFFS2_ACL_NOT_CACHED)
+               posix_acl_release(*i_acl);
+       *i_acl = posix_acl_dup(acl);
+       spin_unlock(&inode->i_lock);
+}
+
+static struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct posix_acl *acl;
+       char *value = NULL;
+       int rc, xprefix;
+
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               acl = jffs2_iget_acl(inode, &f->i_acl_access);
+               if (acl != JFFS2_ACL_NOT_CACHED)
+                       return acl;
+               xprefix = JFFS2_XPREFIX_ACL_ACCESS;
+               break;
+       case ACL_TYPE_DEFAULT:
+               acl = jffs2_iget_acl(inode, &f->i_acl_default);
+               if (acl != JFFS2_ACL_NOT_CACHED)
+                       return acl;
+               xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
+               break;
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+       rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0);
+       if (rc > 0) {
+               value = kmalloc(rc, GFP_KERNEL);
+               if (!value)
+                       return ERR_PTR(-ENOMEM);
+               rc = do_jffs2_getxattr(inode, xprefix, "", value, rc);
+       }
+       if (rc > 0) {
+               acl = jffs2_acl_from_medium(value, rc);
+       } else if (rc == -ENODATA || rc == -ENOSYS) {
+               acl = NULL;
+       } else {
+               acl = ERR_PTR(rc);
+       }
+       if (value)
+               kfree(value);
+       if (!IS_ERR(acl)) {
+               switch (type) {
+               case ACL_TYPE_ACCESS:
+                       jffs2_iset_acl(inode, &f->i_acl_access, acl);
+                       break;
+               case ACL_TYPE_DEFAULT:
+                       jffs2_iset_acl(inode, &f->i_acl_default, acl);
+                       break;
+               }
+       }
+       return acl;
+}
+
+static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       size_t size = 0;
+       char *value = NULL;
+       int rc, xprefix;
+
+       if (S_ISLNK(inode->i_mode))
+               return -EOPNOTSUPP;
+
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               xprefix = JFFS2_XPREFIX_ACL_ACCESS;
+               if (acl) {
+                       mode_t mode = inode->i_mode;
+                       rc = posix_acl_equiv_mode(acl, &mode);
+                       if (rc < 0)
+                               return rc;
+                       if (inode->i_mode != mode) {
+                               inode->i_mode = mode;
+                               jffs2_dirty_inode(inode);
+                       }
+                       if (rc == 0)
+                               acl = NULL;
+               }
+               break;
+       case ACL_TYPE_DEFAULT:
+               xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
+               if (!S_ISDIR(inode->i_mode))
+                       return acl ? -EACCES : 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (acl) {
+               value = jffs2_acl_to_medium(acl, &size);
+               if (IS_ERR(value))
+                       return PTR_ERR(value);
+       }
+
+       rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
+       if (value)
+               kfree(value);
+       if (!rc) {
+               switch(type) {
+               case ACL_TYPE_ACCESS:
+                       jffs2_iset_acl(inode, &f->i_acl_access, acl);
+                       break;
+               case ACL_TYPE_DEFAULT:
+                       jffs2_iset_acl(inode, &f->i_acl_default, acl);
+                       break;
+               }
+       }
+       return rc;
+}
+
+static int jffs2_check_acl(struct inode *inode, int mask)
+{
+       struct posix_acl *acl;
+       int rc;
+
+       acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
+       if (acl) {
+               rc = posix_acl_permission(inode, acl, mask);
+               posix_acl_release(acl);
+               return rc;
+       }
+       return -EAGAIN;
+}
+
+int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+       return generic_permission(inode, mask, jffs2_check_acl);
+}
+
+int jffs2_init_acl(struct inode *inode, struct inode *dir)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct posix_acl *acl = NULL, *clone;
+       mode_t mode;
+       int rc = 0;
+
+       f->i_acl_access = JFFS2_ACL_NOT_CACHED;
+       f->i_acl_default = JFFS2_ACL_NOT_CACHED;
+       if (!S_ISLNK(inode->i_mode)) {
+               acl = jffs2_get_acl(dir, ACL_TYPE_DEFAULT);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+               if (!acl)
+                       inode->i_mode &= ~current->fs->umask;
+       }
+       if (acl) {
+               if (S_ISDIR(inode->i_mode)) {
+                       rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
+                       if (rc)
+                               goto cleanup;
+               }
+               clone = posix_acl_clone(acl, GFP_KERNEL);
+               rc = -ENOMEM;
+               if (!clone)
+                       goto cleanup;
+               mode = inode->i_mode;
+               rc = posix_acl_create_masq(clone, &mode);
+               if (rc >= 0) {
+                       inode->i_mode = mode;
+                       if (rc > 0)
+                               rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
+               }
+               posix_acl_release(clone);
+       }
+ cleanup:
+       posix_acl_release(acl);
+       return rc;
+}
+
+void jffs2_clear_acl(struct inode *inode)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+
+       if (f->i_acl_access && f->i_acl_access != JFFS2_ACL_NOT_CACHED) {
+               posix_acl_release(f->i_acl_access);
+               f->i_acl_access = JFFS2_ACL_NOT_CACHED;
+       }
+       if (f->i_acl_default && f->i_acl_default != JFFS2_ACL_NOT_CACHED) {
+               posix_acl_release(f->i_acl_default);
+               f->i_acl_default = JFFS2_ACL_NOT_CACHED;
+       }
+}
+
+int jffs2_acl_chmod(struct inode *inode)
+{
+       struct posix_acl *acl, *clone;
+       int rc;
+
+       if (S_ISLNK(inode->i_mode))
+               return -EOPNOTSUPP;
+       acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
+       if (IS_ERR(acl) || !acl)
+               return PTR_ERR(acl);
+       clone = posix_acl_clone(acl, GFP_KERNEL);
+       posix_acl_release(acl);
+       if (!clone)
+               return -ENOMEM;
+       rc = posix_acl_chmod_masq(clone, inode->i_mode);
+       if (!rc)
+               rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
+       posix_acl_release(clone);
+       return rc;
+}
+
+static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size,
+                                        const char *name, size_t name_len)
+{
+       const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS);
+
+       if (list && retlen <= list_size)
+               strcpy(list, POSIX_ACL_XATTR_ACCESS);
+       return retlen;
+}
+
+static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size,
+                                         const char *name, size_t name_len)
+{
+       const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT);
+
+       if (list && retlen <= list_size)
+               strcpy(list, POSIX_ACL_XATTR_DEFAULT);
+       return retlen;
+}
+
+static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size)
+{
+       struct posix_acl *acl;
+       int rc;
+
+       acl = jffs2_get_acl(inode, type);
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
+       if (!acl)
+               return -ENODATA;
+       rc = posix_acl_to_xattr(acl, buffer, size);
+       posix_acl_release(acl);
+
+       return rc;
+}
+
+static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
+{
+       if (name[0] != '\0')
+               return -EINVAL;
+       return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size);
+}
+
+static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
+{
+       if (name[0] != '\0')
+               return -EINVAL;
+       return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
+}
+
+static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size)
+{
+       struct posix_acl *acl;
+       int rc;
+
+       if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+               return -EPERM;
+
+       if (value) {
+               acl = posix_acl_from_xattr(value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+               if (acl) {
+                       rc = posix_acl_valid(acl);
+                       if (rc)
+                               goto out;
+               }
+       } else {
+               acl = NULL;
+       }
+       rc = jffs2_set_acl(inode, type, acl);
+ out:
+       posix_acl_release(acl);
+       return rc;
+}
+
+static int jffs2_acl_access_setxattr(struct inode *inode, const char *name,
+                                    const void *buffer, size_t size, int flags)
+{
+       if (name[0] != '\0')
+               return -EINVAL;
+       return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size);
+}
+
+static int jffs2_acl_default_setxattr(struct inode *inode, const char *name,
+                                     const void *buffer, size_t size, int flags)
+{
+       if (name[0] != '\0')
+               return -EINVAL;
+       return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
+}
+
+struct xattr_handler jffs2_acl_access_xattr_handler = {
+       .prefix = POSIX_ACL_XATTR_ACCESS,
+       .list   = jffs2_acl_access_listxattr,
+       .get    = jffs2_acl_access_getxattr,
+       .set    = jffs2_acl_access_setxattr,
+};
+
+struct xattr_handler jffs2_acl_default_xattr_handler = {
+       .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .list   = jffs2_acl_default_listxattr,
+       .get    = jffs2_acl_default_getxattr,
+       .set    = jffs2_acl_default_setxattr,
+};
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
new file mode 100644 (file)
index 0000000..8893bd1
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+struct jffs2_acl_entry {
+       jint16_t        e_tag;
+       jint16_t        e_perm;
+       jint32_t        e_id;
+};
+
+struct jffs2_acl_entry_short {
+       jint16_t        e_tag;
+       jint16_t        e_perm;
+};
+
+struct jffs2_acl_header {
+       jint32_t        a_version;
+};
+
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+
+#define JFFS2_ACL_NOT_CACHED ((void *)-1)
+
+extern int jffs2_permission(struct inode *, int, struct nameidata *);
+extern int jffs2_acl_chmod(struct inode *);
+extern int jffs2_init_acl(struct inode *, struct inode *);
+extern void jffs2_clear_acl(struct inode *);
+
+extern struct xattr_handler jffs2_acl_access_xattr_handler;
+extern struct xattr_handler jffs2_acl_default_xattr_handler;
+
+#else
+
+#define jffs2_permission NULL
+#define jffs2_acl_chmod(inode)         (0)
+#define jffs2_init_acl(inode,dir)      (0)
+#define jffs2_clear_acl(inode)
+
+#endif /* CONFIG_JFFS2_FS_POSIX_ACL */
index 70f7a896c04ad8cac6389646aad49ad44e1da2a5..02826967ab58918ac6fa6ec7723d5e81485c357e 100644 (file)
@@ -160,6 +160,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
                ic->scan_dents = NULL;
                cond_resched();
        }
+       jffs2_build_xattr_subsystem(c);
        c->flags &= ~JFFS2_SB_FLAG_BUILDING;
 
        dbg_fsbuild("FS build complete\n");
@@ -178,6 +179,7 @@ exit:
                                jffs2_free_full_dirent(fd);
                        }
                }
+               jffs2_clear_xattr_subsystem(c);
        }
 
        return ret;
index e7944e665b9fc9245135c0c455b959f47cc721a3..7001ba26c0672fc81b7e77a707e9cab3a6d01dcf 100644 (file)
@@ -412,7 +412,7 @@ void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
                 kfree(comprbuf);
 }
 
-int jffs2_compressors_init(void)
+int __init jffs2_compressors_init(void)
 {
 /* Registering compressors */
 #ifdef CONFIG_JFFS2_ZLIB
index a77e830d85c5fb0cd230dba36670422554bcb398..509b8b1c0811dfb3bea24d92176ab0c9ff4f5250 100644 (file)
@@ -23,8 +23,8 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/jffs2.h>
-#include <linux/jffs2_fs_i.h>
-#include <linux/jffs2_fs_sb.h>
+#include "jffs2_fs_i.h"
+#include "jffs2_fs_sb.h"
 #include "nodelist.h"
 
 #define JFFS2_RUBINMIPS_PRIORITY 10
index 1fe17de713e86dabb250a5a471d8d57d0eec2f2a..72b4fc13a106053bfa64773f3d9e9609ce5ebd7d 100644 (file)
@@ -192,13 +192,13 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c,
                else
                        my_dirty_size += totlen;
 
-               if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
-                       JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
-                               ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
-                               ref_offset(jeb->last_node), jeb->last_node);
+               if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
+                       JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
+                                   ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
+                                   ref_offset(jeb->last_node), jeb->last_node);
                        goto error;
                }
-               ref2 = ref2->next_phys;
+               ref2 = ref_next(ref2);
        }
 
        if (my_used_size != jeb->used_size) {
@@ -268,9 +268,9 @@ __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c,
        }
 
        printk(JFFS2_DBG);
-       for (ref = jeb->first_node; ; ref = ref->next_phys) {
+       for (ref = jeb->first_node; ; ref = ref_next(ref)) {
                printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
-               if (ref->next_phys)
+               if (ref_next(ref))
                        printk("->");
                else
                        break;
index 162af6dfe292c216f0c61f9a1db301b3ceb630b4..5fa494a792b2ab69cd66b1050620b9ccaee91108 100644 (file)
 #define dbg_memalloc(fmt, ...)
 #endif
 
+/* Watch the XATTR subsystem */
+#ifdef JFFS2_DBG_XATTR_MESSAGES
+#define dbg_xattr(fmt, ...)  JFFS2_DEBUG(fmt, ##__VA_ARGS__)
+#else
+#define dbg_xattr(fmt, ...)
+#endif 
 
 /* "Sanity" checks */
 void
index 8bc7a5018e4044be500c3e14bf73b974673c6646..edd8371fc6a5b0f6f3c4dc1e220fe245642c5871 100644 (file)
@@ -17,8 +17,8 @@
 #include <linux/fs.h>
 #include <linux/crc32.h>
 #include <linux/jffs2.h>
-#include <linux/jffs2_fs_i.h>
-#include <linux/jffs2_fs_sb.h>
+#include "jffs2_fs_i.h"
+#include "jffs2_fs_sb.h"
 #include <linux/time.h>
 #include "nodelist.h"
 
@@ -57,7 +57,12 @@ struct inode_operations jffs2_dir_inode_operations =
        .rmdir =        jffs2_rmdir,
        .mknod =        jffs2_mknod,
        .rename =       jffs2_rename,
+       .permission =   jffs2_permission,
        .setattr =      jffs2_setattr,
+       .setxattr =     jffs2_setxattr,
+       .getxattr =     jffs2_getxattr,
+       .listxattr =    jffs2_listxattr,
+       .removexattr =  jffs2_removexattr
 };
 
 /***********************************************************************/
@@ -78,6 +83,9 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
 
        D1(printk(KERN_DEBUG "jffs2_lookup()\n"));
 
+       if (target->d_name.len > JFFS2_MAX_NAME_LEN)
+               return ERR_PTR(-ENAMETOOLONG);
+
        dir_f = JFFS2_INODE_INFO(dir_i);
        c = JFFS2_SB_INFO(dir_i->i_sb);
 
@@ -206,12 +214,15 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
        ret = jffs2_do_create(c, dir_f, f, ri,
                              dentry->d_name.name, dentry->d_name.len);
 
-       if (ret) {
-               make_bad_inode(inode);
-               iput(inode);
-               jffs2_free_raw_inode(ri);
-               return ret;
-       }
+       if (ret)
+               goto fail;
+
+       ret = jffs2_init_security(inode, dir_i);
+       if (ret)
+               goto fail;
+       ret = jffs2_init_acl(inode, dir_i);
+       if (ret)
+               goto fail;
 
        dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
 
@@ -221,6 +232,12 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
        D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
                  inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
        return 0;
+
+ fail:
+       make_bad_inode(inode);
+       iput(inode);
+       jffs2_free_raw_inode(ri);
+       return ret;
 }
 
 /***********************************************************************/
@@ -291,7 +308,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        struct jffs2_full_dnode *fn;
        struct jffs2_full_dirent *fd;
        int namelen;
-       uint32_t alloclen, phys_ofs;
+       uint32_t alloclen;
        int ret, targetlen = strlen(target);
 
        /* FIXME: If you care. We'd need to use frags for the target
@@ -310,8 +327,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
         * Just the node will do for now, though
         */
        namelen = dentry->d_name.len;
-       ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen,
-                               ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+       ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen,
+                                 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
 
        if (ret) {
                jffs2_free_raw_inode(ri);
@@ -339,7 +356,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        ri->data_crc = cpu_to_je32(crc32(0, target, targetlen));
        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
 
-       fn = jffs2_write_dnode(c, f, ri, target, targetlen, phys_ofs, ALLOC_NORMAL);
+       fn = jffs2_write_dnode(c, f, ri, target, targetlen, ALLOC_NORMAL);
 
        jffs2_free_raw_inode(ri);
 
@@ -371,8 +388,20 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        up(&f->sem);
 
        jffs2_complete_reservation(c);
-       ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
-                               ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+
+       ret = jffs2_init_security(inode, dir_i);
+       if (ret) {
+               jffs2_clear_inode(inode);
+               return ret;
+       }
+       ret = jffs2_init_acl(inode, dir_i);
+       if (ret) {
+               jffs2_clear_inode(inode);
+               return ret;
+       }
+
+       ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
+                                 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
        if (ret) {
                /* Eep. */
                jffs2_clear_inode(inode);
@@ -404,7 +433,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
        rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
 
-       fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL);
+       fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
 
        if (IS_ERR(fd)) {
                /* dirent failed to write. Delete the inode normally
@@ -442,7 +471,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
        struct jffs2_full_dnode *fn;
        struct jffs2_full_dirent *fd;
        int namelen;
-       uint32_t alloclen, phys_ofs;
+       uint32_t alloclen;
        int ret;
 
        mode |= S_IFDIR;
@@ -457,8 +486,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
         * Just the node will do for now, though
         */
        namelen = dentry->d_name.len;
-       ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL,
-                               JFFS2_SUMMARY_INODE_SIZE);
+       ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
+                                 JFFS2_SUMMARY_INODE_SIZE);
 
        if (ret) {
                jffs2_free_raw_inode(ri);
@@ -483,7 +512,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
        ri->data_crc = cpu_to_je32(0);
        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
 
-       fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
+       fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
 
        jffs2_free_raw_inode(ri);
 
@@ -501,8 +530,20 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
        up(&f->sem);
 
        jffs2_complete_reservation(c);
-       ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
-                               ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+
+       ret = jffs2_init_security(inode, dir_i);
+       if (ret) {
+               jffs2_clear_inode(inode);
+               return ret;
+       }
+       ret = jffs2_init_acl(inode, dir_i);
+       if (ret) {
+               jffs2_clear_inode(inode);
+               return ret;
+       }
+
+       ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
+                                 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
        if (ret) {
                /* Eep. */
                jffs2_clear_inode(inode);
@@ -534,7 +575,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
        rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
        rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
 
-       fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL);
+       fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
 
        if (IS_ERR(fd)) {
                /* dirent failed to write. Delete the inode normally
@@ -588,12 +629,12 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
        struct jffs2_full_dnode *fn;
        struct jffs2_full_dirent *fd;
        int namelen;
-       jint16_t dev;
+       union jffs2_device_node dev;
        int devlen = 0;
-       uint32_t alloclen, phys_ofs;
+       uint32_t alloclen;
        int ret;
 
-       if (!old_valid_dev(rdev))
+       if (!new_valid_dev(rdev))
                return -EINVAL;
 
        ri = jffs2_alloc_raw_inode();
@@ -602,17 +643,15 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
 
        c = JFFS2_SB_INFO(dir_i->i_sb);
 
-       if (S_ISBLK(mode) || S_ISCHR(mode)) {
-               dev = cpu_to_je16(old_encode_dev(rdev));
-               devlen = sizeof(dev);
-       }
+       if (S_ISBLK(mode) || S_ISCHR(mode))
+               devlen = jffs2_encode_dev(&dev, rdev);
 
        /* Try to reserve enough space for both node and dirent.
         * Just the node will do for now, though
         */
        namelen = dentry->d_name.len;
-       ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen,
-                               ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+       ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen,
+                                 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
 
        if (ret) {
                jffs2_free_raw_inode(ri);
@@ -639,7 +678,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
        ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen));
        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
 
-       fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL);
+       fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, ALLOC_NORMAL);
 
        jffs2_free_raw_inode(ri);
 
@@ -657,8 +696,20 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
        up(&f->sem);
 
        jffs2_complete_reservation(c);
-       ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
-                               ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+
+       ret = jffs2_init_security(inode, dir_i);
+       if (ret) {
+               jffs2_clear_inode(inode);
+               return ret;
+       }
+       ret = jffs2_init_acl(inode, dir_i);
+       if (ret) {
+               jffs2_clear_inode(inode);
+               return ret;
+       }
+
+       ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
+                                 ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
        if (ret) {
                /* Eep. */
                jffs2_clear_inode(inode);
@@ -693,7 +744,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
        rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
        rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
 
-       fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL);
+       fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
 
        if (IS_ERR(fd)) {
                /* dirent failed to write. Delete the inode normally
index dad68fdffe9e3e3ac8662fcc1a98dd19126b0152..1862e8bc101d4124fde048306512dd2e68daa18c 100644 (file)
@@ -30,7 +30,6 @@ static void jffs2_erase_callback(struct erase_info *);
 #endif
 static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset);
 static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
-static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 
 static void jffs2_erase_block(struct jffs2_sb_info *c,
@@ -136,7 +135,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
                        c->used_size -= jeb->used_size;
                        c->dirty_size -= jeb->dirty_size;
                        jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0;
-                       jffs2_free_all_node_refs(c, jeb);
+                       jffs2_free_jeb_node_refs(c, jeb);
                        list_add(&jeb->list, &c->erasing_list);
                        spin_unlock(&c->erase_completion_lock);
 
@@ -231,6 +230,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
                           at the end of the linked list. Stash it and continue
                           from the beginning of the list */
                        ic = (struct jffs2_inode_cache *)(*prev);
+                       BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
                        prev = &ic->nodes;
                        continue;
                }
@@ -283,22 +283,27 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
                jffs2_del_ino_cache(c, ic);
 }
 
-static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
-       struct jffs2_raw_node_ref *ref;
+       struct jffs2_raw_node_ref *block, *ref;
        D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset));
-       while(jeb->first_node) {
-               ref = jeb->first_node;
-               jeb->first_node = ref->next_phys;
 
-               /* Remove from the inode-list */
-               if (ref->next_in_ino)
+       block = ref = jeb->first_node;
+
+       while (ref) {
+               if (ref->flash_offset == REF_LINK_NODE) {
+                       ref = ref->next_in_ino;
+                       jffs2_free_refblock(block);
+                       block = ref;
+                       continue;
+               }
+               if (ref->flash_offset != REF_EMPTY_NODE && ref->next_in_ino)
                        jffs2_remove_node_refs_from_ino_list(c, ref, jeb);
                /* else it was a non-inode node or already removed, so don't bother */
 
-               jffs2_free_raw_node_ref(ref);
+               ref++;
        }
-       jeb->last_node = NULL;
+       jeb->first_node = jeb->last_node = NULL;
 }
 
 static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset)
@@ -351,7 +356,6 @@ fail:
 
 static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
-       struct jffs2_raw_node_ref *marker_ref = NULL;
        size_t retlen;
        int ret;
        uint32_t bad_offset;
@@ -373,12 +377,8 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
                                goto filebad;
                }
 
-               jeb->first_node = jeb->last_node = NULL;
+               /* Everything else got zeroed before the erase */
                jeb->free_size = c->sector_size;
-               jeb->used_size = 0;
-               jeb->dirty_size = 0;
-               jeb->wasted_size = 0;
-
        } else {
 
                struct kvec vecs[1];
@@ -388,11 +388,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
                        .totlen =       cpu_to_je32(c->cleanmarker_size)
                };
 
-               marker_ref = jffs2_alloc_raw_node_ref();
-               if (!marker_ref) {
-                       printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n");
-                       goto refile;
-               }
+               jffs2_prealloc_raw_node_refs(c, jeb, 1);
 
                marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));
 
@@ -408,21 +404,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
                                printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n",
                                       jeb->offset, sizeof(marker), retlen);
 
-                       jffs2_free_raw_node_ref(marker_ref);
                        goto filebad;
                }
 
-               marker_ref->next_in_ino = NULL;
-               marker_ref->next_phys = NULL;
-               marker_ref->flash_offset = jeb->offset | REF_NORMAL;
-               marker_ref->__totlen = c->cleanmarker_size;
-
-               jeb->first_node = jeb->last_node = marker_ref;
-
-               jeb->free_size = c->sector_size - c->cleanmarker_size;
-               jeb->used_size = c->cleanmarker_size;
-               jeb->dirty_size = 0;
-               jeb->wasted_size = 0;
+               /* Everything else got zeroed before the erase */
+               jeb->free_size = c->sector_size;
+               /* FIXME Special case for cleanmarker in empty block */
+               jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
        }
 
        spin_lock(&c->erase_completion_lock);
index 9f4171213e58b2d4105152e78a8627c688e37633..bb8844f40e48e3ecfd6327496a470ffc7bff6814 100644 (file)
@@ -54,7 +54,12 @@ const struct file_operations jffs2_file_operations =
 
 struct inode_operations jffs2_file_inode_operations =
 {
-       .setattr =      jffs2_setattr
+       .permission =   jffs2_permission,
+       .setattr =      jffs2_setattr,
+       .setxattr =     jffs2_setxattr,
+       .getxattr =     jffs2_getxattr,
+       .listxattr =    jffs2_listxattr,
+       .removexattr =  jffs2_removexattr
 };
 
 struct address_space_operations jffs2_file_address_operations =
@@ -129,13 +134,13 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
                struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
                struct jffs2_raw_inode ri;
                struct jffs2_full_dnode *fn;
-               uint32_t phys_ofs, alloc_len;
+               uint32_t alloc_len;
 
                D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
                          (unsigned int)inode->i_size, pageofs));
 
-               ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len,
-                                       ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
                if (ret)
                        return ret;
 
@@ -161,7 +166,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg,
                ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
                ri.data_crc = cpu_to_je32(0);
 
-               fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
+               fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_NORMAL);
 
                if (IS_ERR(fn)) {
                        ret = PTR_ERR(fn);
@@ -215,12 +220,20 @@ static int jffs2_commit_write (struct file *filp, struct page *pg,
        D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n",
                  inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags));
 
-       if (!start && end == PAGE_CACHE_SIZE) {
-               /* We need to avoid deadlock with page_cache_read() in
-                  jffs2_garbage_collect_pass(). So we have to mark the
-                  page up to date, to prevent page_cache_read() from
-                  trying to re-lock it. */
-               SetPageUptodate(pg);
+       if (end == PAGE_CACHE_SIZE) {
+               if (!start) {
+                       /* We need to avoid deadlock with page_cache_read() in
+                          jffs2_garbage_collect_pass(). So we have to mark the
+                          page up to date, to prevent page_cache_read() from
+                          trying to re-lock it. */
+                       SetPageUptodate(pg);
+               } else {
+                       /* When writing out the end of a page, write out the 
+                          _whole_ page. This helps to reduce the number of
+                          nodes in files which have many short writes, like
+                          syslog files. */
+                       start = aligned_start = 0;
+               }
        }
 
        ri = jffs2_alloc_raw_inode();
index 09e5d10b88401ca736bbd70d099d847fd9698bed..7b6c24b14f856c4cab36fe16661132640107bc85 100644 (file)
@@ -33,11 +33,11 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
        struct jffs2_raw_inode *ri;
-       unsigned short dev;
+       union jffs2_device_node dev;
        unsigned char *mdata = NULL;
        int mdatalen = 0;
        unsigned int ivalid;
-       uint32_t phys_ofs, alloclen;
+       uint32_t alloclen;
        int ret;
        D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
        ret = inode_change_ok(inode, iattr);
@@ -51,20 +51,24 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
           it out again with the appropriate data attached */
        if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
                /* For these, we don't actually need to read the old node */
-               dev = old_encode_dev(inode->i_rdev);
+               mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);
                mdata = (char *)&dev;
-               mdatalen = sizeof(dev);
                D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
        } else if (S_ISLNK(inode->i_mode)) {
+               down(&f->sem);
                mdatalen = f->metadata->size;
                mdata = kmalloc(f->metadata->size, GFP_USER);
-               if (!mdata)
+               if (!mdata) {
+                       up(&f->sem);
                        return -ENOMEM;
+               }
                ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
                if (ret) {
+                       up(&f->sem);
                        kfree(mdata);
                        return ret;
                }
+               up(&f->sem);
                D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));
        }
 
@@ -75,8 +79,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
                return -ENOMEM;
        }
 
-       ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen,
-                               ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+       ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen,
+                                 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
        if (ret) {
                jffs2_free_raw_inode(ri);
                if (S_ISLNK(inode->i_mode & S_IFMT))
@@ -127,7 +131,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
        else
                ri->data_crc = cpu_to_je32(0);
 
-       new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, ALLOC_NORMAL);
+       new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL);
        if (S_ISLNK(inode->i_mode))
                kfree(mdata);
 
@@ -180,7 +184,12 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
 
 int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-       return jffs2_do_setattr(dentry->d_inode, iattr);
+       int rc;
+
+       rc = jffs2_do_setattr(dentry->d_inode, iattr);
+       if (!rc && (iattr->ia_valid & ATTR_MODE))
+               rc = jffs2_acl_chmod(dentry->d_inode);
+       return rc;
 }
 
 int jffs2_statfs(struct super_block *sb, struct kstatfs *buf)
@@ -219,6 +228,7 @@ void jffs2_clear_inode (struct inode *inode)
 
        D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
 
+       jffs2_xattr_delete_inode(c, f->inocache);
        jffs2_do_clear_inode(c, f);
 }
 
@@ -227,6 +237,8 @@ void jffs2_read_inode (struct inode *inode)
        struct jffs2_inode_info *f;
        struct jffs2_sb_info *c;
        struct jffs2_raw_inode latest_node;
+       union jffs2_device_node jdev;
+       dev_t rdev = 0;
        int ret;
 
        D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
@@ -258,7 +270,6 @@ void jffs2_read_inode (struct inode *inode)
        inode->i_blocks = (inode->i_size + 511) >> 9;
 
        switch (inode->i_mode & S_IFMT) {
-               jint16_t rdev;
 
        case S_IFLNK:
                inode->i_op = &jffs2_symlink_inode_operations;
@@ -292,8 +303,16 @@ void jffs2_read_inode (struct inode *inode)
        case S_IFBLK:
        case S_IFCHR:
                /* Read the device numbers from the media */
+               if (f->metadata->size != sizeof(jdev.old) &&
+                   f->metadata->size != sizeof(jdev.new)) {
+                       printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size);
+                       up(&f->sem);
+                       jffs2_do_clear_inode(c, f);
+                       make_bad_inode(inode);
+                       return;
+               }
                D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));
-               if (jffs2_read_dnode(c, f, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) {
+               if (jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size) < 0) {
                        /* Eep */
                        printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
                        up(&f->sem);
@@ -301,12 +320,15 @@ void jffs2_read_inode (struct inode *inode)
                        make_bad_inode(inode);
                        return;
                }
+               if (f->metadata->size == sizeof(jdev.old))
+                       rdev = old_decode_dev(je16_to_cpu(jdev.old));
+               else
+                       rdev = new_decode_dev(je32_to_cpu(jdev.new));
 
        case S_IFSOCK:
        case S_IFIFO:
                inode->i_op = &jffs2_file_inode_operations;
-               init_special_inode(inode, inode->i_mode,
-                                  old_decode_dev((je16_to_cpu(rdev))));
+               init_special_inode(inode, inode->i_mode, rdev);
                break;
 
        default:
@@ -492,6 +514,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
        }
        memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *));
 
+       jffs2_init_xattr_subsystem(c);
+
        if ((ret = jffs2_do_mount_fs(c)))
                goto out_inohash;
 
@@ -526,6 +550,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
        else
                kfree(c->blocks);
  out_inohash:
+       jffs2_clear_xattr_subsystem(c);
        kfree(c->inocache_list);
  out_wbuf:
        jffs2_flash_cleanup(c);
@@ -639,13 +664,6 @@ static int jffs2_flash_setup(struct jffs2_sb_info *c) {
                        return ret;
        }
 
-       /* add setups for other bizarre flashes here... */
-       if (jffs2_nor_ecc(c)) {
-               ret = jffs2_nor_ecc_flash_setup(c);
-               if (ret)
-                       return ret;
-       }
-
        /* and Dataflash */
        if (jffs2_dataflash(c)) {
                ret = jffs2_dataflash_setup(c);
@@ -669,11 +687,6 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) {
                jffs2_nand_flash_cleanup(c);
        }
 
-       /* add cleanups for other bizarre flashes here... */
-       if (jffs2_nor_ecc(c)) {
-               jffs2_nor_ecc_flash_cleanup(c);
-       }
-
        /* and DataFlash */
        if (jffs2_dataflash(c)) {
                jffs2_dataflash_cleanup(c);
index f9ffece453a38e65542db843701749f943a71283..477c526d638b979efb7506ba18195ad9b14b2269 100644 (file)
@@ -125,6 +125,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
        struct jffs2_eraseblock *jeb;
        struct jffs2_raw_node_ref *raw;
        int ret = 0, inum, nlink;
+       int xattr = 0;
 
        if (down_interruptible(&c->alloc_sem))
                return -EINTR;
@@ -138,7 +139,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                   the node CRCs etc. Do it now. */
 
                /* checked_ino is protected by the alloc_sem */
-               if (c->checked_ino > c->highest_ino) {
+               if (c->checked_ino > c->highest_ino && xattr) {
                        printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n",
                               c->unchecked_size);
                        jffs2_dbg_dump_block_lists_nolock(c);
@@ -148,6 +149,9 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 
                spin_unlock(&c->erase_completion_lock);
 
+               if (!xattr)
+                       xattr = jffs2_verify_xattr(c);
+
                spin_lock(&c->inocache_lock);
 
                ic = jffs2_get_ino_cache(c, c->checked_ino++);
@@ -181,6 +185,10 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
                           and trigger the BUG() above while we haven't yet
                           finished checking all its nodes */
                        D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino));
+                       /* We need to come back again for the _same_ inode. We've
+                        made no progress in this case, but that should be OK */
+                       c->checked_ino--;
+
                        up(&c->alloc_sem);
                        sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
                        return 0;
@@ -231,7 +239,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 
        while(ref_obsolete(raw)) {
                D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw)));
-               raw = raw->next_phys;
+               raw = ref_next(raw);
                if (unlikely(!raw)) {
                        printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n");
                        printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n",
@@ -248,16 +256,37 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 
        if (!raw->next_in_ino) {
                /* Inode-less node. Clean marker, snapshot or something like that */
-               /* FIXME: If it's something that needs to be copied, including something
-                  we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */
                spin_unlock(&c->erase_completion_lock);
-               jffs2_mark_node_obsolete(c, raw);
+               if (ref_flags(raw) == REF_PRISTINE) {
+                       /* It's an unknown node with JFFS2_FEATURE_RWCOMPAT_COPY */
+                       jffs2_garbage_collect_pristine(c, NULL, raw);
+               } else {
+                       /* Just mark it obsolete */
+                       jffs2_mark_node_obsolete(c, raw);
+               }
                up(&c->alloc_sem);
                goto eraseit_lock;
        }
 
        ic = jffs2_raw_ref_to_ic(raw);
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+       /* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr.
+        * We can decide whether this node is inode or xattr by ic->class.     */
+       if (ic->class == RAWNODE_CLASS_XATTR_DATUM
+           || ic->class == RAWNODE_CLASS_XATTR_REF) {
+               BUG_ON(raw->next_in_ino != (void *)ic);
+               spin_unlock(&c->erase_completion_lock);
+
+               if (ic->class == RAWNODE_CLASS_XATTR_DATUM) {
+                       ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
+               } else {
+                       ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
+               }
+               goto release_sem;
+       }
+#endif
+
        /* We need to hold the inocache. Either the erase_completion_lock or
           the inocache_lock are sufficient; we trade down since the inocache_lock
           causes less contention. */
@@ -499,7 +528,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
                                          struct jffs2_raw_node_ref *raw)
 {
        union jffs2_node_union *node;
-       struct jffs2_raw_node_ref *nraw;
        size_t retlen;
        int ret;
        uint32_t phys_ofs, alloclen;
@@ -508,15 +536,16 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
 
        D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw)));
 
-       rawlen = ref_totlen(c, c->gcblock, raw);
+       alloclen = rawlen = ref_totlen(c, c->gcblock, raw);
 
        /* Ask for a small amount of space (or the totlen if smaller) because we
           don't want to force wastage of the end of a block if splitting would
           work. */
-       ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) +
-                               JFFS2_MIN_DATA_LEN, rawlen), &phys_ofs, &alloclen, rawlen);
-                               /* this is not the exact summary size of it,
-                                       it is only an upper estimation */
+       if (ic && alloclen > sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN)
+               alloclen = sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN;
+
+       ret = jffs2_reserve_space_gc(c, alloclen, &alloclen, rawlen);
+       /* 'rawlen' is not the exact summary size; it is only an upper estimation */
 
        if (ret)
                return ret;
@@ -580,22 +609,17 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
                }
                break;
        default:
-               printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n",
-                      ref_offset(raw), je16_to_cpu(node->u.nodetype));
-               goto bail;
-       }
-
-       nraw = jffs2_alloc_raw_node_ref();
-       if (!nraw) {
-               ret = -ENOMEM;
-               goto out_node;
+               /* If it's inode-less, we don't _know_ what it is. Just copy it intact */
+               if (ic) {
+                       printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n",
+                              ref_offset(raw), je16_to_cpu(node->u.nodetype));
+                       goto bail;
+               }
        }
 
        /* OK, all the CRCs are good; this node can just be copied as-is. */
  retry:
-       nraw->flash_offset = phys_ofs;
-       nraw->__totlen = rawlen;
-       nraw->next_phys = NULL;
+       phys_ofs = write_ofs(c);
 
        ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node);
 
@@ -603,17 +627,11 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
                printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
                        rawlen, phys_ofs, ret, retlen);
                if (retlen) {
-                        /* Doesn't belong to any inode */
-                       nraw->next_in_ino = NULL;
-
-                       nraw->flash_offset |= REF_OBSOLETE;
-                       jffs2_add_physical_node_ref(c, nraw);
-                       jffs2_mark_node_obsolete(c, nraw);
+                       jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
                } else {
-                       printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset);
-                        jffs2_free_raw_node_ref(nraw);
+                       printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs);
                }
-               if (!retried && (nraw = jffs2_alloc_raw_node_ref())) {
+               if (!retried) {
                        /* Try to reallocate space and retry */
                        uint32_t dummy;
                        struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size];
@@ -625,7 +643,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
                        jffs2_dbg_acct_sanity_check(c,jeb);
                        jffs2_dbg_acct_paranoia_check(c, jeb);
 
-                       ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy, rawlen);
+                       ret = jffs2_reserve_space_gc(c, rawlen, &dummy, rawlen);
                                                /* this is not the exact summary size of it,
                                                        it is only an upper estimation */
 
@@ -638,25 +656,13 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
                                goto retry;
                        }
                        D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
-                       jffs2_free_raw_node_ref(nraw);
                }
 
-               jffs2_free_raw_node_ref(nraw);
                if (!ret)
                        ret = -EIO;
                goto out_node;
        }
-       nraw->flash_offset |= REF_PRISTINE;
-       jffs2_add_physical_node_ref(c, nraw);
-
-       /* Link into per-inode list. This is safe because of the ic
-          state being INO_STATE_GC. Note that if we're doing this
-          for an inode which is in-core, the 'nraw' pointer is then
-          going to be fetched from ic->nodes by our caller. */
-       spin_lock(&c->erase_completion_lock);
-        nraw->next_in_ino = ic->nodes;
-        ic->nodes = nraw;
-       spin_unlock(&c->erase_completion_lock);
+       jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic);
 
        jffs2_mark_node_obsolete(c, raw);
        D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw)));
@@ -675,19 +681,16 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
        struct jffs2_full_dnode *new_fn;
        struct jffs2_raw_inode ri;
        struct jffs2_node_frag *last_frag;
-       jint16_t dev;
+       union jffs2_device_node dev;
        char *mdata = NULL, mdatalen = 0;
-       uint32_t alloclen, phys_ofs, ilen;
+       uint32_t alloclen, ilen;
        int ret;
 
        if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
            S_ISCHR(JFFS2_F_I_MODE(f)) ) {
                /* For these, we don't actually need to read the old node */
-               /* FIXME: for minor or major > 255. */
-               dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) |
-                       JFFS2_F_I_RDEV_MIN(f)));
+               mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f));
                mdata = (char *)&dev;
-               mdatalen = sizeof(dev);
                D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
        } else if (S_ISLNK(JFFS2_F_I_MODE(f))) {
                mdatalen = fn->size;
@@ -706,7 +709,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
 
        }
 
-       ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen,
+       ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &alloclen,
                                JFFS2_SUMMARY_INODE_SIZE);
        if (ret) {
                printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n",
@@ -744,7 +747,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
        ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
        ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen));
 
-       new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, phys_ofs, ALLOC_GC);
+       new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, ALLOC_GC);
 
        if (IS_ERR(new_fn)) {
                printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn));
@@ -765,7 +768,7 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er
 {
        struct jffs2_full_dirent *new_fd;
        struct jffs2_raw_dirent rd;
-       uint32_t alloclen, phys_ofs;
+       uint32_t alloclen;
        int ret;
 
        rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -787,14 +790,14 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er
        rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8));
        rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize));
 
-       ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen,
+       ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &alloclen,
                                JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize));
        if (ret) {
                printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n",
                       sizeof(rd)+rd.nsize, ret);
                return ret;
        }
-       new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, phys_ofs, ALLOC_GC);
+       new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, ALLOC_GC);
 
        if (IS_ERR(new_fd)) {
                printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd));
@@ -922,7 +925,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras
        struct jffs2_raw_inode ri;
        struct jffs2_node_frag *frag;
        struct jffs2_full_dnode *new_fn;
-       uint32_t alloclen, phys_ofs, ilen;
+       uint32_t alloclen, ilen;
        int ret;
 
        D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n",
@@ -1001,14 +1004,14 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras
        ri.data_crc = cpu_to_je32(0);
        ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
 
-       ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen,
-                               JFFS2_SUMMARY_INODE_SIZE);
+       ret = jffs2_reserve_space_gc(c, sizeof(ri), &alloclen,
+                                    JFFS2_SUMMARY_INODE_SIZE);
        if (ret) {
                printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n",
                       sizeof(ri), ret);
                return ret;
        }
-       new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_GC);
+       new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_GC);
 
        if (IS_ERR(new_fn)) {
                printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn));
@@ -1070,7 +1073,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
 {
        struct jffs2_full_dnode *new_fn;
        struct jffs2_raw_inode ri;
-       uint32_t alloclen, phys_ofs, offset, orig_end, orig_start;
+       uint32_t alloclen, offset, orig_end, orig_start;
        int ret = 0;
        unsigned char *comprbuf = NULL, *writebuf;
        unsigned long pg;
@@ -1227,7 +1230,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
                uint32_t cdatalen;
                uint16_t comprtype = JFFS2_COMPR_NONE;
 
-               ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs,
+               ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN,
                                        &alloclen, JFFS2_SUMMARY_INODE_SIZE);
 
                if (ret) {
@@ -1264,7 +1267,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
                ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
                ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
 
-               new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC);
+               new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, ALLOC_GC);
 
                jffs2_free_comprbuf(comprbuf, writebuf);
 
diff --git a/fs/jffs2/histo.h b/fs/jffs2/histo.h
deleted file mode 100644 (file)
index 22a93a0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-/* This file provides the bit-probabilities for the input file */
-#define BIT_DIVIDER 629
-static int bits[9] = { 179,167,183,165,159,198,178,119,}; /* ia32 .so files */
similarity index 91%
rename from include/linux/jffs2_fs_i.h
rename to fs/jffs2/jffs2_fs_i.h
index ad565bf9dcc15cf679f27965d0239bfceb6c4ff1..2e0cc8e00b858b399121437b1ba9ebd9beb312e5 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/version.h>
 #include <linux/rbtree.h>
+#include <linux/posix_acl.h>
 #include <asm/semaphore.h>
 
 struct jffs2_inode_info {
@@ -45,6 +46,10 @@ struct jffs2_inode_info {
        struct inode vfs_inode;
 #endif
 #endif
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+       struct posix_acl *i_acl_access;
+       struct posix_acl *i_acl_default;
+#endif
 };
 
 #endif /* _JFFS2_FS_I */
similarity index 92%
rename from include/linux/jffs2_fs_sb.h
rename to fs/jffs2/jffs2_fs_sb.h
index 4bcfb5570221a6fe7e1fa4347c9f5e78f6fc3b68..935fec1b1201bdea3cfa25a0cf665ea6f69ed028 100644 (file)
@@ -100,6 +100,7 @@ struct jffs2_sb_info {
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
        /* Write-behind buffer for NAND flash */
        unsigned char *wbuf;
+       unsigned char *oobbuf;
        uint32_t wbuf_ofs;
        uint32_t wbuf_len;
        struct jffs2_inodirty *wbuf_inodes;
@@ -107,7 +108,7 @@ struct jffs2_sb_info {
        struct rw_semaphore wbuf_sem;   /* Protects the write buffer */
 
        /* Information about out-of-band area usage... */
-       struct nand_oobinfo *oobinfo;
+       struct nand_ecclayout *ecclayout;
        uint32_t badblock_pos;
        uint32_t fsdata_pos;
        uint32_t fsdata_len;
@@ -115,6 +116,16 @@ struct jffs2_sb_info {
 
        struct jffs2_summary *summary;          /* Summary information */
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+#define XATTRINDEX_HASHSIZE    (57)
+       uint32_t highest_xid;
+       struct list_head xattrindex[XATTRINDEX_HASHSIZE];
+       struct list_head xattr_unchecked;
+       struct jffs2_xattr_ref *xref_temp;
+       struct rw_semaphore xattr_sem;
+       uint32_t xdatum_mem_usage;
+       uint32_t xdatum_mem_threshold;
+#endif
        /* OS-private pointer for getting back to master superblock info */
        void *os_priv;
 };
index 036cbd11c00449d6755481b8a51e53bbf0f7fb4f..4889d0700c0e6a32e7e998bf2785438f301613dd 100644 (file)
@@ -26,6 +26,10 @@ 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;
+#ifdef CONFIG_JFFS2_FS_XATTR
+static kmem_cache_t *xattr_datum_cache;
+static kmem_cache_t *xattr_ref_cache;
+#endif
 
 int __init jffs2_create_slab_caches(void)
 {
@@ -53,8 +57,8 @@ int __init jffs2_create_slab_caches(void)
        if (!tmp_dnode_info_slab)
                goto err;
 
-       raw_node_ref_slab = kmem_cache_create("jffs2_raw_node_ref",
-                                             sizeof(struct jffs2_raw_node_ref),
+       raw_node_ref_slab = kmem_cache_create("jffs2_refblock",
+                                             sizeof(struct jffs2_raw_node_ref) * (REFS_PER_BLOCK + 1),
                                              0, 0, NULL, NULL);
        if (!raw_node_ref_slab)
                goto err;
@@ -68,8 +72,24 @@ int __init jffs2_create_slab_caches(void)
        inode_cache_slab = kmem_cache_create("jffs2_inode_cache",
                                             sizeof(struct jffs2_inode_cache),
                                             0, 0, NULL, NULL);
-       if (inode_cache_slab)
-               return 0;
+       if (!inode_cache_slab)
+               goto err;
+
+#ifdef CONFIG_JFFS2_FS_XATTR
+       xattr_datum_cache = kmem_cache_create("jffs2_xattr_datum",
+                                            sizeof(struct jffs2_xattr_datum),
+                                            0, 0, NULL, NULL);
+       if (!xattr_datum_cache)
+               goto err;
+
+       xattr_ref_cache = kmem_cache_create("jffs2_xattr_ref",
+                                          sizeof(struct jffs2_xattr_ref),
+                                          0, 0, NULL, NULL);
+       if (!xattr_ref_cache)
+               goto err;
+#endif
+
+       return 0;
  err:
        jffs2_destroy_slab_caches();
        return -ENOMEM;
@@ -91,6 +111,12 @@ void jffs2_destroy_slab_caches(void)
                kmem_cache_destroy(node_frag_slab);
        if(inode_cache_slab)
                kmem_cache_destroy(inode_cache_slab);
+#ifdef CONFIG_JFFS2_FS_XATTR
+       if (xattr_datum_cache)
+               kmem_cache_destroy(xattr_datum_cache);
+       if (xattr_ref_cache)
+               kmem_cache_destroy(xattr_ref_cache);
+#endif
 }
 
 struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize)
@@ -164,15 +190,65 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
        kmem_cache_free(tmp_dnode_info_slab, x);
 }
 
-struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
+struct jffs2_raw_node_ref *jffs2_alloc_refblock(void)
 {
        struct jffs2_raw_node_ref *ret;
+
        ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
-       dbg_memalloc("%p\n", ret);
+       if (ret) {
+               int i = 0;
+               for (i=0; i < REFS_PER_BLOCK; i++) {
+                       ret[i].flash_offset = REF_EMPTY_NODE;
+                       ret[i].next_in_ino = NULL;
+               }
+               ret[i].flash_offset = REF_LINK_NODE;
+               ret[i].next_in_ino = NULL;
+       }
        return ret;
 }
 
-void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
+int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
+                                struct jffs2_eraseblock *jeb, int nr)
+{
+       struct jffs2_raw_node_ref **p, *ref;
+       int i = nr;
+
+       dbg_memalloc("%d\n", nr);
+
+       p = &jeb->last_node;
+       ref = *p;
+
+       dbg_memalloc("Reserving %d refs for block @0x%08x\n", nr, jeb->offset);
+
+       /* If jeb->last_node is really a valid node then skip over it */
+       if (ref && ref->flash_offset != REF_EMPTY_NODE)
+               ref++;
+
+       while (i) {
+               if (!ref) {
+                       dbg_memalloc("Allocating new refblock linked from %p\n", p);
+                       ref = *p = jffs2_alloc_refblock();
+                       if (!ref)
+                               return -ENOMEM;
+               }
+               if (ref->flash_offset == REF_LINK_NODE) {
+                       p = &ref->next_in_ino;
+                       ref = *p;
+                       continue;
+               }
+               i--;
+               ref++;
+       }
+       jeb->allocated_refs = nr;
+
+       dbg_memalloc("Reserved %d refs for block @0x%08x, last_node is %p (%08x,%p)\n",
+                 nr, jeb->offset, jeb->last_node, jeb->last_node->flash_offset,
+                 jeb->last_node->next_in_ino);
+
+       return 0;
+}
+
+void jffs2_free_refblock(struct jffs2_raw_node_ref *x)
 {
        dbg_memalloc("%p\n", x);
        kmem_cache_free(raw_node_ref_slab, x);
@@ -205,3 +281,40 @@ void jffs2_free_inode_cache(struct jffs2_inode_cache *x)
        dbg_memalloc("%p\n", x);
        kmem_cache_free(inode_cache_slab, x);
 }
+
+#ifdef CONFIG_JFFS2_FS_XATTR
+struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
+{
+       struct jffs2_xattr_datum *xd;
+       xd = kmem_cache_alloc(xattr_datum_cache, GFP_KERNEL);
+       dbg_memalloc("%p\n", xd);
+
+       memset(xd, 0, sizeof(struct jffs2_xattr_datum));
+       xd->class = RAWNODE_CLASS_XATTR_DATUM;
+       INIT_LIST_HEAD(&xd->xindex);
+       return xd;
+}
+
+void jffs2_free_xattr_datum(struct jffs2_xattr_datum *xd)
+{
+       dbg_memalloc("%p\n", xd);
+       kmem_cache_free(xattr_datum_cache, xd);
+}
+
+struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
+{
+       struct jffs2_xattr_ref *ref;
+       ref = kmem_cache_alloc(xattr_ref_cache, GFP_KERNEL);
+       dbg_memalloc("%p\n", ref);
+
+       memset(ref, 0, sizeof(struct jffs2_xattr_ref));
+       ref->class = RAWNODE_CLASS_XATTR_REF;
+       return ref;
+}
+
+void jffs2_free_xattr_ref(struct jffs2_xattr_ref *ref)
+{
+       dbg_memalloc("%p\n", ref);
+       kmem_cache_free(xattr_ref_cache, ref);
+}
+#endif
index 1d46677afd172b5742a4ccd2472b4d59f82a2800..927dfe42ba76cab92b6fae6a39c09baa71d7f607 100644 (file)
@@ -438,8 +438,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
        if (c->mtd->point) {
                err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
                if (!err && retlen < tn->csize) {
-                       JFFS2_WARNING("MTD point returned len too short: %zu "
-                                       "instead of %u.\n", retlen, tn->csize);
+                       JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
                        c->mtd->unpoint(c->mtd, buffer, ofs, len);
                } else if (err)
                        JFFS2_WARNING("MTD point failed: error code %d.\n", err);
@@ -462,8 +461,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
                }
 
                if (retlen != len) {
-                       JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n",
-                                       ofs, retlen, len);
+                       JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len);
                        err = -EIO;
                        goto free_out;
                }
@@ -940,6 +938,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
                this = c->inocache_list[i];
                while (this) {
                        next = this->next;
+                       jffs2_xattr_free_inode(c, this);
                        jffs2_free_inode_cache(this);
                        this = next;
                }
@@ -954,9 +953,13 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
 
        for (i=0; i<c->nr_blocks; i++) {
                this = c->blocks[i].first_node;
-               while(this) {
-                       next = this->next_phys;
-                       jffs2_free_raw_node_ref(this);
+               while (this) {
+                       if (this[REFS_PER_BLOCK].flash_offset == REF_LINK_NODE)
+                               next = this[REFS_PER_BLOCK].next_in_ino;
+                       else
+                               next = NULL;
+
+                       jffs2_free_refblock(this);
                        this = next;
                }
                c->blocks[i].first_node = c->blocks[i].last_node = NULL;
@@ -1047,3 +1050,169 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c)
                cond_resched();
        }
 }
+
+struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
+                                              struct jffs2_eraseblock *jeb,
+                                              uint32_t ofs, uint32_t len,
+                                              struct jffs2_inode_cache *ic)
+{
+       struct jffs2_raw_node_ref *ref;
+
+       BUG_ON(!jeb->allocated_refs);
+       jeb->allocated_refs--;
+
+       ref = jeb->last_node;
+
+       dbg_noderef("Last node at %p is (%08x,%p)\n", ref, ref->flash_offset,
+                   ref->next_in_ino);
+
+       while (ref->flash_offset != REF_EMPTY_NODE) {
+               if (ref->flash_offset == REF_LINK_NODE)
+                       ref = ref->next_in_ino;
+               else
+                       ref++;
+       }
+
+       dbg_noderef("New ref is %p (%08x becomes %08x,%p) len 0x%x\n", ref, 
+                   ref->flash_offset, ofs, ref->next_in_ino, len);
+
+       ref->flash_offset = ofs;
+
+       if (!jeb->first_node) {
+               jeb->first_node = ref;
+               BUG_ON(ref_offset(ref) != jeb->offset);
+       } else if (unlikely(ref_offset(ref) != jeb->offset + c->sector_size - jeb->free_size)) {
+               uint32_t last_len = ref_totlen(c, jeb, jeb->last_node);
+
+               JFFS2_ERROR("Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",
+                           ref, ref_offset(ref), ref_offset(ref)+len,
+                           ref_offset(jeb->last_node), 
+                           ref_offset(jeb->last_node)+last_len);
+               BUG();
+       }
+       jeb->last_node = ref;
+
+       if (ic) {
+               ref->next_in_ino = ic->nodes;
+               ic->nodes = ref;
+       } else {
+               ref->next_in_ino = NULL;
+       }
+
+       switch(ref_flags(ref)) {
+       case REF_UNCHECKED:
+               c->unchecked_size += len;
+               jeb->unchecked_size += len;
+               break;
+
+       case REF_NORMAL:
+       case REF_PRISTINE:
+               c->used_size += len;
+               jeb->used_size += len;
+               break;
+
+       case REF_OBSOLETE:
+               c->dirty_size += len;
+               jeb->dirty_size += len;
+               break;
+       }
+       c->free_size -= len;
+       jeb->free_size -= len;
+
+#ifdef TEST_TOTLEN
+       /* Set (and test) __totlen field... for now */
+       ref->__totlen = len;
+       ref_totlen(c, jeb, ref);
+#endif
+       return ref;
+}
+
+/* No locking, no reservation of 'ref'. Do not use on a live file system */
+int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+                          uint32_t size)
+{
+       if (!size)
+               return 0;
+       if (unlikely(size > jeb->free_size)) {
+               printk(KERN_CRIT "Dirty space 0x%x larger then free_size 0x%x (wasted 0x%x)\n",
+                      size, jeb->free_size, jeb->wasted_size);
+               BUG();
+       }
+       /* REF_EMPTY_NODE is !obsolete, so that works OK */
+       if (jeb->last_node && ref_obsolete(jeb->last_node)) {
+#ifdef TEST_TOTLEN
+               jeb->last_node->__totlen += size;
+#endif
+               c->dirty_size += size;
+               c->free_size -= size;
+               jeb->dirty_size += size;
+               jeb->free_size -= size;
+       } else {
+               uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;
+               ofs |= REF_OBSOLETE;
+
+               jffs2_link_node_ref(c, jeb, ofs, size, NULL);
+       }
+
+       return 0;
+}
+
+/* Calculate totlen from surrounding nodes or eraseblock */
+static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
+                                   struct jffs2_eraseblock *jeb,
+                                   struct jffs2_raw_node_ref *ref)
+{
+       uint32_t ref_end;
+       struct jffs2_raw_node_ref *next_ref = ref_next(ref);
+
+       if (next_ref)
+               ref_end = ref_offset(next_ref);
+       else {
+               if (!jeb)
+                       jeb = &c->blocks[ref->flash_offset / c->sector_size];
+
+               /* Last node in block. Use free_space */
+               if (unlikely(ref != jeb->last_node)) {
+                       printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n",
+                              ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0);
+                       BUG();
+               }
+               ref_end = jeb->offset + c->sector_size - jeb->free_size;
+       }
+       return ref_end - ref_offset(ref);
+}
+
+uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+                           struct jffs2_raw_node_ref *ref)
+{
+       uint32_t ret;
+
+       ret = __ref_totlen(c, jeb, ref);
+
+#ifdef TEST_TOTLEN
+       if (unlikely(ret != ref->__totlen)) {
+               if (!jeb)
+                       jeb = &c->blocks[ref->flash_offset / c->sector_size];
+
+               printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
+                      ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
+                      ret, ref->__totlen);
+               if (ref_next(ref)) {
+                       printk(KERN_CRIT "next %p (0x%08x-0x%08x)\n", ref_next(ref), ref_offset(ref_next(ref)),
+                              ref_offset(ref_next(ref))+ref->__totlen);
+               } else 
+                       printk(KERN_CRIT "No next ref. jeb->last_node is %p\n", jeb->last_node);
+
+               printk(KERN_CRIT "jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n", jeb->wasted_size, jeb->dirty_size, jeb->used_size, jeb->free_size);
+
+#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
+               __jffs2_dbg_dump_node_refs_nolock(c, jeb);
+#endif
+
+               WARN_ON(1);
+
+               ret = ref->__totlen;
+       }
+#endif /* TEST_TOTLEN */
+       return ret;
+}
index 23a67bb3052f916fb60aee403aa48cf802c0c517..b16c60bbcf6ed191d1ab2c08f75fe0b9dded1ec5 100644 (file)
 #include <linux/fs.h>
 #include <linux/types.h>
 #include <linux/jffs2.h>
-#include <linux/jffs2_fs_sb.h>
-#include <linux/jffs2_fs_i.h>
+#include "jffs2_fs_sb.h"
+#include "jffs2_fs_i.h"
+#include "xattr.h"
+#include "acl.h"
 #include "summary.h"
 
 #ifdef __ECOS
 struct jffs2_raw_node_ref
 {
        struct jffs2_raw_node_ref *next_in_ino; /* Points to the next raw_node_ref
-               for this inode. If this is the last, it points to the inode_cache
-               for this inode instead. The inode_cache will have NULL in the first
-               word so you know when you've got there :) */
-       struct jffs2_raw_node_ref *next_phys;
+               for this object. If this _is_ the last, it points to the inode_cache,
+               xattr_ref or xattr_datum instead. The common part of those structures
+               has NULL in the first word. See jffs2_raw_ref_to_ic() below */
        uint32_t flash_offset;
+#define TEST_TOTLEN
+#ifdef TEST_TOTLEN
        uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
+#endif
 };
 
+#define REF_LINK_NODE ((int32_t)-1)
+#define REF_EMPTY_NODE ((int32_t)-2)
+
+/* Use blocks of about 256 bytes */
+#define REFS_PER_BLOCK ((255/sizeof(struct jffs2_raw_node_ref))-1)
+
+static inline struct jffs2_raw_node_ref *ref_next(struct jffs2_raw_node_ref *ref)
+{
+       ref++;
+
+       /* Link to another block of refs */
+       if (ref->flash_offset == REF_LINK_NODE) {
+               ref = ref->next_in_ino;
+               if (!ref)
+                       return ref;
+       }
+
+       /* End of chain */
+       if (ref->flash_offset == REF_EMPTY_NODE)
+               return NULL;
+
+       return ref;
+}
+
+static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
+{
+       while(raw->next_in_ino)
+               raw = raw->next_in_ino;
+
+       /* NB. This can be a jffs2_xattr_datum or jffs2_xattr_ref and
+          not actually a jffs2_inode_cache. Check ->class */
+       return ((struct jffs2_inode_cache *)raw);
+}
+
         /* flash_offset & 3 always has to be zero, because nodes are
           always aligned at 4 bytes. So we have a couple of extra bits
           to play with, which indicate the node's status; see below: */
@@ -95,6 +133,11 @@ struct jffs2_raw_node_ref
 #define ref_obsolete(ref)      (((ref)->flash_offset & 3) == REF_OBSOLETE)
 #define mark_ref_normal(ref)    do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0)
 
+/* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates
+   it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get
+   copied. If you need to do anything different to GC inode-less nodes, then
+   you need to modify gc.c accordingly. */
+
 /* For each inode in the filesystem, we need to keep a record of
    nlink, because it would be a PITA to scan the whole directory tree
    at read_inode() time to calculate it, and to keep sufficient information
@@ -103,15 +146,27 @@ struct jffs2_raw_node_ref
    a pointer to the first physical node which is part of this inode, too.
 */
 struct jffs2_inode_cache {
+       /* First part of structure is shared with other objects which
+          can terminate the raw node refs' next_in_ino list -- which
+          currently struct jffs2_xattr_datum and struct jffs2_xattr_ref. */
+
        struct jffs2_full_dirent *scan_dents; /* Used during scan to hold
                temporary lists of dirents, and later must be set to
                NULL to mark the end of the raw_node_ref->next_in_ino
                chain. */
-       struct jffs2_inode_cache *next;
        struct jffs2_raw_node_ref *nodes;
+       uint8_t class;  /* It's used for identification */
+
+       /* end of shared structure */
+
+       uint8_t flags;
+       uint16_t state;
        uint32_t ino;
+       struct jffs2_inode_cache *next;
+#ifdef CONFIG_JFFS2_FS_XATTR
+       struct jffs2_xattr_ref *xref;
+#endif
        int nlink;
-       int state;
 };
 
 /* Inode states for 'state' above. We need the 'GC' state to prevent
@@ -125,8 +180,16 @@ struct jffs2_inode_cache {
 #define INO_STATE_READING      5       /* In read_inode() */
 #define INO_STATE_CLEARING     6       /* In clear_inode() */
 
+#define INO_FLAGS_XATTR_CHECKED        0x01    /* has no duplicate xattr_ref */
+
+#define RAWNODE_CLASS_INODE_CACHE      0
+#define RAWNODE_CLASS_XATTR_DATUM      1
+#define RAWNODE_CLASS_XATTR_REF                2
+
 #define INOCACHE_HASHSIZE 128
 
+#define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
+
 /*
   Larger representation of a raw node, kept in-core only when the
   struct inode for this particular ino is instantiated.
@@ -192,6 +255,7 @@ struct jffs2_eraseblock
        uint32_t wasted_size;
        uint32_t free_size;     /* Note that sector_size - free_size
                                   is the address of the first free space */
+       uint32_t allocated_refs;
        struct jffs2_raw_node_ref *first_node;
        struct jffs2_raw_node_ref *last_node;
 
@@ -203,57 +267,7 @@ static inline int jffs2_blocks_use_vmalloc(struct jffs2_sb_info *c)
        return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024);
 }
 
-/* Calculate totlen from surrounding nodes or eraseblock */
-static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
-                                   struct jffs2_eraseblock *jeb,
-                                   struct jffs2_raw_node_ref *ref)
-{
-       uint32_t ref_end;
-
-       if (ref->next_phys)
-               ref_end = ref_offset(ref->next_phys);
-       else {
-               if (!jeb)
-                       jeb = &c->blocks[ref->flash_offset / c->sector_size];
-
-               /* Last node in block. Use free_space */
-               BUG_ON(ref != jeb->last_node);
-               ref_end = jeb->offset + c->sector_size - jeb->free_size;
-       }
-       return ref_end - ref_offset(ref);
-}
-
-static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
-                                 struct jffs2_eraseblock *jeb,
-                                 struct jffs2_raw_node_ref *ref)
-{
-       uint32_t ret;
-
-#if CONFIG_JFFS2_FS_DEBUG > 0
-       if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
-               printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
-                      jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
-               BUG();
-       }
-#endif
-
-#if 1
-       ret = ref->__totlen;
-#else
-       /* This doesn't actually work yet */
-       ret = __ref_totlen(c, jeb, ref);
-       if (ret != ref->__totlen) {
-               printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
-                      ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
-                      ret, ref->__totlen);
-               if (!jeb)
-                       jeb = &c->blocks[ref->flash_offset / c->sector_size];
-               jffs2_dbg_dump_node_refs_nolock(c, jeb);
-               BUG();
-       }
-#endif
-       return ret;
-}
+#define ref_totlen(a, b, c) __jffs2_ref_totlen((a), (b), (c))
 
 #define ALLOC_NORMAL   0       /* Normal allocation */
 #define ALLOC_DELETION 1       /* Deletion node. Best to allow it */
@@ -268,13 +282,15 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
 
 #define PAD(x) (((x)+3)&~3)
 
-static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
+static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
 {
-       while(raw->next_in_ino) {
-               raw = raw->next_in_ino;
+       if (old_valid_dev(rdev)) {
+               jdev->old = cpu_to_je16(old_encode_dev(rdev));
+               return sizeof(jdev->old);
+       } else {
+               jdev->new = cpu_to_je32(new_encode_dev(rdev));
+               return sizeof(jdev->new);
        }
-
-       return ((struct jffs2_inode_cache *)raw);
 }
 
 static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
@@ -299,7 +315,6 @@ static inline struct jffs2_node_frag *frag_last(struct rb_root *root)
        return rb_entry(node, struct jffs2_node_frag, rb);
 }
 
-#define rb_parent(rb) ((rb)->rb_parent)
 #define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
 #define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb)
 #define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb)
@@ -324,28 +339,44 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t
 int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
 void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
 int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
+struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
+                                              struct jffs2_eraseblock *jeb,
+                                              uint32_t ofs, uint32_t len,
+                                              struct jffs2_inode_cache *ic);
+extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
+                                  struct jffs2_eraseblock *jeb,
+                                  struct jffs2_raw_node_ref *ref);
 
 /* nodemgmt.c */
 int jffs2_thread_should_wake(struct jffs2_sb_info *c);
-int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
+int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                        uint32_t *len, int prio, uint32_t sumsize);
-int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
+int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
                        uint32_t *len, uint32_t sumsize);
-int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new);
+struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, 
+                                                      uint32_t ofs, uint32_t len,
+                                                      struct jffs2_inode_cache *ic);
 void jffs2_complete_reservation(struct jffs2_sb_info *c);
 void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
 
 /* write.c */
 int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri);
 
-struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode);
-struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode);
+struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+                                          struct jffs2_raw_inode *ri, const unsigned char *data,
+                                          uint32_t datalen, int alloc_mode);
+struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+                                            struct jffs2_raw_dirent *rd, const unsigned char *name,
+                                            uint32_t namelen, int alloc_mode);
 int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                            struct jffs2_raw_inode *ri, unsigned char *buf,
                            uint32_t offset, uint32_t writelen, uint32_t *retlen);
-int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen);
-int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
-int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time);
+int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f,
+                   struct jffs2_raw_inode *ri, const char *name, int namelen);
+int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name,
+                   int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
+int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino,
+                  uint8_t type, const char *name, int namelen, uint32_t time);
 
 
 /* readinode.c */
@@ -368,12 +399,19 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void);
 void jffs2_free_raw_inode(struct jffs2_raw_inode *);
 struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void);
 void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *);
-struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void);
-void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *);
+int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
+                                struct jffs2_eraseblock *jeb, int nr);
+void jffs2_free_refblock(struct jffs2_raw_node_ref *);
 struct jffs2_node_frag *jffs2_alloc_node_frag(void);
 void jffs2_free_node_frag(struct jffs2_node_frag *);
 struct jffs2_inode_cache *jffs2_alloc_inode_cache(void);
 void jffs2_free_inode_cache(struct jffs2_inode_cache *);
+#ifdef CONFIG_JFFS2_FS_XATTR
+struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void);
+void jffs2_free_xattr_datum(struct jffs2_xattr_datum *);
+struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void);
+void jffs2_free_xattr_ref(struct jffs2_xattr_ref *);
+#endif
 
 /* gc.c */
 int jffs2_garbage_collect_pass(struct jffs2_sb_info *c);
@@ -393,12 +431,14 @@ int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf,
                                uint32_t ofs, uint32_t len);
 struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino);
 int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
+int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t size);
 
 /* build.c */
 int jffs2_do_mount_fs(struct jffs2_sb_info *c);
 
 /* erase.c */
 void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count);
+void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 /* wbuf.c */
index 49127a1f045861324bab8e79570b895b7b1ab4c5..8bedfd2ff68991c19f212159d48fb6b5694e7700 100644 (file)
  *     jffs2_reserve_space - request physical space to write nodes to flash
  *     @c: superblock info
  *     @minsize: Minimum acceptable size of allocation
- *     @ofs: Returned value of node offset
  *     @len: Returned value of allocation length
  *     @prio: Allocation type - ALLOC_{NORMAL,DELETION}
  *
  *     Requests a block of physical space on the flash. Returns zero for success
- *     and puts 'ofs' and 'len' into the appriopriate place, or returns -ENOSPC
- *     or other error if appropriate.
+ *     and puts 'len' into the appropriate place, or returns -ENOSPC or other 
+ *     error if appropriate. Doesn't return len since that's 
  *
  *     If it returns zero, jffs2_reserve_space() also downs the per-filesystem
  *     allocation semaphore, to prevent more than one allocation from being
@@ -40,9 +39,9 @@
  */
 
 static int jffs2_do_reserve_space(struct jffs2_sb_info *c,  uint32_t minsize,
-                                       uint32_t *ofs, uint32_t *len, uint32_t sumsize);
+                                 uint32_t *len, uint32_t sumsize);
 
-int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
+int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                        uint32_t *len, int prio, uint32_t sumsize)
 {
        int ret = -EAGAIN;
@@ -132,19 +131,21 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs
                        spin_lock(&c->erase_completion_lock);
                }
 
-               ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize);
+               ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
                if (ret) {
                        D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret));
                }
        }
        spin_unlock(&c->erase_completion_lock);
+       if (!ret)
+               ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
        if (ret)
                up(&c->alloc_sem);
        return ret;
 }
 
-int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
-                       uint32_t *len, uint32_t sumsize)
+int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
+                          uint32_t *len, uint32_t sumsize)
 {
        int ret = -EAGAIN;
        minsize = PAD(minsize);
@@ -153,12 +154,15 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *
 
        spin_lock(&c->erase_completion_lock);
        while(ret == -EAGAIN) {
-               ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize);
+               ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
                if (ret) {
                        D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
                }
        }
        spin_unlock(&c->erase_completion_lock);
+       if (!ret)
+               ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+
        return ret;
 }
 
@@ -259,10 +263,11 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
 }
 
 /* Called with alloc sem _and_ erase_completion_lock */
-static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize)
+static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+                                 uint32_t *len, uint32_t sumsize)
 {
        struct jffs2_eraseblock *jeb = c->nextblock;
-       uint32_t reserved_size;                         /* for summary information at the end of the jeb */
+       uint32_t reserved_size;                         /* for summary information at the end of the jeb */
        int ret;
 
  restart:
@@ -312,6 +317,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
                }
        } else {
                if (jeb && minsize > jeb->free_size) {
+                       uint32_t waste;
+
                        /* Skip the end of this block and file it as having some dirty space */
                        /* If there's a pending write to it, flush now */
 
@@ -324,10 +331,26 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
                                goto restart;
                        }
 
-                       c->wasted_size += jeb->free_size;
-                       c->free_size -= jeb->free_size;
-                       jeb->wasted_size += jeb->free_size;
-                       jeb->free_size = 0;
+                       spin_unlock(&c->erase_completion_lock);
+
+                       ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
+                       if (ret)
+                               return ret;
+                       /* Just lock it again and continue. Nothing much can change because
+                          we hold c->alloc_sem anyway. In fact, it's not entirely clear why
+                          we hold c->erase_completion_lock in the majority of this function...
+                          but that's a question for another (more caffeine-rich) day. */
+                       spin_lock(&c->erase_completion_lock);
+
+                       waste = jeb->free_size;
+                       jffs2_link_node_ref(c, jeb,
+                                           (jeb->offset + c->sector_size - waste) | REF_OBSOLETE,
+                                           waste, NULL);
+                       /* FIXME: that made it count as dirty. Convert to wasted */
+                       jeb->dirty_size -= waste;
+                       c->dirty_size -= waste;
+                       jeb->wasted_size += waste;
+                       c->wasted_size += waste;
 
                        jffs2_close_nextblock(c, jeb);
                        jeb = NULL;
@@ -349,7 +372,6 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
        }
        /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has
           enough space */
-       *ofs = jeb->offset + (c->sector_size - jeb->free_size);
        *len = jeb->free_size - reserved_size;
 
        if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size &&
@@ -365,7 +387,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
                spin_lock(&c->erase_completion_lock);
        }
 
-       D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", *len, *ofs));
+       D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n",
+                 *len, jeb->offset + (c->sector_size - jeb->free_size)));
        return 0;
 }
 
@@ -374,7 +397,6 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
  *     @c: superblock info
  *     @new: new node reference to add
  *     @len: length of this physical node
- *     @dirty: dirty flag for new node
  *
  *     Should only be used to report nodes for which space has been allocated
  *     by jffs2_reserve_space.
@@ -382,42 +404,30 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
  *     Must be called with the alloc_sem held.
  */
 
-int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new)
+struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
+                                                      uint32_t ofs, uint32_t len,
+                                                      struct jffs2_inode_cache *ic)
 {
        struct jffs2_eraseblock *jeb;
-       uint32_t len;
+       struct jffs2_raw_node_ref *new;
 
-       jeb = &c->blocks[new->flash_offset / c->sector_size];
-       len = ref_totlen(c, jeb, new);
+       jeb = &c->blocks[ofs / c->sector_size];
 
-       D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len));
+       D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n",
+                 ofs & ~3, ofs & 3, len));
 #if 1
-       /* we could get some obsolete nodes after nextblock was refiled
-          in wbuf.c */
-       if ((c->nextblock || !ref_obsolete(new))
-           &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) {
+       /* Allow non-obsolete nodes only to be added at the end of c->nextblock, 
+          if c->nextblock is set. Note that wbuf.c will file obsolete nodes
+          even after refiling c->nextblock */
+       if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
+           && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
                printk(KERN_WARNING "argh. node added in wrong place\n");
-               jffs2_free_raw_node_ref(new);
-               return -EINVAL;
+               return ERR_PTR(-EINVAL);
        }
 #endif
        spin_lock(&c->erase_completion_lock);
 
-       if (!jeb->first_node)
-               jeb->first_node = new;
-       if (jeb->last_node)
-               jeb->last_node->next_phys = new;
-       jeb->last_node = new;
-
-       jeb->free_size -= len;
-       c->free_size -= len;
-       if (ref_obsolete(new)) {
-               jeb->dirty_size += len;
-               c->dirty_size += len;
-       } else {
-               jeb->used_size += len;
-               c->used_size += len;
-       }
+       new = jffs2_link_node_ref(c, jeb, ofs, len, ic);
 
        if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
                /* If it lives on the dirty_list, jffs2_reserve_space will put it there */
@@ -438,7 +448,7 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r
 
        spin_unlock(&c->erase_completion_lock);
 
-       return 0;
+       return new;
 }
 
 
@@ -470,8 +480,9 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
        struct jffs2_unknown_node n;
        int ret, addedsize;
        size_t retlen;
+       uint32_t freed_len;
 
-       if(!ref) {
+       if(unlikely(!ref)) {
                printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
                return;
        }
@@ -499,32 +510,34 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
 
        spin_lock(&c->erase_completion_lock);
 
+       freed_len = ref_totlen(c, jeb, ref);
+
        if (ref_flags(ref) == REF_UNCHECKED) {
-               D1(if (unlikely(jeb->unchecked_size < ref_totlen(c, jeb, ref))) {
+               D1(if (unlikely(jeb->unchecked_size < freed_len)) {
                        printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n",
-                              ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size);
+                              freed_len, blocknr, ref->flash_offset, jeb->used_size);
                        BUG();
                })
-               D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref)));
-               jeb->unchecked_size -= ref_totlen(c, jeb, ref);
-               c->unchecked_size -= ref_totlen(c, jeb, ref);
+               D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), freed_len));
+               jeb->unchecked_size -= freed_len;
+               c->unchecked_size -= freed_len;
        } else {
-               D1(if (unlikely(jeb->used_size < ref_totlen(c, jeb, ref))) {
+               D1(if (unlikely(jeb->used_size < freed_len)) {
                        printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n",
-                              ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size);
+                              freed_len, blocknr, ref->flash_offset, jeb->used_size);
                        BUG();
                })
-               D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), ref_totlen(c, jeb, ref)));
-               jeb->used_size -= ref_totlen(c, jeb, ref);
-               c->used_size -= ref_totlen(c, jeb, ref);
+               D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), freed_len));
+               jeb->used_size -= freed_len;
+               c->used_size -= freed_len;
        }
 
        // Take care, that wasted size is taken into concern
-       if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref_totlen(c, jeb, ref))) && jeb != c->nextblock) {
-               D1(printk(KERN_DEBUG "Dirtying\n"));
-               addedsize = ref_totlen(c, jeb, ref);
-               jeb->dirty_size += ref_totlen(c, jeb, ref);
-               c->dirty_size += ref_totlen(c, jeb, ref);
+       if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) {
+               D1(printk("Dirtying\n"));
+               addedsize = freed_len;
+               jeb->dirty_size += freed_len;
+               c->dirty_size += freed_len;
 
                /* Convert wasted space to dirty, if not a bad block */
                if (jeb->wasted_size) {
@@ -543,10 +556,10 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                        }
                }
        } else {
-               D1(printk(KERN_DEBUG "Wasting\n"));
+               D1(printk("Wasting\n"));
                addedsize = 0;
-               jeb->wasted_size += ref_totlen(c, jeb, ref);
-               c->wasted_size += ref_totlen(c, jeb, ref);
+               jeb->wasted_size += freed_len;
+               c->wasted_size += freed_len;
        }
        ref->flash_offset = ref_offset(ref) | REF_OBSOLETE;
 
@@ -622,7 +635,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
        /* The erase_free_sem is locked, and has been since before we marked the node obsolete
           and potentially put its eraseblock onto the erase_pending_list. Thus, we know that
           the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet
-          by jffs2_free_all_node_refs() in erase.c. Which is nice. */
+          by jffs2_free_jeb_node_refs() in erase.c. Which is nice. */
 
        D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref)));
        ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
@@ -634,8 +647,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen);
                goto out_erase_sem;
        }
-       if (PAD(je32_to_cpu(n.totlen)) != PAD(ref_totlen(c, jeb, ref))) {
-               printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), ref_totlen(c, jeb, ref));
+       if (PAD(je32_to_cpu(n.totlen)) != PAD(freed_len)) {
+               printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), freed_len);
                goto out_erase_sem;
        }
        if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) {
@@ -671,6 +684,10 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                spin_lock(&c->erase_completion_lock);
 
                ic = jffs2_raw_ref_to_ic(ref);
+               /* It seems we should never call jffs2_mark_node_obsolete() for
+                  XATTR nodes.... yet. Make sure we notice if/when we change
+                  that :) */
+               BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
                for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
                        ;
 
@@ -683,51 +700,6 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                spin_unlock(&c->erase_completion_lock);
        }
 
-
-       /* Merge with the next node in the physical list, if there is one
-          and if it's also obsolete and if it doesn't belong to any inode */
-       if (ref->next_phys && ref_obsolete(ref->next_phys) &&
-           !ref->next_phys->next_in_ino) {
-               struct jffs2_raw_node_ref *n = ref->next_phys;
-
-               spin_lock(&c->erase_completion_lock);
-
-               ref->__totlen += n->__totlen;
-               ref->next_phys = n->next_phys;
-                if (jeb->last_node == n) jeb->last_node = ref;
-               if (jeb->gc_node == n) {
-                       /* gc will be happy continuing gc on this node */
-                       jeb->gc_node=ref;
-               }
-               spin_unlock(&c->erase_completion_lock);
-
-               jffs2_free_raw_node_ref(n);
-       }
-
-       /* Also merge with the previous node in the list, if there is one
-          and that one is obsolete */
-       if (ref != jeb->first_node ) {
-               struct jffs2_raw_node_ref *p = jeb->first_node;
-
-               spin_lock(&c->erase_completion_lock);
-
-               while (p->next_phys != ref)
-                       p = p->next_phys;
-
-               if (ref_obsolete(p) && !ref->next_in_ino) {
-                       p->__totlen += ref->__totlen;
-                       if (jeb->last_node == ref) {
-                               jeb->last_node = p;
-                       }
-                       if (jeb->gc_node == ref) {
-                               /* gc will be happy continuing gc on this node */
-                               jeb->gc_node=p;
-                       }
-                       p->next_phys = ref->next_phys;
-                       jffs2_free_raw_node_ref(ref);
-               }
-               spin_unlock(&c->erase_completion_lock);
-       }
  out_erase_sem:
        up(&c->erase_free_sem);
 }
index d307cf548625b5a9b654af3c711b6c619edbfce9..cd4021bcb9441d4ccf59668aa4d1315105245186 100644 (file)
@@ -31,9 +31,7 @@ struct kvec;
 #define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
 #define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid)
 #define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid)
-
-#define JFFS2_F_I_RDEV_MIN(f) (iminor(OFNI_EDONI_2SFFJ(f)))
-#define JFFS2_F_I_RDEV_MAJ(f) (imajor(OFNI_EDONI_2SFFJ(f)))
+#define JFFS2_F_I_RDEV(f) (OFNI_EDONI_2SFFJ(f)->i_rdev)
 
 #define ITIME(sec) ((struct timespec){sec, 0})
 #define I_SEC(tv) ((tv).tv_sec)
@@ -60,6 +58,10 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
        f->target = NULL;
        f->flags = 0;
        f->usercompr = 0;
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+       f->i_acl_access = JFFS2_ACL_NOT_CACHED;
+       f->i_acl_default = JFFS2_ACL_NOT_CACHED;
+#endif
 }
 
 
@@ -90,13 +92,10 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
 #define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e)
 #define jffs2_wbuf_timeout NULL
 #define jffs2_wbuf_process NULL
-#define jffs2_nor_ecc(c) (0)
 #define jffs2_dataflash(c) (0)
-#define jffs2_nor_wbuf_flash(c) (0)
-#define jffs2_nor_ecc_flash_setup(c) (0)
-#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0)
 #define jffs2_dataflash_setup(c) (0)
 #define jffs2_dataflash_cleanup(c) do {} while (0)
+#define jffs2_nor_wbuf_flash(c) (0)
 #define jffs2_nor_wbuf_flash_setup(c) (0)
 #define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0)
 
@@ -107,9 +106,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
 #ifdef CONFIG_JFFS2_SUMMARY
 #define jffs2_can_mark_obsolete(c) (0)
 #else
-#define jffs2_can_mark_obsolete(c) \
-  ((c->mtd->type == MTD_NORFLASH && !(c->mtd->flags & (MTD_ECC|MTD_PROGRAM_REGIONS))) || \
-   c->mtd->type == MTD_RAM)
+#define jffs2_can_mark_obsolete(c) (c->mtd->flags & (MTD_BIT_WRITEABLE))
 #endif
 
 #define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH)
@@ -133,15 +130,11 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c);
 int jffs2_nand_flash_setup(struct jffs2_sb_info *c);
 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c);
 
-#define jffs2_nor_ecc(c) (c->mtd->type == MTD_NORFLASH && (c->mtd->flags & MTD_ECC))
-int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c);
-void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c);
-
 #define jffs2_dataflash(c) (c->mtd->type == MTD_DATAFLASH)
 int jffs2_dataflash_setup(struct jffs2_sb_info *c);
 void jffs2_dataflash_cleanup(struct jffs2_sb_info *c);
 
-#define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && (c->mtd->flags & MTD_PROGRAM_REGIONS))
+#define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && ! (c->mtd->flags & MTD_BIT_WRITEABLE))
 int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c);
 void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c);
 
index f1695642d0f7f218757fbdcff49ac0e0ed440a35..5fec012b02ed59a1fa5f8ca871849af4c24e4e40 100644 (file)
@@ -66,7 +66,7 @@ static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
                        jffs2_free_full_dnode(tn->fn);
                        jffs2_free_tmp_dnode_info(tn);
 
-                       this = this->rb_parent;
+                       this = rb_parent(this);
                        if (!this)
                                break;
 
@@ -116,19 +116,42 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
                                uint32_t *latest_mctime, uint32_t *mctime_ver)
 {
        struct jffs2_full_dirent *fd;
+       uint32_t crc;
 
-       /* The direntry nodes are checked during the flash scanning */
-       BUG_ON(ref_flags(ref) == REF_UNCHECKED);
        /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
        BUG_ON(ref_obsolete(ref));
 
-       /* Sanity check */
-       if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
-               JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
-                      ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
+       crc = crc32(0, rd, sizeof(*rd) - 8);
+       if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
+               JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n",
+                            ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
                return 1;
        }
 
+       /* If we've never checked the CRCs on this node, check them now */
+       if (ref_flags(ref) == REF_UNCHECKED) {
+               struct jffs2_eraseblock *jeb;
+               int len;
+
+               /* Sanity check */
+               if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
+                       JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
+                                   ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
+                       return 1;
+               }
+
+               jeb = &c->blocks[ref->flash_offset / c->sector_size];
+               len = ref_totlen(c, jeb, ref);
+
+               spin_lock(&c->erase_completion_lock);
+               jeb->used_size += len;
+               jeb->unchecked_size -= len;
+               c->used_size += len;
+               c->unchecked_size -= len;
+               ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
+               spin_unlock(&c->erase_completion_lock);
+       }
+
        fd = jffs2_alloc_full_dirent(rd->nsize + 1);
        if (unlikely(!fd))
                return -ENOMEM;
@@ -198,13 +221,21 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
        struct jffs2_tmp_dnode_info *tn;
        uint32_t len, csize;
        int ret = 1;
+       uint32_t crc;
 
        /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
        BUG_ON(ref_obsolete(ref));
 
+       crc = crc32(0, rd, sizeof(*rd) - 8);
+       if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
+               JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n",
+                            ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
+               return 1;
+       }
+
        tn = jffs2_alloc_tmp_dnode_info();
        if (!tn) {
-               JFFS2_ERROR("failed to allocate tn (%d bytes).\n", sizeof(*tn));
+               JFFS2_ERROR("failed to allocate tn (%zu bytes).\n", sizeof(*tn));
                return -ENOMEM;
        }
 
@@ -213,14 +244,6 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
 
        /* If we've never checked the CRCs on this node, check them now */
        if (ref_flags(ref) == REF_UNCHECKED) {
-               uint32_t crc;
-
-               crc = crc32(0, rd, sizeof(*rd) - 8);
-               if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
-                       JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
-                                       ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
-                       goto free_out;
-               }
 
                /* Sanity checks */
                if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
@@ -343,7 +366,7 @@ free_out:
  * Helper function for jffs2_get_inode_nodes().
  * It is called every time an unknown node is found.
  *
- * Returns: 0 on succes;
+ * Returns: 0 on success;
  *         1 if the node should be marked obsolete;
  *         negative error code on failure.
  */
@@ -354,37 +377,30 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
 
        un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
 
-       if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) {
-               /* Hmmm. This should have been caught at scan time. */
-               JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref));
-               jffs2_dbg_dump_node(c, ref_offset(ref));
-               return 1;
-       } else {
-               switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
+       switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
 
-               case JFFS2_FEATURE_INCOMPAT:
-                       JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
-                               je16_to_cpu(un->nodetype), ref_offset(ref));
-                       /* EEP */
-                       BUG();
-                       break;
+       case JFFS2_FEATURE_INCOMPAT:
+               JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
+                           je16_to_cpu(un->nodetype), ref_offset(ref));
+               /* EEP */
+               BUG();
+               break;
 
-               case JFFS2_FEATURE_ROCOMPAT:
-                       JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
-                                       je16_to_cpu(un->nodetype), ref_offset(ref));
-                       BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
-                       break;
+       case JFFS2_FEATURE_ROCOMPAT:
+               JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
+                           je16_to_cpu(un->nodetype), ref_offset(ref));
+               BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
+               break;
 
-               case JFFS2_FEATURE_RWCOMPAT_COPY:
-                       JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
-                                       je16_to_cpu(un->nodetype), ref_offset(ref));
-                       break;
+       case JFFS2_FEATURE_RWCOMPAT_COPY:
+               JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
+                            je16_to_cpu(un->nodetype), ref_offset(ref));
+               break;
 
-               case JFFS2_FEATURE_RWCOMPAT_DELETE:
-                       JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
-                                       je16_to_cpu(un->nodetype), ref_offset(ref));
-                       return 1;
-               }
+       case JFFS2_FEATURE_RWCOMPAT_DELETE:
+               JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
+                            je16_to_cpu(un->nodetype), ref_offset(ref));
+               return 1;
        }
 
        return 0;
@@ -434,7 +450,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
        }
 
        if (retlen < len) {
-               JFFS2_ERROR("short read at %#08x: %d instead of %d.\n",
+               JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n",
                                offs, retlen, len);
                return -EIO;
        }
@@ -542,13 +558,25 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
                }
 
                if (retlen < len) {
-                       JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len);
+                       JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", ref_offset(ref), retlen, len);
                        err = -EIO;
                        goto free_out;
                }
 
                node = (union jffs2_node_union *)bufstart;
 
+               /* No need to mask in the valid bit; it shouldn't be invalid */
+               if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
+                       JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n",
+                                    ref_offset(ref), je16_to_cpu(node->u.magic),
+                                    je16_to_cpu(node->u.nodetype),
+                                    je32_to_cpu(node->u.totlen),
+                                    je32_to_cpu(node->u.hdr_crc));
+                       jffs2_dbg_dump_node(c, ref_offset(ref));
+                       jffs2_mark_node_obsolete(c, ref);
+                       goto cont;
+               }
+
                switch (je16_to_cpu(node->u.nodetype)) {
 
                case JFFS2_NODETYPE_DIRENT:
@@ -606,6 +634,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
                                goto free_out;
 
                }
+       cont:
                spin_lock(&c->erase_completion_lock);
        }
 
@@ -679,12 +708,12 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
                        jffs2_mark_node_obsolete(c, fn->raw);
 
                BUG_ON(rb->rb_left);
-               if (rb->rb_parent && rb->rb_parent->rb_left == rb) {
+               if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) {
                        /* We were then left-hand child of our parent. We need
                         * to move our own right-hand child into our place. */
                        repl_rb = rb->rb_right;
                        if (repl_rb)
-                               repl_rb->rb_parent = rb->rb_parent;
+                               rb_set_parent(repl_rb, rb_parent(rb));
                } else
                        repl_rb = NULL;
 
@@ -692,14 +721,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
 
                /* Remove the spent tn from the tree; don't bother rebalancing
                 * but put our right-hand child in our own place. */
-               if (tn->rb.rb_parent) {
-                       if (tn->rb.rb_parent->rb_left == &tn->rb)
-                               tn->rb.rb_parent->rb_left = repl_rb;
-                       else if (tn->rb.rb_parent->rb_right == &tn->rb)
-                               tn->rb.rb_parent->rb_right = repl_rb;
+               if (rb_parent(&tn->rb)) {
+                       if (rb_parent(&tn->rb)->rb_left == &tn->rb)
+                               rb_parent(&tn->rb)->rb_left = repl_rb;
+                       else if (rb_parent(&tn->rb)->rb_right == &tn->rb)
+                               rb_parent(&tn->rb)->rb_right = repl_rb;
                        else BUG();
                } else if (tn->rb.rb_right)
-                       tn->rb.rb_right->rb_parent = NULL;
+                       rb_set_parent(tn->rb.rb_right, NULL);
 
                jffs2_free_tmp_dnode_info(tn);
                if (ret) {
index cf55b221fc2b7dc86d9778a4c6d5c02a38fdbb70..61618080b86f0a9bfe3202e39c8e452f13a21ec5 100644 (file)
@@ -65,6 +65,28 @@ static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size) {
                return DEFAULT_EMPTY_SCAN_SIZE;
 }
 
+static int file_dirty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+{
+       int ret;
+
+       if ((ret = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
+               return ret;
+       if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
+               return ret;
+       /* Turned wasted size into dirty, since we apparently 
+          think it's recoverable now. */
+       jeb->dirty_size += jeb->wasted_size;
+       c->dirty_size += jeb->wasted_size;
+       c->wasted_size -= jeb->wasted_size;
+       jeb->wasted_size = 0;
+       if (VERYDIRTY(c, jeb->dirty_size)) {
+               list_add(&jeb->list, &c->very_dirty_list);
+       } else {
+               list_add(&jeb->list, &c->dirty_list);
+       }
+       return 0;
+}
+
 int jffs2_scan_medium(struct jffs2_sb_info *c)
 {
        int i, ret;
@@ -170,34 +192,20 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
                                        (!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
                                /* Better candidate for the next writes to go to */
                                if (c->nextblock) {
-                                       c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size;
-                                       c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size;
-                                       c->free_size -= c->nextblock->free_size;
-                                       c->wasted_size -= c->nextblock->wasted_size;
-                                       c->nextblock->free_size = c->nextblock->wasted_size = 0;
-                                       if (VERYDIRTY(c, c->nextblock->dirty_size)) {
-                                               list_add(&c->nextblock->list, &c->very_dirty_list);
-                                       } else {
-                                               list_add(&c->nextblock->list, &c->dirty_list);
-                                       }
+                                       ret = file_dirty(c, c->nextblock);
+                                       if (ret)
+                                               return ret;
                                        /* deleting summary information of the old nextblock */
                                        jffs2_sum_reset_collected(c->summary);
                                }
-                               /* update collected summary infromation for the current nextblock */
+                               /* update collected summary information for the current nextblock */
                                jffs2_sum_move_collected(c, s);
                                D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset));
                                c->nextblock = jeb;
                        } else {
-                               jeb->dirty_size += jeb->free_size + jeb->wasted_size;
-                               c->dirty_size += jeb->free_size + jeb->wasted_size;
-                               c->free_size -= jeb->free_size;
-                               c->wasted_size -= jeb->wasted_size;
-                               jeb->free_size = jeb->wasted_size = 0;
-                               if (VERYDIRTY(c, jeb->dirty_size)) {
-                                       list_add(&jeb->list, &c->very_dirty_list);
-                               } else {
-                                       list_add(&jeb->list, &c->dirty_list);
-                               }
+                               ret = file_dirty(c, jeb);
+                               if (ret)
+                                       return ret;
                        }
                        break;
 
@@ -222,9 +230,6 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
                }
        }
 
-       if (jffs2_sum_active() && s)
-               kfree(s);
-
        /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */
        if (c->nextblock && (c->nextblock->dirty_size)) {
                c->nextblock->wasted_size += c->nextblock->dirty_size;
@@ -242,11 +247,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
 
                D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n",
                          skip));
-               c->nextblock->wasted_size += skip;
-               c->wasted_size += skip;
-
-               c->nextblock->free_size -= skip;
-               c->free_size -= skip;
+               jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+               jffs2_scan_dirty_space(c, c->nextblock, skip);
        }
 #endif
        if (c->nr_erasing_blocks) {
@@ -266,6 +268,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
        else
                c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size);
 #endif
+       if (s)
+               kfree(s);
+
        return ret;
 }
 
@@ -290,7 +295,7 @@ int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf,
 int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
        if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size
-               && (!jeb->first_node || !jeb->first_node->next_phys) )
+           && (!jeb->first_node || !ref_next(jeb->first_node)) )
                return BLK_STATE_CLEANMARKER;
 
        /* move blocks with max 4 byte dirty space to cleanlist */
@@ -306,11 +311,119 @@ int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
                return BLK_STATE_ALLDIRTY;
 }
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+                                struct jffs2_raw_xattr *rx, uint32_t ofs,
+                                struct jffs2_summary *s)
+{
+       struct jffs2_xattr_datum *xd;
+       uint32_t totlen, crc;
+       int err;
+
+       crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
+       if (crc != je32_to_cpu(rx->node_crc)) {
+               if (je32_to_cpu(rx->node_crc) != 0xffffffff)
+                       JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+                                     ofs, je32_to_cpu(rx->node_crc), crc);
+               if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
+                       return err;
+               return 0;
+       }
+
+       totlen = PAD(sizeof(*rx) + rx->name_len + 1 + je16_to_cpu(rx->value_len));
+       if (totlen != je32_to_cpu(rx->totlen)) {
+               JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
+                             ofs, je32_to_cpu(rx->totlen), totlen);
+               if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
+                       return err;
+               return 0;
+       }
+
+       xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version));
+       if (IS_ERR(xd)) {
+               if (PTR_ERR(xd) == -EEXIST) {
+                       if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen)))))
+                               return err;
+                       return 0;
+               }
+               return PTR_ERR(xd);
+       }
+       xd->xprefix = rx->xprefix;
+       xd->name_len = rx->name_len;
+       xd->value_len = je16_to_cpu(rx->value_len);
+       xd->data_crc = je32_to_cpu(rx->data_crc);
+
+       xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
+       /* FIXME */ xd->node->next_in_ino = (void *)xd;
+
+       if (jffs2_sum_active())
+               jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
+       dbg_xattr("scaning xdatum at %#08x (xid=%u, version=%u)\n",
+                 ofs, xd->xid, xd->version);
+       return 0;
+}
+
+static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+                               struct jffs2_raw_xref *rr, uint32_t ofs,
+                               struct jffs2_summary *s)
+{
+       struct jffs2_xattr_ref *ref;
+       uint32_t crc;
+       int err;
+
+       crc = crc32(0, rr, sizeof(*rr) - 4);
+       if (crc != je32_to_cpu(rr->node_crc)) {
+               if (je32_to_cpu(rr->node_crc) != 0xffffffff)
+                       JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+                                     ofs, je32_to_cpu(rr->node_crc), crc);
+               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
+                       return err;
+               return 0;
+       }
+
+       if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) {
+               JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%zd\n",
+                             ofs, je32_to_cpu(rr->totlen),
+                             PAD(sizeof(struct jffs2_raw_xref)));
+               if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rr->totlen))))
+                       return err;
+               return 0;
+       }
+
+       ref = jffs2_alloc_xattr_ref();
+       if (!ref)
+               return -ENOMEM;
+
+       /* BEFORE jffs2_build_xattr_subsystem() called, 
+        * ref->xid is used to store 32bit xid, xd is not used
+        * ref->ino is used to store 32bit inode-number, ic is not used
+        * Thoes variables are declared as union, thus using those
+        * are exclusive. In a similar way, ref->next is temporarily
+        * used to chain all xattr_ref object. It's re-chained to
+        * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
+        */
+       ref->ino = je32_to_cpu(rr->ino);
+       ref->xid = je32_to_cpu(rr->xid);
+       ref->next = c->xref_temp;
+       c->xref_temp = ref;
+
+       ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL);
+       /* FIXME */ ref->node->next_in_ino = (void *)ref;
+
+       if (jffs2_sum_active())
+               jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
+       dbg_xattr("scan xref at %#08x (xid=%u, ino=%u)\n",
+                 ofs, ref->xid, ref->ino);
+       return 0;
+}
+#endif
+
+/* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into
+   the flash, XIP-style */
 static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-                               unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
+                                 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
        struct jffs2_unknown_node *node;
        struct jffs2_unknown_node crcnode;
-       struct jffs2_sum_marker *sm;
        uint32_t ofs, prevofs;
        uint32_t hdr_crc, buf_ofs, buf_len;
        int err;
@@ -344,44 +457,75 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
 #endif
 
        if (jffs2_sum_active()) {
-               sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL);
-               if (!sm) {
-                       return -ENOMEM;
-               }
-
-               err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size -
-                                       sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker));
-               if (err) {
-                       kfree(sm);
-                       return err;
-               }
-
-               if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) {
-                       err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random);
-                       if (err) {
-                               kfree(sm);
+               struct jffs2_sum_marker *sm;
+               void *sumptr = NULL;
+               uint32_t sumlen;
+             
+               if (!buf_size) {
+                       /* XIP case. Just look, point at the summary if it's there */
+                       sm = (void *)buf + c->sector_size - sizeof(*sm);
+                       if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
+                               sumptr = buf + je32_to_cpu(sm->offset);
+                               sumlen = c->sector_size - je32_to_cpu(sm->offset);
+                       }
+               } else {
+                       /* If NAND flash, read a whole page of it. Else just the end */
+                       if (c->wbuf_pagesize)
+                               buf_len = c->wbuf_pagesize;
+                       else
+                               buf_len = sizeof(*sm);
+
+                       /* Read as much as we want into the _end_ of the preallocated buffer */
+                       err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len, 
+                                                 jeb->offset + c->sector_size - buf_len,
+                                                 buf_len);                             
+                       if (err)
                                return err;
+
+                       sm = (void *)buf + buf_size - sizeof(*sm);
+                       if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
+                               sumlen = c->sector_size - je32_to_cpu(sm->offset);
+                               sumptr = buf + buf_size - sumlen;
+
+                               /* Now, make sure the summary itself is available */
+                               if (sumlen > buf_size) {
+                                       /* Need to kmalloc for this. */
+                                       sumptr = kmalloc(sumlen, GFP_KERNEL);
+                                       if (!sumptr)
+                                               return -ENOMEM;
+                                       memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len);
+                               }
+                               if (buf_len < sumlen) {
+                                       /* Need to read more so that the entire summary node is present */
+                                       err = jffs2_fill_scan_buf(c, sumptr, 
+                                                                 jeb->offset + c->sector_size - sumlen,
+                                                                 sumlen - buf_len);                            
+                                       if (err)
+                                               return err;
+                               }
                        }
+
                }
 
-               kfree(sm);
+               if (sumptr) {
+                       err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random);
 
-               ofs = jeb->offset;
-               prevofs = jeb->offset - 1;
+                       if (buf_size && sumlen > buf_size)
+                               kfree(sumptr);
+                       /* If it returns with a real error, bail. 
+                          If it returns positive, that's a block classification
+                          (i.e. BLK_STATE_xxx) so return that too.
+                          If it returns zero, fall through to full scan. */
+                       if (err)
+                               return err;
+               }
        }
 
        buf_ofs = jeb->offset;
 
        if (!buf_size) {
+               /* This is the XIP case -- we're reading _directly_ from the flash chip */
                buf_len = c->sector_size;
-
-               if (jffs2_sum_active()) {
-                       /* must reread because of summary test */
-                       err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
-                       if (err)
-                               return err;
-               }
-
        } else {
                buf_len = EMPTY_SCAN_SIZE(c->sector_size);
                err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
@@ -418,7 +562,10 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
        if (ofs) {
                D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset,
                          jeb->offset + ofs));
-               DIRTY_SPACE(ofs);
+               if ((err = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
+                       return err;
+               if ((err = jffs2_scan_dirty_space(c, jeb, ofs)))
+                       return err;
        }
 
        /* Now ofs is a complete physical flash offset as it always was... */
@@ -433,6 +580,11 @@ scan_more:
 
                jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
 
+               /* Make sure there are node refs available for use */
+               err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
+               if (err)
+                       return err;
+
                cond_resched();
 
                if (ofs & 3) {
@@ -442,7 +594,8 @@ scan_more:
                }
                if (ofs == prevofs) {
                        printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs);
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
@@ -451,7 +604,8 @@ scan_more:
                if (jeb->offset + c->sector_size < ofs + sizeof(*node)) {
                        D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node),
                                  jeb->offset, c->sector_size, ofs, sizeof(*node)));
-                       DIRTY_SPACE((jeb->offset + c->sector_size)-ofs);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs)))
+                               return err;
                        break;
                }
 
@@ -481,7 +635,8 @@ scan_more:
                                if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) {
                                        printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n",
                                               empty_start, ofs);
-                                       DIRTY_SPACE(ofs-empty_start);
+                                       if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
+                                               return err;
                                        goto scan_more;
                                }
 
@@ -494,7 +649,7 @@ scan_more:
                        /* If we're only checking the beginning of a block with a cleanmarker,
                           bail now */
                        if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) &&
-                           c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) {
+                           c->cleanmarker_size && !jeb->dirty_size && !ref_next(jeb->first_node)) {
                                D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size)));
                                return BLK_STATE_CLEANMARKER;
                        }
@@ -518,20 +673,23 @@ scan_more:
 
                if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) {
                        printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs);
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
                if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) {
                        D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs));
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
                if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) {
                        printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs);
                        printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n");
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
@@ -540,7 +698,8 @@ scan_more:
                        noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n",
                                     JFFS2_MAGIC_BITMASK, ofs,
                                     je16_to_cpu(node->magic));
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
@@ -557,7 +716,8 @@ scan_more:
                                     je32_to_cpu(node->totlen),
                                     je32_to_cpu(node->hdr_crc),
                                     hdr_crc);
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
@@ -568,7 +728,8 @@ scan_more:
                        printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
                               ofs, je32_to_cpu(node->totlen));
                        printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n");
-                       DIRTY_SPACE(4);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+                               return err;
                        ofs += 4;
                        continue;
                }
@@ -576,7 +737,8 @@ scan_more:
                if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) {
                        /* Wheee. This is an obsoleted node */
                        D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs));
-                       DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+                       if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+                               return err;
                        ofs += PAD(je32_to_cpu(node->totlen));
                        continue;
                }
@@ -614,30 +776,59 @@ scan_more:
                        ofs += PAD(je32_to_cpu(node->totlen));
                        break;
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+               case JFFS2_NODETYPE_XATTR:
+                       if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
+                               buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
+                               D1(printk(KERN_DEBUG "Fewer than %d bytes (xattr node)"
+                                         " left to end of buf. Reading 0x%x at 0x%08x\n",
+                                         je32_to_cpu(node->totlen), buf_len, ofs));
+                               err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
+                               if (err)
+                                       return err;
+                               buf_ofs = ofs;
+                               node = (void *)buf;
+                       }
+                       err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s);
+                       if (err)
+                               return err;
+                       ofs += PAD(je32_to_cpu(node->totlen));
+                       break;
+               case JFFS2_NODETYPE_XREF:
+                       if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
+                               buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
+                               D1(printk(KERN_DEBUG "Fewer than %d bytes (xref node)"
+                                         " left to end of buf. Reading 0x%x at 0x%08x\n",
+                                         je32_to_cpu(node->totlen), buf_len, ofs));
+                               err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
+                               if (err)
+                                       return err;
+                               buf_ofs = ofs;
+                               node = (void *)buf;
+                       }
+                       err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s);
+                       if (err)
+                               return err;
+                       ofs += PAD(je32_to_cpu(node->totlen));
+                       break;
+#endif /* CONFIG_JFFS2_FS_XATTR */
+
                case JFFS2_NODETYPE_CLEANMARKER:
                        D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs));
                        if (je32_to_cpu(node->totlen) != c->cleanmarker_size) {
                                printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n",
                                       ofs, je32_to_cpu(node->totlen), c->cleanmarker_size);
-                               DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));
+                               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
+                                       return err;
                                ofs += PAD(sizeof(struct jffs2_unknown_node));
                        } else if (jeb->first_node) {
                                printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset);
-                               DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));
+                               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
+                                       return err;
                                ofs += PAD(sizeof(struct jffs2_unknown_node));
                        } else {
-                               struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
-                               if (!marker_ref) {
-                                       printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n");
-                                       return -ENOMEM;
-                               }
-                               marker_ref->next_in_ino = NULL;
-                               marker_ref->next_phys = NULL;
-                               marker_ref->flash_offset = ofs | REF_NORMAL;
-                               marker_ref->__totlen = c->cleanmarker_size;
-                               jeb->first_node = jeb->last_node = marker_ref;
+                               jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);
 
-                               USED_SPACE(PAD(c->cleanmarker_size));
                                ofs += PAD(c->cleanmarker_size);
                        }
                        break;
@@ -645,7 +836,8 @@ scan_more:
                case JFFS2_NODETYPE_PADDING:
                        if (jffs2_sum_active())
                                jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen));
-                       DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+                       if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+                               return err;
                        ofs += PAD(je32_to_cpu(node->totlen));
                        break;
 
@@ -656,7 +848,8 @@ scan_more:
                                c->flags |= JFFS2_SB_FLAG_RO;
                                if (!(jffs2_is_readonly(c)))
                                        return -EROFS;
-                               DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+                               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+                                       return err;
                                ofs += PAD(je32_to_cpu(node->totlen));
                                break;
 
@@ -666,15 +859,21 @@ scan_more:
 
                        case JFFS2_FEATURE_RWCOMPAT_DELETE:
                                D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
-                               DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+                               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+                                       return err;
                                ofs += PAD(je32_to_cpu(node->totlen));
                                break;
 
-                       case JFFS2_FEATURE_RWCOMPAT_COPY:
+                       case JFFS2_FEATURE_RWCOMPAT_COPY: {
                                D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
-                               USED_SPACE(PAD(je32_to_cpu(node->totlen)));
+
+                               jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL);
+
+                               /* We can't summarise nodes we don't grok */
+                               jffs2_sum_disable_collecting(s);
                                ofs += PAD(je32_to_cpu(node->totlen));
                                break;
+                               }
                        }
                }
        }
@@ -687,9 +886,9 @@ scan_more:
                }
        }
 
-       D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset,
-                 jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size));
-
+       D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
+                 jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
+       
        /* mark_node_obsolete can add to wasted !! */
        if (jeb->wasted_size) {
                jeb->dirty_size += jeb->wasted_size;
@@ -730,9 +929,9 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin
 static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
                                 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
 {
-       struct jffs2_raw_node_ref *raw;
        struct jffs2_inode_cache *ic;
        uint32_t ino = je32_to_cpu(ri->ino);
+       int err;
 
        D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs));
 
@@ -745,12 +944,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
           Which means that the _full_ amount of time to get to proper write mode with GC
           operational may actually be _longer_ than before. Sucks to be me. */
 
-       raw = jffs2_alloc_raw_node_ref();
-       if (!raw) {
-               printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n");
-               return -ENOMEM;
-       }
-
        ic = jffs2_get_ino_cache(c, ino);
        if (!ic) {
                /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the
@@ -762,30 +955,17 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
                        printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
                               ofs, je32_to_cpu(ri->node_crc), crc);
                        /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
-                       DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen)));
-                       jffs2_free_raw_node_ref(raw);
+                       if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen)))))
+                               return err;
                        return 0;
                }
                ic = jffs2_scan_make_ino_cache(c, ino);
-               if (!ic) {
-                       jffs2_free_raw_node_ref(raw);
+               if (!ic)
                        return -ENOMEM;
-               }
        }
 
        /* Wheee. It worked */
-
-       raw->flash_offset = ofs | REF_UNCHECKED;
-       raw->__totlen = PAD(je32_to_cpu(ri->totlen));
-       raw->next_phys = NULL;
-       raw->next_in_ino = ic->nodes;
-
-       ic->nodes = raw;
-       if (!jeb->first_node)
-               jeb->first_node = raw;
-       if (jeb->last_node)
-               jeb->last_node->next_phys = raw;
-       jeb->last_node = raw;
+       jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
 
        D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n",
                  je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
@@ -794,8 +974,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
 
        pseudo_random += je32_to_cpu(ri->version);
 
-       UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen)));
-
        if (jffs2_sum_active()) {
                jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
        }
@@ -806,10 +984,10 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
 static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
                                  struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s)
 {
-       struct jffs2_raw_node_ref *raw;
        struct jffs2_full_dirent *fd;
        struct jffs2_inode_cache *ic;
        uint32_t crc;
+       int err;
 
        D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs));
 
@@ -821,7 +999,8 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
                printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
                       ofs, je32_to_cpu(rd->node_crc), crc);
                /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
-               DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen)));
+               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
+                       return err;
                return 0;
        }
 
@@ -842,40 +1021,23 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo
                jffs2_free_full_dirent(fd);
                /* FIXME: Why do we believe totlen? */
                /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */
-               DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen)));
+               if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
+                       return err;
                return 0;
        }
-       raw = jffs2_alloc_raw_node_ref();
-       if (!raw) {
-               jffs2_free_full_dirent(fd);
-               printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n");
-               return -ENOMEM;
-       }
        ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino));
        if (!ic) {
                jffs2_free_full_dirent(fd);
-               jffs2_free_raw_node_ref(raw);
                return -ENOMEM;
        }
 
-       raw->__totlen = PAD(je32_to_cpu(rd->totlen));
-       raw->flash_offset = ofs | REF_PRISTINE;
-       raw->next_phys = NULL;
-       raw->next_in_ino = ic->nodes;
-       ic->nodes = raw;
-       if (!jeb->first_node)
-               jeb->first_node = raw;
-       if (jeb->last_node)
-               jeb->last_node->next_phys = raw;
-       jeb->last_node = raw;
+       fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic);
 
-       fd->raw = raw;
        fd->next = NULL;
        fd->version = je32_to_cpu(rd->version);
        fd->ino = je32_to_cpu(rd->ino);
        fd->nhash = full_name_hash(fd->name, rd->nsize);
        fd->type = rd->type;
-       USED_SPACE(PAD(je32_to_cpu(rd->totlen)));
        jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
 
        if (jffs2_sum_active()) {
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
new file mode 100644 (file)
index 0000000..52a9894
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/crc32.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include <linux/security.h>
+#include "nodelist.h"
+
+/* ---- Initial Security Label Attachment -------------- */
+int jffs2_init_security(struct inode *inode, struct inode *dir)
+{
+       int rc;
+       size_t len;
+       void *value;
+       char *name;
+
+       rc = security_inode_init_security(inode, dir, &name, &value, &len);
+       if (rc) {
+               if (rc == -EOPNOTSUPP)
+                       return 0;
+               return rc;
+       }
+       rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
+
+        kfree(name);
+        kfree(value);
+        return rc;
+}
+
+/* ---- XATTR Handler for "security.*" ----------------- */
+static int jffs2_security_getxattr(struct inode *inode, const char *name,
+                                  void *buffer, size_t size)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+
+       return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size);
+}
+
+static int jffs2_security_setxattr(struct inode *inode, const char *name, const void *buffer,
+                                  size_t size, int flags)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+
+       return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size, flags);
+}
+
+static size_t jffs2_security_listxattr(struct inode *inode, char *list, size_t list_size,
+                                      const char *name, size_t name_len)
+{
+       size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
+
+       if (list && retlen <= list_size) {
+               strcpy(list, XATTR_SECURITY_PREFIX);
+               strcpy(list + XATTR_SECURITY_PREFIX_LEN, name);
+       }
+
+       return retlen;
+}
+
+struct xattr_handler jffs2_security_xattr_handler = {
+       .prefix = XATTR_SECURITY_PREFIX,
+       .list = jffs2_security_listxattr,
+       .set = jffs2_security_setxattr,
+       .get = jffs2_security_getxattr
+};
index fb9cec61fcf2ebbe050d58669551ca311b6c7e70..0b02fc79e4d1c183592573f3efd63aa2a12b35fa 100644 (file)
@@ -5,6 +5,7 @@
  *                     Zoltan Sogor <weth@inf.u-szeged.hu>,
  *                     Patrik Kluba <pajko@halom.u-szeged.hu>,
  *                     University of Szeged, Hungary
+ *               2005  KaiGai Kohei <kaigai@ak.jp.nec.com>
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
@@ -81,6 +82,19 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item)
                        dbg_summary("dirent (%u) added to summary\n",
                                                je32_to_cpu(item->d.ino));
                        break;
+#ifdef CONFIG_JFFS2_FS_XATTR
+               case JFFS2_NODETYPE_XATTR:
+                       s->sum_size += JFFS2_SUMMARY_XATTR_SIZE;
+                       s->sum_num++;
+                       dbg_summary("xattr (xid=%u, version=%u) added to summary\n",
+                                   je32_to_cpu(item->x.xid), je32_to_cpu(item->x.version));
+                       break;
+               case JFFS2_NODETYPE_XREF:
+                       s->sum_size += JFFS2_SUMMARY_XREF_SIZE;
+                       s->sum_num++;
+                       dbg_summary("xref added to summary\n");
+                       break;
+#endif
                default:
                        JFFS2_WARNING("UNKNOWN node type %u\n",
                                            je16_to_cpu(item->u.nodetype));
@@ -141,6 +155,40 @@ int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *r
        return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
 }
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs)
+{
+       struct jffs2_sum_xattr_mem *temp;
+
+       temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
+       if (!temp)
+               return -ENOMEM;
+
+       temp->nodetype = rx->nodetype;
+       temp->xid = rx->xid;
+       temp->version = rx->version;
+       temp->offset = cpu_to_je32(ofs);
+       temp->totlen = rx->totlen;
+       temp->next = NULL;
+
+       return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
+}
+
+int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs)
+{
+       struct jffs2_sum_xref_mem *temp;
+
+       temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
+       if (!temp)
+               return -ENOMEM;
+
+       temp->nodetype = rr->nodetype;
+       temp->offset = cpu_to_je32(ofs);
+       temp->next = NULL;
+
+       return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
+}
+#endif
 /* Cleanup every collected summary information */
 
 static void jffs2_sum_clean_collected(struct jffs2_summary *s)
@@ -259,7 +307,40 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs,
 
                        return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
                }
+#ifdef CONFIG_JFFS2_FS_XATTR
+               case JFFS2_NODETYPE_XATTR: {
+                       struct jffs2_sum_xattr_mem *temp;
+                       if (je32_to_cpu(node->x.version) == 0xffffffff)
+                               return 0;
+                       temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
+                       if (!temp)
+                               goto no_mem;
+
+                       temp->nodetype = node->x.nodetype;
+                       temp->xid = node->x.xid;
+                       temp->version = node->x.version;
+                       temp->totlen = node->x.totlen;
+                       temp->offset = cpu_to_je32(ofs);
+                       temp->next = NULL;
+
+                       return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
+               }
+               case JFFS2_NODETYPE_XREF: {
+                       struct jffs2_sum_xref_mem *temp;
+
+                       if (je32_to_cpu(node->r.ino) == 0xffffffff
+                           && je32_to_cpu(node->r.xid) == 0xffffffff)
+                               return 0;
+                       temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
+                       if (!temp)
+                               goto no_mem;
+                       temp->nodetype = node->r.nodetype;
+                       temp->offset = cpu_to_je32(ofs);
+                       temp->next = NULL;
 
+                       return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
+               }
+#endif
                case JFFS2_NODETYPE_PADDING:
                        dbg_summary("node PADDING\n");
                        c->summary->sum_padded += je32_to_cpu(node->u.totlen);
@@ -288,23 +369,41 @@ no_mem:
        return -ENOMEM;
 }
 
+static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c,
+                                                   struct jffs2_eraseblock *jeb,
+                                                   uint32_t ofs, uint32_t len,
+                                                   struct jffs2_inode_cache *ic)
+{
+       /* If there was a gap, mark it dirty */
+       if ((ofs & ~3) > c->sector_size - jeb->free_size) {
+               /* Ew. Summary doesn't actually tell us explicitly about dirty space */
+               jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size));
+       }
+
+       return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic);
+}
 
 /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
 
 static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
                                struct jffs2_raw_summary *summary, uint32_t *pseudo_random)
 {
-       struct jffs2_raw_node_ref *raw;
        struct jffs2_inode_cache *ic;
        struct jffs2_full_dirent *fd;
        void *sp;
        int i, ino;
+       int err;
 
        sp = summary->sum;
 
        for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
                dbg_summary("processing summary index %d\n", i);
 
+               /* Make sure there's a spare ref for dirty space */
+               err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
+               if (err)
+                       return err;
+
                switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
                        case JFFS2_NODETYPE_INODE: {
                                struct jffs2_sum_inode_flash *spi;
@@ -312,38 +411,20 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
 
                                ino = je32_to_cpu(spi->inode);
 
-                               dbg_summary("Inode at 0x%08x\n",
-                                                       jeb->offset + je32_to_cpu(spi->offset));
-
-                               raw = jffs2_alloc_raw_node_ref();
-                               if (!raw) {
-                                       JFFS2_NOTICE("allocation of node reference failed\n");
-                                       kfree(summary);
-                                       return -ENOMEM;
-                               }
+                               dbg_summary("Inode at 0x%08x-0x%08x\n",
+                                           jeb->offset + je32_to_cpu(spi->offset),
+                                           jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spi->totlen));
 
                                ic = jffs2_scan_make_ino_cache(c, ino);
                                if (!ic) {
                                        JFFS2_NOTICE("scan_make_ino_cache failed\n");
-                                       jffs2_free_raw_node_ref(raw);
-                                       kfree(summary);
                                        return -ENOMEM;
                                }
 
-                               raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED;
-                               raw->__totlen = PAD(je32_to_cpu(spi->totlen));
-                               raw->next_phys = NULL;
-                               raw->next_in_ino = ic->nodes;
-
-                               ic->nodes = raw;
-                               if (!jeb->first_node)
-                                       jeb->first_node = raw;
-                               if (jeb->last_node)
-                                       jeb->last_node->next_phys = raw;
-                               jeb->last_node = raw;
-                               *pseudo_random += je32_to_cpu(spi->version);
+                               sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED,
+                                                 PAD(je32_to_cpu(spi->totlen)), ic);
 
-                               UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen)));
+                               *pseudo_random += je32_to_cpu(spi->version);
 
                                sp += JFFS2_SUMMARY_INODE_SIZE;
 
@@ -354,52 +435,33 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                                struct jffs2_sum_dirent_flash *spd;
                                spd = sp;
 
-                               dbg_summary("Dirent at 0x%08x\n",
-                                                       jeb->offset + je32_to_cpu(spd->offset));
+                               dbg_summary("Dirent at 0x%08x-0x%08x\n",
+                                           jeb->offset + je32_to_cpu(spd->offset),
+                                           jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen));
+
 
                                fd = jffs2_alloc_full_dirent(spd->nsize+1);
-                               if (!fd) {
-                                       kfree(summary);
+                               if (!fd)
                                        return -ENOMEM;
-                               }
 
                                memcpy(&fd->name, spd->name, spd->nsize);
                                fd->name[spd->nsize] = 0;
 
-                               raw = jffs2_alloc_raw_node_ref();
-                               if (!raw) {
-                                       jffs2_free_full_dirent(fd);
-                                       JFFS2_NOTICE("allocation of node reference failed\n");
-                                       kfree(summary);
-                                       return -ENOMEM;
-                               }
-
                                ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino));
                                if (!ic) {
                                        jffs2_free_full_dirent(fd);
-                                       jffs2_free_raw_node_ref(raw);
-                                       kfree(summary);
                                        return -ENOMEM;
                                }
 
-                               raw->__totlen = PAD(je32_to_cpu(spd->totlen));
-                               raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE;
-                               raw->next_phys = NULL;
-                               raw->next_in_ino = ic->nodes;
-                               ic->nodes = raw;
-                               if (!jeb->first_node)
-                                       jeb->first_node = raw;
-                               if (jeb->last_node)
-                                       jeb->last_node->next_phys = raw;
-                               jeb->last_node = raw;
-
-                               fd->raw = raw;
+                               fd->raw = sum_link_node_ref(c, jeb,  je32_to_cpu(spd->offset) | REF_UNCHECKED,
+                                                           PAD(je32_to_cpu(spd->totlen)), ic);
+
                                fd->next = NULL;
                                fd->version = je32_to_cpu(spd->version);
                                fd->ino = je32_to_cpu(spd->ino);
                                fd->nhash = full_name_hash(fd->name, spd->nsize);
                                fd->type = spd->type;
-                               USED_SPACE(PAD(je32_to_cpu(spd->totlen)));
+
                                jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
 
                                *pseudo_random += je32_to_cpu(spd->version);
@@ -408,48 +470,105 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
 
                                break;
                        }
+#ifdef CONFIG_JFFS2_FS_XATTR
+                       case JFFS2_NODETYPE_XATTR: {
+                               struct jffs2_xattr_datum *xd;
+                               struct jffs2_sum_xattr_flash *spx;
+
+                               spx = (struct jffs2_sum_xattr_flash *)sp;
+                               dbg_summary("xattr at %#08x-%#08x (xid=%u, version=%u)\n", 
+                                           jeb->offset + je32_to_cpu(spx->offset),
+                                           jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen),
+                                           je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
+
+                               xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
+                                                               je32_to_cpu(spx->version));
+                               if (IS_ERR(xd)) {
+                                       if (PTR_ERR(xd) == -EEXIST) {
+                                               /* a newer version of xd exists */
+                                               if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen))))
+                                                       return err;
+                                               sp += JFFS2_SUMMARY_XATTR_SIZE;
+                                               break;
+                                       }
+                                       JFFS2_NOTICE("allocation of xattr_datum failed\n");
+                                       return PTR_ERR(xd);
+                               }
+
+                               xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
+                                                            PAD(je32_to_cpu(spx->totlen)), NULL);
+                               /* FIXME */ xd->node->next_in_ino = (void *)xd;
+
+                               *pseudo_random += je32_to_cpu(spx->xid);
+                               sp += JFFS2_SUMMARY_XATTR_SIZE;
+
+                               break;
+                       }
+                       case JFFS2_NODETYPE_XREF: {
+                               struct jffs2_xattr_ref *ref;
+                               struct jffs2_sum_xref_flash *spr;
+
+                               spr = (struct jffs2_sum_xref_flash *)sp;
+                               dbg_summary("xref at %#08x-%#08x\n",
+                                           jeb->offset + je32_to_cpu(spr->offset),
+                                           jeb->offset + je32_to_cpu(spr->offset) + 
+                                           (uint32_t)PAD(sizeof(struct jffs2_raw_xref)));
+
+                               ref = jffs2_alloc_xattr_ref();
+                               if (!ref) {
+                                       JFFS2_NOTICE("allocation of xattr_datum failed\n");
+                                       return -ENOMEM;
+                               }
+                               ref->ino = 0xfffffffe;
+                               ref->xid = 0xfffffffd;
+                               ref->next = c->xref_temp;
+                               c->xref_temp = ref;
 
+                               ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
+                                                             PAD(sizeof(struct jffs2_raw_xref)), NULL);
+                               /* FIXME */ ref->node->next_in_ino = (void *)ref;
+
+                               *pseudo_random += ref->node->flash_offset;
+                               sp += JFFS2_SUMMARY_XREF_SIZE;
+
+                               break;
+                       }
+#endif
                        default : {
-                               JFFS2_WARNING("Unsupported node type found in summary! Exiting...");
-                               kfree(summary);
-                               return -EIO;
+                               uint16_t nodetype = je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype);
+                               JFFS2_WARNING("Unsupported node type %x found in summary! Exiting...\n", nodetype);
+                               if ((nodetype & JFFS2_COMPAT_MASK) == JFFS2_FEATURE_INCOMPAT)
+                                       return -EIO;
+
+                               /* For compatible node types, just fall back to the full scan */
+                               c->wasted_size -= jeb->wasted_size;
+                               c->free_size += c->sector_size - jeb->free_size;
+                               c->used_size -= jeb->used_size;
+                               c->dirty_size -= jeb->dirty_size;
+                               jeb->wasted_size = jeb->used_size = jeb->dirty_size = 0;
+                               jeb->free_size = c->sector_size;
+
+                               jffs2_free_jeb_node_refs(c, jeb);
+                               return -ENOTRECOVERABLE;
                        }
                }
        }
-
-       kfree(summary);
        return 0;
 }
 
 /* Process the summary node - called from jffs2_scan_eraseblock() */
-
 int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-                               uint32_t ofs, uint32_t *pseudo_random)
+                          struct jffs2_raw_summary *summary, uint32_t sumsize,
+                          uint32_t *pseudo_random)
 {
        struct jffs2_unknown_node crcnode;
-       struct jffs2_raw_node_ref *cache_ref;
-       struct jffs2_raw_summary *summary;
-       int ret, sumsize;
+       int ret, ofs;
        uint32_t crc;
 
-       sumsize = c->sector_size - ofs;
-       ofs += jeb->offset;
+       ofs = c->sector_size - sumsize;
 
        dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
-                               jeb->offset, ofs, sumsize);
-
-       summary = kmalloc(sumsize, GFP_KERNEL);
-
-       if (!summary) {
-               return -ENOMEM;
-       }
-
-       ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize);
-
-       if (ret) {
-               kfree(summary);
-               return ret;
-       }
+                   jeb->offset, jeb->offset + ofs, sumsize);
 
        /* OK, now check for node validity and CRC */
        crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -486,66 +605,49 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
 
                dbg_summary("Summary : CLEANMARKER node \n");
 
+               ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
+               if (ret)
+                       return ret;
+
                if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) {
                        dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n",
                                je32_to_cpu(summary->cln_mkr), c->cleanmarker_size);
-                       UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr)));
+                       if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
+                               return ret;
                } else if (jeb->first_node) {
                        dbg_summary("CLEANMARKER node not first node in block "
                                        "(0x%08x)\n", jeb->offset);
-                       UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr)));
+                       if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
+                               return ret;
                } else {
-                       struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
-
-                       if (!marker_ref) {
-                               JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
-                               kfree(summary);
-                               return -ENOMEM;
-                       }
-
-                       marker_ref->next_in_ino = NULL;
-                       marker_ref->next_phys = NULL;
-                       marker_ref->flash_offset = jeb->offset | REF_NORMAL;
-                       marker_ref->__totlen = je32_to_cpu(summary->cln_mkr);
-                       jeb->first_node = jeb->last_node = marker_ref;
-
-                       USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) );
+                       jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL,
+                                           je32_to_cpu(summary->cln_mkr), NULL);
                }
        }
 
-       if (je32_to_cpu(summary->padded)) {
-               DIRTY_SPACE(je32_to_cpu(summary->padded));
-       }
-
        ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
+       /* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full
+          scan of this eraseblock. So return zero */
+       if (ret == -ENOTRECOVERABLE)
+               return 0;
        if (ret)
-               return ret;
+               return ret;             /* real error */
 
        /* for PARANOIA_CHECK */
-       cache_ref = jffs2_alloc_raw_node_ref();
-
-       if (!cache_ref) {
-               JFFS2_NOTICE("Failed to allocate node ref for cache\n");
-               return -ENOMEM;
-       }
-
-       cache_ref->next_in_ino = NULL;
-       cache_ref->next_phys = NULL;
-       cache_ref->flash_offset = ofs | REF_NORMAL;
-       cache_ref->__totlen = sumsize;
-
-       if (!jeb->first_node)
-               jeb->first_node = cache_ref;
-       if (jeb->last_node)
-               jeb->last_node->next_phys = cache_ref;
-       jeb->last_node = cache_ref;
+       ret = jffs2_prealloc_raw_node_refs(c, jeb, 2);
+       if (ret)
+               return ret;
 
-       USED_SPACE(sumsize);
+       sum_link_node_ref(c, jeb, ofs | REF_NORMAL, sumsize, NULL);
 
-       jeb->wasted_size += jeb->free_size;
-       c->wasted_size += jeb->free_size;
-       c->free_size -= jeb->free_size;
-       jeb->free_size = 0;
+       if (unlikely(jeb->free_size)) {
+               JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
+                             jeb->free_size, jeb->offset);
+               jeb->wasted_size += jeb->free_size;
+               c->wasted_size += jeb->free_size;
+               c->free_size -= jeb->free_size;
+               jeb->free_size = 0;
+       }
 
        return jffs2_scan_classify_jeb(c, jeb);
 
@@ -564,6 +666,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
        union jffs2_sum_mem *temp;
        struct jffs2_sum_marker *sm;
        struct kvec vecs[2];
+       uint32_t sum_ofs;
        void *wpage;
        int ret;
        size_t retlen;
@@ -581,16 +684,17 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
        wpage = c->summary->sum_buf;
 
        while (c->summary->sum_num) {
+               temp = c->summary->sum_list_head;
 
-               switch (je16_to_cpu(c->summary->sum_list_head->u.nodetype)) {
+               switch (je16_to_cpu(temp->u.nodetype)) {
                        case JFFS2_NODETYPE_INODE: {
                                struct jffs2_sum_inode_flash *sino_ptr = wpage;
 
-                               sino_ptr->nodetype = c->summary->sum_list_head->i.nodetype;
-                               sino_ptr->inode = c->summary->sum_list_head->i.inode;
-                               sino_ptr->version = c->summary->sum_list_head->i.version;
-                               sino_ptr->offset = c->summary->sum_list_head->i.offset;
-                               sino_ptr->totlen = c->summary->sum_list_head->i.totlen;
+                               sino_ptr->nodetype = temp->i.nodetype;
+                               sino_ptr->inode = temp->i.inode;
+                               sino_ptr->version = temp->i.version;
+                               sino_ptr->offset = temp->i.offset;
+                               sino_ptr->totlen = temp->i.totlen;
 
                                wpage += JFFS2_SUMMARY_INODE_SIZE;
 
@@ -600,30 +704,60 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
                        case JFFS2_NODETYPE_DIRENT: {
                                struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage;
 
-                               sdrnt_ptr->nodetype = c->summary->sum_list_head->d.nodetype;
-                               sdrnt_ptr->totlen = c->summary->sum_list_head->d.totlen;
-                               sdrnt_ptr->offset = c->summary->sum_list_head->d.offset;
-                               sdrnt_ptr->pino = c->summary->sum_list_head->d.pino;
-                               sdrnt_ptr->version = c->summary->sum_list_head->d.version;
-                               sdrnt_ptr->ino = c->summary->sum_list_head->d.ino;
-                               sdrnt_ptr->nsize = c->summary->sum_list_head->d.nsize;
-                               sdrnt_ptr->type = c->summary->sum_list_head->d.type;
+                               sdrnt_ptr->nodetype = temp->d.nodetype;
+                               sdrnt_ptr->totlen = temp->d.totlen;
+                               sdrnt_ptr->offset = temp->d.offset;
+                               sdrnt_ptr->pino = temp->d.pino;
+                               sdrnt_ptr->version = temp->d.version;
+                               sdrnt_ptr->ino = temp->d.ino;
+                               sdrnt_ptr->nsize = temp->d.nsize;
+                               sdrnt_ptr->type = temp->d.type;
 
-                               memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name,
-                                                       c->summary->sum_list_head->d.nsize);
+                               memcpy(sdrnt_ptr->name, temp->d.name,
+                                                       temp->d.nsize);
 
-                               wpage += JFFS2_SUMMARY_DIRENT_SIZE(c->summary->sum_list_head->d.nsize);
+                               wpage += JFFS2_SUMMARY_DIRENT_SIZE(temp->d.nsize);
 
                                break;
                        }
+#ifdef CONFIG_JFFS2_FS_XATTR
+                       case JFFS2_NODETYPE_XATTR: {
+                               struct jffs2_sum_xattr_flash *sxattr_ptr = wpage;
+
+                               temp = c->summary->sum_list_head;
+                               sxattr_ptr->nodetype = temp->x.nodetype;
+                               sxattr_ptr->xid = temp->x.xid;
+                               sxattr_ptr->version = temp->x.version;
+                               sxattr_ptr->offset = temp->x.offset;
+                               sxattr_ptr->totlen = temp->x.totlen;
+
+                               wpage += JFFS2_SUMMARY_XATTR_SIZE;
+                               break;
+                       }
+                       case JFFS2_NODETYPE_XREF: {
+                               struct jffs2_sum_xref_flash *sxref_ptr = wpage;
 
+                               temp = c->summary->sum_list_head;
+                               sxref_ptr->nodetype = temp->r.nodetype;
+                               sxref_ptr->offset = temp->r.offset;
+
+                               wpage += JFFS2_SUMMARY_XREF_SIZE;
+                               break;
+                       }
+#endif
                        default : {
-                               BUG();  /* unknown node in summary information */
+                               if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK)
+                                   == JFFS2_FEATURE_RWCOMPAT_COPY) {
+                                       dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n",
+                                                   je16_to_cpu(temp->u.nodetype));
+                                       jffs2_sum_disable_collecting(c->summary);
+                               } else {
+                                       BUG();  /* unknown node in summary information */
+                               }
                        }
                }
 
-               temp = c->summary->sum_list_head;
-               c->summary->sum_list_head = c->summary->sum_list_head->u.next;
+               c->summary->sum_list_head = temp->u.next;
                kfree(temp);
 
                c->summary->sum_num--;
@@ -645,25 +779,34 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
        vecs[1].iov_base = c->summary->sum_buf;
        vecs[1].iov_len = datasize;
 
-       dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n",
-                       jeb->offset + c->sector_size - jeb->free_size);
+       sum_ofs = jeb->offset + c->sector_size - jeb->free_size;
 
-       spin_unlock(&c->erase_completion_lock);
-       ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size -
-                               jeb->free_size, &retlen, 0);
-       spin_lock(&c->erase_completion_lock);
+       dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n",
+                   sum_ofs);
 
+       ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0);
 
        if (ret || (retlen != infosize)) {
-               JFFS2_WARNING("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
-                       infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen);
+
+               JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
+                             infosize, sum_ofs, ret, retlen);
+
+               if (retlen) {
+                       /* Waste remaining space */
+                       spin_lock(&c->erase_completion_lock);
+                       jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL);
+                       spin_unlock(&c->erase_completion_lock);
+               }
 
                c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
-               WASTED_SPACE(infosize);
 
-               return 1;
+               return 0;
        }
 
+       spin_lock(&c->erase_completion_lock);
+       jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL);
+       spin_unlock(&c->erase_completion_lock);
+
        return 0;
 }
 
@@ -671,13 +814,16 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
 
 int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
 {
-       struct jffs2_raw_node_ref *summary_ref;
-       int datasize, infosize, padsize, ret;
+       int datasize, infosize, padsize;
        struct jffs2_eraseblock *jeb;
+       int ret;
 
        dbg_summary("called\n");
 
+       spin_unlock(&c->erase_completion_lock);
+
        jeb = c->nextblock;
+       jffs2_prealloc_raw_node_refs(c, jeb, 1);
 
        if (!c->summary->sum_num || !c->summary->sum_list_head) {
                JFFS2_WARNING("Empty summary info!!!\n");
@@ -696,35 +842,11 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
                jffs2_sum_disable_collecting(c->summary);
 
                JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize);
+               spin_lock(&c->erase_completion_lock);
                return 0;
        }
 
        ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
-       if (ret)
-               return 0; /* can't write out summary, block is marked as NOSUM_SIZE */
-
-       /* for ACCT_PARANOIA_CHECK */
-       spin_unlock(&c->erase_completion_lock);
-       summary_ref = jffs2_alloc_raw_node_ref();
        spin_lock(&c->erase_completion_lock);
-
-       if (!summary_ref) {
-               JFFS2_NOTICE("Failed to allocate node ref for summary\n");
-               return -ENOMEM;
-       }
-
-       summary_ref->next_in_ino = NULL;
-       summary_ref->next_phys = NULL;
-       summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL;
-       summary_ref->__totlen = infosize;
-
-       if (!jeb->first_node)
-               jeb->first_node = summary_ref;
-       if (jeb->last_node)
-               jeb->last_node->next_phys = summary_ref;
-       jeb->last_node = summary_ref;
-
-       USED_SPACE(infosize);
-
-       return 0;
+       return ret;
 }
index b7a678be170972fa68f0ef9423f0781971ab68ce..6bf1f6aa45525a81f99bb8b3765e507fa9c9b65b 100644 (file)
 #include <linux/uio.h>
 #include <linux/jffs2.h>
 
-#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \
-               c->free_size -= _x; c->dirty_size += _x; \
-               jeb->free_size -= _x ; jeb->dirty_size += _x; \
-               }while(0)
-#define USED_SPACE(x) do { typeof(x) _x = (x); \
-               c->free_size -= _x; c->used_size += _x; \
-               jeb->free_size -= _x ; jeb->used_size += _x; \
-               }while(0)
-#define WASTED_SPACE(x) do { typeof(x) _x = (x); \
-               c->free_size -= _x; c->wasted_size += _x; \
-               jeb->free_size -= _x ; jeb->wasted_size += _x; \
-               }while(0)
-#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \
-               c->free_size -= _x; c->unchecked_size += _x; \
-               jeb->free_size -= _x ; jeb->unchecked_size += _x; \
-               }while(0)
-
 #define BLK_STATE_ALLFF                0
 #define BLK_STATE_CLEAN                1
 #define BLK_STATE_PARTDIRTY    2
@@ -45,6 +28,8 @@
 #define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff
 #define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash))
 #define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x))
+#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash))
+#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash))
 
 /* Summary structures used on flash */
 
@@ -75,11 +60,28 @@ struct jffs2_sum_dirent_flash
        uint8_t name[0];        /* dirent name */
 } __attribute__((packed));
 
+struct jffs2_sum_xattr_flash
+{
+       jint16_t nodetype;      /* == JFFS2_NODETYPE_XATR */
+       jint32_t xid;           /* xattr identifier */
+       jint32_t version;       /* version number */
+       jint32_t offset;        /* offset on jeb */
+       jint32_t totlen;        /* node length */
+} __attribute__((packed));
+
+struct jffs2_sum_xref_flash
+{
+       jint16_t nodetype;      /* == JFFS2_NODETYPE_XREF */
+       jint32_t offset;        /* offset on jeb */
+} __attribute__((packed));
+
 union jffs2_sum_flash
 {
        struct jffs2_sum_unknown_flash u;
        struct jffs2_sum_inode_flash i;
        struct jffs2_sum_dirent_flash d;
+       struct jffs2_sum_xattr_flash x;
+       struct jffs2_sum_xref_flash r;
 };
 
 /* Summary structures used in the memory */
@@ -114,11 +116,30 @@ struct jffs2_sum_dirent_mem
        uint8_t name[0];        /* dirent name */
 } __attribute__((packed));
 
+struct jffs2_sum_xattr_mem
+{
+       union jffs2_sum_mem *next;
+       jint16_t nodetype;
+       jint32_t xid;
+       jint32_t version;
+       jint32_t offset;
+       jint32_t totlen;
+} __attribute__((packed));
+
+struct jffs2_sum_xref_mem
+{
+       union jffs2_sum_mem *next;
+       jint16_t nodetype;
+       jint32_t offset;
+} __attribute__((packed));
+
 union jffs2_sum_mem
 {
        struct jffs2_sum_unknown_mem u;
        struct jffs2_sum_inode_mem i;
        struct jffs2_sum_dirent_mem d;
+       struct jffs2_sum_xattr_mem x;
+       struct jffs2_sum_xref_mem r;
 };
 
 /* Summary related information stored in superblock */
@@ -159,8 +180,11 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c);
 int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size);
 int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs);
 int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs);
+int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs);
+int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs);
 int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-                       uint32_t ofs, uint32_t *pseudo_random);
+                          struct jffs2_raw_summary *summary, uint32_t sumlen,
+                          uint32_t *pseudo_random);
 
 #else                          /* SUMMARY DISABLED */
 
@@ -176,7 +200,9 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
 #define jffs2_sum_add_padding_mem(a,b)
 #define jffs2_sum_add_inode_mem(a,b,c)
 #define jffs2_sum_add_dirent_mem(a,b,c)
-#define jffs2_sum_scan_sumnode(a,b,c,d) (0)
+#define jffs2_sum_add_xattr_mem(a,b,c)
+#define jffs2_sum_add_xref_mem(a,b,c)
+#define jffs2_sum_scan_sumnode(a,b,c,d,e) (0)
 
 #endif /* CONFIG_JFFS2_SUMMARY */
 
index ffd8e84b22cc13a32323541203e5dcfdf686ccc4..9d0521451f5943964f6cd223d025f3561b580de7 100644 (file)
@@ -151,7 +151,10 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type,
 
        sb->s_op = &jffs2_super_operations;
        sb->s_flags = flags | MS_NOATIME;
-
+       sb->s_xattr = jffs2_xattr_handlers;
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+       sb->s_flags |= MS_POSIXACL;
+#endif
        ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
 
        if (ret) {
@@ -293,6 +296,7 @@ static void jffs2_put_super (struct super_block *sb)
                kfree(c->blocks);
        jffs2_flash_cleanup(c);
        kfree(c->inocache_list);
+       jffs2_clear_xattr_subsystem(c);
        if (c->mtd->sync)
                c->mtd->sync(c->mtd);
 
@@ -320,6 +324,18 @@ static int __init init_jffs2_fs(void)
 {
        int ret;
 
+       /* Paranoia checks for on-medium structures. If we ask GCC
+          to pack them with __attribute__((packed)) then it _also_
+          assumes that they're not aligned -- so it emits crappy
+          code on some architectures. Ideally we want an attribute
+          which means just 'no padding', without the alignment
+          thing. But GCC doesn't have that -- we have to just
+          hope the structs are the right sizes, instead. */
+       BUG_ON(sizeof(struct jffs2_unknown_node) != 12);
+       BUG_ON(sizeof(struct jffs2_raw_dirent) != 40);
+       BUG_ON(sizeof(struct jffs2_raw_inode) != 68);
+       BUG_ON(sizeof(struct jffs2_raw_summary) != 32);
+
        printk(KERN_INFO "JFFS2 version 2.2."
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
               " (NAND)"
@@ -327,7 +343,7 @@ static int __init init_jffs2_fs(void)
 #ifdef CONFIG_JFFS2_SUMMARY
               " (SUMMARY) "
 #endif
-              " (C) 2001-2003 Red Hat, Inc.\n");
+              " (C) 2001-2006 Red Hat, Inc.\n");
 
        jffs2_inode_cachep = kmem_cache_create("jffs2_i",
                                             sizeof(struct jffs2_inode_info),
index d55754fe8925c537ac2ff5e117007c0370a41ee0..fc211b6e9b03ec1b6dd4641179d18854d8df3d4b 100644 (file)
@@ -24,7 +24,12 @@ struct inode_operations jffs2_symlink_inode_operations =
 {
        .readlink =     generic_readlink,
        .follow_link =  jffs2_follow_link,
-       .setattr =      jffs2_setattr
+       .permission =   jffs2_permission,
+       .setattr =      jffs2_setattr,
+       .setxattr =     jffs2_setxattr,
+       .getxattr =     jffs2_getxattr,
+       .listxattr =    jffs2_listxattr,
+       .removexattr =  jffs2_removexattr
 };
 
 static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
index 4cebf0e57c465bbf130b7077ea667ded3bac0b08..a7f153f79ecb2436be0ef07dfc54cd7b8fcbc160 100644 (file)
@@ -156,69 +156,130 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock
                jffs2_erase_pending_trigger(c);
        }
 
-       /* Adjust its size counts accordingly */
-       c->wasted_size += jeb->free_size;
-       c->free_size -= jeb->free_size;
-       jeb->wasted_size += jeb->free_size;
-       jeb->free_size = 0;
+       if (!jffs2_prealloc_raw_node_refs(c, jeb, 1)) {
+               uint32_t oldfree = jeb->free_size;
+
+               jffs2_link_node_ref(c, jeb, 
+                                   (jeb->offset+c->sector_size-oldfree) | REF_OBSOLETE,
+                                   oldfree, NULL);
+               /* convert to wasted */
+               c->wasted_size += oldfree;
+               jeb->wasted_size += oldfree;
+               c->dirty_size -= oldfree;
+               jeb->dirty_size -= oldfree;
+       }
 
        jffs2_dbg_dump_block_lists_nolock(c);
        jffs2_dbg_acct_sanity_check_nolock(c,jeb);
        jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
 }
 
+static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info *c,
+                                                           struct jffs2_inode_info *f,
+                                                           struct jffs2_raw_node_ref *raw,
+                                                           union jffs2_node_union *node)
+{
+       struct jffs2_node_frag *frag;
+       struct jffs2_full_dirent *fd;
+
+       dbg_noderef("incore_replace_raw: node at %p is {%04x,%04x}\n",
+                   node, je16_to_cpu(node->u.magic), je16_to_cpu(node->u.nodetype));
+
+       BUG_ON(je16_to_cpu(node->u.magic) != 0x1985 &&
+              je16_to_cpu(node->u.magic) != 0);
+
+       switch (je16_to_cpu(node->u.nodetype)) {
+       case JFFS2_NODETYPE_INODE:
+               if (f->metadata && f->metadata->raw == raw) {
+                       dbg_noderef("Will replace ->raw in f->metadata at %p\n", f->metadata);
+                       return &f->metadata->raw;
+               }
+               frag = jffs2_lookup_node_frag(&f->fragtree, je32_to_cpu(node->i.offset));
+               BUG_ON(!frag);
+               /* Find a frag which refers to the full_dnode we want to modify */
+               while (!frag->node || frag->node->raw != raw) {
+                       frag = frag_next(frag);
+                       BUG_ON(!frag);
+               }
+               dbg_noderef("Will replace ->raw in full_dnode at %p\n", frag->node);
+               return &frag->node->raw;
+
+       case JFFS2_NODETYPE_DIRENT:
+               for (fd = f->dents; fd; fd = fd->next) {
+                       if (fd->raw == raw) {
+                               dbg_noderef("Will replace ->raw in full_dirent at %p\n", fd);
+                               return &fd->raw;
+                       }
+               }
+               BUG();
+
+       default:
+               dbg_noderef("Don't care about replacing raw for nodetype %x\n",
+                           je16_to_cpu(node->u.nodetype));
+               break;
+       }
+       return NULL;
+}
+
 /* Recover from failure to write wbuf. Recover the nodes up to the
  * wbuf, not the one which we were starting to try to write. */
 
 static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
 {
        struct jffs2_eraseblock *jeb, *new_jeb;
-       struct jffs2_raw_node_ref **first_raw, **raw;
+       struct jffs2_raw_node_ref *raw, *next, *first_raw = NULL;
        size_t retlen;
        int ret;
+       int nr_refile = 0;
        unsigned char *buf;
        uint32_t start, end, ofs, len;
 
-       spin_lock(&c->erase_completion_lock);
-
        jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
 
+       spin_lock(&c->erase_completion_lock);
        jffs2_block_refile(c, jeb, REFILE_NOTEMPTY);
+       spin_unlock(&c->erase_completion_lock);
+
+       BUG_ON(!ref_obsolete(jeb->last_node));
 
        /* Find the first node to be recovered, by skipping over every
           node which ends before the wbuf starts, or which is obsolete. */
-       first_raw = &jeb->first_node;
-       while (*first_raw &&
-              (ref_obsolete(*first_raw) ||
-               (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) {
-               D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n",
-                         ref_offset(*first_raw), ref_flags(*first_raw),
-                         (ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw)),
-                         c->wbuf_ofs));
-               first_raw = &(*first_raw)->next_phys;
+       for (next = raw = jeb->first_node; next; raw = next) {
+               next = ref_next(raw);
+
+               if (ref_obsolete(raw) || 
+                   (next && ref_offset(next) <= c->wbuf_ofs)) {
+                       dbg_noderef("Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n",
+                                   ref_offset(raw), ref_flags(raw),
+                                   (ref_offset(raw) + ref_totlen(c, jeb, raw)),
+                                   c->wbuf_ofs);
+                       continue;
+               }
+               dbg_noderef("First node to be recovered is at 0x%08x(%d)-0x%08x\n",
+                           ref_offset(raw), ref_flags(raw),
+                           (ref_offset(raw) + ref_totlen(c, jeb, raw)));
+
+               first_raw = raw;
+               break;
        }
 
-       if (!*first_raw) {
+       if (!first_raw) {
                /* All nodes were obsolete. Nothing to recover. */
                D1(printk(KERN_DEBUG "No non-obsolete nodes to be recovered. Just filing block bad\n"));
-               spin_unlock(&c->erase_completion_lock);
+               c->wbuf_len = 0;
                return;
        }
 
-       start = ref_offset(*first_raw);
-       end = ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw);
-
-       /* Find the last node to be recovered */
-       raw = first_raw;
-       while ((*raw)) {
-               if (!ref_obsolete(*raw))
-                       end = ref_offset(*raw) + ref_totlen(c, jeb, *raw);
+       start = ref_offset(first_raw);
+       end = ref_offset(jeb->last_node);
+       nr_refile = 1;
 
-               raw = &(*raw)->next_phys;
-       }
-       spin_unlock(&c->erase_completion_lock);
+       /* Count the number of refs which need to be copied */
+       while ((raw = ref_next(raw)) != jeb->last_node)
+               nr_refile++;
 
-       D1(printk(KERN_DEBUG "wbuf recover %08x-%08x\n", start, end));
+       dbg_noderef("wbuf recover %08x-%08x (%d bytes in %d nodes)\n",
+                   start, end, end - start, nr_refile);
 
        buf = NULL;
        if (start < c->wbuf_ofs) {
@@ -233,28 +294,37 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
                }
 
                /* Do the read... */
-               if (jffs2_cleanmarker_oob(c))
-                       ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo);
-               else
-                       ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf);
+               ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf);
 
-               if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) {
-                       /* ECC recovered */
+               /* ECC recovered ? */
+               if ((ret == -EUCLEAN || ret == -EBADMSG) &&
+                   (retlen == c->wbuf_ofs - start))
                        ret = 0;
-               }
+
                if (ret || retlen != c->wbuf_ofs - start) {
                        printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n");
 
                        kfree(buf);
                        buf = NULL;
                read_failed:
-                       first_raw = &(*first_raw)->next_phys;
+                       first_raw = ref_next(first_raw);
+                       nr_refile--;
+                       while (first_raw && ref_obsolete(first_raw)) {
+                               first_raw = ref_next(first_raw);
+                               nr_refile--;
+                       }
+
                        /* If this was the only node to be recovered, give up */
-                       if (!(*first_raw))
+                       if (!first_raw) {
+                               c->wbuf_len = 0;
                                return;
+                       }
 
                        /* It wasn't. Go on and try to recover nodes complete in the wbuf */
-                       start = ref_offset(*first_raw);
+                       start = ref_offset(first_raw);
+                       dbg_noderef("wbuf now recover %08x-%08x (%d bytes in %d nodes)\n",
+                                   start, end, end - start, nr_refile);
+
                } else {
                        /* Read succeeded. Copy the remaining data from the wbuf */
                        memcpy(buf + (c->wbuf_ofs - start), c->wbuf, end - c->wbuf_ofs);
@@ -263,14 +333,23 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
        /* OK... we're to rewrite (end-start) bytes of data from first_raw onwards.
           Either 'buf' contains the data, or we find it in the wbuf */
 
-
        /* ... and get an allocation of space from a shiny new block instead */
-       ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len, JFFS2_SUMMARY_NOSUM_SIZE);
+       ret = jffs2_reserve_space_gc(c, end-start, &len, JFFS2_SUMMARY_NOSUM_SIZE);
        if (ret) {
                printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n");
                kfree(buf);
                return;
        }
+
+       ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, nr_refile);
+       if (ret) {
+               printk(KERN_WARNING "Failed to allocate node refs for wbuf recovery. Data loss ensues.\n");
+               kfree(buf);
+               return;
+       }
+
+       ofs = write_ofs(c);
+
        if (end-start >= c->wbuf_pagesize) {
                /* Need to do another write immediately, but it's possible
                   that this is just because the wbuf itself is completely
@@ -288,36 +367,22 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
                if (breakme++ == 20) {
                        printk(KERN_NOTICE "Faking write error at 0x%08x\n", ofs);
                        breakme = 0;
-                       c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen,
-                                         brokenbuf, NULL, c->oobinfo);
+                       c->mtd->write(c->mtd, ofs, towrite, &retlen,
+                                     brokenbuf);
                        ret = -EIO;
                } else
 #endif
-               if (jffs2_cleanmarker_oob(c))
-                       ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen,
-                                               rewrite_buf, NULL, c->oobinfo);
-               else
-                       ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, rewrite_buf);
+                       ret = c->mtd->write(c->mtd, ofs, towrite, &retlen,
+                                           rewrite_buf);
 
                if (ret || retlen != towrite) {
                        /* Argh. We tried. Really we did. */
                        printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
                        kfree(buf);
 
-                       if (retlen) {
-                               struct jffs2_raw_node_ref *raw2;
-
-                               raw2 = jffs2_alloc_raw_node_ref();
-                               if (!raw2)
-                                       return;
+                       if (retlen)
+                               jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, first_raw), NULL);
 
-                               raw2->flash_offset = ofs | REF_OBSOLETE;
-                               raw2->__totlen = ref_totlen(c, jeb, *first_raw);
-                               raw2->next_phys = NULL;
-                               raw2->next_in_ino = NULL;
-
-                               jffs2_add_physical_node_ref(c, raw2);
-                       }
                        return;
                }
                printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs);
@@ -326,12 +391,10 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
                c->wbuf_ofs = ofs + towrite;
                memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len);
                /* Don't muck about with c->wbuf_inodes. False positives are harmless. */
-               kfree(buf);
        } else {
                /* OK, now we're left with the dregs in whichever buffer we're using */
                if (buf) {
                        memcpy(c->wbuf, buf, end-start);
-                       kfree(buf);
                } else {
                        memmove(c->wbuf, c->wbuf + (start - c->wbuf_ofs), end - start);
                }
@@ -343,62 +406,111 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
        new_jeb = &c->blocks[ofs / c->sector_size];
 
        spin_lock(&c->erase_completion_lock);
-       if (new_jeb->first_node) {
-               /* Odd, but possible with ST flash later maybe */
-               new_jeb->last_node->next_phys = *first_raw;
-       } else {
-               new_jeb->first_node = *first_raw;
-       }
-
-       raw = first_raw;
-       while (*raw) {
-               uint32_t rawlen = ref_totlen(c, jeb, *raw);
+       for (raw = first_raw; raw != jeb->last_node; raw = ref_next(raw)) {
+               uint32_t rawlen = ref_totlen(c, jeb, raw);
+               struct jffs2_inode_cache *ic;
+               struct jffs2_raw_node_ref *new_ref;
+               struct jffs2_raw_node_ref **adjust_ref = NULL;
+               struct jffs2_inode_info *f = NULL;
 
                D1(printk(KERN_DEBUG "Refiling block of %08x at %08x(%d) to %08x\n",
-                         rawlen, ref_offset(*raw), ref_flags(*raw), ofs));
+                         rawlen, ref_offset(raw), ref_flags(raw), ofs));
+
+               ic = jffs2_raw_ref_to_ic(raw);
+
+               /* Ick. This XATTR mess should be fixed shortly... */
+               if (ic && ic->class == RAWNODE_CLASS_XATTR_DATUM) {
+                       struct jffs2_xattr_datum *xd = (void *)ic;
+                       BUG_ON(xd->node != raw);
+                       adjust_ref = &xd->node;
+                       raw->next_in_ino = NULL;
+                       ic = NULL;
+               } else if (ic && ic->class == RAWNODE_CLASS_XATTR_REF) {
+                       struct jffs2_xattr_datum *xr = (void *)ic;
+                       BUG_ON(xr->node != raw);
+                       adjust_ref = &xr->node;
+                       raw->next_in_ino = NULL;
+                       ic = NULL;
+               } else if (ic && ic->class == RAWNODE_CLASS_INODE_CACHE) {
+                       struct jffs2_raw_node_ref **p = &ic->nodes;
+
+                       /* Remove the old node from the per-inode list */
+                       while (*p && *p != (void *)ic) {
+                               if (*p == raw) {
+                                       (*p) = (raw->next_in_ino);
+                                       raw->next_in_ino = NULL;
+                                       break;
+                               }
+                               p = &((*p)->next_in_ino);
+                       }
 
-               if (ref_obsolete(*raw)) {
-                       /* Shouldn't really happen much */
-                       new_jeb->dirty_size += rawlen;
-                       new_jeb->free_size -= rawlen;
-                       c->dirty_size += rawlen;
-               } else {
-                       new_jeb->used_size += rawlen;
-                       new_jeb->free_size -= rawlen;
+                       if (ic->state == INO_STATE_PRESENT && !ref_obsolete(raw)) {
+                               /* If it's an in-core inode, then we have to adjust any
+                                  full_dirent or full_dnode structure to point to the
+                                  new version instead of the old */
+                               f = jffs2_gc_fetch_inode(c, ic->ino, ic->nlink);
+                               if (IS_ERR(f)) {
+                                       /* Should never happen; it _must_ be present */
+                                       JFFS2_ERROR("Failed to iget() ino #%u, err %ld\n",
+                                                   ic->ino, PTR_ERR(f));
+                                       BUG();
+                               }
+                               /* We don't lock f->sem. There's a number of ways we could
+                                  end up in here with it already being locked, and nobody's
+                                  going to modify it on us anyway because we hold the
+                                  alloc_sem. We're only changing one ->raw pointer too,
+                                  which we can get away with without upsetting readers. */
+                               adjust_ref = jffs2_incore_replace_raw(c, f, raw,
+                                                                     (void *)(buf?:c->wbuf) + (ref_offset(raw) - start));
+                       } else if (unlikely(ic->state != INO_STATE_PRESENT &&
+                                           ic->state != INO_STATE_CHECKEDABSENT &&
+                                           ic->state != INO_STATE_GC)) {
+                               JFFS2_ERROR("Inode #%u is in strange state %d!\n", ic->ino, ic->state);
+                               BUG();
+                       }
+               }
+
+               new_ref = jffs2_link_node_ref(c, new_jeb, ofs | ref_flags(raw), rawlen, ic);
+
+               if (adjust_ref) {
+                       BUG_ON(*adjust_ref != raw);
+                       *adjust_ref = new_ref;
+               }
+               if (f)
+                       jffs2_gc_release_inode(c, f);
+
+               if (!ref_obsolete(raw)) {
                        jeb->dirty_size += rawlen;
                        jeb->used_size  -= rawlen;
                        c->dirty_size += rawlen;
+                       c->used_size -= rawlen;
+                       raw->flash_offset = ref_offset(raw) | REF_OBSOLETE;
+                       BUG_ON(raw->next_in_ino);
                }
-               c->free_size -= rawlen;
-               (*raw)->flash_offset = ofs | ref_flags(*raw);
                ofs += rawlen;
-               new_jeb->last_node = *raw;
-
-               raw = &(*raw)->next_phys;
        }
 
+       kfree(buf);
+
        /* Fix up the original jeb now it's on the bad_list */
-       *first_raw = NULL;
-       if (first_raw == &jeb->first_node) {
-               jeb->last_node = NULL;
+       if (first_raw == jeb->first_node) {
                D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset));
                list_del(&jeb->list);
                list_add(&jeb->list, &c->erase_pending_list);
                c->nr_erasing_blocks++;
                jffs2_erase_pending_trigger(c);
        }
-       else
-               jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys);
 
        jffs2_dbg_acct_sanity_check_nolock(c, jeb);
-        jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
+       jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
 
        jffs2_dbg_acct_sanity_check_nolock(c, new_jeb);
-        jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb);
+       jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb);
 
        spin_unlock(&c->erase_completion_lock);
 
-       D1(printk(KERN_DEBUG "wbuf recovery completed OK\n"));
+       D1(printk(KERN_DEBUG "wbuf recovery completed OK. wbuf_ofs 0x%08x, len 0x%x\n", c->wbuf_ofs, c->wbuf_len));
+
 }
 
 /* Meaning of pad argument:
@@ -412,6 +524,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
 
 static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
 {
+       struct jffs2_eraseblock *wbuf_jeb;
        int ret;
        size_t retlen;
 
@@ -429,6 +542,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
        if (!c->wbuf_len)       /* already checked c->wbuf above */
                return 0;
 
+       wbuf_jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
+       if (jffs2_prealloc_raw_node_refs(c, wbuf_jeb, c->nextblock->allocated_refs + 1))
+               return -ENOMEM;
+
        /* claim remaining space on the page
           this happens, if we have a change to a new block,
           or if fsync forces us to flush the writebuffer.
@@ -458,15 +575,12 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
        if (breakme++ == 20) {
                printk(KERN_NOTICE "Faking write error at 0x%08x\n", c->wbuf_ofs);
                breakme = 0;
-               c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize,
-                                       &retlen, brokenbuf, NULL, c->oobinfo);
+               c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen,
+                             brokenbuf);
                ret = -EIO;
        } else
 #endif
 
-       if (jffs2_cleanmarker_oob(c))
-               ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo);
-       else
                ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);
 
        if (ret || retlen != c->wbuf_pagesize) {
@@ -483,32 +597,34 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
                return ret;
        }
 
-       spin_lock(&c->erase_completion_lock);
-
        /* Adjust free size of the block if we padded. */
        if (pad) {
-               struct jffs2_eraseblock *jeb;
-
-               jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
+               uint32_t waste = c->wbuf_pagesize - c->wbuf_len;
 
                D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n",
-                         (jeb==c->nextblock)?"next":"", jeb->offset));
+                         (wbuf_jeb==c->nextblock)?"next":"", wbuf_jeb->offset));
 
                /* wbuf_pagesize - wbuf_len is the amount of space that's to be
                   padded. If there is less free space in the block than that,
                   something screwed up */
-               if (jeb->free_size < (c->wbuf_pagesize - c->wbuf_len)) {
+               if (wbuf_jeb->free_size < waste) {
                        printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n",
-                              c->wbuf_ofs, c->wbuf_len, c->wbuf_pagesize-c->wbuf_len);
+                              c->wbuf_ofs, c->wbuf_len, waste);
                        printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n",
-                              jeb->offset, jeb->free_size);
+                              wbuf_jeb->offset, wbuf_jeb->free_size);
                        BUG();
                }
-               jeb->free_size -= (c->wbuf_pagesize - c->wbuf_len);
-               c->free_size -= (c->wbuf_pagesize - c->wbuf_len);
-               jeb->wasted_size += (c->wbuf_pagesize - c->wbuf_len);
-               c->wasted_size += (c->wbuf_pagesize - c->wbuf_len);
-       }
+
+               spin_lock(&c->erase_completion_lock);
+
+               jffs2_link_node_ref(c, wbuf_jeb, (c->wbuf_ofs + c->wbuf_len) | REF_OBSOLETE, waste, NULL);
+               /* FIXME: that made it count as dirty. Convert to wasted */
+               wbuf_jeb->dirty_size -= waste;
+               c->dirty_size -= waste;
+               wbuf_jeb->wasted_size += waste;
+               c->wasted_size += waste;
+       } else
+               spin_lock(&c->erase_completion_lock);
 
        /* Stick any now-obsoleted blocks on the erase_pending_list */
        jffs2_refile_wbuf_blocks(c);
@@ -603,20 +719,30 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c)
 
        return ret;
 }
-int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino)
+
+static size_t jffs2_fill_wbuf(struct jffs2_sb_info *c, const uint8_t *buf,
+                             size_t len)
 {
-       struct kvec outvecs[3];
-       uint32_t totlen = 0;
-       uint32_t split_ofs = 0;
-       uint32_t old_totlen;
-       int ret, splitvec = -1;
-       int invec, outvec;
-       size_t wbuf_retlen;
-       unsigned char *wbuf_ptr;
-       size_t donelen = 0;
+       if (len && !c->wbuf_len && (len >= c->wbuf_pagesize))
+               return 0;
+
+       if (len > (c->wbuf_pagesize - c->wbuf_len))
+               len = c->wbuf_pagesize - c->wbuf_len;
+       memcpy(c->wbuf + c->wbuf_len, buf, len);
+       c->wbuf_len += (uint32_t) len;
+       return len;
+}
+
+int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs,
+                      unsigned long count, loff_t to, size_t *retlen,
+                      uint32_t ino)
+{
+       struct jffs2_eraseblock *jeb;
+       size_t wbuf_retlen, donelen = 0;
        uint32_t outvec_to = to;
+       int ret, invec;
 
-       /* If not NAND flash, don't bother */
+       /* If not writebuffered flash, don't bother */
        if (!jffs2_is_writebuffered(c))
                return jffs2_flash_direct_writev(c, invecs, count, to, retlen);
 
@@ -629,34 +755,22 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig
                memset(c->wbuf,0xff,c->wbuf_pagesize);
        }
 
-       /* Fixup the wbuf if we are moving to a new eraseblock.  The checks below
-          fail for ECC'd NOR because cleanmarker == 16, so a block starts at
-          xxx0010.  */
-       if (jffs2_nor_ecc(c)) {
-               if (((c->wbuf_ofs % c->sector_size) == 0) && !c->wbuf_len) {
-                       c->wbuf_ofs = PAGE_DIV(to);
-                       c->wbuf_len = PAGE_MOD(to);
-                       memset(c->wbuf,0xff,c->wbuf_pagesize);
-               }
-       }
-
-       /* Sanity checks on target address.
-          It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs),
-          and it's permitted to write at the beginning of a new
-          erase block. Anything else, and you die.
-          New block starts at xxx000c (0-b = block header)
-       */
+       /*
+        * Sanity checks on target address.  It's permitted to write
+        * at PAD(c->wbuf_len+c->wbuf_ofs), and it's permitted to
+        * write at the beginning of a new erase block. Anything else,
+        * and you die.  New block starts at xxx000c (0-b = block
+        * header)
+        */
        if (SECTOR_ADDR(to) != SECTOR_ADDR(c->wbuf_ofs)) {
                /* It's a write to a new block */
                if (c->wbuf_len) {
-                       D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs));
+                       D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx "
+                                 "causes flush of wbuf at 0x%08x\n",
+                                 (unsigned long)to, c->wbuf_ofs));
                        ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);
-                       if (ret) {
-                               /* the underlying layer has to check wbuf_len to do the cleanup */
-                               D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret));
-                               *retlen = 0;
-                               goto exit;
-                       }
+                       if (ret)
+                               goto outerr;
                }
                /* set pointer to new block */
                c->wbuf_ofs = PAGE_DIV(to);
@@ -665,165 +779,70 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig
 
        if (to != PAD(c->wbuf_ofs + c->wbuf_len)) {
                /* We're not writing immediately after the writebuffer. Bad. */
-               printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write to %08lx\n", (unsigned long)to);
+               printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write "
+                      "to %08lx\n", (unsigned long)to);
                if (c->wbuf_len)
                        printk(KERN_CRIT "wbuf was previously %08x-%08x\n",
-                                         c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len);
+                              c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len);
                BUG();
        }
 
-       /* Note outvecs[3] above. We know count is never greater than 2 */
-       if (count > 2) {
-               printk(KERN_CRIT "jffs2_flash_writev(): count is %ld\n", count);
-               BUG();
-       }
-
-       invec = 0;
-       outvec = 0;
-
-       /* Fill writebuffer first, if already in use */
-       if (c->wbuf_len) {
-               uint32_t invec_ofs = 0;
-
-               /* adjust alignment offset */
-               if (c->wbuf_len != PAGE_MOD(to)) {
-                       c->wbuf_len = PAGE_MOD(to);
-                       /* take care of alignment to next page */
-                       if (!c->wbuf_len)
-                               c->wbuf_len = c->wbuf_pagesize;
-               }
-
-               while(c->wbuf_len < c->wbuf_pagesize) {
-                       uint32_t thislen;
-
-                       if (invec == count)
-                               goto alldone;
-
-                       thislen = c->wbuf_pagesize - c->wbuf_len;
-
-                       if (thislen >= invecs[invec].iov_len)
-                               thislen = invecs[invec].iov_len;
-
-                       invec_ofs = thislen;
-
-                       memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen);
-                       c->wbuf_len += thislen;
-                       donelen += thislen;
-                       /* Get next invec, if actual did not fill the buffer */
-                       if (c->wbuf_len < c->wbuf_pagesize)
-                               invec++;
-               }
-
-               /* write buffer is full, flush buffer */
-               ret = __jffs2_flush_wbuf(c, NOPAD);
-               if (ret) {
-                       /* the underlying layer has to check wbuf_len to do the cleanup */
-                       D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret));
-                       /* Retlen zero to make sure our caller doesn't mark the space dirty.
-                          We've already done everything that's necessary */
-                       *retlen = 0;
-                       goto exit;
-               }
-               outvec_to += donelen;
-               c->wbuf_ofs = outvec_to;
-
-               /* All invecs done ? */
-               if (invec == count)
-                       goto alldone;
-
-               /* Set up the first outvec, containing the remainder of the
-                  invec we partially used */
-               if (invecs[invec].iov_len > invec_ofs) {
-                       outvecs[0].iov_base = invecs[invec].iov_base+invec_ofs;
-                       totlen = outvecs[0].iov_len = invecs[invec].iov_len-invec_ofs;
-                       if (totlen > c->wbuf_pagesize) {
-                               splitvec = outvec;
-                               split_ofs = outvecs[0].iov_len - PAGE_MOD(totlen);
-                       }
-                       outvec++;
-               }
-               invec++;
-       }
-
-       /* OK, now we've flushed the wbuf and the start of the bits
-          we have been asked to write, now to write the rest.... */
-
-       /* totlen holds the amount of data still to be written */
-       old_totlen = totlen;
-       for ( ; invec < count; invec++,outvec++ ) {
-               outvecs[outvec].iov_base = invecs[invec].iov_base;
-               totlen += outvecs[outvec].iov_len = invecs[invec].iov_len;
-               if (PAGE_DIV(totlen) != PAGE_DIV(old_totlen)) {
-                       splitvec = outvec;
-                       split_ofs = outvecs[outvec].iov_len - PAGE_MOD(totlen);
-                       old_totlen = totlen;
+       /* adjust alignment offset */
+       if (c->wbuf_len != PAGE_MOD(to)) {
+               c->wbuf_len = PAGE_MOD(to);
+               /* take care of alignment to next page */
+               if (!c->wbuf_len) {
+                       c->wbuf_len = c->wbuf_pagesize;
+                       ret = __jffs2_flush_wbuf(c, NOPAD);
+                       if (ret)
+                               goto outerr;
                }
        }
 
-       /* Now the outvecs array holds all the remaining data to write */
-       /* Up to splitvec,split_ofs is to be written immediately. The rest
-          goes into the (now-empty) wbuf */
-
-       if (splitvec != -1) {
-               uint32_t remainder;
-
-               remainder = outvecs[splitvec].iov_len - split_ofs;
-               outvecs[splitvec].iov_len = split_ofs;
-
-               /* We did cross a page boundary, so we write some now */
-               if (jffs2_cleanmarker_oob(c))
-                       ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo);
-               else
-                       ret = jffs2_flash_direct_writev(c, outvecs, splitvec+1, outvec_to, &wbuf_retlen);
-
-               if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) {
-                       /* At this point we have no problem,
-                          c->wbuf is empty. However refile nextblock to avoid
-                          writing again to same address.
-                       */
-                       struct jffs2_eraseblock *jeb;
+       for (invec = 0; invec < count; invec++) {
+               int vlen = invecs[invec].iov_len;
+               uint8_t *v = invecs[invec].iov_base;
 
-                       spin_lock(&c->erase_completion_lock);
+               wbuf_retlen = jffs2_fill_wbuf(c, v, vlen);
 
-                       jeb = &c->blocks[outvec_to / c->sector_size];
-                       jffs2_block_refile(c, jeb, REFILE_ANYWAY);
-
-                       *retlen = 0;
-                       spin_unlock(&c->erase_completion_lock);
-                       goto exit;
+               if (c->wbuf_len == c->wbuf_pagesize) {
+                       ret = __jffs2_flush_wbuf(c, NOPAD);
+                       if (ret)
+                               goto outerr;
                }
-
+               vlen -= wbuf_retlen;
+               outvec_to += wbuf_retlen;
                donelen += wbuf_retlen;
-               c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen);
-
-               if (remainder) {
-                       outvecs[splitvec].iov_base += split_ofs;
-                       outvecs[splitvec].iov_len = remainder;
-               } else {
-                       splitvec++;
+               v += wbuf_retlen;
+
+               if (vlen >= c->wbuf_pagesize) {
+                       ret = c->mtd->write(c->mtd, outvec_to, PAGE_DIV(vlen),
+                                           &wbuf_retlen, v);
+                       if (ret < 0 || wbuf_retlen != PAGE_DIV(vlen))
+                               goto outfile;
+
+                       vlen -= wbuf_retlen;
+                       outvec_to += wbuf_retlen;
+                       c->wbuf_ofs = outvec_to;
+                       donelen += wbuf_retlen;
+                       v += wbuf_retlen;
                }
 
-       } else {
-               splitvec = 0;
-       }
-
-       /* Now splitvec points to the start of the bits we have to copy
-          into the wbuf */
-       wbuf_ptr = c->wbuf;
+               wbuf_retlen = jffs2_fill_wbuf(c, v, vlen);
+               if (c->wbuf_len == c->wbuf_pagesize) {
+                       ret = __jffs2_flush_wbuf(c, NOPAD);
+                       if (ret)
+                               goto outerr;
+               }
 
-       for ( ; splitvec < outvec; splitvec++) {
-               /* Don't copy the wbuf into itself */
-               if (outvecs[splitvec].iov_base == c->wbuf)
-                       continue;
-               memcpy(wbuf_ptr, outvecs[splitvec].iov_base, outvecs[splitvec].iov_len);
-               wbuf_ptr += outvecs[splitvec].iov_len;
-               donelen += outvecs[splitvec].iov_len;
+               outvec_to += wbuf_retlen;
+               donelen += wbuf_retlen;
        }
-       c->wbuf_len = wbuf_ptr - c->wbuf;
 
-       /* If there's a remainder in the wbuf and it's a non-GC write,
-          remember that the wbuf affects this ino */
-alldone:
+       /*
+        * If there's a remainder in the wbuf and it's a non-GC write,
+        * remember that the wbuf affects this ino
+        */
        *retlen = donelen;
 
        if (jffs2_sum_active()) {
@@ -836,8 +855,24 @@ alldone:
                jffs2_wbuf_dirties_inode(c, ino);
 
        ret = 0;
+       up_write(&c->wbuf_sem);
+       return ret;
 
-exit:
+outfile:
+       /*
+        * At this point we have no problem, c->wbuf is empty. However
+        * refile nextblock to avoid writing again to same address.
+        */
+
+       spin_lock(&c->erase_completion_lock);
+
+       jeb = &c->blocks[outvec_to / c->sector_size];
+       jffs2_block_refile(c, jeb, REFILE_ANYWAY);
+
+       spin_unlock(&c->erase_completion_lock);
+
+outerr:
+       *retlen = 0;
        up_write(&c->wbuf_sem);
        return ret;
 }
@@ -846,7 +881,8 @@ exit:
  *     This is the entry for flash write.
  *     Check, if we work on NAND FLASH, if so build an kvec and write it via vritev
 */
-int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf)
+int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
+                     size_t *retlen, const u_char *buf)
 {
        struct kvec vecs[1];
 
@@ -871,25 +907,23 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re
 
        /* Read flash */
        down_read(&c->wbuf_sem);
-       if (jffs2_cleanmarker_oob(c))
-               ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo);
-       else
-               ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);
-
-       if ( (ret == -EBADMSG) && (*retlen == len) ) {
-               printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",
-                      len, ofs);
+       ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);
+
+       if ( (ret == -EBADMSG || ret == -EUCLEAN) && (*retlen == len) ) {
+               if (ret == -EBADMSG)
+                       printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx)"
+                              " returned ECC error\n", len, ofs);
                /*
-                * We have the raw data without ECC correction in the buffer, maybe
-                * we are lucky and all data or parts are correct. We check the node.
-                * If data are corrupted node check will sort it out.
-                * We keep this block, it will fail on write or erase and the we
-                * mark it bad. Or should we do that now? But we should give him a chance.
-                * Maybe we had a system crash or power loss before the ecc write or
-                * a erase was completed.
+                * We have the raw data without ECC correction in the buffer,
+                * maybe we are lucky and all data or parts are correct. We
+                * check the node.  If data are corrupted node check will sort
+                * it out.  We keep this block, it will fail on write or erase
+                * and the we mark it bad. Or should we do that now? But we
+                * should give him a chance.  Maybe we had a system crash or
+                * power loss before the ecc write or a erase was completed.
                 * So we return success. :)
                 */
-               ret = 0;
+               ret = 0;
        }
 
        /* if no writebuffer available or write buffer empty, return */
@@ -911,7 +945,7 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re
                orbf = (c->wbuf_ofs - ofs);     /* offset in read buffer */
                if (orbf > len)                 /* is write beyond write buffer ? */
                        goto exit;
-               lwbf = len - orbf;              /* number of bytes to copy */
+               lwbf = len - orbf;              /* number of bytes to copy */
                if (lwbf > c->wbuf_len)
                        lwbf = c->wbuf_len;
        }
@@ -923,158 +957,159 @@ exit:
        return ret;
 }
 
+#define NR_OOB_SCAN_PAGES      4
+
 /*
- *     Check, if the out of band area is empty
+ * Check, if the out of band area is empty
  */
-int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int mode)
+int jffs2_check_oob_empty(struct jffs2_sb_info *c,
+                         struct jffs2_eraseblock *jeb, int mode)
 {
-       unsigned char *buf;
-       int     ret = 0;
-       int     i,len,page;
-       size_t  retlen;
-       int     oob_size;
-
-       /* allocate a buffer for all oob data in this sector */
-       oob_size = c->mtd->oobsize;
-       len = 4 * oob_size;
-       buf = kmalloc(len, GFP_KERNEL);
-       if (!buf) {
-               printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n");
-               return -ENOMEM;
-       }
-       /*
-        * if mode = 0, we scan for a total empty oob area, else we have
-        * to take care of the cleanmarker in the first page of the block
-       */
-       ret = jffs2_flash_read_oob(c, jeb->offset, len , &retlen, buf);
+       int i, page, ret;
+       int oobsize = c->mtd->oobsize;
+       struct mtd_oob_ops ops;
+
+       ops.len = NR_OOB_SCAN_PAGES * oobsize;
+       ops.ooblen = oobsize;
+       ops.oobbuf = c->oobbuf;
+       ops.ooboffs = 0;
+       ops.datbuf = NULL;
+       ops.mode = MTD_OOB_PLACE;
+
+       ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops);
        if (ret) {
-               D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));
-               goto out;
+               D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
+                         "failed %d for block at %08x\n", ret, jeb->offset));
+               return ret;
        }
 
-       if (retlen < len) {
-               D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read "
-                         "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset));
-               ret = -EIO;
-               goto out;
+       if (ops.retlen < ops.len) {
+               D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
+                         "returned short read (%zd bytes not %d) for block "
+                         "at %08x\n", ops.retlen, ops.len, jeb->offset));
+               return -EIO;
        }
 
        /* Special check for first page */
-       for(i = 0; i < oob_size ; i++) {
+       for(i = 0; i < oobsize ; i++) {
                /* Yeah, we know about the cleanmarker. */
                if (mode && i >= c->fsdata_pos &&
                    i < c->fsdata_pos + c->fsdata_len)
                        continue;
 
-               if (buf[i] != 0xFF) {
-                       D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n",
-                                 buf[i], i, jeb->offset));
-                       ret = 1;
-                       goto out;
+               if (ops.oobbuf[i] != 0xFF) {
+                       D2(printk(KERN_DEBUG "Found %02x at %x in OOB for "
+                                 "%08x\n", ops.oobbuf[i], i, jeb->offset));
+                       return 1;
                }
        }
 
        /* we know, we are aligned :) */
-       for (page = oob_size; page < len; page += sizeof(long)) {
-               unsigned long dat = *(unsigned long *)(&buf[page]);
-               if(dat != -1) {
-                       ret = 1;
-                       goto out;
-               }
+       for (page = oobsize; page < ops.len; page += sizeof(long)) {
+               long dat = *(long *)(&ops.oobbuf[page]);
+               if(dat != -1)
+                       return 1;
        }
-
-out:
-       kfree(buf);
-
-       return ret;
+       return 0;
 }
 
 /*
-*      Scan for a valid cleanmarker and for bad blocks
-*      For virtual blocks (concatenated physical blocks) check the cleanmarker
-*      only in the first page of the first physical block, but scan for bad blocks in all
-*      physical blocks
-*/
-int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+ * Scan for a valid cleanmarker and for bad blocks
+ */
+int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c,
+                                 struct jffs2_eraseblock *jeb)
 {
        struct jffs2_unknown_node n;
-       unsigned char buf[2 * NAND_MAX_OOBSIZE];
-       unsigned char *p;
-       int ret, i, cnt, retval = 0;
-       size_t retlen, offset;
-       int oob_size;
-
-       offset = jeb->offset;
-       oob_size = c->mtd->oobsize;
-
-       /* Loop through the physical blocks */
-       for (cnt = 0; cnt < (c->sector_size / c->mtd->erasesize); cnt++) {
-               /* Check first if the block is bad. */
-               if (c->mtd->block_isbad (c->mtd, offset)) {
-                       D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x\n", jeb->offset));
-                       return 2;
-               }
-               /*
-                  *    We read oob data from page 0 and 1 of the block.
-                  *    page 0 contains cleanmarker and badblock info
-                  *    page 1 contains failure count of this block
-                */
-               ret = c->mtd->read_oob (c->mtd, offset, oob_size << 1, &retlen, buf);
+       struct mtd_oob_ops ops;
+       int oobsize = c->mtd->oobsize;
+       unsigned char *p,*b;
+       int i, ret;
+       size_t offset = jeb->offset;
+
+       /* Check first if the block is bad. */
+       if (c->mtd->block_isbad(c->mtd, offset)) {
+               D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker()"
+                          ": Bad block at %08x\n", jeb->offset));
+               return 2;
+       }
 
-               if (ret) {
-                       D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));
-                       return ret;
-               }
-               if (retlen < (oob_size << 1)) {
-                       D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size << 1, jeb->offset));
-                       return -EIO;
-               }
+       ops.len = oobsize;
+       ops.ooblen = oobsize;
+       ops.oobbuf = c->oobbuf;
+       ops.ooboffs = 0;
+       ops.datbuf = NULL;
+       ops.mode = MTD_OOB_PLACE;
 
-               /* Check cleanmarker only on the first physical block */
-               if (!cnt) {
-                       n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
-                       n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-                       n.totlen = cpu_to_je32 (8);
-                       p = (unsigned char *) &n;
+       ret = c->mtd->read_oob(c->mtd, offset, &ops);
+       if (ret) {
+               D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
+                          "Read OOB failed %d for block at %08x\n",
+                          ret, jeb->offset));
+               return ret;
+       }
 
-                       for (i = 0; i < c->fsdata_len; i++) {
-                               if (buf[c->fsdata_pos + i] != p[i]) {
-                                       retval = 1;
-                               }
-                       }
-                       D1(if (retval == 1) {
-                               printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset);
-                               printk(KERN_WARNING "OOB at %08x was ", offset);
-                               for (i=0; i < oob_size; i++) {
-                                       printk("%02x ", buf[i]);
-                               }
-                               printk("\n");
-                       })
-               }
-               offset += c->mtd->erasesize;
+       if (ops.retlen < ops.len) {
+               D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): "
+                           "Read OOB return short read (%zd bytes not %d) "
+                           "for block at %08x\n", ops.retlen, ops.len,
+                           jeb->offset));
+               return -EIO;
        }
-       return retval;
+
+       n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
+       n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
+       n.totlen = cpu_to_je32 (8);
+       p = (unsigned char *) &n;
+       b = c->oobbuf + c->fsdata_pos;
+
+       for (i = c->fsdata_len; i; i--) {
+               if (*b++ != *p++)
+                       ret = 1;
+       }
+
+       D1(if (ret == 1) {
+               printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
+                      "Cleanmarker node not detected in block at %08x\n",
+                      offset);
+               printk(KERN_WARNING "OOB at %08zx was ", offset);
+               for (i=0; i < oobsize; i++)
+                       printk("%02x ", c->oobbuf[i]);
+               printk("\n");
+       });
+       return ret;
 }
 
-int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
+                                struct jffs2_eraseblock *jeb)
 {
-       struct  jffs2_unknown_node n;
-       int     ret;
-       size_t  retlen;
+       struct jffs2_unknown_node n;
+       int     ret;
+       struct mtd_oob_ops ops;
 
        n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
        n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
        n.totlen = cpu_to_je32(8);
 
-       ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n);
+       ops.len = c->fsdata_len;
+       ops.ooblen = c->fsdata_len;;
+       ops.oobbuf = (uint8_t *)&n;
+       ops.ooboffs = c->fsdata_pos;
+       ops.datbuf = NULL;
+       ops.mode = MTD_OOB_PLACE;
+
+       ret = c->mtd->write_oob(c->mtd, jeb->offset, &ops);
 
        if (ret) {
-               D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret));
+               D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
+                         "Write failed for block at %08x: error %d\n",
+                         jeb->offset, ret));
                return ret;
        }
-       if (retlen != c->fsdata_len) {
-               D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, c->fsdata_len));
-               return ret;
+       if (ops.retlen != ops.len) {
+               D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
+                         "Short write for block at %08x: %zd not %d\n",
+                         jeb->offset, ops.retlen, ops.len));
+               return -EIO;
        }
        return 0;
 }
@@ -1108,18 +1143,9 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
        return 1;
 }
 
-#define NAND_JFFS2_OOB16_FSDALEN       8
-
-static struct nand_oobinfo jffs2_oobinfo_docecc = {
-       .useecc = MTD_NANDECC_PLACE,
-       .eccbytes = 6,
-       .eccpos = {0,1,2,3,4,5}
-};
-
-
 static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
 {
-       struct nand_oobinfo *oinfo = &c->mtd->oobinfo;
+       struct nand_ecclayout *oinfo = c->mtd->ecclayout;
 
        /* Do this only, if we have an oob buffer */
        if (!c->mtd->oobsize)
@@ -1129,33 +1155,23 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
        c->cleanmarker_size = 0;
 
        /* Should we use autoplacement ? */
-       if (oinfo && oinfo->useecc == MTD_NANDECC_AUTOPLACE) {
-               D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
-               /* Get the position of the free bytes */
-               if (!oinfo->oobfree[0][1]) {
-                       printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep. Autoplacement selected and no empty space in oob\n");
-                       return -ENOSPC;
-               }
-               c->fsdata_pos = oinfo->oobfree[0][0];
-               c->fsdata_len = oinfo->oobfree[0][1];
-               if (c->fsdata_len > 8)
-                       c->fsdata_len = 8;
-       } else {
-               /* This is just a legacy fallback and should go away soon */
-               switch(c->mtd->ecctype) {
-               case MTD_ECC_RS_DiskOnChip:
-                       printk(KERN_WARNING "JFFS2 using DiskOnChip hardware ECC without autoplacement. Fix it!\n");
-                       c->oobinfo = &jffs2_oobinfo_docecc;
-                       c->fsdata_pos = 6;
-                       c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN;
-                       c->badblock_pos = 15;
-                       break;
+       if (!oinfo) {
+               D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
+               return -EINVAL;
+       }
 
-               default:
-                       D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
-                       return -EINVAL;
-               }
+       D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
+       /* Get the position of the free bytes */
+       if (!oinfo->oobfree[0].length) {
+               printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep."
+                       " Autoplacement selected and no empty space in oob\n");
+               return -ENOSPC;
        }
+       c->fsdata_pos = oinfo->oobfree[0].offset;
+       c->fsdata_len = oinfo->oobfree[0].length;
+       if (c->fsdata_len > 8)
+               c->fsdata_len = 8;
+
        return 0;
 }
 
@@ -1165,13 +1181,17 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
 
        /* Initialise write buffer */
        init_rwsem(&c->wbuf_sem);
-       c->wbuf_pagesize = c->mtd->oobblock;
+       c->wbuf_pagesize = c->mtd->writesize;
        c->wbuf_ofs = 0xFFFFFFFF;
 
        c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
        if (!c->wbuf)
                return -ENOMEM;
 
+       c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->mtd->oobsize, GFP_KERNEL);
+       if (!c->oobbuf)
+               return -ENOMEM;
+
        res = jffs2_nand_set_oobinfo(c);
 
 #ifdef BREAKME
@@ -1189,6 +1209,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
 {
        kfree(c->wbuf);
+       kfree(c->oobbuf);
 }
 
 int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
@@ -1236,33 +1257,14 @@ void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) {
        kfree(c->wbuf);
 }
 
-int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) {
-       /* Cleanmarker is actually larger on the flashes */
-       c->cleanmarker_size = 16;
-
-       /* Initialize write buffer */
-       init_rwsem(&c->wbuf_sem);
-       c->wbuf_pagesize = c->mtd->eccsize;
-       c->wbuf_ofs = 0xFFFFFFFF;
-
-       c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
-       if (!c->wbuf)
-               return -ENOMEM;
-
-       return 0;
-}
-
-void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) {
-       kfree(c->wbuf);
-}
-
 int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
-       /* Cleanmarker currently occupies a whole programming region */
-       c->cleanmarker_size = MTD_PROGREGION_SIZE(c->mtd);
+       /* Cleanmarker currently occupies whole programming regions,
+        * either one or 2 for 8Byte STMicro flashes. */
+       c->cleanmarker_size = max(16u, c->mtd->writesize);
 
        /* Initialize write buffer */
        init_rwsem(&c->wbuf_sem);
-       c->wbuf_pagesize = MTD_PROGREGION_SIZE(c->mtd);
+       c->wbuf_pagesize = c->mtd->writesize;
        c->wbuf_ofs = 0xFFFFFFFF;
 
        c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
index 1342f0158e9b0d0da2565c99c18eb5f088c501a5..67176792e138e8e7a3cbeb5efeaf423d600eaf05 100644 (file)
@@ -37,7 +37,6 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint
        f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
        f->inocache->state = INO_STATE_PRESENT;
 
-
        jffs2_add_ino_cache(c, f->inocache);
        D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));
        ri->ino = cpu_to_je32(f->inocache->ino);
@@ -57,12 +56,14 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint
 /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it,
    write it to the flash, link it into the existing inode/fragment list */
 
-struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode)
+struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+                                          struct jffs2_raw_inode *ri, const unsigned char *data,
+                                          uint32_t datalen, int alloc_mode)
 
 {
-       struct jffs2_raw_node_ref *raw;
        struct jffs2_full_dnode *fn;
        size_t retlen;
+       uint32_t flash_ofs;
        struct kvec vecs[2];
        int ret;
        int retried = 0;
@@ -78,34 +79,21 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
        vecs[1].iov_base = (unsigned char *)data;
        vecs[1].iov_len = datalen;
 
-       jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
-
        if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
                printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen);
        }
-       raw = jffs2_alloc_raw_node_ref();
-       if (!raw)
-               return ERR_PTR(-ENOMEM);
 
        fn = jffs2_alloc_full_dnode();
-       if (!fn) {
-               jffs2_free_raw_node_ref(raw);
+       if (!fn)
                return ERR_PTR(-ENOMEM);
-       }
-
-       fn->ofs = je32_to_cpu(ri->offset);
-       fn->size = je32_to_cpu(ri->dsize);
-       fn->frags = 0;
 
        /* check number of valid vecs */
        if (!datalen || !data)
                cnt = 1;
  retry:
-       fn->raw = raw;
+       flash_ofs = write_ofs(c);
 
-       raw->flash_offset = flash_ofs;
-       raw->__totlen = PAD(sizeof(*ri)+datalen);
-       raw->next_phys = NULL;
+       jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
 
        if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) {
                BUG_ON(!retried);
@@ -125,22 +113,16 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
 
                /* Mark the space as dirtied */
                if (retlen) {
-                       /* Doesn't belong to any inode */
-                       raw->next_in_ino = NULL;
-
                        /* Don't change raw->size to match retlen. We may have
                           written the node header already, and only the data will
                           seem corrupted, in which case the scan would skip over
                           any node we write before the original intended end of
                           this node */
-                       raw->flash_offset |= REF_OBSOLETE;
-                       jffs2_add_physical_node_ref(c, raw);
-                       jffs2_mark_node_obsolete(c, raw);
+                       jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL);
                } else {
-                       printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
-                       jffs2_free_raw_node_ref(raw);
+                       printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
                }
-               if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) {
+               if (!retried && alloc_mode != ALLOC_NORETRY) {
                        /* Try to reallocate space and retry */
                        uint32_t dummy;
                        struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
@@ -153,19 +135,20 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
                        jffs2_dbg_acct_paranoia_check(c, jeb);
 
                        if (alloc_mode == ALLOC_GC) {
-                               ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs,
-                                                       &dummy, JFFS2_SUMMARY_INODE_SIZE);
+                               ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &dummy,
+                                                            JFFS2_SUMMARY_INODE_SIZE);
                        } else {
                                /* Locking pain */
                                up(&f->sem);
                                jffs2_complete_reservation(c);
 
-                               ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs,
-                                                       &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
+                               ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy,
+                                                         alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
                                down(&f->sem);
                        }
 
                        if (!ret) {
+                               flash_ofs = write_ofs(c);
                                D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
 
                                jffs2_dbg_acct_sanity_check(c,jeb);
@@ -174,7 +157,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
                                goto retry;
                        }
                        D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
-                       jffs2_free_raw_node_ref(raw);
                }
                /* Release the full_dnode which is now useless, and return */
                jffs2_free_full_dnode(fn);
@@ -188,20 +170,17 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
        if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) ||
            ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) &&
              (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) ==  je32_to_cpu(ri->isize)))) {
-               raw->flash_offset |= REF_PRISTINE;
+               flash_ofs |= REF_PRISTINE;
        } else {
-               raw->flash_offset |= REF_NORMAL;
+               flash_ofs |= REF_NORMAL;
        }
-       jffs2_add_physical_node_ref(c, raw);
-
-       /* Link into per-inode list */
-       spin_lock(&c->erase_completion_lock);
-       raw->next_in_ino = f->inocache->nodes;
-       f->inocache->nodes = raw;
-       spin_unlock(&c->erase_completion_lock);
+       fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache);
+       fn->ofs = je32_to_cpu(ri->offset);
+       fn->size = je32_to_cpu(ri->dsize);
+       fn->frags = 0;
 
        D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n",
-                 flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize),
+                 flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize),
                  je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
                  je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen)));
 
@@ -212,12 +191,14 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2
        return fn;
 }
 
-struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode)
+struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+                                            struct jffs2_raw_dirent *rd, const unsigned char *name,
+                                            uint32_t namelen, int alloc_mode)
 {
-       struct jffs2_raw_node_ref *raw;
        struct jffs2_full_dirent *fd;
        size_t retlen;
        struct kvec vecs[2];
+       uint32_t flash_ofs;
        int retried = 0;
        int ret;
 
@@ -228,26 +209,16 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
        D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
                printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n");
                BUG();
-       }
-          );
+          });
 
        vecs[0].iov_base = rd;
        vecs[0].iov_len = sizeof(*rd);
        vecs[1].iov_base = (unsigned char *)name;
        vecs[1].iov_len = namelen;
 
-       jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
-
-       raw = jffs2_alloc_raw_node_ref();
-
-       if (!raw)
-               return ERR_PTR(-ENOMEM);
-
        fd = jffs2_alloc_full_dirent(namelen+1);
-       if (!fd) {
-               jffs2_free_raw_node_ref(raw);
+       if (!fd)
                return ERR_PTR(-ENOMEM);
-       }
 
        fd->version = je32_to_cpu(rd->version);
        fd->ino = je32_to_cpu(rd->ino);
@@ -257,11 +228,9 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
        fd->name[namelen]=0;
 
  retry:
-       fd->raw = raw;
+       flash_ofs = write_ofs(c);
 
-       raw->flash_offset = flash_ofs;
-       raw->__totlen = PAD(sizeof(*rd)+namelen);
-       raw->next_phys = NULL;
+       jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
 
        if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) {
                BUG_ON(!retried);
@@ -280,15 +249,11 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
                               sizeof(*rd)+namelen, flash_ofs, ret, retlen);
                /* Mark the space as dirtied */
                if (retlen) {
-                       raw->next_in_ino = NULL;
-                       raw->flash_offset |= REF_OBSOLETE;
-                       jffs2_add_physical_node_ref(c, raw);
-                       jffs2_mark_node_obsolete(c, raw);
+                       jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL);
                } else {
-                       printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
-                       jffs2_free_raw_node_ref(raw);
+                       printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
                }
-               if (!retried && (raw = jffs2_alloc_raw_node_ref())) {
+               if (!retried) {
                        /* Try to reallocate space and retry */
                        uint32_t dummy;
                        struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
@@ -301,39 +266,33 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff
                        jffs2_dbg_acct_paranoia_check(c, jeb);
 
                        if (alloc_mode == ALLOC_GC) {
-                               ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs,
-                                                       &dummy, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+                               ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &dummy,
+                                                            JFFS2_SUMMARY_DIRENT_SIZE(namelen));
                        } else {
                                /* Locking pain */
                                up(&f->sem);
                                jffs2_complete_reservation(c);
 
-                               ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs,
-                                                       &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+                               ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy,
+                                                         alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
                                down(&f->sem);
                        }
 
                        if (!ret) {
+                               flash_ofs = write_ofs(c);
                                D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
                                jffs2_dbg_acct_sanity_check(c,jeb);
                                jffs2_dbg_acct_paranoia_check(c, jeb);
                                goto retry;
                        }
                        D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
-                       jffs2_free_raw_node_ref(raw);
                }
                /* Release the full_dnode which is now useless, and return */
                jffs2_free_full_dirent(fd);
                return ERR_PTR(ret?ret:-EIO);
        }
        /* Mark the space used */
-       raw->flash_offset |= REF_PRISTINE;
-       jffs2_add_physical_node_ref(c, raw);
-
-       spin_lock(&c->erase_completion_lock);
-       raw->next_in_ino = f->inocache->nodes;
-       f->inocache->nodes = raw;
-       spin_unlock(&c->erase_completion_lock);
+       fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache);
 
        if (retried) {
                jffs2_dbg_acct_sanity_check(c,NULL);
@@ -359,14 +318,14 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                struct jffs2_full_dnode *fn;
                unsigned char *comprbuf = NULL;
                uint16_t comprtype = JFFS2_COMPR_NONE;
-               uint32_t phys_ofs, alloclen;
+               uint32_t alloclen;
                uint32_t datalen, cdatalen;
                int retried = 0;
 
        retry:
                D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset));
 
-               ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs,
+               ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN,
                                        &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
                if (ret) {
                        D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
@@ -394,7 +353,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
                ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
 
-               fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY);
+               fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, ALLOC_NORETRY);
 
                jffs2_free_comprbuf(comprbuf, buf);
 
@@ -448,13 +407,13 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
        struct jffs2_raw_dirent *rd;
        struct jffs2_full_dnode *fn;
        struct jffs2_full_dirent *fd;
-       uint32_t alloclen, phys_ofs;
+       uint32_t alloclen;
        int ret;
 
        /* Try to reserve enough space for both node and dirent.
         * Just the node will do for now, though
         */
-       ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL,
+       ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
                                JFFS2_SUMMARY_INODE_SIZE);
        D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
        if (ret) {
@@ -465,7 +424,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
        ri->data_crc = cpu_to_je32(0);
        ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
 
-       fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
+       fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
 
        D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n",
                  jemode_to_cpu(ri->mode)));
@@ -484,7 +443,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
 
        up(&f->sem);
        jffs2_complete_reservation(c);
-       ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
+       ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
                                ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
 
        if (ret) {
@@ -516,7 +475,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
        rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
        rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
 
-       fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
+       fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
 
        jffs2_free_raw_dirent(rd);
 
@@ -545,7 +504,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
 {
        struct jffs2_raw_dirent *rd;
        struct jffs2_full_dirent *fd;
-       uint32_t alloclen, phys_ofs;
+       uint32_t alloclen;
        int ret;
 
        if (1 /* alternative branch needs testing */ ||
@@ -556,7 +515,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
                if (!rd)
                        return -ENOMEM;
 
-               ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
+               ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
                                        ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
                if (ret) {
                        jffs2_free_raw_dirent(rd);
@@ -580,7 +539,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
                rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
                rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
 
-               fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION);
+               fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_DELETION);
 
                jffs2_free_raw_dirent(rd);
 
@@ -659,14 +618,14 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
 {
        struct jffs2_raw_dirent *rd;
        struct jffs2_full_dirent *fd;
-       uint32_t alloclen, phys_ofs;
+       uint32_t alloclen;
        int ret;
 
        rd = jffs2_alloc_raw_dirent();
        if (!rd)
                return -ENOMEM;
 
-       ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
+       ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
                                ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
        if (ret) {
                jffs2_free_raw_dirent(rd);
@@ -692,7 +651,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
        rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
        rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
 
-       fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
+       fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
 
        jffs2_free_raw_dirent(rd);
 
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
new file mode 100644 (file)
index 0000000..2d82e25
--- /dev/null
@@ -0,0 +1,1238 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/crc32.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+/* -------- xdatum related functions ----------------
+ * xattr_datum_hashkey(xprefix, xname, xvalue, xsize)
+ *   is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is
+ *   the index of the xattr name/value pair cache (c->xattrindex).
+ * unload_xattr_datum(c, xd)
+ *   is used to release xattr name/value pair and detach from c->xattrindex.
+ * reclaim_xattr_datum(c)
+ *   is used to reclaim xattr name/value pairs on the xattr name/value pair cache when
+ *   memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold 
+ *   is hard coded as 32KiB.
+ * delete_xattr_datum_node(c, xd)
+ *   is used to delete a jffs2 node is dominated by xdatum. When EBS(Erase Block Summary) is
+ *   enabled, it overwrites the obsolete node by myself.
+ * delete_xattr_datum(c, xd)
+ *   is used to delete jffs2_xattr_datum object. It must be called with 0-value of reference
+ *   counter. (It means how many jffs2_xattr_ref object refers this xdatum.)
+ * do_verify_xattr_datum(c, xd)
+ *   is used to load the xdatum informations without name/value pair from the medium.
+ *   It's necessary once, because those informations are not collected during mounting
+ *   process when EBS is enabled.
+ *   0 will be returned, if success. An negative return value means recoverable error, and
+ *   positive return value means unrecoverable error. Thus, caller must remove this xdatum
+ *   and xref when it returned positive value.
+ * do_load_xattr_datum(c, xd)
+ *   is used to load name/value pair from the medium.
+ *   The meanings of return value is same as do_verify_xattr_datum().
+ * load_xattr_datum(c, xd)
+ *   is used to be as a wrapper of do_verify_xattr_datum() and do_load_xattr_datum().
+ *   If xd need to call do_verify_xattr_datum() at first, it's called before calling
+ *   do_load_xattr_datum(). The meanings of return value is same as do_verify_xattr_datum().
+ * save_xattr_datum(c, xd)
+ *   is used to write xdatum to medium. xd->version will be incremented.
+ * create_xattr_datum(c, xprefix, xname, xvalue, xsize)
+ *   is used to create new xdatum and write to medium.
+ * -------------------------------------------------- */
+
+static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
+{
+       int name_len = strlen(xname);
+
+       return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
+}
+
+static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version));
+       if (xd->xname) {
+               c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len);
+               kfree(xd->xname);
+       }
+
+       list_del_init(&xd->xindex);
+       xd->hashkey = 0;
+       xd->xname = NULL;
+       xd->xvalue = NULL;
+}
+
+static void reclaim_xattr_datum(struct jffs2_sb_info *c)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_xattr_datum *xd, *_xd;
+       uint32_t target, before;
+       static int index = 0;
+       int count;
+
+       if (c->xdatum_mem_threshold > c->xdatum_mem_usage)
+               return;
+
+       before = c->xdatum_mem_usage;
+       target = c->xdatum_mem_usage * 4 / 5; /* 20% reduction */
+       for (count = 0; count < XATTRINDEX_HASHSIZE; count++) {
+               list_for_each_entry_safe(xd, _xd, &c->xattrindex[index], xindex) {
+                       if (xd->flags & JFFS2_XFLAGS_HOT) {
+                               xd->flags &= ~JFFS2_XFLAGS_HOT;
+                       } else if (!(xd->flags & JFFS2_XFLAGS_BIND)) {
+                               unload_xattr_datum(c, xd);
+                       }
+                       if (c->xdatum_mem_usage <= target)
+                               goto out;
+               }
+               index = (index+1) % XATTRINDEX_HASHSIZE;
+       }
+ out:
+       JFFS2_NOTICE("xdatum_mem_usage from %u byte to %u byte (%u byte reclaimed)\n",
+                    before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
+}
+
+static void delete_xattr_datum_node(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_raw_xattr rx;
+       size_t length;
+       int rc;
+
+       if (!xd->node) {
+               JFFS2_WARNING("xdatum (xid=%u) is removed twice.\n", xd->xid);
+               return;
+       }
+       if (jffs2_sum_active()) {
+               memset(&rx, 0xff, sizeof(struct jffs2_raw_xattr));
+               rc = jffs2_flash_read(c, ref_offset(xd->node),
+                                     sizeof(struct jffs2_unknown_node),
+                                     &length, (char *)&rx);
+               if (rc || length != sizeof(struct jffs2_unknown_node)) {
+                       JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
+                                   rc, sizeof(struct jffs2_unknown_node),
+                                   length, ref_offset(xd->node));
+               }
+               rc = jffs2_flash_write(c, ref_offset(xd->node), sizeof(rx),
+                                      &length, (char *)&rx);
+               if (rc || length != sizeof(struct jffs2_raw_xattr)) {
+                       JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu ar %#08x\n",
+                                   rc, sizeof(rx), length, ref_offset(xd->node));
+               }
+       }
+       spin_lock(&c->erase_completion_lock);
+       xd->node->next_in_ino = NULL;
+       spin_unlock(&c->erase_completion_lock);
+       jffs2_mark_node_obsolete(c, xd->node);
+       xd->node = NULL;
+}
+
+static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       BUG_ON(xd->refcnt);
+
+       unload_xattr_datum(c, xd);
+       if (xd->node) {
+               delete_xattr_datum_node(c, xd);
+               xd->node = NULL;
+       }
+       jffs2_free_xattr_datum(xd);
+}
+
+static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_eraseblock *jeb;
+       struct jffs2_raw_xattr rx;
+       size_t readlen;
+       uint32_t crc, totlen;
+       int rc;
+
+       BUG_ON(!xd->node);
+       BUG_ON(ref_flags(xd->node) != REF_UNCHECKED);
+
+       rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx);
+       if (rc || readlen != sizeof(rx)) {
+               JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
+                             rc, sizeof(rx), readlen, ref_offset(xd->node));
+               return rc ? rc : -EIO;
+       }
+       crc = crc32(0, &rx, sizeof(rx) - 4);
+       if (crc != je32_to_cpu(rx.node_crc)) {
+               if (je32_to_cpu(rx.node_crc) != 0xffffffff)
+                       JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+                                   ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc);
+               return EIO;
+       }
+       totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
+       if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
+           || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR
+           || je32_to_cpu(rx.totlen) != totlen
+           || je32_to_cpu(rx.xid) != xd->xid
+           || je32_to_cpu(rx.version) != xd->version) {
+               JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
+                           "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n",
+                           ref_offset(xd->node), je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK,
+                           je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
+                           je32_to_cpu(rx.totlen), totlen,
+                           je32_to_cpu(rx.xid), xd->xid,
+                           je32_to_cpu(rx.version), xd->version);
+               return EIO;
+       }
+       xd->xprefix = rx.xprefix;
+       xd->name_len = rx.name_len;
+       xd->value_len = je16_to_cpu(rx.value_len);
+       xd->data_crc = je32_to_cpu(rx.data_crc);
+
+       /* This JFFS2_NODETYPE_XATTR node is checked */
+       jeb = &c->blocks[ref_offset(xd->node) / c->sector_size];
+       totlen = PAD(je32_to_cpu(rx.totlen));
+
+       spin_lock(&c->erase_completion_lock);
+       c->unchecked_size -= totlen; c->used_size += totlen;
+       jeb->unchecked_size -= totlen; jeb->used_size += totlen;
+       xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE;
+       spin_unlock(&c->erase_completion_lock);
+
+       /* unchecked xdatum is chained with c->xattr_unchecked */
+       list_del_init(&xd->xindex);
+
+       dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n",
+                 xd->xid, xd->version);
+
+       return 0;
+}
+
+static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       char *data;
+       size_t readlen;
+       uint32_t crc, length;
+       int i, ret, retry = 0;
+
+       BUG_ON(!xd->node);
+       BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
+       BUG_ON(!list_empty(&xd->xindex));
+ retry:
+       length = xd->name_len + 1 + xd->value_len;
+       data = kmalloc(length, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       ret = jffs2_flash_read(c, ref_offset(xd->node)+sizeof(struct jffs2_raw_xattr),
+                              length, &readlen, data);
+
+       if (ret || length!=readlen) {
+               JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%zu, at %#08x\n",
+                             ret, length, readlen, ref_offset(xd->node));
+               kfree(data);
+               return ret ? ret : -EIO;
+       }
+
+       data[xd->name_len] = '\0';
+       crc = crc32(0, data, length);
+       if (crc != xd->data_crc) {
+               JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XREF)"
+                             " at %#08x, read: 0x%08x calculated: 0x%08x\n",
+                             ref_offset(xd->node), xd->data_crc, crc);
+               kfree(data);
+               return EIO;
+       }
+
+       xd->flags |= JFFS2_XFLAGS_HOT;
+       xd->xname = data;
+       xd->xvalue = data + xd->name_len+1;
+
+       c->xdatum_mem_usage += length;
+
+       xd->hashkey = xattr_datum_hashkey(xd->xprefix, xd->xname, xd->xvalue, xd->value_len);
+       i = xd->hashkey % XATTRINDEX_HASHSIZE;
+       list_add(&xd->xindex, &c->xattrindex[i]);
+       if (!retry) {
+               retry = 1;
+               reclaim_xattr_datum(c);
+               if (!xd->xname)
+                       goto retry;
+       }
+
+       dbg_xattr("success on loading xdatum (xid=%u, xprefix=%u, xname='%s')\n",
+                 xd->xid, xd->xprefix, xd->xname);
+
+       return 0;
+}
+
+static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem);
+        * rc < 0 : recoverable error, try again
+        * rc = 0 : success
+        * rc > 0 : Unrecoverable error, this node should be deleted.
+        */
+       int rc = 0;
+       BUG_ON(xd->xname);
+       if (!xd->node)
+               return EIO;
+       if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) {
+               rc = do_verify_xattr_datum(c, xd);
+               if (rc > 0) {
+                       list_del_init(&xd->xindex);
+                       delete_xattr_datum_node(c, xd);
+               }
+       }
+       if (!rc)
+               rc = do_load_xattr_datum(c, xd);
+       return rc;
+}
+
+static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_raw_node_ref *raw;
+       struct jffs2_raw_xattr rx;
+       struct kvec vecs[2];
+       size_t length;
+       int rc, totlen;
+       uint32_t phys_ofs = write_ofs(c);
+
+       BUG_ON(!xd->xname);
+
+       vecs[0].iov_base = &rx;
+       vecs[0].iov_len = PAD(sizeof(rx));
+       vecs[1].iov_base = xd->xname;
+       vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
+       totlen = vecs[0].iov_len + vecs[1].iov_len;
+
+       /* Setup raw-xattr */
+       rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+       rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
+       rx.totlen = cpu_to_je32(PAD(totlen));
+       rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
+
+       rx.xid = cpu_to_je32(xd->xid);
+       rx.version = cpu_to_je32(++xd->version);
+       rx.xprefix = xd->xprefix;
+       rx.name_len = xd->name_len;
+       rx.value_len = cpu_to_je16(xd->value_len);
+       rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
+       rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4));
+
+       rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0);
+       if (rc || totlen != length) {
+               JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n",
+                             rc, totlen, length, phys_ofs);
+               rc = rc ? rc : -EIO;
+               if (length)
+                       jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL);
+
+               return rc;
+       }
+
+       /* success */
+       raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL);
+       /* FIXME */ raw->next_in_ino = (void *)xd;
+
+       if (xd->node)
+               delete_xattr_datum_node(c, xd);
+       xd->node = raw;
+
+       dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
+                 xd->xid, xd->version, xd->xprefix, xd->xname);
+
+       return 0;
+}
+
+static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
+                                                   int xprefix, const char *xname,
+                                                   const char *xvalue, int xsize)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_xattr_datum *xd;
+       uint32_t hashkey, name_len;
+       char *data;
+       int i, rc;
+
+       /* Search xattr_datum has same xname/xvalue by index */
+       hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize);
+       i = hashkey % XATTRINDEX_HASHSIZE;
+       list_for_each_entry(xd, &c->xattrindex[i], xindex) {
+               if (xd->hashkey==hashkey
+                   && xd->xprefix==xprefix
+                   && xd->value_len==xsize
+                   && !strcmp(xd->xname, xname)
+                   && !memcmp(xd->xvalue, xvalue, xsize)) {
+                       xd->refcnt++;
+                       return xd;
+               }
+       }
+
+       /* Not found, Create NEW XATTR-Cache */
+       name_len = strlen(xname);
+
+       xd = jffs2_alloc_xattr_datum();
+       if (!xd)
+               return ERR_PTR(-ENOMEM);
+
+       data = kmalloc(name_len + 1 + xsize, GFP_KERNEL);
+       if (!data) {
+               jffs2_free_xattr_datum(xd);
+               return ERR_PTR(-ENOMEM);
+       }
+       strcpy(data, xname);
+       memcpy(data + name_len + 1, xvalue, xsize);
+
+       xd->refcnt = 1;
+       xd->xid = ++c->highest_xid;
+       xd->flags |= JFFS2_XFLAGS_HOT;
+       xd->xprefix = xprefix;
+
+       xd->hashkey = hashkey;
+       xd->xname = data;
+       xd->xvalue = data + name_len + 1;
+       xd->name_len = name_len;
+       xd->value_len = xsize;
+       xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len);
+
+       rc = save_xattr_datum(c, xd);
+       if (rc) {
+               kfree(xd->xname);
+               jffs2_free_xattr_datum(xd);
+               return ERR_PTR(rc);
+       }
+
+       /* Insert Hash Index */
+       i = hashkey % XATTRINDEX_HASHSIZE;
+       list_add(&xd->xindex, &c->xattrindex[i]);
+
+       c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len);
+       reclaim_xattr_datum(c);
+
+       return xd;
+}
+
+/* -------- xref related functions ------------------
+ * verify_xattr_ref(c, ref)
+ *   is used to load xref information from medium. Because summary data does not
+ *   contain xid/ino, it's necessary to verify once while mounting process.
+ * delete_xattr_ref_node(c, ref)
+ *   is used to delete a jffs2 node is dominated by xref. When EBS is enabled,
+ *   it overwrites the obsolete node by myself. 
+ * delete_xattr_ref(c, ref)
+ *   is used to delete jffs2_xattr_ref object. If the reference counter of xdatum
+ *   is refered by this xref become 0, delete_xattr_datum() is called later.
+ * save_xattr_ref(c, ref)
+ *   is used to write xref to medium.
+ * create_xattr_ref(c, ic, xd)
+ *   is used to create a new xref and write to medium.
+ * jffs2_xattr_delete_inode(c, ic)
+ *   is called to remove xrefs related to obsolete inode when inode is unlinked.
+ * jffs2_xattr_free_inode(c, ic)
+ *   is called to release xattr related objects when unmounting. 
+ * check_xattr_ref_inode(c, ic)
+ *   is used to confirm inode does not have duplicate xattr name/value pair.
+ * -------------------------------------------------- */
+static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+       struct jffs2_eraseblock *jeb;
+       struct jffs2_raw_xref rr;
+       size_t readlen;
+       uint32_t crc, totlen;
+       int rc;
+
+       BUG_ON(ref_flags(ref->node) != REF_UNCHECKED);
+
+       rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr);
+       if (rc || sizeof(rr) != readlen) {
+               JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",
+                             rc, sizeof(rr), readlen, ref_offset(ref->node));
+               return rc ? rc : -EIO;
+       }
+       /* obsolete node */
+       crc = crc32(0, &rr, sizeof(rr) - 4);
+       if (crc != je32_to_cpu(rr.node_crc)) {
+               if (je32_to_cpu(rr.node_crc) != 0xffffffff)
+                       JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+                                   ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc);
+               return EIO;
+       }
+       if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
+           || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF
+           || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
+               JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
+                           "nodetype=%#04x/%#04x, totlen=%u/%zu\n",
+                           ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
+                           je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
+                           je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
+               return EIO;
+       }
+       ref->ino = je32_to_cpu(rr.ino);
+       ref->xid = je32_to_cpu(rr.xid);
+
+       /* fixup superblock/eraseblock info */
+       jeb = &c->blocks[ref_offset(ref->node) / c->sector_size];
+       totlen = PAD(sizeof(rr));
+
+       spin_lock(&c->erase_completion_lock);
+       c->unchecked_size -= totlen; c->used_size += totlen;
+       jeb->unchecked_size -= totlen; jeb->used_size += totlen;
+       ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE;
+       spin_unlock(&c->erase_completion_lock);
+
+       dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
+                 ref->ino, ref->xid, ref_offset(ref->node));
+       return 0;
+}
+
+static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+       struct jffs2_raw_xref rr;
+       size_t length;
+       int rc;
+
+       if (jffs2_sum_active()) {
+               memset(&rr, 0xff, sizeof(rr));
+               rc = jffs2_flash_read(c, ref_offset(ref->node),
+                                     sizeof(struct jffs2_unknown_node),
+                                     &length, (char *)&rr);
+               if (rc || length != sizeof(struct jffs2_unknown_node)) {
+                       JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
+                                   rc, sizeof(struct jffs2_unknown_node),
+                                   length, ref_offset(ref->node));
+               }
+               rc = jffs2_flash_write(c, ref_offset(ref->node), sizeof(rr),
+                                      &length, (char *)&rr);
+               if (rc || length != sizeof(struct jffs2_raw_xref)) {
+                       JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu at %#08x\n",
+                                   rc, sizeof(rr), length, ref_offset(ref->node));
+               }
+       }
+       spin_lock(&c->erase_completion_lock);
+       ref->node->next_in_ino = NULL;
+       spin_unlock(&c->erase_completion_lock);
+       jffs2_mark_node_obsolete(c, ref->node);
+       ref->node = NULL;
+}
+
+static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_xattr_datum *xd;
+
+       BUG_ON(!ref->node);
+       delete_xattr_ref_node(c, ref);
+
+       xd = ref->xd;
+       xd->refcnt--;
+       if (!xd->refcnt)
+               delete_xattr_datum(c, xd);
+       jffs2_free_xattr_ref(ref);
+}
+
+static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_raw_node_ref *raw;
+       struct jffs2_raw_xref rr;
+       size_t length;
+       uint32_t phys_ofs = write_ofs(c);
+       int ret;
+
+       rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+       rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
+       rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
+       rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
+
+       rr.ino = cpu_to_je32(ref->ic->ino);
+       rr.xid = cpu_to_je32(ref->xd->xid);
+       rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
+
+       ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
+       if (ret || sizeof(rr) != length) {
+               JFFS2_WARNING("jffs2_flash_write() returned %d, request=%zu, retlen=%zu, at %#08x\n",
+                             ret, sizeof(rr), length, phys_ofs);
+               ret = ret ? ret : -EIO;
+               if (length)
+                       jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL);
+
+               return ret;
+       }
+
+       raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL);
+       /* FIXME */ raw->next_in_ino = (void *)ref;
+       if (ref->node)
+               delete_xattr_ref_node(c, ref);
+       ref->node = raw;
+
+       dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
+
+       return 0;
+}
+
+static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic,
+                                               struct jffs2_xattr_datum *xd)
+{
+       /* must be called under down_write(xattr_sem) */
+       struct jffs2_xattr_ref *ref;
+       int ret;
+
+       ref = jffs2_alloc_xattr_ref();
+       if (!ref)
+               return ERR_PTR(-ENOMEM);
+       ref->ic = ic;
+       ref->xd = xd;
+
+       ret = save_xattr_ref(c, ref);
+       if (ret) {
+               jffs2_free_xattr_ref(ref);
+               return ERR_PTR(ret);
+       }
+
+       /* Chain to inode */
+       ref->next = ic->xref;
+       ic->xref = ref;
+
+       return ref; /* success */
+}
+
+void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+{
+       /* It's called from jffs2_clear_inode() on inode removing.
+          When an inode with XATTR is removed, those XATTRs must be removed. */
+       struct jffs2_xattr_ref *ref, *_ref;
+
+       if (!ic || ic->nlink > 0)
+               return;
+
+       down_write(&c->xattr_sem);
+       for (ref = ic->xref; ref; ref = _ref) {
+               _ref = ref->next;
+               delete_xattr_ref(c, ref);
+       }
+       ic->xref = NULL;
+       up_write(&c->xattr_sem);
+}
+
+void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+{
+       /* It's called from jffs2_free_ino_caches() until unmounting FS. */
+       struct jffs2_xattr_datum *xd;
+       struct jffs2_xattr_ref *ref, *_ref;
+
+       down_write(&c->xattr_sem);
+       for (ref = ic->xref; ref; ref = _ref) {
+               _ref = ref->next;
+               xd = ref->xd;
+               xd->refcnt--;
+               if (!xd->refcnt) {
+                       unload_xattr_datum(c, xd);
+                       jffs2_free_xattr_datum(xd);
+               }
+               jffs2_free_xattr_ref(ref);
+       }
+       ic->xref = NULL;
+       up_write(&c->xattr_sem);
+}
+
+static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+{
+       /* success of check_xattr_ref_inode() means taht inode (ic) dose not have
+        * duplicate name/value pairs. If duplicate name/value pair would be found,
+        * one will be removed.
+        */
+       struct jffs2_xattr_ref *ref, *cmp, **pref;
+       int rc = 0;
+
+       if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
+               return 0;
+       down_write(&c->xattr_sem);
+ retry:
+       rc = 0;
+       for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+               if (!ref->xd->xname) {
+                       rc = load_xattr_datum(c, ref->xd);
+                       if (unlikely(rc > 0)) {
+                               *pref = ref->next;
+                               delete_xattr_ref(c, ref);
+                               goto retry;
+                       } else if (unlikely(rc < 0))
+                               goto out;
+               }
+               for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) {
+                       if (!cmp->xd->xname) {
+                               ref->xd->flags |= JFFS2_XFLAGS_BIND;
+                               rc = load_xattr_datum(c, cmp->xd);
+                               ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
+                               if (unlikely(rc > 0)) {
+                                       *pref = cmp->next;
+                                       delete_xattr_ref(c, cmp);
+                                       goto retry;
+                               } else if (unlikely(rc < 0))
+                                       goto out;
+                       }
+                       if (ref->xd->xprefix == cmp->xd->xprefix
+                           && !strcmp(ref->xd->xname, cmp->xd->xname)) {
+                               *pref = cmp->next;
+                               delete_xattr_ref(c, cmp);
+                               goto retry;
+                       }
+               }
+       }
+       ic->flags |= INO_FLAGS_XATTR_CHECKED;
+ out:
+       up_write(&c->xattr_sem);
+
+       return rc;
+}
+
+/* -------- xattr subsystem functions ---------------
+ * jffs2_init_xattr_subsystem(c)
+ *   is used to initialize semaphore and list_head, and some variables.
+ * jffs2_find_xattr_datum(c, xid)
+ *   is used to lookup xdatum while scanning process.
+ * jffs2_clear_xattr_subsystem(c)
+ *   is used to release any xattr related objects.
+ * jffs2_build_xattr_subsystem(c)
+ *   is used to associate xdatum and xref while super block building process.
+ * jffs2_setup_xattr_datum(c, xid, version)
+ *   is used to insert xdatum while scanning process.
+ * -------------------------------------------------- */
+void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
+{
+       int i;
+
+       for (i=0; i < XATTRINDEX_HASHSIZE; i++)
+               INIT_LIST_HEAD(&c->xattrindex[i]);
+       INIT_LIST_HEAD(&c->xattr_unchecked);
+       c->xref_temp = NULL;
+
+       init_rwsem(&c->xattr_sem);
+       c->xdatum_mem_usage = 0;
+       c->xdatum_mem_threshold = 32 * 1024;    /* Default 32KB */
+}
+
+static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid)
+{
+       struct jffs2_xattr_datum *xd;
+       int i = xid % XATTRINDEX_HASHSIZE;
+
+       /* It's only used in scanning/building process. */
+       BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING)));
+
+       list_for_each_entry(xd, &c->xattrindex[i], xindex) {
+               if (xd->xid==xid)
+                       return xd;
+       }
+       return NULL;
+}
+
+void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
+{
+       struct jffs2_xattr_datum *xd, *_xd;
+       struct jffs2_xattr_ref *ref, *_ref;
+       int i;
+
+       for (ref=c->xref_temp; ref; ref = _ref) {
+               _ref = ref->next;
+               jffs2_free_xattr_ref(ref);
+       }
+       c->xref_temp = NULL;
+
+       for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
+               list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
+                       list_del(&xd->xindex);
+                       if (xd->xname)
+                               kfree(xd->xname);
+                       jffs2_free_xattr_datum(xd);
+               }
+       }
+}
+
+void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
+{
+       struct jffs2_xattr_ref *ref, *_ref;
+       struct jffs2_xattr_datum *xd, *_xd;
+       struct jffs2_inode_cache *ic;
+       int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0;
+
+       BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
+
+       /* Phase.1 */
+       for (ref=c->xref_temp; ref; ref=_ref) {
+               _ref = ref->next;
+               /* checking REF_UNCHECKED nodes */
+               if (ref_flags(ref->node) != REF_PRISTINE) {
+                       if (verify_xattr_ref(c, ref)) {
+                               delete_xattr_ref_node(c, ref);
+                               jffs2_free_xattr_ref(ref);
+                               continue;
+                       }
+               }
+               /* At this point, ref->xid and ref->ino contain XID and inode number.
+                  ref->xd and ref->ic are not valid yet. */
+               xd = jffs2_find_xattr_datum(c, ref->xid);
+               ic = jffs2_get_ino_cache(c, ref->ino);
+               if (!xd || !ic) {
+                       if (ref_flags(ref->node) != REF_UNCHECKED)
+                               JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n",
+                                             ref->ino, ref->xid);
+                       delete_xattr_ref_node(c, ref);
+                       jffs2_free_xattr_ref(ref);
+                       continue;
+               }
+               ref->xd = xd;
+               ref->ic = ic;
+               xd->refcnt++;
+               ref->next = ic->xref;
+               ic->xref = ref;
+               xref_count++;
+       }
+       c->xref_temp = NULL;
+       /* After this, ref->xid/ino are NEVER used. */
+
+       /* Phase.2 */
+       for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
+               list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
+                       list_del_init(&xd->xindex);
+                       if (!xd->refcnt) {
+                               if (ref_flags(xd->node) != REF_UNCHECKED)
+                                       JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n",
+                                                     xd->xid, xd->version, ref_offset(xd->node));
+                               delete_xattr_datum(c, xd);
+                               continue;
+                       }
+                       if (ref_flags(xd->node) != REF_PRISTINE) {
+                               dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n",
+                                         xd->xid, ref_offset(xd->node));
+                               list_add(&xd->xindex, &c->xattr_unchecked);
+                               xdatum_unchecked_count++;
+                       }
+                       xdatum_count++;
+               }
+       }
+       /* build complete */
+       JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and "
+                    "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count);
+}
+
+struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
+                                                 uint32_t xid, uint32_t version)
+{
+       struct jffs2_xattr_datum *xd, *_xd;
+
+       _xd = jffs2_find_xattr_datum(c, xid);
+       if (_xd) {
+               dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n",
+                         xid, version, _xd->version, ref_offset(_xd->node));
+               if (version < _xd->version)
+                       return ERR_PTR(-EEXIST);
+       }
+       xd = jffs2_alloc_xattr_datum();
+       if (!xd)
+               return ERR_PTR(-ENOMEM);
+       xd->xid = xid;
+       xd->version = version;
+       if (xd->xid > c->highest_xid)
+               c->highest_xid = xd->xid;
+       list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
+
+       if (_xd) {
+               list_del_init(&_xd->xindex);
+               delete_xattr_datum_node(c, _xd);
+               jffs2_free_xattr_datum(_xd);
+       }
+       return xd;
+}
+
+/* -------- xattr subsystem functions ---------------
+ * xprefix_to_handler(xprefix)
+ *   is used to translate xprefix into xattr_handler.
+ * jffs2_listxattr(dentry, buffer, size)
+ *   is an implementation of listxattr handler on jffs2.
+ * do_jffs2_getxattr(inode, xprefix, xname, buffer, size)
+ *   is an implementation of getxattr handler on jffs2.
+ * do_jffs2_setxattr(inode, xprefix, xname, buffer, size, flags)
+ *   is an implementation of setxattr handler on jffs2.
+ * -------------------------------------------------- */
+struct xattr_handler *jffs2_xattr_handlers[] = {
+       &jffs2_user_xattr_handler,
+#ifdef CONFIG_JFFS2_FS_SECURITY
+       &jffs2_security_xattr_handler,
+#endif
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+       &jffs2_acl_access_xattr_handler,
+       &jffs2_acl_default_xattr_handler,
+#endif
+       &jffs2_trusted_xattr_handler,
+       NULL
+};
+
+static struct xattr_handler *xprefix_to_handler(int xprefix) {
+       struct xattr_handler *ret;
+
+       switch (xprefix) {
+       case JFFS2_XPREFIX_USER:
+               ret = &jffs2_user_xattr_handler;
+               break;
+#ifdef CONFIG_JFFS2_FS_SECURITY
+       case JFFS2_XPREFIX_SECURITY:
+               ret = &jffs2_security_xattr_handler;
+               break;
+#endif
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+       case JFFS2_XPREFIX_ACL_ACCESS:
+               ret = &jffs2_acl_access_xattr_handler;
+               break;
+       case JFFS2_XPREFIX_ACL_DEFAULT:
+               ret = &jffs2_acl_default_xattr_handler;
+               break;
+#endif
+       case JFFS2_XPREFIX_TRUSTED:
+               ret = &jffs2_trusted_xattr_handler;
+               break;
+       default:
+               ret = NULL;
+               break;
+       }
+       return ret;
+}
+
+ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+       struct inode *inode = dentry->d_inode;
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       struct jffs2_inode_cache *ic = f->inocache;
+       struct jffs2_xattr_ref *ref, **pref;
+       struct jffs2_xattr_datum *xd;
+       struct xattr_handler *xhandle;
+       ssize_t len, rc;
+       int retry = 0;
+
+       rc = check_xattr_ref_inode(c, ic);
+       if (unlikely(rc))
+               return rc;
+
+       down_read(&c->xattr_sem);
+ retry:
+       len = 0;
+       for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+               BUG_ON(ref->ic != ic);
+               xd = ref->xd;
+               if (!xd->xname) {
+                       /* xdatum is unchached */
+                       if (!retry) {
+                               retry = 1;
+                               up_read(&c->xattr_sem);
+                               down_write(&c->xattr_sem);
+                               goto retry;
+                       } else {
+                               rc = load_xattr_datum(c, xd);
+                               if (unlikely(rc > 0)) {
+                                       *pref = ref->next;
+                                       delete_xattr_ref(c, ref);
+                                       goto retry;
+                               } else if (unlikely(rc < 0))
+                                       goto out;
+                       }
+               }
+               xhandle = xprefix_to_handler(xd->xprefix);
+               if (!xhandle)
+                       continue;
+               if (buffer) {
+                       rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len);
+               } else {
+                       rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len);
+               }
+               if (rc < 0)
+                       goto out;
+               len += rc;
+       }
+       rc = len;
+ out:
+       if (!retry) {
+               up_read(&c->xattr_sem);
+       } else {
+               up_write(&c->xattr_sem);
+       }
+       return rc;
+}
+
+int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
+                     char *buffer, size_t size)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       struct jffs2_inode_cache *ic = f->inocache;
+       struct jffs2_xattr_datum *xd;
+       struct jffs2_xattr_ref *ref, **pref;
+       int rc, retry = 0;
+
+       rc = check_xattr_ref_inode(c, ic);
+       if (unlikely(rc))
+               return rc;
+
+       down_read(&c->xattr_sem);
+ retry:
+       for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+               BUG_ON(ref->ic!=ic);
+
+               xd = ref->xd;
+               if (xd->xprefix != xprefix)
+                       continue;
+               if (!xd->xname) {
+                       /* xdatum is unchached */
+                       if (!retry) {
+                               retry = 1;
+                               up_read(&c->xattr_sem);
+                               down_write(&c->xattr_sem);
+                               goto retry;
+                       } else {
+                               rc = load_xattr_datum(c, xd);
+                               if (unlikely(rc > 0)) {
+                                       *pref = ref->next;
+                                       delete_xattr_ref(c, ref);
+                                       goto retry;
+                               } else if (unlikely(rc < 0)) {
+                                       goto out;
+                               }
+                       }
+               }
+               if (!strcmp(xname, xd->xname)) {
+                       rc = xd->value_len;
+                       if (buffer) {
+                               if (size < rc) {
+                                       rc = -ERANGE;
+                               } else {
+                                       memcpy(buffer, xd->xvalue, rc);
+                               }
+                       }
+                       goto out;
+               }
+       }
+       rc = -ENODATA;
+ out:
+       if (!retry) {
+               up_read(&c->xattr_sem);
+       } else {
+               up_write(&c->xattr_sem);
+       }
+       return rc;
+}
+
+int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
+                     const char *buffer, size_t size, int flags)
+{
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       struct jffs2_inode_cache *ic = f->inocache;
+       struct jffs2_xattr_datum *xd;
+       struct jffs2_xattr_ref *ref, *newref, **pref;
+       uint32_t length, request;
+       int rc;
+
+       rc = check_xattr_ref_inode(c, ic);
+       if (unlikely(rc))
+               return rc;
+
+       request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size);
+       rc = jffs2_reserve_space(c, request, &length,
+                                ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE);
+       if (rc) {
+               JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
+               return rc;
+       }
+
+       /* Find existing xattr */
+       down_write(&c->xattr_sem);
+ retry:
+       for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+               xd = ref->xd;
+               if (xd->xprefix != xprefix)
+                       continue;
+               if (!xd->xname) {
+                       rc = load_xattr_datum(c, xd);
+                       if (unlikely(rc > 0)) {
+                               *pref = ref->next;
+                               delete_xattr_ref(c, ref);
+                               goto retry;
+                       } else if (unlikely(rc < 0))
+                               goto out;
+               }
+               if (!strcmp(xd->xname, xname)) {
+                       if (flags & XATTR_CREATE) {
+                               rc = -EEXIST;
+                               goto out;
+                       }
+                       if (!buffer) {
+                               *pref = ref->next;
+                               delete_xattr_ref(c, ref);
+                               rc = 0;
+                               goto out;
+                       }
+                       goto found;
+               }
+       }
+       /* not found */
+       if (flags & XATTR_REPLACE) {
+               rc = -ENODATA;
+               goto out;
+       }
+       if (!buffer) {
+               rc = -EINVAL;
+               goto out;
+       }
+ found:
+       xd = create_xattr_datum(c, xprefix, xname, buffer, size);
+       if (IS_ERR(xd)) {
+               rc = PTR_ERR(xd);
+               goto out;
+       }
+       up_write(&c->xattr_sem);
+       jffs2_complete_reservation(c);
+
+       /* create xattr_ref */
+       request = PAD(sizeof(struct jffs2_raw_xref));
+       rc = jffs2_reserve_space(c, request, &length,
+                                ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
+       if (rc) {
+               JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
+               down_write(&c->xattr_sem);
+               xd->refcnt--;
+               if (!xd->refcnt)
+                       delete_xattr_datum(c, xd);
+               up_write(&c->xattr_sem);
+               return rc;
+       }
+       down_write(&c->xattr_sem);
+       if (ref)
+               *pref = ref->next;
+       newref = create_xattr_ref(c, ic, xd);
+       if (IS_ERR(newref)) {
+               if (ref) {
+                       ref->next = ic->xref;
+                       ic->xref = ref;
+               }
+               rc = PTR_ERR(newref);
+               xd->refcnt--;
+               if (!xd->refcnt)
+                       delete_xattr_datum(c, xd);
+       } else if (ref) {
+               delete_xattr_ref(c, ref);
+       }
+ out:
+       up_write(&c->xattr_sem);
+       jffs2_complete_reservation(c);
+       return rc;
+}
+
+/* -------- garbage collector functions -------------
+ * jffs2_garbage_collect_xattr_datum(c, xd)
+ *   is used to move xdatum into new node.
+ * jffs2_garbage_collect_xattr_ref(c, ref)
+ *   is used to move xref into new node.
+ * jffs2_verify_xattr(c)
+ *   is used to call do_verify_xattr_datum() before garbage collecting.
+ * -------------------------------------------------- */
+int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+       uint32_t totlen, length, old_ofs;
+       int rc = -EINVAL;
+
+       down_write(&c->xattr_sem);
+       BUG_ON(!xd->node);
+
+       old_ofs = ref_offset(xd->node);
+       totlen = ref_totlen(c, c->gcblock, xd->node);
+       if (totlen < sizeof(struct jffs2_raw_xattr))
+               goto out;
+
+       if (!xd->xname) {
+               rc = load_xattr_datum(c, xd);
+               if (unlikely(rc > 0)) {
+                       delete_xattr_datum_node(c, xd);
+                       rc = 0;
+                       goto out;
+               } else if (unlikely(rc < 0))
+                       goto out;
+       }
+       rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
+       if (rc || length < totlen) {
+               JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen);
+               rc = rc ? rc : -EBADFD;
+               goto out;
+       }
+       rc = save_xattr_datum(c, xd);
+       if (!rc)
+               dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",
+                         xd->xid, xd->version, old_ofs, ref_offset(xd->node));
+ out:
+       up_write(&c->xattr_sem);
+       return rc;
+}
+
+
+int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+       uint32_t totlen, length, old_ofs;
+       int rc = -EINVAL;
+
+       down_write(&c->xattr_sem);
+       BUG_ON(!ref->node);
+
+       old_ofs = ref_offset(ref->node);
+       totlen = ref_totlen(c, c->gcblock, ref->node);
+       if (totlen != sizeof(struct jffs2_raw_xref))
+               goto out;
+
+       rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
+       if (rc || length < totlen) {
+               JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n",
+                             __FUNCTION__, rc, totlen);
+               rc = rc ? rc : -EBADFD;
+               goto out;
+       }
+       rc = save_xattr_ref(c, ref);
+       if (!rc)
+               dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",
+                         ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
+ out:
+       up_write(&c->xattr_sem);
+       return rc;
+}
+
+int jffs2_verify_xattr(struct jffs2_sb_info *c)
+{
+       struct jffs2_xattr_datum *xd, *_xd;
+       int rc;
+
+       down_write(&c->xattr_sem);
+       list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
+               rc = do_verify_xattr_datum(c, xd);
+               if (rc == 0) {
+                       list_del_init(&xd->xindex);
+                       break;
+               } else if (rc > 0) {
+                       list_del_init(&xd->xindex);
+                       delete_xattr_datum_node(c, xd);
+               }
+       }
+       up_write(&c->xattr_sem);
+
+       return list_empty(&c->xattr_unchecked) ? 1 : 0;
+}
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
new file mode 100644 (file)
index 0000000..2c19985
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#ifndef _JFFS2_FS_XATTR_H_
+#define _JFFS2_FS_XATTR_H_
+
+#include <linux/xattr.h>
+#include <linux/list.h>
+
+#define JFFS2_XFLAGS_HOT       (0x01)  /* This datum is HOT */
+#define JFFS2_XFLAGS_BIND      (0x02)  /* This datum is not reclaimed */
+
+struct jffs2_xattr_datum
+{
+       void *always_null;
+       struct jffs2_raw_node_ref *node;
+       uint8_t class;
+       uint8_t flags;
+       uint16_t xprefix;                       /* see JFFS2_XATTR_PREFIX_* */
+
+       struct list_head xindex;        /* chained from c->xattrindex[n] */
+       uint32_t refcnt;                /* # of xattr_ref refers this */
+       uint32_t xid;
+       uint32_t version;
+
+       uint32_t data_crc;
+       uint32_t hashkey;
+       char *xname;            /* XATTR name without prefix */
+       uint32_t name_len;      /* length of xname */
+       char *xvalue;           /* XATTR value */
+       uint32_t value_len;     /* length of xvalue */
+};
+
+struct jffs2_inode_cache;
+struct jffs2_xattr_ref
+{
+       void *always_null;
+       struct jffs2_raw_node_ref *node;
+       uint8_t class;
+       uint8_t flags;          /* Currently unused */
+       u16 unused;
+
+       union {
+               struct jffs2_inode_cache *ic;   /* reference to jffs2_inode_cache */
+               uint32_t ino;                   /* only used in scanning/building  */
+       };
+       union {
+               struct jffs2_xattr_datum *xd;   /* reference to jffs2_xattr_datum */
+               uint32_t xid;                   /* only used in sccanning/building */
+       };
+       struct jffs2_xattr_ref *next;           /* chained from ic->xref_list */
+};
+
+#ifdef CONFIG_JFFS2_FS_XATTR
+
+extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
+extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c);
+extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
+
+extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
+                                                  uint32_t xid, uint32_t version);
+
+extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
+extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
+
+extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
+extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
+extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
+
+extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
+                            char *buffer, size_t size);
+extern int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
+                            const char *buffer, size_t size, int flags);
+
+extern struct xattr_handler *jffs2_xattr_handlers[];
+extern struct xattr_handler jffs2_user_xattr_handler;
+extern struct xattr_handler jffs2_trusted_xattr_handler;
+
+extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
+#define jffs2_getxattr         generic_getxattr
+#define jffs2_setxattr         generic_setxattr
+#define jffs2_removexattr      generic_removexattr
+
+#else
+
+#define jffs2_init_xattr_subsystem(c)
+#define jffs2_build_xattr_subsystem(c)
+#define jffs2_clear_xattr_subsystem(c)
+
+#define jffs2_xattr_delete_inode(c, ic)
+#define jffs2_xattr_free_inode(c, ic)
+#define jffs2_verify_xattr(c)                  (1)
+
+#define jffs2_xattr_handlers   NULL
+#define jffs2_listxattr                NULL
+#define jffs2_getxattr         NULL
+#define jffs2_setxattr         NULL
+#define jffs2_removexattr      NULL
+
+#endif /* CONFIG_JFFS2_FS_XATTR */
+
+#ifdef CONFIG_JFFS2_FS_SECURITY
+extern int jffs2_init_security(struct inode *inode, struct inode *dir);
+extern struct xattr_handler jffs2_security_xattr_handler;
+#else
+#define jffs2_init_security(inode,dir) (0)
+#endif /* CONFIG_JFFS2_FS_SECURITY */
+
+#endif /* _JFFS2_FS_XATTR_H_ */
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
new file mode 100644 (file)
index 0000000..ed046e1
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+
+static int jffs2_trusted_getxattr(struct inode *inode, const char *name,
+                                 void *buffer, size_t size)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+       return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size);
+}
+
+static int jffs2_trusted_setxattr(struct inode *inode, const char *name, const void *buffer,
+                                 size_t size, int flags)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+       return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags);
+}
+
+static size_t jffs2_trusted_listxattr(struct inode *inode, char *list, size_t list_size,
+                                     const char *name, size_t name_len)
+{
+       size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
+
+       if (list && retlen<=list_size) {
+               strcpy(list, XATTR_TRUSTED_PREFIX);
+               strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name);
+       }
+
+       return retlen;
+}
+
+struct xattr_handler jffs2_trusted_xattr_handler = {
+       .prefix = XATTR_TRUSTED_PREFIX,
+       .list = jffs2_trusted_listxattr,
+       .set = jffs2_trusted_setxattr,
+       .get = jffs2_trusted_getxattr
+};
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
new file mode 100644 (file)
index 0000000..2f8e9aa
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+
+static int jffs2_user_getxattr(struct inode *inode, const char *name,
+                               void *buffer, size_t size)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+       return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size);
+}
+
+static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
+                               size_t size, int flags)
+{
+       if (!strcmp(name, ""))
+               return -EINVAL;
+       return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size, flags);
+}
+
+static size_t jffs2_user_listxattr(struct inode *inode, char *list, size_t list_size,
+                                  const char *name, size_t name_len)
+{
+       size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
+
+       if (list && retlen <= list_size) {
+               strcpy(list, XATTR_USER_PREFIX);
+               strcpy(list + XATTR_USER_PREFIX_LEN, name);
+       }
+
+       return retlen;
+}
+
+struct xattr_handler jffs2_user_xattr_handler = {
+       .prefix = XATTR_USER_PREFIX,
+       .list = jffs2_user_listxattr,
+       .set = jffs2_user_setxattr,
+       .get = jffs2_user_getxattr
+};
index 6f99c0a6f83629fbaa3eaaaf853fb6b7b9a9cfcc..ab61a8b548292c025c86a4ba87db4dcab08015d8 100644 (file)
@@ -755,6 +755,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
        if (request->fl_type == F_UNLCK)
                goto out;
 
+       error = -ENOMEM;
        new_fl = locks_alloc_lock();
        if (new_fl == NULL)
                goto out;
@@ -781,6 +782,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
        locks_copy_lock(new_fl, request);
        locks_insert_lock(&inode->i_flock, new_fl);
        new_fl = NULL;
+       error = 0;
 
 out:
        unlock_kernel();
index 96723ae83c89d5283b335320b7b4315145a02d6b..184fe4acf82449dae1c62eade2d4489b078f24aa 100644 (file)
@@ -1080,8 +1080,8 @@ static int fastcall do_path_lookup(int dfd, const char *name,
        nd->flags = flags;
        nd->depth = 0;
 
-       read_lock(&current->fs->lock);
        if (*name=='/') {
+               read_lock(&current->fs->lock);
                if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
                        nd->mnt = mntget(current->fs->altrootmnt);
                        nd->dentry = dget(current->fs->altroot);
@@ -1092,48 +1092,49 @@ static int fastcall do_path_lookup(int dfd, const char *name,
                }
                nd->mnt = mntget(current->fs->rootmnt);
                nd->dentry = dget(current->fs->root);
+               read_unlock(&current->fs->lock);
        } else if (dfd == AT_FDCWD) {
+               read_lock(&current->fs->lock);
                nd->mnt = mntget(current->fs->pwdmnt);
                nd->dentry = dget(current->fs->pwd);
+               read_unlock(&current->fs->lock);
        } else {
                struct dentry *dentry;
 
                file = fget_light(dfd, &fput_needed);
                retval = -EBADF;
                if (!file)
-                       goto unlock_fail;
+                       goto out_fail;
 
                dentry = file->f_dentry;
 
                retval = -ENOTDIR;
                if (!S_ISDIR(dentry->d_inode->i_mode))
-                       goto fput_unlock_fail;
+                       goto fput_fail;
 
                retval = file_permission(file, MAY_EXEC);
                if (retval)
-                       goto fput_unlock_fail;
+                       goto fput_fail;
 
                nd->mnt = mntget(file->f_vfsmnt);
                nd->dentry = dget(dentry);
 
                fput_light(file, fput_needed);
        }
-       read_unlock(&current->fs->lock);
        current->total_link_count = 0;
        retval = link_path_walk(name, nd);
 out:
        if (likely(retval == 0)) {
                if (unlikely(current->audit_context && nd && nd->dentry &&
                                nd->dentry->d_inode))
-               audit_inode(name, nd->dentry->d_inode, flags);
+               audit_inode(name, nd->dentry->d_inode);
        }
+out_fail:
        return retval;
 
-fput_unlock_fail:
+fput_fail:
        fput_light(file, fput_needed);
-unlock_fail:
-       read_unlock(&current->fs->lock);
-       return retval;
+       goto out_fail;
 }
 
 int fastcall path_lookup(const char *name, unsigned int flags,
index 317b7c7f38a73aac8cc8f3edc463919dabb2f947..4f178acd4c09ccfb35a2cac2dfebd42a17081604 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -633,7 +633,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
        dentry = file->f_dentry;
        inode = dentry->d_inode;
 
-       audit_inode(NULL, inode, 0);
+       audit_inode(NULL, inode);
 
        err = -EROFS;
        if (IS_RDONLY(inode))
@@ -786,7 +786,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
        if (file) {
                struct dentry * dentry;
                dentry = file->f_dentry;
-               audit_inode(NULL, dentry->d_inode, 0);
+               audit_inode(NULL, dentry->d_inode);
                error = chown_common(dentry, user, group);
                fput(file);
        }
index 6cc77dc3f3ff79c49fa7d4ce89360b595995d839..6afff725a8c922b08bb3b6bbd52bf044ecc42e6c 100644 (file)
@@ -1019,8 +1019,8 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
        if (current != task)
                return -EPERM;
 
-       if (count > PAGE_SIZE)
-               count = PAGE_SIZE;
+       if (count >= PAGE_SIZE)
+               count = PAGE_SIZE - 1;
 
        if (*ppos != 0) {
                /* No partial writes. */
@@ -1033,6 +1033,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
        if (copy_from_user(page, buf, count))
                goto out_free_page;
 
+       page[count] = '\0';
        loginuid = simple_strtoul(page, &tmp, 10);
        if (tmp == page) {
                length = -EINVAL;
index e416190f5e9cda02c34577ae57f2fa88e58945e7..c32f15b5f60fd29d69ec8f4aa7a4f3eec0501fd6 100644 (file)
@@ -242,7 +242,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
        if (!f)
                return error;
        dentry = f->f_dentry;
-       audit_inode(NULL, dentry->d_inode, 0);
+       audit_inode(NULL, dentry->d_inode);
        error = setxattr(dentry, name, value, size, flags);
        fput(f);
        return error;
@@ -469,7 +469,7 @@ sys_fremovexattr(int fd, char __user *name)
        if (!f)
                return error;
        dentry = f->f_dentry;
-       audit_inode(NULL, dentry->d_inode, 0);
+       audit_inode(NULL, dentry->d_inode);
        error = removexattr(dentry, name);
        fput(f);
        return error;
index 2e6d54569ee8adcd7296737a8264ca35b9f3a13d..3c6a6205853aab3701c9b81ff7947e831b9e7c6b 100644 (file)
@@ -49,7 +49,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/ctype.h>
index badf0277b1be7314a59f9b6a8c7836e25b14c314..ef7d83a414709742880ce23c36af67dcf4c29a39 100644 (file)
@@ -2,7 +2,6 @@
 #define __ACPI_PROCESSOR_H
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 
 #include <asm/acpi.h>
 
index 3f88715e811eaa10e5f9c4395131fa22f6f6545f..4b6ef7f21b9396e779e3cb86400d578ad3590e9e 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_BITOPS_H
 #define _ALPHA_BITOPS_H
 
-#include <linux/config.h>
 #include <asm/compiler.h>
 
 /*
index e6d4d1695e256cdccce5a74d1b87edc8e99b8542..f199e69a5d0b0a83fd39e7d5464a5fa439c79265 100644 (file)
@@ -4,7 +4,6 @@
 #ifndef __ARCH_ALPHA_CACHE_H
 #define __ARCH_ALPHA_CACHE_H
 
-#include <linux/config.h>
 
 /* Bytes per L1 (data) cache line. */
 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EV6)
index 3fc6ef726d8c280a84136688f404a5561eda5dd4..805640b4107815330274fd5699d9531fcb6aa5a0 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_CACHEFLUSH_H
 #define _ALPHA_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 /* Caches aren't brain-dead on the Alpha. */
index 3a70d68bfce83f9d6e1ac87653a8eba8cc15189e..9e0516c0ca27b33895082d7ecec6e06a1db72943 100644 (file)
@@ -4,7 +4,6 @@
 /* Define to experiment with fitting everything into one 512MB HAE window.  */
 #define CIA_ONE_HAE_WINDOW 1
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/compiler.h>
 
index 5c1c40338c82a1180478af35aac2df995e98231a..dba70c62a16c0d3a56df6ffebd917983d0367f3b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ALPHA_T2__H__
 #define __ALPHA_T2__H__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/compiler.h>
index 62d0d6681aa91d587e52b5de824e90a790de9f2f..b9ff4d8cb33a95dd5c50db2d77c88a110c415d70 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_DMA_MAPPING_H
 #define _ALPHA_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 
index 683afaa3deedceb725556b3467c776ac44f3e8c1..87cfdbdf08fc8e278f4d12386456c31cf900acf7 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
 
index 289a00d51a907e8bfa03afb34ef705a39a8e62e3..e177d4180f83610d92ab5be68853eb3516896dfc 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __ASM_ALPHA_FLOPPY_H
 #define __ASM_ALPHA_FLOPPY_H
 
-#include <linux/config.h>
 
 #define fd_inb(port)                   inb_p(port)
 #define fd_outb(value,port)            outb_p(value,port)
index 7bb6a36c96a17aecdbe474ba300aaaae72cd1c0f..d953e234daa8ff694ced89b3af4f24f155b3b058 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_HARDIRQ_H
 #define _ALPHA_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cache.h>
 
index a310b9efc906993e2091ddec797818f8b3a229df..ca9d43b6350276b1bf07e675907033b52690a9e8 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_HW_IRQ_H
 #define _ALPHA_HW_IRQ_H
 
-#include <linux/config.h>
 
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {}
 
index 6126afe2738078558e54b8c2f0815294e0b8eb80..2a5cc0b367ab4c36dfa79839248c662fa75f7aec 100644 (file)
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #define IDE_ARCH_OBSOLETE_DEFAULTS
 
index 3ebbeee753e9c80e8410933087f08d45915e6e3d..f5ae98c25d1f4f0f4fb2627b8916ec1648ce20fd 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/compiler.h>
 #include <asm/system.h>
index 566db720000a2a55cb8fef9a7ce93cbfd98ced93..f6de033718a0f3f60cf177fb0ce7b731235f2e2c 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include <linux/linkage.h>
-#include <linux/config.h>
 
 #if   defined(CONFIG_ALPHA_GENERIC)
 
index 3d10cd3ea75fe1d9f5bc7640a5f5de5355fde506..3e6735a34c571b011172cf54ee3e09db254434da 100644 (file)
@@ -3,7 +3,6 @@
 
 /* Dummy header just to define km_type. */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
index ece166a203ecb82dac18cc3769cc1e3421379526..aced22f91752e454ae446c2d8ac3014de49dee41 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ALPHA_MACHVEC_H
 #define __ALPHA_MACHVEC_H 1
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /*
index 0c017fc181c1d7eb724605006107b88fb2f185e5..fe249e9d3360041a31f4399358f9d2c13253b9d5 100644 (file)
@@ -7,7 +7,6 @@
  * Copyright (C) 1996, Linus Torvalds
  */
 
-#include <linux/config.h>
 #include <asm/system.h>
 #include <asm/machvec.h>
 #include <asm/compiler.h>
index 192d80c875b06479ff4670693914b9e591600c5c..64d0ab98fcd8da6e7bd1765c8572512fb02e9e7d 100644 (file)
@@ -5,7 +5,6 @@
 #ifndef _ASM_MMZONE_H_
 #define _ASM_MMZONE_H_
 
-#include <linux/config.h>
 #include <asm/smp.h>
 
 struct bootmem_data_t; /* stupid forward decl. */
index 61bcf70b5eac66852a19e47fe61fb07c07b1a953..8c7cd50d4eae01639ca85b35644d817ce2696466 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_PAGE_H
 #define _ALPHA_PAGE_H
 
-#include <linux/config.h>
 #include <asm/pal.h>
 
 /* PAGE_SHIFT determines the page size */
index 3ed0b3b02e52c5a2b739af40c00be241fc73c4e1..214e7996346f25e890c9221c35fac975f4e7ee78 100644 (file)
@@ -5,7 +5,6 @@
    hardware ignores reprogramming.  We also need userland buy-in to the 
    change in HZ, since this is visible in the wait4 resources etc.  */
 
-#include <linux/config.h>
 
 #ifndef HZ
 # ifndef CONFIG_ALPHA_RAWHIDE
index 3084756429139872b56603dda87d02ff6ca6f73a..471864e8d4c370d17d3ff5a672c95cc71444087a 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_PGALLOC_H
 #define _ALPHA_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/mmzone.h>
 
index a985cd29b6db2f5dc013d7313cf92b4f40c7b7e2..93eaa58b7961bdfd83b12f2db4d467b174886990 100644 (file)
@@ -10,7 +10,6 @@
  * This hopefully works with any standard Alpha page-size, as defined
  * in <asm/page.h> (currently 8192).
  */
-#include <linux/config.h>
 #include <linux/mmzone.h>
 
 #include <asm/page.h>
index 7e4b2987d453dfc3de77184cb7306be68a94010a..9d263e8d8ccc19d9feef762f4be58cc70206ecd1 100644 (file)
@@ -2,7 +2,6 @@
  * include/asm-alpha/serial.h
  */
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
index 9950706abdf8289f0d2815dd45102aa787016038..a1a1eca6be45b0e3ebe72d9d236071719ba979d9 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/bitops.h>
@@ -45,10 +44,8 @@ extern struct cpuinfo_alpha cpu_data[NR_CPUS];
 #define hard_smp_processor_id()        __hard_smp_processor_id()
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
-extern cpumask_t cpu_present_mask;
-extern cpumask_t cpu_online_map;
 extern int smp_num_cpus;
-#define cpu_possible_map       cpu_present_mask
+#define cpu_possible_map       cpu_present_map
 
 int smp_call_function_on_cpu(void (*func) (void *info), void *info,int retry, int wait, cpumask_t cpu);
 
index 8197c69eff44cdbebed4823db0bfdf0c1a2428fd..0c294c9b0c558a8a45f080b8e0b825fadbdf859f 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_SPINLOCK_H
 #define _ALPHA_SPINLOCK_H
 
-#include <linux/config.h>
 #include <asm/system.h>
 #include <linux/kernel.h>
 #include <asm/current.h>
index f3b7b1a59c568d6950f7432ac467b361b2a02eaf..03e9c0e5ed7451d99161959d0d6f716e6789984c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ALPHA_SYSTEM_H
 #define __ALPHA_SYSTEM_H
 
-#include <linux/config.h>
 #include <asm/pal.h>
 #include <asm/page.h>
 #include <asm/barrier.h>
index f4837fa29420428a5b4c70c7b360b467bd49fae0..5541101b58aef8c962ebc416539daefe12cc3fd8 100644 (file)
@@ -148,6 +148,7 @@ struct termios {
 #define HUPCL  00040000
 
 #define CLOCAL 00100000
+#define CMSPAR   010000000000          /* mark or space (stick) parity */
 #define CRTSCTS          020000000000          /* flow control */
 
 /* c_lflag bits */
index 9d484c1fdc823052254efdcd82a1160c2e18b10b..1ca3ed3bd6d38f1c2461e5d83980758affeac76e 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_TLBFLUSH_H
 #define _ALPHA_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/compiler.h>
 
index ef25b65851194e98fb8fccdbaf8999cb4e9af805..bc6e6a9259dceae583af27b0c5bda3b33f21d323 100644 (file)
 #define __NR_inotify_add_watch         445
 #define __NR_inotify_rm_watch          446
 
+#ifdef __KERNEL__
+
 #define NR_SYSCALLS                    447
 
 #if defined(__GNUC__)
@@ -565,9 +567,8 @@ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6)\
        _syscall_return(type);                                          \
 }
 
-#endif /* __LIBRARY__ && __GNUC__ */
+#endif /* __GNUC__ */
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
@@ -578,7 +579,6 @@ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, type6 arg6)\
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -661,4 +661,5 @@ asmlinkage long sys_rt_sigaction(int sig,
 
 #define cond_syscall(x)  asm(".weak\t" #x "\n" #x " = sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ALPHA_UNISTD_H */
index 3a50eb759c2830b9b1339c52832ded38ff0f5ec5..d09113b37e4ae28548c653c47f02fb927f3c4def 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef ARM_ASM_SA1100_APM_H
 #define ARM_ASM_SA1100_APM_H
 
-#include <linux/config.h>
 #include <linux/apm_bios.h>
 
 /*
index d8209f8911d6365adfb09fcdb7090c467d6f272c..24b51cccde8f270ce7efe2a70d7481706e6996ed 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <linux/config.h>
 
 #define PHYS_OFFSET    UL(0xf0000000)
 
index 3867231a44700bd7e7457b6cfc0c01b0f83e1d7c..aea6330c97453f624a2c8bd5c2ca4958b603e08a 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 #define acornfb_valid_pixrate(var) (var->pixclock >= 39325 && var->pixclock <= 40119)
 
 static inline void
index 1386871e1a5afa61505ebdf14b3632e11dadbeda..0fdbe72fff2afc7a9f50030fa2d942eb13767c67 100644 (file)
@@ -22,7 +22,6 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <linux/config.h>
 
 #define CLPS7111_VIRT_BASE     0xff000000
 #define CLPS7111_BASE          CLPS7111_VIRT_BASE
index 61d8717406ce276d01694d7b7326e33f02c9d257..c6e8dcf674def5111a990215b9a11b1ea3f94faf 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <linux/config.h>
 
 /*
  * Physical DRAM offset.
index 07157b7e4b202297106421a71b63a860ad3d28ac..03d233ae87ce36e8b931299d59238e154dfd8318 100644 (file)
@@ -17,7 +17,6 @@
  * 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/config.h>
 #include <asm/arch/io.h>
 #include <asm/hardware.h>
 #include <asm/hardware/clps7111.h>
index ec51fe92483b13e12485f7753a6db86b0293b613..daad8ee2d19477313ec778edc5dd79ca507c69ef 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <linux/config.h>
 #include <asm/arch/memory.h>
 
 #ifdef CONFIG_ARCH_FOOTBRIDGE
index 99181ffc7e27977899929aa65eed85501403bb36..cbd7ae64bcc97a217cfe10338f4aabee2ab8c48f 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_FOOTBRIDGE_ADDIN)
 /*
index d1ca955ce4346eead53d0d960585f44e924ab2f1..02598200997d4e8fd4c37e8d347b4026a6aea8eb 100644 (file)
@@ -6,7 +6,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_ARCH_FOOTBRIDGE
 #define VMALLOC_END       (PAGE_OFFSET + 0x30000000)
index da6981efdc394057840030d6503bcd34ecfc446a..ab2c79bb95050cc58e4c9388f3423235c23554d9 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef ASMARM_ARCH_SMP_H
 #define ASMARM_ARCH_SMP_H
 
-#include <linux/config.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
index bc62f4b132359f31e67ba5ecf613745cc7f2d132..e43ebd9847459b18915b5d59c99203161df7f411 100644 (file)
@@ -5,7 +5,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <linux/config.h>
 #include <asm/hardware.h>
 
 /*
index 472badb451c4d6c1652302d9249230666a73f366..14ca8d0f7b29f08649f313b2ab7f206bd4b1ca2a 100644 (file)
@@ -3,7 +3,6 @@
  *
  * IOP3xx architecture timex specifications
  */
-#include <linux/config.h>
 #include <asm/hardware.h>
 
 #if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
index c98eb6254b1f06016638f59db4db6f47a5f7a939..fbdd5af644fe67130fd51c543e3c8056d784f2d3 100644 (file)
@@ -1,7 +1,6 @@
 /*
  *  linux/include/asm-arm/arch-iop3xx/uncompress.h
  */
-#include <linux/config.h>
 #include <asm/types.h>
 #include <asm/mach-types.h>
 #include <linux/serial_reg.h>
index 6e19f46d54d1c2aaf947aca24fdc01c4569390fc..c85fc06a043c10dc00392d72b3ef726aa40eece9 100644 (file)
@@ -49,7 +49,7 @@ static inline int __ixp23xx_arch_is_coherent(void)
 {
        extern unsigned int processor_id;
 
-       if (((processor_id & 15) >= 2) || machine_is_roadrunner())
+       if (((processor_id & 15) >= 4) || machine_is_roadrunner())
                return 1;
 
        return 0;
index b1a071ecebc8a26c3aebd5632228036806c57f88..789f7f53c3578c93e18155fc648a155e2bf34c7f 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-#include <linux/config.h>
 #include <linux/device.h>
 #include <linux/pci.h>
 #include <asm/page.h>
index 238c595d97ea79760d151e453da1869ad99c4dcc..b1008a9d23e5a8aea54870ff13eccb6604370161 100644 (file)
@@ -28,7 +28,7 @@
 #define UARTDR                 0x00    /* Tx/Rx data */
 #define RXSTAT                 0x04    /* Rx status */
 #define H_UBRLCR               0x08    /* mode register high */
-#define M_UBRLCR               0x0C    /* mode reg mid (MSB of buad)*/
+#define M_UBRLCR               0x0C    /* mode reg mid (MSB of baud)*/
 #define L_UBRLCR               0x10    /* mode reg low (LSB of baud)*/
 #define UARTCON                        0x14    /* control register */
 #define UARTFLG                        0x18    /* flag register */
index 9fcd40aee3e3027a929b03e2aa0c24f6e00ebd8d..04be2a088639df302ac0bed781027f6ec2f828c2 100644 (file)
@@ -6,7 +6,7 @@
  * Changelog:
  *  05-01-2000 SJH     Created
  *  05-13-2000 SJH     Filled in function bodies
- *  07-26-2000 SJH     Removed hard coded buad rate
+ *  07-26-2000 SJH     Removed hard coded baud rate
  */
 
 #include <asm/hardware.h>
diff --git a/include/asm-arm/arch-lh7a40x/clocks.h b/include/asm-arm/arch-lh7a40x/clocks.h
new file mode 100644 (file)
index 0000000..bee02fd
--- /dev/null
@@ -0,0 +1,20 @@
+/* include/asm-arm/arch-lh7a40x/clocks.h
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  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/config.h>
+
+#ifndef __ASM_ARCH_CLOCKS_H
+#define __ASM_ARCH_CLOCKS_H
+
+unsigned int fclkfreq_get (void);
+unsigned int hclkfreq_get (void);
+unsigned int pclkfreq_get (void);
+
+#endif  /* _ASM_ARCH_CLOCKS_H */
index 52c1cb9c39c686a117fc44a148fd05602800d9f1..51de96e87faf93753332139f2789be08ec5b4bf0 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_ARCH_CONSTANTS_H
 #define __ASM_ARCH_CONSTANTS_H
 
-#include <linux/config.h>
 
 /* Addressing constants */
 
@@ -29,8 +28,7 @@
 
 #if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
 
-# define IOBARRIER_PHYS                0xc0000000 /* Start of SDRAM */
-/*# define IOBARRIER_PHYS              0x00000000 */ /* Start of flash */
+# define IOBARRIER_PHYS                0x10000000 /* Second bank, fastest timing */
 # define IOBARRIER_VIRT                0xf0000000
 # define IOBARRIER_SIZE                PAGE_SIZE
 
@@ -53,6 +51,9 @@
 # define CPLD08_PHYS           CPLDX_PHYS (0x08)
 # define CPLD08_VIRT           CPLDX_VIRT (0x08)
 # define CPLD08_SIZE           PAGE_SIZE
+# define CPLD0A_PHYS           CPLDX_PHYS (0x0a)
+# define CPLD0A_VIRT           CPLDX_VIRT (0x0a)
+# define CPLD0A_SIZE           PAGE_SIZE
 # define CPLD0C_PHYS           CPLDX_PHYS (0x0c)
 # define CPLD0C_VIRT           CPLDX_VIRT (0x0c)
 # define CPLD0C_SIZE           PAGE_SIZE
@@ -84,5 +85,7 @@
 #define        XTAL_IN                 14745600        /* 14.7456 MHz crystal */
 #define PLL_CLOCK              (XTAL_IN * 21)  /* 309 MHz PLL clock */
 #define MAX_HCLK_KHZ           100000          /* HCLK max limit ~100MHz */
+#define HCLK                   (99993600)
+//#define HCLK                 (119808000)
 
 #endif /* __ASM_ARCH_CONSTANTS_H */
index 15492e3253f6abdc5088e6f6522613f53f537a8b..a8cbd14bbf9d7693c41eea756175a5e75c6c29fc 100644 (file)
@@ -1,9 +1,86 @@
 /* include/asm-arm/arch-lh7a40x/dma.h
  *
- *  Copyright (C) 2003 Coastal Environmental Systems
+ *  Copyright (C) 2005 Marc Singer
  *
  *  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.
  *
  */
+
+typedef enum {
+       DMA_M2M0        = 0,
+       DMA_M2M1        = 1,
+       DMA_M2P0        = 2,    /* Tx */
+       DMA_M2P1        = 3,    /* Rx */
+       DMA_M2P2        = 4,    /* Tx */
+       DMA_M2P3        = 5,    /* Rx */
+       DMA_M2P4        = 6,    /* Tx - AC97 */
+       DMA_M2P5        = 7,    /* Rx - AC97 */
+       DMA_M2P6        = 8,    /* Tx */
+       DMA_M2P7        = 9,    /* Rx */
+} dma_device_t;
+
+#define DMA_LENGTH_MAX         ((64*1024) - 4) /* bytes */
+
+#define DMAC_GCA               __REG(DMAC_PHYS + 0x2b80)
+#define DMAC_GIR               __REG(DMAC_PHYS + 0x2bc0)
+
+#define DMAC_GIR_MMI1          (1<<11)
+#define DMAC_GIR_MMI0          (1<<10)
+#define DMAC_GIR_MPI8          (1<<9)
+#define DMAC_GIR_MPI9          (1<<8)
+#define DMAC_GIR_MPI6          (1<<7)
+#define DMAC_GIR_MPI7          (1<<6)
+#define DMAC_GIR_MPI4          (1<<5)
+#define DMAC_GIR_MPI5          (1<<4)
+#define DMAC_GIR_MPI2          (1<<3)
+#define DMAC_GIR_MPI3          (1<<2)
+#define DMAC_GIR_MPI0          (1<<1)
+#define DMAC_GIR_MPI1          (1<<0)
+
+#define DMAC_M2P0              0x0000
+#define DMAC_M2P1              0x0040
+#define DMAC_M2P2              0x0080
+#define DMAC_M2P3              0x00c0
+#define DMAC_M2P4              0x0240
+#define DMAC_M2P5              0x0200
+#define DMAC_M2P6              0x02c0
+#define DMAC_M2P7              0x0280
+#define DMAC_M2P8              0x0340
+#define DMAC_M2P9              0x0300
+#define DMAC_M2M0              0x0100
+#define DMAC_M2M1              0x0140
+
+#define DMAC_P_PCONTROL(c)     __REG(DMAC_PHYS + (c) + 0x00)
+#define DMAC_P_PINTERRUPT(c)   __REG(DMAC_PHYS + (c) + 0x04)
+#define DMAC_P_PPALLOC(c)      __REG(DMAC_PHYS + (c) + 0x08)
+#define DMAC_P_PSTATUS(c)      __REG(DMAC_PHYS + (c) + 0x0c)
+#define DMAC_P_REMAIN(c)       __REG(DMAC_PHYS + (c) + 0x14)
+#define DMAC_P_MAXCNT0(c)      __REG(DMAC_PHYS + (c) + 0x20)
+#define DMAC_P_BASE0(c)                __REG(DMAC_PHYS + (c) + 0x24)
+#define DMAC_P_CURRENT0(c)     __REG(DMAC_PHYS + (c) + 0x28)
+#define DMAC_P_MAXCNT1(c)      __REG(DMAC_PHYS + (c) + 0x30)
+#define DMAC_P_BASE1(c)                __REG(DMAC_PHYS + (c) + 0x34)
+#define DMAC_P_CURRENT1(c)     __REG(DMAC_PHYS + (c) + 0x38)
+
+#define DMAC_PCONTROL_ENABLE   (1<<4)
+
+#define DMAC_PORT_USB          0
+#define DMAC_PORT_SDMMC                1
+#define DMAC_PORT_AC97_1       2
+#define DMAC_PORT_AC97_2       3
+#define DMAC_PORT_AC97_3       4
+#define DMAC_PORT_UART1                6
+#define DMAC_PORT_UART2                7
+#define DMAC_PORT_UART3                8
+
+#define DMAC_PSTATUS_CURRSTATE_SHIFT   4
+#define DMAC_PSTATUS_CURRSTATE_MASK    0x3
+
+#define DMAC_PSTATUS_NEXTBUF    (1<<6)
+#define DMAC_PSTATUS_STALLRINT  (1<<0)
+
+#define DMAC_INT_CHE            (1<<3)
+#define DMAC_INT_NFB            (1<<1)
+#define DMAC_INT_STALL          (1<<0)
index a2f67c06d9c94281741d5e0f9509367eab92778a..9fc7f4988124af1b81247778df5890095e6acd6f 100644 (file)
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
 
-# if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
-#  error "LH7A400 and LH7A404 are mutually exclusive"
-# endif
+/* In order to allow there to be support for both of the processor
+   classes at the same time, we make a hack here that isn't very
+   pretty.  At startup, the link pointed to with the
+   branch_irq_lh7a400 symbol is replaced with a NOP when the CPU is
+   detected as a lh7a404.
 
-# if defined (CONFIG_ARCH_LH7A400)
+   *** FIXME: we should clean this up so that there is only one
+             implementation for each CPU's design.
+
+*/
+
+#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
+
+               .macro  disable_fiq
+               .endm
+
+               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+branch_irq_lh7a400: b 1000f
+
+@ Implementation of the LH7A404 get_irqnr_and_base.
+
+               mov     \irqnr, #0                      @ VIC1 irq base
+               mov     \base, #io_p2v(0x80000000)      @ APB registers
+               add     \base, \base, #0x8000
+               ldr     \tmp, [\base, #0x0030]          @ VIC1_VECTADDR
+               tst     \tmp, #VA_VECTORED              @ Direct vectored
+               bne     1002f
+               tst     \tmp, #VA_VIC1DEFAULT           @ Default vectored VIC1
+               ldrne   \irqstat, [\base, #0]           @ VIC1_IRQSTATUS
+               bne     1001f
+               add     \base, \base, #(0xa000 - 0x8000)
+               ldr     \tmp, [\base, #0x0030]          @ VIC2_VECTADDR
+               tst     \tmp, #VA_VECTORED              @ Direct vectored
+               bne     1002f
+               ldr     \irqstat, [\base, #0]           @ VIC2_IRQSTATUS
+               mov     \irqnr, #32                     @ VIC2 irq base
+
+1001:          movs    \irqstat, \irqstat, lsr #1      @ Shift into carry
+               bcs     1008f                           @ Bit set; irq found
+               add     \irqnr, \irqnr, #1
+               bne     1001b                           @ Until no bits
+               b       1009f                           @ Nothing?  Hmm.
+1002:          and     \irqnr, \tmp, #0x3f             @ Mask for valid bits
+1008:          movs    \irqstat, #1                    @ Force !Z
+               str     \tmp, [\base, #0x0030]          @ Clear vector
+               b       1009f
+
+@ Implementation of the LH7A400 get_irqnr_and_base.
+
+1000:          mov     \irqnr, #0
+               mov     \base, #io_p2v(0x80000000)      @ APB registers
+               ldr     \irqstat, [\base, #0x500]       @ PIC INTSR
+
+1001:          movs    \irqstat, \irqstat, lsr #1      @ Shift into carry
+               bcs     1008f                           @ Bit set; irq found
+               add     \irqnr, \irqnr, #1
+               bne     1001b                           @ Until no bits
+               b       1009f                           @ Nothing?  Hmm.
+1008:          movs    \irqstat, #1                    @ Force !Z
+
+1009:
+               .endm
+
+
+
+#elif defined (CONFIG_ARCH_LH7A400)
                .macro  disable_fiq
                .endm
 
index aeb07c162e2594d1051d76c230d49751ca8b63b7..e9ff74fd79396a882c2889310dcc2ef939d2cbd2 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
+#include <asm/sizes.h>         /* Added for the sake of amba-clcd driver */
+
 #define io_p2v(x) (0xf0000000 | (((x) & 0xfff00000) >> 4) | ((x) & 0x0000ffff))
 #define io_v2p(x) (             (((x) & 0x0fff0000) << 4) | ((x) & 0x0000ffff))
 
@@ -53,6 +55,8 @@ typedef struct { volatile u8 offset[4096]; } __regbase8;
 
 #endif
 
+#define MASK_AND_SET(v,m,s)    (v) = ((v)&~(m))|(s)
+
 #include "registers.h"
 
 #endif  /* _ASM_ARCH_HARDWARE_H */
index f91f3e59f3abfc10c329341e0675242b3742f78f..afe8c7cbad6a181d552550cab3c00c47d302ade7 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __ASM_ARCH_IRQS_H
 #define __ASM_ARCH_IRQS_H
 
-#include <linux/config.h>
 
 #define FIQ_START      80
 
 #if !defined (IRQ_GPIO0INTR)
 # define IRQ_GPIO0INTR IRQ_GPIO0FIQ
 #endif
-#define IRQ_TICK       IRQ_TINTR
+#define IRQ_TICK       IRQ_TINTR
 #define IRQ_PCC1_RDY   IRQ_GPIO6INTR   /* PCCard 1 ready */
 #define IRQ_PCC2_RDY   IRQ_GPIO7INTR   /* PCCard 2 ready */
+#define IRQ_USB                IRQ_USBINTR     /* USB device */
 
 #ifdef CONFIG_MACH_KEV7A400
 # define IRQ_TS                IRQ_GPIOFIQ     /* Touchscreen */
 # define IRQ_LPD7A400_TS       IRQ_LPD7A40X_CPLD + 1   /* Touch screen */
 #endif
 
+#if defined (CONFIG_MACH_LPD7A400)
+# define IRQ_TOUCH             IRQ_LPD7A400_TS
+#endif
+
 #define NR_IRQS                (NR_IRQ_CPU + NR_IRQ_BOARD)
 
 #endif
index 2edb22e35450996dd824d5565c8ae6830057f8fa..b4f09b3e2d0376564308474a5987123f219bdb44 100644 (file)
@@ -9,7 +9,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <asm/arch/constants.h>
 
 #ifndef __ASM_ARCH_REGISTERS_H
@@ -18,7 +17,7 @@
 
        /* Physical register base addresses */
 
-#define AC97_PHYS      (0x80000000)    /* AC97 Controller */
+#define AC97C_PHYS     (0x80000000)    /* AC97 Controller */
 #define MMC_PHYS       (0x80000100)    /* Multimedia Card Controller */
 #define USB_PHYS       (0x80000200)    /* USB Client */
 #define SCI_PHYS       (0x80000300)    /* Secure Card Interface */
@@ -35,6 +34,8 @@
 #define RTC_PHYS       (0x80000d00)    /* Real-time Clock */
 #define GPIO_PHYS      (0x80000e00)    /* General Purpose IO */
 #define BMI_PHYS       (0x80000f00)    /* Battery Monitor Interface */
+#define HRTFTC_PHYS    (0x80001000)    /* High-res TFT Controller (LH7A400) */
+#define ALI_PHYS       (0x80001000)    /* Advanced LCD Interface (LH7A404) */
 #define WDT_PHYS       (0x80001400)    /* Watchdog Timer */
 #define SMC_PHYS       (0x80002000)    /* Static Memory Controller */
 #define SDRC_PHYS      (0x80002400)    /* SDRAM Controller */
@@ -43,6 +44,7 @@
 
        /* Physical registers of the LH7A404 */
 
+#define ADC_PHYS       (0x80001300)    /* A/D & Touchscreen Controller */
 #define VIC1_PHYS      (0x80008000)    /* Vectored Interrupt Controller 1 */
 #define USBH_PHYS      (0x80009000)    /* USB OHCI host controller */
 #define VIC2_PHYS      (0x8000a000)    /* Vectored Interrupt Controller 2 */
 
        /* Clock/State Controller register */
 
+#define CSC_PWRSR      __REG(CSC_PHYS + 0x00) /* Reset register & ID */
 #define CSC_PWRCNT     __REG(CSC_PHYS + 0x04) /* Power control */
+#define CSC_CLKSET     __REG(CSC_PHYS + 0x20) /* Clock speed control */
+#define CSC_USBDRESET  __REG(CSC_PHYS + 0x4c) /* USB Device resets */
 
 #define CSC_PWRCNT_USBH_EN     (1<<28) /* USB Host power enable */
-
+#define CSC_PWRCNT_DMAC_M2M1_EN        (1<<27)
+#define CSC_PWRCNT_DMAC_M2M0_EN        (1<<26)
+#define CSC_PWRCNT_DMAC_M2P8_EN        (1<<25)
+#define CSC_PWRCNT_DMAC_M2P9_EN        (1<<24)
+#define CSC_PWRCNT_DMAC_M2P6_EN        (1<<23)
+#define CSC_PWRCNT_DMAC_M2P7_EN        (1<<22)
+#define CSC_PWRCNT_DMAC_M2P4_EN        (1<<21)
+#define CSC_PWRCNT_DMAC_M2P5_EN        (1<<20)
+#define CSC_PWRCNT_DMAC_M2P2_EN        (1<<19)
+#define CSC_PWRCNT_DMAC_M2P3_EN        (1<<18)
+#define CSC_PWRCNT_DMAC_M2P0_EN        (1<<17)
+#define CSC_PWRCNT_DMAC_M2P1_EN        (1<<16)
+
+#define CSC_PWRSR_CHIPMAN_SHIFT        (24)
+#define CSC_PWRSR_CHIPMAN_MASK (0xff)
+#define CSC_PWRSR_CHIPID_SHIFT (16)
+#define CSC_PWRSR_CHIPID_MASK  (0xff)
+
+#define CSC_USBDRESET_APBRESETREG      (1<<1)
+#define CSC_USBDRESET_IORESETREG       (1<<0)
 
        /* Interrupt Controller registers */
 
 #define GPIO_GPIOFEOI  __REG(GPIO_PHYS + 0x54) /* GPIO End-of-Interrupt */
 #define GPIO_GPIOINTEN __REG(GPIO_PHYS + 0x58) /* GPIO Interrupt Enable */
 #define GPIO_INTSTATUS __REG(GPIO_PHYS + 0x5c) /* GPIO Interrupt Status */
+#define GPIO_PINMUX    __REG(GPIO_PHYS + 0x2c)
+#define GPIO_PADD      __REG(GPIO_PHYS + 0x10)
+#define GPIO_PAD       __REG(GPIO_PHYS + 0x00)
+#define GPIO_PCD       __REG(GPIO_PHYS + 0x08)
+#define GPIO_PCDD      __REG(GPIO_PHYS + 0x18)
+#define GPIO_PEDD      __REG(GPIO_PHYS + 0x24)
+#define GPIO_PED       __REG(GPIO_PHYS + 0x20)
 
 
        /* Static Memory Controller registers */
 #endif
 
 #if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
-# define CPLD_CONTROL          __REG8(CPLD02_PHYS)
-# define CPLD_SPI_DATA         __REG8(CPLD06_PHYS)
-# define CPLD_SPI_CONTROL      __REG8(CPLD08_PHYS)
-# define CPLD_SPI_EEPROM       __REG8(CPLD0A_PHYS)
-# define CPLD_INTERRUPTS       __REG8(CPLD0C_PHYS) /* IRQ mask/status */
-# define CPLD_BOOT_MODE                __REG8(CPLD0E_PHYS)
-# define CPLD_FLASH            __REG8(CPLD10_PHYS)
-# define CPLD_POWER_MGMT       __REG8(CPLD12_PHYS)
-# define CPLD_REVISION         __REG8(CPLD14_PHYS)
-# define CPLD_GPIO_EXT         __REG8(CPLD16_PHYS)
-# define CPLD_GPIO_DATA                __REG8(CPLD18_PHYS)
-# define CPLD_GPIO_DIR         __REG8(CPLD1A_PHYS)
-#endif
 
+# define CPLD_CONTROL          __REG16(CPLD02_PHYS)
+# define CPLD_SPI_DATA         __REG16(CPLD06_PHYS)
+# define CPLD_SPI_CONTROL      __REG16(CPLD08_PHYS)
+# define CPLD_SPI_EEPROM       __REG16(CPLD0A_PHYS)
+# define CPLD_INTERRUPTS       __REG16(CPLD0C_PHYS) /* IRQ mask/status */
+# define CPLD_BOOT_MODE                __REG16(CPLD0E_PHYS)
+# define CPLD_FLASH            __REG16(CPLD10_PHYS)
+# define CPLD_POWER_MGMT       __REG16(CPLD12_PHYS)
+# define CPLD_REVISION         __REG16(CPLD14_PHYS)
+# define CPLD_GPIO_EXT         __REG16(CPLD16_PHYS)
+# define CPLD_GPIO_DATA                __REG16(CPLD18_PHYS)
+# define CPLD_GPIO_DIR         __REG16(CPLD1A_PHYS)
+
+#endif
 
        /* Timer registers */
 
 
 
 #endif  /* _ASM_ARCH_REGISTERS_H */
-
diff --git a/include/asm-arm/arch-lh7a40x/ssp.h b/include/asm-arm/arch-lh7a40x/ssp.h
new file mode 100644 (file)
index 0000000..132b1c4
--- /dev/null
@@ -0,0 +1,71 @@
+/* ssp.h
+     $Id$
+
+   written by Marc Singer
+   6 Dec 2004
+
+   Copyright (C) 2004 Marc Singer
+
+   -----------
+   DESCRIPTION
+   -----------
+
+   This SSP header is available throughout the kernel, for this
+   machine/architecture, because drivers that use it may be dispersed.
+
+   This file was cloned from the 7952x implementation.  It would be
+   better to share them, but we're taking an easier approach for the
+   time being.
+
+*/
+
+#if !defined (__SSP_H__)
+#    define   __SSP_H__
+
+/* ----- Includes */
+
+/* ----- Types */
+
+struct ssp_driver {
+       int  (*init)            (void);
+       void (*exit)            (void);
+       void (*acquire)         (void);
+       void (*release)         (void);
+       int  (*configure)       (int device, int mode, int speed,
+                                int frame_size_write, int frame_size_read);
+       void (*chip_select)     (int enable);
+       void (*set_callbacks)   (void* handle,
+                                irqreturn_t (*callback_tx)(void*),
+                                irqreturn_t (*callback_rx)(void*));
+       void (*enable)          (void);
+       void (*disable)         (void);
+//     int  (*save_state)      (void*);
+//     void (*restore_state)   (void*);
+       int  (*read)            (void);
+       int  (*write)           (u16 data);
+       int  (*write_read)      (u16 data);
+       void (*flush)           (void);
+       void (*write_async)     (void* pv, size_t cb);
+       size_t (*write_pos)     (void);
+};
+
+       /* These modes are only available on the LH79524 */
+#define SSP_MODE_SPI           (1)
+#define SSP_MODE_SSI           (2)
+#define SSP_MODE_MICROWIRE     (3)
+#define SSP_MODE_I2S           (4)
+
+       /* CPLD SPI devices */
+#define DEVICE_EEPROM  0       /* Configuration eeprom */
+#define DEVICE_MAC     1       /* MAC eeprom (LPD79524) */
+#define DEVICE_CODEC   2       /* Audio codec */
+#define DEVICE_TOUCH   3       /* Touch screen (LPD79520) */
+
+/* ----- Globals */
+
+/* ----- Prototypes */
+
+//extern struct ssp_driver lh79520_i2s_driver;
+extern struct ssp_driver lh7a400_cpld_ssp_driver;
+
+#endif  /* __SSP_H__ */
index f8053346f60897d58c36440118d270f01cabf924..3d1ce0426a33646127a90e92f1a3b05a47e2fb48 100644 (file)
@@ -16,7 +16,7 @@
 #ifndef UART_R_STATUS
 # define UART_R_STATUS (0x10)
 #endif
-#define nTxRdy         (0x20)  /* Not TxReady (literally Tx FIFO full) */
+#define nTxRdy         (0x20)  /* Not TxReady (literally Tx FIFO full) */
 
        /* Access UART with physical addresses before MMU is setup */
 #define UART_STATUS (*(volatile unsigned long*) (UART2_PHYS + UART_R_STATUS))
index 6d6240a4681cafb0cedb4eed9fb7e717d639b640..dfdbf06fd646c5a14d053fc36606054945b8b3aa 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _OMAP_BOARD_H
 #define _OMAP_BOARD_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /* Different peripheral ids */
index 7909b729826c41bdbbace4d679c07fd9bf6624ea..c7d9e857795df7fde58111cbec5fb8b5b65d6036 100644 (file)
@@ -37,7 +37,6 @@
 #define __ASM_ARCH_OMAP_HARDWARE_H
 
 #include <asm/sizes.h>
-#include <linux/config.h>
 #ifndef __ASSEMBLER__
 #include <asm/types.h>
 #include <asm/arch/cpu.h>
index 67970d1a2020b213a32d6b9c36f7bdc9ccb42014..ac2bfa433f06e9c160ccd404f98849f272e648d8 100644 (file)
@@ -4,7 +4,6 @@
  */
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
-#include <linux/config.h>
 #include <linux/clk.h>
 
 #include <asm/mach-types.h>
index ca2c8bec82e7d299a1f8fbf94465f68f1a090b80..aca0adfef1b8da878ca3a499fbfea14e0e98a2f0 100644 (file)
@@ -17,7 +17,6 @@
  * kind, whether express or implied.
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/serial_reg.h>
 #include <asm/arch/serial.h>
diff --git a/include/asm-arm/arch-pnx4008/clock.h b/include/asm-arm/arch-pnx4008/clock.h
new file mode 100644 (file)
index 0000000..91ae003
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * include/asm-arm/arch-pnx4008/clock.h
+ *
+ * Clock control driver for PNX4008 - header file
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __PNX4008_CLOCK_H__
+#define __PNX4008_CLOCK_H__
+
+struct module;
+struct clk;
+
+#define PWRMAN_VA_BASE         IO_ADDRESS(PNX4008_PWRMAN_BASE)
+#define HCLKDIVCTRL_REG                (PWRMAN_VA_BASE + 0x40)
+#define PWRCTRL_REG            (PWRMAN_VA_BASE + 0x44)
+#define PLLCTRL_REG            (PWRMAN_VA_BASE + 0x48)
+#define OSC13CTRL_REG          (PWRMAN_VA_BASE + 0x4c)
+#define SYSCLKCTRL_REG         (PWRMAN_VA_BASE + 0x50)
+#define HCLKPLLCTRL_REG                (PWRMAN_VA_BASE + 0x58)
+#define USBCTRL_REG            (PWRMAN_VA_BASE + 0x64)
+#define SDRAMCLKCTRL_REG       (PWRMAN_VA_BASE + 0x68)
+#define MSCTRL_REG             (PWRMAN_VA_BASE + 0x80)
+#define BTCLKCTRL              (PWRMAN_VA_BASE + 0x84)
+#define DUMCLKCTRL_REG         (PWRMAN_VA_BASE + 0x90)
+#define I2CCLKCTRL_REG         (PWRMAN_VA_BASE + 0xac)
+#define KEYCLKCTRL_REG         (PWRMAN_VA_BASE + 0xb0)
+#define TSCLKCTRL_REG          (PWRMAN_VA_BASE + 0xb4)
+#define PWMCLKCTRL_REG         (PWRMAN_VA_BASE + 0xb8)
+#define SPICTRL_REG            (PWRMAN_VA_BASE + 0xc4)
+#define FLASHCLKCTRL_REG       (PWRMAN_VA_BASE + 0xc8)
+#define UART3CLK_REG           (PWRMAN_VA_BASE + 0xd0)
+#define UARTCLKCTRL_REG                (PWRMAN_VA_BASE + 0xe4)
+#define DMACLKCTRL_REG         (PWRMAN_VA_BASE + 0xe8)
+#define AUTOCLK_CTRL           (PWRMAN_VA_BASE + 0xec)
+#define JPEGCLKCTRL_REG                (PWRMAN_VA_BASE + 0xfc)
+
+#define AUDIOCONFIG_VA_BASE    IO_ADDRESS(PNX4008_AUDIOCONFIG_BASE)
+#define DSPPLLCTRL_REG         (AUDIOCONFIG_VA_BASE + 0x60)
+#define DSPCLKCTRL_REG         (AUDIOCONFIG_VA_BASE + 0x64)
+#define AUDIOCLKCTRL_REG       (AUDIOCONFIG_VA_BASE + 0x68)
+#define AUDIOPLLCTRL_REG       (AUDIOCONFIG_VA_BASE + 0x6C)
+
+#define USB_OTG_CLKCTRL_REG    IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xff4)
+
+#define VFP9CLKCTRL_REG                IO_ADDRESS(PNX4008_DEBUG_BASE)
+
+#define CLK_RATE_13MHZ 13000
+#define CLK_RATE_1MHZ 1000
+#define CLK_RATE_208MHZ 208000
+#define CLK_RATE_48MHZ 48000
+#define CLK_RATE_32KHZ 32
+
+#define PNX4008_UART_CLK CLK_RATE_13MHZ * 1000 /* in MHz */
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/debug-macro.S b/include/asm-arm/arch-pnx4008/debug-macro.S
new file mode 100644 (file)
index 0000000..eb3839d
--- /dev/null
@@ -0,0 +1,27 @@
+/* linux/include/asm-arm/arch-pnx4008/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?
+               mov     \rx, #0x00090000
+               addeq   \rx, \rx, #0x40000000
+               addne   \rx, \rx, #0xf4000000
+               .endm
+
+               .macro  senduart,rd,rx
+               strb    \rd, [\rx, #0x0]
+               .endm
+
+#define UART_SHIFT     2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-pnx4008/dma.h b/include/asm-arm/arch-pnx4008/dma.h
new file mode 100644 (file)
index 0000000..3aee120
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  linux/include/asm-arm/arch-pnx4008/dma.h
+ *
+ *  PNX4008 DMA header file
+ *
+ *  Author:    Vitaly Wool
+ *  Copyright: MontaVista Software Inc. (c) 2005
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#include "platform.h"
+
+#define MAX_DMA_ADDRESS                0xffffffff
+
+#define MAX_DMA_CHANNELS       8
+
+#define DMAC_BASE              IO_ADDRESS(PNX4008_DMA_CONFIG_BASE)
+#define DMAC_INT_STAT          (DMAC_BASE + 0x0000)
+#define DMAC_INT_TC_STAT       (DMAC_BASE + 0x0004)
+#define DMAC_INT_TC_CLEAR      (DMAC_BASE + 0x0008)
+#define DMAC_INT_ERR_STAT      (DMAC_BASE + 0x000c)
+#define DMAC_INT_ERR_CLEAR     (DMAC_BASE + 0x0010)
+#define DMAC_SOFT_SREQ         (DMAC_BASE + 0x0024)
+#define DMAC_CONFIG            (DMAC_BASE + 0x0030)
+#define DMAC_Cx_SRC_ADDR(c)    (DMAC_BASE + 0x0100 + (c) * 0x20)
+#define DMAC_Cx_DEST_ADDR(c)   (DMAC_BASE + 0x0104 + (c) * 0x20)
+#define DMAC_Cx_LLI(c)         (DMAC_BASE + 0x0108 + (c) * 0x20)
+#define DMAC_Cx_CONTROL(c)     (DMAC_BASE + 0x010c + (c) * 0x20)
+#define DMAC_Cx_CONFIG(c)      (DMAC_BASE + 0x0110 + (c) * 0x20)
+
+enum {
+       WIDTH_BYTE = 0,
+       WIDTH_HWORD,
+       WIDTH_WORD
+};
+
+enum {
+       FC_MEM2MEM_DMA,
+       FC_MEM2PER_DMA,
+       FC_PER2MEM_DMA,
+       FC_PER2PER_DMA,
+       FC_PER2PER_DPER,
+       FC_MEM2PER_PER,
+       FC_PER2MEM_PER,
+       FC_PER2PER_SPER
+};
+
+enum {
+       DMA_INT_UNKNOWN = 0,
+       DMA_ERR_INT = 1,
+       DMA_TC_INT = 2,
+};
+
+enum {
+       DMA_BUFFER_ALLOCATED = 1,
+       DMA_HAS_LL = 2,
+};
+
+enum {
+       PER_CAM_DMA_1 = 0,
+       PER_NDF_FLASH = 1,
+       PER_MBX_SLAVE_FIFO = 2,
+       PER_SPI2_REC_XMIT = 3,
+       PER_MS_SD_RX_XMIT = 4,
+       PER_HS_UART_1_XMIT = 5,
+       PER_HS_UART_1_RX = 6,
+       PER_HS_UART_2_XMIT = 7,
+       PER_HS_UART_2_RX = 8,
+       PER_HS_UART_7_XMIT = 9,
+       PER_HS_UART_7_RX = 10,
+       PER_SPI1_REC_XMIT = 11,
+       PER_MLC_NDF_SREC = 12,
+       PER_CAM_DMA_2 = 13,
+       PER_PRNG_INFIFO = 14,
+       PER_PRNG_OUTFIFO = 15,
+};
+
+struct pnx4008_dma_ch_ctrl {
+       int tc_mask;
+       int cacheable;
+       int bufferable;
+       int priv_mode;
+       int di;
+       int si;
+       int dest_ahb1;
+       int src_ahb1;
+       int dwidth;
+       int swidth;
+       int dbsize;
+       int sbsize;
+       int tr_size;
+};
+
+struct pnx4008_dma_ch_config {
+       int halt;
+       int active;
+       int lock;
+       int itc;
+       int ie;
+       int flow_cntrl;
+       int dest_per;
+       int src_per;
+};
+
+struct pnx4008_dma_ll {
+       unsigned long src_addr;
+       unsigned long dest_addr;
+       u32 next_dma;
+       unsigned long ch_ctrl;
+       struct pnx4008_dma_ll *next;
+       int flags;
+       void *alloc_data;
+       int (*free) (void *);
+};
+
+struct pnx4008_dma_config {
+       int is_ll;
+       unsigned long src_addr;
+       unsigned long dest_addr;
+       unsigned long ch_ctrl;
+       unsigned long ch_cfg;
+       struct pnx4008_dma_ll *ll;
+       u32 ll_dma;
+       int flags;
+       void *alloc_data;
+       int (*free) (void *);
+};
+
+extern struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t *);
+extern void pnx4008_free_ll_entry(struct pnx4008_dma_ll *, dma_addr_t);
+extern void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll *);
+
+extern int pnx4008_request_channel(char *, int,
+                                  void (*)(int, int, void *, struct pt_regs *),
+                                  void *);
+extern void pnx4008_free_channel(int);
+extern int pnx4008_config_dma(int, int, int);
+extern int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl *,
+                                   unsigned long *);
+extern int pnx4008_dma_parse_control(unsigned long,
+                                    struct pnx4008_dma_ch_ctrl *);
+extern int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config *,
+                                  unsigned long *);
+extern int pnx4008_dma_parse_config(unsigned long,
+                                   struct pnx4008_dma_ch_config *);
+extern int pnx4008_config_channel(int, struct pnx4008_dma_config *);
+extern int pnx4008_channel_get_config(int, struct pnx4008_dma_config *);
+extern int pnx4008_dma_ch_enable(int);
+extern int pnx4008_dma_ch_disable(int);
+extern int pnx4008_dma_ch_enabled(int);
+extern void pnx4008_dma_split_head_entry(struct pnx4008_dma_config *,
+                                        struct pnx4008_dma_ch_ctrl *);
+extern void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll *,
+                                      struct pnx4008_dma_ch_ctrl *);
+
+#endif                         /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-pnx4008/entry-macro.S b/include/asm-arm/arch-pnx4008/entry-macro.S
new file mode 100644 (file)
index 0000000..c1c198e
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * include/asm-arm/arch-pnx4008/entry-macro.S
+ *
+ * Low-level IRQ helper macros for PNX4008-based platforms
+ *
+ * 2005-2006 (c) MontaVista Software, Inc.
+ * Author: Vitaly Wool <vwool@ru.mvista.com>
+ * 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 "platform.h"
+
+#define IO_BASE         0xF0000000
+#define IO_ADDRESS(x)  (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)
+
+#define INTRC_MASK                     0x00
+#define INTRC_RAW_STAT                 0x04
+#define INTRC_STAT                     0x08
+#define INTRC_POLAR                    0x0C
+#define INTRC_ACT_TYPE                 0x10
+#define INTRC_TYPE                     0x14
+
+#define SIC1_BASE_INT   32
+#define SIC2_BASE_INT   64
+
+               .macro  disable_fiq
+               .endm
+
+               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+/* decode the MIC interrupt numbers */
+               ldr     \base, =IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
+               ldr     \irqstat, [\base, #INTRC_STAT]
+
+               cmp     \irqstat,#1<<16
+               movhs   \irqnr,#16
+               movlo   \irqnr,#0
+               movhs   \irqstat,\irqstat,lsr#16
+               cmp     \irqstat,#1<<8
+               addhs   \irqnr,\irqnr,#8
+               movhs   \irqstat,\irqstat,lsr#8
+               cmp     \irqstat,#1<<4
+               addhs   \irqnr,\irqnr,#4
+               movhs   \irqstat,\irqstat,lsr#4
+               cmp     \irqstat,#1<<2
+               addhs   \irqnr,\irqnr,#2
+               movhs   \irqstat,\irqstat,lsr#2
+               cmp     \irqstat,#1<<1
+               addhs   \irqnr,\irqnr,#1
+
+/* was there an interrupt ? if not then drop out with EQ status */
+               teq     \irqstat,#0
+               beq     1003f
+
+/* and now check for extended IRQ reasons */
+               cmp     \irqnr,#1
+               bls     1003f
+               cmp     \irqnr,#30
+               blo     1002f
+
+/* IRQ 31,30  : High priority cascade IRQ handle */
+/* read the correct SIC */
+/* decoding status after compare : eq is 30 (SIC1) , ne is 31 (SIC2) */
+/* set the base IRQ number */
+               ldreq   \base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
+               moveq  \irqnr,#SIC1_BASE_INT
+               ldrne   \base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
+               movne   \irqnr,#SIC2_BASE_INT
+               ldr     \irqstat, [\base, #INTRC_STAT]
+               ldr     \tmp,     [\base, #INTRC_TYPE]
+/* and with inverted mask : low priority interrupts  */
+               and     \irqstat,\irqstat,\tmp
+               b       1004f
+
+1003:
+/* IRQ 1,0  : Low priority cascade IRQ handle */
+/* read the correct SIC */
+/* decoding status after compare : eq is 1 (SIC2) , ne is 0 (SIC1)*/
+/* read the correct SIC */
+/* set the base IRQ number  */
+               ldrne   \base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
+               movne   \irqnr,#SIC1_BASE_INT
+               ldreq   \base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
+               moveq   \irqnr,#SIC2_BASE_INT
+               ldr     \irqstat, [\base, #INTRC_STAT]
+               ldr     \tmp,     [\base, #INTRC_TYPE]
+/* and with inverted mask : low priority interrupts  */
+               bic     \irqstat,\irqstat,\tmp
+
+1004:
+
+               cmp     \irqstat,#1<<16
+               addhs   \irqnr,\irqnr,#16
+               movhs   \irqstat,\irqstat,lsr#16
+               cmp     \irqstat,#1<<8
+               addhs   \irqnr,\irqnr,#8
+               movhs   \irqstat,\irqstat,lsr#8
+               cmp     \irqstat,#1<<4
+               addhs   \irqnr,\irqnr,#4
+               movhs   \irqstat,\irqstat,lsr#4
+               cmp     \irqstat,#1<<2
+               addhs   \irqnr,\irqnr,#2
+               movhs   \irqstat,\irqstat,lsr#2
+               cmp     \irqstat,#1<<1
+               addhs   \irqnr,\irqnr,#1
+
+
+/* is irqstat not zero */
+
+1002:
+/* we assert that irqstat is not equal to zero and return ne status if true*/
+               teq     \irqstat,#0
+1003:
+               .endm
+
+
+               .macro  irq_prio_table
+               .endm
+
+
diff --git a/include/asm-arm/arch-pnx4008/gpio.h b/include/asm-arm/arch-pnx4008/gpio.h
new file mode 100644 (file)
index 0000000..1fa5a77
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * include/asm-arm/arch-pnx4008/gpio.h
+ *
+ * PNX4008 GPIO driver - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef _PNX4008_GPIO_H_
+#define _PNX4008_GPIO_H_
+
+
+/* Block numbers */
+#define GPIO_IN                (0)
+#define GPIO_OUT               (0x100)
+#define GPIO_BID               (0x200)
+#define GPIO_RAM               (0x300)
+#define GPIO_MUX               (0x400)
+
+#define GPIO_TYPE_MASK(K) ((K) & 0x700)
+
+/* INPUT GPIOs */
+/* GPI */
+#define GPI_00         (GPIO_IN | 0)
+#define GPI_01         (GPIO_IN | 1)
+#define GPI_02         (GPIO_IN | 2)
+#define GPI_03                 (GPIO_IN | 3)
+#define GPI_04         (GPIO_IN | 4)
+#define GPI_05         (GPIO_IN | 5)
+#define GPI_06         (GPIO_IN | 6)
+#define GPI_07         (GPIO_IN | 7)
+#define GPI_08         (GPIO_IN | 8)
+#define GPI_09         (GPIO_IN | 9)
+#define U1_RX          (GPIO_IN | 15)
+#define U2_HTCS        (GPIO_IN | 16)
+#define U2_RX          (GPIO_IN | 17)
+#define U3_RX          (GPIO_IN | 18)
+#define U4_RX          (GPIO_IN | 19)
+#define U5_RX          (GPIO_IN | 20)
+#define U6_IRRX        (GPIO_IN | 21)
+#define U7_HCTS        (GPIO_IN | 22)
+#define U7_RX          (GPIO_IN | 23)
+/* MISC IN */
+#define SPI1_DATIN     (GPIO_IN | 25)
+#define DISP_SYNC      (GPIO_IN | 26)
+#define SPI2_DATIN     (GPIO_IN | 27)
+#define GPI_11         (GPIO_IN | 28)
+
+#define GPIO_IN_MASK   0x1eff83ff
+
+/* OUTPUT GPIOs */
+/* GPO */
+#define GPO_00         (GPIO_OUT | 0)
+#define GPO_01         (GPIO_OUT | 1)
+#define GPO_02         (GPIO_OUT | 2)
+#define GPO_03                 (GPIO_OUT | 3)
+#define GPO_04         (GPIO_OUT | 4)
+#define GPO_05         (GPIO_OUT | 5)
+#define GPO_06         (GPIO_OUT | 6)
+#define GPO_07         (GPIO_OUT | 7)
+#define GPO_08         (GPIO_OUT | 8)
+#define GPO_09         (GPIO_OUT | 9)
+#define GPO_10         (GPIO_OUT | 10)
+#define GPO_11                 (GPIO_OUT | 11)
+#define GPO_12         (GPIO_OUT | 12)
+#define GPO_13         (GPIO_OUT | 13)
+#define GPO_14         (GPIO_OUT | 14)
+#define GPO_15         (GPIO_OUT | 15)
+#define GPO_16         (GPIO_OUT | 16)
+#define GPO_17                 (GPIO_OUT | 17)
+#define GPO_18         (GPIO_OUT | 18)
+#define GPO_19         (GPIO_OUT | 19)
+#define GPO_20         (GPIO_OUT | 20)
+#define GPO_21         (GPIO_OUT | 21)
+#define GPO_22         (GPIO_OUT | 22)
+#define GPO_23         (GPIO_OUT | 23)
+
+#define GPIO_OUT_MASK   0xffffff
+
+/* BIDIRECTIONAL GPIOs */
+/* RAM pins */
+#define RAM_D19                (GPIO_RAM | 0)
+#define RAM_D20        (GPIO_RAM | 1)
+#define RAM_D21        (GPIO_RAM | 2)
+#define RAM_D22        (GPIO_RAM | 3)
+#define RAM_D23        (GPIO_RAM | 4)
+#define RAM_D24        (GPIO_RAM | 5)
+#define RAM_D25        (GPIO_RAM | 6)
+#define RAM_D26        (GPIO_RAM | 7)
+#define RAM_D27                (GPIO_RAM | 8)
+#define RAM_D28        (GPIO_RAM | 9)
+#define RAM_D29        (GPIO_RAM | 10)
+#define RAM_D30        (GPIO_RAM | 11)
+#define RAM_D31        (GPIO_RAM | 12)
+
+#define GPIO_RAM_MASK   0x1fff
+
+/* I/O pins */
+#define GPIO_00        (GPIO_BID | 25)
+#define GPIO_01        (GPIO_BID | 26)
+#define GPIO_02        (GPIO_BID | 27)
+#define GPIO_03        (GPIO_BID | 28)
+#define GPIO_04        (GPIO_BID | 29)
+#define GPIO_05        (GPIO_BID | 30)
+
+#define GPIO_BID_MASK   0x7e000000
+
+/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */
+#define GPIO_SDRAM_SEL         (GPIO_MUX | 3)
+
+#define GPIO_MUX_MASK   0x8
+
+/* Extraction/assembly macros */
+#define GPIO_BIT_MASK(K) ((K) & 0x1F)
+#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K))
+#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK))
+#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK))
+#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK))
+#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
+#define GPIO_ISIN(K)  ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
+
+extern int pnx4008_gpio_register_pin(unsigned short pin);
+extern int pnx4008_gpio_unregister_pin(unsigned short pin);
+extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
+extern int pnx4008_gpio_write_pin(unsigned short pin, int output);
+extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
+extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
+
+#endif                         /* _PNX4008_GPIO_H_ */
diff --git a/include/asm-arm/arch-pnx4008/hardware.h b/include/asm-arm/arch-pnx4008/hardware.h
new file mode 100644 (file)
index 0000000..a441039
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * linux/include/asm-arm/arch-pnx4008/hardware.h
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+#include <asm/arch/platform.h>
+
+/* Start of virtual addresses for IO devices */
+#define IO_BASE         0xF0000000
+
+/* This macro relies on fact that for all HW i/o addresses bits 20-23 are 0 */
+#define IO_ADDRESS(x)  (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/io.h b/include/asm-arm/arch-pnx4008/io.h
new file mode 100644 (file)
index 0000000..29ee439
--- /dev/null
@@ -0,0 +1,21 @@
+
+/*
+ *  include/asm-arm/arch-pnx4008/io.h
+ *
+ * Author: Dmitry Chigirev <chigirev@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)                        ((void __iomem *)(a))
+#define __mem_pci(a)           (a)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/irq.h b/include/asm-arm/arch-pnx4008/irq.h
new file mode 100644 (file)
index 0000000..fabff5d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * include/asm-arm/arch-pnx4008/irq.h
+ *
+ * PNX4008 IRQ controller driver - header file
+ * this one is used in entry-arnv.S as well so it cannot contain C code
+ *
+ * Copyright (c) 2005 Philips Semiconductors
+ * Copyright (c) 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.
+ */
+#ifndef __PNX4008_IRQ_H__
+#define __PNX4008_IRQ_H__
+
+#define MIC_VA_BASE             IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
+#define SIC1_VA_BASE            IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
+#define SIC2_VA_BASE            IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
+
+/* Manual: Chapter 20, page 195 */
+
+#define INTC_BIT(irq) (1<< ((irq) & 0x1F))
+
+#define INTC_ER(irq)    IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x0 + (((irq)&(0x3<<5))<<9)))
+#define INTC_RSR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x4 + (((irq)&(0x3<<5))<<9)))
+#define INTC_SR(irq)    IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x8 + (((irq)&(0x3<<5))<<9)))
+#define INTC_APR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0xC + (((irq)&(0x3<<5))<<9)))
+#define INTC_ATR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x10 + (((irq)&(0x3<<5))<<9)))
+#define INTC_ITR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x14 + (((irq)&(0x3<<5))<<9)))
+
+#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
+
+#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
+
+extern void __init pnx4008_init_irq(void);
+
+#endif /* __PNX4008_IRQ_H__ */
diff --git a/include/asm-arm/arch-pnx4008/irqs.h b/include/asm-arm/arch-pnx4008/irqs.h
new file mode 100644 (file)
index 0000000..13ec7ed
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * include/asm-arm/arch-pnx4008/irqs.h
+ *
+ * PNX4008 IRQ controller driver - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __PNX4008_IRQS_h__
+#define __PNX4008_IRQS_h__
+
+#define NR_IRQS         96
+
+/*Manual: table 259, page 199*/
+
+/*SUB2 Interrupt Routing (SIC2)*/
+
+#define SIC2_BASE_INT   64
+
+#define CLK_SWITCH_ARM_INT 95  /*manual: Clkswitch ARM  */
+#define CLK_SWITCH_DSP_INT 94  /*manual: ClkSwitch DSP  */
+#define CLK_SWITCH_AUD_INT 93  /*manual: Clkswitch AUD  */
+#define GPI_06_INT         92
+#define GPI_05_INT         91
+#define GPI_04_INT         90
+#define GPI_03_INT         89
+#define GPI_02_INT         88
+#define GPI_01_INT         87
+#define GPI_00_INT         86
+#define BT_CLKREQ_INT      85
+#define SPI1_DATIN_INT     84
+#define U5_RX_INT          83
+#define SDIO_INT_N         82
+#define CAM_HS_INT         81
+#define CAM_VS_INT         80
+#define GPI_07_INT         79
+#define DISP_SYNC_INT      78
+#define DSP_INT8           77
+#define U7_HCTS_INT        76
+#define GPI_10_INT         75
+#define GPI_09_INT         74
+#define GPI_08_INT         73
+#define DSP_INT7           72
+#define U2_HCTS_INT        71
+#define SPI2_DATIN_INT     70
+#define GPIO_05_INT        69
+#define GPIO_04_INT        68
+#define GPIO_03_INT        67
+#define GPIO_02_INT        66
+#define GPIO_01_INT        65
+#define GPIO_00_INT        64
+
+/*Manual: table 258, page 198*/
+
+/*SUB1 Interrupt Routing (SIC1)*/
+
+#define SIC1_BASE_INT   32
+
+#define USB_I2C_INT        63
+#define USB_DEV_HP_INT     62
+#define USB_DEV_LP_INT     61
+#define USB_DEV_DMA_INT    60
+#define USB_HOST_INT       59
+#define USB_OTG_ATX_INT_N  58
+#define USB_OTG_TIMER_INT  57
+#define SW_INT             56
+#define SPI1_INT           55
+#define KEY_IRQ            54
+#define DSP_M_INT          53
+#define RTC_INT            52
+#define I2C_1_INT          51
+#define I2C_2_INT          50
+#define PLL1_LOCK_INT      49
+#define PLL2_LOCK_INT      48
+#define PLL3_LOCK_INT      47
+#define PLL4_LOCK_INT      46
+#define PLL5_LOCK_INT      45
+#define SPI2_INT           44
+#define DSP_INT1           43
+#define DSP_INT2           42
+#define DSP_TDM_INT2       41
+#define TS_AUX_INT         40
+#define TS_IRQ             39
+#define TS_P_INT           38
+#define UOUT1_TO_PAD_INT   37
+#define GPI_11_INT         36
+#define DSP_INT4           35
+#define JTAG_COMM_RX_INT   34
+#define JTAG_COMM_TX_INT   33
+#define DSP_INT3           32
+
+/*Manual: table 257, page 197*/
+
+/*MAIN Interrupt Routing*/
+
+#define MAIN_BASE_INT   0
+
+#define SUB2_FIQ_N         31  /*active low */
+#define SUB1_FIQ_N         30  /*active low */
+#define JPEG_INT           29
+#define DMA_INT            28
+#define MSTIMER_INT        27
+#define IIR1_INT           26
+#define IIR2_INT           25
+#define IIR7_INT           24
+#define DSP_TDM_INT0       23
+#define DSP_TDM_INT1       22
+#define DSP_P_INT          21
+#define DSP_INT0           20
+#define DUM_INT            19
+#define UOUT0_TO_PAD_INT   18
+#define MP4_ENC_INT        17
+#define MP4_DEC_INT        16
+#define SD0_INT            15
+#define MBX_INT            14
+#define SD1_INT            13
+#define MS_INT_N           12
+#define FLASH_INT          11 /*NAND*/
+#define IIR6_INT           10
+#define IIR5_INT           9
+#define IIR4_INT           8
+#define IIR3_INT           7
+#define WATCH_INT          6
+#define HSTIMER_INT        5
+#define ARCH_TIMER_IRQ     HSTIMER_INT
+#define CAM_INT            4
+#define PRNG_INT           3
+#define CRYPTO_INT         2
+#define SUB2_IRQ_N         1   /*active low */
+#define SUB1_IRQ_N         0   /*active low */
+
+#define PNX4008_IRQ_TYPES \
+{                                           /*IRQ #'s: */         \
+IRQT_LOW,  IRQT_LOW,  IRQT_LOW,  IRQT_HIGH, /*  0, 1, 2, 3 */     \
+IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /*  4, 5, 6, 7 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /*  8, 9,10,11 */     \
+IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 12,13,14,15 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 16,17,18,19 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 20,21,22,23 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 24,25,26,27 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_LOW,  /* 28,29,30,31 */     \
+IRQT_HIGH, IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, /* 32,33,34,35 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_FALLING, IRQT_HIGH, /* 36,37,38,39 */  \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 40,41,42,43 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 44,45,46,47 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_LOW,  /* 48,49,50,51 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 52,53,54,55 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_HIGH, /* 56,57,58,59 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 60,61,62,63 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 64,65,66,67 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 68,69,70,71 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 72,73,74,75 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 76,77,78,79 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 80,81,82,83 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 84,85,86,87 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 88,89,90,91 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 92,93,94,95 */     \
+}
+
+/* Start Enable Pin Interrupts - table 58 page 66 */
+
+#define SE_PIN_BASE_INT   32
+
+#define SE_U7_RX_INT            63
+#define SE_U7_HCTS_INT          62
+#define SE_BT_CLKREQ_INT        61
+#define SE_U6_IRRX_INT          60
+/*59 unused*/
+#define SE_U5_RX_INT            58
+#define SE_GPI_11_INT           57
+#define SE_U3_RX_INT            56
+#define SE_U2_HCTS_INT          55
+#define SE_U2_RX_INT            54
+#define SE_U1_RX_INT            53
+#define SE_DISP_SYNC_INT        52
+/*51 unused*/
+#define SE_SDIO_INT_N           50
+#define SE_MSDIO_START_INT      49
+#define SE_GPI_06_INT           48
+#define SE_GPI_05_INT           47
+#define SE_GPI_04_INT           46
+#define SE_GPI_03_INT           45
+#define SE_GPI_02_INT           44
+#define SE_GPI_01_INT           43
+#define SE_GPI_00_INT           42
+#define SE_SYSCLKEN_PIN_INT     41
+#define SE_SPI1_DATAIN_INT      40
+#define SE_GPI_07_INT           39
+#define SE_SPI2_DATAIN_INT      38
+#define SE_GPI_10_INT           37
+#define SE_GPI_09_INT           36
+#define SE_GPI_08_INT           35
+/*34-32 unused*/
+
+/* Start Enable Internal Interrupts - table 57 page 65 */
+
+#define SE_INT_BASE_INT   0
+
+#define SE_TS_IRQ               31
+#define SE_TS_P_INT             30
+#define SE_TS_AUX_INT           29
+/*27-28 unused*/
+#define SE_USB_AHB_NEED_CLK_INT 26
+#define SE_MSTIMER_INT          25
+#define SE_RTC_INT              24
+#define SE_USB_NEED_CLK_INT     23
+#define SE_USB_INT              22
+#define SE_USB_I2C_INT          21
+#define SE_USB_OTG_TIMER_INT    20
+
+#endif /* __PNX4008_IRQS_h__ */
diff --git a/include/asm-arm/arch-pnx4008/memory.h b/include/asm-arm/arch-pnx4008/memory.h
new file mode 100644 (file)
index 0000000..0d8268a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-pnx4008/memory.h
+ *
+ * Copyright (c) 2005 Philips Semiconductors
+ * Copyright (c) 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.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET     (0x80000000)
+
+#define __virt_to_bus(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __bus_to_virt(x) ((x) + PAGE_OFFSET - PHYS_OFFSET)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/param.h b/include/asm-arm/arch-pnx4008/param.h
new file mode 100644 (file)
index 0000000..95d5f54
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *  linux/include/asm-arm/arch-pnx4008/param.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define HZ 100
diff --git a/include/asm-arm/arch-pnx4008/platform.h b/include/asm-arm/arch-pnx4008/platform.h
new file mode 100644 (file)
index 0000000..485a365
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * include/asm-arm/arch-pnx4008/platfrom.h
+ *
+ * PNX4008 Base addresses - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+
+#ifndef __ASM_ARCH_PLATFORM_H__
+#define __ASM_ARCH_PLATFORM_H__
+
+#define PNX4008_IRAM_BASE              0x08000000
+#define PNX4008_IRAM_SIZE              0x00010000
+#define PNX4008_YUV_SLAVE_BASE         0x10000000
+#define PNX4008_DUM_SLAVE_BASE         0x18000000
+#define PNX4008_NDF_FLASH_BASE         0x20020000
+#define PNX4008_SPI1_BASE              0x20088000
+#define PNX4008_SPI2_BASE              0x20090000
+#define PNX4008_SD_CONFIG_BASE         0x20098000
+#define PNX4008_FLASH_DATA             0x200B0000
+#define PNX4008_MLC_FLASH_BASE         0x200B8000
+#define PNX4008_JPEG_CONFIG_BASE       0x300A0000
+#define PNX4008_DMA_CONFIG_BASE                0x31000000
+#define PNX4008_USB_CONFIG_BASE                0x31020000
+#define PNX4008_SDRAM_CFG_BASE         0x31080000
+#define PNX4008_AHB2FAB_BASE           0x40000000
+#define PNX4008_PWRMAN_BASE            0x40004000
+#define PNX4008_INTCTRLMIC_BASE                0x40008000
+#define PNX4008_INTCTRLSIC1_BASE       0x4000C000
+#define PNX4008_INTCTRLSIC2_BASE       0x40010000
+#define PNX4008_HSUART1_BASE           0x40014000
+#define PNX4008_HSUART2_BASE           0x40018000
+#define PNX4008_HSUART7_BASE           0x4001C000
+#define PNX4008_RTC_BASE               0x40024000
+#define PNX4008_PIO_BASE               0x40028000
+#define PNX4008_MSTIMER_BASE           0x40034000
+#define PNX4008_HSTIMER_BASE           0x40038000
+#define PNX4008_WDOG_BASE              0x4003C000
+#define PNX4008_DEBUG_BASE             0x40040000
+#define PNX4008_TOUCH1_BASE            0x40048000
+#define PNX4008_KEYSCAN_BASE           0x40050000
+#define PNX4008_UARTCTRL_BASE          0x40054000
+#define PNX4008_PWM_BASE               0x4005C000
+#define PNX4008_UART3_BASE             0x40080000
+#define PNX4008_UART4_BASE             0x40088000
+#define PNX4008_UART5_BASE             0x40090000
+#define PNX4008_UART6_BASE             0x40098000
+#define PNX4008_I2C1_BASE              0x400A0000
+#define PNX4008_I2C2_BASE              0x400A8000
+#define PNX4008_MAGICGATE_BASE         0x400B0000
+#define PNX4008_DUMCONF_BASE           0x400B8000
+#define PNX4008_DUM_MAINCFG_BASE               0x400BC000
+#define PNX4008_DSP_BASE               0x400C0000
+#define PNX4008_PROFCOUNTER_BASE       0x400C8000
+#define PNX4008_CRYPTO_BASE            0x400D0000
+#define PNX4008_CAMIFCONF_BASE         0x400D8000
+#define PNX4008_YUV2RGB_BASE           0x400E0000
+#define PNX4008_AUDIOCONFIG_BASE       0x400E8000
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/pm.h b/include/asm-arm/arch-pnx4008/pm.h
new file mode 100644 (file)
index 0000000..c660486
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * include/asm-arm/arch-pnx4008/pm.h
+ *
+ * PNX4008 Power Management Routiness - header file
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_ARCH_PNX4008_PM_H
+#define __ASM_ARCH_PNX4008_PM_H
+
+#ifndef __ASSEMBLER__
+#include "irq.h"
+#include "irqs.h"
+#include "clock.h"
+
+extern void pnx4008_pm_idle(void);
+extern void pnx4008_pm_suspend(void);
+extern unsigned int pnx4008_cpu_suspend_sz;
+extern void pnx4008_cpu_suspend(void);
+extern unsigned int pnx4008_cpu_standby_sz;
+extern void pnx4008_cpu_standby(void);
+
+extern int pnx4008_startup_pll(struct clk *);
+extern int pnx4008_shutdown_pll(struct clk *);
+
+static inline void start_int_umask(u8 irq)
+{
+       __raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
+                    START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_mask(u8 irq)
+{
+       __raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
+                    ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_ack(u8 irq)
+{
+       __raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
+}
+
+static inline void start_int_set_falling_edge(u8 irq)
+{
+       __raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
+                    ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+static inline void start_int_set_rising_edge(u8 irq)
+{
+       __raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
+                    START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+#endif                         /* ASSEMBLER */
+#endif                         /* __ASM_ARCH_PNX4008_PM_H */
diff --git a/include/asm-arm/arch-pnx4008/system.h b/include/asm-arm/arch-pnx4008/system.h
new file mode 100644 (file)
index 0000000..6e3da70
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * linux/include/asm-arm/arch-pnx4008/system.h
+ *
+ * Copyright (C) 2003 Philips Semiconductors
+ * Copyright (C) 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/arch/platform.h>
+
+static void arch_idle(void)
+{
+       cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+       cpu_reset(0);
+}
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/timex.h b/include/asm-arm/arch-pnx4008/timex.h
new file mode 100644 (file)
index 0000000..ee470a3
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * include/asm-arm/arch-pnx4008/timex.h
+ *
+ * PNX4008 timers header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PNX4008_TIMEX_H
+#define __PNX4008_TIMEX_H
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#define CLOCK_TICK_RATE                1000000
+
+#define TICKS2USECS(x) (x)
+
+/* MilliSecond Timer - Chapter 21 Page 202 */
+
+#define MSTIM_INT     IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0))
+#define MSTIM_CTRL    IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4))
+#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8))
+#define MSTIM_MCTRL   IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14))
+#define MSTIM_MATCH0  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18))
+#define MSTIM_MATCH1  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c))
+
+/* High Speed Timer - Chpater 22, Page 205 */
+
+#define HSTIM_INT     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0))
+#define HSTIM_CTRL    IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4))
+#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8))
+#define HSTIM_PMATCH  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC))
+#define HSTIM_PCOUNT  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10))
+#define HSTIM_MCTRL   IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14))
+#define HSTIM_MATCH0  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18))
+#define HSTIM_MATCH1  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c))
+#define HSTIM_MATCH2  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20))
+#define HSTIM_CCR     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28))
+#define HSTIM_CR0     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C))
+#define HSTIM_CR1     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30))
+
+/* IMPORTANT: both timers are UPCOUNTING */
+
+/* xSTIM_MCTRL bit definitions */
+#define MR0_INT        1
+#define RESET_COUNT0   (1<<1)
+#define STOP_COUNT0    (1<<2)
+#define MR1_INT        (1<<3)
+#define RESET_COUNT1   (1<<4)
+#define STOP_COUNT1    (1<<5)
+#define MR2_INT        (1<<6)
+#define RESET_COUNT2   (1<<7)
+#define STOP_COUNT2    (1<<8)
+
+/* xSTIM_CTRL bit definitions */
+#define COUNT_ENAB     1
+#define RESET_COUNT    (1<<1)
+#define DEBUG_EN       (1<<2)
+
+/* xSTIM_INT bit definitions */
+#define MATCH0_INT     1
+#define MATCH1_INT     (1<<1)
+#define MATCH2_INT     (1<<2)
+#define RTC_TICK0      (1<<4)
+#define RTC_TICK1      (1<<5)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/uncompress.h b/include/asm-arm/arch-pnx4008/uncompress.h
new file mode 100644 (file)
index 0000000..8fa4d24
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  linux/include/asm-arm/arch-pnx4008/uncompress.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2006 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.
+ *
+ * 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
+ */
+
+#define UART5_BASE 0x40090000
+
+#define UART5_DR    (*(volatile unsigned char *) (UART5_BASE))
+#define UART5_FR    (*(volatile unsigned char *) (UART5_BASE + 18))
+
+static __inline__ void putc(char c)
+{
+       while (UART5_FR & (1 << 5))
+               barrier();
+
+       UART5_DR = c;
+}
+
+/*
+ * This does not append a newline
+ */
+static inline void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-pnx4008/vmalloc.h b/include/asm-arm/arch-pnx4008/vmalloc.h
new file mode 100644 (file)
index 0000000..140d925
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-pnx4008/vmalloc.h
+ *
+ * Author: Vitaly Wool <source@mvista.com>
+ *
+ * 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
index e7ef497417bbeef88690495343a05ea933d1a285..b6952534a4e16039775ee1ba60399e548c8e480c 100644 (file)
@@ -15,7 +15,6 @@
  *             Changes for 2.6 kernel.
  */
 
-#include <linux/config.h>
 
 /*
  * Note: this file must be safe to include in assembly files
index 67af238a8f8ed8cf7165e80ba02b7b01779da553..f3bc70eee35b3b7aabc012af82170db1f1133ded 100644 (file)
@@ -10,7 +10,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PXA27x
 #define PXA_IRQ_SKIP   0
index 7da89569061eb025163eff9745437971c6459743..e848a47128cdd42b3a9bed8b48b3fc316ff1d2d4 100644 (file)
@@ -11,6 +11,8 @@ struct pxaohci_platform_data {
 #define PMM_NPS_MODE           1
 #define PMM_GLOBAL_MODE        2
 #define PMM_PERPORT_MODE       3
+
+       int power_budget;
 };
 
 extern void pxa_set_ohci_info(struct pxaohci_platform_data *info);
index c8f53a71c076b84210ab54320979aa955e623c9c..6650d4decaeb2e3cd68df4939c266551f7ec7c85 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef __PXA_REGS_H
 #define __PXA_REGS_H
 
-#include <linux/config.h>
 
 /*
  * PXA Chip selects
index aa125ec56a32fcb62ce83a65727e24bd4a911083..2473bb51d0a6a21a0cfac4349a856328d0b57fd1 100644 (file)
@@ -10,7 +10,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/config.h>
 
 #if defined(CONFIG_PXA25x)
 /* PXA250/210 timer base */
index fc87783e8e8b7a308812e7cc9b76c13a16050346..515819efd0469a726100632070af7a8ee4e5243b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef ASMARM_ARCH_SMP_H
 #define ASMARM_ARCH_SMP_H
 
-#include <linux/config.h>
 
 #include <asm/hardware/gic.h>
 
index b011e14f3bc663d6858fb7afc2811eaf7395c3d5..72964f9b8414e9b2fd78e15a59280f2789cd2503 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-#include <linux/config.h>
 #include <linux/sysdev.h>
 #include "hardware.h"
 
index c380d264a8479137fe2a979b91d9969fc64cac03..5e4c8c37bc66d86fe33980604c5fd6dec254cea2 100644 (file)
 #define S3C24XX_SZ_IIS    SZ_1M
 
 /* GPIO ports */
-#define S3C24XX_VA_GPIO           S3C2410_ADDR(0x00E00000)
+
+/* the calculation for the VA of this must ensure that
+ * it is the same distance apart from the UART in the
+ * phsyical address space, as the initial mapping for the IO
+ * is done as a 1:1 maping. This puts it (currently) at
+ * 0xF6800000, which is not in the way of any current mapping
+ * by the base system.
+*/
+
 #define S3C2400_PA_GPIO           (0x15600000)
 #define S3C2410_PA_GPIO           (0x56000000)
+#define S3C24XX_VA_GPIO           ((S3C2410_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
 #define S3C24XX_SZ_GPIO           SZ_1M
 
 /* RTC */
index 34360706e0169cbffa8528c6f9da72b137b3273b..6c92faffe98562266e22fc80a04f2c2f009be042 100644 (file)
@@ -114,7 +114,7 @@ s3c2410_get_pll(unsigned int pllval, unsigned int baseclk)
 
 #endif /* __ASSEMBLY__ */
 
-#ifdef CONFIG_CPU_S3C2440
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
 
 /* extra registers */
 #define S3C2440_CAMDIVN            S3C2410_CLKREG(0x18)
@@ -136,7 +136,9 @@ s3c2410_get_pll(unsigned int pllval, unsigned int baseclk)
 #define S3C2440_CAMDIVN_HCLK4_HALF   (1<<9)
 #define S3C2440_CAMDIVN_DVSEN        (1<<12)
 
-#endif /* CONFIG_CPU_S3C2440 */
+#define S3C2442_CAMDIVN_CAMCLK_DIV3  (1<<5)
+
+#endif /* CONFIG_CPU_S3C2440 or CONFIG_CPU_S3C2442 */
 
 
 #endif /* __ASM_ARM_REGS_CLOCK */
index d2574084697f845e70330d47a9c45eab1ce4ff16..5f10334f06bf2861e9463aac9c2c8ed9906a0bd5 100644 (file)
 #define S3C2410_GPD0_OUTP      (0x01 << 0)
 #define S3C2410_GPD0_VD8       (0x02 << 0)
 #define S3C2400_GPD0_VFRAME    (0x02 << 0)
+#define S3C2442_GPD0_nSPICS1   (0x03 << 0)
 
 #define S3C2410_GPD1            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 1)
 #define S3C2410_GPD1_INP       (0x00 << 2)
 #define S3C2410_GPD1_OUTP      (0x01 << 2)
 #define S3C2410_GPD1_VD9       (0x02 << 2)
 #define S3C2400_GPD1_VM                (0x02 << 2)
+#define S3C2442_GPD1_SPICLK1   (0x03 << 2)
 
 #define S3C2410_GPD2            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 2)
 #define S3C2410_GPD2_INP       (0x00 << 4)
 #define S3C2410_GPG12_OUTP    (0x01 << 24)
 #define S3C2410_GPG12_EINT20  (0x02 << 24)
 #define S3C2410_GPG12_XMON    (0x03 << 24)
+#define S3C2442_GPG12_nSPICS0 (0x03 << 24)
 
 #define S3C2410_GPG13         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13)
 #define S3C2410_GPG13_INP     (0x00 << 26)
 #define S3C2410_GPH9_INP      (0x00 << 18)
 #define S3C2410_GPH9_OUTP     (0x01 << 18)
 #define S3C2410_GPH9_CLKOUT0  (0x02 << 18)
+#define S3C2442_GPH9_nSPICS0  (0x03 << 18)
 
 #define S3C2410_GPH10         S3C2410_GPIONO(S3C2410_GPIO_BANKH, 10)
 #define S3C2410_GPH10_INP     (0x00 << 20)
 #define S3C2410_GSTATUS1_IDMASK           (0xffff0000)
 #define S3C2410_GSTATUS1_2410     (0x32410000)
 #define S3C2410_GSTATUS1_2440     (0x32440000)
+#define S3C2410_GSTATUS1_2442     (0x32440aaa)
 
 #define S3C2410_GSTATUS2_WTRESET   (1<<2)
 #define S3C2410_GSTATUS2_OFFRESET  (1<<1)
index a6f6a0e44afaf2e818a716288fc7ba34e1316ffc..8e152a05e53369f51094e923dd92c642ca796631 100644 (file)
@@ -22,7 +22,6 @@
 #ifndef __ASM_ARCH_UNCOMPRESS_H
 #define __ASM_ARCH_UNCOMPRESS_H
 
-#include <linux/config.h>
 
 /* defines for UART registers */
 #include "asm/arch/regs-serial.h"
@@ -82,7 +81,8 @@ static void putc(int ch)
                while (1) {
                        level = uart_rd(S3C2410_UFSTAT);
 
-                       if (cpuid == S3C2410_GSTATUS1_2440) {
+                       if (cpuid == S3C2410_GSTATUS1_2440 ||
+                           cpuid == S3C2410_GSTATUS1_2442) {
                                level &= S3C2440_UFSTAT_TXMASK;
                                level >>= S3C2440_UFSTAT_TXSHIFT;
                        } else {
@@ -130,7 +130,7 @@ static void arch_decomp_wdog_start(void)
 {
        __raw_writel(WDOG_COUNT, S3C2410_WTDAT);
        __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
-       __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
+       __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON);
 }
 
 #else
index 1f59b368c3f68334364997b0c500a1e3862bceac..d6a1bb5b494484065aee1d5dfab8877a108c7750 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_ARCH_ASSABET_H
 #define __ASM_ARCH_ASSABET_H
 
-#include <linux/config.h>
 
 /* System Configuration Register flags */
 
index 356d5ba88991cf7fb4018e8b72bbb66e6dc6a03f..9a19c3d07c1e50f95ce634b1e7dc3e773fd2846a 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _INCLUDE_CERF_H_
 #define _INCLUDE_CERF_H_
 
-#include <linux/config.h>
 
 #define CERF_ETH_IO                    0xf0000000
 #define CERF_ETH_IRQ IRQ_GPIO26
index d49e5ff63ca433ab4917717c1767640c8c1151c1..14a344aa3cc72539e531a688dda7324c8b0763de 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_COLLIE_H
 #define __ASM_ARCH_COLLIE_H
 
-#include <linux/config.h>
 
 #define COLLIE_SCP_CHARGE_ON   SCOOP_GPCR_PA11
 #define COLLIE_SCP_DIAG_BOOT1  SCOOP_GPCR_PA12
index 02575d72ac6bcd9548c870ac5987aa71a95d7bc5..6b7917a2e77a957acdb0a0cb55f4718ea2c2d1e4 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-#include <linux/config.h>
 #include "hardware.h"
 
 
index ee008a5484f316a64afc59046985b9e48f0e1d66..1abd7cfc8bcef4817cc19eaa2573ee18dcf5695a 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <linux/config.h>
 
 #define UNCACHEABLE_ADDR       0xfa050000
 
index 2153538069c7999332e3ffa1279d2dc22cf28e47..98b10bcf9f1b87d44058bed3c1f9753415fd1de8 100644 (file)
@@ -9,7 +9,6 @@
  *              architectures.
  */
 
-#include <linux/config.h>
 #include <asm/irq.h>
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
index eabd3be3d7052aae72548f8cc1a2cded267ad32b..d7940683efb18c8175c7b836901a0680c5f650a5 100644 (file)
@@ -7,7 +7,6 @@
  *
  * 2001/11/14  RMK     Cleaned up and standardised a lot of the IRQs.
  */
-#include <linux/config.h>
 
 #define        IRQ_GPIO0               0
 #define        IRQ_GPIO1               1
index a29fac1387caf7324016a7d3607568924f71294f..1ff172dc8e33f21fd7375c359a29d31da831465d 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <linux/config.h>
 #include <asm/sizes.h>
 
 /*
index 0f0612f79b2b0924476c0433add323028aa0372e..aef91e3b63fe60dc1eb948a23e3bf85dc0ac6a3e 100644 (file)
@@ -3,7 +3,6 @@
  *
  * Copyright (c) 1999 Nicolas Pitre <nico@cam.org>
  */
-#include <linux/config.h>
 #include <asm/hardware.h>
 
 static inline void arch_idle(void)
index 3d7283d84405e58b1249a562e4839570170928ec..4b0ce3e7de9a4267088ab585e46232214b139879 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __ASM_ARM_ATOMIC_H
 #define __ASM_ARM_ATOMIC_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 
 typedef struct { volatile int counter; } atomic_t;
index 5ab8216f5204aa7f204cd5b34fffb228428ff618..7fb02138f585985dd810407a82a8643bb3874d9f 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASMARM_BUG_H
 
 #include <linux/config.h>
-#include <linux/stddef.h>
 
 #ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
index 746be56b1b705e9a88819868e2fe01f44527c8fc..fe0c744e02666caac87b43d526e87b7a24f87693 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASMARM_CACHEFLUSH_H
 #define _ASMARM_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 
index 751bc7462074fab8f617ba2c66fc4da19e61b92b..715426b9b08ef355728a7ce9ebde64b5d522ce14 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __ASM_ARM_CPU_H
 #define __ASM_ARM_CPU_H
 
-#include <linux/config.h>
 #include <linux/percpu.h>
 
 struct cpuinfo_arm {
index 63ca7412a4623984777fcbec72bff0dfa32cacb1..55eb4dc3253ddfd1dea70d7900b2be0a1caa9ed9 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/mm.h> /* need struct page */
 
 #include <asm/scatterlist.h>
index 49c01e2bf7c8f7b6a7afad9fc4ba71ca60240329..9f2c5305c26014a9aea95faaf73a9c82c1260201 100644 (file)
@@ -3,7 +3,6 @@
 
 typedef unsigned int dmach_t;
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
 #include <asm/scatterlist.h>
index 2d44b42d1847871a8b6fcc22238eeaa2507ee02a..71061ca5c5d0dc9266a6e7f72d09f3a0ac44ff4f 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASMARM_ELF_H
 #define __ASMARM_ELF_H
 
-#include <linux/config.h>
 
 /*
  * ELF register definitions..
index 52bae088a185c04fb95186acde501e53e92e1817..132c3c5628b2a4b4d5be60bee7f1a41f04e627d0 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __ASM_ARM_FPSTATE_H
 #define __ASM_ARM_FPSTATE_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
index 223e0d6c41be4b7ead21f13a3e8ebdea4f1da028..0cc5d3b10ce2fb888a7735eb17e1e65a620514aa 100644 (file)
@@ -15,7 +15,6 @@
  */
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifdef __STDC__
 #define ____glue(name,fn)      name##fn
index 1cbb173bf5b108b2d136a78961ed7ffc873dc276..182310b991950b6e22d69930b376d3337335d80a 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/cache.h>
 #include <linux/threads.h>
 #include <asm/irq.h>
index 6685e3fb97b1fe7afece91656f0fb6ede8bbfc83..546f7077be9c42313dbae0798c59a8c8f50933a1 100644 (file)
@@ -18,7 +18,6 @@
 #define DC21285_PCI_IO                 0x7c000000
 #define DC21285_PCI_MEM                        0x80000000
 
-#include <linux/config.h>
 #ifndef __ASSEMBLY__
 #include <asm/hardware.h>
 #define DC21285_IO(x)          ((volatile unsigned long *)(ARMCSR_BASE+(x)))
index 82fa2c279a18027cb04244a31fa0e2ca6be294d9..396e55ad06c6afe41fb754b548d257ca04c0c1a7 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef __ASMARM_HARDWARE_IOMD_H
 #define __ASMARM_HARDWARE_IOMD_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
index 88ce4124f85456d65705e3759b1231dd52b612cb..12290ea55801c101341e0707c233bf9fb4e082ab 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef ASM_ARM_LEDS_H
 #define ASM_ARM_LEDS_H
 
-#include <linux/config.h>
 
 typedef enum {
        led_idle_start,
index 98f4b0cb883ca17c8ca02a4caa250e92ee63f7ec..a0269de12079b88d987b19a1b8de4081977547c6 100644 (file)
@@ -7,7 +7,6 @@
  *
  *  Low level machine dependent UART functions.
  */
-#include <linux/config.h>
 
 struct uart_port;
 
index 9162018585df7ae5fd747e3f2af33fc9b5aae338..20c22bb218d92493240fae963cd0816d67d514a4 100644 (file)
@@ -7,7 +7,6 @@
  *
  * Low level machine dependent UART functions.
  */
-#include <linux/config.h>
 
 struct uart_port;
 struct uart_info;
index 96c6db7dd0e1928e25b96e9b0e87fb64c7f113ce..9f28073559e8f6140788546012acecdd16479330 100644 (file)
@@ -50,6 +50,7 @@ struct sys_timer {
 #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 */
index 20928940759545f0caefc7ed142a9bd308b8802f..731e321a57d1722779b93babdfae17742aca8440 100644 (file)
@@ -22,7 +22,6 @@
 #define UL(x) (x)
 #endif
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/arch/memory.h>
 #include <asm/sizes.h>
index a404d2bf0c68b9c0818efc75ca11571133444a77..66cfeb5290ea5c0e077f67db6bd154c5768ab9b1 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASMARM_PAGE_H
 #define _ASMARM_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT             12
index ead3ced38cb8f4aa2b20cae06d982291f5dbeb6a..f21abd4ddac61b8915fb6c437d45378c48b38b0f 100644 (file)
@@ -2,7 +2,6 @@
 #define ASMARM_PCI_H
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <asm-generic/pci-dma-compat.h>
 
 #include <asm/hardware.h> /* for PCIBIOS_MIN_* */
index 106045edb8627846336531a560cb32b5608e85d1..e9310895e79dae741c6104ba85f63a5afc660cb2 100644 (file)
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * Work out if we need multiple CPU support
index 77adb7fa169bb291368589f4fc206821f2988707..2bebe3dc0a30c5a8be30081d11f2e14fa798f4da 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __ASM_ARM_PTRACE_H
 #define __ASM_ARM_PTRACE_H
 
-#include <linux/config.h>
 
 #define PTRACE_GETREGS         12
 #define PTRACE_SETREGS         13
index fe45f7f612230be865e49497809f5ecf1aa68021..f67acce387e7fc1bc0dd18326c5633e4fd2314c2 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __ASM_ARM_SMP_H
 #define __ASM_ARM_SMP_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/thread_info.h>
index 95b3abf4851bb9cc70596edd3a239076910939ee..9c744ae6c6e3b8b9fb47c84524ee0e4c2fb200f1 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #define CPU_ARCH_UNKNOWN       0
 #define CPU_ARCH_ARMv3         1
@@ -127,6 +126,12 @@ static inline int cpu_is_xsc3(void)
 }
 #endif
 
+#if !defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_CPU_XSC3)
+#define        cpu_is_xscale() 0
+#else
+#define        cpu_is_xscale() 1
+#endif
+
 #define set_cr(x)                                      \
        __asm__ __volatile__(                           \
        "mcr    p15, 0, %0, c1, c0, 0   @ set CR"       \
index 728992451dd18243a962a617b81c49506cb915b5..d97fc76189a5e5c95570424a19e0e0f5790a8fea 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASMARM_TLBFLUSH_H
 #define _ASMARM_TLBFLUSH_H
 
-#include <linux/config.h>
 
 #ifndef CONFIG_MMU
 
index cbf39a56dbe768db84f96396ebf77823cc525c3d..1e891f860ef3ef4f430d6757dc7c6786977de882 100644 (file)
@@ -13,8 +13,6 @@
 #ifndef __ASM_ARM_UNISTD_H
 #define __ASM_ARM_UNISTD_H
 
-#include <linux/linkage.h>
-
 #define __NR_OABI_SYSCALL_BASE 0x900000
 
 #if defined(__thumb__) || defined(__ARM_EABI__)
 #undef __NR_ipc
 #endif
 
+#ifdef __KERNEL__
+#include <linux/linkage.h>
+
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
 
@@ -526,7 +527,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
   __syscall_return(type,__res);                                                \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
@@ -547,7 +547,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_SOCKETCALL
 #endif
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -571,7 +570,7 @@ asmlinkage long sys_rt_sigaction(int sig,
                                struct sigaction __user *oact,
                                size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -581,4 +580,5 @@ asmlinkage long sys_rt_sigaction(int sig,
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* __ASM_ARM_UNISTD_H */
index 1552c8653990e46bbba426c3dda5e0d05fa2190c..97e944fe1cff4c9bf4d9c0eb7603fca6e43bf916 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef __ASM_ARM_ATOMIC_H
 #define __ASM_ARM_ATOMIC_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 #error SMP is NOT supported
index 7177c7399967028cb891fdd7b8382fe810eadbde..8545d58b0475ba5646b20df3b00fb7f80bbf2e44 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASMARM_BUG_H
 #define _ASMARM_BUG_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
index 995e223e43a130fd3bcd2d9bd76126e1614f4211..4326ba85eb7244a7e7b0ff35d7098ab76faa7c40 100644 (file)
@@ -3,7 +3,6 @@
 
 typedef unsigned int dmach_t;
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
 #include <asm/memory.h>
index 87c19d2bb6a8035df4c4f747f8214a76ad47f9b8..e717742ffce06905a0231f4e62e78b7d3568f054 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/cache.h>
 #include <linux/threads.h>
 #include <asm/irq.h>
index 82fc55e2a009a8f12dbe1202ca221d8d9791d93e..801df0bde8b7fc8bea4279463b5a862d5d6dae2b 100644 (file)
@@ -16,7 +16,6 @@
 #ifndef __ASM_HARDWARE_H
 #define __ASM_HARDWARE_H
 
-#include <linux/config.h>
 
 
 /*
index 02f94d88a1247bba02ec6dd9e0f61967151d4ffc..2aa033bd0678b07ba8936aedb375a5a21b757df1 100644 (file)
@@ -22,7 +22,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
 #include <asm/memory.h>
index 88ce4124f85456d65705e3759b1231dd52b612cb..12290ea55801c101341e0707c233bf9fb4e082ab 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef ASM_ARM_LEDS_H
 #define ASM_ARM_LEDS_H
 
-#include <linux/config.h>
 
 typedef enum {
        led_idle_start,
index b34045b78128e534887cafdc97875bc7c43fc5ce..0aeaedcbac96622531b904a941f2780f75e794e0 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef __ASM_ARM_MACH_TYPE_H
 #define __ASM_ARM_MACH_TYPE_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 extern unsigned int __machine_arch_type;
index d3f23ac4d468fc748c3f366dbd383b2196ace705..fa19de28fda04bdaa04adc7f330940dfc1efa2c6 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASMARM_PAGE_H
 #define _ASMARM_PAGE_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
index a590250277f811631f2ccced4618410404125d3a..19ac9101a6bbedf5baa53bd351a97fac2dc509c1 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <asm/memory.h>
 
 /*
index 5fc747d1b501f74c62b5f4f4ebb5e3474a5c0998..dd86a716cb0b3c98478b2567d5ad6216d0ad0b59 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef __ASM_SERIAL_H
 #define __ASM_SERIAL_H
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
index 5ca771631fd8de1701c0e76af28c71794c02dd21..38349ec8b61b4f69692e900e6f28d1504cf2061c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 #error SMP not supported
index cad250c7b9ec69b8092b72661903128eef56d2f8..81dca90d9a3f930e43bf8f0199b92e63c027199c 100644 (file)
@@ -11,7 +11,6 @@
  *   04-04-1998 PJB     Merged arc and a5k versions
  */
 
-#include <linux/config.h>
 
 #if defined(CONFIG_ARCH_A5K)
 #define IRQ_PRINTER             0
index 702884926a55931254ad69f3aadd968845054596..d1f69d7061986b4f6ce2588e949205dade591a9d 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * This is used to ensure the compiler did actually allocate the register we
index be4c2fb9c04944cdf9a982f4a3b1412001e68edb..70eb6d91cfd0c85448477479fa0d2fca848dfaf9 100644 (file)
@@ -14,8 +14,6 @@
 #ifndef __ASM_ARM_UNISTD_H
 #define __ASM_ARM_UNISTD_H
 
-#include <linux/linkage.h>
-
 #define __NR_SYSCALL_BASE      0x900000
 
 /*
 #define __ARM_NR_cacheflush            (__ARM_NR_BASE+2)
 #define __ARM_NR_usr26                 (__ARM_NR_BASE+3)
 
+#ifdef __KERNEL__
+#include <linux/linkage.h>
+
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
 
@@ -443,7 +444,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
   __syscall_return(type,__res);                                                \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
@@ -462,7 +462,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -486,7 +485,7 @@ asmlinkage long sys_rt_sigaction(int sig,
                                struct sigaction __user *oact,
                                size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -496,4 +495,5 @@ asmlinkage long sys_rt_sigaction(int sig,
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* __ASM_ARM_UNISTD_H */
index dd39198ec67d31cea570d54e7eec84db883007f3..11ef5b53d84e684b37b128de724210e966c21ceb 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_ARCH_CRIS_IO_H
 
 #include <asm/arch/svinto.h>
-#include <linux/config.h>
 
 /* Etrax shadow registers - which live in arch/cris/kernel/shadows.c */
 
index 407e6e68f49e636e09efdd4ab043d7a656d31a36..7d8307aed7f31995cf40e19103175663fea52e16 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _CRIS_ARCH_PAGE_H
 #define _CRIS_ARCH_PAGE_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 
index 1ac7b639b1b01670c59dca8323c5e17556b65987..4a9cd36c9e16e58b16e0dbb6f8e3a2db31145b86 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_CRIS_ARCH_SYSTEM_H
 #define __ASM_CRIS_ARCH_SYSTEM_H
 
-#include <linux/config.h>
 
 /* read the CPU version register */
 
index 043c9ce5294e9192ee00e0aa75edf9eb94f4c33e..5efe4d9490018f6145451f84fec1a781c9be2b8b 100644 (file)
@@ -4,7 +4,6 @@
 #include <asm/arch/hwregs/reg_map.h>
 #include <asm/arch/hwregs/reg_rdwr.h>
 #include <asm/arch/hwregs/gio_defs.h>
-#include <linux/config.h>
 
 enum crisv32_io_dir
 {
index d35aa8174c2f58ed60019a831969974cec4c52c4..eeb0a80262c88ed0df39c8649639850a0d88b789 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_ARCH_IRQ_H
 #define _ASM_ARCH_IRQ_H
 
-#include <linux/config.h>
 #include "hwregs/intr_vect.h"
 
 /* Number of non-cpu interrupts. */
index 77827bc17cca08844c73bcfee002ef0dea3ceca3..fa454fe1242521d41965fa92a5d6eeb5410a7476 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_CRIS_ARCH_PAGE_H
 #define _ASM_CRIS_ARCH_PAGE_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 
index 32bf2e538ced1913b7618e2b13360a09ee65bb9a..5553b0cd02bf0f2f473554e5b27cd2f68fdd9b6f 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_CRIS_ARCH_PROCESSOR_H
 #define _ASM_CRIS_ARCH_PROCESSOR_H
 
-#include <linux/config.h>
 
 /* Return current instruction pointer. */
 #define current_text_addr() \
index a3d75d581e2f5d20942eeee48df4dde3a3737409..d20e2d6d64a362c1d4709b850e87b88ca6a35b6e 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_CRIS_ARCH_SYSTEM_H
 #define _ASM_CRIS_ARCH_SYSTEM_H
 
-#include <linux/config.h>
 
 /* Read the CPU version register. */
 static inline unsigned long rdvr(void)
index 2b577cde17ebda58ad59f1df07ae1bc4c770ed4e..10ce36cf79a911f6ae4d55e7eac35f812710b50c 100644 (file)
@@ -32,7 +32,6 @@
 /* We have dependencies all over the place for the host system
    for xsim being a linux system, so let's not pretend anything
    else with #ifdef:s here until fixed.  */
-#include <linux/config.h>
 #include <linux/limits.h>
 
 /* Maybe do sanity checking if file input. */
index 80ee10f70d43956d52d8f4d46a42f3cb7ce4fcb6..5d0028dba7c69198763558f7383a0b0c7ee05c09 100644 (file)
@@ -25,7 +25,6 @@
 #ifndef _ASM_ETRAXGPIO_H
 #define _ASM_ETRAXGPIO_H
 
-#include <linux/config.h>
 /* etraxgpio _IOC_TYPE, bits 8 to 15 in ioctl cmd */
 #ifdef CONFIG_ETRAX_ARCH_V10
 #define ETRAXGPIO_IOCTYPE 43
index 69522028baa5710c962eccb265f504aae9670fd1..a3a77132ce326023a525f743dfe07962fccc1381 100644 (file)
@@ -5,7 +5,6 @@
  * This may be useful in other OS than Linux so use 2 space indentation...
  * Copyright (C) 2000, 2002 Axis Communications AB
  */
-#include <linux/config.h>
 #include <linux/time.h> /* struct timeval */
 #include <linux/timex.h>
 
index 3787633e6209649a47c0f80b2ca367583dd159a8..81832e9e157f89efe4bfc6a3a00df28f4376e3e3 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _CRIS_PAGE_H
 #define _CRIS_PAGE_H
 
-#include <linux/config.h>
 #include <asm/arch/page.h>
 
 /* PAGE_SHIFT determines the page size */
index 2064bc1de074e118f709ea992a8f57e2bcc38a09..b2ac8a331da1f9d17fdaf7c60a80b4b9a6ba895b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_CRIS_PCI_H
 #define __ASM_CRIS_PCI_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 #include <linux/mm.h>          /* for struct page */
index 70a832514f62ba7cda4097e5de7b49c1e73d3f0d..5d76c1c0d6c9b92154fc38841d636929c4dcbec4 100644 (file)
@@ -9,7 +9,6 @@
 #include <asm-generic/pgtable-nopmd.h>
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <asm/mmu.h>
 #endif
index 961e2bceadbc645915fd1379ed939cf008db19ff..568da1deceb908d9f89f341b810954b3958d1487 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __ASM_CRIS_PROCESSOR_H
 #define __ASM_CRIS_PROCESSOR_H
 
-#include <linux/config.h>
 #include <asm/system.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
index 97c13039834ac73c436b82c7adc0e102aad593ff..cb4bf9217fee6e1155c70966280e32f776f60c68 100644 (file)
@@ -4,7 +4,6 @@
 #define __RTC_H__
 
 
-#include <linux/config.h>
 
 #ifdef CONFIG_ETRAX_DS1302
    /* Dallas DS1302 clock/calendar register numbers. */
index c52238005b5592539be59892b8ef61a4bf1a3380..0569612477e3eddc1df7cbd7132b5238f19a14be 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _CRIS_TLBFLUSH_H
 #define _CRIS_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
 #include <asm/pgtable.h>
index bb2dfe480213571dbaf0776892c0516af6b76a9d..c2954e90aa24f9caa311285aff06f3dca485d5e1 100644 (file)
 #define __NR_request_key       287
 #define __NR_keyctl            288
 
-#define NR_syscalls 289
+#ifdef __KERNEL__
 
+#define NR_syscalls 289
 
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -379,12 +379,10 @@ asmlinkage long sys_rt_sigaction(int sig,
  * complaints.  We don't want to use -fno-builtin, so just use a
  * different name when in the kernel.
  */
-#ifdef __KERNEL__
 #define _exit kernel_syscall_exit
-#endif
 static inline _syscall1(int,_exit,int,exitcode)
 static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 
 /*
@@ -395,4 +393,5 @@ static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_CRIS_UNISTD_H_ */
index 5d9f84bfdcad3300ddccb8b031c86433b472648d..9a4ff03c3969fd6c779cf560135420ae9b77f84a 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef _ASM_ATOMIC_H
 #define _ASM_ATOMIC_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/spr-regs.h>
 
index 6344d06390b9fea57456b694cdff7a52dc99b910..980ae1b0cd285a5578075b0d6e82866f5f7ea047 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef _ASM_BITOPS_H
 #define _ASM_BITOPS_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/byteorder.h>
 #include <asm/system.h>
index 451712cc30600901ba0cae6b28623f8d546debaf..6b1b44d71028f9573d53372e23e5b361ff7ddfa9 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_BUG_H
 #define _ASM_BUG_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 
 #ifdef CONFIG_BUG
index cf69b6373b344a4e1c8a748fb3da147a988ae6de..2797163b8f4f12cb543495664610de65376b1319 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_CACHE_H
 #define __ASM_CACHE_H
 
-#include <linux/config.h>
 
 /* bytes per L1 cache line */
 #define L1_CACHE_SHIFT         (CONFIG_FRV_L1_CACHE_SHIFT)
index d8f9a2f21521e36ac27c4cde3b06a90107ec4a72..18d6bb8f84fcb0543f0b3f3b6c93d68aba215b31 100644 (file)
@@ -14,7 +14,6 @@
 
 //#define DMA_DEBUG 1
 
-#include <linux/config.h>
 #include <linux/interrupt.h>
 
 #undef MAX_DMA_CHANNELS                /* don't use kernel/dma.c */
index 7d2098f0476b90ecf54dab7b2ef20548cba64156..38656da00e4005ffe1f26647195595cf5fdd22cc 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_ELF_H
 #define __ASM_ELF_H
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
index b1178f8ca5ced3c019238327fc25983cbe3a4c4f..d73c60b56641bfa9d4b06e53d216481f2284f8fa 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_FPU_H
 #define __ASM_FPU_H
 
-#include <linux/config.h>
 
 /*
  * MAX floating point unit state size (FSAVE/FRESTORE)
index 685123981e8b291d9ab1865220ba221722e14bb0..7581b5a7559a1d507175aaff954ebdd286706343 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
index 295f74a57f22975fe01f44170e5d12a587536c68..cfbf7d3a1feb86262d2b0bd996d0efcaa10d68c0 100644 (file)
@@ -17,7 +17,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <asm/mem-layout.h>
 #include <asm/spr-regs.h>
index ae031eaa3dd2a05705fca170524ec3cedad996c5..f0bd2cb250c110ca64c353dfae02f054a22d9395 100644 (file)
@@ -14,7 +14,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/irq.h>
index 01247cb2bc39d88ba228d4bd1b82131754848f33..b56eba59e3cd900552af6bb130653e9d8ee61f1d 100644 (file)
@@ -17,7 +17,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/virtconvert.h>
 #include <asm/string.h>
index 2c16d8dc02fd50fd339508faa6e974b6c8f73996..58b619215a50c7e279a310185911b88c2b40bb02 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_IRQ_H_
 #define _ASM_IRQ_H_
 
-#include <linux/config.h>
 
 /*
  * the system has an on-CPU PIC and another PIC on the FPGA and other PICs on other peripherals,
index 4fb9ea3c5bc9a78a313a320a1f7a263074c6bcb2..72edcaaccd5de30d7b126520d218f360ef3696fb 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_MMU_CONTEXT_H
 #define _ASM_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
index dc0f7e08a4c2a4f000f0580f68a40877492afd60..134cc0cdf6c2727201a3f5d243d1f2761d18f342 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/virtconvert.h>
 #include <asm/mem-layout.h>
 #include <asm/sections.h>
index 598b0c6b695da9af576f43458241604bbcc4678c..f35a4511e7b91c7a0f815b911678f13edc891005 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef ASM_PCI_H
 #define        ASM_PCI_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/scatterlist.h>
 #include <asm-generic/pci-dma-compat.h>
index 1bd28f41bfa845238ca8eb4218f827c67fc8dcdd..ce982a6c610f0081a97c836d6edbc17e52e98f5c 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _ASM_PGALLOC_H
 #define _ASM_PGALLOC_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/virtconvert.h>
 
index d1c3b182c6914282b860d4b4d4a855dfb27f5d5d..7af7485e889eeb488960ae78d51627f2cd7d3c98 100644 (file)
@@ -16,7 +16,6 @@
 #ifndef _ASM_PGTABLE_H
 #define _ASM_PGTABLE_H
 
-#include <linux/config.h>
 #include <asm/mem-layout.h>
 #include <asm/setup.h>
 #include <asm/processor.h>
index 5228c18b7f78c69929b9598d0cdd01276fdf5510..1c4dba1c5f57168eb70954b0bc75138485d71a0c 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_PROCESSOR_H
 #define _ASM_PROCESSOR_H
 
-#include <linux/config.h>
 #include <asm/mem-layout.h>
 
 #ifndef __ASSEMBLY__
index 61222f00dfc17cd83538f5507ed3c1ec23368881..e3616a6f941d4ad535aa7183ca7dadc3f6999377 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_SEGMENT_H
 #define _ASM_SEGMENT_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
index 6917d556a1e111c1bc8b2f8698bae88175edc7a0..dbb8259986895143196cd7edf504dba1f0587076 100644 (file)
@@ -6,7 +6,6 @@
  *
  * Based on linux/include/asm-i386/serial.h
  */
-#include <linux/config.h>
 #include <asm/serial-regs.h>
 
 /*
index 5ca771631fd8de1701c0e76af28c71794c02dd21..38349ec8b61b4f69692e900e6f28d1504cf2061c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 #error SMP not supported
index 1734ed91bcdcdb7f0136f10bd9f14fc8e9d535b3..351863dfd06e14528b6237bd01fe1f124d0ff64c 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_SYSTEM_H
 #define _ASM_SYSTEM_H
 
-#include <linux/config.h> /* get configuration macros */
 #include <linux/linkage.h>
 #include <asm/atomic.h>
 
index bc34626250846942bf70ff87a7acac767fc7fb3a..da3a3179a85da26e74522707ecca1d6a6c3da8b6 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_TLBFLUSH_H
 #define _ASM_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
 
index 2560f596a75db78b2e7f406864f281933fff3957..1b6d1923b25b5e41b3f7092a36bf213ebd531675 100644 (file)
@@ -46,7 +46,6 @@ typedef unsigned long long __u64;
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef signed char s8;
 typedef unsigned char u8;
index a0d199bf01d9e2bef57bd117644914dfdcdb5305..dc8e9c9bf6bd9a54402db5ecb90619e89efbcb1d 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_UNALIGNED_H
 #define _ASM_UNALIGNED_H
 
-#include <linux/config.h>
 
 /*
  * Unaligned accesses on uClinux can't be performed in a fault handler - the
index 2662a3e12dc4157ff0d7ab408559bd84280ed7bc..7c2e712c3b73166078f6212e55a8c48a43bd2a26 100644 (file)
 #define __NR_pselect6          308
 #define __NR_ppoll             309
 
+#ifdef __KERNEL__
+
 #define NR_syscalls 310
 
 /*
@@ -477,9 +479,8 @@ static inline pid_t wait(int * wait_stat)
        return waitpid(-1,wait_stat,0);
 }
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 /* #define __ARCH_WANT_OLD_READDIR */
 #define __ARCH_WANT_OLD_STAT
@@ -503,7 +504,6 @@ static inline pid_t wait(int * wait_stat)
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#endif
 
 /*
  * "Conditional" syscalls
@@ -515,4 +515,5 @@ static inline pid_t wait(int * wait_stat)
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_UNISTD_H_ */
index a29a0aec291ff3ecef9fae50c7b0b64be048ac93..59788fa2a8138c441a6a2eadf4c9f77acc6272f4 100644 (file)
@@ -17,7 +17,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/setup.h>
 
 #ifdef CONFIG_MMU
index 1a565a9d2fa72f0860fb4496eb2454f88b1e4556..0cd9711895faaf6259baeaf3a66cf6484d41804a 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_GENERIC_BUG_H
 
 #include <linux/compiler.h>
-#include <linux/config.h>
 
 #ifdef CONFIG_BUG
 #ifndef HAVE_ARCH_BUG
index 1b356207712c848a3e7318c96515d7fcac24608b..b541e48cc545f6c467bc5ca691731a8535df98bd 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _ASM_GENERIC_DMA_MAPPING_H
 #define _ASM_GENERIC_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 
index b663520dcdc487531caea8fbed1908fefa0f5754..c154b9d6e7e51a8593d06b0d6e3104aa7008e5d4 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_GENERIC_FCNTL_H
 #define _ASM_GENERIC_FCNTL_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
index 9291c24f5819b2140de560835b86a00f46dedfbb..ab469297272c1da3e8cee1d77a6ab5f70a2805fc 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_GENERIC_LOCAL_H
 #define _ASM_GENERIC_LOCAL_H
 
-#include <linux/config.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
 #include <asm/atomic.h>
index 358e4d309ceb179776f2a7036dabce02cdfad1d2..c2059a3a06216cb936a163255501e20d464c6b21 100644 (file)
@@ -159,17 +159,8 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
 #define lazy_mmu_prot_update(pte)      do { } while (0)
 #endif
 
-#ifndef __HAVE_ARCH_MULTIPLE_ZERO_PAGE
+#ifndef __HAVE_ARCH_MOVE_PTE
 #define move_pte(pte, prot, old_addr, new_addr)        (pte)
-#else
-#define move_pte(pte, prot, old_addr, new_addr)                                \
-({                                                                     \
-       pte_t newpte = (pte);                                           \
-       if (pte_present(pte) && pfn_valid(pte_pfn(pte)) &&              \
-                       pte_page(pte) == ZERO_PAGE(old_addr))           \
-               newpte = mk_pte(ZERO_PAGE(new_addr), (prot));           \
-       newpte;                                                         \
-})
 #endif
 
 /*
index 9418d6e9b8cd532fe4655c2d60de53ab606f850f..dae1d8720076fde1aad89772b6390f22b1db3345 100644 (file)
@@ -1,3 +1,8 @@
+#ifndef __ASM_GENERIC_SIGNAL_H
+#define __ASM_GENERIC_SIGNAL_H
+
+#include <linux/compiler.h>
+
 #ifndef SIG_BLOCK
 #define SIG_BLOCK          0   /* for blocking signals */
 #endif
@@ -19,3 +24,5 @@ typedef __restorefn_t __user *__sigrestore_t;
 #define SIG_IGN        ((__force __sighandler_t)1)     /* ignore signal */
 #define SIG_ERR        ((__force __sighandler_t)-1)    /* error return from signal */
 #endif
+
+#endif /* __ASM_GENERIC_SIGNAL_H */
index cdd4145243cd66ec2e1164bd51a8895fad23f6d0..867d9008fafa9434417f1cecd46f2489e140b872 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _ASM_GENERIC__TLB_H
 #define _ASM_GENERIC__TLB_H
 
-#include <linux/config.h>
 #include <linux/swap.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
index 574f57b6c4d1852630f830a1da0f660a4c076efa..d76299c98b817ad0c492a276f79262bb22fea8d8 100644 (file)
@@ -6,7 +6,6 @@
  * Copyright 2002, Yoshinori Sato
  */
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/system.h>
 
index 3708681b7ddcf817cff9a049c3c694644b8fe935..3edbaaaedf5b77520e0fbcac750bc9f85fdb04ca 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _H8300_DMA_H
 #define _H8300_DMA_H 
  
-#include <linux/config.h>
 
 /*
  * Set number of channels of DMA on ColdFire for different implementations.
index f4af1553a55fcc4c0829a27fe65c48987fea3f01..7ba6a0af447c6196165f4a85fde10a819043ac98 100644 (file)
@@ -5,7 +5,6 @@
  * ELF register definitions..
  */
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
index e961bfe201b86bab9fb1e111e122f6e321162e9c..18fa7931e09fab9072728db7996ab6ee6f44bd64 100644 (file)
@@ -2,7 +2,6 @@
 #define __H8300_HARDIRQ_H
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
index 1773e373e9c6c6c007c90a6d23adff2071e256f8..91b7487cb7ae9582cc0d0c3e3d00ab9d7cfec071 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/virtconvert.h>
 
 #if defined(CONFIG_H83007) || defined(CONFIG_H83068)
index b05d11387ae5271de82ba483f83edfe656daa6ff..fbad65e8a5c0ab8cf70d702b30abadf0a8366ee0 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _H8300_KEYBOARD_H
 #define _H8300_KEYBOARD_H
 
-#include <linux/config.h>
 
 /* dummy i.e. no real keyboard */
 #define kbd_setkeycode(x...)   (-ENOSYS)
index 23b555b7b4b9892ed4c6a78ce60c9010fe98eabe..855721a5dcc973d0661e6e182301d958cdaf6606 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __H8300_MMU_CONTEXT_H
 #define __H8300_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
index 6472c9f88227182ddaf2e914dc14fdfcefd64c50..f9f9d3eea8ed2fd3e9e9349c26dcfb5e1570df3b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _H8300_PAGE_H
 #define _H8300_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 
index 8cc6e17218a806f8629a4605c0da6c125bd9a300..f8706463008c155a47cba5fd4322df979e4665dc 100644 (file)
@@ -1,4 +1,3 @@
 
-#include <linux/config.h>
 #define PAGE_OFFSET_RAW                0x00000000
 
index 126dddf72359cf83e901f5136c57ae067348db72..c25806ed1fb368d2581b00f853bb4d55ade94b9d 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _H8300_PARAM_H
 #define _H8300_PARAM_H
 
-#include <linux/config.h>
 
 #ifndef HZ
 #define HZ 100
index f6e296fc1297da57e448851613fc11542bd566fc..8b7c6857998bafdb817bc124756e57ab0fb87460 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <asm/processor.h>
 #include <asm/page.h>
index c6f0a7108ef37e3eb0d84668d37e79c42ba5f215..c7e2f454b83a570b5a445b061f028705166637bb 100644 (file)
@@ -17,7 +17,6 @@
  */
 #define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
-#include <linux/config.h>
 #include <asm/segment.h>
 #include <asm/fpu.h>
 #include <asm/ptrace.h>
index 29e0fbf1acb70a7f75c4d8dee3058ef2f99abfba..4fea36be5fd85df5004a23af32e678db21868835 100644 (file)
@@ -10,7 +10,6 @@
  * m68k version by Andreas Schwab
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 
 /*
index bec7585248394f813ce046ebdfcda3dc11f6d73b..ed6623c0545db2d2735f3bc58f553ec67d918865 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _H8300_SHM_H
 #define _H8300_SHM_H
 
-#include <linux/config.h>
 
 /* format of page table entries that correspond to shared memory pages
    currently out in swap space (see also mm/swap.c):
index 8e81cf665e75ea3406b2d4a79f7a002671aa52f8..134e0929fce5500939b4d4bee7d34bd03d400890 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _H8300_SYSTEM_H
 #define _H8300_SYSTEM_H
 
-#include <linux/config.h> /* get configuration macros */
 #include <linux/linkage.h>
 
 /*
index 8a93961173c3ed45f04cc5f95b9accc3f9fdbacc..ffb67f472070c995d362d7cc6ac2698276c8becd 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __H8300_UNALIGNED_H
 #define __H8300_UNALIGNED_H
 
-#include <linux/config.h>
 
 /* Use memmove here, so gcc does not insert a __builtin_memcpy. */
 
index adb05159379b975dcf19c5c2005fd8e2dc0e7720..226dd596c2dad0de1e22943ba1853610c7c8cb20 100644 (file)
 #define __NR_request_key       287
 #define __NR_keyctl            288
 
+#ifdef __KERNEL__
+
 #define NR_syscalls 289
 
 
@@ -460,7 +462,6 @@ type name(atype a, btype b, ctype c, dtype d, etype e, ftype f)     \
   __syscall_return(type, __res);                       \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -483,7 +484,6 @@ type name(atype a, btype b, ctype c, dtype d, etype e, ftype f)     \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -534,7 +534,7 @@ asmlinkage long sys_rt_sigaction(int sig,
                                struct sigaction __user *oact,
                                size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -543,4 +543,5 @@ asmlinkage long sys_rt_sigaction(int sig,
   asm (".weak\t_" #name "\n"                           \
        ".set\t_" #name ",_sys_ni_syscall");
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_H8300_UNISTD_H_ */
index 3b344c1dfe0f3951f973725b2b8b56b522569de9..ee7d5ea10065dc3ba28a7d9d9f8c5ca0724b8993 100644 (file)
@@ -7,7 +7,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 
index 288233fd77d7b755b8c5962da5084d32a1558351..cc9b940fb7e85af98013ff5c5519240728091aaa 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_APIC_H
 #define __ASM_APIC_H
 
-#include <linux/config.h>
 #include <linux/pm.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
index 4ddce5296a788a2b6442700f4126bb636cd14df9..4f061fa7379410f3d08624adbe1faecc1e755aff 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ARCH_I386_ATOMIC__
 #define __ARCH_I386_ATOMIC__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/processor.h>
 
index 08deaeee6be971cd362fc8f57bf62add9a533882..1c780fa1e762e966a6f6255dbf0e5bbf4a326e65 100644 (file)
@@ -5,7 +5,6 @@
  * Copyright 1992, Linus Torvalds.
  */
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/alternative.h>
 
index 8f79de19eb9405f67cd19389da24ebdac1ad25dc..8062cdbf2587f9213a2f0e35c8b536fc92572dec 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _I386_BUG_H
 #define _I386_BUG_H
 
-#include <linux/config.h>
 
 /*
  * Tell the user there is some problem.
index 50233e0345fba1e729d00293419d11f422a532b2..2a9e4ee5904d50b91d3b6310ed2e78451ce2630c 100644 (file)
@@ -17,7 +17,6 @@
  *     void check_bugs(void);
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
index a0d73f48d5bea050cb21d61dfab049e38f5a3b78..a45470a8b74abb89d6c19b10985c2ef4bc8cd450 100644 (file)
@@ -8,7 +8,6 @@
 
 /* For avoiding bswap on i386 */
 #ifdef __KERNEL__
-#include <linux/config.h>
 #endif
 
 static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
index ca15c9c665cf68bf5a10dacd78a6e10624b0de38..57c62f414158b378f6667fd26d1af95575e6030d 100644 (file)
@@ -4,7 +4,6 @@
 #ifndef __ARCH_I386_CACHE_H
 #define __ARCH_I386_CACHE_H
 
-#include <linux/config.h>
 
 /* L1 cache line size */
 #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
index f24b2bba2831776ad5123d891f4dc9ede8fdfe52..d23aac8e1a50daeb32a4e70b84901ae587a645dc 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>    /* And spinlocks */
 #include <asm/io.h>            /* need byte IO */
 #include <linux/delay.h>
index cfb1c61d3b9c0b933766a9e70acc61db561642cf..f7e068f4d2f98d7cdb8c5198cd26c1796bb3d9dc 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#include <linux/config.h>
 
 /* used by vmalloc.c, vsyscall.lds.S.
  *
index ee754d35973413b6e4d12e43033ea52cea148fae..0e358dc405f820f6259cf61b247201a568bc9e64 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
index 0fd331306b60115f9b889fe74313722ae28141ac..e9a34ebc25d58f5b63391274159dca5683b80c19 100644 (file)
@@ -20,7 +20,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/interrupt.h>
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
index 7f1a8a6ee32fa41dfcb86683f6f5aaae4f9d3d52..af5d435519d15592a0f30bce4aabe29d9c2efa87 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/processor.h>
 
 #include <linux/timex.h>
-#include <linux/config.h>
 
 #include <asm/fixmap.h>
 
index 622815bf3243e00306774bbea1ab01e2bc2a2f3e..95d3fd090298be566194d02812bf07c0dda807c2 100644 (file)
@@ -12,7 +12,6 @@
  *     <tomsoft@informatik.tu-chemnitz.de>
  */
 
-#include <linux/config.h>
 #include <linux/profile.h>
 #include <asm/atomic.h>
 #include <asm/irq.h>
index 454440193eacd8913277df03e9593ed3d3169dbb..73465d2892b92e27183e3427dc0d4783c9b8f6b0 100644 (file)
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifndef MAX_HWIFS
 # ifdef CONFIG_BLK_DEV_IDEPCI
index 79670bb4b0c7140e593718e6d30954475c712deb..b3724fe93ff1008111dad9d1fc993defdafdda11 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/compiler.h>
 
index d92e253f7f6f2963076ff7b7280396603a814685..5092e819b8a2b23c336a79840e8ca2a955599c4a 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_IO_APIC_H
 #define __ASM_IO_APIC_H
 
-#include <linux/config.h>
 #include <asm/types.h>
 #include <asm/mpspec.h>
 
index 5169d7af456f4cdfa9ac082db031b38dbda02504..331726b411282646928f286590963bcd0c865c7b 100644 (file)
@@ -10,7 +10,6 @@
  *     <tomsoft@informatik.tu-chemnitz.de>
  */
 
-#include <linux/config.h>
 #include <linux/sched.h>
 /* include comes from machine specific directory */
 #include "irq_vectors.h"
index 6886a0c3fedfde6ed82cce4d2ca988d561c6d244..806aae3c533892b1e65917c4742943ff2692374b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
index 3d6d12937e1fbfae5098236ce4776f945d2d57e8..9fd0732862895fc4bf002765655fe329aef53ff8 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_MACH_APIC_H
 #define __ASM_MACH_APIC_H
 
-#include <linux/config.h>
 #include <asm/smp.h>
 
 #define esr_disable (1)
index bf08218357ea70c06d67d7aeb7384f231fd47e35..62b7bf1840942013a0a258a039a03e90c8458a66 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __I386_SCHED_H
 #define __I386_SCHED_H
 
-#include <linux/config.h>
 #include <asm/desc.h>
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
index 64cf937c7e33d46b80ad4f0369b67a196bca9db9..5a46de08efea389bc97c4d4e95d3ad42af9af46d 100644 (file)
@@ -23,7 +23,6 @@
 #ifndef _LINUX_MTRR_H
 #define _LINUX_MTRR_H
 
-#include <linux/config.h>
 #include <linux/ioctl.h>
 #include <linux/errno.h>
 
index 30f52a2263ba547e0bf2e4d5367d3ae9012fd5cd..e3a552fa5538744bd578d6351c8c23756774c782 100644 (file)
@@ -12,7 +12,6 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_X86_USE_3DNOW
 
@@ -137,9 +136,9 @@ extern int page_is_ram(unsigned long pagenr);
        ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#endif /* __KERNEL__ */
-
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+#endif /* __KERNEL__ */
+
 #endif /* _I386_PAGE_H */
index 095580f3a45cfb4d556427e84c65a9fad15c690f..745dc5bd0fbc159e835fe530c074682ca8223efe 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASMi386_PARAM_H
 
 #ifdef __KERNEL__
-# include <linux/config.h>
 # define HZ            CONFIG_HZ       /* Internal kernel timer frequency */
 # define USER_HZ       100             /* .. some user interfaces are in "ticks" */
 # define CLOCKS_PER_SEC                (USER_HZ)       /* like times() */
index 78c85985aee36901c8b6369372643b52f3d94b65..64b6d0baedbce7109c8691095e55b039186750c2 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __i386_PCI_H
 #define __i386_PCI_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 #include <linux/mm.h>          /* for struct page */
index 0380c3dc1f7e882244b1af6b22b600c6a96450c1..4b1e61359f89923428a5bb2368374c8d7b44ceb8 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _I386_PGALLOC_H
 #define _I386_PGALLOC_H
 
-#include <linux/config.h>
 #include <asm/fixmap.h>
 #include <linux/threads.h>
 #include <linux/mm.h>          /* for struct page */
index 672c3f76b9df9344caacbbdbc64d308d929bc04e..09697fec3d2b33a29ab990abe03505625a85400d 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _I386_PGTABLE_H
 #define _I386_PGTABLE_H
 
-#include <linux/config.h>
 
 /*
  * The Linux memory management assumes a three-level page table setup. On
index 805f0dcda468d3d720b2e836d506870b0657d0ee..4df3818e41226e8adb90a57aff788191cf95fd86 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/msr.h>
 #include <asm/system.h>
 #include <linux/cache.h>
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/percpu.h>
 #include <linux/cpumask.h>
index e1ecfccb743b7a16fc7934cab046ac2bdd8aaa51..bd67480ca1094f9896aacdf5395d0b541552fb75 100644 (file)
@@ -2,7 +2,6 @@
  * include/asm-i386/serial.h
  */
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
index 61d3ab9db70cd7c9559907e5c0106962b110ede6..142d10e34adeac2c4960e90018575c2094c28a62 100644 (file)
@@ -5,7 +5,6 @@
  * We need the APIC definitions automatically as part of 'smp.h'
  */
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
index d76b7693cf1da5674a8b10ea616a4498b54a8c76..04ba30234c486e383e73127a34cb3ea8bc3bb898 100644 (file)
@@ -4,7 +4,6 @@
 #include <asm/atomic.h>
 #include <asm/rwlock.h>
 #include <asm/page.h>
-#include <linux/config.h>
 #include <linux/compiler.h>
 
 /*
index bb5f88a27f7a8e23711afa0aa8ca5f30d1ed95c7..b9277361954b795ed539fe013385240cd8c26eca 100644 (file)
@@ -2,7 +2,6 @@
 #define _I386_STRING_H_
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 /*
  * On a 486 or Pentium, we are better off not using the
  * byte string operations. But on a 386 or a PPro the
index 19cc79c9a35db68f4fbe1e673b61238a2613e78b..0249f912a29c2d42ebee12883be318dd627c79a1 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SYSTEM_H
 #define __ASM_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/segment.h>
 #include <asm/cpufeature.h>
index 1f7d48c9ba3f5b284a71733f4dd552e9455c9da4..8420ed12491e74c83407b62c7d2b3638de23e3d2 100644 (file)
@@ -9,7 +9,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/page.h>
 
index 292b5a68f6271b08b410d19197e3434f654e517f..d434984303ca35f15556bbb8f2bee352a1c48cf3 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _ASMi386_TIMEX_H
 #define _ASMi386_TIMEX_H
 
-#include <linux/config.h>
 #include <asm/processor.h>
 
 #ifdef CONFIG_X86_ELAN
index ab216e1370efb85fb3b6f73dab1ad588bf1382f7..d57ca5c540b69cd74821e9ca7cec039a9e3b805a 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _I386_TLBFLUSH_H
 #define _I386_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
 
index e50a08bd7ced0ef43ac153958d613f85f89fb7cc..4b4b295ccdb9b75deca70c45467571cd7fdf5c38 100644 (file)
@@ -35,7 +35,6 @@ typedef unsigned long long __u64;
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef signed char s8;
 typedef unsigned char u8;
index 371457b1ceb6de2b47e8fcf7d125f8e57488cfb5..1ec65523ea5e750f0105095476112056061f9693 100644 (file)
@@ -4,7 +4,6 @@
 /*
  * User space memory access functions
  */
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
 #include <linux/prefetch.h>
index eb4b152c82fc0d1093c6a246a9dcef4859e4eb09..de2ccc149e3406008eb516141754c12a5ed411d8 100644 (file)
 #define __NR_tee               315
 #define __NR_vmsplice          316
 
+#ifdef __KERNEL__
+
 #define NR_syscalls 317
 
 /*
@@ -422,7 +424,6 @@ __asm__ volatile ("push %%ebp ; push %%ebx ; movl 4(%2),%%ebp ; " \
 __syscall_return(type,__res); \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -446,7 +447,6 @@ __syscall_return(type,__res); \
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -485,7 +485,7 @@ asmlinkage long sys_rt_sigaction(int sig,
                                struct sigaction __user *oact,
                                size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -497,4 +497,5 @@ asmlinkage long sys_rt_sigaction(int sig,
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_I386_UNISTD_H_ */
index edf2cebb2969d55e3bbd3915175e6a74cee6b8a0..c22b4658fc6120144753962bd667c10c9a646f8c 100644 (file)
@@ -6,7 +6,6 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #define ENTRY(name)                            \
        .align 32;                              \
index f0a104db8f20dcb5a37639ac26ffbf863fe4d8b3..e7482bd628ff21ab21d98277d1c2d79f14cfea38 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_IA64_CACHE_H
 #define _ASM_IA64_CACHE_H
 
-#include <linux/config.h>
 
 /*
  * Copyright (C) 1998-2000 Hewlett-Packard Co
index bba70207639103caaa05d0a0815b90d6eb4d3fa2..a30a62f235e1107ce9134a2ddd38ff60aa5b75da 100644 (file)
@@ -12,7 +12,6 @@
  * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/compiler.h>
index df67d40801de9ac9dc2041145927c251e7e5c7c5..99a8f8e1218c18283fbfe96baf1547d5e3b500d9 100644 (file)
@@ -5,7 +5,6 @@
  * Copyright (C) 2003-2004 Hewlett-Packard Co
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
-#include <linux/config.h>
 #include <asm/machvec.h>
 
 #define dma_alloc_coherent     platform_dma_alloc_coherent
index 3be1b4925e182eb7354ee5e69418f7ab7375791b..dad3a735df8bf2bdfb0905775f028259950fa35a 100644 (file)
@@ -6,7 +6,6 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <asm/io.h>            /* need byte IO */
 
index 446fce036fd929eedb87ffdf95917703a568a9ae..25f9835d5459e2028c3b1ba1c811861bb2d19193 100644 (file)
@@ -8,7 +8,6 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <asm/fpu.h>
 #include <asm/page.h>
index 33ef8f096d953e4a1c8307938cd029e7728458c3..140e495b8e0e841b615a1a1b1c971438638c720b 100644 (file)
@@ -6,7 +6,6 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <linux/threads.h>
 #include <linux/irq.h>
index f8044a1169cd39fdb653f5c86733aba719fd8356..5ff8d74c3e0051934bc43f010a923e02cdfeb024 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_IA64_IA32_H
 #define _ASM_IA64_IA32_H
 
-#include <linux/config.h>
 
 #include <asm/ptrace.h>
 #include <asm/signal.h>
index 93f45c5f189f0649bc0df0b62fcc6f10bc270a50..e928675de352b08f06799442fd9761ab0c341ea6 100644 (file)
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #include <linux/irq.h>
 
index 8089f955e5d21a2ad50813c964b0f79eb92670c4..3a95aa432e99f839dc94da7ae0b2786629a8cbcf 100644 (file)
@@ -9,7 +9,6 @@
  */
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 
 /* include compiler specific intrinsics */
 #include <asm/ia64regs.h>
index bc777525fa12fc284e971e987992fdcc79cbb227..5d1658aa2b3bf2a4770ce77c02519439a0c73857 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_IA64_KMAP_TYPES_H
 #define _ASM_IA64_KMAP_TYPES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
index a9c995a86c21e42482060eeda9fd68ce55078b07..0df72a134c8b80e26f2f04cc471e655ffddd3c75 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_IA64_MACHVEC_H
 #define _ASM_IA64_MACHVEC_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /* forward declarations: */
index 46501b01a5c58589055927e2dabdbde43e6c3ed5..894bc4d89dc02b718ba01f8c2e1a6a772fc9ae18 100644 (file)
@@ -7,7 +7,6 @@
  * for more details.
  */
 
-#include <linux/config.h>
 
 /*
  * Entries defined so far:
index 9978c7ce7549c32f2eeb5a1cc8ed36ef2de6d0ce..a140310bf84dcb4120980b883965a9ea9260a847 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_IA64_NODEDATA_H
 #define _ASM_IA64_NODEDATA_H
 
-#include <linux/config.h>
 #include <linux/numa.h>
 
 #include <asm/percpu.h>
index dae6aeb7b1190b5e863c2f799a23bfe6aa780d7e..e5a8260593a55e3c15f88a6bc8391a8b8e021db3 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_IA64_NUMA_H
 #define _ASM_IA64_NUMA_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_NUMA
 
index 2087825eefa4f61c576b0b6478b2da15ff7cc230..f5a949ec6e1ee60355ecadd7b7edb23b916b2d07 100644 (file)
@@ -7,7 +7,6 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <asm/intrinsics.h>
 #include <asm/types.h>
index 5e1e0d2d7baf3b7f8a1d3b95252bd9ed1dc20336..49c62dd5eccf2a8bfa9af981b1a2c4255ff81e3c 100644 (file)
@@ -19,7 +19,6 @@
 #define MAXHOSTNAMELEN 64      /* max length of hostname */
 
 #ifdef __KERNEL__
-# include <linux/config.h>     /* mustn't include <linux/config.h> outside of #ifdef __KERNEL__ */
 # ifdef CONFIG_IA64_HP_SIM
   /*
    * Yeah, simulating stuff is slow, so let us catch some breath between
index 2b14dee29ce7af3ba52cbfcb777eefd5bc506720..ae357d504fba81ddd0827df421f6ec317c71e6b0 100644 (file)
@@ -12,7 +12,6 @@
 # define THIS_CPU(var) (per_cpu__##var)  /* use this to mark accesses to per-CPU variables... */
 #else /* !__ASSEMBLY__ */
 
-#include <linux/config.h>
 
 #include <linux/threads.h>
 
index f2f23384647692d9e4d0ebec0b92f086828699a1..9cb68e9b377e2c831f71187dc1314643b83fc933 100644 (file)
@@ -13,7 +13,6 @@
  * Copyright (C) 2000, Goutham Rao <goutham.rao@intel.com>
  */
 
-#include <linux/config.h>
 
 #include <linux/compiler.h>
 #include <linux/mm.h>
index c0f8144f23497ae0f95804148f19206b170393c8..eaac08d5e0bd7d49343453f690a6fc8d6acc386e 100644 (file)
@@ -12,7 +12,6 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <asm/mman.h>
 #include <asm/page.h>
index b3bd58e806900053bc0e71870809ce86d7b1a16d..265f4824db0e2e6ea04abc225f81758547a8de62 100644 (file)
@@ -13,7 +13,6 @@
  * 06/16/00    A. Mallick      added csd/ssd/tssd for ia32 support
  */
 
-#include <linux/config.h>
 
 #include <asm/intrinsics.h>
 #include <asm/kregs.h>
index 9471cdc3f4c0989a3a8d34a37035f06918e96232..415abb23b210e1b79813361c59c409c855da61c7 100644 (file)
@@ -54,7 +54,6 @@
  * This is because ar.ec is saved as part of ar.pfs.
  */
 
-#include <linux/config.h>
 
 #include <asm/fpu.h>
 #ifndef ASM_OFFSETS_C
index a3914352c995e83222080a9d7151a9567256196c..719ff309ce090276b0678b0ebccfeccf4a43b4ea 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_IA64_SMP_H
 #define _ASM_IA64_SMP_H
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
index 16a48b5a039ce88fd1d2911c302b4db025abbce9..c3fd3eb25768d7b04967b1fc86bd0e57b982c2d7 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _ASM_IA64_SN_SIMULATOR_H
 #define _ASM_IA64_SN_SIMULATOR_H
 
-#include <linux/config.h>
 
 #define SNMAGIC 0xaeeeeeee8badbeefL
 #define IS_MEDUSA()                    ({long sn; asm("mov %0=cpuid[%1]" : "=r"(sn) : "r"(2)); sn == SNMAGIC;})
index 749deb2ca6c1fe1dd530242c455ad36488399f99..a676dd9ace3eb2dceba652dea92761ea56d93842 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_IA64_SN_SN_CPUID_H
 #define _ASM_IA64_SN_SN_CPUID_H
 
-#include <linux/config.h>
 #include <linux/smp.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/pda.h>
index 51aca022cf3906c632eb4c192e3070b211e1b16f..8c865e43f609ac1dfe2f5464ac7fd6e1edce8d43 100644 (file)
@@ -12,7 +12,6 @@
  */
 
 
-#include <linux/config.h>
 #include <asm/sal.h>
 #include <asm/sn/sn_cpuid.h>
 #include <asm/sn/arch.h>
index aa3b8ace90308f7ec6004e2990a395da07885b64..8406f1ef4cafa39238ff5f00ecf923ed2bf38f87 100644 (file)
@@ -15,7 +15,6 @@
 #define _ASM_IA64_SN_XPC_H
 
 
-#include <linux/config.h>
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
 #include <linux/device.h>
index 43502d3b57e527434604632394489cc0b7d532c0..85fd65c52a8c0a7449e60d2f84cdf56b393b23af 100644 (file)
@@ -9,7 +9,6 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>      /* remove this once we remove the A-step workaround... */
 
 #define __HAVE_ARCH_STRLEN     1 /* see arch/ia64/lib/strlen.S */
 #define __HAVE_ARCH_MEMSET     1 /* see arch/ia64/lib/memset.S */
index 2f3620593687818aac2ef154351995e8a42a9fae..65db43ce4de6e533a89a81d2df70ec6e799d8962 100644 (file)
@@ -12,7 +12,6 @@
  * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
  * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
  */
-#include <linux/config.h>
 
 #include <asm/kregs.h>
 #include <asm/page.h>
index 834370b9dea166d5749b3afad52b2bedd4576e13..26edcb750f9f28bc37a106c20356e0fbc55b1665 100644 (file)
@@ -37,7 +37,6 @@
  *     }
  *     tlb_finish_mmu(tlb, start, end);        // finish unmap for address space MM
  */
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
index a35b323bae4ca7e0ae6f544c4578c309804a03d2..cf9acb9bb1fb69b7744f4e40081ad1bdcf8061b0 100644 (file)
@@ -6,7 +6,6 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <linux/mm.h>
 
index 7107763168bfd4b82f2c5f5edf96978a2a2446f8..632f2eedf72c9fab463c74ce682485a576e7c077 100644 (file)
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #define NR_syscalls                    279 /* length of syscall table */
 
index 1a1aa17edd33fe737d1035676d756421b93a1fe8..47041d19d4a8c5019845cd53dbaf8b8c6c1f017f 100644 (file)
@@ -9,7 +9,6 @@
  * This file contains M32R architecture specific macro definitions.
  */
 
-#include <linux/config.h>
 
 #ifndef __STR
 #ifdef __ASSEMBLY__
index 3122fe106f051b32a6bc1bebfeffbf7b92d23371..f5a7d7301c72170523cc265402acfc487d16b553 100644 (file)
@@ -9,7 +9,6 @@
  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>
 #include <asm/assembler.h>
 #include <asm/system.h>
 
index 902a366101a5dc6b66f173ec5107d8e1b871f366..66ab672162cdc42b8f2b5725d64508e07aea1fb6 100644 (file)
@@ -11,7 +11,6 @@
  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/assembler.h>
 #include <asm/system.h>
index e57427b6e249369219690672d2cf832da6e321bb..8b261b49149e7cac1529bbe95dc153845410997f 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_M32R_CACHEFLUSH_H
 #define _ASM_M32R_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 extern void _flush_cache_all(void);
index 5da830ec1587397f7d1cb5759ec2e1b23764105f..cb8aa762f2351435932b45f28e38921b5957121b 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
index f7aa96970d180c7389a272ea0b8b583ca1ca8325..219a0f74eff316e525e464c4c9c75f8f73040846 100644 (file)
@@ -15,7 +15,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifndef MAX_HWIFS
 # ifdef CONFIG_BLK_DEV_IDEPCI
index ca943954572aae4f28f47a9f4872a7f205837cf2..2f93f4743add897ce75a9700c9a4abfa58d8442b 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef _ASM_M32R_IRQ_H
 #define _ASM_M32R_IRQ_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_USRV)
 /*
index 7429591010b69288306a55026cfca3c5404d5931..0524d89edb0f4709de3bdc42c5ecf00438f46d5e 100644 (file)
@@ -3,7 +3,6 @@
 
 /* Dummy header just to define km_type. */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
index a4eac20553dfaa0bc6faad46b3f1e8b13708b363..6ba4ddf7dcf788a6d362d342f947aa856ab734c1 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _M32104UT_M32104UT_PLD_H
 #define _M32104UT_M32104UT_PLD_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_PLAT_M32104UT)
 #define PLD_PLAT_BASE          0x02c00000
index 50545ec9c42c376367bcda0f4697a4566fecab3e..c050b19e81010d452494139154a17dcc4677dbdd 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _M32700UT_M32700UT_LAN_H
 #define _M32700UT_M32700UT_LAN_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 /*
index ede6c77bd5e6dc4acfc218df4ee5a66fb6645558..4da4e822e2f38dac6d211da8f4bec1c1ff06e027 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _M32700UT_M32700UT_LCD_H
 #define _M32700UT_M32700UT_LCD_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 /*
index f5e4794866960ad523cf8efbaaba696eaef41e61..f35f9159acffdb44f32019a164619f3bb3ee2f40 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _M32700UT_M32700UT_PLD_H
 #define _M32700UT_M32700UT_PLD_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_PLAT_M32700UT_Alpha)
 #define PLD_PLAT_BASE          0x08c00000
index b133ca61acf197247921d7cb3f9f434452dfdb76..decfc59907c7f62b929cbaa6668edde9e95a8d02 100644 (file)
@@ -7,7 +7,6 @@
  * Copyright (C) 2003, 2004  Renesas Technology Corp.
  */
 
-#include <linux/config.h>
 
 /* Chip type */
 #if defined(CONFIG_CHIP_XNUX_MP) || defined(CONFIG_CHIP_XNUX2_MP)
index 9c00eb78ee5029ae19bcd1d0bebc401922571259..cf3f6d78ac66ab13bc056b2f01f9389ad71a8ea5 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_M32R_MMU_H
 #define _ASM_M32R_MMU_H
 
-#include <linux/config.h>
 
 #if !defined(CONFIG_MMU)
 typedef struct {
index 3634c5361a9b0d55b5786c3b02fb6e4e5858c321..542302eb6bcbf97d9e1bd87474c4ce3bbd6ee145 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #include <asm/m32r.h>
 
@@ -15,7 +14,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu.h>
index 7a2a839eedabc52240081cd6706baea6cc0e4cf5..61948296f44568921a1fc70b5491785a70f14129 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _OPSPUT_OPSPUT_LAN_H
 #define _OPSPUT_OPSPUT_LAN_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 /*
index 3a883e3d71873b46405750864fee109dc61ef430..44cfd7fe2d88c3cad9675f25c5d183653e77a72a 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _OPSPUT_OPSPUT_LCD_H
 #define _OPSPUT_OPSPUT_LCD_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 /*
index 2018e6925035f8f5b6950d9b1add9f9bc86bfb66..46296fe1ec1a63027c68f22d6d6568cc0d19e15d 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _OPSPUT_OPSPUT_PLD_H
 #define _OPSPUT_OPSPUT_PLD_H
 
-#include <linux/config.h>
 
 #define PLD_PLAT_BASE          0x1cc00000
 
index 9ddbc087dbc5c4973c577a92211bfaae940c48db..9688be0036208a69fae49a5545a1748c628b7f67 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_M32R_PAGE_H
 #define _ASM_M32R_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT     12
index 6da309b6fda7faf3dd7927310753bea1da978531..e09a86c3cadf44bf4266eece984c47dbf390b804 100644 (file)
@@ -3,7 +3,6 @@
 
 /* $Id$ */
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 #include <asm/io.h>
index 861727c20e8f52f7570662f8716f65149918d8cf..be0f167e344a6b68a07da3b0a54a85934ce37efe 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * traditional M32R two-level paging structure:
index 75740debcd01e0c46842c6aee002e0d28fb216b7..1983b7f4527af8fd6cd9b059471d10e78be2fd59 100644 (file)
@@ -20,7 +20,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/processor.h>
 #include <asm/addrspace.h>
index 09fd1813e780c36845d8266d65d980d2f66996e5..32755bf136de83891063e6f672be1dc1e66be259 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <asm/cache.h>
 #include <asm/ptrace.h>  /* pt_regs */
 
index 53c792452dfc0c036538230f69fce24406d119f9..a07fa90314d2f773212fa7f82a6049e6d194a21d 100644 (file)
@@ -12,7 +12,6 @@
  *   Copyright (C) 2001-2002, 2004  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>
 #include <asm/m32r.h>          /* M32R_PSW_BSM, M32R_PSW_BPM */
 
 /* 0 - 13 are integer registers (general purpose registers).  */
index ec3cdf666c68285047451dc48215baa55fef65ab..6b2b837c59782b910e3d679a3678f78296a4286f 100644 (file)
@@ -4,7 +4,6 @@
 #define __RTC_H__
 
 
-#include <linux/config.h>
 
    /* Dallas DS1302 clock/calendar register numbers. */
 #  define RTC_SECONDS      0
index 81750edc8916267e035dcf47484afe001910c74a..41e45d7b87ef2262c396872c87b3a143fd9ff88a 100644 (file)
@@ -12,7 +12,6 @@
  * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>
 #include <linux/wait.h>
 #include <linux/rwsem.h>
 #include <asm/assembler.h>
index 1bf480f58493e3ae8a68ed9f6f1312a45b0d1265..5ac244c72f1539b2d4ce0ac54fdde10bd49d14b4 100644 (file)
@@ -3,7 +3,6 @@
 
 /* include/asm-m32r/serial.h */
 
-#include <linux/config.h>
 
 #define BASE_BAUD      115200
 
index 942b8a30937df79deb9ac1dc76bb8cd27862afd9..73025c0c41a1ff94a5ff5ac5e979a566011c7aad 100644 (file)
@@ -3,7 +3,6 @@
 
 /* $Id$ */
 
-#include <linux/config.h>
 
 struct sigcontext {
        /* CPU registers */
index 1184293e57127c532b47477c2003e37f22749f45..650d2558c304c1e271e034c54246e8203f6bc3e5 100644 (file)
@@ -3,7 +3,6 @@
 
 /* $Id$ */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 #ifndef __ASSEMBLY__
index 7de7def28da97c651ef7aaebed4271905663e038..f94c1a673569109cbe336c2849b7f228183bc988 100644 (file)
@@ -9,7 +9,6 @@
  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>      /* CONFIG_DEBUG_SPINLOCK, CONFIG_SMP */
 #include <linux/compiler.h>
 #include <asm/atomic.h>
 #include <asm/page.h>
index e55013f378e582357df670aee5638e62e8e5a2af..33567e8bfe6b2a220ebd4821c717fb5a4b00ee6a 100644 (file)
@@ -10,7 +10,6 @@
  * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>
 #include <asm/assembler.h>
 
 #ifdef __KERNEL__
index abf12e7ffbf352adfeb36cb2d012eccd4f13647f..e89bfd17db519bd0e78718f2db2342547060c21a 100644 (file)
@@ -9,7 +9,6 @@
  * m32r architecture timex specifications
  */
 
-#include <linux/config.h>
 
 #define CLOCK_TICK_RATE        (CONFIG_BUS_CLOCK / CONFIG_TIMER_DIVIDE)
 #define CLOCK_TICK_FACTOR      20      /* Factor of both 1000000 and CLOCK_TICK_RATE */
index bc7c407dbd927025232fec33aa8dc8b96f7bd304..ae4494960593312b5c8d4813192c7f9e0639b421 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_M32R_TLBFLUSH_H
 #define _ASM_M32R_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <asm/m32r.h>
 
 /*
index 819cc28a94f7c430e977064ccd84f2052406795e..26e978c7e3b40a060c0d3e80f1ef41cf5923635a 100644 (file)
@@ -11,7 +11,6 @@
 /*
  * User space memory access functions
  */
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
 #include <asm/page.h>
index be0eb014c3b0c99b745e9de701fd660fc2849714..cc31790d8077c5dbc07e9c434ecf10d4f6a79870 100644 (file)
 #define __NR_kexec_load                283
 #define __NR_waitid            284
 
+#ifdef __KERNEL__
+
 #define NR_syscalls 285
 
 /* user-visible error numbers are in the range -1 - -124: see
@@ -405,7 +407,6 @@ __asm__ __volatile__ (\
 __syscall_return(type,__res); \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
@@ -421,7 +422,6 @@ __syscall_return(type,__res); \
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -470,4 +470,5 @@ asmlinkage long sys_rt_sigaction(int sig,
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_M32R_UNISTD_H */
index 732d696d31a6590aa3a00647be49ec41d9d4f4aa..d5eed64cb833d277bcc459ab0175022c045232be 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ARCH_M68K_ATOMIC__
 #define __ARCH_M68K_ATOMIC__
 
-#include <linux/config.h>
 
 #include <asm/system.h>        /* local_irq_XXX() */
 
index 072ce274d53751d3ecbff96f0b2dca93b8056e97..7b60776cc966dfd15be72db4366cc33a78bd8f9f 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68K_BUG_H
 #define _M68K_BUG_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
index b1920c703d82387bb802846507fc39b722b92835..dffd59cf136496c57d392f2908cf5e23d210107f 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68K_DMA_MAPPING_H
 #define _M68K_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
index d5266a88622655f9bb629b64507faf78dc5a3a32..d0c9e61e57b448e5aca2f4955467c72d2b3a7758 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68K_DMA_H
 #define _M68K_DMA_H 1
 
-#include <linux/config.h>
 
 /* it's useless on the m68k, but unfortunately needed by the new
    bootmem allocator (but this should do it for this) */
index 5978f87b0a8acc15020e143fb998ffadb0207bdf..e1112de5a5e3ba25bd483a227cda44fd0359d7bc 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef __M68K_DVMA_H
 #define __M68K_DVMA_H
 
-#include <linux/config.h>
 
 #define DVMA_PAGE_SHIFT        13
 #define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT)
index 38bf8347f14daa58b95d27c8b040f68ac305ede9..eb63b85f933674f47e1ea8afab0f7d82d23bd3bd 100644 (file)
@@ -5,7 +5,6 @@
  * ELF register definitions..
  */
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
index 0396495cd97de0d3f6187b83bed39d3db4520f6e..f8f6b185d793b16d7dfe8781098524ea991ee762 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __M68K_ENTRY_H
 #define __M68K_ENTRY_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 
index 3bcf85065c1910cf0d6e9de496b883e1e920f091..59701d7b4e78a646bda5390c901133557f893be4 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __M68K_FPU_H
 #define __M68K_FPU_H
 
-#include <linux/config.h>
 
 /*
  * MAX floating point unit state size (FSAVE/FRESTORE)
index 5e1c5826c83d179e3d4f3228a884f7673b476e21..394ee946015c4284eea9ee0f668e1851ccfdd38b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __M68K_HARDIRQ_H
 #define __M68K_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cache.h>
 
index 36118fd01867967e11441e80485c721f14fa688b..365f76fb8013fbfa1c1ae0e531abe6d45ea93d51 100644 (file)
@@ -31,7 +31,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #include <asm/setup.h>
 #include <asm/io.h>
index dcfaa352d34c072fcee570059d5d29d62da4768b..5e0fcf41804d634a02b9d0d2d53122680b6ecef0 100644 (file)
@@ -23,7 +23,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/raw_io.h>
 #include <asm/virtconvert.h>
index 9ac047c400c45654b927374b23536971ae57b4cf..b4f48b2a6a572c956b8766e24550246c376c1872 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68K_IRQ_H_
 #define _M68K_IRQ_H_
 
-#include <linux/config.h>
 #include <linux/interrupt.h>
 
 /*
index 11442095a8cf408129286d992df4815b7b43bcfd..11fe12ddb913ca313cdc9416e9bd1163429c42ef 100644 (file)
@@ -4,7 +4,6 @@
 #ifndef _ASM_MC146818RTC_H
 #define _ASM_MC146818RTC_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_ATARI
 /* RTC in Atari machines */
index 661191d15c819880315f3436e56582654bd5cabb..231d11bd8e320921d6d869eef47edba1c4d52118 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __M68K_MMU_CONTEXT_H
 #define __M68K_MMU_CONTEXT_H
 
-#include <linux/config.h>
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
index 1628723458f5bc044f203eaa1d9e1037eae1fa53..1ccc7338a54bb5a5828e68911b43c8cf35aa1868 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _MOTOROLA_PGTABLE_H
 #define _MOTOROLA_PGTABLE_H
 
-#include <linux/config.h>
 
 /*
  * Definitions for MMU descriptors
index efbfb0bec6e236264d6669b1a1bbf5ff934a8a30..869ab9176e9fdca951b17e822efb96a324dadaaa 100644 (file)
@@ -8,7 +8,6 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/config.h>
 
 /* Empirical constants... */
 #ifdef CONFIG_SUN3
index f206dfbc1d486268aff67915433f5f2bf7d54f04..db017f838c2913dcff9ac66522cec7cbed82d64e 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68K_PAGE_H
 #define _M68K_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #ifndef CONFIG_SUN3
index 86d3c2845ad4e33fed7b59c3c96c6f5c5049221a..1cbdb7f30ac24b97a1d24dfb9b23d92ecce2cba5 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 
 /* This handles the memory map.. */
 #ifndef CONFIG_SUN3
index b468b7958aaaf2cae774bee984f772735bf2d770..a9cfb4b99d88b206c43d145694d588d6dc99524b 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef M68K_PGALLOC_H
 #define M68K_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <asm/setup.h>
index add129e93fd7076a5fadcf27134e5c71111b801f..f3aa05377987d0a08b50a040c56064fc87303bd3 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <asm/setup.h>
 
 #ifndef __ASSEMBLY__
index 7982285e84edcdaf3d3f3647b45ed87687ebb542..352799e71f0846eed8a176cdd681391e677ad3a1 100644 (file)
@@ -13,7 +13,6 @@
  */
 #define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
-#include <linux/config.h>
 #include <linux/thread_info.h>
 #include <asm/segment.h>
 #include <asm/fpu.h>
index 1516a642f9a57da31c0585a9f61eb1c9bc6841ed..eef30ba0b499f64e6b15c5831bac2becc7519f7f 100644 (file)
@@ -9,7 +9,6 @@
  * m68k version by Andreas Schwab
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 
 /*
index 3fe29f8b01948aa5493906175914a14aef6d6e3e..2b90d6e690700ba66e85370268b0aa2284794043 100644 (file)
@@ -6,7 +6,6 @@
  *
  */
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
index a89aa84073e5867f2928d0abda4d17ca726202e9..7facc9a46e74dde0ce6f792cab5fd3189fa1e003 100644 (file)
@@ -23,7 +23,6 @@
 #ifndef _M68K_SETUP_H
 #define _M68K_SETUP_H
 
-#include <linux/config.h>
 
 
     /*
index 3fa2f368fc1a653984f6ef4c1a3b2f31ef065ffc..fa56ec84a12642e5a9c4d02d433b6b39a85edf5b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68K_SHM_H
 #define _M68K_SHM_H
 
-#include <linux/config.h>
 
 /* format of page table entries that correspond to shared memory pages
    currently out in swap space (see also mm/swap.c):
index 64d3481df74c6a60bb730638550899b5689ed5c3..d6dd8052cd6f199f5775486ba416c7c2075c2d74 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68K_SYSTEM_H
 #define _M68K_SYSTEM_H
 
-#include <linux/config.h> /* get configuration macros */
 #include <linux/linkage.h>
 #include <linux/kernel.h>
 #include <asm/segment.h>
index 8e61ccffe13a361517e218cc63d508c463032e96..31678831ee470cb8409e5d24c194704a82943d02 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68K_TLBFLUSH_H
 #define _M68K_TLBFLUSH_H
 
-#include <linux/config.h>
 
 #ifndef CONFIG_SUN3
 
index c2554bcd17471a43588d0ab3719fbdc70c4a7d17..f236fe92156f4f6d0a727e233b6aaa44c7567f53 100644 (file)
 #define __NR_request_key       280
 #define __NR_keyctl            281
 
+#ifdef __KERNEL__
+
 #define NR_syscalls            282
 
 /* user-visible error numbers are in the range -1 - -124: see
@@ -383,7 +385,6 @@ __asm__ __volatile__ ("trap  #0" \
 __syscall_return(type,__res); \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -406,7 +407,6 @@ __syscall_return(type,__res); \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -451,7 +451,7 @@ asmlinkage long sys_rt_sigaction(int sig,
                                struct sigaction __user *oact,
                                size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -461,4 +461,5 @@ asmlinkage long sys_rt_sigaction(int sig,
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_M68K_UNISTD_H_ */
index 8c4e8037b89849a47de6d63a1620d95648279b65..83a87c9b1a16fa399f1dfa4126315b84f861421c 100644 (file)
@@ -7,7 +7,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/setup.h>
 #include <asm/page.h>
index 0b68ccd327f7454c3737fcdd92adc62baf11b6bc..d7fa7d9c0e0f0c87c80e82366be1b800b6de01aa 100644 (file)
@@ -5,7 +5,6 @@
  * Copyright 1992, Linus Torvalds.
  */
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/byteorder.h>     /* swab32 */
 #include <asm/system.h>                /* save_flags */
index 6190f77b1e6c9cd361d8439047ad6446d201465c..2fabca91df839d561181c739e7a10434e12db1d1 100644 (file)
@@ -12,7 +12,6 @@
 #define        coldfire_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Define the processor support peripherals base address.
index e522ca8193a2740ec7ac909ae52b96fb670ce474..0161ebb5d883f903e9bef07371ba2dbd5b79331f 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef __CPM_360__
 #define __CPM_360__
 
-#include <linux/config.h>
 
 /* CPM Command register masks: */
 #define CPM_CR_RST     ((ushort)0x8000)
index a6c42ba48da6afdf74092a4a8dee652443f559d1..5622b855a577ed190918e6b5206230991def7dbe 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68KNOMMU_DMA_MAPPING_H
 #define _M68KNOMMU_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
index 43e98c96a5c255b1cf2c07759f328526c3892075..3338001abb4017ec9cd1e2c2046f8a9fd3d5d1cd 100644 (file)
@@ -3,7 +3,6 @@
  
 //#define      DMA_DEBUG       1
 
-#include <linux/config.h>
 
 #ifdef CONFIG_COLDFIRE
 /*
index 9919487703bc6a898761e89f6b4ef3739edab843..40b1ed6827db5d2937feea7469860aa9c9752f6c 100644 (file)
@@ -5,7 +5,6 @@
  * ELF register definitions..
  */
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
index f18b8e9d8c363e5902b066f698174dd2c6af0190..e037d4e2de334c9f3388ef53def94270ba300014 100644 (file)
@@ -12,7 +12,6 @@
 #define        elia_h
 /****************************************************************************/
 
-#include <linux/config.h>
 #include <asm/coldfire.h>
 
 #ifdef CONFIG_eLIA
index 06f5aa70b0b524ed6e129ceff8aa7d934e3292c2..c2553d26273dc13b42f8c2486698ae56b71acdab 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __M68KNOMMU_ENTRY_H
 #define __M68KNOMMU_ENTRY_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 
index 225082991a03e06768662dc5e5cd64ffab73860b..b16b2e4fca2a1f2b18c3f3326ab325fb06d09d7f 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __M68KNOMMU_FPU_H
 #define __M68KNOMMU_FPU_H
 
-#include <linux/config.h>
 
 /*
  * MAX floating point unit state size (FSAVE/FRESTORE)
index 476180f4cba2b6518479b74ebbbbb1647a7f7376..980075bab792741e3ddb253767701062fa3a41cf 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __M68K_HARDIRQ_H
 #define __M68K_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/cache.h>
 #include <linux/threads.h>
 #include <asm/irq.h>
index e08f2ee4b4a29cb5c0ca9bb112b24f10601a80e2..8df4cee2a0cd272ee28339f75ae80772fde54f83 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * These are for ISA/PCI shared memory _only_ and should never be used
index 20c48ec858a4e785d6e480b5957d08ad1f6dd811..2b408842a30ecdedd39b07ec8b7d86b68cee8104 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68K_IRQ_H_
 #define _M68K_IRQ_H_
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 
 #ifdef CONFIG_COLDFIRE
index d1e7509021c5c2abf72e5fd22dacdfc086d78a9b..7e3594dea88b01af1c792e24dfb4922d5b540468 100644 (file)
@@ -12,7 +12,6 @@
 #define        m5206sim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Define the 5206 SIM register set addresses.
index 6dc62869e62be27ae7f8b351aa10f30592b3185c..1dac22ea95ba635cc8f1ac83aa607809229efc89 100644 (file)
@@ -11,7 +11,6 @@
 #define m520xsim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *  Define the 5282 SIM register set addresses.
index 926cfb805df7aea2a8b7658b4a251445c6935305..bf397313e93f11b380b6dc13120751df9a3d1699 100644 (file)
@@ -11,7 +11,6 @@
 #define        m523xsim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Define the 523x SIM register set addresses.
index b40875362f464f9a52f902219cea82adc1a54726..6217edc2113955f7f6d722baf6d704ec562ed194 100644 (file)
@@ -12,7 +12,6 @@
 #define        m5272sim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Define the 5272 SIM register set addresses.
index e7878d0f7d7a57d94003a0c9788fc858cbec88e9..1f63ab3fb3e671fd3b44ee731664c1a9c6709c86 100644 (file)
@@ -11,7 +11,6 @@
 #define        m527xsim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Define the 5270/5271 SIM register set addresses.
index 610774a17f70d86a00524fb1c1e88f99f9d484af..1a3b1ae06b1e788b828c2d489fab6ac039f80856 100644 (file)
@@ -11,7 +11,6 @@
 #define        m528xsim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Define the 5280/5282 SIM register set addresses.
index 9cb4014218351515226443804a96e73768ac17a6..45d1ac57ea829f7ec4cc66d28cfcc755c0616462 100644 (file)
@@ -11,7 +11,6 @@
 #define        __M68KNOMMU_MCFCACHE_H
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     The different ColdFire families have different cache arrangments.
index b93f8ba8a248e6269a0d8385217dc6f50893cb3a..ea729e81a6befe1f4f3b5b550277715de4beb532 100644 (file)
@@ -11,7 +11,6 @@
 #define        mcfdma_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Get address specific defines for this Coldfire member.
index 4762589e858a7178c350be5236395ae38278a41f..13df9d41bd1a89ce651f2ac92289569a50224672 100644 (file)
@@ -11,7 +11,6 @@
 
 #ifndef mcfmbus_h
 #define mcfmbus_h
-#include <linux/config.h>
 
 
 #define MCFMBUS_BASE           0x280
index a71b1c8cb4f858041fbadb252934f17c8955aa25..c920ccdb61fef26c82188658de184a5ced0dac3c 100644 (file)
@@ -18,7 +18,6 @@
 #define        mcfne_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Support for NE2000 clones devices in ColdFire based boards.
index d6229047d06e3be8494cb2daec14cf962ef031cb..f1507dd06ec6e731746d36471b2e4b01e54b6e49 100644 (file)
@@ -12,7 +12,6 @@
 #define        mcfpci_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 
index a685f1b45401df269c8b3a4f7e0fe9531ec26f32..0d2672dd518a3336e0d71f5be760fef98bd1ce5f 100644 (file)
@@ -11,7 +11,6 @@
 #define        mcfpit_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Get address specific defines for the 5270/5271, 5280/5282, and 5208.
index 81d74a31dc43712b4e4aeb52a855f81797ec8eed..97a0c2734a7292eaff2aad23e7a7e4e2fe3103ef 100644 (file)
@@ -12,7 +12,6 @@
 #define        mcfsim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Include 5204, 5206/e, 5235, 5249, 5270/5271, 5272, 5280/5282,
index 2583900b95913cc4a0d23c0ef26a826014c23803..2d7a4dbd96832a735f2a1300c67aab7181826782 100644 (file)
@@ -17,7 +17,6 @@
  *     allow 8 bit accesses. So this code is 16bit access only.
  */
 
-#include <linux/config.h>
 
 #undef outb
 #undef inb
index 0f47164c33a9d1234e802a77b63323a99d42444b..68bf33ac10d1834ccdecf61ef299e97d082ef515 100644 (file)
@@ -12,7 +12,6 @@
 #define        mcftimer_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Get address specific defines for this ColdFire member.
index b016fad83119a9b7cdfea60b51dd59a9ee43fc6f..8040e43786bebf37eba16da556b2c6d966db9411 100644 (file)
@@ -12,7 +12,6 @@
 #define        mcfuart_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *     Define the base address of the UARTS within the MBAR address
index 6ceae103596b3d0211f70e422a2e1512f2732031..27f70e45d700808cebcdebdb9afa4500fff0957b 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef mcfdebug_h
 #define mcfdebug_h
 /****************************************************************************/
-#include <linux/config.h>
 
 /* Define the debug module registers */
 #define MCFDEBUG_CSR   0x0                     /* Configuration status         */
index 1e080eca9ca8bb348607c934ed4cce1b692b9aff..6c077d3a2572c32bb6eaab0319fe5e24ceedeaa5 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __M68KNOMMU_MMU_CONTEXT_H
 #define __M68KNOMMU_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
index 9bda307e6544be02dea18d5ce52d4824eec29210..0299f6a2deeb62f548129f269a150218570b8789 100644 (file)
@@ -13,7 +13,6 @@
 #define        nettel_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /****************************************************************************/
 #ifdef CONFIG_NETtel
index 942dfbead27fa8f80a403b03420aa0543c294da4..a22bf5a88160d1eaf22f85c42cc92a703ea33de0 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68KNOMMU_PAGE_H
 #define _M68KNOMMU_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 
index 2b45645e9b29bf4327eb54ba28362685f06aa685..8ed6d7b7d9d104b4331f3c427e9a4c8b3c753fc9 100644 (file)
@@ -1,5 +1,4 @@
 
-#include <linux/config.h>
 
 /* This handles the memory map.. */
 
index 3f57d5db81f5968cd56ca170a11f195f15d73422..4c9904d6512ed6e278184fa56375d072239f0f07 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68KNOMMU_PARAM_H
 #define _M68KNOMMU_PARAM_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_CLEOPATRA)
 #define        HZ 1000
index 00893055e6c2c89669859082d19f6163a7298215..549ad231efadb0b1fc7cc76315b7781279327e32 100644 (file)
@@ -7,7 +7,6 @@
  * (C) Copyright 2000-2002, Greg Ungerer <gerg@snapgear.com>
  */
 
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <asm/processor.h>
 #include <asm/page.h>
index ba393b1a023b83102965627719c0e02b5ecf0a25..278b00bc60c5131ff89171fb906d00dfccddda59 100644 (file)
@@ -13,7 +13,6 @@
  */
 #define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/types.h>
 #include <asm/segment.h>
index a6586417c1c2144c3231868e9d0d1b83e4254c60..43da7bc483c79ad00ddf4f09666557324f613de6 100644 (file)
@@ -9,7 +9,6 @@
  * m68k version by Andreas Schwab
  */
 
-#include <linux/config.h>
 
 /*
  * These two _must_ execute atomically wrt each other.
index 6338afc850bad7e6a8d3e25c95f42d158a543f3f..2bbe2db00a22a7a3c1731ea0b574558580027fc0 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _M68KNOMMU_SYSTEM_H
 #define _M68KNOMMU_SYSTEM_H
 
-#include <linux/config.h> /* get configuration macros */
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/entry.h>
index 8876f034ea6486503134df5bd3be494b9b120aff..869e9dd24f544f276001793aeea97356c6230c0c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __M68K_UNALIGNED_H
 #define __M68K_UNALIGNED_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_COLDFIRE
 
index 5373988a7e519eec5f038c3b792a75960162de16..1b2abdf281e1800b62f66bdda3b7ff9a9057bfb9 100644 (file)
 #define __NR_request_key       280
 #define __NR_keyctl            281
  
+#ifdef __KERNEL__
+
 #define NR_syscalls            282
 
 /* user-visible error numbers are in the range -1 - -122: see
@@ -437,7 +439,6 @@ type name(atype a, btype b, ctype c, dtype d, etype e)                              \
   return (type)__res;                                                          \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -460,7 +461,6 @@ type name(atype a, btype b, ctype c, dtype d, etype e)                              \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -515,7 +515,7 @@ asmlinkage long sys_rt_sigaction(int sig,
                                struct sigaction __user *oact,
                                size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -525,4 +525,5 @@ asmlinkage long sys_rt_sigaction(int sig,
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_M68K_UNISTD_H_ */
index 2b3dc3bed4dac632a85114034722d00f9aa51d3b..ef33c3f1348446ceb3ca5bb41b2ac81977fdf4ae 100644 (file)
@@ -10,7 +10,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #endif
 
index 42520cc84b0f7d5074cb8e9fa6d08580b23099c4..45c706e34df1ba343e196aa73e5c4ccf814568b6 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_ADDRSPACE_H
 #define _ASM_ADDRSPACE_H
 
-#include <linux/config.h>
 #include <spaces.h>
 
 /*
 #if defined (CONFIG_CPU_R4300)                                         \
     || defined (CONFIG_CPU_R4X00)                                      \
     || defined (CONFIG_CPU_R5000)                                      \
+    || defined (CONFIG_CPU_RM7000)                                     \
     || defined (CONFIG_CPU_NEVADA)                                     \
     || defined (CONFIG_CPU_TX49XX)                                     \
     || defined (CONFIG_CPU_MIPS64)
-#define KUSIZE         _LLCONST_(0x0000010000000000)   /* 2^^40 */
-#define KUSIZE_64      _LLCONST_(0x0000010000000000)   /* 2^^40 */
-#define K0SIZE         _LLCONST_(0x0000001000000000)   /* 2^^36 */
-#define K1SIZE         _LLCONST_(0x0000001000000000)   /* 2^^36 */
-#define K2SIZE         _LLCONST_(0x000000ff80000000)
-#define KSEGSIZE       _LLCONST_(0x000000ff80000000)   /* max syssegsz */
 #define TO_PHYS_MASK   _LLCONST_(0x0000000fffffffff)   /* 2^^36 - 1 */
 #endif
 
 #if defined (CONFIG_CPU_R8000)
 /* We keep KUSIZE consistent with R4000 for now (2^^40) instead of (2^^48) */
-#define KUSIZE         _LLCONST_(0x0000010000000000)   /* 2^^40 */
-#define KUSIZE_64      _LLCONST_(0x0000010000000000)   /* 2^^40 */
-#define K0SIZE         _LLCONST_(0x0000010000000000)   /* 2^^40 */
-#define K1SIZE         _LLCONST_(0x0000010000000000)   /* 2^^40 */
-#define K2SIZE         _LLCONST_(0x0001000000000000)
-#define KSEGSIZE       _LLCONST_(0x0000010000000000)   /* max syssegsz */
 #define TO_PHYS_MASK   _LLCONST_(0x000000ffffffffff)   /* 2^^40 - 1 */
 #endif
 
 #if defined (CONFIG_CPU_R10000)
-#define KUSIZE         _LLCONST_(0x0000010000000000)   /* 2^^40 */
-#define KUSIZE_64      _LLCONST_(0x0000010000000000)   /* 2^^40 */
-#define K0SIZE         _LLCONST_(0x0000010000000000)   /* 2^^40 */
-#define K1SIZE         _LLCONST_(0x0000010000000000)   /* 2^^40 */
-#define K2SIZE         _LLCONST_(0x00000fff80000000)
-#define KSEGSIZE       _LLCONST_(0x00000fff80000000)   /* max syssegsz */
 #define TO_PHYS_MASK   _LLCONST_(0x000000ffffffffff)   /* 2^^40 - 1 */
 #endif
 
 #if defined(CONFIG_CPU_SB1) || defined(CONFIG_CPU_SB1A)
-#define KUSIZE         _LLCONST_(0x0000100000000000)   /* 2^^44 */
-#define KUSIZE_64      _LLCONST_(0x0000100000000000)   /* 2^^44 */
-#define K0SIZE         _LLCONST_(0x0000100000000000)   /* 2^^44 */
-#define K1SIZE         _LLCONST_(0x0000100000000000)   /* 2^^44 */
-#define K2SIZE         _LLCONST_(0x0000ffff80000000)
-#define KSEGSIZE       _LLCONST_(0x0000ffff80000000)   /* max syssegsz */
 #define TO_PHYS_MASK   _LLCONST_(0x00000fffffffffff)   /* 2^^44 - 1 */
 #endif
 
-/*
- * Further names for SGI source compatibility.  These are stolen from
- * IRIX's <sys/mips_addrspace.h>.
- */
-#define KUBASE         _LLCONST_(0)
-#define KUSIZE_32      _LLCONST_(0x0000000080000000)   /* KUSIZE
-                                                          for a 32 bit proc */
-#define K0BASE_EXL_WR  _LLCONST_(0xa800000000000000)   /* exclusive on write */
-#define K0BASE_NONCOH  _LLCONST_(0x9800000000000000)   /* noncoherent */
-#define K0BASE_EXL     _LLCONST_(0xa000000000000000)   /* exclusive */
-
 #ifndef CONFIG_CPU_R8000
 
 /*
diff --git a/include/asm-mips/apm.h b/include/asm-mips/apm.h
new file mode 100644 (file)
index 0000000..e8c6920
--- /dev/null
@@ -0,0 +1,65 @@
+/* -*- linux-c -*-
+ *
+ * (C) 2003 zecke@handhelds.org
+ *
+ * GPL version 2
+ *
+ * based on arch/arm/kernel/apm.c
+ * factor out the information needed by architectures to provide
+ * apm status
+ *
+ *
+ */
+#ifndef MIPS_ASM_SA1100_APM_H
+#define MIPS_ASM_SA1100_APM_H
+
+#include <linux/config.h>
+#include <linux/apm_bios.h>
+
+/*
+ * This structure gets filled in by the machine specific 'get_power_status'
+ * implementation.  Any fields which are not set default to a safe value.
+ */
+struct apm_power_info {
+       unsigned char   ac_line_status;
+#define APM_AC_OFFLINE                 0
+#define APM_AC_ONLINE                  1
+#define APM_AC_BACKUP                  2
+#define APM_AC_UNKNOWN                 0xff
+
+       unsigned char   battery_status;
+#define APM_BATTERY_STATUS_HIGH                0
+#define APM_BATTERY_STATUS_LOW         1
+#define APM_BATTERY_STATUS_CRITICAL    2
+#define APM_BATTERY_STATUS_CHARGING    3
+#define APM_BATTERY_STATUS_NOT_PRESENT 4
+#define APM_BATTERY_STATUS_UNKNOWN     0xff
+
+       unsigned char   battery_flag;
+#define APM_BATTERY_FLAG_HIGH          (1 << 0)
+#define APM_BATTERY_FLAG_LOW           (1 << 1)
+#define APM_BATTERY_FLAG_CRITICAL      (1 << 2)
+#define APM_BATTERY_FLAG_CHARGING      (1 << 3)
+#define APM_BATTERY_FLAG_NOT_PRESENT   (1 << 7)
+#define APM_BATTERY_FLAG_UNKNOWN       0xff
+
+       int             battery_life;
+       int             time;
+       int             units;
+#define APM_UNITS_MINS                 0
+#define APM_UNITS_SECS                 1
+#define APM_UNITS_UNKNOWN              -1
+
+};
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+extern void (*apm_get_power_status)(struct apm_power_info *);
+
+/*
+ * Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND)
+ */
+void apm_queue_event(apm_event_t event);
+
+#endif
index bbb725c366fb74f8e0008c7f86e64782e7e059ad..b9adcd6f0860ecd24dce55c55fab08f441f406d8 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_ARC_TYPES_H
 #define _ASM_ARC_TYPES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_ARC32
 
index 4b090f3142e0d6c74cde9f0e595b9272d18cec20..e3038a4599eef0f8ffa61693bd63a09a22cd2df2 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef __ASM_ASM_H
 #define __ASM_ASM_H
 
-#include <linux/config.h>
 #include <asm/sgidefs.h>
 
 #ifndef CAT
index 11daf5ceb7b4e6daebeb8a25690386521f397353..5de3963f511ec2c3a0607e6ee85bdf504e649639 100644 (file)
@@ -12,7 +12,7 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 
-       .macro  fpu_save_double thread status tmp1=t0 tmp2
+       .macro  fpu_save_double thread status tmp1=t0
        cfc1    \tmp1,  fcr31
        sdc1    $f0,  THREAD_FPR0(\thread)
        sdc1    $f2,  THREAD_FPR2(\thread)
@@ -70,7 +70,7 @@
        sw      \tmp, THREAD_FCR31(\thread)
        .endm
 
-       .macro  fpu_restore_double thread tmp=t0
+       .macro  fpu_restore_double thread status tmp=t0
        lw      \tmp, THREAD_FCR31(\thread)
        ldc1    $f0,  THREAD_FPR0(\thread)
        ldc1    $f2,  THREAD_FPR2(\thread)
index 559c355b9b868e007461fea60c17d4c4d6ac36f2..225feefcb25d606f7a5725bff61643ad955a94ec 100644 (file)
        sdc1    $f31, THREAD_FPR31(\thread)
        .endm
 
-       .macro  fpu_save_double thread status tmp1 tmp2
-       sll     \tmp2, \tmp1, 5
-       bgez    \tmp2, 2f
+       .macro  fpu_save_double thread status tmp
+       sll     \tmp, \status, 5
+       bgez    \tmp, 2f
        fpu_save_16odd \thread
 2:
-       fpu_save_16even \thread \tmp1                   # clobbers t1
+       fpu_save_16even \thread \tmp
        .endm
 
        .macro  fpu_restore_16even thread tmp=t0
        ldc1    $f31, THREAD_FPR31(\thread)
        .endm
 
-       .macro  fpu_restore_double thread tmp
-       mfc0    t0, CP0_STATUS
-       sll     t1, t0, 5
-       bgez    t1, 1f                          # 16 register mode?
+       .macro  fpu_restore_double thread status tmp
+       sll     \tmp, \status, 5
+       bgez    \tmp, 1f                                # 16 register mode?
 
-       fpu_restore_16odd a0
-1:     fpu_restore_16even a0, t0               # clobbers t0
+       fpu_restore_16odd \thread
+1:     fpu_restore_16even \thread \tmp
        .endm
 
        .macro  cpu_save_nonscratch thread
index f54aa147ec19066ac6aa9f729f72e78f35958153..2c42f6b00a49e2f171d09043395e35d39781e947 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _ASM_ASMMACRO_H
 #define _ASM_ASMMACRO_H
 
-#include <linux/config.h>
 #include <asm/hazards.h>
 
 #ifdef CONFIG_32BIT
index 2c8b853376c995892680d5cf3f9b139b57bc5b5b..13d44e14025ac873ce8921bb7dc25d52ca47997d 100644 (file)
@@ -17,7 +17,6 @@
  * <linux/spinlock.h> we have to include <linux/spinlock.h> outside the
  * main big wrapper ...
  */
-#include <linux/config.h>
 #include <linux/spinlock.h>
 
 #ifndef _ASM_ATOMIC_H
index 446102b34f4e8702088025ca67cb71ac22c6ebc3..3646a3f2ed3863240ecd86b97b84de3a4533ab11 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_BCACHE_H
 #define _ASM_BCACHE_H
 
-#include <linux/config.h>
 
 /* Some R4000 / R4400 / R4600 / R5000 machines may have a non-dma-coherent,
    chipset implemented caches.  On machines with other CPUs the CPU does the
index d2f444537e4b3266c67473e763752677c2a54538..098cec263681b47cb925266cdef2bc2034482253 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_BITOPS_H
 #define _ASM_BITOPS_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <asm/bug.h>
index 14fc88f2722640bc364ad563f700cffc22e171c8..3b745e76f429bd0bea3e2615d33136bdc82ba9e1 100644 (file)
  */
 #define MACH_GROUP_TITAN       22      /* PMC-Sierra Titan             */
 #define  MACH_TITAN_YOSEMITE   1       /* PMC-Sierra Yosemite          */
+#define  MACH_TITAN_EXCITE     2       /* Basler eXcite                */
+
+/*
+ * Valid machtype for group NEC EMMA2RH
+ */
+#define MACH_GROUP_NEC_EMMA2RH 25      /* NEC EMMA2RH (was 23)         */
+#define  MACH_NEC_MARKEINS     0       /* NEC EMMA2RH Mark-eins        */
 
 #define CL_SIZE                        COMMAND_LINE_SIZE
 
@@ -258,4 +265,10 @@ extern char arcs_cmdline[CL_SIZE];
  * Registers a0, a1, a3 and a4 as passed to the kenrel entry by firmware
  */
 extern unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
+
+/*
+ * Platform memory detection hook called by setup_arch
+ */
+extern void plat_mem_setup(void);
+
 #endif /* _ASM_BOOTINFO_H */
index 87d49a5bdc63a5863a49f912bd3048694c6c1b59..7b4739dc8f3f28387ac71a26e11089dddbc1cff5 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_BUG_H
 #define __ASM_BUG_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_BUG
 
index cb2ea7c15c7ac66ce79a4b7a94c0bb96f4765f51..0d7f9c1f55469e4c7d9700ba44bb3ad75b787ba6 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _ASM_BUGS_H
 #define _ASM_BUGS_H
 
-#include <linux/config.h>
 #include <linux/delay.h>
 #include <asm/cpu.h>
 #include <asm/cpu-info.h>
index aefc02f16fd84319c3cdd46ced02e60569edc8e5..eee83cbdf2b08c7a22644255b153a8fcace0ec5e 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _ASM_BYTEORDER_H
 #define _ASM_BYTEORDER_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/types.h>
 
index 55e19f2ff0e012474a2d0f4c94a123e5e72bc9d9..37f175c42bb5530c9c7c76655cb54e94722597fe 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_CACHE_H
 #define _ASM_CACHE_H
 
-#include <linux/config.h>
 #include <kmalloc.h>
 
 #define L1_CACHE_SHIFT         CONFIG_MIPS_L1_CACHE_SHIFT
index b09f8971e95d7fd1ba8ebb1f7ae1a9b758eec826..a5e6050ec0f3942c6ef25886b41d14d41c0dc286 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_CHECKSUM_H
 #define _ASM_CHECKSUM_H
 
-#include <linux/config.h>
 #include <linux/in6.h>
 
 #include <asm/uaccess.h>
index 254e11ed247b04cc4085782a51bd067f21db9e1b..881ce1f9803da703f0b8681ed0459f01c7c67dc3 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef __ASM_CPU_FEATURES_H
 #define __ASM_CPU_FEATURES_H
 
-#include <linux/config.h>
 
 #include <asm/cpu.h>
 #include <asm/cpu-info.h>
index 6572ac703662068da6de5ad81c8b952aec4ee591..a2f0c8ea916090ae07ee0d997bf9e23a0aa0b090 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_CPU_INFO_H
 #define __ASM_CPU_INFO_H
 
-#include <linux/config.h>
 #include <asm/cache.h>
 
 #ifdef CONFIG_SGI_IP27
index 818b9a97e214280c0c6a93af52699028e32a95bb..dff2a0a52f8f300e6979b79a2848c88c71b42cd6 100644 (file)
@@ -51,6 +51,7 @@
 #define PRID_IMP_R4300         0x0b00
 #define PRID_IMP_VR41XX                0x0c00
 #define PRID_IMP_R12000                0x0e00
+#define PRID_IMP_R14000                0x0f00
 #define PRID_IMP_R8000         0x1000
 #define PRID_IMP_PR4450                0x1200
 #define PRID_IMP_R4600         0x2000
@@ -87,6 +88,7 @@
 #define PRID_IMP_24K           0x9300
 #define PRID_IMP_34K           0x9500
 #define PRID_IMP_24KE          0x9600
+#define PRID_IMP_74K           0x9700
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
 #define CPU_34K                        60
 #define CPU_PR4450             61
 #define CPU_SB1A               62
-#define CPU_LAST               62
+#define CPU_74K                        63
+#define CPU_R14000             64
+#define CPU_LAST               64
 
 /*
  * ISA Level encodings
diff --git a/include/asm-mips/ddb5074.h b/include/asm-mips/ddb5074.h
deleted file mode 100644 (file)
index 0d09ac2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- *  include/asm-mips/ddb5074.h -- NEC DDB Vrc-5074 definitions
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-
-extern void ddb5074_led_hex(int hex);
-extern void ddb5074_led_d2(int on);
-extern void ddb5074_led_d3(int on);
-
diff --git a/include/asm-mips/ddb5xxx/ddb5074.h b/include/asm-mips/ddb5xxx/ddb5074.h
deleted file mode 100644 (file)
index 58d8830..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  include/asm-mips/ddb5074.h -- NEC DDB Vrc-5074 definitions
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-
-#ifndef _ASM_DDB5XXX_DDB5074_H
-#define _ASM_DDB5XXX_DDB5074_H
-
-#include <asm/nile4.h>
-
-#define DDB_SDRAM_SIZE      0x04000000      /* 64MB */
-
-#define DDB_PCI_IO_BASE     0x06000000
-#define DDB_PCI_IO_SIZE     0x02000000      /* 32 MB */
-
-#define DDB_PCI_MEM_BASE    0x08000000
-#define DDB_PCI_MEM_SIZE    0x08000000  /* 128 MB */
-
-#define DDB_PCI_CONFIG_BASE DDB_PCI_MEM_BASE
-#define DDB_PCI_CONFIG_SIZE DDB_PCI_MEM_SIZE
-
-#define NILE4_PCI_IO_BASE   0xa6000000
-#define NILE4_PCI_MEM_BASE  0xa8000000
-#define NILE4_PCI_CFG_BASE  NILE4_PCI_MEM_BASE
-#define DDB_PCI_IACK_BASE NILE4_PCI_IO_BASE
-
-#define NILE4_IRQ_BASE NUM_I8259_INTERRUPTS
-#define CPU_IRQ_BASE (NUM_NILE4_INTERRUPTS + NILE4_IRQ_BASE)
-#define CPU_NILE4_CASCADE 2
-
-extern void ddb5074_led_hex(int hex);
-extern void ddb5074_led_d2(int on);
-extern void ddb5074_led_d3(int on);
-
-extern void nile4_irq_setup(u32 base);
-#endif
diff --git a/include/asm-mips/ddb5xxx/ddb5476.h b/include/asm-mips/ddb5xxx/ddb5476.h
deleted file mode 100644 (file)
index 4c23390..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * header file specific for ddb5476
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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.
- *
- */
-
-/*
- *  Memory map (physical address)
- *
- *  Note most of the following address must be properly aligned by the
- *  corresponding size.  For example, if PCI_IO_SIZE is 16MB, then
- *  PCI_IO_BASE must be aligned along 16MB boundary.
- */
-#define DDB_SDRAM_BASE         0x00000000
-#define DDB_SDRAM_SIZE         0x04000000      /* 64MB */
-
-#define        DDB_DCS3_BASE           0x04000000      /* flash 1 */
-#define        DDB_DCS3_SIZE           0x01000000      /* 16MB */
-
-#define        DDB_DCS2_BASE           0x05000000      /* flash 2 */
-#define        DDB_DCS2_SIZE           0x01000000      /* 16MB */
-
-#define DDB_PCI_IO_BASE                0x06000000
-#define DDB_PCI_IO_SIZE                0x02000000      /* 32 MB */
-
-#define        DDB_PCI_MEM_BASE        0x08000000
-#define        DDB_PCI_MEM_SIZE        0x08000000      /* 128 MB */
-
-#define        DDB_DCS5_BASE           0x13000000      /* DDB status regs */
-#define        DDB_DCS5_SIZE           0x00200000      /* 2MB, 8-bit */
-
-#define        DDB_DCS4_BASE           0x14000000      /* DDB control regs */
-#define        DDB_DCS4_SIZE           0x00200000      /* 2MB, 8-bit */
-
-#define DDB_INTCS_BASE         0x1fa00000      /* VRC5476 control regs */
-#define DDB_INTCS_SIZE         0x00200000      /* 2MB */
-
-#define DDB_BOOTCS_BASE         0x1fc00000      /* Boot ROM / EPROM /Flash */
-#define DDB_BOOTCS_SIZE         0x00200000      /* 2 MB - doc says 4MB */
-
-
-/* aliases */
-#define        DDB_PCI_CONFIG_BASE     DDB_PCI_MEM_BASE
-#define        DDB_PCI_CONFIG_SIZE     DDB_PCI_MEM_SIZE
-
-/* PCI intr ack share PCIW0 with PCI IO */
-#define        DDB_PCI_IACK_BASE       DDB_PCI_IO_BASE
-
-/*
- * Interrupt mapping
- *
- * We have three interrupt controllers:
- *
- *   . CPU itself - 8 sources
- *   . i8259 - 16 sources
- *   . vrc5476 - 16 sources
- *
- *  They connected as follows:
- *    all vrc5476 interrupts are routed to cpu IP2 (by software setting)
- *    all i2869 are routed to INTC in vrc5476 (by hardware connection)
- *
- *  All VRC5476 PCI interrupts are level-triggered (no ack needed).
- *  All PCI irq but INTC are active low.
- */
-
-/*
- * irq number block assignment
- */
-
-#define        NUM_CPU_IRQ             8
-#define        NUM_I8259_IRQ           16
-#define        NUM_VRC5476_IRQ         16
-
-#define        DDB_IRQ_BASE            0
-
-#define        I8259_IRQ_BASE          DDB_IRQ_BASE
-#define        VRC5476_IRQ_BASE        (I8259_IRQ_BASE + NUM_I8259_IRQ)
-#define        CPU_IRQ_BASE            (VRC5476_IRQ_BASE + NUM_VRC5476_IRQ)
-
-/*
- * vrc5476 irq defs, see page 52-64 of Vrc5074 system controller manual
- */
-
-#define VRC5476_IRQ_CPCE       0       /* cpu parity error */
-#define VRC5476_IRQ_CNTD       1       /* cpu no target */
-#define VRC5476_IRQ_MCE                2       /* memory check error */
-#define VRC5476_IRQ_DMA                3       /* DMA */
-#define VRC5476_IRQ_UART       4       /* vrc5476 builtin UART, not used */
-#define VRC5476_IRQ_WDOG       5       /* watchdog timer */
-#define VRC5476_IRQ_GPT                6       /* general purpose timer */
-#define VRC5476_IRQ_LBRT       7       /* local bus read timeout */
-#define VRC5476_IRQ_INTA       8       /* PCI INT #A */
-#define VRC5476_IRQ_INTB       9       /* PCI INT #B */
-#define VRC5476_IRQ_INTC       10      /* PCI INT #C */
-#define VRC5476_IRQ_INTD       11      /* PCI INT #D */
-#define VRC5476_IRQ_INTE       12      /* PCI INT #E */
-#define VRC5476_IRQ_RESERVED_13        13      /* reserved  */
-#define VRC5476_IRQ_PCIS       14      /* PCI SERR #  */
-#define VRC5476_IRQ_PCI                15      /* PCI internal error */
-
-/*
- * i2859 irq assignment
- */
-#define I8259_IRQ_RESERVED_0   0
-#define I8259_IRQ_KEYBOARD     1       /* M1543 default */
-#define I8259_IRQ_CASCADE      2
-#define I8259_IRQ_UART_B       3       /* M1543 default, may conflict with RTC according to schematic diagram  */
-#define I8259_IRQ_UART_A       4       /* M1543 default */
-#define I8259_IRQ_PARALLEL     5       /* M1543 default */
-#define I8259_IRQ_RESERVED_6   6
-#define I8259_IRQ_RESERVED_7   7
-#define I8259_IRQ_RTC          8       /* who set this? */
-#define I8259_IRQ_USB          9       /* ddb_setup */
-#define I8259_IRQ_PMU          10      /* ddb_setup */
-#define I8259_IRQ_RESERVED_11  11
-#define I8259_IRQ_RESERVED_12  12      /* m1543_irq_setup */
-#define I8259_IRQ_RESERVED_13  13
-#define I8259_IRQ_HDC1         14      /* default and ddb_setup */
-#define I8259_IRQ_HDC2         15      /* default */
-
-
-/*
- * misc
- */
-#define        VRC5476_I8259_CASCADE   VRC5476_IRQ_INTC
-#define        CPU_VRC5476_CASCADE     2
-
-#define is_i8259_irq(irq)       ((irq) < NUM_I8259_IRQ)
-#define nile4_to_irq(n)         ((n)+NUM_I8259_IRQ)
-#define irq_to_nile4(n)         ((n)-NUM_I8259_IRQ)
-
-/*
- * low-level irq functions
- */
-#ifndef __ASSEMBLY__
-extern void nile4_map_irq(int nile4_irq, int cpu_irq);
-extern void nile4_map_irq_all(int cpu_irq);
-extern void nile4_enable_irq(int nile4_irq);
-extern void nile4_disable_irq(int nile4_irq);
-extern void nile4_disable_irq_all(void);
-extern u16 nile4_get_irq_stat(int cpu_irq);
-extern void nile4_enable_irq_output(int cpu_irq);
-extern void nile4_disable_irq_output(int cpu_irq);
-extern void nile4_set_pci_irq_polarity(int pci_irq, int high);
-extern void nile4_set_pci_irq_level_or_edge(int pci_irq, int level);
-extern void nile4_clear_irq(int nile4_irq);
-extern void nile4_clear_irq_mask(u32 mask);
-extern u8 nile4_i8259_iack(void);
-extern void nile4_dump_irq_status(void);        /* Debug */
-#endif /* !__ASSEMBLY__ */
index a438548e6ef3b6c9930f7bf52640ba65a23b5e2d..c5af4b73fdd77ef3cb7fda33fa88ee8f31217264 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef __ASM_DDB5XXX_DDB5477_H
 #define __ASM_DDB5XXX_DDB5477_H
 
-#include <linux/config.h>
 
 /*
  * This contains macros that are specific to DDB5477 or renamed from
index 873c03f2c5fe8385340099b2b92a2130a1be63cb..e97fcc8d548b3d367a35a38cac1d99e2cd8430c5 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __ASM_DDB5XXX_DDB5XXX_H
 #define __ASM_DDB5XXX_DDB5XXX_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /*
 
 static inline void ddb_sync(void)
 {
-/* The DDB5074 doesn't seem to like these accesses. They kill the board on
- * interrupt load
- */
-#ifndef CONFIG_DDB5074
     volatile u32 *p = (volatile u32 *)0xbfc00000;
     (void)(*p);
-#endif
 }
 
 static inline void ddb_out32(u32 offset, u32 val)
@@ -260,11 +254,7 @@ extern void ddb_pci_reset_bus(void);
 /*
  * include the board dependent part
  */
-#if defined(CONFIG_DDB5074)
-#include <asm/ddb5xxx/ddb5074.h>
-#elif defined(CONFIG_DDB5476)
-#include <asm/ddb5xxx/ddb5476.h>
-#elif defined(CONFIG_DDB5477)
+#if defined(CONFIG_DDB5477)
 #include <asm/ddb5xxx/ddb5477.h>
 #else
 #error "Unknown DDB board!"
index 930f2b75e766c2f8d087bc9363dae4f55e5aebef..1fd5a2b39445a97122189e06980d2ce884dd6d2a 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _ASM_DEBUG_H
 #define _ASM_DEBUG_H
 
-#include <linux/config.h>
 
 /*
  * run-time macros for catching spurious errors.  Eable CONFIG_RUNTIME_DEBUG in
index 1384dd0964b91c117ea508aa56dd74332445213f..b9c8203688d5cd3ac8e1fc8a865f5f194fd98439 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _ASM_DEC_PROM_H
 #define _ASM_DEC_PROM_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
index 64dd45150f64f69e38c7116a28a05a0c508015ae..ea77050f8e3a6f3266bd80a13126f79b35c964bb 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_DELAY_H
 #define _ASM_DELAY_H
 
-#include <linux/config.h>
 #include <linux/param.h>
 #include <linux/smp.h>
 #include <asm/compiler.h>
@@ -19,20 +18,22 @@ static inline void __delay(unsigned long loops)
 {
        if (sizeof(long) == 4)
                __asm__ __volatile__ (
-               ".set\tnoreorder\n"
-               "1:\tbnez\t%0,1b\n\t"
-               "subu\t%0,1\n\t"
-               ".set\treorder"
+               "       .set    noreorder                               \n"
+               "       .align  3                                       \n"
+               "1:     bnez    %0, 1b                                  \n"
+               "       subu    %0, 1                                   \n"
+               "       .set    reorder                                 \n"
                : "=r" (loops)
                : "0" (loops));
        else if (sizeof(long) == 8)
                __asm__ __volatile__ (
-               ".set\tnoreorder\n"
-               "1:\tbnez\t%0,1b\n\t"
-               "dsubu\t%0,1\n\t"
-               ".set\treorder"
-               :"=r" (loops)
-               :"0" (loops));
+               "       .set    noreorder                               \n"
+               "       .align  3                                       \n"
+               "1:     bnez    %0, 1b                                  \n"
+               "       dsubu   %0, 1                                   \n"
+               "       .set    reorder                                 \n"
+               : "=r" (loops)
+               : "0" (loops));
 }
 
 
index 6aaf9939a716212d5c16fbb505bad98b32629435..e85849ac165fc5a1f30811328e3b8a20577c634d 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <asm/io.h>                    /* need byte IO */
 #include <linux/spinlock.h>            /* And spinlocks */
 #include <linux/delay.h>
index bdc9de2df1ef28d52644252ab060de9969f6ab2c..ebd6bfb19d667117f194048db9534885adc4a99c 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _ASM_ELF_H
 #define _ASM_ELF_H
 
-#include <linux/config.h>
 
 /* ELF header e_flags defines. */
 /* MIPS architecture level. */
diff --git a/include/asm-mips/emma2rh/emma2rh.h b/include/asm-mips/emma2rh/emma2rh.h
new file mode 100644 (file)
index 0000000..4fb8df7
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ *  include/asm-mips/emma2rh/emma2rh.h
+ *      This file is EMMA2RH common header.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file based on include/asm-mips/ddb5xxx/ddb5xxx.h
+ *          Copyright 2001 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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_EMMA2RH_EMMA2RH_H
+#define __ASM_EMMA2RH_EMMA2RH_H
+
+/*
+ * EMMA2RH registers
+ */
+#define REGBASE 0x10000000
+
+#define EMMA2RH_BHIF_STRAP_0   (0x000010+REGBASE)
+#define EMMA2RH_BHIF_INT_ST_0  (0x000030+REGBASE)
+#define EMMA2RH_BHIF_INT_ST_1  (0x000034+REGBASE)
+#define EMMA2RH_BHIF_INT_ST_2  (0x000038+REGBASE)
+#define EMMA2RH_BHIF_INT_EN_0  (0x000040+REGBASE)
+#define EMMA2RH_BHIF_INT_EN_1  (0x000044+REGBASE)
+#define EMMA2RH_BHIF_INT_EN_2  (0x000048+REGBASE)
+#define EMMA2RH_BHIF_INT1_EN_0 (0x000050+REGBASE)
+#define EMMA2RH_BHIF_INT1_EN_1 (0x000054+REGBASE)
+#define EMMA2RH_BHIF_INT1_EN_2 (0x000058+REGBASE)
+#define EMMA2RH_BHIF_SW_INT    (0x000070+REGBASE)
+#define EMMA2RH_BHIF_SW_INT_EN (0x000080+REGBASE)
+#define EMMA2RH_BHIF_SW_INT_CLR        (0x000090+REGBASE)
+#define EMMA2RH_BHIF_MAIN_CTRL (0x0000b4+REGBASE)
+#define EMMA2RH_BHIF_EXCEPT_VECT_BASE_ADDRESS  (0x0000c0+REGBASE)
+#define EMMA2RH_GPIO_DIR       (0x110d20+REGBASE)
+#define EMMA2RH_GPIO_INT_ST    (0x110d30+REGBASE)
+#define EMMA2RH_GPIO_INT_MASK  (0x110d3c+REGBASE)
+#define EMMA2RH_GPIO_INT_MODE  (0x110d48+REGBASE)
+#define EMMA2RH_GPIO_INT_CND_A (0x110d54+REGBASE)
+#define EMMA2RH_GPIO_INT_CND_B (0x110d60+REGBASE)
+#define EMMA2RH_PBRD_INT_EN    (0x100010+REGBASE)
+#define EMMA2RH_PBRD_CLKSEL    (0x100028+REGBASE)
+#define EMMA2RH_PFUR0_BASE     (0x101000+REGBASE)
+#define EMMA2RH_PFUR1_BASE     (0x102000+REGBASE)
+#define EMMA2RH_PFUR2_BASE     (0x103000+REGBASE)
+#define EMMA2RH_PIIC0_BASE     (0x107000+REGBASE)
+#define EMMA2RH_PIIC1_BASE     (0x108000+REGBASE)
+#define EMMA2RH_PIIC2_BASE     (0x109000+REGBASE)
+#define EMMA2RH_PCI_CONTROL    (0x200000+REGBASE)
+#define EMMA2RH_PCI_ARBIT_CTR  (0x200004+REGBASE)
+#define EMMA2RH_PCI_IWIN0_CTR  (0x200010+REGBASE)
+#define EMMA2RH_PCI_IWIN1_CTR  (0x200014+REGBASE)
+#define EMMA2RH_PCI_INIT_ESWP  (0x200018+REGBASE)
+#define EMMA2RH_PCI_INT                (0x200020+REGBASE)
+#define EMMA2RH_PCI_INT_EN     (0x200024+REGBASE)
+#define EMMA2RH_PCI_TWIN_CTR   (0x200030+REGBASE)
+#define EMMA2RH_PCI_TWIN_BADR  (0x200034+REGBASE)
+#define EMMA2RH_PCI_TWIN0_DADR (0x200038+REGBASE)
+#define EMMA2RH_PCI_TWIN1_DADR (0x20003c+REGBASE)
+
+/*
+ *  Memory map (physical address)
+ *
+ *  Note most of the following address must be properly aligned by the
+ *  corresponding size.  For example, if PCI_IO_SIZE is 16MB, then
+ *  PCI_IO_BASE must be aligned along 16MB boundary.
+ */
+
+/* the actual ram size is detected at run-time */
+#define EMMA2RH_RAM_BASE       0x00000000
+#define EMMA2RH_RAM_SIZE       0x10000000      /* less than 256MB */
+
+#define EMMA2RH_IO_BASE                0x10000000
+#define EMMA2RH_IO_SIZE                0x01000000      /* 16 MB */
+
+#define EMMA2RH_GENERALIO_BASE 0x11000000
+#define EMMA2RH_GENERALIO_SIZE 0x01000000      /* 16 MB */
+
+#define EMMA2RH_PCI_IO_BASE    0x12000000
+#define EMMA2RH_PCI_IO_SIZE    0x02000000      /* 32 MB */
+
+#define EMMA2RH_PCI_MEM_BASE   0x14000000
+#define EMMA2RH_PCI_MEM_SIZE   0x08000000      /* 128 MB */
+
+#define EMMA2RH_ROM_BASE       0x1c000000
+#define EMMA2RH_ROM_SIZE       0x04000000      /* 64 MB */
+
+#define EMMA2RH_PCI_CONFIG_BASE        EMMA2RH_PCI_IO_BASE
+#define EMMA2RH_PCI_CONFIG_SIZE        EMMA2RH_PCI_IO_SIZE
+
+#define NUM_CPU_IRQ            8
+#define NUM_EMMA2RH_IRQ                96
+
+#define CPU_EMMA2RH_CASCADE    2
+#define EMMA2RH_IRQ_BASE       0
+
+/*
+ * emma2rh irq defs
+ */
+
+#define EMMA2RH_IRQ_INT0       (0 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT1       (1 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT2       (2 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT3       (3 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT4       (4 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT5       (5 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT6       (6 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT7       (7 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT8       (8 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT9       (9 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT10      (10 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT11      (11 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT12      (12 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT13      (13 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT14      (14 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT15      (15 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT16      (16 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT17      (17 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT18      (18 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT19      (19 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT20      (20 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT21      (21 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT22      (22 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT23      (23 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT24      (24 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT25      (25 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT26      (26 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT27      (27 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT28      (28 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT29      (29 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT30      (30 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT31      (31 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT32      (32 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT33      (33 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT34      (34 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT35      (35 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT36      (36 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT37      (37 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT38      (38 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT39      (39 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT40      (40 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT41      (41 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT42      (42 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT43      (43 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT44      (44 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT45      (45 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT46      (46 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT47      (47 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT48      (48 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT49      (49 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT50      (50 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT51      (51 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT52      (52 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT53      (53 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT54      (54 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT55      (55 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT56      (56 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT57      (57 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT58      (58 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT59      (59 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT60      (60 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT61      (61 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT62      (62 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT63      (63 + EMMA2RH_IRQ_BASE)
+
+#define EMMA2RH_IRQ_PFUR0      EMMA2RH_IRQ_INT49
+#define EMMA2RH_IRQ_PFUR1      EMMA2RH_IRQ_INT50
+#define EMMA2RH_IRQ_PFUR2      EMMA2RH_IRQ_INT51
+#define EMMA2RH_IRQ_PIIC0      EMMA2RH_IRQ_INT56
+#define EMMA2RH_IRQ_PIIC1      EMMA2RH_IRQ_INT57
+#define EMMA2RH_IRQ_PIIC2      EMMA2RH_IRQ_INT58
+
+/*
+ *  EMMA2RH Register Access
+ */
+
+#define EMMA2RH_BASE (0xa0000000)
+
+static inline void emma2rh_sync(void)
+{
+       volatile u32 *p = (volatile u32 *)0xbfc00000;
+       (void)(*p);
+}
+
+static inline void emma2rh_out32(u32 offset, u32 val)
+{
+       *(volatile u32 *)(EMMA2RH_BASE | offset) = val;
+       emma2rh_sync();
+}
+
+static inline u32 emma2rh_in32(u32 offset)
+{
+       u32 val = *(volatile u32 *)(EMMA2RH_BASE | offset);
+       emma2rh_sync();
+       return val;
+}
+
+static inline void emma2rh_out16(u32 offset, u16 val)
+{
+       *(volatile u16 *)(EMMA2RH_BASE | offset) = val;
+       emma2rh_sync();
+}
+
+static inline u16 emma2rh_in16(u32 offset)
+{
+       u16 val = *(volatile u16 *)(EMMA2RH_BASE | offset);
+       emma2rh_sync();
+       return val;
+}
+
+static inline void emma2rh_out8(u32 offset, u8 val)
+{
+       *(volatile u8 *)(EMMA2RH_BASE | offset) = val;
+       emma2rh_sync();
+}
+
+static inline u8 emma2rh_in8(u32 offset)
+{
+       u8 val = *(volatile u8 *)(EMMA2RH_BASE | offset);
+       emma2rh_sync();
+       return val;
+}
+
+/**
+ * IIC registers map
+ **/
+
+/*---------------------------------------------------------------------------*/
+/* CNT - Control register (00H R/W)                                          */
+/*---------------------------------------------------------------------------*/
+#define SPT         0x00000001
+#define STT         0x00000002
+#define ACKE        0x00000004
+#define WTIM        0x00000008
+#define SPIE        0x00000010
+#define WREL        0x00000020
+#define LREL        0x00000040
+#define IICE        0x00000080
+#define CNT_RESERVED    0x000000ff     /* reserved bit 0 */
+
+#define I2C_EMMA_START      (IICE | STT)
+#define I2C_EMMA_STOP       (IICE | SPT)
+#define I2C_EMMA_REPSTART   I2C_EMMA_START
+
+/*---------------------------------------------------------------------------*/
+/* STA - Status register (10H Read)                                          */
+/*---------------------------------------------------------------------------*/
+#define MSTS        0x00000080
+#define ALD         0x00000040
+#define EXC         0x00000020
+#define COI         0x00000010
+#define TRC         0x00000008
+#define ACKD        0x00000004
+#define STD         0x00000002
+#define SPD         0x00000001
+
+/*---------------------------------------------------------------------------*/
+/* CSEL - Clock select register (20H R/W)                                    */
+/*---------------------------------------------------------------------------*/
+#define FCL         0x00000080
+#define ND50        0x00000040
+#define CLD         0x00000020
+#define DAD         0x00000010
+#define SMC         0x00000008
+#define DFC         0x00000004
+#define CL          0x00000003
+#define CSEL_RESERVED   0x000000ff     /* reserved bit 0 */
+
+#define FAST397     0x0000008b
+#define FAST297     0x0000008a
+#define FAST347     0x0000000b
+#define FAST260     0x0000000a
+#define FAST130     0x00000008
+#define STANDARD108 0x00000083
+#define STANDARD83  0x00000082
+#define STANDARD95  0x00000003
+#define STANDARD73  0x00000002
+#define STANDARD36  0x00000001
+#define STANDARD71  0x00000000
+
+/*---------------------------------------------------------------------------*/
+/* SVA - Slave address register (30H R/W)                                    */
+/*---------------------------------------------------------------------------*/
+#define SVA         0x000000fe
+
+/*---------------------------------------------------------------------------*/
+/* SHR - Shift register (40H R/W)                                            */
+/*---------------------------------------------------------------------------*/
+#define SR          0x000000ff
+
+/*---------------------------------------------------------------------------*/
+/* INT - Interrupt register (50H R/W)                                        */
+/* INTM - Interrupt mask register (60H R/W)                                  */
+/*---------------------------------------------------------------------------*/
+#define INTE0       0x00000001
+
+/***********************************************************************
+ * I2C registers
+ ***********************************************************************
+ */
+#define I2C_EMMA_CNT            0x00
+#define I2C_EMMA_STA            0x10
+#define I2C_EMMA_CSEL           0x20
+#define I2C_EMMA_SVA            0x30
+#define I2C_EMMA_SHR            0x40
+#define I2C_EMMA_INT            0x50
+#define I2C_EMMA_INTM           0x60
+
+/*
+ * include the board dependent part
+ */
+#if defined(CONFIG_MARKEINS)
+#include <asm/emma2rh/markeins.h>
+#else
+#error "Unknown EMMA2RH board!"
+#endif
+
+#endif /* __ASM_EMMA2RH_EMMA2RH_H */
diff --git a/include/asm-mips/emma2rh/markeins.h b/include/asm-mips/emma2rh/markeins.h
new file mode 100644 (file)
index 0000000..8fa7667
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  include/asm-mips/emma2rh/markeins.h
+ *      This file is EMMA2RH board depended header.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file based on include/asm-mips/ddb5xxx/ddb5xxx.h
+ *          Copyright 2001 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.
+ *
+ *  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 MARKEINS_H
+#define MARKEINS_H
+
+#define NUM_EMMA2RH_IRQ_SW     32
+#define NUM_EMMA2RH_IRQ_GPIO   32
+
+#define EMMA2RH_SW_CASCADE     (EMMA2RH_IRQ_INT7 - EMMA2RH_IRQ_INT0)
+#define EMMA2RH_GPIO_CASCADE   (EMMA2RH_IRQ_INT46 - EMMA2RH_IRQ_INT0)
+
+#define EMMA2RH_SW_IRQ_BASE    (EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ)
+#define EMMA2RH_GPIO_IRQ_BASE  (EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW)
+#define CPU_IRQ_BASE           (EMMA2RH_GPIO_IRQ_BASE + NUM_EMMA2RH_IRQ_GPIO)
+
+#define EMMA2RH_SW_IRQ_INT0    (0+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT1    (1+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT2    (2+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT3    (3+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT4    (4+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT5    (5+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT6    (6+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT7    (7+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT8    (8+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT9    (9+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT10   (10+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT11   (11+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT12   (12+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT13   (13+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT14   (14+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT15   (15+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT16   (16+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT17   (17+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT18   (18+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT19   (19+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT20   (20+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT21   (21+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT22   (22+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT23   (23+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT24   (24+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT25   (25+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT26   (26+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT27   (27+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT28   (28+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT29   (29+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT30   (30+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT31   (31+EMMA2RH_SW_IRQ_BASE)
+
+#define MARKEINS_PCI_IRQ_INTA  EMMA2RH_GPIO_IRQ_BASE+15
+#define MARKEINS_PCI_IRQ_INTB  EMMA2RH_GPIO_IRQ_BASE+16
+#define MARKEINS_PCI_IRQ_INTC  EMMA2RH_GPIO_IRQ_BASE+17
+#define MARKEINS_PCI_IRQ_INTD  EMMA2RH_GPIO_IRQ_BASE+18
+
+#endif /* CONFIG_MARKEINS */
index 43d047a9a6af06aa986b90a93eba696bb22051ac..787220e6c1fc4f187b855de989f24b0e4f63c441 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _ASM_FCNTL_H
 #define _ASM_FCNTL_H
 
-#include <linux/config.h>
 
 #define O_APPEND       0x0008
 #define O_SYNC         0x0010
index 73a3028dd9f9785ad089f3556d8dbed5f766675d..1cadefbbc0373b256d5090fa48bad770770e2c3d 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#include <linux/config.h>
 #include <asm/page.h>
 #ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
index b0f50015e25253688fd24e6154f48d70710d5fa3..58c561a9ec6b74b8eaf4c48d0609c44098e96538 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_FPU_H
 #define _ASM_FPU_H
 
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/thread_info.h>
 
@@ -138,10 +137,9 @@ static inline fpureg_t *get_fpu_regs(struct task_struct *tsk)
        if (cpu_has_fpu) {
                if ((tsk == current) && __is_fpu_owner())
                        _save_fp(current);
-               return tsk->thread.fpu.hard.fpr;
        }
 
-       return tsk->thread.fpu.soft.fpr;
+       return tsk->thread.fpu.fpr;
 }
 
 #endif /* _ASM_FPU_H */
index 16cb4d11dd0ba6a40a814c3dbd6566d3a56bb8bb..2731c38bd7ae1f67b5ae3155eb13f7789cc8f29c 100644 (file)
@@ -12,8 +12,8 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * Further private data for which no space exists in mips_fpu_soft_struct.
- * This should be subsumed into the mips_fpu_soft_struct structure as
+ * Further private data for which no space exists in mips_fpu_struct.
+ * This should be subsumed into the mips_fpu_struct structure as
  * defined in processor.h as soon as the absurd wired absolute assembler
  * offsets become dynamic at compile time.
  *
index a554089991f26ce3407da2e1d26b9904dd025800..ed023eae067447d24e19ac421d694de5bcb7e624 100644 (file)
@@ -3,10 +3,10 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/futex.h>
 #include <asm/errno.h>
 #include <asm/uaccess.h>
+#include <asm/war.h>
 
 #ifdef CONFIG_SMP
 #define __FUTEX_SMP_SYNC "     sync                                    \n"
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)             \
 {                                                                      \
-       __asm__ __volatile__(                                           \
-       "       .set    push                                    \n"     \
-       "       .set    noat                                    \n"     \
-       "       .set    mips3                                   \n"     \
-       "1:     ll      %1, (%3)        # __futex_atomic_op1    \n"     \
-       "       .set    mips0                                   \n"     \
-       "       " insn  "                                       \n"     \
-       "       .set    mips3                                   \n"     \
-       "2:     sc      $1, (%3)                                \n"     \
-       "       beqzl   $1, 1b                                  \n"     \
-       __FUTEX_SMP_SYNC                                                \
-       "3:                                                     \n"     \
-       "       .set    pop                                     \n"     \
-       "       .set    mips0                                   \n"     \
-       "       .section .fixup,\"ax\"                          \n"     \
-       "4:     li      %0, %5                                  \n"     \
-       "       j       2b                                      \n"     \
-       "       .previous                                       \n"     \
-       "       .section __ex_table,\"a\"                       \n"     \
-       "       "__UA_ADDR "\t1b, 4b                            \n"     \
-       "       "__UA_ADDR "\t2b, 4b                            \n"     \
-       "       .previous                                       \n"     \
-       : "=r" (ret), "=r" (oldval)                                     \
-       : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT));           \
+       if (cpu_has_llsc && R10000_LLSC_WAR) {                          \
+               __asm__ __volatile__(                                   \
+               "       .set    push                            \n"     \
+               "       .set    noat                            \n"     \
+               "       .set    mips3                           \n"     \
+               "1:     ll      %1, %4  # __futex_atomic_op     \n"     \
+               "       .set    mips0                           \n"     \
+               "       " insn  "                               \n"     \
+               "       .set    mips3                           \n"     \
+               "2:     sc      $1, %2                          \n"     \
+               "       beqzl   $1, 1b                          \n"     \
+               __FUTEX_SMP_SYNC                                        \
+               "3:                                             \n"     \
+               "       .set    pop                             \n"     \
+               "       .set    mips0                           \n"     \
+               "       .section .fixup,\"ax\"                  \n"     \
+               "4:     li      %0, %6                          \n"     \
+               "       j       2b                              \n"     \
+               "       .previous                               \n"     \
+               "       .section __ex_table,\"a\"               \n"     \
+               "       "__UA_ADDR "\t1b, 4b                    \n"     \
+               "       "__UA_ADDR "\t2b, 4b                    \n"     \
+               "       .previous                               \n"     \
+               : "=r" (ret), "=&r" (oldval), "=R" (*uaddr)             \
+               : "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)    \
+               : "memory");                                            \
+       } else if (cpu_has_llsc) {                                      \
+               __asm__ __volatile__(                                   \
+               "       .set    push                            \n"     \
+               "       .set    noat                            \n"     \
+               "       .set    mips3                           \n"     \
+               "1:     ll      %1, %4  # __futex_atomic_op     \n"     \
+               "       .set    mips0                           \n"     \
+               "       " insn  "                               \n"     \
+               "       .set    mips3                           \n"     \
+               "2:     sc      $1, %2                          \n"     \
+               "       beqz    $1, 1b                          \n"     \
+               __FUTEX_SMP_SYNC                                        \
+               "3:                                             \n"     \
+               "       .set    pop                             \n"     \
+               "       .set    mips0                           \n"     \
+               "       .section .fixup,\"ax\"                  \n"     \
+               "4:     li      %0, %6                          \n"     \
+               "       j       2b                              \n"     \
+               "       .previous                               \n"     \
+               "       .section __ex_table,\"a\"               \n"     \
+               "       "__UA_ADDR "\t1b, 4b                    \n"     \
+               "       "__UA_ADDR "\t2b, 4b                    \n"     \
+               "       .previous                               \n"     \
+               : "=r" (ret), "=&r" (oldval), "=R" (*uaddr)             \
+               : "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)    \
+               : "memory");                                            \
+       } else                                                          \
+               ret = -ENOSYS;                                          \
 }
 
 static inline int
@@ -60,23 +90,23 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 
        switch (op) {
        case FUTEX_OP_SET:
-               __futex_atomic_op("move $1, %z4", ret, oldval, uaddr, oparg);
+               __futex_atomic_op("move $1, %z5", ret, oldval, uaddr, oparg);
                break;
 
        case FUTEX_OP_ADD:
-               __futex_atomic_op("addu $1, %1, %z4",
+               __futex_atomic_op("addu $1, %1, %z5",
                                  ret, oldval, uaddr, oparg);
                break;
        case FUTEX_OP_OR:
-               __futex_atomic_op("or   $1, %1, %z4",
+               __futex_atomic_op("or   $1, %1, %z5",
                                  ret, oldval, uaddr, oparg);
                break;
        case FUTEX_OP_ANDN:
-               __futex_atomic_op("and  $1, %1, %z4",
+               __futex_atomic_op("and  $1, %1, %z5",
                                  ret, oldval, uaddr, ~oparg);
                break;
        case FUTEX_OP_XOR:
-               __futex_atomic_op("xor  $1, %1, %z4",
+               __futex_atomic_op("xor  $1, %1, %z5",
                                  ret, oldval, uaddr, oparg);
                break;
        default:
@@ -102,7 +132,69 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 static inline int
 futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 {
-       return -ENOSYS;
+       int retval;
+
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       if (cpu_has_llsc && R10000_LLSC_WAR) {
+               __asm__ __volatile__(
+               "# futex_atomic_cmpxchg_inatomic                        \n"
+               "       .set    push                                    \n"
+               "       .set    noat                                    \n"
+               "       .set    mips3                                   \n"
+               "1:     ll      %0, %2                                  \n"
+               "       bne     %0, %z3, 3f                             \n"
+               "       .set    mips0                                   \n"
+               "       move    $1, %z4                                 \n"
+               "       .set    mips3                                   \n"
+               "2:     sc      $1, %1                                  \n"
+               "       beqzl   $1, 1b                                  \n"
+               __FUTEX_SMP_SYNC
+               "3:                                                     \n"
+               "       .set    pop                                     \n"
+               "       .section .fixup,\"ax\"                          \n"
+               "4:     li      %0, %5                                  \n"
+               "       j       3b                                      \n"
+               "       .previous                                       \n"
+               "       .section __ex_table,\"a\"                       \n"
+               "       "__UA_ADDR "\t1b, 4b                            \n"
+               "       "__UA_ADDR "\t2b, 4b                            \n"
+               "       .previous                                       \n"
+               : "=&r" (retval), "=R" (*uaddr)
+               : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
+               : "memory");
+       } else if (cpu_has_llsc) {
+               __asm__ __volatile__(
+               "# futex_atomic_cmpxchg_inatomic                        \n"
+               "       .set    push                                    \n"
+               "       .set    noat                                    \n"
+               "       .set    mips3                                   \n"
+               "1:     ll      %0, %2                                  \n"
+               "       bne     %0, %z3, 3f                             \n"
+               "       .set    mips0                                   \n"
+               "       move    $1, %z4                                 \n"
+               "       .set    mips3                                   \n"
+               "2:     sc      $1, %1                                  \n"
+               "       beqz    $1, 1b                                  \n"
+               __FUTEX_SMP_SYNC
+               "3:                                                     \n"
+               "       .set    pop                                     \n"
+               "       .section .fixup,\"ax\"                          \n"
+               "4:     li      %0, %5                                  \n"
+               "       j       3b                                      \n"
+               "       .previous                                       \n"
+               "       .section __ex_table,\"a\"                       \n"
+               "       "__UA_ADDR "\t1b, 4b                            \n"
+               "       "__UA_ADDR "\t2b, 4b                            \n"
+               "       .previous                                       \n"
+               : "=&r" (retval), "=R" (*uaddr)
+               : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
+               : "memory");
+       } else
+               return -ENOSYS;
+
+       return retval;
 }
 
 #endif
index dadc05188db717c288ab9ecd6a86d483e4731119..66943c451c1dbcb196db60f042cd2a33928d7254 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_HAZARDS_H
 #define _ASM_HAZARDS_H
 
-#include <linux/config.h>
 
 #ifdef __ASSEMBLY__
 
index 8cf598402492c2d2394aeb0fc2add6f7f8f57724..c976bfaaba83a1bafec7f40df8c806a845aec442 100644 (file)
@@ -19,7 +19,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <asm/kmap_types.h>
index e0745f4ff6240292f0cdb510534bb67aee2157b7..1ed8d0f62577d4e01246d2834e2da4fed935ac85 100644 (file)
@@ -6,6 +6,7 @@
  * for more details.
  *
  * Copyright (C) 1996, 2000 by Ralf Baechle
+ * Copyright (C) 2006 by Thiemo Seufer
  */
 #ifndef _ASM_INST_H
 #define _ASM_INST_H
@@ -21,14 +22,14 @@ enum major_op {
        cop0_op, cop1_op, cop2_op, cop1x_op,
        beql_op, bnel_op, blezl_op, bgtzl_op,
        daddi_op, daddiu_op, ldl_op, ldr_op,
-       major_1c_op, jalx_op, major_1e_op, major_1f_op,
+       spec2_op, jalx_op, mdmx_op, spec3_op,
        lb_op, lh_op, lwl_op, lw_op,
        lbu_op, lhu_op, lwr_op, lwu_op,
        sb_op, sh_op, swl_op, sw_op,
        sdl_op, sdr_op, swr_op, cache_op,
        ll_op, lwc1_op, lwc2_op, pref_op,
        lld_op, ldc1_op, ldc2_op, ld_op,
-       sc_op, swc1_op, swc2_op, rdhwr_op,
+       sc_op, swc1_op, swc2_op, major_3b_op,
        scd_op, sdc1_op, sdc2_op, sd_op
 };
 
@@ -37,7 +38,7 @@ enum major_op {
  */
 enum spec_op {
        sll_op, movc_op, srl_op, sra_op,
-       sllv_op, srlv_op, srav_op, spec1_unused_op, /* Opcode 0x07 is unused */
+       sllv_op, pmon_op, srlv_op, srav_op,
        jr_op, jalr_op, movz_op, movn_op,
        syscall_op, break_op, spim_op, sync_op,
        mfhi_op, mthi_op, mflo_op, mtlo_op,
@@ -54,6 +55,28 @@ enum spec_op {
        dsll32_op, spec8_unused_op, dsrl32_op, dsra32_op
 };
 
+/*
+ * func field of spec2 opcode.
+ */
+enum spec2_op {
+       madd_op, maddu_op, mul_op, spec2_3_unused_op,
+       msub_op, msubu_op, /* more unused ops */
+       clz_op = 0x20, clo_op,
+       dclz_op = 0x24, dclo_op,
+       sdbpp_op = 0x3f
+};
+
+/*
+ * func field of spec3 opcode.
+ */
+enum spec3_op {
+       ext_op, dextm_op, dextu_op, dext_op,
+       ins_op, dinsm_op, dinsu_op, dins_op,
+       bshfl_op = 0x20,
+       dbshfl_op = 0x24,
+       rdhwr_op = 0x3f
+};
+
 /*
  * rt field of bcond opcodes.
  */
@@ -151,8 +174,8 @@ enum cop1x_func {
  * func field for mad opcodes (MIPS IV).
  */
 enum mad_func {
-       madd_op      = 0x08, msub_op      = 0x0a,
-       nmadd_op     = 0x0c, nmsub_op     = 0x0e
+       madd_fp_op      = 0x08, msub_fp_op      = 0x0a,
+       nmadd_fp_op     = 0x0c, nmsub_fp_op     = 0x0e
 };
 
 /*
index 4bb9c06f44107006f4c6330df7f0aedb23bc96a2..a99d6867510fde017b85e00ddee65d79ae5762e5 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_INTERRUPT_H
 #define _ASM_INTERRUPT_H
 
-#include <linux/config.h>
 #include <asm/hazards.h>
 
 __asm__ (
index 6b17eb9d79a52017f819f68073bc0fe5ba8add47..df624e1ee6e2eb278931b6ecf56e3a5ea494dbcd 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
index e440fdf4b2326deb6cb796cf42e3169835b9ce49..1b631b8da6f862661cb0fa53b55e03ff20fe9bea 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_IP32_MACHINE_H
 #define _ASM_IP32_MACHINE_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SGI_IP32
 
index dde677f02bc015e1129d3b30a550f707f3b8f61d..d35c61776a0249d5620a8a70a8033b15735f48fc 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 
 #include <asm/mipsmtregs.h>
index 7bb003511d9e9bdab65a90b77b9c2766b40a68e3..24c6cda7937760e0ddd6e7ffa3d033b9e5ed4981 100644 (file)
@@ -5,7 +5,6 @@
  *
  * Copyright (c) 1998 Harald Koerfgen
  */
-#include <linux/config.h>
 
 #ifndef __ASM_ISADEP_H
 #define __ASM_ISADEP_H
index b0c325a2234357fe06bbf95cece6191783d55001..fe551f33a74fc9cd808ef754a63cb216fa91ebbd 100644 (file)
@@ -12,7 +12,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <asm/irq.h>
 
 struct tb_irq_space {
index 6886a0c3fedfde6ed82cce4d2ca988d561c6d244..806aae3c533892b1e65917c4742943ff2692374b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
index c38844f615fc790896faef323b487dbd83c40249..9e2d43bae388c06da2ae83f8e17ec7b14772dc78 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_LOCAL_H
 #define _ASM_LOCAL_H
 
-#include <linux/config.h>
 #include <linux/percpu.h>
 #include <asm/atomic.h>
 
index 4686e17c206cc166603c73b3f8d655ab5d7fcf78..582acd8adb81fd17d77cef2defbe8a606ec9312b 100644 (file)
@@ -35,7 +35,6 @@
 #ifndef _AU1000_H_
 #define _AU1000_H_
 
-#include <linux/config.h>
 
 #ifndef _LANGUAGE_ASSEMBLY
 
index b7b46dd9b929ee1a17bc66427a7579ab1e57f2d0..947135941033ec94ac2649579551063340e99055 100644 (file)
@@ -23,7 +23,6 @@
 #ifndef _AU1XXX_H_
 #define _AU1XXX_H_
 
-#include <linux/config.h>
 
 #include <asm/mach-au1x00/au1000.h>
 
index b327bcd3fee15be5d9c4805357564a76efa7780a..d5b38a247e5a666899fcb6cefabfef0f1b475f2a 100644 (file)
@@ -34,7 +34,6 @@
 #ifndef _AU1000_DBDMA_H_
 #define _AU1000_DBDMA_H_
 
-#include <linux/config.h>
 
 #ifndef _LANGUAGE_ASSEMBLY
 
index e867b4ef96d1f09bcaec1fb05dc5d153d1d580bd..301e71300779cb7648c36c47135dafffddb61588 100644 (file)
@@ -29,7 +29,6 @@
  * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE
  *       Interface and Linux Device Driver" Application Note.
  */
-#include <linux/config.h>
 
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
         #define DMA_WAIT_TIMEOUT        100
index 8e5fb3c7da4da1a2e420bd172d53c2b828307a52..5c3e2a38ce12fa261b9bafd421497371323f129e 100644 (file)
@@ -33,7 +33,6 @@
 #ifndef _AU1000_PSC_H_
 #define _AU1000_PSC_H_
 
-#include <linux/config.h>
 
 /* The PSC base addresses.  */
 #ifdef CONFIG_SOC_AU1550
index d3ec6274575a74d01492de292b484011a6033402..098fca4289bb3fb80f0112604940a49ba26bad25 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef __ASM_MACH_AU1X00_IOREMAP_H
 #define __ASM_MACH_AU1X00_IOREMAP_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
index ace8c5ef97015c741b5f2b1c7206ca78466ccc78..e0e08fc5d7f726c6efd9053409b75c4f9fe007eb 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef __ASM_COBALT_CPU_FEATURE_OVERRIDES_H
 #define __ASM_COBALT_CPU_FEATURE_OVERRIDES_H
 
-#include <linux/config.h>
 
 #define cpu_has_tlb            1
 #define cpu_has_4kex           1
index 7b28b23f91ceefa28e1a8dd18ce82f64f90a96a3..8fbb4b42a8b502860b79f974fb8cc2f6853ceec9 100644 (file)
@@ -28,7 +28,6 @@
 #ifndef __ASM_DB1X00_H
 #define __ASM_DB1X00_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_MIPS_DB1550
 #define BCSR_KSEG1_ADDR 0xAF000000
diff --git a/include/asm-mips/mach-ddb5074/mc146818rtc.h b/include/asm-mips/mach-ddb5074/mc146818rtc.h
deleted file mode 100644 (file)
index 2eb9acb..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1998, 2001, 03 by Ralf Baechle
- *
- * RTC routines for PC style attached Dallas chip.
- */
-#ifndef __ASM_MACH_DDB5074_MC146818RTC_H
-#define __ASM_MACH_DDB5074_MC146818RTC_H
-
-#include <asm/ddb5xxx/ddb5074.h>
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-#define RTC_PORT(x)    (0x70 + (x))
-#define RTC_IRQ                8
-
-static inline unsigned char CMOS_READ(unsigned long addr)
-{
-       return *(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr);
-}
-
-static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
-{
-       *(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr) = data;
-}
-
-#define RTC_ALWAYS_BCD 1
-
-#endif /* __ASM_MACH_DDB5074_MC146818RTC_H */
diff --git a/include/asm-mips/mach-dec/param.h b/include/asm-mips/mach-dec/param.h
deleted file mode 100644 (file)
index 3e4f0e3..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 by Ralf Baechle
- */
-#ifndef __ASM_MACH_DEC_PARAM_H
-#define __ASM_MACH_DEC_PARAM_H
-
-/*
- * log2(HZ), change this here if you want another HZ value. This is also
- * used in dec_time_init.  Minimum is 1, Maximum is 15.
- */
-#define LOG_2_HZ 7
-#define HZ (1 << LOG_2_HZ)
-
-#endif /* __ASM_MACH_DEC_PARAM_H */
similarity index 58%
rename from include/asm-mips/mach-mips/param.h
rename to include/asm-mips/mach-emma2rh/irq.h
index 805ef6d27d3ce8b21fa49cc21d6a9e739989914c..bce64244b800dff2008523890a275e4ea2c3e2eb 100644 (file)
@@ -5,9 +5,9 @@
  *
  * Copyright (C) 2003 by Ralf Baechle
  */
-#ifndef __ASM_MACH_MIPS_PARAM_H
-#define __ASM_MACH_MIPS_PARAM_H
+#ifndef __ASM_MACH_EMMA2RH_IRQ_H
+#define __ASM_MACH_EMMA2RH_IRQ_H
 
-#define HZ             100             /* Internal kernel timer frequency */
+#define NR_IRQS        256
 
-#endif /* __ASM_MACH_MIPS_PARAM_H */
+#endif /* __ASM_MACH_EMMA2RH_IRQ_H */
diff --git a/include/asm-mips/mach-excite/cpu-feature-overrides.h b/include/asm-mips/mach-excite/cpu-feature-overrides.h
new file mode 100644 (file)
index 0000000..abb76b2
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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) 2004 Thomas Koeller <thomas.koeller@baslerweb.com>
+ */
+#ifndef __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H
+
+/*
+ * Basler eXcite has an RM9122 processor.
+ */
+#define cpu_has_watch          1
+#define cpu_has_mips16         0
+#define cpu_has_divec          0
+#define cpu_has_vce            0
+#define cpu_has_cache_cdex_p   0
+#define cpu_has_cache_cdex_s   0
+#define cpu_has_prefetch       1
+#define cpu_has_mcheck         0
+#define cpu_has_ejtag          0
+
+#define cpu_has_llsc           1
+#define cpu_has_vtag_icache    0
+#define cpu_has_dc_aliases     0
+#define cpu_has_ic_fills_f_dc  0
+#define cpu_has_dsp            0
+#define cpu_icache_snoops_remote_store 0
+
+#define cpu_has_nofpuex                0
+#define cpu_has_64bits         1
+
+#define cpu_has_subset_pcaches 0
+
+#define cpu_dcache_line_size() 32
+#define cpu_icache_line_size() 32
+#define cpu_scache_line_size() 32
+
+#endif /* __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-excite/excite.h b/include/asm-mips/mach-excite/excite.h
new file mode 100644 (file)
index 0000000..c52610d
--- /dev/null
@@ -0,0 +1,155 @@
+#ifndef __EXCITE_H__
+#define __EXCITE_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+
+#define EXCITE_CPU_EXT_CLOCK 100000000
+
+#if !defined(__ASSEMBLER__)
+void __init excite_kgdb_init(void);
+void excite_procfs_init(void);
+extern unsigned long memsize;
+extern char modetty[];
+extern u32 unit_id;
+#endif
+
+/* Base name for XICAP devices */
+#define XICAP_NAME     "xicap_gpi"
+
+/* OCD register offsets */
+#define LKB0           0x0038
+#define LKB5           0x0128
+#define LKM5           0x012C
+#define LKB7           0x0138
+#define LKM7           0x013c
+#define LKB8           0x0140
+#define LKM8           0x0144
+#define LKB9           0x0148
+#define LKM9           0x014c
+#define LKB10          0x0150
+#define LKM10          0x0154
+#define LKB11          0x0158
+#define LKM11          0x015c
+#define LKB12          0x0160
+#define LKM12          0x0164
+#define LKB13          0x0168
+#define LKM13          0x016c
+#define LDP0           0x0200
+#define LDP1           0x0210
+#define LDP2           0x0220
+#define LDP3           0x0230
+#define INTPIN0                0x0A40
+#define INTPIN1                0x0A44
+#define INTPIN2                0x0A48
+#define INTPIN3                0x0A4C
+#define INTPIN4                0x0A50
+#define INTPIN5                0x0A54
+#define INTPIN6                0x0A58
+#define INTPIN7                0x0A5C
+
+
+
+
+/* TITAN register offsets */
+#define CPRR           0x0004
+#define CPDSR          0x0008
+#define CPTC0R         0x000c
+#define CPTC1R         0x0010
+#define CPCFG0         0x0020
+#define CPCFG1         0x0024
+#define CPDST0A                0x0028
+#define CPDST0B                0x002c
+#define CPDST1A                0x0030
+#define CPDST1B                0x0034
+#define CPXDSTA                0x0038
+#define CPXDSTB                0x003c
+#define CPXCISRA       0x0048
+#define CPXCISRB       0x004c
+#define CPGIG0ER       0x0050
+#define CPGIG1ER       0x0054
+#define CPGRWL         0x0068
+#define CPURSLMT       0x00f8
+#define UACFG          0x0200
+#define UAINTS         0x0204
+#define SDRXFCIE       0x4828
+#define SDTXFCIE       0x4928
+#define INTP0Status0   0x1B00
+#define INTP0Mask0     0x1B04
+#define INTP0Set0      0x1B08
+#define INTP0Clear0    0x1B0C
+#define GXCFG          0x5000
+#define GXDMADRPFX     0x5018
+#define GXDMA_DESCADR  0x501c
+#define GXCH0TDESSTRT  0x5054
+
+/* IRQ definitions */
+#define NMICONFIG              0xac0
+#define TITAN_MSGINT   0xc4
+#define TITAN_IRQ      ((TITAN_MSGINT / 0x20) + 2)
+#define FPGA0_MSGINT   0x5a
+#define FPGA0_IRQ      ((FPGA0_MSGINT / 0x20) + 2)
+#define FPGA1_MSGINT   0x7b
+#define FPGA1_IRQ      ((FPGA1_MSGINT / 0x20) + 2)
+#define PHY_MSGINT     0x9c
+#define PHY_IRQ                ((PHY_MSGINT   / 0x20) + 2)
+
+#if defined(CONFIG_BASLER_EXCITE_PROTOTYPE)
+/* Pre-release units used interrupt pin #9 */
+#define USB_IRQ                11
+#else
+/* Re-designed units use interrupt pin #1 */
+#define USB_MSGINT     0x39
+#define USB_IRQ                ((USB_MSGINT / 0x20) + 2)
+#endif
+#define TIMER_IRQ      12
+
+
+/* Device address ranges */
+#define EXCITE_OFFS_OCD                0x1fffc000
+#define        EXCITE_SIZE_OCD         (16 * 1024)
+#define EXCITE_PHYS_OCD                CPHYSADDR(EXCITE_OFFS_OCD)
+#define EXCITE_ADDR_OCD                CKSEG1ADDR(EXCITE_OFFS_OCD)
+
+#define EXCITE_OFFS_SCRAM      0x1fffa000
+#define        EXCITE_SIZE_SCRAM       (8 << 10)
+#define EXCITE_PHYS_SCRAM      CPHYSADDR(EXCITE_OFFS_SCRAM)
+#define EXCITE_ADDR_SCRAM      CKSEG1ADDR(EXCITE_OFFS_SCRAM)
+
+#define EXCITE_OFFS_PCI_IO     0x1fff8000
+#define        EXCITE_SIZE_PCI_IO      (8 << 10)
+#define EXCITE_PHYS_PCI_IO     CPHYSADDR(EXCITE_OFFS_PCI_IO)
+#define EXCITE_ADDR_PCI_IO     CKSEG1ADDR(EXCITE_OFFS_PCI_IO)
+
+#define EXCITE_OFFS_TITAN      0x1fff0000
+#define EXCITE_SIZE_TITAN      (32 << 10)
+#define EXCITE_PHYS_TITAN      CPHYSADDR(EXCITE_OFFS_TITAN)
+#define EXCITE_ADDR_TITAN      CKSEG1ADDR(EXCITE_OFFS_TITAN)
+
+#define EXCITE_OFFS_PCI_MEM    0x1ffe0000
+#define EXCITE_SIZE_PCI_MEM    (64 << 10)
+#define EXCITE_PHYS_PCI_MEM    CPHYSADDR(EXCITE_OFFS_PCI_MEM)
+#define EXCITE_ADDR_PCI_MEM    CKSEG1ADDR(EXCITE_OFFS_PCI_MEM)
+
+#define EXCITE_OFFS_FPGA       0x1ffdc000
+#define EXCITE_SIZE_FPGA       (16 << 10)
+#define EXCITE_PHYS_FPGA       CPHYSADDR(EXCITE_OFFS_FPGA)
+#define EXCITE_ADDR_FPGA       CKSEG1ADDR(EXCITE_OFFS_FPGA)
+
+#define EXCITE_OFFS_NAND       0x1ffd8000
+#define EXCITE_SIZE_NAND       (16 << 10)
+#define EXCITE_PHYS_NAND       CPHYSADDR(EXCITE_OFFS_NAND)
+#define EXCITE_ADDR_NAND       CKSEG1ADDR(EXCITE_OFFS_NAND)
+
+#define EXCITE_OFFS_BOOTROM    0x1f000000
+#define EXCITE_SIZE_BOOTROM    (8 << 20)
+#define EXCITE_PHYS_BOOTROM    CPHYSADDR(EXCITE_OFFS_BOOTROM)
+#define EXCITE_ADDR_BOOTROM    CKSEG1ADDR(EXCITE_OFFS_BOOTROM)
+
+/* FPGA address offsets */
+#define EXCITE_FPGA_DPR                0x0104  /* dual-ported ram */
+#define EXCITE_FPGA_SYSCTL     0x0200  /* system control register block */
+
+#endif /* __EXCITE_H__ */
diff --git a/include/asm-mips/mach-excite/excite_nandflash.h b/include/asm-mips/mach-excite/excite_nandflash.h
new file mode 100644 (file)
index 0000000..c4cf614
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __EXCITE_NANDFLASH_H__
+#define __EXCITE_NANDFLASH_H__
+
+/* Resource names */
+#define EXCITE_NANDFLASH_RESOURCE_REGS "excite_nandflash_regs"
+
+#endif /* __EXCITE_NANDFLASH_H__ */
diff --git a/include/asm-mips/mach-excite/rm9k_eth.h b/include/asm-mips/mach-excite/rm9k_eth.h
new file mode 100644 (file)
index 0000000..94705a4
--- /dev/null
@@ -0,0 +1,23 @@
+#if !defined(__RM9K_ETH_H__)
+#define __RM9K_ETH_H__
+
+#define RM9K_GE_NAME                   "rm9k_ge"
+
+/* Resource names */
+#define RM9K_GE_RESOURCE_MAC           "rm9k_ge_mac"
+#define RM9K_GE_RESOURCE_MSTAT         "rm9k_ge_mstat"
+#define RM9K_GE_RESOURCE_PKTPROC       "rm9k_ge_pktproc"
+#define RM9K_GE_RESOURCE_XDMA          "rm9k_ge_xdma"
+#define RM9K_GE_RESOURCE_FIFO_RX       "rm9k_ge_fifo_rx"
+#define RM9K_GE_RESOURCE_FIFO_TX       "rm9k_ge_fifo_tx"
+#define RM9K_GE_RESOURCE_FIFOMEM_RX    "rm9k_ge_fifo_memory_rx"
+#define RM9K_GE_RESOURCE_FIFOMEM_TX    "rm9k_ge_fifo_memory_tx"
+#define RM9K_GE_RESOURCE_PHY           "rm9k_ge_phy"
+#define RM9K_GE_RESOURCE_DMADESC_RX    "rm9k_ge_dmadesc_rx"
+#define RM9K_GE_RESOURCE_DMADESC_TX    "rm9k_ge_dmadesc_tx"
+#define RM9K_GE_RESOURCE_IRQ_MAIN      "rm9k_ge_irq_main"
+#define RM9K_GE_RESOURCE_IRQ_PHY       "rm9k_ge_irq_phy"
+#define RM9K_GE_RESOURCE_GPI_SLICE     "rm9k_ge_gpi_slice"
+#define RM9K_GE_RESOURCE_MDIO_CHANNEL  "rm9k_ge_mdio_channel"
+
+#endif /* !defined(__RM9K_ETH_H__) */
diff --git a/include/asm-mips/mach-excite/rm9k_wdt.h b/include/asm-mips/mach-excite/rm9k_wdt.h
new file mode 100644 (file)
index 0000000..3fa3c08
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __RM9K_WDT_H__
+#define __RM9K_WDT_H__
+
+/* Device name */
+#define WDT_NAME               "wdt_gpi"
+
+/* Resource names */
+#define WDT_RESOURCE_REGS      "excite_watchdog_regs"
+#define WDT_RESOURCE_IRQ       "excite_watchdog_irq"
+#define WDT_RESOURCE_COUNTER   "excite_watchdog_counter"
+
+#endif /* __RM9K_WDT_H__ */
diff --git a/include/asm-mips/mach-excite/rm9k_xicap.h b/include/asm-mips/mach-excite/rm9k_xicap.h
new file mode 100644 (file)
index 0000000..0095777
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __EXCITE_XICAP_H__
+#define __EXCITE_XICAP_H__
+
+
+/* Resource names */
+#define XICAP_RESOURCE_FIFO_RX         "xicap_fifo_rx"
+#define XICAP_RESOURCE_FIFO_TX         "xicap_fifo_tx"
+#define XICAP_RESOURCE_XDMA            "xicap_xdma"
+#define XICAP_RESOURCE_DMADESC         "xicap_dmadesc"
+#define XICAP_RESOURCE_PKTPROC         "xicap_pktproc"
+#define XICAP_RESOURCE_IRQ             "xicap_irq"
+#define XICAP_RESOURCE_GPI_SLICE       "xicap_gpi_slice"
+#define XICAP_RESOURCE_FIFO_BLK                "xicap_fifo_blocks"
+#define XICAP_RESOURCE_PKT_STREAM      "xicap_pkt_stream"
+
+#endif /* __EXCITE_XICAP_H__ */
index e3315359500abba1617bb13f4abd17be79dc2f66..6eba2e576aaa396e898823fd0e34c6b6d8effd10 100644 (file)
@@ -15,7 +15,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/stddef.h>
 #include <asm/processor.h>
index 373d66dee9d734ac71092425c215bd844abd9864..410ab5f6c5636b519c6ecc8c56932e4abcf08d95 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_MACH_GENERIC_KMALLOC_H
 #define __ASM_MACH_GENERIC_KMALLOC_H
 
-#include <linux/config.h>
 
 #ifndef CONFIG_DMA_COHERENT
 /*
diff --git a/include/asm-mips/mach-generic/param.h b/include/asm-mips/mach-generic/param.h
deleted file mode 100644 (file)
index a0d12f9..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 by Ralf Baechle
- */
-#ifndef __ASM_MACH_GENERIC_PARAM_H
-#define __ASM_MACH_GENERIC_PARAM_H
-
-#define HZ             1000            /* Internal kernel timer frequency */
-
-#endif /* __ASM_MACH_GENERIC_PARAM_H */
index b849d8dd7e7848f5cb5873c2f579412f043752f2..0ae9997bc9a8ba32200b1697947a1a3a6c887dcc 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_MACH_GENERIC_SPACES_H
 #define _ASM_MACH_GENERIC_SPACES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_32BIT
 
index 2a37bedb40535b02f4aad8cd2beccdc1a8f3679d..f7c5dc8a5336663c3b2fe1f3443e3ace396a5f40 100644 (file)
@@ -13,7 +13,7 @@
  */
 #define cpu_has_tlb            1
 #define cpu_has_4kex           1
-#define cpu_has_4kcache                1
+#define cpu_has_4k_cache       1
 #define cpu_has_fpu            1
 #define cpu_has_32fpr          1
 #define cpu_has_counter                1
index 8385f716798d09947aa4ccb74e18e19b9408f6da..ab20c026fd1949968595a3927fceff6dbd1ce070 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_MACH_IP22_SPACES_H
 #define _ASM_MACH_IP22_SPACES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_32BIT
 
index 2d2f5b91e47fc967c165016b37fddc4b5a4616db..19c2d135985bd9f89ecdc4bcb0da44dba59dac4f 100644 (file)
@@ -31,6 +31,9 @@
 #define cpu_has_nofpuex                0
 #define cpu_has_64bits         1
 
+#define cpu_has_4kex           1
+#define cpu_has_4k_cache       1
+
 #define cpu_has_subset_pcaches 1
 
 #define cpu_dcache_line_size() 32
index 36070b5654abadb0593337139a8d5761d879ce2d..2a3de092bf130af48835c4a14f21a2b71f068159 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H
 
-#include <linux/config.h>
 
 /*
  * R5000 has an interesting "restriction":  ll(d)/sc(d)
@@ -38,6 +37,8 @@
 #define cpu_has_vtag_icache    0
 #define cpu_has_ic_fills_f_dc  0
 #define cpu_has_dsp            0
+#define cpu_has_4k_cache       1
+
 
 #define cpu_has_mips32r1       0
 #define cpu_has_mips32r2       0
index 9d2d4d9ac036f26e04e1410ba81cce91df5294f3..f6198a21fba19ca3714b633917d11bd40e69261c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_MACH_IP32_KMALLOC_H
 #define __ASM_MACH_IP32_KMALLOC_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_CPU_R5000) || defined (CONFIG_CPU_RM7000)
 #define ARCH_KMALLOC_MINALIGN  32
diff --git a/include/asm-mips/mach-jazz/param.h b/include/asm-mips/mach-jazz/param.h
deleted file mode 100644 (file)
index 639763a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 by Ralf Baechle
- */
-#ifndef __ASM_MACH_JAZZ_PARAM_H
-#define __ASM_MACH_JAZZ_PARAM_H
-
-/*
- * Jazz is currently using the internal 100Hz timer of the R4030
- */
-#define HZ             100             /* Internal kernel timer frequency */
-
-#endif /* __ASM_MACH_JAZZ_PARAM_H */
index e06af6c86f8660818f6ff0bdb906e75fb1e9c3aa..e960679f54ba8fc2e08db47f24cf0b5c023b909f 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H
 
-#include <linux/config.h>
 
 /*
  * CPU feature overrides for MIPS boards
@@ -17,7 +16,7 @@
 #ifdef CONFIG_CPU_MIPS32
 #define cpu_has_tlb            1
 #define cpu_has_4kex           1
-#define cpu_has_4kcache                1
+#define cpu_has_4k_cache       1
 /* #define cpu_has_fpu         ? */
 /* #define cpu_has_32fpr       ? */
 #define cpu_has_counter                1
@@ -47,7 +46,7 @@
 #ifdef CONFIG_CPU_MIPS64
 #define cpu_has_tlb            1
 #define cpu_has_4kex           1
-#define cpu_has_4kcache                1
+#define cpu_has_4k_cache       1
 /* #define cpu_has_fpu         ? */
 /* #define cpu_has_32fpr       ? */
 #define cpu_has_counter                1
index f8579696ca5410f4b6cbacaeae883e2c7d78cdec..083d9c512a04914c6520f54603c310af932a5213 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_MACH_MIPS_IRQ_H
 #define __ASM_MACH_MIPS_IRQ_H
 
-#include <linux/config.h>
 
 #define NR_IRQS        256
 
index 9578ead11e8a07825a8cfbc86ef21a88153ada54..9a4955ce3b4a02ea7467aac80687d595adea85dd 100644 (file)
@@ -27,7 +27,6 @@
 #ifndef __ASM_PB1550_H
 #define __ASM_PB1550_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
diff --git a/include/asm-mips/mach-qemu/param.h b/include/asm-mips/mach-qemu/param.h
deleted file mode 100644 (file)
index cb30ee4..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2005 by Ralf Baechle
- */
-#ifndef __ASM_MACH_QEMU_PARAM_H
-#define __ASM_MACH_QEMU_PARAM_H
-
-#define HZ             100             /* Internal kernel timer frequency */
-
-#endif /* __ASM_MACH_QEMU_PARAM_H */
index 91e7cf5f2bfecd7e760f6ab951d0f64f958ac205..11410ae10d36236aaaef1cc24d44578d5a570726 100644 (file)
@@ -14,7 +14,7 @@
 
 #define cpu_has_tlb            1
 #define cpu_has_4kex           1
-#define cpu_has_4kcache                1
+#define cpu_has_4k_cache       1
 #define cpu_has_fpu            1
 #define cpu_has_32fpr          1
 #define cpu_has_counter                1
 #define cpu_has_nofpuex                0
 #define cpu_has_64bits         1
 
-#define cpu_has_subset_pcaches 0       /* No S-cache on R5000 I think ...  */
 #define cpu_dcache_line_size() 32
 #define cpu_icache_line_size() 32
-#define cpu_scache_line_size() 0       /* No S-cache on R5000 I think ...  */
 
 #define cpu_has_mips32r1       0
 #define cpu_has_mips32r2       0
index cadbe8eda79c540e9fd0c555c4201a16f98ce007..d736bdadb6df3930d6a7fcc3304b533dc530056c 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H
 
-#include <linux/config.h>
 
 /*
  * CPU feature overrides for MIPS boards
@@ -16,7 +15,7 @@
 #ifdef CONFIG_CPU_MIPS32
 #define cpu_has_tlb            1
 #define cpu_has_4kex           1
-#define cpu_has_4kcache                1
+#define cpu_has_4k_cache       1
 #define cpu_has_fpu            0
 /* #define cpu_has_32fpr       ? */
 #define cpu_has_counter                1
@@ -41,7 +40,7 @@
 #ifdef CONFIG_CPU_MIPS64
 #define cpu_has_tlb            1
 #define cpu_has_4kex           1
-#define cpu_has_4kcache                1
+#define cpu_has_4k_cache       1
 /* #define cpu_has_fpu         ? */
 /* #define cpu_has_32fpr       ? */
 #define cpu_has_counter                1
diff --git a/include/asm-mips/mach-wrppmc/mach-gt64120.h b/include/asm-mips/mach-wrppmc/mach-gt64120.h
new file mode 100644 (file)
index 0000000..ba9205a
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * This is a direct copy of the ev96100.h file, with a global
+ * search and replace.  The numbers are the same.
+ *
+ * The reason I'm duplicating this is so that the 64120/96100
+ * defines won't be confusing in the source code.
+ */
+#ifndef __ASM_MIPS_GT64120_H
+#define __ASM_MIPS_GT64120_H
+
+/*
+ * This is the CPU physical memory map of PPMC Board:
+ *
+ *    0x00000000-0x03FFFFFF      - 64MB SDRAM (SCS[0]#)
+ *    0x1C000000-0x1C000000      - LED (CS0)
+ *    0x1C800000-0x1C800007      - UART 16550 port (CS1)
+ *    0x1F000000-0x1F000000      - MailBox (CS3)
+ *    0x1FC00000-0x20000000      - 4MB Flash (BOOT CS)
+ */
+
+#define WRPPMC_SDRAM_SCS0_BASE 0x00000000
+#define WRPPMC_SDRAM_SCS0_SIZE 0x04000000
+
+#define WRPPMC_UART16550_BASE  0x1C800000
+#define WRPPMC_UART16550_CLOCK 3686400 /* 3.68MHZ */
+
+#define WRPPMC_LED_BASE                0x1C000000
+#define WRPPMC_MBOX_BASE       0x1F000000
+
+#define WRPPMC_BOOTROM_BASE    0x1FC00000
+#define WRPPMC_BOOTROM_SIZE    0x00400000 /* 4M Flash */
+
+#define WRPPMC_MIPS_TIMER_IRQ  7 /* MIPS compare/count timer interrupt */
+#define WRPPMC_UART16550_IRQ   6
+#define WRPPMC_PCI_INTA_IRQ    3
+
+/*
+ * PCI Bus I/O and Memory resources allocation
+ *
+ * NOTE: We only have PCI_0 hose interface
+ */
+#define GT_PCI_MEM_BASE        0x13000000UL
+#define GT_PCI_MEM_SIZE        0x02000000UL
+#define GT_PCI_IO_BASE 0x11000000UL
+#define GT_PCI_IO_SIZE 0x02000000UL
+#define GT_ISA_IO_BASE PCI_IO_BASE
+
+/*
+ * PCI interrupts will come in on either the INTA or INTD interrups lines,
+ * which are mapped to the #2 and #5 interrupt pins of the MIPS.  On our
+ * boards, they all either come in on IntD or they all come in on IntA, they
+ * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the
+ * "requested" interrupt numbers and go through the list whenever we get an
+ * IntA/D.
+ *
+ * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and
+ * INTD is 11.
+ */
+#define GT_TIMER       4
+#define GT_INTA                2
+#define GT_INTD                5
+
+#ifndef __ASSEMBLY__
+
+/*
+ * GT64120 internal register space base address
+ */
+extern unsigned long gt64120_base;
+
+#define GT64120_BASE   (gt64120_base)
+
+/* define WRPPMC_EARLY_DEBUG to enable early output something to UART */
+#undef WRPPMC_EARLY_DEBUG
+
+#ifdef WRPPMC_EARLY_DEBUG
+extern void wrppmc_led_on(int mask);
+extern void wrppmc_led_off(int mask);
+extern void wrppmc_early_printk(const char *fmt, ...);
+#else
+#define wrppmc_early_printk(fmt, ...) do {} while (0)
+#endif /* WRPPMC_EARLY_DEBUG */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_MIPS_GT64120_H */
index fa8b913cc3e0e0ba262d938ad1d8829df6443ed7..b98f1658cfd00a2aac65671daeba3a2e49cc86b9 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef __ASM_MIPS_BOARDS_GENERIC_H
 #define __ASM_MIPS_BOARDS_GENERIC_H
 
-#include <linux/config.h>
 #include <asm/addrspace.h>
 #include <asm/byteorder.h>
 #include <asm/mips-boards/bonito64.h>
index a2ef579f6b1a26d8e87d3b5c19b405629dfe0b29..673977901ed3e65b490031bbd2ecb38fef279c71 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _ASM_MIPSREGS_H
 #define _ASM_MIPSREGS_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 #include <asm/hazards.h>
 
 #define ST0_DL                 (_ULCAST_(1) << 24)
 
 /*
- * Enable the MIPS DSP ASE
+ * Enable the MIPS MDMX and DSP ASEs
  */
 #define ST0_MX                 0x01000000
 
@@ -1451,12 +1450,10 @@ static inline void __emt(unsigned int previous)
 {
        if ((previous & __EMT_ENABLE))
                __asm__ __volatile__(
-               "       .set    noreorder                               \n"
                "       .set    mips32r2                                \n"
                "       .word   0x41600be1              # emt           \n"
                "       ehb                                             \n"
-               "       .set    mips0                                   \n"
-               "       .set    reorder                                 \n");
+               "       .set    mips0                                   \n");
 }
 
 static inline void __ehb(void)
index 6e09f4c87211017602fe9adba197855294e5dc77..18b69de87daa14ff4881a5bc10ffd3c999e0be5a 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_MMU_CONTEXT_H
 #define _ASM_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
index 7bde4432092b75c554d754b0213ad8423f1df2e4..dc231c89bef9b5a2147530f52b71cc62e6c3945b 100644 (file)
@@ -5,7 +5,6 @@
 #ifndef _ASM_MMZONE_H_
 #define _ASM_MMZONE_H_
 
-#include <linux/config.h>
 #include <asm/page.h>
 #include <mmzone.h>
 
 #define kvaddr_to_nid(kvaddr)  pa_to_nid(__pa(kvaddr))
 #define pfn_to_nid(pfn)                pa_to_nid((pfn) << PAGE_SHIFT)
 
-#define pfn_valid(pfn)                                         \
-({                                                             \
-       unsigned long __pfn = (pfn);                            \
-       int __n = pfn_to_nid(__pfn);                            \
-       ((__n >= 0) ? (__pfn < NODE_DATA(__n)->node_start_pfn + \
-                      NODE_DATA(__n)->node_spanned_pages) : 0);\
-})
-
-/* XXX: FIXME -- wli */
-#define kern_addr_valid(addr)  (0)
-
 #endif /* CONFIG_DISCONTIGMEM */
 
 #endif /* _ASM_MMZONE_H_ */
index 2af496c78c12a08f72d103070be8cd928f1e0d17..399d03f1c4fcf3c1f4d8049667c73a05cb2e24b4 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_MODULE_H
 #define _ASM_MODULE_H
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <asm/uaccess.h>
 
index a1533959742e4693f69f1f6b2311db956cc5cd01..0d6c7f14de31ade52bbef1ba33506396bcf8eafb 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_MSGBUF_H
 #define _ASM_MSGBUF_H
 
-#include <linux/config.h>
 
 /*
  * The msqid64_ds structure for the MIPS architecture.
index 46f2d23d26977cf54863322320692abb8132aa19..147844ef103be2ad76a08c5400081d761374fa48 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _ASM_PACCESS_H
 #define _ASM_PACCESS_H
 
-#include <linux/config.h>
 #include <linux/errno.h>
 
 #ifdef CONFIG_32BIT
index a1eab136ff6c7963a6dc2dde3b996db13e70bcda..6b97744f00cd7a79bf015daa06a060219dea5bc2 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_PAGE_H
 #define _ASM_PAGE_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 
@@ -139,9 +138,30 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
 
+#ifndef CONFIG_SPARSEMEM
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 #define pfn_valid(pfn)         ((pfn) < max_mapnr)
 #endif
+#endif
+
+#ifdef CONFIG_FLATMEM
+
+#define pfn_valid(pfn)         ((pfn) < max_mapnr)
+
+#elif defined(CONFIG_NEED_MULTIPLE_NODES)
+
+#define pfn_valid(pfn)                                                 \
+({                                                                     \
+       unsigned long __pfn = (pfn);                                    \
+       int __n = pfn_to_nid(__pfn);                                    \
+       ((__n >= 0) ? (__pfn < NODE_DATA(__n)->node_start_pfn +         \
+                              NODE_DATA(__n)->node_spanned_pages)      \
+                   : 0);                                               \
+})
+
+#else
+#error Provide a definition of pfn_valid
+#endif
 
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
index 2bead8273cedf401a4d55a30003eb7ac7416d15d..1d9bb8c5ab246cc52f62eca86d77d33764ee2f05 100644 (file)
@@ -11,7 +11,7 @@
 
 #ifdef __KERNEL__
 
-# include <param.h>                    /* Internal kernel timer frequency */
+# define HZ            CONFIG_HZ       /* Internal kernel timer frequency */
 # define USER_HZ       100             /* .. some user interfaces are in "ticks" */
 # define CLOCKS_PER_SEC        (USER_HZ)       /* like times() */
 #endif
index 6c9ad8171a773a9dd3e49d44b356292167306ece..c4d68bebdca655cc2c1c44f99c4fa0b5b19ca9ea 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _ASM_PCI_H
 #define _ASM_PCI_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 #ifdef __KERNEL__
index b4ee995c56e6370ebb492e80c0869501594b56be..0c45e7598f3fa06663eb9e9c72a67ab2f1785cb8 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <asm/xtalk/xwidget.h>         /* generic widget header */
+#include <asm/sn/types.h>
 
 /* I/O page size */
 
@@ -848,4 +849,6 @@ struct bridge_controller {
 extern void register_bridge_irq(unsigned int irq);
 extern int request_bridge_irq(struct bridge_controller *bc);
 
+extern struct pci_ops bridge_pci_ops;
+
 #endif /* _ASM_PCI_BRIDGE_H */
index fe1df572318b12f7dfb980c61d6ef8c8e945f536..582c1fe6cc4ac1243206f9d9901b251cb3d3d25a 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_PGALLOC_H
 #define _ASM_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
 
index 4d6bc45df5947280ed1e88d17fc3ae66685fecde..4b26d8528133f6a7c8c6289622cd1428d6d3257b 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_PGTABLE_32_H
 #define _ASM_PGTABLE_32_H
 
-#include <linux/config.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
 
@@ -177,48 +176,67 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
        ((swp_entry_t) { ((type) << 10) | ((offset) << 15) })
 
 /*
- * Bits 0, 1, 2, 9 and 10 are taken, split up the 27 bits of offset
- * into this range:
+ * Bits 0, 4, 8, and 9 are taken, split up 28 bits of offset into this range:
  */
-#define PTE_FILE_MAX_BITS      27
+#define PTE_FILE_MAX_BITS      28
 
-#define pte_to_pgoff(_pte) \
-       ((((_pte).pte >> 3) & 0x3f ) + (((_pte).pte >> 11) << 8 ))
+#define pte_to_pgoff(_pte)     ((((_pte).pte >> 1 ) & 0x07) | \
+                                (((_pte).pte >> 2 ) & 0x38) | \
+                                (((_pte).pte >> 10) <<  6 ))
 
-#define pgoff_to_pte(off) \
-       ((pte_t) { (((off) & 0x3f) << 3) + (((off) >> 8) << 11) + _PAGE_FILE })
+#define pgoff_to_pte(off)      ((pte_t) { (((off) & 0x07) << 1 ) | \
+                                          (((off) & 0x38) << 2 ) | \
+                                          (((off) >>  6 ) << 10) | \
+                                          _PAGE_FILE })
 
 #else
 
 /* Swap entries must have VALID and GLOBAL bits cleared. */
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#define __swp_type(x)          (((x).val >> 2) & 0x1f)
+#define __swp_offset(x)         ((x).val >> 7)
+#define __swp_entry(type,offset)       \
+               ((swp_entry_t)  { ((type) << 2) | ((offset) << 7) })
+#else
 #define __swp_type(x)          (((x).val >> 8) & 0x1f)
-#define __swp_offset(x)                ((x).val >> 13)
+#define __swp_offset(x)         ((x).val >> 13)
 #define __swp_entry(type,offset)       \
-               ((swp_entry_t) { ((type) << 8) | ((offset) << 13) })
+               ((swp_entry_t)  { ((type) << 8) | ((offset) << 13) })
+#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) */
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
 /*
- * Bits 0, 1, 2, 7 and 8 are taken, split up the 27 bits of offset
- * into this range:
+ * Bits 0 and 1 of pte_high are taken, use the rest for the page offset...
  */
-#define PTE_FILE_MAX_BITS      27
+#define PTE_FILE_MAX_BITS      30
 
-#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
-       /* fixme */
-#define pte_to_pgoff(_pte) (((_pte).pte_high >> 6) + ((_pte).pte_high & 0x3f))
-#define pgoff_to_pte(off) \
-       ((pte_t){(((off) & 0x3f) + ((off) << 6) + _PAGE_FILE)})
+#define pte_to_pgoff(_pte)     ((_pte).pte_high >> 2)
+#define pgoff_to_pte(off)      ((pte_t) { _PAGE_FILE, (off) << 2 })
 
 #else
-#define pte_to_pgoff(_pte) \
-       ((((_pte).pte >> 3) & 0x1f ) + (((_pte).pte >> 9) << 6 ))
+/*
+ * Bits 0, 4, 6, and 7 are taken, split up 28 bits of offset into this range:
+ */
+#define PTE_FILE_MAX_BITS      28
+
+#define pte_to_pgoff(_pte)     ((((_pte).pte >> 1) & 0x7) | \
+                                (((_pte).pte >> 2) & 0x8) | \
+                                (((_pte).pte >> 8) <<  4))
 
-#define pgoff_to_pte(off) \
-       ((pte_t) { (((off) & 0x1f) << 3) + (((off) >> 6) << 9) + _PAGE_FILE })
+#define pgoff_to_pte(off)      ((pte_t) { (((off) & 0x7) << 1) | \
+                                          (((off) & 0x8) << 2) | \
+                                          (((off) >>  4) << 8) | \
+                                          _PAGE_FILE })
 #endif
 
 #endif
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high })
+#define __swp_entry_to_pte(x)  ((pte_t) { 0, (x).val })
+#else
 #define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
+#endif
 
 #endif /* _ASM_PGTABLE_32_H */
index 82166b254b2704d649dc27f1acb725ba07dadf38..e3db93212eab0845b7c82e697d116b67a67c786c 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_PGTABLE_64_H
 #define _ASM_PGTABLE_64_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 
 #include <asm/addrspace.h>
@@ -224,15 +223,12 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 #define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
 
 /*
- * Bits 0, 1, 2, 7 and 8 are taken, split up the 32 bits of offset
- * into this range:
+ * Bits 0, 4, 6, and 7 are taken. Let's leave bits 1, 2, 3, and 5 alone to
+ * make things easier, and only use the upper 56 bits for the page offset...
  */
-#define PTE_FILE_MAX_BITS      32
+#define PTE_FILE_MAX_BITS      56
 
-#define pte_to_pgoff(_pte) \
-       ((((_pte).pte >> 3) & 0x1f ) + (((_pte).pte >> 9) << 6 ))
-
-#define pgoff_to_pte(off) \
-       ((pte_t) { (((off) & 0x1f) << 3) + (((off) >> 6) << 9) + _PAGE_FILE })
+#define pte_to_pgoff(_pte)     ((_pte).pte >> 8)
+#define pgoff_to_pte(off)      ((pte_t) { ((off) << 8) | _PAGE_FILE })
 
 #endif /* _ASM_PGTABLE_64_H */
index 01e76e932e3f7e5af198bb01a4d3a93735a89902..7494ba91112a77dca294aa9a01a91498c8041125 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_PGTABLE_BITS_H
 #define _ASM_PGTABLE_BITS_H
 
-#include <linux/config.h>
 
 /*
  * Note that we shift the lower 32bits of each EntryLo[01] entry
index 702a28fa7a3489d01c2ff986c7dfd0adefebe0bc..a36ca1be17f25b829a171c7a475c0be54ed3e757 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _ASM_PGTABLE_H
 #define _ASM_PGTABLE_H
 
-#include <linux/config.h>
 #ifdef CONFIG_32BIT
 #include <asm/pgtable-32.h>
 #endif
@@ -70,7 +69,15 @@ extern unsigned long zero_page_mask;
 #define ZERO_PAGE(vaddr) \
        (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
 
-#define __HAVE_ARCH_MULTIPLE_ZERO_PAGE
+#define __HAVE_ARCH_MOVE_PTE
+#define move_pte(pte, prot, old_addr, new_addr)                                \
+({                                                                     \
+       pte_t newpte = (pte);                                           \
+       if (pte_present(pte) && pfn_valid(pte_pfn(pte)) &&              \
+                       pte_page(pte) == ZERO_PAGE(old_addr))           \
+               newpte = mk_pte(ZERO_PAGE(new_addr), (prot));           \
+       newpte;                                                         \
+})
 
 extern void paging_init(void);
 
@@ -82,10 +89,11 @@ extern void paging_init(void);
 #define pmd_page(pmd)          (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
 #define pmd_page_kernel(pmd)   pmd_val(pmd)
 
-#define pte_none(pte)          (!(pte_val(pte) & ~_PAGE_GLOBAL))
-#define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
-
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
+
+#define pte_none(pte)          (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
+#define pte_present(pte)       ((pte).pte_low & _PAGE_PRESENT)
+
 static inline void set_pte(pte_t *ptep, pte_t pte)
 {
        ptep->pte_high = pte.pte_high;
@@ -93,27 +101,35 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
        ptep->pte_low = pte.pte_low;
        //printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low);
 
-       if (pte_val(pte) & _PAGE_GLOBAL) {
+       if (pte.pte_low & _PAGE_GLOBAL) {
                pte_t *buddy = ptep_buddy(ptep);
                /*
                 * Make sure the buddy is global too (if it's !none,
                 * it better already be global)
                 */
-               if (pte_none(*buddy))
-                       buddy->pte_low |= _PAGE_GLOBAL;
+               if (pte_none(*buddy)) {
+                       buddy->pte_low  |= _PAGE_GLOBAL;
+                       buddy->pte_high |= _PAGE_GLOBAL;
+               }
        }
 }
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
+       pte_t null = __pte(0);
+
        /* Preserve global status for the pair */
-       if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
-               set_pte_at(mm, addr, ptep, __pte(_PAGE_GLOBAL));
-       else
-               set_pte_at(mm, addr, ptep, __pte(0));
+       if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL)
+               null.pte_low = null.pte_high = _PAGE_GLOBAL;
+
+       set_pte_at(mm, addr, ptep, null);
 }
 #else
+
+#define pte_none(pte)          (!(pte_val(pte) & ~_PAGE_GLOBAL))
+#define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
+
 /*
  * Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
@@ -174,75 +190,76 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
  */
 static inline int pte_user(pte_t pte)  { BUG(); return 0; }
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
-static inline int pte_read(pte_t pte)  { return (pte).pte_low & _PAGE_READ; }
-static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_WRITE; }
-static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_MODIFIED; }
-static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; }
-static inline int pte_file(pte_t pte)  { return (pte).pte_low & _PAGE_FILE; }
+static inline int pte_read(pte_t pte)  { return pte.pte_low & _PAGE_READ; }
+static inline int pte_write(pte_t pte) { return pte.pte_low & _PAGE_WRITE; }
+static inline int pte_dirty(pte_t pte) { return pte.pte_low & _PAGE_MODIFIED; }
+static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)  { return pte.pte_low & _PAGE_FILE; }
+
 static inline pte_t pte_wrprotect(pte_t pte)
 {
-       (pte).pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
-       (pte).pte_high &= ~_PAGE_SILENT_WRITE;
+       pte.pte_low  &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+       pte.pte_high &= ~_PAGE_SILENT_WRITE;
        return pte;
 }
 
 static inline pte_t pte_rdprotect(pte_t pte)
 {
-       (pte).pte_low &= ~(_PAGE_READ | _PAGE_SILENT_READ);
-       (pte).pte_high &= ~_PAGE_SILENT_READ;
+       pte.pte_low  &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+       pte.pte_high &= ~_PAGE_SILENT_READ;
        return pte;
 }
 
 static inline pte_t pte_mkclean(pte_t pte)
 {
-       (pte).pte_low &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
-       (pte).pte_high &= ~_PAGE_SILENT_WRITE;
+       pte.pte_low  &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
+       pte.pte_high &= ~_PAGE_SILENT_WRITE;
        return pte;
 }
 
 static inline pte_t pte_mkold(pte_t pte)
 {
-       (pte).pte_low &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
-       (pte).pte_high &= ~_PAGE_SILENT_READ;
+       pte.pte_low  &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ);
+       pte.pte_high &= ~_PAGE_SILENT_READ;
        return pte;
 }
 
 static inline pte_t pte_mkwrite(pte_t pte)
 {
-       (pte).pte_low |= _PAGE_WRITE;
-       if ((pte).pte_low & _PAGE_MODIFIED) {
-               (pte).pte_low |= _PAGE_SILENT_WRITE;
-               (pte).pte_high |= _PAGE_SILENT_WRITE;
+       pte.pte_low |= _PAGE_WRITE;
+       if (pte.pte_low & _PAGE_MODIFIED) {
+               pte.pte_low  |= _PAGE_SILENT_WRITE;
+               pte.pte_high |= _PAGE_SILENT_WRITE;
        }
        return pte;
 }
 
 static inline pte_t pte_mkread(pte_t pte)
 {
-       (pte).pte_low |= _PAGE_READ;
-       if ((pte).pte_low & _PAGE_ACCESSED) {
-               (pte).pte_low |= _PAGE_SILENT_READ;
-               (pte).pte_high |= _PAGE_SILENT_READ;
+       pte.pte_low |= _PAGE_READ;
+       if (pte.pte_low & _PAGE_ACCESSED) {
+               pte.pte_low  |= _PAGE_SILENT_READ;
+               pte.pte_high |= _PAGE_SILENT_READ;
        }
        return pte;
 }
 
 static inline pte_t pte_mkdirty(pte_t pte)
 {
-       (pte).pte_low |= _PAGE_MODIFIED;
-       if ((pte).pte_low & _PAGE_WRITE) {
-               (pte).pte_low |= _PAGE_SILENT_WRITE;
-               (pte).pte_high |= _PAGE_SILENT_WRITE;
+       pte.pte_low |= _PAGE_MODIFIED;
+       if (pte.pte_low & _PAGE_WRITE) {
+               pte.pte_low  |= _PAGE_SILENT_WRITE;
+               pte.pte_high |= _PAGE_SILENT_WRITE;
        }
        return pte;
 }
 
 static inline pte_t pte_mkyoung(pte_t pte)
 {
-       (pte).pte_low |= _PAGE_ACCESSED;
-       if ((pte).pte_low & _PAGE_READ)
-               (pte).pte_low |= _PAGE_SILENT_READ;
-               (pte).pte_high |= _PAGE_SILENT_READ;
+       pte.pte_low |= _PAGE_ACCESSED;
+       if (pte.pte_low & _PAGE_READ)
+               pte.pte_low  |= _PAGE_SILENT_READ;
+               pte.pte_high |= _PAGE_SILENT_READ;
        return pte;
 }
 #else
@@ -335,8 +352,9 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1)
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-       pte.pte_low &= _PAGE_CHG_MASK;
-       pte.pte_low |= pgprot_val(newprot);
+       pte.pte_low  &= _PAGE_CHG_MASK;
+       pte.pte_high &= ~0x3f;
+       pte.pte_low  |= pgprot_val(newprot);
        pte.pte_high |= pgprot_val(newprot) & 0x3f;
        return pte;
 }
@@ -360,9 +378,7 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
        __update_cache(vma, address, pte);
 }
 
-#ifndef CONFIG_NEED_MULTIPLE_NODES
 #define kern_addr_valid(addr)  (1)
-#endif
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
 extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot);
index 71293ec1657c3319b52e83651007d239500139bd..17850834ccb0960ea8fe46c910c48e64cb61171a 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef __ASM_PREFETCH_H
 #define __ASM_PREFETCH_H
 
-#include <linux/config.h>
 
 /*
  * R5000 and RM5200 implements pref and prefx instructions but they're nops, so
index 0fb75f0762e0b6934dbe03b18f3aace575ba5f96..5f80ba71ab92b3ad17778e483a8cad854d728c24 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_PROCESSOR_H
 #define _ASM_PROCESSOR_H
 
-#include <linux/config.h>
 #include <linux/cpumask.h>
 #include <linux/threads.h>
 
@@ -71,11 +70,6 @@ extern unsigned int vced_count, vcei_count;
 
 typedef __u64 fpureg_t;
 
-struct mips_fpu_hard_struct {
-       fpureg_t        fpr[NUM_FPU_REGS];
-       unsigned int    fcr31;
-};
-
 /*
  * It would be nice to add some more fields for emulator statistics, but there
  * are a number of fixed offsets in offset.h and elsewhere that would have to
@@ -83,18 +77,13 @@ struct mips_fpu_hard_struct {
  * the FPU emulator for now.  See asm-mips/fpu_emulator.h.
  */
 
-struct mips_fpu_soft_struct {
+struct mips_fpu_struct {
        fpureg_t        fpr[NUM_FPU_REGS];
        unsigned int    fcr31;
 };
 
-union mips_fpu_union {
-        struct mips_fpu_hard_struct hard;
-        struct mips_fpu_soft_struct soft;
-};
-
 #define INIT_FPU { \
-       {{0,},} \
+       {0,} \
 }
 
 #define NUM_DSP_REGS   6
@@ -133,7 +122,7 @@ struct thread_struct {
        unsigned long cp0_status;
 
        /* Saved fpu/fpu emulator stuff. */
-       union mips_fpu_union fpu;
+       struct mips_fpu_struct fpu;
 #ifdef CONFIG_MIPS_MT_FPAFF
        /* Emulated instruction count */
        unsigned long emulated_fp;
index fa9d8713c12a2615ac0e1c89ff3b22f9be683797..4113316ee0da595bc6292bb50bbedb19737dcb46 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_PTRACE_H
 #define _ASM_PTRACE_H
 
-#include <linux/config.h>
 
 #include <asm/isadep.h>
 
index 905c39585903924d6c3e034e16ee28b634e589a9..531caf44560cca531de876941f33a828f58e8a4b 100644 (file)
  */
 #define QEMU_C0_COUNTER_CLOCK  100000000
 
+/*
+ * Magic qemu system control location.
+ */
+#define QEMU_RESTART_REG       0xBFBF0000
+#define QEMU_HALT_REG          0xBFBF0004
+
 #endif /* __ASM_QEMU_H */
index 6173004cc88ec72f443f617fdbf17b3a7ad3a32a..634b55d7e7f6d1ada10dfa02175c11a81790f78d 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_MIPS_REG_H
 #define __ASM_MIPS_REG_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H)
 
index 1fba00c2207714bc83c3911ca393954ec3afb1b1..87cb3085269ca49f1a3280865f43a37b6d5be74b 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_RESOURCE_H
 #define _ASM_RESOURCE_H
 
-#include <linux/config.h>
 
 /*
  * These five resource limit IDs have a MIPS/Linux-specific ordering,
diff --git a/include/asm-mips/rm9k-ocd.h b/include/asm-mips/rm9k-ocd.h
new file mode 100644 (file)
index 0000000..b0b80d9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if !defined(_ASM_RM9K_OCD_H)
+#define _ASM_RM9K_OCD_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+extern volatile void __iomem * const ocd_base;
+extern volatile void __iomem * const titan_base;
+
+#define ocd_addr(__x__)                (ocd_base + (__x__))
+#define titan_addr(__x__)      (titan_base + (__x__))
+#define scram_addr(__x__)      (scram_base + (__x__))
+
+/* OCD register access */
+#define ocd_readl(__offs__) __raw_readl(ocd_addr(__offs__))
+#define ocd_readw(__offs__) __raw_readw(ocd_addr(__offs__))
+#define ocd_readb(__offs__) __raw_readb(ocd_addr(__offs__))
+#define ocd_writel(__val__, __offs__) \
+       __raw_writel((__val__), ocd_addr(__offs__))
+#define ocd_writew(__val__, __offs__) \
+       __raw_writew((__val__), ocd_addr(__offs__))
+#define ocd_writeb(__val__, __offs__) \
+       __raw_writeb((__val__), ocd_addr(__offs__))
+
+/* TITAN register access - 32 bit-wide only */
+#define titan_readl(__offs__) __raw_readl(titan_addr(__offs__))
+#define titan_writel(__val__, __offs__) \
+       __raw_writel((__val__), titan_addr(__offs__))
+
+/* Protect access to shared TITAN registers */
+extern spinlock_t titan_lock;
+extern int titan_irqflags;
+#define lock_titan_regs() spin_lock_irqsave(&titan_lock, titan_irqflags)
+#define unlock_titan_regs() spin_unlock_irqrestore(&titan_lock, titan_irqflags)
+
+#endif /* !defined(_ASM_RM9K_OCD_H) */
index 7196ceb0e94821988a2bea67bff64e90568b5c32..584bd9c0ab2e862f8267ea78af7c5ede2700acd4 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_SERIAL_H
 #define _ASM_SERIAL_H
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
index 722b77a8c5e5a010fe693374ac37644c7a6cd43f..ddb859d0525773edb42a912eb0a9abcfe8d53aa8 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_SGIARCS_H
 #define _ASM_SGIARCS_H
 
-#include <linux/config.h>
 #include <asm/types.h>
 #include <asm/arc/types.h>
 
index 900edcbeec37950a6770a098d9483ec5e5b3dc55..3dfe29ed42a8cdf6cc45f01e1dfbd978dbada5c5 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef _SIBYTE_BOARD_H
 #define _SIBYTE_BOARD_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_PTSWARM) || \
     defined(CONFIG_SIBYTE_CRHONE) || defined(CONFIG_SIBYTE_CRHINE) || \
index b5e7dae19f0fc7842d5a10fdc4379af41254dde3..57c53e62a37ac70a24d2ba7dc69f50355521aacc 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __ASM_SIBYTE_CARMEL_H
 #define __ASM_SIBYTE_CARMEL_H
 
-#include <linux/config.h>
 
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_int.h>
index 824605847af4813bd1dd4cf45e3ee7a09b32711f..64c47874f32d83d1e69e91ff262596283a932c51 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __ASM_SIBYTE_SENTOSA_H
 #define __ASM_SIBYTE_SENTOSA_H
 
-#include <linux/config.h>
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_int.h>
 
index 06e1d528e03aeb9c05bfa16a9543ae8bea4b2861..86db37e5ad85dc9e860df6d24a56d6bbcfb5212b 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __ASM_SIBYTE_SWARM_H
 #define __ASM_SIBYTE_SWARM_H
 
-#include <linux/config.h>
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_int.h>
 
index 8edabb0be23f64f8cb576178fde9c2643b93e12b..cefa657dd04a86268923122e5bb8fce3ec1fa480 100644 (file)
@@ -55,8 +55,14 @@ struct sigcontext {
 struct sigcontext {
        unsigned long   sc_regs[32];
        unsigned long   sc_fpregs[32];
-       unsigned long   sc_hi[4];
-       unsigned long   sc_lo[4];
+       unsigned long   sc_mdhi;
+       unsigned long   sc_hi1;
+       unsigned long   sc_hi2;
+       unsigned long   sc_hi3;
+       unsigned long   sc_mdlo;
+       unsigned long   sc_lo1;
+       unsigned long   sc_lo2;
+       unsigned long   sc_lo3;
        unsigned long   sc_pc;
        unsigned int    sc_fpc_csr;
        unsigned int    sc_used_math;
index 2ba313d94a7860adf984c8925e2343eac02399b4..2e32949bd674d08425654f7268641bf3a27f5a9c 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_SIGINFO_H
 #define _ASM_SIGINFO_H
 
-#include <linux/config.h>
 
 #define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(long) + 2*sizeof(int))
 #undef __ARCH_SI_TRAPNO        /* exception code needs to fill this ...  */
index d8349e4b55ee333f17670475420ca564fbda9bfc..a1f3a3fa9bd60e49af8b1bfa858fc3b26df42236 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_SIGNAL_H
 #define _ASM_SIGNAL_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #define _NSIG          128
index 9c2af1b00e19732f07f1cebd1ec6ec0a2a9de331..67c4fe52bb426c3d9a6281d0ca886d5d6843f49d 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_SIM_H
 #define _ASM_SIM_H
 
-#include <linux/config.h>
 
 #include <asm/asm-offsets.h>
 
index 75c6fe7c212682390e3e29c6f6ab0ba55e362552..1608fd71d6f7ffd7d1e1a39cf181515c658c3ea4 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 
@@ -48,7 +47,6 @@ extern struct call_data_struct *call_data;
 #define SMP_CALL_FUNCTION      0x2
 
 extern cpumask_t phys_cpu_present_map;
-extern cpumask_t cpu_online_map;
 #define cpu_possible_map       phys_cpu_present_map
 
 extern cpumask_t cpu_callout_map;
@@ -86,9 +84,9 @@ extern void prom_init_secondary(void);
 extern void plat_smp_setup(void);
 
 /*
- * Called after init_IRQ but before __cpu_up.
+ * Called in smp_prepare_cpus.
  */
-extern void prom_prepare_cpus(unsigned int max_cpus);
+extern void plat_prepare_cpus(unsigned int max_cpus);
 
 /*
  * Last chance for the board code to finish SMP initialization before
index 2b5cef1ba37fc9fbbc17aa92330036997afb3feb..8fa0af6b68d237c8d454e251e650ae78533ec4d7 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_SN_ADDRS_H
 #define _ASM_SN_ADDRS_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
 #ifndef __ASSEMBLY__
 
-#if defined(CONFIG_SGI_IO)     /* FIXME */
-#define PS_UINT_CAST           (__psunsigned_t)
-#define UINT64_CAST            (__uint64_t)
-#else  /* CONFIG_SGI_IO */
 #define PS_UINT_CAST           (unsigned long)
 #define UINT64_CAST            (unsigned long)
-#endif /* CONFIG_SGI_IO */
 
 #define HUBREG_CAST            (volatile hubreg_t *)
 
  * for _x.
  */
 
-#ifdef _STANDALONE
-
-/* DO NOT USE THESE DIRECTLY IN THE KERNEL. SEE BELOW. */
-#define LOCAL_HUB(_x)          (HUBREG_CAST (IALIAS_BASE + (_x)))
-#define REMOTE_HUB(_n, _x)     (HUBREG_CAST (NODE_SWIN_BASE(_n, 1) +   \
-                                             0x800000 + (_x)))
-#endif /* _STANDALONE */
-
 /*
  * WARNING:
  *     When certain Hub chip workaround are defined, it's not sufficient
        PHYS_TO_K0(NODE_OFFSET(nasid) | ARCS_SPB_OFFSET)
 #define ARCS_SPB_SIZE          0x0400
 
-#ifdef _STANDALONE
-
-#define ARCS_TVECTOR_OFFSET    0x2800
-#define ARCS_PVECTOR_OFFSET    0x2c00
-
-/*
- * These addresses are used by the master CPU to install the transfer
- * and private vectors.  All others use the SPB to find them.
- */
-#define TVADDR (NODE_CAC_BASE(get_nasid()) + ARCS_TVECTOR_OFFSET)
-#define PVADDR (NODE_CAC_BASE(get_nasid()) + ARCS_PVECTOR_OFFSET)
-
-#endif /* _STANDALONE */
-
 #define KLDIR_OFFSET           0x2000
 #define KLDIR_ADDR(nasid)                                              \
        TO_NODE_UNCAC((nasid), KLDIR_OFFSET)
index d6df13aaed4971e061014164aff14564fac3fc5e..ac4ea85c3a5c7da6338859581135486b8c65607a 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_SGI_SN_AGENT_H
 #define _ASM_SGI_SN_AGENT_H
 
-#include <linux/config.h>
 #include <linux/topology.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
index d247a819de7f88c351b4af8eecdf3a75d801e88e..51174af6ac5213608f3f85a0ecc90749adabe421 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_SN_ARCH_H
 #define _ASM_SN_ARCH_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/sn/types.h>
 #ifdef CONFIG_SGI_IP27
similarity index 90%
rename from include/asm-mips/sn/sn0/sn0_fru.h
rename to include/asm-mips/sn/fru.h
index 82c6377c275ae5e6fa556a788813d4207307a020..b3e3606723b77898114aeac611f85722e1d25c89 100644 (file)
@@ -6,10 +6,10 @@
  * Derived from IRIX <sys/SN/SN0/sn0_fru.h>
  *
  * Copyright (C) 1992 - 1997, 1999 Silcon Graphics, Inc.
- * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2006 Ralf Baechle (ralf@linux-mips)
  */
-#ifndef _ASM_SN_SN0_SN0_FRU_H
-#define _ASM_SN_SN0_SN0_FRU_H
+#ifndef __ASM_SN_FRU_H
+#define __ASM_SN_FRU_H
 
 #define MAX_DIMMS                      8        /* max # of dimm banks */
 #define MAX_PCIDEV                     8        /* max # of pci devices on a pci bus */
@@ -41,4 +41,4 @@ typedef struct kf_pci_bus_s {
                                        /* confidence level that the pci dev is bad */
 } kf_pci_bus_t;
 
-#endif /* _ASM_SN_SN0_SN0_FRU_H */
+#endif /* __ASM_SN_FRU_H */
index 13326453efc99a5cc8542cce657df26de455b39b..ab2fa8cd2627094181cbeab2f16af96daf8c0fef 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_SN_IO_H
 #define _ASM_SN_IO_H
 
-#include <linux/config.h>
 #if defined (CONFIG_SGI_IP27)
 #include <asm/sn/sn0/hubio.h>
 #endif
index 9709ff701d9be8095dcacd33049d1a18a81e2680..52238e65af8e43227f304c35d4d2fcb6d3321b35 100644 (file)
@@ -27,7 +27,6 @@
  *      that offsets of existing fields do not change.
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/sn/types.h>
 
@@ -37,7 +36,7 @@
 //#include <sys/SN/router.h>
 // XXX Stolen from <sys/SN/router.h>:
 #define MAX_ROUTER_PORTS (6)    /* Max. number of ports on a router */
-#include <asm/sn/sn0/sn0_fru.h>
+#include <asm/sn/fru.h>
 //#include <sys/graph.h>
 //#include <sys/xtalk/xbow.h>
 
 #include <asm/sn/agent.h>
 #include <asm/arc/types.h>
 #include <asm/arc/hinv.h>
-#if defined(CONFIG_SGI_IO) || defined(CONFIG_SGI_IP35)
+#if defined(CONFIG_SGI_IP35)
 // The hack file has to be before vector and after sn0_fru....
 #include <asm/hack.h>
 #include <asm/sn/vector.h>
 #include <asm/xtalk/xtalk.h>
-#endif /* CONFIG_SGI_IO || CONFIG_SGI_IP35 */
+#endif /* CONFIG_SGI_IP35 */
 #endif /* CONFIG_SGI_IP27 || CONFIG_SGI_IP35 */
 
 #define KLCFGINFO_MAGIC        0xbeedbabe
 
-#ifdef FRUTEST
-typedef u64 klconf_off_t;
-#else
 typedef s32 klconf_off_t;
-#endif
 
 /*
  * Some IMPORTANT OFFSETS. These are the offsets on all NODES.
  */
-#if 0
-#define RAMBASE                 0
-#define ARCSSPB_OFF             0x1000 /* shift it to sys/arcs/spb.h */
-
-#define OFF_HWGRAPH            0
-#endif
-
 #define        MAX_MODULE_ID           255
 #define SIZE_PAD               4096 /* 4k padding for structures */
 /*
@@ -134,15 +122,9 @@ typedef s32 klconf_off_t;
 
 
 typedef struct console_s {
-#if defined(CONFIG_SGI_IO)     /* FIXME */
-       __psunsigned_t  uart_base;
-       __psunsigned_t  config_base;
-       __psunsigned_t  memory_base;
-#else
        unsigned long   uart_base;
        unsigned long   config_base;
        unsigned long   memory_base;
-#endif
        short           baud;
        short           flag;
        int             type;
@@ -174,10 +156,6 @@ typedef struct kl_config_hdr {
 
 
 #define KL_CONFIG_HDR(_nasid)  ((kl_config_hdr_t *)(KLCONFIG_ADDR(_nasid)))
-#if 0
-#define KL_CONFIG_MALLOC_HDR(_nasid) \
-                                (KL_CONFIG_HDR(_nasid)->ch_malloc_hdr)
-#endif
 #define KL_CONFIG_INFO_OFFSET(_nasid)                                  \
         (KL_CONFIG_HDR(_nasid)->ch_board_info)
 #define KL_CONFIG_INFO_SET_OFFSET(_nasid, _off)                                \
@@ -197,23 +175,13 @@ typedef struct kl_config_hdr {
 
 /* --- New Macros for the changed kl_config_hdr_t structure --- */
 
-#if defined(CONFIG_SGI_IO)
-#define PTR_CH_MALLOC_HDR(_k)   ((klc_malloc_hdr_t *)\
-                       ((__psunsigned_t)_k + (_k->ch_malloc_hdr_off)))
-#else
 #define PTR_CH_MALLOC_HDR(_k)   ((klc_malloc_hdr_t *)\
                        (unsigned long)_k + (_k->ch_malloc_hdr_off)))
-#endif
 
 #define KL_CONFIG_CH_MALLOC_HDR(_n)   PTR_CH_MALLOC_HDR(KL_CONFIG_HDR(_n))
 
-#if defined(CONFIG_SGI_IO)
-#define PTR_CH_CONS_INFO(_k)   ((console_t *)\
-                       ((__psunsigned_t)_k + (_k->ch_cons_off)))
-#else
 #define PTR_CH_CONS_INFO(_k)   ((console_t *)\
                        ((unsigned long)_k + (_k->ch_cons_off)))
-#endif
 
 #define KL_CONFIG_CH_CONS_INFO(_n)   PTR_CH_CONS_INFO(KL_CONFIG_HDR(_n))
 
@@ -490,14 +458,6 @@ typedef struct lboard_s {
 #define KLCF_NUM_COMPS(_brd)   ((_brd)->brd_numcompts)
 #define KLCF_MODULE_ID(_brd)   ((_brd)->brd_module)
 
-#ifdef FRUTEST
-
-#define KLCF_NEXT(_brd)                ((_brd)->brd_next ? (lboard_t *)((_brd)->brd_next):  NULL)
-#define KLCF_COMP(_brd, _ndx)          (klinfo_t *)((_brd)->brd_compts[(_ndx)])
-#define KLCF_COMP_ERROR(_brd, _comp)           (_brd = _brd , (_comp)->errinfo)
-
-#else
-
 #define KLCF_NEXT(_brd)        \
         ((_brd)->brd_next ?    \
         (lboard_t *)(NODE_OFFSET_TO_K1(NASID_GET(_brd), (_brd)->brd_next)):\
@@ -509,8 +469,6 @@ typedef struct lboard_s {
 #define KLCF_COMP_ERROR(_brd, _comp)   \
                (NODE_OFFSET_TO_K1(NASID_GET(_brd), (_comp)->errinfo))
 
-#endif
-
 #define KLCF_COMP_TYPE(_comp)  ((_comp)->struct_type)
 #define KLCF_BRIDGE_W_ID(_comp)        ((_comp)->physid)       /* Widget ID */
 
@@ -631,18 +589,6 @@ typedef struct klport_s {
        klconf_off_t    port_offset;
 } klport_t;
 
-#if 0
-/*
- * This is very similar to the klport_s but instead of having a componant
- * offset it has a board offset.
- */
-typedef struct klxbow_port_s {
-       nasid_t         port_nasid;
-       unsigned char   port_flag;
-       klconf_off_t    board_offset;
-} klxbow_port_t;
-#endif
-
 typedef struct klcpu_s {                          /* CPU */
        klinfo_t        cpu_info;
        unsigned short  cpu_prid;       /* Processor PRID value */
@@ -945,36 +891,6 @@ extern klcpu_t *nasid_slice_to_cpuinfo(nasid_t, int);
 extern lboard_t *find_lboard_class(lboard_t *start, unsigned char brd_class);
 
 
-#if defined(CONFIG_SGI_IO)
-extern xwidgetnum_t nodevertex_widgetnum_get(vertex_hdl_t node_vtx);
-extern vertex_hdl_t nodevertex_xbow_peer_get(vertex_hdl_t node_vtx);
-extern lboard_t *find_gfxpipe(int pipenum);
-extern void setup_gfxpipe_link(vertex_hdl_t vhdl,int pipenum);
-extern lboard_t *find_lboard_module_class(lboard_t *start, moduleid_t mod,
-                                               unsigned char brd_class);
-extern lboard_t *find_nic_lboard(lboard_t *, nic_t);
-extern lboard_t *find_nic_type_lboard(nasid_t, unsigned char, nic_t);
-extern lboard_t *find_lboard_modslot(lboard_t *start, moduleid_t mod, slotid_t slot);
-extern lboard_t *find_lboard_module(lboard_t *start, moduleid_t mod);
-extern lboard_t *get_board_name(nasid_t nasid, moduleid_t mod, slotid_t slot, char *name);
-extern int     config_find_nic_router(nasid_t, nic_t, lboard_t **, klrou_t**);
-extern int     config_find_nic_hub(nasid_t, nic_t, lboard_t **, klhub_t**);
-extern int     config_find_xbow(nasid_t, lboard_t **, klxbow_t**);
-extern klcpu_t *get_cpuinfo(cpuid_t cpu);
-extern int     update_klcfg_cpuinfo(nasid_t, int);
-extern void    board_to_path(lboard_t *brd, char *path);
-extern moduleid_t get_module_id(nasid_t nasid);
-extern void    nic_name_convert(char *old_name, char *new_name);
-extern int     module_brds(nasid_t nasid, lboard_t **module_brds, int n);
-extern lboard_t *brd_from_key(ulong_t key);
-extern void    device_component_canonical_name_get(lboard_t *,klinfo_t *,
-                                                   char *);
-extern int     board_serial_number_get(lboard_t *,char *);
-extern int     is_master_baseio(nasid_t,moduleid_t,slotid_t);
-extern nasid_t get_actual_nasid(lboard_t *brd) ;
-extern net_vec_t klcfg_discover_route(lboard_t *, lboard_t *, int);
-#else  /* CONFIG_SGI_IO */
 extern klcpu_t *sn_get_cpuinfo(cpuid_t cpu);
-#endif /* CONFIG_SGI_IO */
 
 #endif /* _ASM_SN_KLCONFIG_H */
index f0efab1672ecc34adc9bb05ecd8344210b8b10c9..0573cbffc104e07f8c192e6ebfc056794100e7be 100644 (file)
 #ifndef _ASM_SN_KLDIR_H
 #define _ASM_SN_KLDIR_H
 
-#include <linux/config.h>
-
-#if defined(CONFIG_SGI_IO)
-#include <asm/hack.h>
-#endif
 
 /*
  * The kldir memory area resides at a fixed place in each node's memory and
 #define KLDIR_OFF_STRIDE               0x28
 #endif /* __ASSEMBLY__ */
 
-#if !defined(CONFIG_SGI_IO)
-
 /*
  * This is defined here because IP27_SYMMON_STK_SIZE must be at least what
  * we define here.  Since it's set up in the prom.  We can't redefine it later
  */
 #define SYMMON_STACK_SIZE              0x8000
 
-#if defined (PROM) || defined (SABLE)
+#if defined (PROM)
 
 /*
  * These defines are prom version dependent.  No code other than the IP27
 #define IP27_FREEMEM_COUNT             1
 #define IP27_FREEMEM_STRIDE            0
 
-#endif /* PROM || SABLE*/
+#endif /* PROM */
 /*
  * There will be only one of these in a partition so the IO6 must set it up.
  */
 #define KLDIR_ENT_SIZE                 0x40
 #define KLDIR_MAX_ENTRIES              (0x400 / 0x40)
 
-#endif /* !CONFIG_SGI_IO */
-
 #ifndef __ASSEMBLY__
 typedef struct kldir_ent_s {
        u64             magic;          /* Indicates validity of entry      */
        off_t           offset;         /* Offset from start of node space  */
-#if defined(CONFIG_SGI_IO)     /* FIXME */
-       __psunsigned_t  pointer;        /* Pointer to area in some cases    */
-#else
        unsigned long   pointer;        /* Pointer to area in some cases    */
-#endif
        size_t          size;           /* Size in bytes                    */
        u64             count;          /* Repeat count if array, 1 if not  */
        size_t          stride;         /* Stride if array, 0 if not        */
@@ -227,22 +214,4 @@ typedef struct kldir_ent_s {
 } kldir_ent_t;
 #endif /* !__ASSEMBLY__ */
 
-#if defined(CONFIG_SGI_IO)
-
-#define KLDIR_ENT_SIZE                 0x40
-#define KLDIR_MAX_ENTRIES              (0x400 / 0x40)
-
-/*
- * The actual offsets of each memory area are machine-dependent
- */
-#ifdef CONFIG_SGI_IP27
-// Not yet #include <asm/sn/sn0/kldir.h>
-#elif defined(CONFIG_SGI_IP35)
-#include <asm/sn/sn1/kldir.h>
-#else
-#error "kldir.h is currently defined for IP27 and IP35 platforms only"
-#endif
-
-#endif /* CONFIG_SGI_IO */
-
 #endif /* _ASM_SN_KLDIR_H */
index b67699c0c475e1a7cb929f141d5a6b6a203d696d..b7c2226312c627122183ac8d18d7c74ee39b49f3 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_SN_LAUNCH_H
 #define _ASM_SN_LAUNCH_H
 
-#include <linux/config.h>
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
 
index 59edb20f8ec50b492fe7d2c66d7b0ffd5ad198ea..c3dd5d0d525fc66be6c92dc70c86b2ad5b547577 100644 (file)
@@ -20,7 +20,6 @@
  * code. So no jumps can be done before we have switched to using
  * cksseg addresses.
  */
-#include <linux/config.h>
 #include <asm/addrspace.h>
 
 #define REP_BASE       CAC_BASE
index 398815639fb893fc299a2b14269f058db1d1e89a..9e8cc52910f6d6d08c697a4ea95f811de07daf8b 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_SN_SN0_ADDRS_H
 #define _ASM_SN_SN0_ADDRS_H
 
-#include <linux/config.h>
 
 /*
  * SN0 (on a T5) Address map
@@ -49,7 +48,7 @@
  * so for now we just use defines bracketed by an ifdef.
  */
 
-#ifdef CONFIG_SGI_SN0_N_MODE
+#ifdef CONFIG_SGI_SN_N_MODE
 
 #define NODE_SIZE_BITS         31
 #define BWIN_SIZE_BITS         28
@@ -63,7 +62,7 @@
 #define BDDIR_UPPER_MASK       (UINT64_CAST 0x7ffff << 10)
 #define BDECC_UPPER_MASK       (UINT64_CAST 0x3ffffff << 3)
 
-#else /* !defined(CONFIG_SGI_SN0_N_MODE), assume that M-mode is desired */
+#else /* !defined(CONFIG_SGI_SN_N_MODE), assume that M-mode is desired */
 
 #define NODE_SIZE_BITS         32
 #define BWIN_SIZE_BITS         29
@@ -77,7 +76,7 @@
 #define BDDIR_UPPER_MASK       (UINT64_CAST 0xfffff << 10)
 #define BDECC_UPPER_MASK       (UINT64_CAST 0x7ffffff << 3)
 
-#endif /* !defined(CONFIG_SGI_SN0_N_MODE) */
+#endif /* !defined(CONFIG_SGI_SN_N_MODE) */
 
 #define NODE_ADDRSPACE_SIZE    (UINT64_CAST 1 << NODE_SIZE_BITS)
 
 #define NASID_GET(_pa)         (int) ((UINT64_CAST (_pa) >>            \
                                        NASID_SHFT) & NASID_BITMASK)
 
-#if !defined(__ASSEMBLY__) && !defined(_STANDALONE)
+#if !defined(__ASSEMBLY__)
 
 #define NODE_SWIN_BASE(nasid, widget)                                  \
        ((widget == 0) ? NODE_BWIN_BASE((nasid), SWIN0_BIGWIN)          \
        : RAW_NODE_SWIN_BASE(nasid, widget))
-#else /* __ASSEMBLY__ || _STANDALONE */
+#else /* __ASSEMBLY__ */
 #define NODE_SWIN_BASE(nasid, widget) \
      (NODE_IO_BASE(nasid) + (UINT64_CAST (widget) << SWIN_SIZE_BITS))
-#endif /* __ASSEMBLY__ || _STANDALONE */
+#endif /* __ASSEMBLY__ */
 
 /*
  * The following definitions pertain to the IO special address
 #define SN0_WIDGET_BASE(_nasid, _wid)  (NODE_SWIN_BASE((_nasid), (_wid)))
 
 /* Turn on sable logging for the processors whose bits are set. */
-#ifdef SABLE
-#define SABLE_LOG_TRIGGER(_map)        \
-               *((volatile hubreg_t *)(IO_BASE + 0x17ffff0)) = (_map)
-#else
 #define SABLE_LOG_TRIGGER(_map)
-#endif /* SABLE */
 
 #ifndef __ASSEMBLY__
 #define KERN_NMI_ADDR(nasid, slice)                                    \
 
 #define _ARCSPROM
 
-#ifdef _STANDALONE
-
-/*
- * The PROM needs to pass the device base address and the
- * device pci cfg space address to the device drivers during
- * install. The COMPONENT->Key field is used for this purpose.
- * Macros needed by SN0 device drivers to convert the
- * COMPONENT->Key field to the respective base address.
- * Key field looks as follows:
- *
- *  +----------------------------------------------------+
- *  |devnasid | widget  |pciid |hubwidid|hstnasid | adap |
- *  |   2     |   1     |  1   |   1    |    2    |   1  |
- *  +----------------------------------------------------+
- *  |         |         |      |        |         |      |
- *  64        48        40     32       24        8      0
- *
- * These are used by standalone drivers till the io infrastructure
- * is in place.
- */
-
-#ifndef __ASSEMBLY__
-
-#define uchar unsigned char
-
-#define KEY_DEVNASID_SHFT  48
-#define KEY_WIDID_SHFT    40
-#define KEY_PCIID_SHFT    32
-#define KEY_HUBWID_SHFT           24
-#define KEY_HSTNASID_SHFT  8
-
-#define MK_SN0_KEY(nasid, widid, pciid) \
-                       ((((__psunsigned_t)nasid)<< KEY_DEVNASID_SHFT |\
-                               ((__psunsigned_t)widid) << KEY_WIDID_SHFT) |\
-                               ((__psunsigned_t)pciid) << KEY_PCIID_SHFT)
-
-#define ADD_HUBWID_KEY(key,hubwid)\
-                       (key|=((__psunsigned_t)hubwid << KEY_HUBWID_SHFT))
-
-#define ADD_HSTNASID_KEY(key,hstnasid)\
-                       (key|=((__psunsigned_t)hstnasid << KEY_HSTNASID_SHFT))
-
-#define GET_DEVNASID_FROM_KEY(key)     ((short)(key >> KEY_DEVNASID_SHFT))
-#define GET_WIDID_FROM_KEY(key)                ((uchar)(key >> KEY_WIDID_SHFT))
-#define GET_PCIID_FROM_KEY(key)                ((uchar)(key >> KEY_PCIID_SHFT))
-#define GET_HUBWID_FROM_KEY(key)       ((uchar)(key >> KEY_HUBWID_SHFT))
-#define GET_HSTNASID_FROM_KEY(key)     ((short)(key >> KEY_HSTNASID_SHFT))
-
-#define PCI_64_TARGID_SHFT             60
-
-#define GET_PCIBASE_FROM_KEY(key)  (NODE_SWIN_BASE(GET_DEVNASID_FROM_KEY(key),\
-                                       GET_WIDID_FROM_KEY(key))\
-                                       | BRIDGE_DEVIO(GET_PCIID_FROM_KEY(key)))
-
-#define GET_PCICFGBASE_FROM_KEY(key) \
-                       (NODE_SWIN_BASE(GET_DEVNASID_FROM_KEY(key),\
-                             GET_WIDID_FROM_KEY(key))\
-                       | BRIDGE_TYPE0_CFG_DEV(GET_PCIID_FROM_KEY(key)))
-
-#define GET_WIDBASE_FROM_KEY(key) \
-                        (NODE_SWIN_BASE(GET_DEVNASID_FROM_KEY(key),\
-                              GET_WIDID_FROM_KEY(key)))
-
-#define PUT_INSTALL_STATUS(c,s)                c->Revision = s
-#define GET_INSTALL_STATUS(c)          c->Revision
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _STANDALONE */
-
 #if defined (HUB_ERR_STS_WAR)
 
 #define ERR_STS_WAR_REGISTER   IIO_IIBUSERR
index fb78773a5efed10f94111a6d887751922d5c5d5e..f734f2007f2400be504183c3386321f3e462be70 100644 (file)
@@ -11,9 +11,6 @@
 #ifndef _ASM_SN_SN0_ARCH_H
 #define _ASM_SN_SN0_ARCH_H
 
-#include <linux/config.h>
-
-#ifndef SABLE
 
 #ifndef SN0XXL  /* 128 cpu SMP max */
 /*
  */
 #define MAX_PARTITIONS         MAX_REGIONS
 
-
-#else
-
-#define MAX_COMPACT_NODES      4
-#define MAX_NASIDS             4
-#define MAXCPUS                        8
-
-#endif
-
 #define NASID_MASK_BYTES       ((MAX_NASIDS + 7) / 8)
 
 /*
  * Slot constants for SN0
  */
-#ifdef CONFIG_SGI_SN0_N_MODE
+#ifdef CONFIG_SGI_SN_N_MODE
 #define MAX_MEM_SLOTS   16                      /* max slots per node */
-#else /* !CONFIG_SGI_SN0_N_MODE, assume M_MODE */
+#else /* !CONFIG_SGI_SN_N_MODE, assume CONFIG_SGI_SN_M_MODE */
 #define MAX_MEM_SLOTS   32                      /* max slots per node */
-#endif /* defined(N_MODE) */
+#endif /* CONFIG_SGI_SN_M_MODE */
 
 #define SLOT_SHIFT             (27)
 #define SLOT_MIN_MEM_SIZE      (32*1024*1024)
index f5dbba6f4610c7f0826f3231c445b0ead9ca85ee..3e228f8e79695ff386d3d8f56989486733697d4a 100644 (file)
 #include <asm/sn/sn0/hubni.h>
 //#include <asm/sn/sn0/hubcore.h>
 
-#ifdef SABLE
-#define IP27_NO_HUBUART_INT    1
-#endif
-
 /* Translation of uncached attributes */
 #define        UATTR_HSPEC     0
 #define        UATTR_IO        1
index f314da21b9706c81581edb6867ff3354cf7efe1e..ef91b3363554ca8e1736112f3ab4a017b117e2cd 100644 (file)
@@ -486,22 +486,6 @@ typedef union h1_icrba_u {
 #define ICRBN_A_CERR_SHFT      54
 #define ICRBN_A_ERR_MASK       0x3ff
 
-#if 0  /* Disabled, this causes namespace polution and break allmodconfig */
-/*
- * Easy access macros.
- */
-#define        a_error         icrba_fields_s.error
-#define        a_ecode         icrba_fields_s.ecode
-#define        a_lnetuce       icrba_fields_s.lnetuce
-#define        a_mark          icrba_fields_s.mark
-#define        a_xerr          icrba_fields_s.xerr
-#define        a_sidn          icrba_fields_s.sidn
-#define        a_tnum          icrba_fields_s.tnum
-#define        a_addr          icrba_fields_s.addr
-#define        a_valid         icrba_fields_s.valid
-#define        a_iow           icrba_fields_s.iow
-#endif
-
 #endif /* !__ASSEMBLY__ */
 
 #define        IIO_ICRB_ADDR_SHFT      2       /* Shift to get proper address */
index a66def4e0ba0dc34e54ecb7ee72c8e35076066fd..14c225d80664b38faeab3aafd81cc847383ffd7f 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef        _ASM_SN_SN0_HUBMD_H
 #define        _ASM_SN_SN0_HUBMD_H
 
-#include <linux/config.h>
 
 /*
  * Hub Memory/Directory interface registers
@@ -92,7 +91,7 @@
 #define MD_UREG1_14            0x2200f0 /* uController/UART 1 register     */
 #define MD_UREG1_15            0x2200f8 /* uController/UART 1 register     */
 
-#ifdef CONFIG_SGI_SN0_N_MODE
+#ifdef CONFIG_SGI_SN_N_MODE
 #define MD_MEM_BANKS           4        /* 4 banks of memory max in N mode */
 #else
 #define MD_MEM_BANKS           8        /* 8 banks of memory max in M mode */
index 355bba8552e3f6339a413e966ae232c4a00edbdd..e39f5f9da040595d2e80c124398ecae29012ba55 100644 (file)
@@ -398,24 +398,6 @@ typedef u64        rtc_time_t;
 
 /* PI_RT_FILTER_CTRL mask and shift definitions */
 
-#if 0
-/*
- * XXX - This register's definition has changed, but it's only implemented
- * in Hub 2.
- */
-#define PRFC_DROP_COUNT_SHFT   27
-#define PRFC_DROP_COUNT_MASK   (UINT64_CAST 0x3ff << 27)
-#define PRFC_DROP_CTR_SHFT     18
-#define PRFC_DROP_CTR_MASK     (UINT64_CAST 0x1ff << 18)
-#define PRFC_MASK_ENABLE_SHFT  10
-#define PRFC_MASK_ENABLE_MASK  (UINT64_CAST 0x7f << 10)
-#define PRFC_MASK_CTR_SHFT     2
-#define PRFC_MASK_CTR_MASK     (UINT64_CAST 0xff << 2)
-#define PRFC_OFFSET_SHFT       0
-#define PRFC_OFFSET_MASK       (UINT64_CAST 3)
-#endif /* 0 */
-
-
 /*
  * Bits for NACK_CNT_A/B and NACK_CMP
  */
index ade0e974dd780ec80040099554bb98eb4f7483a5..3c97e0855c8d69a724643ed8a9d3f28eb193395e 100644 (file)
@@ -6,7 +6,7 @@
  * Derived from IRIX <sys/SN/SN0/IP27.h>.
  *
  * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc.
- * Copyright (C) 1999 by Ralf Baechle
+ * Copyright (C) 1999, 2006 by Ralf Baechle
  */
 #ifndef _ASM_SN_SN0_IP27_H
 #define _ASM_SN_SN0_IP27_H
 #define SEND_NMI(_nasid, _slice)       \
           REMOTE_HUB_S((_nasid),  (PI_NMI_A + ((_slice) * PI_NMI_OFFSET)), 1)
 
-/* Sanity hazzard ...  Below all the Origin hacks are following.  */
-
-#define SN00_BRIDGE            0x9200000008000000
-#define SN00I_BRIDGE0          0x920000000b000000
-#define SN00I_BRIDGE1          0x920000000e000000
-#define SN00I_BRIDGE2          0x920000000f000000
-
 #endif /* _ASM_SN_SN0_IP27_H */
index b3bc698dfdeeca4e6629517813788881f06fa48f..b9ba54d0dd359ebd6bfabfd84da4dcf2e53b4d93 100644 (file)
@@ -15,9 +15,6 @@
 /*
  * ASIC PCI registers for little endian configuration.
  */
-#ifndef __MIPSEL__
-#error "Fix me for big endian"
-#endif
 #define PCIMT_UCONF            0xbfff0000
 #define PCIMT_IOADTIMEOUT2     0xbfff0008
 #define PCIMT_IOMEMCONF                0xbfff0010
@@ -51,9 +48,9 @@
 #define PCIMT_PCI_CONF         0xbfff0100
 
 /*
- * Data port for the PCI bus.
+ * Data port for the PCI bus in IO space
  */
-#define PCIMT_CONFIG_DATA      0xb4000cfc
+#define PCIMT_CONFIG_DATA      0x0cfc
 
 /*
  * Board specific registers
diff --git a/include/asm-mips/sparsemem.h b/include/asm-mips/sparsemem.h
new file mode 100644 (file)
index 0000000..795ac6c
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _MIPS_SPARSEMEM_H
+#define _MIPS_SPARSEMEM_H
+#ifdef CONFIG_SPARSEMEM
+
+/*
+ * SECTION_SIZE_BITS           2^N: how big each section will be
+ * MAX_PHYSMEM_BITS            2^N: how much memory we can have in that space
+ */
+#define SECTION_SIZE_BITS       28
+#define MAX_PHYSMEM_BITS        35
+
+#endif /* CONFIG_SPARSEMEM */
+#endif /* _MIPS_SPARSEMEM_H */
+
index c4856a874965f3ad851808c9ec7886fd45bcd2a7..513aa5133830e59aa0f0dfa9c1162accbbbefc72 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_STACKFRAME_H
 #define _ASM_STACKFRAME_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 
 #include <asm/asm.h>
index 907da600fddd16497773728c8f59a1154f2f01dd..436e3ad352d95e78d8d9a24d72043fee0c087366 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_STRING_H
 #define _ASM_STRING_H
 
-#include <linux/config.h>
 
 /*
  * Most of the inline functions are rather naive implementations so I just
index 261f71d16a074f4dd4b3ab2fc2d42ba2c583d2e9..130333d7c4ee8021ff3736210443963e921d3598 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _ASM_SYSTEM_H
 #define _ASM_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
index f8d97dafd2f4c7659a8e78c0ba3118032637a541..ae8ada5b42a9e7bf58d8aca7071340b2058184cb 100644 (file)
@@ -9,7 +9,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
index bb4ae3cdcbf153c46a496b8b1876aa1c501b7d20..276be77c3e8531a30175edd74459c0d7e345dd17 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_TLBFLUSH_H
 #define __ASM_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 /*
index 6ce1e9475f998961256d36fd932dfe9576d761f5..94bef03d96358ba6ca4d8917f84b8758222115f4 100644 (file)
@@ -27,7 +27,6 @@
 #ifndef __ASM_TX4927_TOSHIBA_RBTX4927_H
 #define __ASM_TX4927_TOSHIBA_RBTX4927_H
 
-#include <linux/config.h>
 #include <asm/tx4927/tx4927.h>
 #include <asm/tx4927/tx4927_mips.h>
 #ifdef CONFIG_PCI
index cd2813d8e136af1f64d7b54b1f34661459e21110..2b52e180c6f25d75c28911ca68affdf41164afff 100644 (file)
@@ -52,7 +52,6 @@ typedef unsigned long long __u64;
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef __signed char s8;
 typedef unsigned char u8;
index b96f3e0f3933229788359d528657e73865b3dfca..1cdd4eeb2f735e5b8f27bd0e476348ce9056737f 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
index 1068fe9a0a583cff6f272357733f1f664833a7f7..8bb0bb9b2e68dbd8efb43406cf475e9e3f629f72 100644 (file)
 #define __NR_N32_Linux                 6000
 #define __NR_N32_Linux_syscalls                268
 
+#ifdef __KERNEL__
+
 #ifndef __ASSEMBLY__
 
 /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
@@ -1168,9 +1170,6 @@ type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
 
 #endif /* (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) */
 
-#ifdef __KERNEL__
-
-#include <linux/config.h>
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
@@ -1197,7 +1196,6 @@ type name (atype a,btype b,ctype c,dtype d,etype e,ftype f) \
 # ifdef CONFIG_MIPS32_O32
 #  define __ARCH_WANT_COMPAT_SYS_TIME
 # endif
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -1248,4 +1246,5 @@ asmlinkage long sys_rt_sigaction(int sig,
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_UNISTD_H */
index 4d41a9c091d4d5371f3107c35435dd119bb5f2e2..96fdcd54cec7a61b71ae97fc7998c375a7df0c48 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef __NEC_VRC4173_H
 #define __NEC_VRC4173_H
 
-#include <linux/config.h>
 #include <asm/io.h>
 
 /*
index ad374bd3f130b6f75fb0847626ff86df5e125a80..3ac146c019c9eab7d3fda08c72d9e3bd98252b13 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _ASM_WAR_H
 #define _ASM_WAR_H
 
-#include <linux/config.h>
 
 /*
  * Another R4600 erratum.  Due to the lack of errata information the exact
  * On the RM9000 there is a problem which makes the CreateDirtyExclusive
  * cache operation unusable on SMP systems.
  */
-#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_PMC_YOSEMITE)
+#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_PMC_YOSEMITE) || \
+    defined(CONFIG_BASLER_EXCITE)
 #define  RM9000_CDEX_SMP_WAR           1
 #endif
 
  * being fetched may case spurious exceptions.
  */
 #if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \
-    defined(CONFIG_PMC_YOSEMITE)
+    defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_BASLER_EXCITE)
 #define ICACHE_REFILLS_WORKAROUND_WAR  1
 #endif
 
index c3bef50f37a82585a52dbc8b263b3c5bc67cf9ca..eadc0ac47e2448d2c1bef79798f918404278fdc4 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_WBFLUSH_H
 #define _ASM_WBFLUSH_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_CPU_HAS_WB
 
index 403ea97316cf2fbdeecefed72db9c38561ad8965..48bf9b8ab8ff7fe0f22c049712993881d429c79f 100644 (file)
@@ -5,7 +5,6 @@
 #ifndef _ASM_PARISC_ATOMIC_H_
 #define _ASM_PARISC_ATOMIC_H_
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/system.h>
 
index c831665473cb79b2b5d132bf7f174b7daa859763..7d22fa206fc407f04908372f52d6b3685b6c3f99 100644 (file)
@@ -5,7 +5,6 @@
 #ifndef __ARCH_PARISC_CACHE_H
 #define __ARCH_PARISC_CACHE_H
 
-#include <linux/config.h>
 
 /*
  * PA 2.0 processors have 64-byte cachelines; PA 1.1 processors have
index 76b6b7d6046a741cfc103c46496f924f5e365704..0b459cdfbd6ffbe79d1b70781069d83949f1803e 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _PARISC_CACHEFLUSH_H
 #define _PARISC_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/cache.h> /* for flush_user_dcache_range_asm() proto */
 
index 74d4ac6f2151ebfdece63746f6d93fd1e3bde8c3..1e387e1dad3044a99a718c7ca5b86142b4a0b844 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _PARISC_DMA_MAPPING_H
 #define _PARISC_DMA_MAPPING_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/cacheflush.h>
 #include <asm/scatterlist.h>
index 31fd10df43a76a997ae6f8b002388fb1e703fdba..9979c3cb37454a23e53a3d7ce2d300a8bd11a3f7 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <asm/io.h>            /* need byte IO */
 #include <asm/system.h>        
 
index 244f6b8883f4414fe2d7fc8401208e9249a73835..b9eb245b88749f16ea144fac741942041f30dc27 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/pgtable.h>
 
index b0a30e2c9813b7369837a533b3673b7528dfb60c..377ba90c7d0256841568386405399164191569b4 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _ASM_PARISC_IRQ_H
 #define _ASM_PARISC_IRQ_H
 
-#include <linux/config.h>
 #include <linux/cpumask.h>
 #include <asm/types.h>
 
index 6886a0c3fedfde6ed82cce4d2ca988d561c6d244..806aae3c533892b1e65917c4742943ff2692374b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
index c0dd461fb8f10f2c5b52aa417d4bf7421407bb13..0695bc958d564c9702b5c03bf95814597b636220 100644 (file)
@@ -10,7 +10,6 @@
 
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 
 #if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
 # define PAGE_SHIFT    12      /* 4k */
index f4694d452dd64f0b08abf1247350d5744c419c3b..07cb9b93cfe25e30bf449f47ac2275fdf6ac9781 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASMPARISC_PARAM_H
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 # ifdef CONFIG_PA20
 #  define HZ           1000            /* Faster machines */
 # else
index 77bbafb7f73e2fb15b87a5a179b461e451054d7c..8b631f47eb257b90a8a472bd8ed1cbf290d07631 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_PARISC_PCI_H
 #define __ASM_PARISC_PCI_H
 
-#include <linux/config.h>
 #include <asm/scatterlist.h>
 
 
index 0a3face6c480b87ce97660fa8bde6c87bd6469d1..08364f957e7a8811e50ed54f27ed5550e38395ff 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _PARISC_PDC_H
 #define _PARISC_PDC_H
 
-#include <linux/config.h>
 
 /*
  *     PDC return values ...
index aec089eb8b85e6e49f8d30db30c260f56eb57eb9..b6bcc672ba8064610bf0286f9cf34988774c44e6 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <asm/fixmap.h>
 
 #ifndef __ASSEMBLY__
index 89f2f1c16c126de8443868e2a71d927e568b3110..ca49dc91f4fca86bff592f5336ab4265a80ca497 100644 (file)
@@ -9,7 +9,6 @@
 #define __ASM_PARISC_PROCESSOR_H
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/spinlock_types.h>
 
index 4334d6ca2add20c59ed5b89b523b70000e40b546..5a3e23c9ce639591549febc256f390363553fbcf 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef _PARISC_PSW_H
 
-#include <linux/config.h>
 
 #define        PSW_I   0x00000001
 #define        PSW_D   0x00000002
index dbdbd2e9fdf9304e658a6ea61a56cdf8c6688e67..d4c0e26afcd1a88fa9bfdaa2fccefe227c92f5ff 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_SMP)
 
index a5a973c0c07f55f272d4fccd7c6587f516afff84..863876134b2ca9cce106096cfff6551689403c79 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __PARISC_SYSTEM_H
 #define __PARISC_SYSTEM_H
 
-#include <linux/config.h>
 #include <asm/psw.h>
 
 /* The program status word as bitfields.  */
index 825994a90e2db1f42f80b6ce53f11fae9c51cc11..f662e837dea14a1a0533e59b368daa5ef5406032 100644 (file)
@@ -3,7 +3,6 @@
 
 /* TLB flushing routines.... */
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/mmu_context.h>
 
index 0e1a30be2e302649116f3ab2f13bd2342c541719..12b867238a4751438fc76b3ac37132fd37f5f938 100644 (file)
 #define HPUX_GATEWAY_ADDR       0xC0000004
 #define LINUX_GATEWAY_ADDR      0x100
 
+#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 #define SYS_ify(syscall_name)   __NR_##syscall_name
@@ -934,7 +935,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)       \
     return K_INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5);    \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
@@ -956,7 +956,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)       \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 /* mmap & mmap2 take 6 arguments */
 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
@@ -1056,4 +1055,5 @@ asmlinkage long sys_rt_sigaction(int sig,
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_PARISC_UNISTD_H_ */
index c5c3259e0f86f3d147f9daf50719ea5e6311162c..4aa220718b19a09b00cd137ca384bc4a7fa9f292 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_POWERPC_ABS_ADDR_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * c 2001 PPC 64 Team, IBM Corp
index 6379c2df5c40ff51830e32ecbffd55a949bd0b7a..642be62cf393cd468b61b04e5adb4d87f23f7c07 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /* bytes per L1 cache line */
 #if defined(CONFIG_8xx) || defined(CONFIG_403GCX)
index 9fcf0162d859e3e5ec7ae95649850c305785ee04..f6265c2a0dd28f0b461f67def4621e7a4aa6f0ac 100644 (file)
@@ -329,7 +329,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
 #define CPU_FTRS_CELL  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
-           CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO)
+           CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE)
 #define CPU_FTRS_COMPATIBLE    (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
 #endif
index 2ac63f56959270e49cd3169b8a9c0067854cb603..2ab9baf78bb4e40514bf317296903097ba110d47 100644 (file)
@@ -8,7 +8,6 @@
 #define _ASM_DMA_MAPPING_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/cache.h>
 /* need struct page definitions */
index 4bb57fe370972cf5c77893bbca5f9de710d7ead8..7a4374bdbef48fa482e55682e92e3e8cc74fdfa0 100644 (file)
@@ -22,7 +22,6 @@
  * with a grain of salt.
  */
 
-#include <linux/config.h>
 #include <asm/io.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
index 868c7139dbfff8db6d6730db3900e0ccce6add4d..e9c86b1eedab50c309f03ea7eedef1e0c99f890d 100644 (file)
@@ -21,7 +21,6 @@
 #define _PPC64_EEH_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/string.h>
index 94d228f9c6ac0a799e2b431f6464b5e124c1258e..99c18b71aa820a4648e9472914d93dc2dbaa076d 100644 (file)
@@ -3,14 +3,14 @@
 
 #ifdef __KERNEL__
 #include <linux/sched.h>       /* for task_struct */
+#include <asm/page.h>
+#include <asm/string.h>
 #endif
 
 #include <asm/types.h>
 #include <asm/ptrace.h>
 #include <asm/cputable.h>
 #include <asm/auxvec.h>
-#include <asm/page.h>
-#include <asm/string.h>
 
 /* PowerPC relocations defined by the ABIs */
 #define R_PPC_NONE             0
@@ -129,7 +129,7 @@ typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG];
   /* 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
+# define elf_addr_t __u32
 #endif /* ELF_ARCH */
 
 /* Floating point registers */
@@ -161,6 +161,7 @@ typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG];
 typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32];
 #endif
 
+#ifdef __KERNEL__
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
@@ -176,8 +177,6 @@ typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32];
 
 #define ELF_ET_DYN_BASE         (0x08000000)
 
-#ifdef __KERNEL__
-
 /* Common routine for both 32-bit and 64-bit processes */
 static inline void ppc_elf_core_copy_regs(elf_gregset_t elf_regs,
                                            struct pt_regs *regs)
index 608164c39efbc1cd00f34923e292357bed5f9a4d..7e2d169ee8569b74ceccfdfe78e442ef253266c3 100644 (file)
@@ -11,7 +11,6 @@
 #define __ASM_POWERPC_FLOPPY_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/machdep.h>
 
 #define fd_inb(port)           inb_p(port)
index 26b89d859c56e24245a72cdad5e314a1612f5ef5..ce0f7db63c1673a1435d93e7906a27bb9cb947cd 100644 (file)
@@ -6,7 +6,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
index da5f640480cf3eb89a064e42bcba728c6ec6e856..b09b42af6a1ef59b1977e0784690721afc5e9b3d 100644 (file)
@@ -22,7 +22,6 @@
 #endif
 
 #ifndef  __powerpc64__
-#include <linux/config.h>
 #include <linux/hdreg.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
index 18ca29e9105a5d92f1e302d49f411f1f83229159..2acf7b29ef068e9a420facebbeebc2a9a8eeb940 100644 (file)
@@ -22,7 +22,6 @@
 #define _ASM_IOMMU_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/types.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
index 7bc6d73b2823c5032852d3b1ae57b8db569795e8..1e9f25330307d67cbe4038273addab554f8cdb5b 100644 (file)
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/threads.h>
 
 #include <asm/types.h>
index 496aa852b6170f8738442ce7f9b699bef07c1883..f29009bd63c98009236fec24ab66eaa072d2abf5 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_POWERPC_ISERIES_ISERIES_IO_H
 #define _ASM_POWERPC_ISERIES_ISERIES_IO_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PPC_ISERIES
 #include <linux/types.h>
index 0f9254c18914d6c6afad891d62dc87781cbe3f85..3e7d37aa4a6d7d9b398b53af14ea4780da92debb 100644 (file)
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
index 88d70bae7769629c8d31a34c54aec9fe6b00ab9e..d484ca94cb7c9b9a2c06c6627818db2ca6696022 100644 (file)
@@ -8,7 +8,6 @@
 #define _ASM_MMZONE_H_
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * generic non-linear memory support:
index 706325f99a84d07b18163d07b90b68a930afbb2b..3c6f644d49b4f8e097f37179d771f624d9f5f8a4 100644 (file)
@@ -16,7 +16,6 @@
 #define _ASM_POWERPC_PACA_H
 #ifdef __KERNEL__
 
-#include       <linux/config.h>
 #include       <asm/types.h>
 #include       <asm/lppaca.h>
 #include       <asm/mmu.h>
index 2fbecebe1c92a4c6e8785cf889dc0da7e40fcb53..f0469b9613590c7f6524ce8bf79f837d3fc3f5cd 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <asm/asm-compat.h>
 
 /*
index e9f1f4627e6bab35cd34910e3bf4bb05763b85ff..964e312a1ffcbe487c31573ad0d4462bbf2819b6 100644 (file)
@@ -12,7 +12,6 @@
  */
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <asm/processor.h>             /* For TASK_SIZE */
 #include <asm/mmu.h>
index dd1c0a913d5f6324712d676c827372a40e880553..a940cfe040da1a4d38b253b09c948bdbdac401a9 100644 (file)
@@ -5,7 +5,6 @@
 #define _ASM_POWERPC_PPC_ASM_H
 
 #include <linux/stringify.h>
-#include <linux/config.h>
 #include <asm/asm-compat.h>
 
 #ifndef __ASSEMBLY__
index 97ef1cd71a4da2ed226b58e9fd121d7970f52a19..f4e2ca6fd53f31dc77addb2ce41223bc1f325400 100644 (file)
@@ -15,7 +15,6 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <asm/atomic.h>
index 4a716f707cf670036ac8ec1903f37ca91c95c07d..068f119aa298fd7fb8d5f35f4e8ab8a2b3b34a0a 100644 (file)
@@ -17,7 +17,6 @@
 #define _ASM_POWERPC_SMP_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/kernel.h>
index 2dc93632f210c94d2fdd18b47dc44ea6d0014bd1..51e65fc46a038cd80bfb86f92a6aa0b0cd75c6c0 100644 (file)
@@ -5,7 +5,6 @@
  * Definitions for talking to the SMU chip in newer G5 PowerMacs
  */
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/list.h>
 #endif
 #include <linux/types.h>
index 7cfcff3ef027f47502b5818ce57d59a597155ec1..95713f397357d62d63d6163a8ffb677f3b1f3fe9 100644 (file)
@@ -24,7 +24,6 @@
 #define _SPU_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/kref.h>
 #include <linux/workqueue.h>
 
index ebf6055481dcb0f4547ecd5c9f1d6e7c1afea896..6d533b07aaf52daa3e1911df34fffcc6bf788d4d 100644 (file)
@@ -153,6 +153,7 @@ struct termios {
 #define HUPCL  00040000
 
 #define CLOCAL 00100000
+#define CMSPAR   010000000000          /* mark or space (stick) parity */
 #define CRTSCTS          020000000000          /* flow control */
 
 /* c_lflag bits */
index 88b553c6b26c9b461660b8de1f31c98c87c86a68..d339e2e88b1144f73a95dbf67f8440e7b671916e 100644 (file)
@@ -21,7 +21,6 @@
 #define THREAD_SIZE            (1 << THREAD_SHIFT)
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/cache.h>
 #include <asm/processor.h>
 #include <asm/page.h>
index 912118db13ae7d183a41a46b2236edc4d1bc08a2..4463148c659f9672b4b4cadf48d79a037a462dcc 100644 (file)
@@ -14,7 +14,6 @@
 #define __POWERPC_TIME_H
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/percpu.h>
 
index c02d15aced9106b3d3a85517837759ccb883e80b..3b9a8e78680646f3ee64f2582b0c14b26d0a08c9 100644 (file)
@@ -7,7 +7,6 @@
  * PowerPC architecture timex specifications
  */
 
-#include <linux/config.h>
 #include <asm/cputable.h>
 
 #define CLOCK_TICK_RATE        1024000 /* Underlying HZ */
index 601a53cf96d5b177d9077864ad8815eb207f71c7..4e2a834683fbcae87e39b4bbdaaefa3b7bbc6b18 100644 (file)
@@ -13,7 +13,6 @@
 #define _ASM_POWERPC_TLB_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #ifndef __powerpc64__
 #include <asm/pgtable.h>
 #endif
index a2998eee37bb4e9363e662cad602e600a0e5f38e..93c7d0c7230f5db796ee9115f84f84270ae680a6 100644 (file)
@@ -17,7 +17,6 @@
  */
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 struct mm_struct;
 
index 87362a05542b6ba5036d8631b5f20aa481651980..19c575f391644ea6766c275f6ef34f3553554cbe 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASM_POWERPC_TOPOLOGY_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 struct sys_device;
 struct device_node;
index baabba96e31342ecf9be2af2a9d7c335fe4630be..d6fb56b80453c44d5ad922d25cfc25060655748c 100644 (file)
@@ -64,7 +64,6 @@ typedef struct {
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef signed char s8;
 typedef unsigned char u8;
index edde2462bf52d59709e4c1cf6ffd1e61205707a6..eb66eae6616fb3026dbf38f966afff686664601c 100644 (file)
 #define __NR_get_robust_list   299
 #define __NR_set_robust_list   300
 
+#ifdef __KERNEL__
+
 #define __NR_syscalls          301
 
-#ifdef __KERNEL__
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
-#endif
 
 #ifndef __ASSEMBLY__
 
@@ -441,9 +441,7 @@ 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); \
 }
 
-#ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
 #include <linux/linkage.h>
@@ -499,8 +497,8 @@ extern int execve(const char *file, char **argv, char **envp);
 #define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall")
 #endif
 
-#endif         /* __KERNEL__ */
 
 #endif         /* __ASSEMBLY__ */
+#endif         /* __KERNEL__ */
 
 #endif /* _ASM_PPC_UNISTD_H_ */
index f8d350aabf1a019f49ca194ff19f9f6b211d853c..eadaf2f3d03255c0eefe558138a943894cecdaf1 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <asm/io.h>
 
-#include <linux/config.h>
 
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE)
 
index 0544ece51761f9236ff3b24cfaa46c0e653d23e9..be14c59846f96249e85d8e984653b84f1d6c3365 100644 (file)
@@ -15,7 +15,6 @@
 #define _ASM_POWERPC_VIO_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/device.h>
index 8c98945e7dc1f9337b8b5ea239b0a63fa05e47ff..90fd1274d727a2e757f3684ea49f4d91261d64d0 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef __ASMPPC_AMIGAHW_H
 #define __ASMPPC_AMIGAHW_H
 
-#include <linux/config.h>
 #include <asm-m68k/amigahw.h>
 
 #undef CHIP_PHYSADDR
index 93d955c70d652b06d6b1da3dfd21ea995be52fc9..2ace4a74f26327cba677492f2f074a9524383b10 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _PPC_BOOTINFO_H
 #define _PPC_BOOTINFO_H
 
-#include <linux/config.h>
 #include <asm/page.h>
 
 #if defined(CONFIG_APUS) && !defined(__BOOTER__)
index 31f362966a58856295b44838b91ed7633cdc2133..3247bea5fc2b18d377953351eaedd368bb95a6cd 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef __CPM_8XX__
 #define __CPM_8XX__
 
-#include <linux/config.h>
 #include <asm/8xx_immap.h>
 #include <asm/ptrace.h>
 
index bf6efa0417ab70a52f431e9b1df250e2afd87893..c9c5d539cfdb65ece7b3bdf57512d33733d5f923 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_IBM403_H__
 #define __ASM_IBM403_H__
 
-#include <linux/config.h>
 
 #if defined(CONFIG_403GCX)
 
index 3acc382cc83f3fc92077016ece9cd0a6b5815f34..7818b54b6e37de0223a59274c7c4e015128cc8d5 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef __ASM_IBM44x_H__
 #define __ASM_IBM44x_H__
 
-#include <linux/config.h>
 
 #ifndef NR_BOARD_IRQS
 #define NR_BOARD_IRQS 0
index 38f99710752b1f041b29a3a40acea8ecc639d529..cf62b69cb69a12b42e18dcaace44cb82287f28d3 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef __ASM_IBM4XX_H__
 #define __ASM_IBM4XX_H__
 
-#include <linux/config.h>
 #include <asm/types.h>
 
 #ifdef CONFIG_40x
index b919d8fb7d98b8771a6037c346630e0c86be7191..89c6f1bc3aaba0eb27511d536eb0ffe5985001e7 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef _PPC_IO_H
 #define _PPC_IO_H
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/types.h>
 
index e1a0a7b213d7bdbc313cf043572e1983f0304b3a..da7746738aee723ad331a7bb20b796a337894307 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef _PPC_MACHDEP_H
 #define _PPC_MACHDEP_H
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kexec.h>
 
index 9205db404c7a27fb9d8b7be620a083323a928588..0a70b05b3afb4422d7e4e609fcf9d48152a6b3e1 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _PPC_MMU_H_
 #define _PPC_MMU_H_
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
index 4f152cca13c1985a02fc0c73d4a02808a2ea228d..94f2bf71310d09f66c8b3cfbee7b017a188fb468 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef __PPC_MMU_CONTEXT_H
 #define __PPC_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <asm/atomic.h>
 #include <asm/bitops.h>
 #include <asm/mmu.h>
index 6ba69a86b9ddf2cc2e488f01a0c57cad44e80c8f..4b93481e7679944d519e6862697c38f8c4fd906a 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef __ASM_PPC_MPC8260_H__
 #define __ASM_PPC_MPC8260_H__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_8260
 
index 3c23fc43bfbc4781afeea22ac1b562090c8e1916..02ed2c3257149fe53badc6c58477377457fbe2d8 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef __ASM_MPC83xx_H__
 #define __ASM_MPC83xx_H__
 
-#include <linux/config.h>
 #include <asm/mmu.h>
 
 #ifdef CONFIG_83xx
index f47002a60edf59dd293906233df56fc386c67679..c25bdd9debf8d9b10e21cd32a1b37a9a6ce00663 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef __ASM_MPC85xx_H__
 #define __ASM_MPC85xx_H__
 
-#include <linux/config.h>
 #include <asm/mmu.h>
 
 #ifdef CONFIG_85xx
index 3515a7fa6c8939cc11515b6ff3807e35e576da9f..adcce33f20ae7a6d3248510b3b5722f18b526c55 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef __CONFIG_8xx_DEFS
 #define __CONFIG_8xx_DEFS
 
-#include <linux/config.h>
 
 #ifdef CONFIG_8xx
 
index 4f2405b8361206550792e46b256df558c7130b69..663edbee3e910206f369383c8d339e9219a94dff 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/config.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
index 983116f59d909f0e802c6f19c30a5d5a9a974e82..3be5d760ffcd9c5eaa1a81ce0b6449cf2f68bfa7 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/config.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/device.h>
 
index ec2f46629ca28ea177090589d972ed35e07cf95c..a4fe962d9f7301a242393160323945d06bf38524 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _PPC_KERNEL_OPEN_PIC_H
 #define _PPC_KERNEL_OPEN_PIC_H
 
-#include <linux/config.h>
 #include <linux/irq.h>
 
 #define OPENPIC_SIZE   0x40000
index 0fb68a0b0181c311eae08877d29809980639a76e..0b19af82507ff25b8793694c79fef18632185cab 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _PPC_PAGE_H
 #define _PPC_PAGE_H
 
-#include <linux/config.h>
 #include <asm/asm-compat.h>
 
 /* PAGE_SHIFT determines the page size */
@@ -15,7 +14,6 @@
 #define PAGE_MASK      (~((1 << PAGE_SHIFT) - 1))
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 
 /* This must match what is in arch/ppc/Makefile */
 #define PAGE_OFFSET    CONFIG_KERNEL_START
index 8f994f9f8857e70c2a6530247a668d12ca8f8f19..81a2d0fdaf00fecc76ad7120f3d8e2002ad789fd 100644 (file)
@@ -9,7 +9,6 @@
  * anyone using any of those on a PPC platform.  -- paulus
  */
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
index bdefd1c4a5581b5a4317587bd2377e075ea7ed81..44d88a98e87ca8a57d0f6a90cae48bd93c193822 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef _PPC_PGALLOC_H
 #define _PPC_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 
 extern void __bad_pte(pmd_t *pmd);
index 570b355162fae0bba5247e84c01407fe55e4ab88..9cb83679836c33f45cfc2c6707c3f8dae87aa5ba 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 #include <linux/sched.h>
index 46a086fff81629e95d3efad1bc585ed346119702..935d1e05366b4cb7cc89e4c40d657dfec34423e7 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef __ASMPPC_PPC4xx_DMA_H
 #define __ASMPPC_PPC4xx_DMA_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/mmu.h>
 #include <asm/ibm4xx.h>
index c16c7f81cfd8d593521d81de28bf95610a76d8d7..e44261206f8bc1bdb07b37e55222c8a2a9dd9ab9 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef        __PPC4XX_PIC_H__
 #define        __PPC4XX_PIC_H__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/irq.h>
 
index b74af54615643174037673475ab3aa67ee5fb549..8a59f8871f32173449216a2b2aa233d5dfc2d071 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef __ASM_SERIAL_H__
 #define __ASM_SERIAL_H__
 
-#include <linux/config.h>
 
 #if defined(CONFIG_EV64260)
 #include <platforms/ev64260.h>
index 30e9268a888c4664f441586630dc1ecf682102cd..0b7fa89589df5db61bf429c2c528858eff29683c 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _PPC_SMP_H
 #define _PPC_SMP_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/bitops.h>
 #include <linux/errno.h>
index c86112323c9f097e3297d7dc74a51efeae76b4cb..f7eadf6ac8063ddb6604a9cd09a5aba57abc1c2f 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef __ASM_TIME_H__
 #define __ASM_TIME_H__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/rtc.h>
 #include <linux/threads.h>
index ca092ffb7a95c36cd8e531f0d66857c05d495d40..4d2b126ba15961a6b7f7ee8b83d0e751d02b9a8c 100644 (file)
@@ -12,7 +12,6 @@
  *    Copyright (C) 1992, Linus Torvalds
  *
  */
-#include <linux/config.h>
 #include <linux/compiler.h>
 
 /*
index dae1dd4fb937b34055c8fe46da90b7c23f21a4c6..2d09950a9c11207d43daaa593860256bc52438b1 100644 (file)
@@ -47,7 +47,7 @@ struct cmbdata {
 /* reset channel measurement block */
 #define BIODASDRESETCMB                _IO(DASD_IOCTL_LETTER,34)
 /* read channel measurement data */
-#define BIODASDREADCMB         _IOWR(DASD_IOCTL_LETTER,32,u64)
+#define BIODASDREADCMB         _IOWR(DASD_IOCTL_LETTER,32,__u64)
 /* read channel measurement data */
 #define BIODASDREADALLCMB      _IOWR(DASD_IOCTL_LETTER,33,struct cmbdata)
 
index 23450ed4b571907e6c66609fa536c19a9f386b63..7f1ef99fd1e18b12f05ea1168bc01fc387142b37 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef DEBUG_H
 #define DEBUG_H
 
-#include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/string.h>
 
index 40c25e166a9b91ffcf2a6fbd549c1892c303405b..1802775568b9904a6c8b5eddd811b908d3f4f0a3 100644 (file)
 #define __futex_atomic_fixup \
                     ".section __ex_table,\"a\"\n"                      \
                     "   .align 4\n"                                    \
-                    "   .long  0b,2b,1b,2b\n"                          \
+                    "   .long  0b,4b,2b,4b,3b,4b\n"                    \
                     ".previous"
 #else /* __s390x__ */
 #define __futex_atomic_fixup \
                     ".section __ex_table,\"a\"\n"                      \
                     "   .align 8\n"                                    \
-                    "   .quad  0b,2b,1b,2b\n"                          \
+                    "   .quad  0b,4b,2b,4b,3b,4b\n"                    \
                     ".previous"
 #endif /* __s390x__ */
 
 #define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg)     \
-       asm volatile("   l   %1,0(%6)\n"                                \
-                    "0: " insn                                         \
-                    "   cs  %1,%2,0(%6)\n"                             \
-                    "1: jl  0b\n"                                      \
+       asm volatile("   sacf 256\n"                                    \
+                    "0: l   %1,0(%6)\n"                                \
+                    "1: " insn                                         \
+                    "2: cs  %1,%2,0(%6)\n"                             \
+                    "3: jl  1b\n"                                      \
                     "   lhi %0,0\n"                                    \
-                    "2:\n"                                             \
+                    "4: sacf 0\n"                                      \
                     __futex_atomic_fixup                               \
                     : "=d" (ret), "=&d" (oldval), "=&d" (newval),      \
                       "=m" (*uaddr)                                    \
index 6792c559a124022c2e4d71a3fb1ed0428d770771..e84b7ef54aac614d968883ca8c8c459b8f67c8ed 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/sched.h>
 #include <linux/cache.h>
index 8038858b86bbf9dba00980a8ef1fdf39f2ede74a..e82c10efe65aee289c94fe59f761ce8c4c49acbb 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _S390_IDALS_H
 #define _S390_IDALS_H
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/types.h>
index cf8189009c30e509a2e055023c3e58fc9014ab3d..86745a1b29bb614fcef946aea28b7d938c8db38b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_LOCAL_H
 #define _ASM_LOCAL_H
 
-#include <linux/config.h>
 #include <linux/percpu.h>
 #include <asm/atomic.h>
 
index db0606c1abd4fbf56c938905790f8785a904c364..596c8b1721049a499081bfc8a53347a96e452e9c 100644 (file)
@@ -98,8 +98,8 @@
 #define __LC_KERNEL_ASCE               0xD58
 #define __LC_USER_ASCE                 0xD60
 #define __LC_PANIC_STACK                0xD68
-#define __LC_CPUID                      0xD90
-#define __LC_CPUADDR                    0xD98
+#define __LC_CPUID                     0xD80
+#define __LC_CPUADDR                   0xD88
 #define __LC_IPLDEV                     0xDB8
 #define __LC_JIFFY_TIMER               0xDC0
 #define __LC_CURRENT                   0xDD8
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <asm/processor.h>
 #include <linux/types.h>
 #include <asm/sigp.h>
index 3b1138ac7e7943589a998bd5c9c280aada267f4f..b2628dc5c49075d0841c9b440c2b8a8288f4cd6e 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _S390_PAGE_H
 #define _S390_PAGE_H
 
-#include <asm/setup.h>
 #include <asm/types.h>
 
 /* PAGE_SHIFT determines the page size */
@@ -20,6 +19,7 @@
 #define PAGE_DEFAULT_KEY       (PAGE_DEFAULT_ACC << 4)
 
 #ifdef __KERNEL__
+#include <asm/setup.h>
 #ifndef __ASSEMBLY__
 
 #ifndef __s390x__
@@ -189,9 +189,9 @@ page_get_storage_key(unsigned long addr)
 #define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
                                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#endif /* __KERNEL__ */
-
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+#endif /* __KERNEL__ */
+
 #endif /* _S390_PAGE_H */
index e28aaf28e4a8d8cfbed25b9bc4665fbb5bb833d4..3002fda89d33272e6b7f4f2c9f24e7091efa3f90 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _S390_PGALLOC_H
 #define _S390_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/gfp.h>
 #include <linux/mm.h>
index 61788de3c0c30d6639f807e3b4d82ff6370115b2..b94c98856e127f5656f01eea303a484e4285fb6c 100644 (file)
@@ -76,24 +76,36 @@ typedef struct {
 } __kernel_fsid_t;
 
 
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-
-#ifndef _S390_BITOPS_H
-#include <asm/bitops.h>
-#endif
-
-#undef  __FD_SET
-#define __FD_SET(fd,fdsetp)  set_bit((fd),(fdsetp)->fds_bits)
-
-#undef  __FD_CLR
-#define __FD_CLR(fd,fdsetp)  clear_bit((fd),(fdsetp)->fds_bits)
-
-#undef  __FD_ISSET
-#define __FD_ISSET(fd,fdsetp)  test_bit((fd),(fdsetp)->fds_bits)
+#ifdef __KERNEL__
+
+#undef __FD_SET
+static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+       unsigned long _tmp = fd / __NFDBITS;
+       unsigned long _rem = fd % __NFDBITS;
+       fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+       unsigned long _tmp = fd / __NFDBITS;
+       unsigned long _rem = fd % __NFDBITS;
+       fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static inline int __FD_ISSET(unsigned long fd, const __kernel_fd_set *fdsetp)
+{
+       unsigned long _tmp = fd / __NFDBITS;
+       unsigned long _rem = fd % __NFDBITS;
+       return (fdsetp->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
 
 #undef  __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset ((fdsetp), 0, sizeof(*(fd_set *)(fdsetp))))
+#define __FD_ZERO(fdsetp) \
+       ((void) memset ((__ptr_t) (fdsetp), 0, sizeof (__kernel_fd_set)))
 
-#endif     /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)*/
+#endif     /* __KERNEL__ */
 
 #endif
index a949cc077cc72fcfc5b371e4acd54c7bde23621b..4d75d77b0f9960cad73cedb09adaae4e85a6c5c1 100644 (file)
 #define PTRACE_OLDSETOPTIONS         21
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/types.h>
-#include <asm/setup.h>
-#include <asm/page.h>
 
 typedef union
 {
@@ -301,6 +298,9 @@ typedef struct
 } s390_regs;
 
 #ifdef __KERNEL__
+#include <asm/setup.h>
+#include <asm/page.h>
+
 /*
  * The pt_regs struct defines the way the registers are stored on
  * the stack during a system call.
index 3c79b5384f44b7c49441302c357aa78fd09dcdbb..de69dfa46fbba0baee8e305a61639adb1614d167 100644 (file)
@@ -25,7 +25,6 @@
 #ifndef _SFP_MACHINE_H
 #define _SFP_MACHINE_H
    
-#include <linux/config.h>
 
 #define _FP_W_TYPE_SIZE                32
 #define _FP_W_TYPE             unsigned long
index 444dae5912e6b544d9d31c0c45b0fcc53cefe473..657646054c5ede693b2cf0400a69383e11ec0a0e 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/bitops.h>
index 6a89dbb03c1e363e86870718e2633fdbc112a6d3..71a0732cd5180f89b59a2a53ecef653416783b75 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __ASM_SYSTEM_H
 #define __ASM_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/types.h>
 #include <asm/ptrace.h>
index 1bb73b0e61fad19cb65cc84128a5aef59c504089..73cd85bebfb2ade78de40e577452ff86054bbb14 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _S390_TLBFLUSH_H
 #define _S390_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
 
index 5738ad63537c53228dcdc4cf70b2a72c54f32c99..ae2951cc83aca1cc634d4b6ab7d56694779da41d 100644 (file)
@@ -58,7 +58,6 @@ typedef __signed__ long saddr_t;
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef signed char s8;
 typedef unsigned char u8;
index 41c2792ff6b04cd9d0be3d98c774549113ba2552..e21443d3ea1df4532562d613571f611c1b464a63 100644 (file)
 
 #endif
 
+#ifdef __KERNEL__
+
 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
 
 #define __syscall_return(type, res)                         \
@@ -546,7 +548,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4,    \
        __syscall_return(type,__res);                        \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
@@ -573,11 +574,9 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4,    \
 #   define __ARCH_WANT_COMPAT_SYS_TIME
 #   define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 # endif
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <asm/ptrace.h>
@@ -625,7 +624,7 @@ asmlinkage long sys_rt_sigaction(int sig,
                                struct sigaction __user *oact,
                                size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -635,4 +634,5 @@ asmlinkage long sys_rt_sigaction(int sig,
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_S390_UNISTD_H_ */
index d1de5b7ebb0b45aeb9bd83d29ed59f04ee675f3b..3a5267d90d29921e9b3e6b60999ab928fa1c087a 100644 (file)
@@ -177,27 +177,27 @@ struct vtoc_format7_label
 } __attribute__ ((packed));
 
 struct vtoc_cms_label {
-       u8 label_id[4];         /* Label identifier */
-       u8 vol_id[6];           /* Volid */
-       u16 version_id;         /* Version identifier */
-       u32 block_size;         /* Disk block size */
-       u32 origin_ptr;         /* Disk origin pointer */
-       u32 usable_count;       /* Number of usable cylinders/blocks */
-       u32 formatted_count;    /* Maximum number of formatted cylinders/
+       __u8 label_id[4];               /* Label identifier */
+       __u8 vol_id[6];         /* Volid */
+       __u16 version_id;               /* Version identifier */
+       __u32 block_size;               /* Disk block size */
+       __u32 origin_ptr;               /* Disk origin pointer */
+       __u32 usable_count;     /* Number of usable cylinders/blocks */
+       __u32 formatted_count;  /* Maximum number of formatted cylinders/
                                 * blocks */
-       u32 block_count;        /* Disk size in CMS blocks */
-       u32 used_count;         /* Number of CMS blocks in use */
-       u32 fst_size;           /* File Status Table (FST) size */
-       u32 fst_count;          /* Number of FSTs per CMS block */
-       u8 format_date[6];      /* Disk FORMAT date */
-       u8 reserved1[2];
-       u32 disk_offset;        /* Disk offset when reserved*/
-       u32 map_block;          /* Allocation Map Block with next hole */
-       u32 hblk_disp;          /* Displacement into HBLK data of next hole */
-       u32 user_disp;          /* Displacement into user part of Allocation
+       __u32 block_count;      /* Disk size in CMS blocks */
+       __u32 used_count;               /* Number of CMS blocks in use */
+       __u32 fst_size;         /* File Status Table (FST) size */
+       __u32 fst_count;                /* Number of FSTs per CMS block */
+       __u8 format_date[6];    /* Disk FORMAT date */
+       __u8 reserved1[2];
+       __u32 disk_offset;      /* Disk offset when reserved*/
+       __u32 map_block;                /* Allocation Map Block with next hole */
+       __u32 hblk_disp;                /* Displacement into HBLK data of next hole */
+       __u32 user_disp;                /* Displacement into user part of Allocation
                                 * map */
-       u8 reserved2[4];
-       u8 segment_name[8];     /* Name of shared segment */
+       __u8 reserved2[4];
+       __u8 segment_name[8];   /* Name of shared segment */
 } __attribute__ ((packed));
 
 #endif /* _ASM_S390_VTOC_H */
diff --git a/include/asm-s390/z90crypt.h b/include/asm-s390/z90crypt.h
new file mode 100644 (file)
index 0000000..31a2439
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ *  include/asm-s390/z90crypt.h
+ *
+ *  z90crypt 1.3.3 (user-visible header)
+ *
+ *  Copyright (C)  2001, 2005 IBM Corporation
+ *  Author(s): Robert Burroughs
+ *             Eric Rossman (edrossma@us.ibm.com)
+ *
+ *  Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_S390_Z90CRYPT_H
+#define __ASM_S390_Z90CRYPT_H
+#include <linux/ioctl.h>
+
+#define z90crypt_VERSION 1
+#define z90crypt_RELEASE 3     // 2 = PCIXCC, 3 = rewrite for coding standards
+#define z90crypt_VARIANT 3     // 3 = CEX2A support
+
+/**
+ * struct ica_rsa_modexpo
+ *
+ * Requirements:
+ * - outputdatalength is at least as large as inputdatalength.
+ * - All key parts are right justified in their fields, padded on
+ *   the left with zeroes.
+ * - length(b_key) = inputdatalength
+ * - length(n_modulus) = inputdatalength
+ */
+struct ica_rsa_modexpo {
+       char __user *   inputdata;
+       unsigned int    inputdatalength;
+       char __user *   outputdata;
+       unsigned int    outputdatalength;
+       char __user *   b_key;
+       char __user *   n_modulus;
+};
+
+/**
+ * struct ica_rsa_modexpo_crt
+ *
+ * Requirements:
+ * - inputdatalength is even.
+ * - outputdatalength is at least as large as inputdatalength.
+ * - All key parts are right justified in their fields, padded on
+ *   the left with zeroes.
+ * - length(bp_key)    = inputdatalength/2 + 8
+ * - length(bq_key)    = inputdatalength/2
+ * - length(np_key)    = inputdatalength/2 + 8
+ * - length(nq_key)    = inputdatalength/2
+ * - length(u_mult_inv) = inputdatalength/2 + 8
+ */
+struct ica_rsa_modexpo_crt {
+       char __user *   inputdata;
+       unsigned int    inputdatalength;
+       char __user *   outputdata;
+       unsigned int    outputdatalength;
+       char __user *   bp_key;
+       char __user *   bq_key;
+       char __user *   np_prime;
+       char __user *   nq_prime;
+       char __user *   u_mult_inv;
+};
+
+#define Z90_IOCTL_MAGIC 'z'  // NOTE:  Need to allocate from linux folks
+
+/**
+ * Interface notes:
+ *
+ * The ioctl()s which are implemented (along with relevant details)
+ * are:
+ *
+ *   ICARSAMODEXPO
+ *     Perform an RSA operation using a Modulus-Exponent pair
+ *     This takes an ica_rsa_modexpo struct as its arg.
+ *
+ *     NOTE: please refer to the comments preceding this structure
+ *           for the implementation details for the contents of the
+ *           block
+ *
+ *   ICARSACRT
+ *     Perform an RSA operation using a Chinese-Remainder Theorem key
+ *     This takes an ica_rsa_modexpo_crt struct as its arg.
+ *
+ *     NOTE: please refer to the comments preceding this structure
+ *           for the implementation details for the contents of the
+ *           block
+ *
+ *   Z90STAT_TOTALCOUNT
+ *     Return an integer count of all device types together.
+ *
+ *   Z90STAT_PCICACOUNT
+ *     Return an integer count of all PCICAs.
+ *
+ *   Z90STAT_PCICCCOUNT
+ *     Return an integer count of all PCICCs.
+ *
+ *   Z90STAT_PCIXCCMCL2COUNT
+ *     Return an integer count of all MCL2 PCIXCCs.
+ *
+ *   Z90STAT_PCIXCCMCL3COUNT
+ *     Return an integer count of all MCL3 PCIXCCs.
+ *
+ *   Z90STAT_CEX2CCOUNT
+ *     Return an integer count of all CEX2Cs.
+ *
+ *   Z90STAT_CEX2ACOUNT
+ *     Return an integer count of all CEX2As.
+ *
+ *   Z90STAT_REQUESTQ_COUNT
+ *     Return an integer count of the number of entries waiting to be
+ *     sent to a device.
+ *
+ *   Z90STAT_PENDINGQ_COUNT
+ *     Return an integer count of the number of entries sent to a
+ *     device awaiting the reply.
+ *
+ *   Z90STAT_TOTALOPEN_COUNT
+ *     Return an integer count of the number of open file handles.
+ *
+ *   Z90STAT_DOMAIN_INDEX
+ *     Return the integer value of the Cryptographic Domain.
+ *
+ *   Z90STAT_STATUS_MASK
+ *     Return an 64 element array of unsigned chars for the status of
+ *     all devices.
+ *       0x01: PCICA
+ *       0x02: PCICC
+ *       0x03: PCIXCC_MCL2
+ *       0x04: PCIXCC_MCL3
+ *       0x05: CEX2C
+ *       0x06: CEX2A
+ *       0x0d: device is disabled via the proc filesystem
+ *
+ *   Z90STAT_QDEPTH_MASK
+ *     Return an 64 element array of unsigned chars for the queue
+ *     depth of all devices.
+ *
+ *   Z90STAT_PERDEV_REQCNT
+ *     Return an 64 element array of unsigned integers for the number
+ *     of successfully completed requests per device since the device
+ *     was detected and made available.
+ *
+ *   ICAZ90STATUS (deprecated)
+ *     Return some device driver status in a ica_z90_status struct
+ *     This takes an ica_z90_status struct as its arg.
+ *
+ *     NOTE: this ioctl() is deprecated, and has been replaced with
+ *           single ioctl()s for each type of status being requested
+ *
+ *   Z90STAT_PCIXCCCOUNT (deprecated)
+ *     Return an integer count of all PCIXCCs (MCL2 + MCL3).
+ *     This is DEPRECATED now that MCL3 PCIXCCs are treated differently from
+ *     MCL2 PCIXCCs.
+ *
+ *   Z90QUIESCE (not recommended)
+ *     Quiesce the driver.  This is intended to stop all new
+ *     requests from being processed.  Its use is NOT recommended,
+ *     except in circumstances where there is no other way to stop
+ *     callers from accessing the driver.  Its original use was to
+ *     allow the driver to be "drained" of work in preparation for
+ *     a system shutdown.
+ *
+ *     NOTE: once issued, this ban on new work cannot be undone
+ *           except by unloading and reloading the driver.
+ */
+
+/**
+ * Supported ioctl calls
+ */
+#define ICARSAMODEXPO  _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0)
+#define ICARSACRT      _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0)
+
+/* DEPRECATED status calls (bound for removal at some point) */
+#define ICAZ90STATUS   _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status)
+#define Z90STAT_PCIXCCCOUNT    _IOR(Z90_IOCTL_MAGIC, 0x43, int)
+
+/* unrelated to ICA callers */
+#define Z90QUIESCE     _IO(Z90_IOCTL_MAGIC, 0x11)
+
+/* New status calls */
+#define Z90STAT_TOTALCOUNT     _IOR(Z90_IOCTL_MAGIC, 0x40, int)
+#define Z90STAT_PCICACOUNT     _IOR(Z90_IOCTL_MAGIC, 0x41, int)
+#define Z90STAT_PCICCCOUNT     _IOR(Z90_IOCTL_MAGIC, 0x42, int)
+#define Z90STAT_PCIXCCMCL2COUNT        _IOR(Z90_IOCTL_MAGIC, 0x4b, int)
+#define Z90STAT_PCIXCCMCL3COUNT        _IOR(Z90_IOCTL_MAGIC, 0x4c, int)
+#define Z90STAT_CEX2CCOUNT     _IOR(Z90_IOCTL_MAGIC, 0x4d, int)
+#define Z90STAT_CEX2ACOUNT     _IOR(Z90_IOCTL_MAGIC, 0x4e, int)
+#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int)
+#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int)
+#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
+#define Z90STAT_DOMAIN_INDEX   _IOR(Z90_IOCTL_MAGIC, 0x47, int)
+#define Z90STAT_STATUS_MASK    _IOR(Z90_IOCTL_MAGIC, 0x48, char[64])
+#define Z90STAT_QDEPTH_MASK    _IOR(Z90_IOCTL_MAGIC, 0x49, char[64])
+#define Z90STAT_PERDEV_REQCNT  _IOR(Z90_IOCTL_MAGIC, 0x4a, int[64])
+
+#endif /* __ASM_S390_Z90CRYPT_H */
index 70508a360cd669b84ade8a09ab29f570d6dcf8de..1b4fc52a59e86beb62adf210158260c453a01ab5 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH_BUG_H
 #define __ASM_SH_BUG_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_BUG
 /*
index 5ebd0f24299eeb064bb3cd0a772d5164599aba68..fa03b30c4269f6ee60080ba2982c4c986ca8417a 100644 (file)
@@ -9,7 +9,6 @@
  * Copyright (C) 1999 by Kaz Kojima & Niibe Yutaka
  */
 
-#include <linux/config.h>
 #include <linux/in6.h>
 
 /*
index 48f1f42c5d14b49d2d5632e3fb612456b63fada5..124968f9866e9f2cabeb0d78474a3c2dcaf1f2e0 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH_DMA_MAPPING_H
 #define __ASM_SH_DMA_MAPPING_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/scatterlist.h>
 #include <asm/cacheflush.h>
index a118a0d43053fb90350ffc5dea90900a5f5e7ea6..e62a6d0ed932cec3631ee42e1d3e51331d09ae23 100644 (file)
@@ -11,7 +11,6 @@
 #define __ASM_SH_DMA_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/sysdev.h>
index 509224bdba286719155adf1077c71702f8ef680e..412bccaa07e6ee8ffddaf7e7afc0570df0db9f2f 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/page.h>
 #ifdef CONFIG_HIGHMEM
index f2fdf0f760e594b8983f00007f352030818aceae..715ee237fc77bc045f556965321c601a9d5f5c54 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH_HARDIRQ_H
 #define __ASM_SH_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
index c457ca277a42c3d85ebbc3f0daa77ed564affaa1..87f13d24c630ac5bf2a7a973340d90a8c5e2bff4 100644 (file)
@@ -5,7 +5,6 @@
  *     Copyright (C) 2000 YAEGASHI Takeshi
  *     Hitachi HD64461 companion chip support
  */
-#include <linux/config.h>
 
 /* Constants for PCMCIA mappings */
 #define HD64461_PCC_WINDOW     0x01000000
index c672032b72c9af60abca3752f6dec8b5af065517..cfd0e803d2a27e9c5b134821decef2a9f07173a1 100644 (file)
@@ -11,7 +11,6 @@
  * Derived from <asm/hd64461.h> which bore the message:
  * Copyright (C) 2000 YAEGASHI Takeshi
  */
-#include <linux/config.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 711dad4cb48ba322b929db9dc51be586de01352e..9f8e9142dc33b68ff8f737682ff5d8ac16d5ca84 100644 (file)
@@ -14,7 +14,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #define ide_default_io_ctl(base)       (0)
 
index 2c3afe71323da32c2ff45f0f314dd5e2c1465c32..894e64b2d5f0a0f066c50f2fca4a9dc554f172dd 100644 (file)
@@ -23,7 +23,6 @@
  *  inb   by default expands to _inb, but the machine specific code may
  *        define it to __inb if it chooses.
  */
-#include <linux/config.h>
 #include <asm/cache.h>
 #include <asm/system.h>
 #include <asm/addrspace.h>
index 42b8394c04ed6de00474532297b18c1d8ce84fd4..611e67cd062728bf08726717ee3ec96858eaf057 100644 (file)
@@ -11,7 +11,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <asm/machvec.h>
 #include <asm/ptrace.h>                /* for pt_regs */
 
index 1103df0032434b5c428b2adf085caeaeaf24343f..31dcc4fa5f2893d1286b4884b66231c925e37d4e 100644 (file)
@@ -5,7 +5,6 @@
  */
 
 #include <linux/kd.h>
-#include <linux/config.h>
 #include <asm/machvec.h>
 
 #ifdef CONFIG_SH_MPC1211
index 2492ba07148f672a1c2224f51f1608dc91b48462..84d565c696befbaee91e7770721d1ec2a5ed6f8c 100644 (file)
@@ -3,7 +3,6 @@
 
 /* Dummy header just to define km_type. */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
index 550c50a7359e2018345d84735444e1c70586ca0b..550501fa4fede12048f4a288e6880fc9311bab78 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _ASM_SH_MACHVEC_H
 #define _ASM_SH_MACHVEC_H 1
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/time.h>
 
index 9e7de808f7f8770022dd37272461bb3e190a31c8..e397798ebd9493abd107748496d89a0dac46fd40 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __SH_MACHVEC_INIT_H
 #define __SH_MACHVEC_INIT_H
 
-#include <linux/config.h>
 
 /*
  * In a GENERIC kernel, we have lots of these vectors floating about,
index 0a2fdab3e4547fa3b3b1165337611909c2c07e74..e506d1aaa0d00c4637a6b28ddafe56b80065e80b 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _ASM_MPC1211_DMA_H
 #define _ASM_MPC1211_DMA_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>    /* And spinlocks */
 #include <asm/io.h>            /* need byte IO */
 #include <linux/delay.h>
index aa62ae68c55c147e60845e6f2b21edeb16c76a59..fc746c244f8387d5a3a781459704cff2887e2390 100644 (file)
@@ -6,7 +6,6 @@
  *
  */
 
-#include <linux/config.h>
 
 #ifndef __OVERDRIVE_H__
 #define __OVERDRIVE_H__
index 9c89287c3e56c2ad61f016782847897c0cd3eab4..a5559e38744ee2b21c061b3b0d37162f7f2dcd72 100644 (file)
@@ -13,7 +13,6 @@
    [ P4 control   ]            0xE0000000
  */
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT     12
index bb0efb31a8cbeb230a60ab4386b3c4d122b8f099..dcd23a03683dfb6d5897aec520953920706180ea 100644 (file)
@@ -8,7 +8,6 @@
  * Copyright (C) 2002, 2003, 2004 Paul Mundt
  */
 
-#include <linux/config.h>
 #include <asm/pgtable-2level.h>
 
 /*
index f51e232d5cd94f085fef8e3698c67c390b0edca1..8734590d27e8c79c6fb7bb831b1b13c8d923bf5b 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _ASM_SERIAL_H
 #define _ASM_SERIAL_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 
 #ifdef CONFIG_SH_EC3104
index f19a8b3b69a6a24af8519ab3828469ed510eb5d3..f57c4fe9692a97d27557bdeaabc9f33b0791badc 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __ASM_SH_SMP_H
 #define __ASM_SH_SMP_H
 
-#include <linux/config.h>
 #include <linux/bitops.h>
 #include <linux/cpumask.h>
 
index bb0330499bdfef3987cc88d7dd454ead0df3a929..b752e5cbb830f174c18b87b49dc3b1c5df5d2d49 100644 (file)
@@ -6,7 +6,6 @@
  * Copyright (C) 2002 Paul Mundt
  */
 
-#include <linux/config.h>
 
 /*
  *     switch_to() should switch tasks to task nr n, first
index 488552f43b2a17bf866168f8636d91d1fa14d448..3c09dd4ca31cabb7d59e3d56415a2638839eeb1a 100644 (file)
@@ -35,7 +35,6 @@ typedef unsigned long long __u64;
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef __signed__ char s8;
 typedef unsigned char u8;
index 05520cebda1289ae4b490342efe3c56cb8a8e2ad..76b5430cb4580ae09995ce8979a078ceb4ba84e9 100644 (file)
 
 #define NR_syscalls 293
 
+#ifdef __KERNEL__
+
 /* user-visible error numbers are in the range -1 - -124: see <asm-sh/errno.h> */
 
 #define __syscall_return(type, res) \
@@ -420,7 +422,6 @@ __asm__ __volatile__ ("trapa        #0x16" \
 __syscall_return(type,__sc0); \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -443,7 +444,6 @@ __syscall_return(type,__sc0); \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -513,7 +513,7 @@ asmlinkage long sys_rt_sigaction(int sig,
                                struct sigaction __user *oact,
                                size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -525,4 +525,5 @@ asmlinkage long sys_rt_sigaction(int sig,
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* __ASM_SH_UNISTD_H */
index f0cf4be21655a1d64e04c8466ad38ebbf4607495..09ca41972a11ce49d091fdc52d672a4e48e9af81 100644 (file)
@@ -13,7 +13,6 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <asm/cpu/watchdog.h>
 #include <asm/io.h>
 
index 5d659ec28e10116fc85a56b89e7f2c92076d3c6b..81f722efeb6352de0145c68a88e823a0eaccc91c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH64_BUG_H
 #define __ASM_SH64_BUG_H
 
-#include <linux/config.h>
 
 /*
  * Tell the user there is some problem, then force a segfault (in process
index cc9a2e86f5b413d566f81c07781596cc4a7b5b65..a74a49e47922b03e223b8db5a387d93335d1bc7c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH_DMA_MAPPING_H
 #define __ASM_SH_DMA_MAPPING_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
index ad2330e41fd5d8945e09f6feca2e445a53bbf9a8..555fd7a35108a34f11c4b06cb6f91b51d69908ad 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH64_HARDIRQ_H
 #define __ASM_SH64_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
index 852f50afe39cae1910815809c84834ae5b116b01..c9d84d5f772edbe1eb2554135d659fb83598e41e 100644 (file)
@@ -15,7 +15,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /* Without this, the initialisation of PCI IDE cards end up calling
  * ide_init_hwif_ports, which won't work. */
index f815b43df845e84404106082d5b82d5765b4a428..1ca49e29288a04795cb93f1db7e89ee1fe540559 100644 (file)
@@ -12,7 +12,6 @@
  *
  */
 
-#include <linux/config.h>
 
 /*
  * Encoded IRQs are not considered worth to be supported.
index 991cfda4cdf66f2be9c1caa0af5de484f8fd72ac..8c860dab2d0e6554b9b21329dc26c79f79da0249 100644 (file)
@@ -26,7 +26,6 @@
  */
 extern unsigned long mmu_context_cache;
 
-#include <linux/config.h>
 #include <asm/page.h>
 
 
index e4937cdabebd3e839ef503bf929d28a6cd2b5818..34fb34754ae6cd20139256fe1fd3be8c2cccea92 100644 (file)
@@ -17,7 +17,6 @@
  *
  */
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT     12
index d18cc87c1a80435be7737a249384880f8e3e2d3d..f409adb41540fc10c13087a256db6415116cb371 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ASM_SH64_PARAM_H
 #define __ASM_SH64_PARAM_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 # ifdef CONFIG_SH_WDT
index 57af6b3eb271e02116e4dab16f4c6092f78c819e..54c7821893f5fb4b8e70487639013b1f3ee3da2e 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <linux/threads.h>
-#include <linux/config.h>
 
 struct vm_area_struct;
 
index 3002e988180c5a8ee68dae4438df1c45c1be2a80..7606f6e1f01ed9b6c253b245d3b1b599d73ff477 100644 (file)
@@ -14,7 +14,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <asm/registers.h>
 #include <asm/processor.h>
 
index 1f8f394ae37184dd2b2b931f97420d25c4de118d..9a1590fffc1533d86ef6f1c670df551b7874f4d4 100644 (file)
 #define __NR_inotify_add_watch 319
 #define __NR_inotify_rm_watch  320
 
+#ifdef __KERNEL__ 
+
 #define NR_syscalls 321
 
 /* user-visible error numbers are in the range -1 - -125: see <asm-sh64/errno.h> */
@@ -486,7 +488,6 @@ __asm__ __volatile__ ("!dummy       %0 %1 %2 %3 %4 %5 %6"                       \
 __syscall_return(type,__sc0);                                              \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -509,7 +510,6 @@ __syscall_return(type,__sc0);                                                   \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -550,7 +550,7 @@ static inline pid_t wait(int * wait_stat)
 {
        return waitpid(-1,wait_stat,0);
 }
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -562,4 +562,5 @@ static inline pid_t wait(int * wait_stat)
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* __ASM_SH64_UNISTD_H */
index 0d4b65bd252bb4ee2745889fc05e35f1640eabb5..a619a4d97aaee4b69469bc97159196ee60846089 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _SPARC_ASMMACRO_H
 #define _SPARC_ASMMACRO_H
 
-#include <linux/config.h>
 #include <asm/btfixup.h>
 #include <asm/asi.h>
 
index e1033170bd3ad89dcb473f76ebd9f636641cb57a..731fa56e0c374c8413c41c8460f16f4844d7046b 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __ARCH_SPARC_ATOMIC__
 #define __ARCH_SPARC_ATOMIC__
 
-#include <linux/config.h>
 
 typedef struct { volatile int counter; } atomic_t;
 
index e652f89e0effdc95335cd89fdfb6fc361b394a35..a0f939beeea12de43ecafca6c626bc15a89f63d5 100644 (file)
@@ -5,7 +5,6 @@
  */
 
 #include <asm/cpudata.h>
-#include <linux/config.h>
 
 extern unsigned long loops_per_jiffy;
 
index 4901217008c0919f733a954fb2988bef610076e4..fc632f811cd83eefc733df569ebfdf8840909a87 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _SPARC_CACHEFLUSH_H
 #define _SPARC_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>          /* Common for other includes */
 // #include <linux/kernel.h> from pgalloc.h
 // #include <linux/sched.h>  from pgalloc.h
index 7ec8e9f7ad4fa66aa259625f2687b094c53c2a08..48aa70eef9975c356c0cc5c6706869fdfc30934f 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef __SPARC_DELAY_H
 #define __SPARC_DELAY_H
 
-#include <linux/config.h>
 #include <asm/cpudata.h>
 
 static inline void __delay(unsigned long loops)
index d7c3b0f0a90103de71853fbdaa5aedf380197c49..6db83dc93cb7c58fa595d0666c7f44d96c096f84 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_SPARC_DMA_MAPPING_H
 #define _ASM_SPARC_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
index 8ec206aa5f2ecac2191556a6344953398495210b..407b3614468a94a058c929817b65446c6d2a73c7 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _ASM_SPARC_DMA_H
 #define _ASM_SPARC_DMA_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 
index 4a71d7c1eacef14c39e669b1f37f7c0ad252300e..83a3dd15a6edffa502634290d3d3b4d910bf85de 100644 (file)
@@ -6,7 +6,6 @@
  * ELF register definitions..
  */
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 
 #ifdef __KERNEL__
index 9de52b4d2cfb46df46a811f7d4b835d8a717ae29..f18fc0755adf0f9bbb3929f7dc171fcfe01a5a5c 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/page.h>
 #ifdef CONFIG_HIGHMEM
index 2a668c479f680dc535c5ca9366a1138ed0e56357..4f63ed8df55191517f819cacd3ec54f886a19941 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef __SPARC_HARDIRQ_H
 #define __SPARC_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/spinlock.h>
 #include <linux/cache.h>
index 64d810385ea410d9ffb7217ec3e854107684b12e..a6d735a1310e32aa6a31a1dd453cd86fcff34a5e 100644 (file)
@@ -11,7 +11,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/psr.h>
index cee356b0dae35538cb78c7d3521d64a283c9b0c9..dbc6874032084740d3f8f483edee5830eb8acad2 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _SPARC_IRQ_H
 #define _SPARC_IRQ_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/threads.h>     /* For NR_CPUS */
 #include <linux/interrupt.h>
index 59b86bc793bf9a7bee6c351f5e6e6bdae04bc0fc..bd92a78f49379f5e9b339552b9081f6072c33cbe 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _SPARC_MOSTEK_H
 #define _SPARC_MOSTEK_H
 
-#include <linux/config.h>
 #include <asm/idprom.h>
 #include <asm/io.h>
 
index ec3274b7ddf4b347c2303f2331bdeb2c832978b9..5bab8a7c25cee332924fdad50208f6ddf26dada9 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _SPARC_PAGE_H
 #define _SPARC_PAGE_H
 
-#include <linux/config.h>
 #ifdef CONFIG_SUN4
 #define PAGE_SHIFT   13
 #else
index 126800acd10dcfd6bef608d26e0937aedffc7ec9..a449cd4912d1f711889c9991dcd8f155c5545a38 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef _SPARC_PGALLOC_H
 #define _SPARC_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 
index 9eea8f4d41f059a21394449eb388898b3ec8681c..226c6475c9a261091a169d3fa4e11b1e3d71d5a5 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/swap.h>
 #include <asm/types.h>
index b4ca2d94bf084a29975a6da772459ab3471b9239..ecfc86a4a725caee13da26b328f2992975534a92 100644 (file)
@@ -25,7 +25,6 @@
 #ifndef _SFP_MACHINE_H
 #define _SFP_MACHINE_H
 
-#include <linux/config.h>
    
 #define _FP_W_TYPE_SIZE                32
 #define _FP_W_TYPE             unsigned long
index 98c46e3fbe8a2faae8bb92f3e2d66889a624f9da..5a1b7e4e7cc91ff14c219738a388607eed2f1bc2 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _SPARC_SMP_H
 #define _SPARC_SMP_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/head.h>
 #include <asm/btfixup.h>
index 58dd162927bbdd076ff1f6c11a80fadcdb68b324..cb7dda1e5e91fe93a853d60b382e74e723ae155a 100644 (file)
@@ -1,10 +1,8 @@
 /* $Id: system.h,v 1.86 2001/10/30 04:57:10 davem Exp $ */
-#include <linux/config.h>
 
 #ifndef __SPARC_SYSTEM_H
 #define __SPARC_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/threads.h>     /* NR_CPUS */
 #include <linux/thread_info.h>
index b16eb739dddbce898ff23c13099e2fb7d0fcf01b..cb1fa1d1f184dbc2c2880c93003c71ea87764f1e 100644 (file)
@@ -4,7 +4,6 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/config.h>
 
 #ifndef _SPARC_TIMER_H
 #define _SPARC_TIMER_H
index 5643ca31ead97e18e9dfb244d9e0a876e4f676e6..4a3b66618e753a9bd4edf287080ad52f94e80a80 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _SPARC_TLBFLUSH_H
 #define _SPARC_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 // #include <asm/processor.h>
 
index 45a576507785df07ed0969b9e97b1eb5248f391c..2553762465ca78f1d31cdaf10d57f6d8279bf4c0 100644 (file)
 #define __NR_set_robust_list   300
 #define __NR_get_robust_list   301
 
+#ifdef __KERNEL__
 /* WARNING: You MAY NOT add syscall numbers larger than 301, since
  *          all of the syscall tables in the Sparc kernel are
  *          sized to have 301 entries (starting at zero).  Therefore
@@ -455,7 +456,6 @@ errno = -__res; \
 return -1; \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
@@ -477,7 +477,6 @@ return -1; \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -534,4 +533,5 @@ asmlinkage long sys_rt_sigaction(int sig,
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _SPARC_UNISTD_H */
index 9e01723230429c5d25e7d13b072678b7551f7ca5..ab6f53b913ea707079898f6a141ff97dff41a664 100644 (file)
@@ -8,7 +8,6 @@
  * Copyright (C) 1994, David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/config.h>
 #include <asm/sysen.h>
 #include <asm/contregs.h>
 #include <asm/asi.h>
index 557257eef3f947b0f2d60bee5267a0bd8e9f05d0..096f3d3d90c3f7996f78c03f4570fb7cec013f6e 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _SPARC_WINMACRO_H
 #define _SPARC_WINMACRO_H
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 
 /* Store the register window onto the 8-byte aligned area starting
index 468eb48d814246e0b793b900d459b0ad51422cd6..2f0bec26a695df90ec4fee0c07935ec4a3c0f0de 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef __ARCH_SPARC64_ATOMIC__
 #define __ARCH_SPARC64_ATOMIC__
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 typedef struct { volatile int counter; } atomic_t;
index 71944b0f09de7e1cf52a5b08eeb0fe16bd9605e4..3d5e1af84723bade56ba80e46e98944d14d0e4d7 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _SPARC64_BITOPS_H
 #define _SPARC64_BITOPS_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/byteorder.h>
 
index 360dd04ed8e44dffd7817089e60c17b3c28969c0..120422fdb02f349bb64e6bc01ad957cb3efebeaf 100644 (file)
@@ -4,7 +4,6 @@
  *  Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/config.h>
 
 extern unsigned long loops_per_jiffy;
 
index b3f61659ba81531a4acc77e9f21acbd918fc660c..745d1ab6037196863cd5c1d03be99f15a0588fa2 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _SPARC64_CACHEFLUSH_H
 #define _SPARC64_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <asm/page.h>
 
 #ifndef __ASSEMBLY__
index 2901ea0c342d9a231147ee1d1ebdb7e4c6ba772b..a4aae6f8062741a757fcd2636228fd68b6bab68b 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __SPARC64_DELAY_H
 #define __SPARC64_DELAY_H
 
-#include <linux/config.h>
 #include <linux/param.h>
 #include <asm/cpudata.h>
 
index a8d39f23d43b7755023541770b35e3fa1e2c88b2..3c2b5bc8650b46491edb4c015ac687697ba3bc29 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_SPARC64_DMA_MAPPING_H
 #define _ASM_SPARC64_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 
index 1aab3c8dce2b0b0e9c5ed76e7464487f1de72159..27f65972b3bbd89a565b123576f5084dab2f71e5 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _ASM_SPARC64_DMA_H
 #define _ASM_SPARC64_DMA_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
index 6a95d5d0c57613c5760773123ace45b08d765456..07ccd6f04b52e64cbec01e82ac8c239fc6ecc7fd 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef __ASM_SPARC64_FLOPPY_H
 #define __ASM_SPARC64_FLOPPY_H
 
-#include <linux/config.h>
 #include <linux/init.h>
 
 #include <asm/page.h>
index c393f815b0be2b1acce8aed503a2bb5cdd2dfe4c..55149cf933c26bb8c61cbb4d760576ed3cedf0ef 100644 (file)
@@ -10,7 +10,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/pgalloc.h>
 #include <asm/io.h>
 #include <asm/spitfire.h>
index de33d6e1afb52d008d63cb3067390871bb9eb752..fa164d37ee3fb25c88300440a0d8899bc24399fe 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _SPARC64_IRQ_H
 #define _SPARC64_IRQ_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
index e4efe652b54b91322a81025a42e11f44ddcc2bbe..e9bb26f770eddcfd4288c01d247c5cb9a1a83cd8 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/percpu.h>
 
index 75bd572b35feb19c91be88077fc608c95d51c1aa..e9c0fcc25c6f44e2c729cda84994949b32606bb0 100644 (file)
@@ -4,7 +4,6 @@
 #ifndef __ASM_SPARC64_MC146818RTC_H
 #define __ASM_SPARC64_MC146818RTC_H
 
-#include <linux/config.h>
 #include <asm/io.h>
 
 #ifndef RTC_PORT
index 2d4f2ea9568a901d223cbfce903bb3dd4b7114c3..70af4b6ce136910caa4b72a3aefd43ba56f46705 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __MMU_H
 #define __MMU_H
 
-#include <linux/config.h>
 #include <asm/page.h>
 #include <asm/const.h>
 #include <asm/hypervisor.h>
index c754676e13ef16043791164ee4f8b1695eb29823..dea3e73f0955993cfec5c27d650b141a74eda3db 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef __SPARC64_OPLIB_H
 #define __SPARC64_OPLIB_H
 
-#include <linux/config.h>
 #include <asm/openprom.h>
 
 /* OBP version string. */
index aabb219067243a353b41726297e61d9544b59187..fdf0ceb7602816fd3ce48989d892572418b62265 100644 (file)
@@ -3,7 +3,6 @@
 #ifndef _SPARC64_PAGE_H
 #define _SPARC64_PAGE_H
 
-#include <linux/config.h>
 #include <asm/const.h>
 
 #if defined(CONFIG_SPARC64_PAGE_SIZE_8KB)
index a1cd4974630b4dbac56661a554e1f7b9f61e8f7d..f0125cf5a9df7dac55b4ffdb25b150befb6ab048 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASMSPARC64_PARAM_H
 #define _ASMSPARC64_PARAM_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 # define HZ            CONFIG_HZ       /* Internal kernel timer frequency */
index 12e4a273bd43adf54f6f12901ff1912305e6a0ce..010f9cd0a672137d89ed4569549e78dd6868197e 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef _SPARC64_PGALLOC_H
 #define _SPARC64_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
index c44e7466534e9dab3f4d1cd3c5936cec1b45a80b..4e218814bb3c2b62932b3f0b1ed3227dd523a0dd 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <asm-generic/pgtable-nopud.h>
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/types.h>
 #include <asm/spitfire.h>
@@ -689,6 +688,23 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p
 #define pte_clear(mm,addr,ptep)                \
        set_pte_at((mm), (addr), (ptep), __pte(0UL))
 
+#ifdef DCACHE_ALIASING_POSSIBLE
+#define __HAVE_ARCH_MOVE_PTE
+#define move_pte(pte, prot, old_addr, new_addr)                                \
+({                                                                     \
+       pte_t newpte = (pte);                                           \
+       if (tlb_type != hypervisor && pte_present(pte)) {               \
+               unsigned long this_pfn = pte_pfn(pte);                  \
+                                                                       \
+               if (pfn_valid(this_pfn) &&                              \
+                   (((old_addr) ^ (new_addr)) & (1 << 13)))            \
+                       flush_dcache_page_all(current->mm,              \
+                                             pfn_to_page(this_pfn));   \
+       }                                                               \
+       newpte;                                                         \
+})
+#endif
+
 extern pgd_t swapper_pg_dir[2048];
 extern pmd_t swapper_low_pmd_dir[2048];
 
index c6896b88283e14415a5b925c566945db7be8179e..66dd2fa0e319ef9025b849951887d2ee0775b04d 100644 (file)
@@ -13,7 +13,6 @@
  */
 #define current_text_addr() ({ void *pc; __asm__("rd %%pc, %0" : "=r" (pc)); pc; })
 
-#include <linux/config.h>
 #include <asm/asi.h>
 #include <asm/a.out.h>
 #include <asm/pstate.h>
index df17e47abc1c49f918aa9bd3bf809292d5e8c728..c96e6c30f8b0580c1738b722ea441f3f69fd4a1f 100644 (file)
@@ -11,7 +11,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compat.h>
 
 #ifdef CONFIG_COMPAT
index e3059bb4a465519a8b6f22490828dea4168706fa..fdc42a14d4e64a776aef4af390967811f03f7eaf 100644 (file)
@@ -6,7 +6,6 @@
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/personality.h>
 #include <linux/types.h>
 #include <linux/compat.h>
index 89d86ecaab2459ddf168695fb80b11ebdf787ee0..388249b751c32b61aab26acde0f52cff5eefeec0 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _SPARC64_SMP_H
 #define _SPARC64_SMP_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/asi.h>
 #include <asm/starfire.h>
index 508c416e9d6a8b1423ab3bb88eef8ee27d67ec9a..bd5ffc76bc7e6774274b596ca8b43154c894ed08 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef __SPARC64_SPINLOCK_H
 #define __SPARC64_SPINLOCK_H
 
-#include <linux/config.h>
 #include <linux/threads.h>     /* For NR_CPUS */
 
 #ifndef __ASSEMBLY__
index a18ec87a52c1b2530c55f5dd2452133c5ce4703c..4ca68600c670413315b17bca7428778aa707fb95 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef __SPARC64_SYSTEM_H
 #define __SPARC64_SYSTEM_H
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/visasm.h>
index edc8e08c3a39042b73d9a52b9de7617761a8991f..d435594df7869dc5c660c17bde7d46082c91b587 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <linux/types.h>
 
-#include <linux/config.h>
 
 struct sparc64_tick_ops {
        void (*init_tick)(unsigned long);
index 61c01882b5629db7f665943255fc7574e3ee7c46..7af1e1109c49e1f5092f44914601f98624b96a5a 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _SPARC64_TLB_H
 #define _SPARC64_TLB_H
 
-#include <linux/config.h>
 #include <linux/swap.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
index e3a7c453b5002a4d0b4e1fa5e28c118038eeddf0..3487328570edc1b5e86886ec29de371a72055136 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _SPARC64_TLBFLUSH_H
 #define _SPARC64_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/mmu_context.h>
 
index 2d5e3c464df598ee7679eacd3c66b0bb987d9c2e..f2352606a79f5a1dd6e0f8ff305d6becc1665ce7 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef _SPARC64_TTABLE_H
 #define _SPARC64_TTABLE_H
 
-#include <linux/config.h>
 #include <asm/utrap.h>
 
 #ifdef __ASSEMBLY__
index 998ef4ab0e068fbcf564f4b0fbdf05a2744f3663..badc73fdcb97c261a1011db687a45a4ac88b59a5 100644 (file)
 #define __NR_set_robust_list   300
 #define __NR_get_robust_list   301
 
+#ifdef __KERNEL__
 /* WARNING: You MAY NOT add syscall numbers larger than 301, since
  *          all of the syscall tables in the Sparc kernel are
  *          sized to have 301 entries (starting at zero).  Therefore
@@ -487,7 +488,6 @@ asmlinkage long sys_rt_sigaction(int sig,
 
 #endif /* __KERNEL_SYSCALLS__ */
 
-#ifdef __KERNEL__
 /* sysconf options, for SunOS compatibility */
 #define   _SC_ARG_MAX             1
 #define   _SC_CHILD_MAX           2
@@ -521,7 +521,6 @@ asmlinkage long sys_rt_sigaction(int sig,
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
-#endif
 
 /*
  * "Conditional" syscalls
@@ -531,4 +530,5 @@ asmlinkage long sys_rt_sigaction(int sig,
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _SPARC64_UNISTD_H */
index 7c26265e1d7a37ff59bacf179436a7f1a4b47fdf..50cee7b296f44693a65cea7751253844e12df7df 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __UM_A_OUT_H
 #define __UM_A_OUT_H
 
-#include "linux/config.h"
 #include "asm/arch/a.out.h"
 #include "choose-mode.h"
 
index 3d0587075521ee3fb3108dfdcf3c219cb5467125..19e1bdd674165739b66dab05cb04e7527f174b79 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __UM_CACHE_H
 #define __UM_CACHE_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT)
 # define L1_CACHE_SHIFT                (CONFIG_X86_L1_CACHE_SHIFT)
index 2998cf925042886e1bca6667beda08a6ad039727..99711134e477a2bae4a4ddb9c80961363b458f19 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __UM_ELF_PPC_H
 #define __UM_ELF_PPC_H
 
-#include "linux/config.h"
 
 extern long elf_aux_hwcap;
 #define ELF_HWCAP (elf_aux_hwcap)
index ae0ca3932d5086f208e8e8b2903260af599e8d2c..d352a35cfafb3c1a0aff2eeab1f630d8646f220a 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __UM_FIXMAP_H
 #define __UM_FIXMAP_H
 
-#include <linux/config.h>
 #include <asm/kmap_types.h>
 #include <asm/archparam.h>
 #include <asm/elf.h>
index 1224b2690a235d6029ecca8a02afe6ce45151708..313ebb8a256615be39566b1eba42b8caaf37a9a0 100644 (file)
@@ -3,7 +3,6 @@
 #ifndef __ASM_UM_HARDIRQ_H
 #define __ASM_UM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
diff --git a/include/asm-um/irqflags.h b/include/asm-um/irqflags.h
new file mode 100644 (file)
index 0000000..659b9ab
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __UM_IRQFLAGS_H
+#define __UM_IRQFLAGS_H
+
+/* Empty for now */
+
+#endif
index e3d62dcbd3565685b110bc9e1f3a76b871a365b3..78b862472b363e9bde4c01e43b3f69d81697bd7d 100644 (file)
@@ -3,7 +3,6 @@
 
 #include "asm/arch/linkage.h"
 
-#include <linux/config.h>
 
 /* <linux/linkage.h> will pick sane defaults */
 #ifdef CONFIG_GPROF
index 9a0e48eb542e019d5e259f3972550649bb1e46a8..f709c784bf1296e21de0a33175e403e86a974df6 100644 (file)
@@ -7,7 +7,6 @@
 #define __UM_MMU_CONTEXT_H
 
 #include "linux/sched.h"
-#include "linux/config.h"
 #include "choose-mode.h"
 #include "um_mmu.h"
 
index 41364330aff17542c2b0aa3ffcc9fccc741e8c33..4296d3135aa996e5f3eeeaf1267338644acdc2ad 100644 (file)
@@ -9,7 +9,6 @@
 
 struct page;
 
-#include <linux/config.h>
 #include <asm/vm-flags.h>
 
 /* PAGE_SHIFT determines the page size */
index ea49411236dcf71334dc4dafbb152d33e720e6cc..34ab268ef40e6f5453662ce1b1b00a08429f734b 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef __UM_PGALLOC_H
 #define __UM_PGALLOC_H
 
-#include "linux/config.h"
 #include "linux/mm.h"
 #include "asm/fixmap.h"
 
index da07a69ce82a5bda77c7746faa22b8c4afdd8a99..824c2889638215177fb372219df2cf4c968fc61e 100644 (file)
@@ -10,7 +10,6 @@ struct pt_regs;
 
 struct task_struct;
 
-#include "linux/config.h"
 #include "asm/ptrace.h"
 #include "choose-mode.h"
 #include "registers.h"
index 503484305e6771552f3d993db812d94ab25b7043..a36f5371b36b0148886714d86d05baa2a4eca8e5 100644 (file)
@@ -8,7 +8,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include "linux/config.h"
 
 #define pt_regs pt_regs_subarch
 #define show_regs show_regs_subarch
index aeda6657f366e156ff8e6997f06a6726f19098ea..ca552261ed1fcee5c3493830d2903e9754bcc3a3 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef CONFIG_SMP
 
-#include "linux/config.h"
 #include "linux/bitops.h"
 #include "asm/current.h"
 #include "linux/cpumask.h"
index f166b9837c6a59eca771e760d2b4b46dbfbd3a43..261e2f4528f6a62e1f5dd94c41ff06d5405beeed 100644 (file)
@@ -8,7 +8,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/types.h>
 
index bea5a015f6674b4102030cf81de18813a07e2883..16c734af9193c8442fbed9ff7d561420ec8157ec 100644 (file)
 
 #define __get_user(x, ptr) \
 ({ \
-       const __typeof__(ptr) __private_ptr = ptr;      \
+       const __typeof__(*(ptr)) __user *__private_ptr = (ptr); \
        __typeof__(x) __private_val;                    \
        int __private_ret = -EFAULT;                    \
        (x) = (__typeof__(*(__private_ptr)))0;                          \
-       if (__copy_from_user((void *) &__private_val, (__private_ptr),  \
+       if (__copy_from_user((__force void *)&__private_val, (__private_ptr),\
                             sizeof(*(__private_ptr))) == 0) {          \
                (x) = (__typeof__(*(__private_ptr))) __private_val;     \
                __private_ret = 0;                                      \
@@ -62,7 +62,7 @@
 
 #define __put_user(x, ptr) \
 ({ \
-        __typeof__(ptr) __private_ptr = ptr; \
+        __typeof__(*(ptr)) __user *__private_ptr = ptr; \
         __typeof__(*(__private_ptr)) __private_val; \
         int __private_ret = -EFAULT; \
         __private_val = (__typeof__(*(__private_ptr))) (x); \
index 166df00457eaeaf5f5bace956c1594b258f4b747..e4e57de08f73054b042592f638ed12d76d046f9e 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef __V850_ATOMIC_H__
 #define __V850_ATOMIC_H__
 
-#include <linux/config.h>
 
 #include <asm/system.h>
 
index 1f6fd5ab4177badda30517f04e339b84a471c144..1fa99baf4e25bbaf2f82daaf1960537bb59bfde8 100644 (file)
@@ -14,7 +14,6 @@
 #define __V850_BITOPS_H__
 
 
-#include <linux/config.h>
 #include <linux/compiler.h>    /* unlikely  */
 #include <asm/byteorder.h>     /* swab32 */
 #include <asm/system.h>                /* interrupt enable/disable */
index c63fb50ec9eff33641b52b2ec81a34c705e5ba40..1cc42c603a1b858ec6e8ab8d00ce0fbc5edaa0d2 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __V850_DMA_MAPPING_H__
 #define __V850_DMA_MAPPING_H__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
index d98488cd5af1fb0dd793863ebdb74ed36b6e4be6..04e20127c5af5b161194414f49c699540f44f4db 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __V850_HARDIRQ_H__
 #define __V850_HARDIRQ_H__
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cache.h>
 
index 98d8bf63970eda99d669ae7497a0ab3b1994150c..f1e3b8b91508d55f2a59659acc1de2aac773bb04 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef __V850_MACHDEP_H__
 #define __V850_MACHDEP_H__
 
-#include <linux/config.h>
 
 /* chips */
 #ifdef CONFIG_V850E_MA1
index 3cf8775ce85f11f9aea4e1807cd8553997f5645c..1ea2a900f0f8bb4da4e4f1613dc2b6ced48f25a6 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <asm/page.h>
 
 
index 2d31308935a00ab0263feab4b75ce8be482724be..6965b66ccaed89ff828bd331bece3a5a5c6ceefa 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef __V850_PROCESSOR_H__
 #define __V850_PROCESSOR_H__
 
-#include <linux/config.h>
 #ifndef __ASSEMBLY__ /* <linux/thread_info.h> is not asm-safe.  */
 #include <linux/thread_info.h>
 #endif
index 8c2a609ba2b0487f81583660ec34f9b799699f04..36d8f4cbbf39a03bb3d83f83cf8c50c7c5553448 100644 (file)
@@ -6,7 +6,6 @@
  * Copyright (C) 1999 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */ 
-#include <linux/config.h>
 
 #ifdef CONFIG_RTE_CB_ME2
 
index 82460a7bb233fbc6f4354fafb903197ae7c0ca16..bcb44bfe577a58c257b22d591ce9840427e74821 100644 (file)
@@ -14,8 +14,6 @@
 #ifndef __V850_UNISTD_H__
 #define __V850_UNISTD_H__
 
-#include <asm/clinkage.h>
-
 #define __NR_restart_syscall     0
 #define __NR_exit                1
 #define __NR_fork                2
    except the syscall number (r12).  */
 #define SYSCALL_SHORT_CLOBBERS SYSCALL_CLOBBERS, "r13", "r14"
 
+#ifdef __KERNEL__
 
-/* User programs sometimes end up including this header file
-   (indirectly, via uClibc header files), so I'm a bit nervous just
-   including <linux/compiler.h>.  */
+#include <asm/clinkage.h>
 
 #define __syscall_return(type, res)                                          \
   do {                                                                       \
@@ -368,7 +365,6 @@ type name (atype a, btype b, ctype c, dtype d, etype e, ftype f)          \
 }
                
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
@@ -389,7 +385,6 @@ type name (atype a, btype b, ctype c, dtype d, etype e, ftype f)          \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -440,7 +435,7 @@ asmlinkage long sys_rt_sigaction(int sig,
                                struct sigaction __user *oact,
                                size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -455,4 +450,5 @@ asmlinkage long sys_rt_sigaction(int sig,
   void name (void) __attribute__ ((weak, alias ("sys_ni_syscall")));
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* __V850_UNISTD_H__ */
index 5930d5990b193ce029bb18e112bfdafa3e06544a..5182fb4cc989fe2125868925d60fd6a12f4d1f58 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef __V850_V850E_UART_H__
 #define __V850_V850E_UART_H__
 
-#include <linux/config.h>
 #include <linux/termios.h>
 
 #include <asm/v850e_utils.h>
index bdbd8935612a7d6eaa9f96e63e796abc72cfb66b..a731be2204d21fd78eb22a84ada942a77b7fd0d3 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_APIC_H
 #define __ASM_APIC_H
 
-#include <linux/config.h>
 #include <linux/pm.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
index cecbf7baa6aa346297efa3bb14480bddd5e4236a..bd3fa67ed835dfdc8f294cf722d7f41c5b79556a 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ARCH_X86_64_ATOMIC__
 #define __ARCH_X86_64_ATOMIC__
 
-#include <linux/config.h>
 #include <asm/types.h>
 
 /* atomic_t should be 32 bit signed type */
index 79212128d0f748d82a72198d970581b541ab909a..e9bf933d25d0a78f55d45be879b4dee1f7e4b770 100644 (file)
@@ -5,7 +5,6 @@
  * Copyright 1992, Linus Torvalds.
  */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 #define LOCK_PREFIX "lock ; "
index 59bc68925d0fdfd1b1de6d5c14cfe2516466f838..d86c5dd689fa619b3fab3c909104889125d00324 100644 (file)
@@ -10,7 +10,6 @@
  *     void check_bugs(void);
  */
 
-#include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/msr.h>
index f8dff1c67538b75381964b6c5c7b4dd3dcc9b37d..ed8a9d25272db1e8fe770051f0830efa3a2deb1c 100644 (file)
@@ -4,7 +4,6 @@
 #ifndef __ARCH_X8664_CACHE_H
 #define __ARCH_X8664_CACHE_H
 
-#include <linux/config.h>
 
 /* L1 cache line size */
 #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
index fc2c5a6c262a20356c1fc1dc5e475fa84d97189c..6f4f63af96e1a661f215895e502155f402b40678 100644 (file)
@@ -2,7 +2,6 @@
  * Some macros to handle stack frames in assembly.
  */ 
 
-#include <linux/config.h>
 
 #define R15 0
 #define R14 8
index 49a81a66516e9ba2d6556c0154925d970d0ceaf8..498f66df36b948e69cd290c66f72f2026586764d 100644 (file)
@@ -6,7 +6,6 @@
  * documentation.
  */
 
-#include <linux/config.h>
 
 #include <asm/scatterlist.h>
 #include <asm/io.h>
index 6f2a817b6a7c6d1ce382e6850a1a3cc3ff0c4078..c556208d3dd7b1ed36d6b8ba9f3c32cb6e366227 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>    /* And spinlocks */
 #include <asm/io.h>            /* need byte IO */
 #include <linux/delay.h>
index 07654bd155bf9d44c35fc4a619b8506692fc6b5e..0744db777676033aa351c41b7b64ebf0bdc4cd25 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _DWARF2_H
 #define _DWARF2_H 1
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 #warning "asm/dwarf2.h should be only included in pure assembly files"
index c98633af07d26abb0ee6776f90c6eef7dd60008f..b4f8f4a41a6e93fbebddbd3a399b1c932dd23387 100644 (file)
@@ -159,7 +159,7 @@ extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
 
 /* 1GB for 64bit, 8MB for 32bit */
-#define STACK_RND_MASK (is_compat_task() ? 0x7ff : 0x3fffff)
+#define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff)
 
 #endif
 
index 7b286bd21d1dc5e641a72a282cbe92d432ec110e..0b4ffbd1a12521a2fab5be65938f87f3348a1004 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/apicdef.h>
 #include <asm/page.h>
index 8689951e350348be7123affa57241d77997eb41b..64a65ce2f41fe690033bff1f8ce0d9314b5a9a82 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 #include <asm/pda.h>
index 0df1715dee7186b1cce490e86c6456d6b7d2466b..3de96fd86a707b0bd3f29a94790520925fda0a86 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <asm/atomic.h>
 #include <asm/irq.h>
 #include <linux/profile.h>
index e6b7f2234e439ccdac3400be1e49d2cd624f1d61..0190b7c4e319cc1a153a23ba2030267ba8694b4e 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_X86_64_IA32_H
 #define _ASM_X86_64_IA32_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_IA32_EMULATION
 
index a05da8a50bfdf28a659df356a0d7a7fbf6342409..70e91fe7634485708815dda0c851c2f066064a1c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
-#include <linux/config.h>
 
 /*
  * This file contains the definitions for the x86 IO instructions
index 52484e82c641d884dd7da4f8b63b743073402a80..fb7a0909a17417778eaa659da883f488ab324f61 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_IO_APIC_H
 #define __ASM_IO_APIC_H
 
-#include <linux/config.h>
 #include <asm/types.h>
 #include <asm/mpspec.h>
 
index 19f0c83d0792a24cc6fca9b45390c1c008f5ca98..af03b9f852d650eec292f0b8eced273a23bcaca8 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __X86_64_MMU_CONTEXT_H
 #define __X86_64_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <asm/desc.h>
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
index 6944e7122df5194c767217444a993a90db3d6ede..70bb9969766e2f11df1ca81e5c1ad6168c05bff8 100644 (file)
@@ -4,7 +4,6 @@
 #ifndef _ASM_X86_64_MMZONE_H
 #define _ASM_X86_64_MMZONE_H 1
 
-#include <linux/config.h>
 
 #ifdef CONFIG_NUMA
 
index 66ac1c0f27e1d7eba11de129680617d3476a0f33..d6135b2549bff80123657052a09364f732e6aa04 100644 (file)
@@ -23,9 +23,7 @@
 #ifndef _LINUX_MTRR_H
 #define _LINUX_MTRR_H
 
-#include <linux/config.h>
 #include <linux/ioctl.h>
-#include <linux/compat.h>
 
 #define        MTRR_IOCTL_BASE 'M'
 
@@ -102,11 +100,10 @@ static __inline__ int mtrr_del_page (int reg, unsigned long base,
     return -ENODEV;
 }
 
-#  endif
-
-#endif
+#endif /* CONFIG_MTRR */
 
 #ifdef CONFIG_COMPAT
+#include <linux/compat.h>
 
 struct mtrr_sentry32
 {
@@ -138,4 +135,6 @@ struct mtrr_gentry32
 
 #endif /* CONFIG_COMPAT */
 
+#endif /* __KERNEL__ */
+
 #endif  /*  _LINUX_MTRR_H  */
index 408185bac35108cbf9d3b433f662f823c124b373..f7bf875aae4050d322c5ed15893be6a1537f76ba 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _X86_64_PAGE_H
 #define _X86_64_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT     12
@@ -136,9 +135,9 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #define __HAVE_ARCH_GATE_AREA 1        
 
-#endif /* __KERNEL__ */
-
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+#endif /* __KERNEL__ */
+
 #endif /* _X86_64_PAGE_H */
index 5956b23b57c247d6a18a911469a54e312007429b..a728786c3c7c0376f8dfac4ecf3365c70ce31ff9 100644 (file)
@@ -2,7 +2,6 @@
 #define _ASMx86_64_PARAM_H
 
 #ifdef __KERNEL__
-# include <linux/config.h>
 # define HZ            CONFIG_HZ       /* Internal kernel timer frequency */
 # define USER_HZ       100             /* .. some user interfaces are in "ticks */
 #define CLOCKS_PER_SEC        (USER_HZ)       /* like times() */
index 8a05af264d1865d57e429ce69e696cc379b2dc95..2db0620d544912a099181231bc75fc4dfd94976f 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __x8664_PCI_H
 #define __x8664_PCI_H
 
-#include <linux/config.h>
 #include <asm/io.h>
 
 #ifdef __KERNEL__
index 37a3ec433ee5816e7ada16d4f8da264b1623343e..3061a38a3b1d8504f40a5cf0e84dc23a298cc3e5 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/types.h>
 #include <asm/sigcontext.h>
 #include <asm/cpufeature.h>
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/msr.h>
 #include <asm/current.h>
index dc752eafa681e1f3dcd46045fb0cce9dd40bdfae..b0496e0d72a68669cf5a5c1204af07bc1bcee334 100644 (file)
@@ -2,7 +2,6 @@
  * include/asm-x86_64/serial.h
  */
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
index a4fdaeb5c3977b189f919153a0e51aa46cd94477..7686b9b25aefd47da20b0ab128071f6ab764628a 100644 (file)
@@ -5,7 +5,6 @@
  * We need the APIC definitions automatically as part of 'smp.h'
  */
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/bitops.h>
index fe484a699cc3609cca9d1c592e17624bd7bd22a8..5d8a5e3589ff544cc9a707cfeca75c17107b320e 100644 (file)
@@ -4,7 +4,6 @@
 #include <asm/atomic.h>
 #include <asm/rwlock.h>
 #include <asm/page.h>
-#include <linux/config.h>
 
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
index 60757efd1353b9770fc240008955c9dcbfd1ae10..5f9a0180582187b1b23196955b66dda63951b214 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_SWIOTLB_H
 #define _ASM_SWTIOLB_H 1
 
-#include <linux/config.h>
 
 #include <asm/dma-mapping.h>
 
index 3975989802280ff1ad2ffc7322a68611ad2d5793..f48e0dad8b3d3c5503a827a4bc3b5b8a73b0885f 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_SYSTEM_H
 #define __ASM_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/segment.h>
 
index 4a9c20ea9b105d9523bb712e0b9a30d93aa30047..d16d5b60f419b4680d20bd14bb7b93bba8f74308 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _X8664_TLBFLUSH_H
 #define _X8664_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
 
index 9db54e9d17bb0c68f31677fc2cc6fceccb8df6d7..80c4e44d011ca2f58c02e4a3c42b18d119c5d7b3 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_X86_64_TOPOLOGY_H
 #define _ASM_X86_64_TOPOLOGY_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_NUMA
 
index bddffcb591b8b26c1068292c459d3d1ae446350b..1e1fa003daa3364ca9a2e96c0c1e7af75216cbd5 100644 (file)
@@ -4,7 +4,6 @@
 /*
  * User space memory access functions
  */
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
index feb77cb8c0442eb629799b18163a07f663d3fbd5..0aff22bdbb2187c49615dcd49b53847958a3e42f 100644 (file)
@@ -618,6 +618,8 @@ __SYSCALL(__NR_sync_file_range, sys_sync_file_range)
 #define __NR_vmsplice          278
 __SYSCALL(__NR_vmsplice, sys_vmsplice)
 
+#ifdef __KERNEL__
+
 #define __NR_syscall_max __NR_vmsplice
 
 #ifndef __NO_STUBS
@@ -635,7 +637,6 @@ do { \
        return (type) (res); \
 } while (0)
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
 #define __ARCH_WANT_SYS_ALARM
@@ -657,7 +658,6 @@ do { \
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_TIME
 #define __ARCH_WANT_COMPAT_SYS_TIME
-#endif
 
 #ifndef __KERNEL_SYSCALLS__
 
@@ -821,7 +821,7 @@ asmlinkage long sys_pipe(int *fildes);
 
 #endif /* __KERNEL_SYSCALLS__ */
 
-#if !defined(__ASSEMBLY__) && defined(__KERNEL__)
+#ifndef __ASSEMBLY__
 
 #include <linux/linkage.h>
 #include <linux/compiler.h>
@@ -848,4 +848,5 @@ asmlinkage long sys_rt_sigaction(int sig,
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif
index fe105a123924207ea5769829250d4ab15faaab7b..5c2672021068670758d9d9d3d4f8ef30abaa5705 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _XTENSA_ATOMIC_H
 #define _XTENSA_ATOMIC_H
 
-#include <linux/config.h>
 #include <linux/stringify.h>
 
 typedef struct { volatile int counter; } atomic_t;
index 81a797ae3abe1a8a3d4212a6ddb9645b27af3d01..bdc00ae9be48dfc0e6bce1274549cb92b2c7c2d1 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _XTENSA_CHECKSUM_H
 #define _XTENSA_CHECKSUM_H
 
-#include <linux/config.h>
 #include <linux/in6.h>
 #include <xtensa/config/core.h>
 
index 1bc601ec3621a0bca23226ab8758f4a94e04cc84..e1d8c9e010c1df976624ce71ea0449d6c8f47ae4 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef _XTENSA_DELAY_H
 #define _XTENSA_DELAY_H
 
-#include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/param.h>
 
index 1c22b02345865ea124276875c26929bab5da2359..db2633f67789ad994df5b0fb9527c5d1f347e7bd 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _XTENSA_DMA_H
 #define _XTENSA_DMA_H
 
-#include <linux/config.h>
 #include <asm/io.h>            /* need byte IO */
 #include <xtensa/config/core.h>
 
index aa9c1adf68d706f9f1f7aca00a0c59c1a9850eac..87cb19d1b10c4a780844c39ccfb9649d9b1be8c8 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _XTENSA_HARDIRQ_H
 #define _XTENSA_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/cache.h>
 #include <asm/irq.h>
 
index b523cd4a486ec155f347fa2a6738b4a739a3fb61..6b912742a42d34b085596131bc37b1441faa308c 100644 (file)
@@ -14,7 +14,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifndef MAX_HWIFS
 # define MAX_HWIFS     1
index c5c13985bbe1f013577fa2d371a086517bab8a7c..556e5eed34f54af663fd01b7200b1c5310beece3 100644 (file)
@@ -12,7 +12,6 @@
 #define _XTENSA_IO_H
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <asm/byteorder.h>
 
 #include <linux/types.h>
index d984e955938fe441f1dbbd704513bf21c0a56bb2..049fde7e752d3a098d389600e5d9b3fe8b2aa50f 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _XTENSA_IRQ_H
 #define _XTENSA_IRQ_H
 
-#include <linux/config.h>
 #include <asm/platform/hardware.h>
 
 #include <xtensa/config/core.h>
index 364a7b057bfaa60b2e2336e7573e29193e4c451b..af683a74a4ec74884ca7c8fafa42768d84f8b623 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _XTENSA_MMU_CONTEXT_H
 #define _XTENSA_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <linux/stringify.h>
 
 #include <asm/pgtable.h>
index 992bac5c12586a740f6ba3a2c9c5b9250c844239..40f4c6c3f580fd830706e21d9405235a38801d92 100644 (file)
@@ -14,7 +14,6 @@
 #ifdef __KERNEL__
 
 #include <asm/processor.h>
-#include <linux/config.h>
 
 /*
  * PAGE_SHIFT determines the page size
index 734a8d06039556bedd12a9928fd92842a0aa5d2f..d56ddf2055e12c263ad468391bbe4168985d0de1 100644 (file)
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/highmem.h>
 #include <asm/processor.h>
index 36163894bc20be1f601ae36d7073f6063921df7f..48135a9718b0d5f9da79c3098ab5d1538789306a 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _XTENSA_PLATFORM_H
 #define _XTENSA_PLATFORM_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 
index b29f7ae6a08ae5a872be5ca443844a4f01dd7362..f986170bd2a15416c5e6e94ec686f11fbb975c09 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _XTENSA_SYSTEM_H
 #define _XTENSA_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/stringify.h>
 
 #include <asm/processor.h>
index 6b39d6609d9c0c0fd2be7d05011e137ee73a631a..5e1b99dc4ab3bfd93b3657182e9d43a960b19e11 100644 (file)
@@ -11,8 +11,6 @@
 #ifndef _XTENSA_UNISTD_H
 #define _XTENSA_UNISTD_H
 
-#include <linux/linkage.h>
-
 #define __NR_spill               0
 #define __NR_exit                1
 #define __NR_read                3
 #define SYSXTENSA_COUNT                   5    /* count of syscall0 functions*/
 
 #ifdef __KERNEL__
-#define __syscall_return(type, res) return ((type)(res))
-#else
-#define __syscall_return(type, res) \
-do { \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) { \
-       /* Avoid using "res" which is declared to be in register r2; \
-        * errno might expand to a function call and clobber it.  */ \
-               int __err = -(res); \
-               errno = __err; \
-               res = -1; \
-       } \
-       return (type) (res); \
-} while (0)
-#endif
+#include <linux/linkage.h>
 
+#define __syscall_return(type, res) return ((type)(res))
 
 /* Tensilica's xt-xcc compiler is much more agressive at code
  * optimization than gcc.  Multiple __asm__ statements are
@@ -429,11 +415,10 @@ static __inline__ _syscall3(int,execve,const char*,file,char**,argv,char**,envp)
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_UTIME
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
+#endif /* __KERNEL__ */
 
 #endif /* _XTENSA_UNISTD_H */
index 9a66401073fc1b8ff8e90b2d70d020c032a9900e..3d54fbcf969e60ddee19968455593f871b223d97 100644 (file)
@@ -16,7 +16,6 @@
 #define _LINUX_ACCT_H
 
 #include <linux/types.h>
-#include <linux/jiffies.h>
 
 #include <asm/param.h>
 #include <asm/byteorder.h>
@@ -116,7 +115,6 @@ struct acct_v3
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_BSD_PROCESS_ACCT
 struct vfsmount;
@@ -165,6 +163,7 @@ typedef struct acct acct_t;
 #endif /* __KERNEL */
 
 #ifdef __KERNEL__
+#include <linux/jiffies.h>
 /*
  * Yet another set of HZ to *HZ helper functions.
  * See <linux/jiffies.h> for the original.
index d3bc25e6d27da8f0b38dccab6073ca92dd81ab24..1cf0b91d05bd287aa328d710ba7a85c9aee7ec51 100644 (file)
@@ -25,7 +25,6 @@
 #ifndef _LINUX_ACPI_H
 #define _LINUX_ACPI_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_ACPI
 
index 3fb869939d82484a9947d6860e3fe490b2d4efdf..f1b948c1f5925fd9c495ea0174295021b581cbb6 100644 (file)
@@ -1,45 +1,47 @@
 #ifndef        AFFS_HARDBLOCKS_H
 #define        AFFS_HARDBLOCKS_H
 
+#include <linux/types.h>
+
 /* Just the needed definitions for the RDB of an Amiga HD. */
 
 struct RigidDiskBlock {
-       u32     rdb_ID;
+       __u32   rdb_ID;
        __be32  rdb_SummedLongs;
-       s32     rdb_ChkSum;
-       u32     rdb_HostID;
+       __s32   rdb_ChkSum;
+       __u32   rdb_HostID;
        __be32  rdb_BlockBytes;
-       u32     rdb_Flags;
-       u32     rdb_BadBlockList;
+       __u32   rdb_Flags;
+       __u32   rdb_BadBlockList;
        __be32  rdb_PartitionList;
-       u32     rdb_FileSysHeaderList;
-       u32     rdb_DriveInit;
-       u32     rdb_Reserved1[6];
-       u32     rdb_Cylinders;
-       u32     rdb_Sectors;
-       u32     rdb_Heads;
-       u32     rdb_Interleave;
-       u32     rdb_Park;
-       u32     rdb_Reserved2[3];
-       u32     rdb_WritePreComp;
-       u32     rdb_ReducedWrite;
-       u32     rdb_StepRate;
-       u32     rdb_Reserved3[5];
-       u32     rdb_RDBBlocksLo;
-       u32     rdb_RDBBlocksHi;
-       u32     rdb_LoCylinder;
-       u32     rdb_HiCylinder;
-       u32     rdb_CylBlocks;
-       u32     rdb_AutoParkSeconds;
-       u32     rdb_HighRDSKBlock;
-       u32     rdb_Reserved4;
+       __u32   rdb_FileSysHeaderList;
+       __u32   rdb_DriveInit;
+       __u32   rdb_Reserved1[6];
+       __u32   rdb_Cylinders;
+       __u32   rdb_Sectors;
+       __u32   rdb_Heads;
+       __u32   rdb_Interleave;
+       __u32   rdb_Park;
+       __u32   rdb_Reserved2[3];
+       __u32   rdb_WritePreComp;
+       __u32   rdb_ReducedWrite;
+       __u32   rdb_StepRate;
+       __u32   rdb_Reserved3[5];
+       __u32   rdb_RDBBlocksLo;
+       __u32   rdb_RDBBlocksHi;
+       __u32   rdb_LoCylinder;
+       __u32   rdb_HiCylinder;
+       __u32   rdb_CylBlocks;
+       __u32   rdb_AutoParkSeconds;
+       __u32   rdb_HighRDSKBlock;
+       __u32   rdb_Reserved4;
        char    rdb_DiskVendor[8];
        char    rdb_DiskProduct[16];
        char    rdb_DiskRevision[4];
        char    rdb_ControllerVendor[8];
        char    rdb_ControllerProduct[16];
        char    rdb_ControllerRevision[4];
-       u32     rdb_Reserved5[10];
+       __u32   rdb_Reserved5[10];
 };
 
 #define        IDNAME_RIGIDDISK        0x5244534B      /* "RDSK" */
@@ -47,16 +49,16 @@ struct RigidDiskBlock {
 struct PartitionBlock {
        __be32  pb_ID;
        __be32  pb_SummedLongs;
-       s32     pb_ChkSum;
-       u32     pb_HostID;
+       __s32   pb_ChkSum;
+       __u32   pb_HostID;
        __be32  pb_Next;
-       u32     pb_Flags;
-       u32     pb_Reserved1[2];
-       u32     pb_DevFlags;
-       u8      pb_DriveName[32];
-       u32     pb_Reserved2[15];
+       __u32   pb_Flags;
+       __u32   pb_Reserved1[2];
+       __u32   pb_DevFlags;
+       __u8    pb_DriveName[32];
+       __u32   pb_Reserved2[15];
        __be32  pb_Environment[17];
-       u32     pb_EReserved[15];
+       __u32   pb_EReserved[15];
 };
 
 #define        IDNAME_PARTITION        0x50415254      /* "PART" */
index 6d59c8efe3be2a1be4b1bb559bb506c551d3c213..bfb8ec791b7b6ef3596d1306f4b5ee6de36de898 100644 (file)
@@ -27,8 +27,6 @@
 #ifndef _AGP_H
 #define _AGP_H 1
 
-#include <linux/agp_backend.h>
-
 #define AGPIOC_BASE       'A'
 #define AGPIOC_INFO       _IOR (AGPIOC_BASE, 0, struct agp_info*)
 #define AGPIOC_ACQUIRE    _IO  (AGPIOC_BASE, 1)
@@ -112,6 +110,7 @@ typedef struct _agp_unbind {
 
 #else                          /* __KERNEL__ */
 #include <linux/mutex.h>
+#include <linux/agp_backend.h>
 
 #define AGPGART_MINOR 175
 
index 9cf64b1b688b58440e6f6d2e89f308ef4e1e9c1f..29c0448265cf7c7e4b9312f3cd684a319fcf8de3 100644 (file)
@@ -9,7 +9,6 @@
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
-#include <linux/config.h>
 #include <linux/fb.h>
 
 /*
index b203ea82a0a8b8db8e13613d15eca2d764b900bf..1eb238affb124fe8d657cda89f55b2a627142eb8 100644 (file)
@@ -209,7 +209,6 @@ struct atm_cirange {
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/wait.h> /* wait_queue_head_t */
 #include <linux/time.h> /* struct timeval */
 #include <linux/net.h>
index b74c148f14e30ad26b1b1a63cbe22765bb4a2651..e051ff9c5b5061fabd5b92dc7fbf5463f9eec4d5 100644 (file)
@@ -24,8 +24,7 @@
 #ifndef _LINUX_AUDIT_H_
 #define _LINUX_AUDIT_H_
 
-#include <linux/sched.h>
-#include <linux/elf.h>
+#include <linux/elf-em.h>
 
 /* The netlink messages for the audit system is divided into blocks:
  * 1000 - 1099 are for commanding the audit system
 #define AUDIT_CONFIG_CHANGE    1305    /* Audit system configuration change */
 #define AUDIT_SOCKADDR         1306    /* sockaddr copied as syscall arg */
 #define AUDIT_CWD              1307    /* Current working directory */
+#define AUDIT_EXECVE           1309    /* execve arguments */
 #define AUDIT_IPC_SET_PERM     1311    /* IPC new permissions record type */
+#define AUDIT_MQ_OPEN          1312    /* POSIX MQ open record type */
+#define AUDIT_MQ_SENDRECV      1313    /* POSIX MQ send/receive record type */
+#define AUDIT_MQ_NOTIFY                1314    /* POSIX MQ notify record type */
+#define AUDIT_MQ_GETSETATTR    1315    /* POSIX MQ get/set attribute record type */
 
 #define AUDIT_AVC              1400    /* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR      1401    /* Internal SE Linux Errors */
 #define AUDIT_SE_TYPE  15      /* security label type */
 #define AUDIT_SE_SEN   16      /* security label sensitivity label */
 #define AUDIT_SE_CLR   17      /* security label clearance label */
+#define AUDIT_PPID     18
 
                                /* These are ONLY useful when checking
                                 * at syscall exit time (AUDIT_AT_EXIT). */
 #define AUDIT_INODE    102
 #define AUDIT_EXIT     103
 #define AUDIT_SUCCESS   104    /* exit >= 0; value ignored */
+#define AUDIT_WATCH    105
 
 #define AUDIT_ARG0      200
 #define AUDIT_ARG1      (AUDIT_ARG0+1)
@@ -273,16 +279,21 @@ struct audit_rule {               /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
 };
 
 #ifdef __KERNEL__
+#include <linux/sched.h>
 
 struct audit_sig_info {
        uid_t           uid;
        pid_t           pid;
+       char            ctx[0];
 };
 
 struct audit_buffer;
 struct audit_context;
 struct inode;
 struct netlink_skb_parms;
+struct linux_binprm;
+struct mq_attr;
+struct mqstat;
 
 #define AUDITSC_INVALID 0
 #define AUDITSC_SUCCESS 1
@@ -297,15 +308,19 @@ extern void audit_syscall_entry(int arch,
                                int major, unsigned long a0, unsigned long a1,
                                unsigned long a2, unsigned long a3);
 extern void audit_syscall_exit(int failed, long return_code);
-extern void audit_getname(const char *name);
+extern void __audit_getname(const char *name);
 extern void audit_putname(const char *name);
-extern void __audit_inode(const char *name, const struct inode *inode, unsigned flags);
+extern void __audit_inode(const char *name, const struct inode *inode);
 extern void __audit_inode_child(const char *dname, const struct inode *inode,
                                unsigned long pino);
-static inline void audit_inode(const char *name, const struct inode *inode,
-                              unsigned flags) {
+static inline void audit_getname(const char *name)
+{
        if (unlikely(current->audit_context))
-               __audit_inode(name, inode, flags);
+               __audit_getname(name);
+}
+static inline void audit_inode(const char *name, const struct inode *inode) {
+       if (unlikely(current->audit_context))
+               __audit_inode(name, inode);
 }
 static inline void audit_inode_child(const char *dname, 
                                     const struct inode *inode, 
@@ -320,13 +335,61 @@ 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 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, struct kern_ipc_perm *ipcp);
+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);
 extern int audit_socketcall(int nargs, unsigned long *args);
 extern int audit_sockaddr(int len, void *addr);
 extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
-extern void audit_signal_info(int sig, struct task_struct *t);
 extern int audit_set_macxattr(const char *name);
+extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr);
+extern int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout);
+extern int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout);
+extern int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification);
+extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
+
+static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp)
+{
+       if (unlikely(current->audit_context))
+               return __audit_ipc_obj(ipcp);
+       return 0;
+}
+static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
+{
+       if (unlikely(current->audit_context))
+               return __audit_ipc_set_perm(qbytes, uid, gid, mode);
+       return 0;
+}
+static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
+{
+       if (unlikely(current->audit_context))
+               return __audit_mq_open(oflag, mode, u_attr);
+       return 0;
+}
+static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout)
+{
+       if (unlikely(current->audit_context))
+               return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
+       return 0;
+}
+static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout)
+{
+       if (unlikely(current->audit_context))
+               return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
+       return 0;
+}
+static inline int audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
+{
+       if (unlikely(current->audit_context))
+               return __audit_mq_notify(mqdes, u_notification);
+       return 0;
+}
+static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
+{
+       if (unlikely(current->audit_context))
+               return __audit_mq_getsetattr(mqdes, mqstat);
+       return 0;
+}
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
@@ -334,19 +397,24 @@ extern int audit_set_macxattr(const char *name);
 #define audit_syscall_exit(f,r) do { ; } while (0)
 #define audit_getname(n) do { ; } while (0)
 #define audit_putname(n) do { ; } while (0)
-#define __audit_inode(n,i,f) do { ; } while (0)
+#define __audit_inode(n,i) do { ; } while (0)
 #define __audit_inode_child(d,i,p) do { ; } while (0)
-#define audit_inode(n,i,f) do { ; } while (0)
+#define audit_inode(n,i) do { ; } while (0)
 #define audit_inode_child(d,i,p) do { ; } while (0)
 #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
 #define audit_get_loginuid(c) ({ -1; })
 #define audit_ipc_obj(i) ({ 0; })
-#define audit_ipc_set_perm(q,u,g,m,i) ({ 0; })
+#define audit_ipc_set_perm(q,u,g,m) ({ 0; })
+#define audit_bprm(p) ({ 0; })
 #define audit_socketcall(n,a) ({ 0; })
 #define audit_sockaddr(len, addr) ({ 0; })
 #define audit_avc_path(dentry, mnt) ({ 0; })
-#define audit_signal_info(s,t) do { ; } while (0)
 #define audit_set_macxattr(n) do { ; } while (0)
+#define audit_mq_open(o,m,a) ({ 0; })
+#define audit_mq_timedsend(d,l,p,t) ({ 0; })
+#define audit_mq_timedreceive(d,l,p,t) ({ 0; })
+#define audit_mq_notify(d,n) ({ 0; })
+#define audit_mq_getsetattr(d,s) ({ 0; })
 #endif
 
 #ifdef CONFIG_AUDIT
@@ -364,8 +432,11 @@ extern void                    audit_log_end(struct audit_buffer *ab);
 extern void                audit_log_hex(struct audit_buffer *ab,
                                          const unsigned char *buf,
                                          size_t len);
-extern void                audit_log_untrustedstring(struct audit_buffer *ab,
+extern const char *        audit_log_untrustedstring(struct audit_buffer *ab,
                                                      const char *string);
+extern const char *        audit_log_n_untrustedstring(struct audit_buffer *ab,
+                                                       size_t n,
+                                                       const char *string);
 extern void                audit_log_d_path(struct audit_buffer *ab,
                                             const char *prefix,
                                             struct dentry *dentry,
@@ -383,8 +454,8 @@ extern int  audit_receive_filter(int type, int pid, int uid, int seq,
 #define audit_log_end(b) do { ; } while (0)
 #define audit_log_hex(a,b,l) do { ; } while (0)
 #define audit_log_untrustedstring(a,s) do { ; } while (0)
+#define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
 #define audit_log_d_path(b,p,d,v) do { ; } while (0)
-#define audit_panic(m) do { ; } while (0)
 #endif
 #endif
 #endif
index 59e1259b1c408ad22a68b25b4b0a2e1580513747..5d327313a9f7d2a11edbd7691825818cd78cee4f 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_BLKDEV_H
 #define _LINUX_BLKDEV_H
 
-#include <linux/config.h>
 #include <linux/major.h>
 #include <linux/genhd.h>
 #include <linux/list.h>
index be5d0f4ad24cbc8496ae42a281c82cdf5a162553..faf8a45af210053c535537c85cb25b1af228c7e0 100644 (file)
@@ -24,6 +24,7 @@
  *
  * For today, only the partition stuff - aeb, 990515
  */
+#include <linux/compiler.h>
 #include <linux/ioctl.h>
 
 #define BLKPG      _IO(0x12,105)
index b34d3e73d5ea6b870f8592596f2a92f9e2af7ff4..eb1a867ed2459031bc3af14fdce41c4b72eda559 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef BLKTRACE_H
 #define BLKTRACE_H
 
-#include <linux/config.h>
 #include <linux/blkdev.h>
 #include <linux/relay.h>
 
index 0137ee5dd43c2edd67d4b8e8308e999cbec7ae16..8607312983bd8045c24a402335b30ee034c4505c 100644 (file)
@@ -6,7 +6,6 @@
  * Simple hashed spinlocking.
  */
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/cache.h>
 
index cc4b3aafad9a1fda984dbe6e08bfcd09d8b3b73f..4552504c02289239953aab738adede76c8da20f3 100644 (file)
@@ -2,7 +2,6 @@
 #define __LINUX_CACHE_H
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <asm/cache.h>
 
 #ifndef L1_CACHE_ALIGN
index bbc5afcd7db677209dcce87228e0b205e5165b51..b5cf0780c51a6a0e9ebc243a6053922572756f09 100644 (file)
@@ -59,7 +59,6 @@ Mellon the rights to redistribute these changes without encumbrance.
 #ifndef _CODA_HEADER_
 #define _CODA_HEADER_
 
-#include <linux/config.h>
 
 /* Catch new _KERNEL defn for NetBSD and DJGPP/__CYGWIN32__ */
 #if defined(__NetBSD__) || \
index 6d3a654be1ae8d7626c267de8208a6ba31770245..dda1697ec753025f61d0b96234e107bbbb7e9ef7 100644 (file)
@@ -4,7 +4,6 @@
  * These are the type definitions for the architecture specific
  * syscall compatibility layer.
  */
-#include <linux/config.h>
 
 #ifdef CONFIG_COMPAT
 
index f23d3c6fc2c06ea9766ec18a8580f1de5234975e..9b4f110949375c78b8fa1db830009e64ab3fbf73 100644 (file)
@@ -78,6 +78,7 @@ extern void __chk_io_ptr(void __iomem *);
 
 #endif /* __ASSEMBLY__ */
 
+#ifdef __KERNEL__
 /*
  * Allow us to mark functions as 'deprecated' and have gcc emit a nice
  * warning for each use, in hopes of speeding the functions removal.
@@ -127,6 +128,16 @@ extern void __chk_io_ptr(void __iomem *);
 # define __attribute_pure__    /* unimplemented */
 #endif
 
+#ifndef noinline
+#define noinline
+#endif
+
+#ifndef __always_inline
+#define __always_inline inline
+#endif
+
+#endif /* __KERNEL__ */
+
 /*
  * From the GCC manual:
  *
@@ -145,12 +156,4 @@ extern void __chk_io_ptr(void __iomem *);
 # define __attribute_const__   /* unimplemented */
 #endif
 
-#ifndef noinline
-#define noinline
-#endif
-
-#ifndef __always_inline
-#define __always_inline inline
-#endif
-
 #endif /* __LINUX_COMPILER_H */
index 721371382ae5ff1a55eace3ec867fc355b22c24a..08734e660d4182c11c9bc55a6a7e2632f1d3e917 100644 (file)
@@ -117,6 +117,10 @@ extern void console_stop(struct console *);
 extern void console_start(struct console *);
 extern int is_console_locked(void);
 
+/* Suspend and resume console messages over PM events */
+extern void suspend_console(void);
+extern void resume_console(void);
+
 /* Some debug stub to catch some of the obvious races in the VT code */
 #if 1
 #define WARN_CONSOLE_UNLOCKED()        WARN_ON(!is_console_locked() && !oops_in_progress)
index 17866d7e2b71ad08e12fc9340d5b77448032da48..5aa95011f7e641e5f5e7ebfc8228f4fca7b3322b 100644 (file)
@@ -15,7 +15,6 @@
 #define _LINUX_CPUFREQ_H
 
 #include <linux/mutex.h>
-#include <linux/config.h>
 #include <linux/notifier.h>
 #include <linux/threads.h>
 #include <linux/device.h>
index a8948f34b776f068a1d938e3a2403a5ca1e5eed0..a41f38428c37d794ac80f947502c4142123a4afc 100644 (file)
@@ -1,13 +1,7 @@
 #ifndef __CRAMFS_H
 #define __CRAMFS_H
 
-#ifndef __KERNEL__
-
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-
-#endif
+#include <linux/types.h>
 
 #define CRAMFS_MAGIC           0x28cd3d45      /* some random number */
 #define CRAMFS_SIGNATURE       "Compressed ROMFS"
@@ -33,9 +27,9 @@ typedef unsigned int u32;
  * Reasonably terse representation of the inode data.
  */
 struct cramfs_inode {
-       u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH;
+       __u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH;
        /* SIZE for device files is i_rdev */
-       u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH;
+       __u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH;
        /* NAMELEN is the length of the file name, divided by 4 and
            rounded up.  (cramfs doesn't support hard links.) */
        /* OFFSET: For symlinks and non-empty regular files, this
@@ -44,27 +38,27 @@ struct cramfs_inode {
           see README).  For non-empty directories it is the offset
           (divided by 4) of the inode of the first file in that
           directory.  For anything else, offset is zero. */
-       u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH;
+       __u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH;
 };
 
 struct cramfs_info {
-       u32 crc;
-       u32 edition;
-       u32 blocks;
-       u32 files;
+       __u32 crc;
+       __u32 edition;
+       __u32 blocks;
+       __u32 files;
 };
 
 /*
  * Superblock information at the beginning of the FS.
  */
 struct cramfs_super {
-       u32 magic;                      /* 0x28cd3d45 - random number */
-       u32 size;                       /* length in bytes */
-       u32 flags;                      /* feature flags */
-       u32 future;                     /* reserved for future use */
-       u8 signature[16];               /* "Compressed ROMFS" */
+       __u32 magic;                    /* 0x28cd3d45 - random number */
+       __u32 size;                     /* length in bytes */
+       __u32 flags;                    /* feature flags */
+       __u32 future;                   /* reserved for future use */
+       __u8 signature[16];             /* "Compressed ROMFS" */
        struct cramfs_info fsid;        /* unique filesystem info */
-       u8 name[16];                    /* user-defined name */
+       __u8 name[16];                  /* user-defined name */
        struct cramfs_inode root;       /* root inode data */
 };
 
index 0ab1bc1152cacba6734044b3f6d7eefe5237bb6e..5a0470e361111fe4ac7c389ca8573c3cc99972d3 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef _LINUX_CRYPTO_H
 #define _LINUX_CRYPTO_H
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
index 300d704bdb9a5416b781b955f0c7172a6451d269..b88f7f428e58c6590b5069127895ea3f85d4685a 100644 (file)
@@ -24,7 +24,6 @@
 * 1998/08/08   acme            Version 0.0.1
 */
 
-#include <linux/config.h>
 #include <linux/wanrouter.h>
 #include <linux/spinlock.h>
 
index 1d68428c925db1425ab43db4bd93b06ceca636b7..0fe7cdf326f735c0722ffc08443cbcf993991fca 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef DCOOKIES_H
 #define DCOOKIES_H
  
-#include <linux/config.h>
 
 #ifdef CONFIG_PROFILING
  
index 89810e73d2569a066b5680dd015c10a98626c030..0d74a6f22abcab3c5d31a71c938be0aaa143a3cd 100644 (file)
@@ -2,7 +2,6 @@
 #define _LINUX_DEVFS_FS_KERNEL_H
 
 #include <linux/fs.h>
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
index e8e53b9accc67345908ecbb27c947b6035438e4f..b2e5da2b637ba0b5db4775dabc3ec9de24dff3e9 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _DEVICE_H_
 #define _DEVICE_H_
 
-#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/kobject.h>
 #include <linux/klist.h>
index 6919b09133d47d704435cbf5b86412dd78264cd3..8fb4e9de6843f8694b17c26bfb487c8af733c8b8 100644 (file)
@@ -27,10 +27,10 @@ struct divert_blk
 {
        int             divert;  /* are we active */
        unsigned int protos;    /* protocols */
-       u16             tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */
-       u16             tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */
-       u16             udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */
-       u16             udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */
+       __u16           tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */
+       __u16           tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */
+       __u16           udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */
+       __u16           udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */
 };
 
 /*
@@ -40,12 +40,12 @@ struct divert_blk
 
 typedef union _divert_cf_arg
 {
-       s16             int16;
-       u16             uint16;
-       s32             int32;
-       u32             uint32;
-       s64             int64;
-       u64             uint64;
+       __s16           int16;
+       __u16           uint16;
+       __s32           int32;
+       __u32           uint32;
+       __s64           int64;
+       __u64           uint64;
        void    __user *ptr;
 } divert_cf_arg;
 
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
new file mode 100644 (file)
index 0000000..78b236c
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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 COPYING.
+ */
+#ifndef DMAENGINE_H
+#define DMAENGINE_H
+#include <linux/config.h>
+#ifdef CONFIG_DMA_ENGINE
+
+#include <linux/device.h>
+#include <linux/uio.h>
+#include <linux/kref.h>
+#include <linux/completion.h>
+#include <linux/rcupdate.h>
+
+/**
+ * enum dma_event - resource PNP/power managment events
+ * @DMA_RESOURCE_SUSPEND: DMA device going into low power state
+ * @DMA_RESOURCE_RESUME: DMA device returning to full power
+ * @DMA_RESOURCE_ADDED: DMA device added to the system
+ * @DMA_RESOURCE_REMOVED: DMA device removed from the system
+ */
+enum dma_event {
+       DMA_RESOURCE_SUSPEND,
+       DMA_RESOURCE_RESUME,
+       DMA_RESOURCE_ADDED,
+       DMA_RESOURCE_REMOVED,
+};
+
+/**
+ * typedef dma_cookie_t
+ *
+ * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code
+ */
+typedef s32 dma_cookie_t;
+
+#define dma_submit_error(cookie) ((cookie) < 0 ? 1 : 0)
+
+/**
+ * enum dma_status - DMA transaction status
+ * @DMA_SUCCESS: transaction completed successfully
+ * @DMA_IN_PROGRESS: transaction not yet processed
+ * @DMA_ERROR: transaction failed
+ */
+enum dma_status {
+       DMA_SUCCESS,
+       DMA_IN_PROGRESS,
+       DMA_ERROR,
+};
+
+/**
+ * struct dma_chan_percpu - the per-CPU part of struct dma_chan
+ * @refcount: local_t used for open-coded "bigref" counting
+ * @memcpy_count: transaction counter
+ * @bytes_transferred: byte counter
+ */
+
+struct dma_chan_percpu {
+       local_t refcount;
+       /* stats */
+       unsigned long memcpy_count;
+       unsigned long bytes_transferred;
+};
+
+/**
+ * struct dma_chan - devices supply DMA channels, clients use them
+ * @client: ptr to the client user of this chan, will be NULL when unused
+ * @device: ptr to the dma device who supplies this channel, always !NULL
+ * @cookie: last cookie value returned to client
+ * @chan_id:
+ * @class_dev:
+ * @refcount: kref, used in "bigref" slow-mode
+ * @slow_ref:
+ * @rcu:
+ * @client_node: used to add this to the client chan list
+ * @device_node: used to add this to the device chan list
+ * @local: per-cpu pointer to a struct dma_chan_percpu
+ */
+struct dma_chan {
+       struct dma_client *client;
+       struct dma_device *device;
+       dma_cookie_t cookie;
+
+       /* sysfs */
+       int chan_id;
+       struct class_device class_dev;
+
+       struct kref refcount;
+       int slow_ref;
+       struct rcu_head rcu;
+
+       struct list_head client_node;
+       struct list_head device_node;
+       struct dma_chan_percpu *local;
+};
+
+void dma_chan_cleanup(struct kref *kref);
+
+static inline void dma_chan_get(struct dma_chan *chan)
+{
+       if (unlikely(chan->slow_ref))
+               kref_get(&chan->refcount);
+       else {
+               local_inc(&(per_cpu_ptr(chan->local, get_cpu())->refcount));
+               put_cpu();
+       }
+}
+
+static inline void dma_chan_put(struct dma_chan *chan)
+{
+       if (unlikely(chan->slow_ref))
+               kref_put(&chan->refcount, dma_chan_cleanup);
+       else {
+               local_dec(&(per_cpu_ptr(chan->local, get_cpu())->refcount));
+               put_cpu();
+       }
+}
+
+/*
+ * typedef dma_event_callback - function pointer to a DMA event callback
+ */
+typedef void (*dma_event_callback) (struct dma_client *client,
+               struct dma_chan *chan, enum dma_event event);
+
+/**
+ * struct dma_client - info on the entity making use of DMA services
+ * @event_callback: func ptr to call when something happens
+ * @chan_count: number of chans allocated
+ * @chans_desired: number of chans requested. Can be +/- chan_count
+ * @lock: protects access to the channels list
+ * @channels: the list of DMA channels allocated
+ * @global_node: list_head for global dma_client_list
+ */
+struct dma_client {
+       dma_event_callback      event_callback;
+       unsigned int            chan_count;
+       unsigned int            chans_desired;
+
+       spinlock_t              lock;
+       struct list_head        channels;
+       struct list_head        global_node;
+};
+
+/**
+ * struct dma_device - info on the entity supplying DMA services
+ * @chancnt: how many DMA channels are supported
+ * @channels: the list of struct dma_chan
+ * @global_node: list_head for global dma_device_list
+ * @refcount:
+ * @done:
+ * @dev_id:
+ * Other func ptrs: used to make use of this device's capabilities
+ */
+struct dma_device {
+
+       unsigned int chancnt;
+       struct list_head channels;
+       struct list_head global_node;
+
+       struct kref refcount;
+       struct completion done;
+
+       int dev_id;
+
+       int (*device_alloc_chan_resources)(struct dma_chan *chan);
+       void (*device_free_chan_resources)(struct dma_chan *chan);
+       dma_cookie_t (*device_memcpy_buf_to_buf)(struct dma_chan *chan,
+                       void *dest, void *src, size_t len);
+       dma_cookie_t (*device_memcpy_buf_to_pg)(struct dma_chan *chan,
+                       struct page *page, unsigned int offset, void *kdata,
+                       size_t len);
+       dma_cookie_t (*device_memcpy_pg_to_pg)(struct dma_chan *chan,
+                       struct page *dest_pg, unsigned int dest_off,
+                       struct page *src_pg, unsigned int src_off, size_t len);
+       enum dma_status (*device_memcpy_complete)(struct dma_chan *chan,
+                       dma_cookie_t cookie, dma_cookie_t *last,
+                       dma_cookie_t *used);
+       void (*device_memcpy_issue_pending)(struct dma_chan *chan);
+};
+
+/* --- public DMA engine API --- */
+
+struct dma_client *dma_async_client_register(dma_event_callback event_callback);
+void dma_async_client_unregister(struct dma_client *client);
+void dma_async_client_chan_request(struct dma_client *client,
+               unsigned int number);
+
+/**
+ * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
+ * @chan: DMA channel to offload copy to
+ * @dest: destination address (virtual)
+ * @src: source address (virtual)
+ * @len: length
+ *
+ * Both @dest and @src must be mappable to a bus address according to the
+ * DMA mapping API rules for streaming mappings.
+ * Both @dest and @src must stay memory resident (kernel memory or locked
+ * user space pages)
+ */
+static inline dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
+       void *dest, void *src, size_t len)
+{
+       int cpu = get_cpu();
+       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+       put_cpu();
+
+       return chan->device->device_memcpy_buf_to_buf(chan, dest, src, len);
+}
+
+/**
+ * dma_async_memcpy_buf_to_pg - offloaded copy
+ * @chan: DMA channel to offload copy to
+ * @page: destination page
+ * @offset: offset in page to copy to
+ * @kdata: source address (virtual)
+ * @len: length
+ *
+ * Both @page/@offset and @kdata must be mappable to a bus address according
+ * to the DMA mapping API rules for streaming mappings.
+ * Both @page/@offset and @kdata must stay memory resident (kernel memory or
+ * locked user space pages)
+ */
+static inline dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
+       struct page *page, unsigned int offset, void *kdata, size_t len)
+{
+       int cpu = get_cpu();
+       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+       put_cpu();
+
+       return chan->device->device_memcpy_buf_to_pg(chan, page, offset,
+                                                    kdata, len);
+}
+
+/**
+ * dma_async_memcpy_buf_to_pg - offloaded copy
+ * @chan: DMA channel to offload copy to
+ * @dest_page: destination page
+ * @dest_off: offset in page to copy to
+ * @src_page: source page
+ * @src_off: offset in page to copy from
+ * @len: length
+ *
+ * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
+ * address according to the DMA mapping API rules for streaming mappings.
+ * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
+ * (kernel memory or locked user space pages)
+ */
+static inline dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
+       struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
+       unsigned int src_off, size_t len)
+{
+       int cpu = get_cpu();
+       per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+       per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+       put_cpu();
+
+       return chan->device->device_memcpy_pg_to_pg(chan, dest_pg, dest_off,
+                                                   src_pg, src_off, len);
+}
+
+/**
+ * dma_async_memcpy_issue_pending - flush pending copies to HW
+ * @chan:
+ *
+ * This allows drivers to push copies to HW in batches,
+ * reducing MMIO writes where possible.
+ */
+static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
+{
+       return chan->device->device_memcpy_issue_pending(chan);
+}
+
+/**
+ * dma_async_memcpy_complete - poll for transaction completion
+ * @chan: DMA channel
+ * @cookie: transaction identifier to check status of
+ * @last: returns last completed cookie, can be NULL
+ * @used: returns last issued cookie, can be NULL
+ *
+ * If @last and @used are passed in, upon return they reflect the driver
+ * internal state and can be used with dma_async_is_complete() to check
+ * the status of multiple cookies without re-checking hardware state.
+ */
+static inline enum dma_status dma_async_memcpy_complete(struct dma_chan *chan,
+       dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+{
+       return chan->device->device_memcpy_complete(chan, cookie, last, used);
+}
+
+/**
+ * dma_async_is_complete - test a cookie against chan state
+ * @cookie: transaction identifier to test status of
+ * @last_complete: last know completed transaction
+ * @last_used: last cookie value handed out
+ *
+ * dma_async_is_complete() is used in dma_async_memcpy_complete()
+ * the test logic is seperated for lightweight testing of multiple cookies
+ */
+static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie,
+                       dma_cookie_t last_complete, dma_cookie_t last_used)
+{
+       if (last_complete <= last_used) {
+               if ((cookie <= last_complete) || (cookie > last_used))
+                       return DMA_SUCCESS;
+       } else {
+               if ((cookie <= last_complete) && (cookie > last_used))
+                       return DMA_SUCCESS;
+       }
+       return DMA_IN_PROGRESS;
+}
+
+
+/* --- DMA device --- */
+
+int dma_async_device_register(struct dma_device *device);
+void dma_async_device_unregister(struct dma_device *device);
+
+/* --- Helper iov-locking functions --- */
+
+struct dma_page_list {
+       char *base_address;
+       int nr_pages;
+       struct page **pages;
+};
+
+struct dma_pinned_list {
+       int nr_iovecs;
+       struct dma_page_list page_list[0];
+};
+
+struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len);
+void dma_unpin_iovec_pages(struct dma_pinned_list* pinned_list);
+
+dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov,
+       struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len);
+dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov,
+       struct dma_pinned_list *pinned_list, struct page *page,
+       unsigned int offset, size_t len);
+
+#endif /* CONFIG_DMA_ENGINE */
+#endif /* DMAENGINE_H */
index 64fd6c366604c08e4b7f53a2322cf731bba340ab..b2cd2071d432d137b8d913134c21b0b93a920b25 100644 (file)
@@ -2,7 +2,6 @@
 #define __DMI_H__
 
 #include <linux/list.h>
-#include <linux/config.h>
 
 enum dmi_field {
        DMI_NONE,
index f134a01975c7342fa42b1a986b2d9d5aee86bd98..102a902b43963e2de2ba8862931b80508f9ae9d5 100644 (file)
@@ -18,7 +18,6 @@ struct dnotify_struct {
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DNOTIFY
 
index ad133fcfb239ddbf16e6961e88f47161e8d1447e..1713ace808bfb4d581ccfff53aa4b0c42ebfa9ef 100644 (file)
@@ -21,7 +21,7 @@ typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
 typedef void (elevator_activate_req_fn) (request_queue_t *, struct request *);
 typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
 
-typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
+typedef void *(elevator_init_fn) (request_queue_t *, elevator_t *);
 typedef void (elevator_exit_fn) (elevator_t *);
 
 struct elevator_ops
diff --git a/include/linux/elf-em.h b/include/linux/elf-em.h
new file mode 100644 (file)
index 0000000..114a96d
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _LINUX_ELF_EM_H
+#define _LINUX_ELF_EM_H
+
+/* These constants define the various ELF target machines */
+#define EM_NONE                0
+#define EM_M32         1
+#define EM_SPARC       2
+#define EM_386         3
+#define EM_68K         4
+#define EM_88K         5
+#define EM_486         6       /* Perhaps disused */
+#define EM_860         7
+#define EM_MIPS                8       /* MIPS R3000 (officially, big-endian only) */
+#define EM_MIPS_RS4_BE 10      /* MIPS R4000 big-endian */
+#define EM_PARISC      15      /* HPPA */
+#define EM_SPARC32PLUS 18      /* Sun's "v8plus" */
+#define EM_PPC         20      /* PowerPC */
+#define EM_PPC64       21       /* PowerPC64 */
+#define EM_SH          42      /* SuperH */
+#define EM_SPARCV9     43      /* SPARC v9 64-bit */
+#define EM_IA_64       50      /* HP/Intel IA-64 */
+#define EM_X86_64      62      /* AMD x86-64 */
+#define EM_S390                22      /* IBM S/390 */
+#define EM_CRIS                76      /* Axis Communications 32-bit embedded processor */
+#define EM_V850                87      /* NEC v850 */
+#define EM_M32R                88      /* Renesas M32R */
+#define EM_H8_300      46      /* Renesas H8/300,300H,H8S */
+#define EM_FRV         0x5441  /* Fujitsu FR-V */
+
+/*
+ * This is an interim value that we will use until the committee comes
+ * up with a final number.
+ */
+#define EM_ALPHA       0x9026
+
+/* Bogus old v850 magic number, used by old tools. */
+#define EM_CYGNUS_V850 0x9080
+/* Bogus old m32r magic number, used by old tools. */
+#define EM_CYGNUS_M32R 0x9041
+/* This is the old interim value for S/390 architecture */
+#define EM_S390_OLD    0xA390
+
+
+#endif /* _LINUX_ELF_EM_H */
index d3bfacb2449642f751e182977c23e482b85a8ab8..b70d1d2c8d2859cf82c8b39435e40a126cf3b8a9 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <linux/auxvec.h>
+#include <linux/elf-em.h>
 #include <asm/elf.h>
 
 #ifndef elf_read_implies_exec
@@ -55,64 +56,6 @@ typedef __s64        Elf64_Sxword;
 #define ET_LOPROC 0xff00
 #define ET_HIPROC 0xffff
 
-/* These constants define the various ELF target machines */
-#define EM_NONE  0
-#define EM_M32   1
-#define EM_SPARC 2
-#define EM_386   3
-#define EM_68K   4
-#define EM_88K   5
-#define EM_486   6   /* Perhaps disused */
-#define EM_860   7
-
-#define EM_MIPS                8       /* MIPS R3000 (officially, big-endian only) */
-
-#define EM_MIPS_RS4_BE 10      /* MIPS R4000 big-endian */
-
-#define EM_PARISC      15      /* HPPA */
-
-#define EM_SPARC32PLUS 18      /* Sun's "v8plus" */
-
-#define EM_PPC        20       /* PowerPC */
-#define EM_PPC64       21       /* PowerPC64 */
-
-#define EM_SH         42       /* SuperH */
-
-#define EM_SPARCV9     43      /* SPARC v9 64-bit */
-
-#define EM_IA_64       50      /* HP/Intel IA-64 */
-
-#define EM_X86_64      62      /* AMD x86-64 */
-
-#define EM_S390                22      /* IBM S/390 */
-
-#define EM_CRIS         76      /* Axis Communications 32-bit embedded processor */
-
-#define EM_V850                87      /* NEC v850 */
-
-#define EM_M32R                88      /* Renesas M32R */
-
-#define EM_H8_300       46      /* Renesas H8/300,300H,H8S */
-
-/*
- * This is an interim value that we will use until the committee comes
- * up with a final number.
- */
-#define EM_ALPHA       0x9026
-
-/* Bogus old v850 magic number, used by old tools.  */
-#define EM_CYGNUS_V850 0x9080
-
-/* Bogus old m32r magic number, used by old tools.  */
-#define EM_CYGNUS_M32R 0x9041
-
-/*
- * This is the old interim value for S/390 architecture
- */
-#define EM_S390_OLD     0xA390
-
-#define EM_FRV         0x5441          /* Fujitsu FR-V */
-
 /* This is the info that is needed to parse the dynamic section of the file */
 #define DT_NULL                0
 #define DT_NEEDED      1
index 174582fedb8b01825f4444e5f8cf4ea86c2ef93c..408118a07763fecc3718d8dcc6569857d3aa52e4 100644 (file)
@@ -21,7 +21,6 @@ struct sock_extended_err
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <net/ip.h>
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 #include <linux/ipv6.h>
index 93535f0932167818e5e7e9c168188cbed0626df9..cf2abeca92a09679aaee30379853926ceed2342d 100644 (file)
 
 /* This should work for both 32 and 64 bit userland. */
 struct ethtool_cmd {
-       u32     cmd;
-       u32     supported;      /* Features this interface supports */
-       u32     advertising;    /* Features this interface advertises */
-       u16     speed;          /* The forced speed, 10Mb, 100Mb, gigabit */
-       u8      duplex;         /* Duplex, half or full */
-       u8      port;           /* Which connector port */
-       u8      phy_address;
-       u8      transceiver;    /* Which transceiver to use */
-       u8      autoneg;        /* Enable or disable autonegotiation */
-       u32     maxtxpkt;       /* Tx pkts before generating tx int */
-       u32     maxrxpkt;       /* Rx pkts before generating rx int */
-       u32     reserved[4];
+       __u32   cmd;
+       __u32   supported;      /* Features this interface supports */
+       __u32   advertising;    /* Features this interface advertises */
+       __u16   speed;          /* The forced speed, 10Mb, 100Mb, gigabit */
+       __u8    duplex;         /* Duplex, half or full */
+       __u8    port;           /* Which connector port */
+       __u8    phy_address;
+       __u8    transceiver;    /* Which transceiver to use */
+       __u8    autoneg;        /* Enable or disable autonegotiation */
+       __u32   maxtxpkt;       /* Tx pkts before generating tx int */
+       __u32   maxrxpkt;       /* Rx pkts before generating rx int */
+       __u32   reserved[4];
 };
 
 #define ETHTOOL_BUSINFO_LEN    32
 /* these strings are set to whatever the driver author decides... */
 struct ethtool_drvinfo {
-       u32     cmd;
+       __u32   cmd;
        char    driver[32];     /* driver short name, "tulip", "eepro100" */
        char    version[32];    /* driver version string */
        char    fw_version[32]; /* firmware version string, if applicable */
@@ -40,53 +40,53 @@ struct ethtool_drvinfo {
                                /* For PCI devices, use pci_name(pci_dev). */
        char    reserved1[32];
        char    reserved2[16];
-       u32     n_stats;        /* number of u64's from ETHTOOL_GSTATS */
-       u32     testinfo_len;
-       u32     eedump_len;     /* Size of data from ETHTOOL_GEEPROM (bytes) */
-       u32     regdump_len;    /* Size of data from ETHTOOL_GREGS (bytes) */
+       __u32   n_stats;        /* number of u64's from ETHTOOL_GSTATS */
+       __u32   testinfo_len;
+       __u32   eedump_len;     /* Size of data from ETHTOOL_GEEPROM (bytes) */
+       __u32   regdump_len;    /* Size of data from ETHTOOL_GREGS (bytes) */
 };
 
 #define SOPASS_MAX     6
 /* wake-on-lan settings */
 struct ethtool_wolinfo {
-       u32     cmd;
-       u32     supported;
-       u32     wolopts;
-       u8      sopass[SOPASS_MAX]; /* SecureOn(tm) password */
+       __u32   cmd;
+       __u32   supported;
+       __u32   wolopts;
+       __u8    sopass[SOPASS_MAX]; /* SecureOn(tm) password */
 };
 
 /* for passing single values */
 struct ethtool_value {
-       u32     cmd;
-       u32     data;
+       __u32   cmd;
+       __u32   data;
 };
 
 /* for passing big chunks of data */
 struct ethtool_regs {
-       u32     cmd;
-       u32     version; /* driver-specific, indicates different chips/revs */
-       u32     len; /* bytes */
-       u8      data[0];
+       __u32   cmd;
+       __u32   version; /* driver-specific, indicates different chips/revs */
+       __u32   len; /* bytes */
+       __u8    data[0];
 };
 
 /* for passing EEPROM chunks */
 struct ethtool_eeprom {
-       u32     cmd;
-       u32     magic;
-       u32     offset; /* in bytes */
-       u32     len; /* in bytes */
-       u8      data[0];
+       __u32   cmd;
+       __u32   magic;
+       __u32   offset; /* in bytes */
+       __u32   len; /* in bytes */
+       __u8    data[0];
 };
 
 /* for configuring coalescing parameters of chip */
 struct ethtool_coalesce {
-       u32     cmd;    /* ETHTOOL_{G,S}COALESCE */
+       __u32   cmd;    /* ETHTOOL_{G,S}COALESCE */
 
        /* How many usecs to delay an RX interrupt after
         * a packet arrives.  If 0, only rx_max_coalesced_frames
         * is used.
         */
-       u32     rx_coalesce_usecs;
+       __u32   rx_coalesce_usecs;
 
        /* How many packets to delay an RX interrupt after
         * a packet arrives.  If 0, only rx_coalesce_usecs is
@@ -94,21 +94,21 @@ struct ethtool_coalesce {
         * to zero as this would cause RX interrupts to never be
         * generated.
         */
-       u32     rx_max_coalesced_frames;
+       __u32   rx_max_coalesced_frames;
 
        /* Same as above two parameters, except that these values
         * apply while an IRQ is being serviced by the host.  Not
         * all cards support this feature and the values are ignored
         * in that case.
         */
-       u32     rx_coalesce_usecs_irq;
-       u32     rx_max_coalesced_frames_irq;
+       __u32   rx_coalesce_usecs_irq;
+       __u32   rx_max_coalesced_frames_irq;
 
        /* How many usecs to delay a TX interrupt after
         * a packet is sent.  If 0, only tx_max_coalesced_frames
         * is used.
         */
-       u32     tx_coalesce_usecs;
+       __u32   tx_coalesce_usecs;
 
        /* How many packets to delay a TX interrupt after
         * a packet is sent.  If 0, only tx_coalesce_usecs is
@@ -116,22 +116,22 @@ struct ethtool_coalesce {
         * to zero as this would cause TX interrupts to never be
         * generated.
         */
-       u32     tx_max_coalesced_frames;
+       __u32   tx_max_coalesced_frames;
 
        /* Same as above two parameters, except that these values
         * apply while an IRQ is being serviced by the host.  Not
         * all cards support this feature and the values are ignored
         * in that case.
         */
-       u32     tx_coalesce_usecs_irq;
-       u32     tx_max_coalesced_frames_irq;
+       __u32   tx_coalesce_usecs_irq;
+       __u32   tx_max_coalesced_frames_irq;
 
        /* How many usecs to delay in-memory statistics
         * block updates.  Some drivers do not have an in-memory
         * statistic block, and in such cases this value is ignored.
         * This value must not be zero.
         */
-       u32     stats_block_coalesce_usecs;
+       __u32   stats_block_coalesce_usecs;
 
        /* Adaptive RX/TX coalescing is an algorithm implemented by
         * some drivers to improve latency under low packet rates and
@@ -140,18 +140,18 @@ struct ethtool_coalesce {
         * not implemented by the driver causes these values to be
         * silently ignored.
         */
-       u32     use_adaptive_rx_coalesce;
-       u32     use_adaptive_tx_coalesce;
+       __u32   use_adaptive_rx_coalesce;
+       __u32   use_adaptive_tx_coalesce;
 
        /* When the packet rate (measured in packets per second)
         * is below pkt_rate_low, the {rx,tx}_*_low parameters are
         * used.
         */
-       u32     pkt_rate_low;
-       u32     rx_coalesce_usecs_low;
-       u32     rx_max_coalesced_frames_low;
-       u32     tx_coalesce_usecs_low;
-       u32     tx_max_coalesced_frames_low;
+       __u32   pkt_rate_low;
+       __u32   rx_coalesce_usecs_low;
+       __u32   rx_max_coalesced_frames_low;
+       __u32   tx_coalesce_usecs_low;
+       __u32   tx_max_coalesced_frames_low;
 
        /* When the packet rate is below pkt_rate_high but above
         * pkt_rate_low (both measured in packets per second) the
@@ -162,43 +162,43 @@ struct ethtool_coalesce {
         * is above pkt_rate_high, the {rx,tx}_*_high parameters are
         * used.
         */
-       u32     pkt_rate_high;
-       u32     rx_coalesce_usecs_high;
-       u32     rx_max_coalesced_frames_high;
-       u32     tx_coalesce_usecs_high;
-       u32     tx_max_coalesced_frames_high;
+       __u32   pkt_rate_high;
+       __u32   rx_coalesce_usecs_high;
+       __u32   rx_max_coalesced_frames_high;
+       __u32   tx_coalesce_usecs_high;
+       __u32   tx_max_coalesced_frames_high;
 
        /* How often to do adaptive coalescing packet rate sampling,
         * measured in seconds.  Must not be zero.
         */
-       u32     rate_sample_interval;
+       __u32   rate_sample_interval;
 };
 
 /* for configuring RX/TX ring parameters */
 struct ethtool_ringparam {
-       u32     cmd;    /* ETHTOOL_{G,S}RINGPARAM */
+       __u32   cmd;    /* ETHTOOL_{G,S}RINGPARAM */
 
        /* Read only attributes.  These indicate the maximum number
         * of pending RX/TX ring entries the driver will allow the
         * user to set.
         */
-       u32     rx_max_pending;
-       u32     rx_mini_max_pending;
-       u32     rx_jumbo_max_pending;
-       u32     tx_max_pending;
+       __u32   rx_max_pending;
+       __u32   rx_mini_max_pending;
+       __u32   rx_jumbo_max_pending;
+       __u32   tx_max_pending;
 
        /* Values changeable by the user.  The valid values are
         * in the range 1 to the "*_max_pending" counterpart above.
         */
-       u32     rx_pending;
-       u32     rx_mini_pending;
-       u32     rx_jumbo_pending;
-       u32     tx_pending;
+       __u32   rx_pending;
+       __u32   rx_mini_pending;
+       __u32   rx_jumbo_pending;
+       __u32   tx_pending;
 };
 
 /* for configuring link flow control parameters */
 struct ethtool_pauseparam {
-       u32     cmd;    /* ETHTOOL_{G,S}PAUSEPARAM */
+       __u32   cmd;    /* ETHTOOL_{G,S}PAUSEPARAM */
 
        /* If the link is being auto-negotiated (via ethtool_cmd.autoneg
         * being true) the user may set 'autonet' here non-zero to have the
@@ -210,9 +210,9 @@ struct ethtool_pauseparam {
         * then {rx,tx}_pause force the driver to use/not-use pause
         * flow control.
         */
-       u32     autoneg;
-       u32     rx_pause;
-       u32     tx_pause;
+       __u32   autoneg;
+       __u32   rx_pause;
+       __u32   tx_pause;
 };
 
 #define ETH_GSTRING_LEN                32
@@ -223,10 +223,10 @@ enum ethtool_stringset {
 
 /* for passing string sets for data tagging */
 struct ethtool_gstrings {
-       u32     cmd;            /* ETHTOOL_GSTRINGS */
-       u32     string_set;     /* string set id e.c. ETH_SS_TEST, etc*/
-       u32     len;            /* number of strings in the string set */
-       u8      data[0];
+       __u32   cmd;            /* ETHTOOL_GSTRINGS */
+       __u32   string_set;     /* string set id e.c. ETH_SS_TEST, etc*/
+       __u32   len;            /* number of strings in the string set */
+       __u8    data[0];
 };
 
 enum ethtool_test_flags {
@@ -236,26 +236,28 @@ enum ethtool_test_flags {
 
 /* for requesting NIC test and getting results*/
 struct ethtool_test {
-       u32     cmd;            /* ETHTOOL_TEST */
-       u32     flags;          /* ETH_TEST_FL_xxx */
-       u32     reserved;
-       u32     len;            /* result length, in number of u64 elements */
-       u64     data[0];
+       __u32   cmd;            /* ETHTOOL_TEST */
+       __u32   flags;          /* ETH_TEST_FL_xxx */
+       __u32   reserved;
+       __u32   len;            /* result length, in number of u64 elements */
+       __u64   data[0];
 };
 
 /* for dumping NIC-specific statistics */
 struct ethtool_stats {
-       u32     cmd;            /* ETHTOOL_GSTATS */
-       u32     n_stats;        /* number of u64's being returned */
-       u64     data[0];
+       __u32   cmd;            /* ETHTOOL_GSTATS */
+       __u32   n_stats;        /* number of u64's being returned */
+       __u64   data[0];
 };
 
 struct ethtool_perm_addr {
-       u32     cmd;            /* ETHTOOL_GPERMADDR */
-       u32     size;
-       u8      data[0];
+       __u32   cmd;            /* ETHTOOL_GPERMADDR */
+       __u32   size;
+       __u8    data[0];
 };
 
+#ifdef __KERNEL__
+
 struct net_device;
 
 /* Some generic methods drivers may use in their ethtool_ops */
@@ -371,6 +373,7 @@ struct ethtool_ops {
        u32     (*get_ufo)(struct net_device *);
        int     (*set_ufo)(struct net_device *, u32);
 };
+#endif /* __KERNEL__ */
 
 /* CMDs currently supported */
 #define ETHTOOL_GSET           0x00000001 /* Get settings. */
index f7bd1c7ebefbd2a116c4970608b6cfb3c341bf90..facf34e9895463a35c04ecfb56bd577866c45370 100644 (file)
@@ -17,7 +17,6 @@
 #define _LINUX_EXT2_FS_H
 
 #include <linux/types.h>
-#include <linux/ext2_fs_sb.h>
 
 /*
  * The second extended filesystem constants/structures
@@ -70,6 +69,7 @@
 #define EXT2_SUPER_MAGIC       0xEF53
 
 #ifdef __KERNEL__
+#include <linux/ext2_fs_sb.h>
 static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb)
 {
        return sb->s_fs_info;
index 3ade6a4e3bdd7233cfddfe02f0f1494dcc6616d3..757d54d8f1a58f3a15c5467df00438b5f9d6e075 100644 (file)
 #define _LINUX_EXT3_FS_H
 
 #include <linux/types.h>
-#include <linux/ext3_fs_i.h>
-#include <linux/ext3_fs_sb.h>
-
-
-struct statfs;
 
 /*
  * The second extended filesystem constants/structures
@@ -487,6 +482,8 @@ struct ext3_super_block {
 };
 
 #ifdef __KERNEL__
+#include <linux/ext3_fs_i.h>
+#include <linux/ext3_fs_sb.h>
 static inline struct ext3_sb_info * EXT3_SB(struct super_block *sb)
 {
        return sb->s_fs_info;
@@ -664,6 +661,8 @@ struct ext3_dir_entry_2 {
 #define DX_HASH_HALF_MD4       1
 #define DX_HASH_TEA            2
 
+#ifdef __KERNEL__
+
 /* hash info structure used by the directory hash */
 struct dx_hash_info
 {
@@ -675,7 +674,6 @@ struct dx_hash_info
 
 #define EXT3_HTREE_EOF 0x7fffffff
 
-#ifdef __KERNEL__
 /*
  * Control parameters used by ext3_htree_next_block
  */
index f813bc8266aa592455caba8d264b90419544c5cc..ecc8c2c3d8ca8382d5b121c7219d9f73b33baba4 100644 (file)
@@ -6,7 +6,6 @@
  * structures etc.
  */
 
-#include <linux/config.h>
 #include <linux/limits.h>
 #include <linux/ioctl.h>
 
index 11438eff4d4455573f76789edfd5ffb0cc646473..cc5dec70c32c216f72d238c600ae64f577407e86 100644 (file)
@@ -54,19 +54,20 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
 
        if (isdir)
                isdir = IN_ISDIR;
-       inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name);
-       inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name);
+       inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name,
+                                 source);
+       inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name,
+                                 source);
 
        if (target) {
-               inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL);
+               inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL, NULL);
                inotify_inode_is_dead(target);
        }
 
        if (source) {
-               inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL);
+               inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
        }
-       audit_inode_child(old_name, source, old_dir->i_ino);
-       audit_inode_child(new_name, target, new_dir->i_ino);
+       audit_inode_child(new_name, source, new_dir->i_ino);
 }
 
 /*
@@ -85,7 +86,7 @@ static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
  */
 static inline void fsnotify_inoderemove(struct inode *inode)
 {
-       inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
+       inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL, NULL);
        inotify_inode_is_dead(inode);
 }
 
@@ -95,7 +96,8 @@ static inline void fsnotify_inoderemove(struct inode *inode)
 static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
 {
        inode_dir_notify(inode, DN_CREATE);
-       inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name);
+       inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name,
+                                 dentry->d_inode);
        audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
 }
 
@@ -106,7 +108,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
 {
        inode_dir_notify(inode, DN_CREATE);
        inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, 
-                                 dentry->d_name.name);
+                                 dentry->d_name.name, dentry->d_inode);
        audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
 }
 
@@ -123,7 +125,7 @@ static inline void fsnotify_access(struct dentry *dentry)
 
        dnotify_parent(dentry, DN_ACCESS);
        inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-       inotify_inode_queue_event(inode, mask, 0, NULL);
+       inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -139,7 +141,7 @@ static inline void fsnotify_modify(struct dentry *dentry)
 
        dnotify_parent(dentry, DN_MODIFY);
        inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-       inotify_inode_queue_event(inode, mask, 0, NULL);
+       inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -154,7 +156,7 @@ static inline void fsnotify_open(struct dentry *dentry)
                mask |= IN_ISDIR;
 
        inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-       inotify_inode_queue_event(inode, mask, 0, NULL);        
+       inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -172,7 +174,7 @@ static inline void fsnotify_close(struct file *file)
                mask |= IN_ISDIR;
 
        inotify_dentry_parent_queue_event(dentry, mask, 0, name);
-       inotify_inode_queue_event(inode, mask, 0, NULL);
+       inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -187,7 +189,7 @@ static inline void fsnotify_xattr(struct dentry *dentry)
                mask |= IN_ISDIR;
 
        inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-       inotify_inode_queue_event(inode, mask, 0, NULL);
+       inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -234,7 +236,7 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
        if (in_mask) {
                if (S_ISDIR(inode->i_mode))
                        in_mask |= IN_ISDIR;
-               inotify_inode_queue_event(inode, in_mask, 0, NULL);
+               inotify_inode_queue_event(inode, in_mask, 0, NULL, NULL);
                inotify_dentry_parent_queue_event(dentry, in_mask, 0,
                                                  dentry->d_name.name);
        }
index 72faeec9f6e11d37b7ffd61ef80281209bfbf211..7e7038cba86a880a84cd2420d862ddadc7d40c3e 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/mm.h>
 #endif
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/mtio.h>
 
 #define FT_SECTOR(x)           (x+1)   /* sector offset into real sector */
index 71e7b2847cb30e3842b8a3ce9eb61bbf6b53e8d6..2cdba0c2395707184544ee755e9a5f9ddefbe9a1 100644 (file)
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  */
 
+#ifdef __KERNEL__
 #include <asm/io.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
@@ -154,6 +155,8 @@ static inline void gameport_register_driver(struct gameport_driver *drv)
 
 void gameport_unregister_driver(struct gameport_driver *drv);
 
+#endif /* __KERNEL__ */
+
 #define GAMEPORT_MODE_DISABLED         0
 #define GAMEPORT_MODE_RAW              1
 #define GAMEPORT_MODE_COOKED           2
@@ -169,6 +172,8 @@ void gameport_unregister_driver(struct gameport_driver *drv);
 #define GAMEPORT_ID_VENDOR_GRAVIS      0x0009
 #define GAMEPORT_ID_VENDOR_GUILLEMOT   0x000a
 
+#ifdef __KERNEL__
+
 static inline void gameport_trigger(struct gameport *gameport)
 {
        if (gameport->trigger)
@@ -219,4 +224,5 @@ static inline void gameport_set_poll_interval(struct gameport *gameport, unsigne
 void gameport_start_polling(struct gameport *gameport);
 void gameport_stop_polling(struct gameport *gameport);
 
+#endif /* __KERNEL__ */
 #endif
index 652611a4bdcd1ea05aa0bcd6e6a2d9d1a2a39da7..e2538456195568141da767ace0da9ec5abe08a3d 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef GENERIC_SERIAL_H
 #define GENERIC_SERIAL_H
 
+#ifdef __KERNEL__
 #include <linux/mutex.h>
 
 struct real_driver {
@@ -54,6 +55,7 @@ struct gs_port {
   spinlock_t              driver_lock;
 };
 
+#endif /* __KERNEL__ */
 
 /* Flags */
 /* Warning: serial.h defines some ASYNC_ flags, they say they are "only"
@@ -75,7 +77,7 @@ struct gs_port {
 #define GS_DEBUG_FLOW    0x00000020
 #define GS_DEBUG_WRITE   0x00000040
 
-
+#ifdef __KERNEL__
 void gs_put_char(struct tty_struct *tty, unsigned char ch);
 int  gs_write(struct tty_struct *tty, 
              const unsigned char *buf, int count);
@@ -94,5 +96,5 @@ 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);
 void gs_got_break(struct gs_port *port);
-
+#endif /* __KERNEL__ */
 #endif
index 2ef845b35175815b8823e35bf6c23723725c13d3..3498a0c6818441cb9a81f6e329dac5fa8b03f7e3 100644 (file)
@@ -9,13 +9,7 @@
  *             <drew@colorado.edu>
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
-#include <linux/major.h>
-#include <linux/device.h>
-#include <linux/smp.h>
-#include <linux/string.h>
-#include <linux/fs.h>
 
 enum {
 /* These three have identical behaviour; use the second one if DOS FDISK gets
@@ -61,6 +55,12 @@ struct partition {
 #endif
 
 #ifdef __KERNEL__
+#include <linux/major.h>
+#include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+
 struct partition {
        unsigned char boot_ind;         /* 0x80 - active */
        unsigned char head;             /* starting head */
index 3ac452945a7d58fdbe7c4e59fed4373f904798f7..cc9e608444845c30509331521f330512b2dbbb4c 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/mmzone.h>
 #include <linux/stddef.h>
 #include <linux/linkage.h>
-#include <linux/config.h>
 
 struct vm_area_struct;
 
index eab537091f2a1602e55a17b5cdc7a17afb20f99f..114ae583cca9a28480ba684c342a54b97bf46686 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef LINUX_HARDIRQ_H
 #define LINUX_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/preempt.h>
 #include <linux/smp_lock.h>
 #include <asm/hardirq.h>
index 892c4ea1b4254a63d6540f948229a6f8164282e1..85ce7ef9a51200a8351fa155829682c5128718ec 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_HIGHMEM_H
 #define _LINUX_HIGHMEM_H
 
-#include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 
index 53ecac3905e8d71429d0562a9d113f85a20e1f5f..434e56246f678c615b118720ba499c5fc127ab9c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_HIGHUID_H
 #define _LINUX_HIGHUID_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /*
index 306acf1dc6d58b54aef407d2ab9e370ff18eaa99..7d2a1b974c5edd4657d647a07b8c62416ae22476 100644 (file)
@@ -127,7 +127,7 @@ extern ktime_t hrtimer_get_next_event(void);
 
 static inline int hrtimer_active(const struct hrtimer *timer)
 {
-       return timer->node.rb_parent != HRTIMER_INACTIVE;
+       return rb_parent(&timer->node) != &timer->node;
 }
 
 /* Forward a hrtimer so it expires after now: */
index 26a8b89855f123ea8a443fe542841a6fc705df2b..0073fe96c76ea7b7f34e5e7b5c6b5ba695b42c32 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef I2C_ALGO_ITE_H
 #define I2C_ALGO_ITE_H 1
 
-#include <linux/i2c.h>
+#include <linux/types.h>
 
 /* Example of a sequential read request:
        struct i2c_iic_msg s_msg; 
@@ -49,6 +49,9 @@ struct i2c_iic_msg {
        char *buf;      /* pointer to msg data */
 };
 
+#ifdef __KERNEL__
+struct i2c_adapter;
+
 struct i2c_algo_iic_data {
        void *data;             /* private data for lolevel routines    */
        void (*setiic) (void *data, int ctl, int val);
@@ -65,5 +68,5 @@ struct i2c_algo_iic_data {
 
 int i2c_iic_add_bus(struct i2c_adapter *);
 int i2c_iic_del_bus(struct i2c_adapter *);
-
+#endif /* __KERNEL__ */
 #endif /* I2C_ALGO_ITE_H */
index 1635ee25918fc19ea613d1e8dbcb672075220efb..0510430e00dbc88bcfc045bd4f7463ad32bbcc95 100644 (file)
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
 /* ------------------------------------------------------------------------- */
 
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
+/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
    Frodo Looijaard <frodol@dds.nl> */
 
 #ifndef _LINUX_I2C_H
 #define _LINUX_I2C_H
 
-#include <linux/module.h>
 #include <linux/types.h>
+#ifdef __KERNEL__ 
+#include <linux/module.h>
 #include <linux/i2c-id.h>
 #include <linux/mod_devicetable.h>
 #include <linux/device.h>      /* for struct device */
@@ -354,6 +355,7 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap)
 {
        return adap->nr;
 }
+#endif /* __KERNEL__ */
 
 /*
  * I2C Message - used for pure i2c transaction, also from /dev interface
@@ -469,6 +471,7 @@ union i2c_smbus_data {
 #define I2C_SMBUS      0x0720  /* SMBus-level access */
 
 /* ----- I2C-DEV: char device interface stuff ------------------------- */
+#ifdef __KERNEL__
 
 #define I2C_MAJOR      89              /* Device major number          */
 
@@ -646,5 +649,5 @@ static unsigned short *forces[] = { force, force_##chip1,           \
                                    force_##chip6, force_##chip7,       \
                                    force_##chip8, NULL };              \
 I2C_CLIENT_INSMOD_COMMON
-
+#endif /* __KERNEL__ */
 #endif /* _LINUX_I2C_H */
index 36fd18cdad2897f6f0f3ff38ad4770db29227c13..c2519df1b6dcbd2f208dfb236f39d5688279a670 100644 (file)
@@ -13,7 +13,7 @@
  * This header file defines the I2O APIs that are available to both
  * the kernel and user level applications.  Kernel specific structures
  * are defined in i2o_osm. OSMs should include _only_ i2o_osm.h which
- * automatically includs this file.
+ * automatically includes this file.
  *
  */
 
 /* How many controllers are we allowing */
 #define MAX_I2O_CONTROLLERS    32
 
-//#include <linux/ioctl.h>
-#ifndef __KERNEL__
-
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-
-#endif                         /* __KERNEL__ */
+#include <linux/ioctl.h>
 
 /*
  * I2O Control IOCTLs and structures
@@ -53,7 +46,7 @@ typedef unsigned int u32;
 
 struct i2o_cmd_passthru32 {
        unsigned int iop;       /* IOP unit number */
-       u32 msg;                /* message */
+       __u32 msg;              /* message */
 };
 
 struct i2o_cmd_passthru {
@@ -138,53 +131,53 @@ typedef struct i2o_sg_io_hdr {
 #define I2O_BUS_UNKNOWN 0x80
 
 typedef struct _i2o_pci_bus {
-       u8 PciFunctionNumber;
-       u8 PciDeviceNumber;
-       u8 PciBusNumber;
-       u8 reserved;
-       u16 PciVendorID;
-       u16 PciDeviceID;
+       __u8 PciFunctionNumber;
+       __u8 PciDeviceNumber;
+       __u8 PciBusNumber;
+       __u8 reserved;
+       __u16 PciVendorID;
+       __u16 PciDeviceID;
 } i2o_pci_bus;
 
 typedef struct _i2o_local_bus {
-       u16 LbBaseIOPort;
-       u16 reserved;
-       u32 LbBaseMemoryAddress;
+       __u16 LbBaseIOPort;
+       __u16 reserved;
+       __u32 LbBaseMemoryAddress;
 } i2o_local_bus;
 
 typedef struct _i2o_isa_bus {
-       u16 IsaBaseIOPort;
-       u8 CSN;
-       u8 reserved;
-       u32 IsaBaseMemoryAddress;
+       __u16 IsaBaseIOPort;
+       __u8 CSN;
+       __u8 reserved;
+       __u32 IsaBaseMemoryAddress;
 } i2o_isa_bus;
 
 typedef struct _i2o_eisa_bus_info {
-       u16 EisaBaseIOPort;
-       u8 reserved;
-       u8 EisaSlotNumber;
-       u32 EisaBaseMemoryAddress;
+       __u16 EisaBaseIOPort;
+       __u8 reserved;
+       __u8 EisaSlotNumber;
+       __u32 EisaBaseMemoryAddress;
 } i2o_eisa_bus;
 
 typedef struct _i2o_mca_bus {
-       u16 McaBaseIOPort;
-       u8 reserved;
-       u8 McaSlotNumber;
-       u32 McaBaseMemoryAddress;
+       __u16 McaBaseIOPort;
+       __u8 reserved;
+       __u8 McaSlotNumber;
+       __u32 McaBaseMemoryAddress;
 } i2o_mca_bus;
 
 typedef struct _i2o_other_bus {
-       u16 BaseIOPort;
-       u16 reserved;
-       u32 BaseMemoryAddress;
+       __u16 BaseIOPort;
+       __u16 reserved;
+       __u32 BaseMemoryAddress;
 } i2o_other_bus;
 
 typedef struct _i2o_hrt_entry {
-       u32 adapter_id;
-       u32 parent_tid:12;
-       u32 state:4;
-       u32 bus_num:8;
-       u32 bus_type:8;
+       __u32 adapter_id;
+       __u32 parent_tid:12;
+       __u32 state:4;
+       __u32 bus_num:8;
+       __u32 bus_type:8;
        union {
                i2o_pci_bus pci_bus;
                i2o_local_bus local_bus;
@@ -196,66 +189,66 @@ typedef struct _i2o_hrt_entry {
 } i2o_hrt_entry;
 
 typedef struct _i2o_hrt {
-       u16 num_entries;
-       u8 entry_len;
-       u8 hrt_version;
-       u32 change_ind;
+       __u16 num_entries;
+       __u8 entry_len;
+       __u8 hrt_version;
+       __u32 change_ind;
        i2o_hrt_entry hrt_entry[1];
 } i2o_hrt;
 
 typedef struct _i2o_lct_entry {
-       u32 entry_size:16;
-       u32 tid:12;
-       u32 reserved:4;
-       u32 change_ind;
-       u32 device_flags;
-       u32 class_id:12;
-       u32 version:4;
-       u32 vendor_id:16;
-       u32 sub_class;
-       u32 user_tid:12;
-       u32 parent_tid:12;
-       u32 bios_info:8;
-       u8 identity_tag[8];
-       u32 event_capabilities;
+       __u32 entry_size:16;
+       __u32 tid:12;
+       __u32 reserved:4;
+       __u32 change_ind;
+       __u32 device_flags;
+       __u32 class_id:12;
+       __u32 version:4;
+       __u32 vendor_id:16;
+       __u32 sub_class;
+       __u32 user_tid:12;
+       __u32 parent_tid:12;
+       __u32 bios_info:8;
+       __u8 identity_tag[8];
+       __u32 event_capabilities;
 } i2o_lct_entry;
 
 typedef struct _i2o_lct {
-       u32 table_size:16;
-       u32 boot_tid:12;
-       u32 lct_ver:4;
-       u32 iop_flags;
-       u32 change_ind;
+       __u32 table_size:16;
+       __u32 boot_tid:12;
+       __u32 lct_ver:4;
+       __u32 iop_flags;
+       __u32 change_ind;
        i2o_lct_entry lct_entry[1];
 } i2o_lct;
 
 typedef struct _i2o_status_block {
-       u16 org_id;
-       u16 reserved;
-       u16 iop_id:12;
-       u16 reserved1:4;
-       u16 host_unit_id;
-       u16 segment_number:12;
-       u16 i2o_version:4;
-       u8 iop_state;
-       u8 msg_type;
-       u16 inbound_frame_size;
-       u8 init_code;
-       u8 reserved2;
-       u32 max_inbound_frames;
-       u32 cur_inbound_frames;
-       u32 max_outbound_frames;
+       __u16 org_id;
+       __u16 reserved;
+       __u16 iop_id:12;
+       __u16 reserved1:4;
+       __u16 host_unit_id;
+       __u16 segment_number:12;
+       __u16 i2o_version:4;
+       __u8 iop_state;
+       __u8 msg_type;
+       __u16 inbound_frame_size;
+       __u8 init_code;
+       __u8 reserved2;
+       __u32 max_inbound_frames;
+       __u32 cur_inbound_frames;
+       __u32 max_outbound_frames;
        char product_id[24];
-       u32 expected_lct_size;
-       u32 iop_capabilities;
-       u32 desired_mem_size;
-       u32 current_mem_size;
-       u32 current_mem_base;
-       u32 desired_io_size;
-       u32 current_io_size;
-       u32 current_io_base;
-       u32 reserved3:24;
-       u32 cmd_status:8;
+       __u32 expected_lct_size;
+       __u32 iop_capabilities;
+       __u32 desired_mem_size;
+       __u32 current_mem_size;
+       __u32 current_mem_base;
+       __u32 desired_io_size;
+       __u32 current_io_size;
+       __u32 current_io_base;
+       __u32 reserved3:24;
+       __u32 cmd_status:8;
 } i2o_status_block;
 
 /* Event indicator mask flags */
index dd7d627bf66f306b4ee9401f06ed4fb574896a85..c115e9e840b4e051b7b573a37c27bfc4564ad504 100644 (file)
@@ -1114,8 +1114,11 @@ static inline struct i2o_message *i2o_msg_get(struct i2o_controller *c)
 
        mmsg->mfa = readl(c->in_port);
        if (unlikely(mmsg->mfa >= c->in_queue.len)) {
+               u32 mfa = mmsg->mfa;
+
                mempool_free(mmsg, c->in_msg.mempool);
-               if(mmsg->mfa == I2O_QUEUE_EMPTY)
+
+               if (mfa == I2O_QUEUE_EMPTY)
                        return ERR_PTR(-EBUSY);
                return ERR_PTR(-EFAULT);
        }
index a8bef1d1371cc999ce6882d355c7554ca7738173..77e66d055f5b64338db137aaebb471cb3fcfb16e 100644 (file)
@@ -6,7 +6,6 @@
  *  Copyright (C) 1994-2002  Linus Torvalds & authors
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/hdreg.h>
index 1288a161bc0baf1b64583d668a24069e0f03a44b..e0a150046208465fe8d8f61e44c1e1d5bc956cad 100644 (file)
@@ -102,6 +102,7 @@ struct fddihdr
                } hdr;
        } __attribute__ ((packed));
 
+#ifdef __KERNEL__
 /* Define FDDI statistics structure */
 struct fddi_statistics {
 
@@ -193,5 +194,6 @@ struct fddi_statistics {
        __u32   port_ler_flag[2];
        __u32   port_hardware_present[2];
        };
+#endif /* __KERNEL__ */
 
 #endif /* _LINUX_IF_FDDI_H */
index 395f0aad9cbf048a0650ba3e48565669a96707bd..f272a80caa3e577aa21d73760ac3519c2659506e 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef _FRAD_H_
 #define _FRAD_H_
 
-#include <linux/config.h>
 #include <linux/if.h>
 
 #if defined(CONFIG_DLCI) || defined(CONFIG_DLCI_MODULE)
index 5502f597cf0e8808b582c6bb8d7cc52412bd2d11..2f94cf2c7abbed7969f2a29e91485cc56a046345 100644 (file)
@@ -43,7 +43,6 @@ struct trh_hdr {
 };
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/skbuff.h>
 
 static inline struct trh_hdr *tr_hdr(const struct sk_buff *skb)
index 28f4f3b36950593a5eec787ce7193cb207bf9be8..899c3d4776f3dffc690274bd3dfb44224c6608ab 100644 (file)
@@ -169,7 +169,7 @@ struct ip_sf_list
 struct ip_mc_list
 {
        struct in_device        *interface;
-       unsigned long           multiaddr;
+       __be32                  multiaddr;
        struct ip_sf_list       *sources;
        struct ip_sf_list       *tomb;
        unsigned int            sfmode;
index 93dcbe1abb4c83b65cc6af59fb84c3c5e16effbb..6667785dd1ff22d7452b716b380e7475158ee8b9 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_INIT_H
 #define _LINUX_INIT_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 
 /* These macros are used to mark some functions or 
index 09e00433c78e267b37b3f485c0d877de780a0674..d4f48c6402e6ffd615b81a50a65ea7c41b47dcaf 100644 (file)
@@ -67,20 +67,66 @@ struct inotify_event {
 
 #include <linux/dcache.h>
 #include <linux/fs.h>
-#include <linux/config.h>
+
+/*
+ * struct inotify_watch - represents a watch request on a specific inode
+ *
+ * h_list is protected by ih->mutex of the associated inotify_handle.
+ * i_list, mask are protected by inode->inotify_mutex of the associated inode.
+ * ih, inode, and wd are never written to once the watch is created.
+ *
+ * Callers must use the established inotify interfaces to access inotify_watch
+ * contents.  The content of this structure is private to the inotify
+ * implementation.
+ */
+struct inotify_watch {
+       struct list_head        h_list; /* entry in inotify_handle's list */
+       struct list_head        i_list; /* entry in inode's list */
+       atomic_t                count;  /* reference count */
+       struct inotify_handle   *ih;    /* associated inotify handle */
+       struct inode            *inode; /* associated inode */
+       __s32                   wd;     /* watch descriptor */
+       __u32                   mask;   /* event mask for this watch */
+};
+
+struct inotify_operations {
+       void (*handle_event)(struct inotify_watch *, u32, u32, u32,
+                            const char *, struct inode *);
+       void (*destroy_watch)(struct inotify_watch *);
+};
 
 #ifdef CONFIG_INOTIFY
 
+/* Kernel API for producing events */
+
 extern void inotify_d_instantiate(struct dentry *, struct inode *);
 extern void inotify_d_move(struct dentry *);
 extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
-                                     const char *);
+                                     const char *, struct inode *);
 extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
                                              const char *);
 extern void inotify_unmount_inodes(struct list_head *);
 extern void inotify_inode_is_dead(struct inode *);
 extern u32 inotify_get_cookie(void);
 
+/* Kernel Consumer API */
+
+extern struct inotify_handle *inotify_init(const struct inotify_operations *);
+extern void inotify_init_watch(struct inotify_watch *);
+extern void inotify_destroy(struct inotify_handle *);
+extern __s32 inotify_find_watch(struct inotify_handle *, struct inode *,
+                               struct inotify_watch **);
+extern __s32 inotify_find_update_watch(struct inotify_handle *, struct inode *,
+                                      u32);
+extern __s32 inotify_add_watch(struct inotify_handle *, struct inotify_watch *,
+                              struct inode *, __u32);
+extern int inotify_rm_watch(struct inotify_handle *, struct inotify_watch *);
+extern int inotify_rm_wd(struct inotify_handle *, __u32);
+extern void inotify_remove_watch_locked(struct inotify_handle *,
+                                       struct inotify_watch *);
+extern void get_inotify_watch(struct inotify_watch *);
+extern void put_inotify_watch(struct inotify_watch *);
+
 #else
 
 static inline void inotify_d_instantiate(struct dentry *dentry,
@@ -94,7 +140,8 @@ static inline void inotify_d_move(struct dentry *dentry)
 
 static inline void inotify_inode_queue_event(struct inode *inode,
                                             __u32 mask, __u32 cookie,
-                                            const char *filename)
+                                            const char *filename,
+                                            struct inode *n_inode)
 {
 }
 
@@ -117,6 +164,62 @@ static inline u32 inotify_get_cookie(void)
        return 0;
 }
 
+static inline struct inotify_handle *inotify_init(const struct inotify_operations *ops)
+{
+       return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void inotify_init_watch(struct inotify_watch *watch)
+{
+}
+
+static inline void inotify_destroy(struct inotify_handle *ih)
+{
+}
+
+static inline __s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode,
+                                      struct inotify_watch **watchp)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline __s32 inotify_find_update_watch(struct inotify_handle *ih,
+                                             struct inode *inode, u32 mask)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline __s32 inotify_add_watch(struct inotify_handle *ih,
+                                     struct inotify_watch *watch,
+                                     struct inode *inode, __u32 mask)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int inotify_rm_watch(struct inotify_handle *ih,
+                                  struct inotify_watch *watch)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int inotify_rm_wd(struct inotify_handle *ih, __u32 wd)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline void inotify_remove_watch_locked(struct inotify_handle *ih,
+                                              struct inotify_watch *watch)
+{
+}
+
+static inline void get_inotify_watch(struct inotify_watch *watch)
+{
+}
+
+static inline void put_inotify_watch(struct inotify_watch *watch)
+{
+}
+
 #endif /* CONFIG_INOTIFY */
 
 #endif /* __KERNEL __ */
index 50e338d2ffda9cb5a835d67849e38ae0ceba1647..b32c2b6e53f6947ed7233bfd4013e1c462273d55 100644 (file)
@@ -15,6 +15,7 @@
 #else
 #include <sys/time.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
 #include <asm/types.h>
 #endif
 
@@ -345,6 +346,8 @@ struct input_absinfo {
 #define KEY_SAVE               234
 #define KEY_DOCUMENTS          235
 
+#define KEY_BATTERY            236
+
 #define KEY_UNKNOWN            240
 
 #define BTN_MISC               0x100
@@ -577,14 +580,9 @@ struct input_absinfo {
  * Switch events
  */
 
-#define SW_0                   0x00
-#define SW_1                   0x01
-#define SW_2                   0x02
-#define SW_3                   0x03
-#define SW_4                   0x04
-#define SW_5                   0x05
-#define SW_6                   0x06
-#define SW_7                   0x07
+#define SW_LID                 0x00  /* set = lid shut */
+#define SW_TABLET_MODE         0x01  /* set = tablet mode */
+#define SW_HEADPHONE_INSERT    0x02  /* set = inserted */
 #define SW_MAX                 0x0f
 
 /*
index 2c08fdc2bdf70b5aff6a670e39299ba227f898c7..9e0fefd7884a9e79f2b1a9455de06e4708305fb6 100644 (file)
@@ -2,7 +2,6 @@
 #ifndef _LINUX_INTERRUPT_H
 #define _LINUX_INTERRUPT_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/linkage.h>
 #include <linux/bitops.h>
index 0a84b56935c20450205dc976c5912867e23c5d3c..5653b2f23b6a6fdf94f0e1d15ae8cb7436638db0 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <linux/ipmi_msgdefs.h>
 #include <linux/compiler.h>
-#include <linux/device.h>
 
 /*
  * This file describes an interface to an IPMI driver.  You have to
@@ -210,6 +209,7 @@ struct kernel_ipmi_msg
  */
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/device.h>
 
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
index 1263d8cb3c18db024e6c4313764ce7f9e6f5c24a..297853c841b4b70d26b0b57e9528e1672885cdc8 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _IPV6_H
 #define _IPV6_H
 
-#include <linux/config.h>
 #include <linux/in6.h>
 #include <asm/byteorder.h>
 
index ee2a82a572f7d7b6b95c6ea593e1e65f85fb89d9..42c9cd5628603e66b9d6deb8332b1f095b03a9d1 100644 (file)
@@ -9,7 +9,6 @@
  * Thanks. --rmk
  */
 
-#include <linux/config.h>
 #include <linux/smp.h>
 
 #if !defined(CONFIG_S390)
index af93505ec2ec83f415820576c021a4982c2d5927..77e4bac292872848aed81c358ab3d0ee75441145 100644 (file)
@@ -9,7 +9,6 @@
  * Keith Owens <kaos@ocs.com.au> July 2000.
  */
 
-#include <linux/config.h>
 
 /*
  * Simple wrappers reducing source bloat.  Define all irq_stat fields
index 26c64c286f4213c6fc0e6ed26d66549d69e235c5..1e8728a9ee8a0bce0e05e1fa41cb47a09876d053 100644 (file)
@@ -22,7 +22,6 @@
 #ifndef LINUX_ISAPNP_H
 #define LINUX_ISAPNP_H
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/pnp.h>
 
index 53eaee96065bc0512370b866511c7b3ed4f11737..62991148d5a53aa8df83180ce0e61a6943b7bc36 100644 (file)
@@ -146,7 +146,6 @@ typedef struct {
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
index 9f65bea49d117fcd067ac391bfef5982914d0227..d18dd0dc570d0b171b45ea4f137ead5c69fdeae6 100644 (file)
@@ -26,7 +26,6 @@
 #define _TPAM_H_
 
 #include <linux/types.h>
-#include <linux/pci.h>
 
 /* IOCTL commands */
 #define TPAM_CMD_DSPLOAD       0x0001
index 26b00a76e1350a0b96e8959300c4a85093ce9322..8687a7dc0632378c4828b2c58664ec638227919d 100644 (file)
@@ -67,7 +67,6 @@ struct isdn_ppp_comp_data {
 #ifdef __KERNEL__
 
 
-#include <linux/config.h>
 
 #ifdef CONFIG_IPPP_FILTER
 #include <linux/filter.h>
index 04e10f9f14f890b2cb0468f06f9c872a1a5a2803..b9b5a684ed6989be4095c74a4bcf0b355a9fd8b1 100644 (file)
@@ -54,7 +54,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/skbuff.h>
 
 /***************************************************************************/
index cf792bb3c72655beafc28d29c72f25f14bf96a4b..c6f70660b3716e39736153151cc5ef6c1b82fd70 100644 (file)
 
 #define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)
 
+#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8)
+#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)
+
+/* XATTR Related */
+#define JFFS2_XPREFIX_USER             1       /* for "user." */
+#define JFFS2_XPREFIX_SECURITY         2       /* for "security." */
+#define JFFS2_XPREFIX_ACL_ACCESS       3       /* for "system.posix_acl_access" */
+#define JFFS2_XPREFIX_ACL_DEFAULT      4       /* for "system.posix_acl_default" */
+#define JFFS2_XPREFIX_TRUSTED          5       /* for "trusted.*" */
+
+#define JFFS2_ACL_VERSION              0x0001
+
 // Maybe later...
 //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
 //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)
 
 typedef struct {
        uint32_t v32;
-} __attribute__((packed))  jint32_t;
+} __attribute__((packed)) jint32_t;
 
 typedef struct {
        uint32_t m;
-} __attribute__((packed))  jmode_t;
+} __attribute__((packed)) jmode_t;
 
 typedef struct {
        uint16_t v16;
@@ -99,7 +111,7 @@ struct jffs2_unknown_node
        jint16_t nodetype;
        jint32_t totlen; /* So we can skip over nodes we don't grok */
        jint32_t hdr_crc;
-} __attribute__((packed));
+};
 
 struct jffs2_raw_dirent
 {
@@ -117,7 +129,7 @@ struct jffs2_raw_dirent
        jint32_t node_crc;
        jint32_t name_crc;
        uint8_t name[0];
-} __attribute__((packed));
+};
 
 /* The JFFS2 raw inode structure: Used for storage on physical media.  */
 /* The uid, gid, atime, mtime and ctime members could be longer, but
@@ -149,6 +161,32 @@ struct jffs2_raw_inode
        jint32_t data_crc;   /* CRC for the (compressed) data.  */
        jint32_t node_crc;   /* CRC for the raw inode (excluding data)  */
        uint8_t data[0];
+};
+
+struct jffs2_raw_xattr {
+       jint16_t magic;
+       jint16_t nodetype;      /* = JFFS2_NODETYPE_XATTR */
+       jint32_t totlen;
+       jint32_t hdr_crc;
+       jint32_t xid;           /* XATTR identifier number */
+       jint32_t version;
+       uint8_t xprefix;
+       uint8_t name_len;
+       jint16_t value_len;
+       jint32_t data_crc;
+       jint32_t node_crc;
+       uint8_t data[0];
+} __attribute__((packed));
+
+struct jffs2_raw_xref
+{
+       jint16_t magic;
+       jint16_t nodetype;      /* = JFFS2_NODETYPE_XREF */
+       jint32_t totlen;
+       jint32_t hdr_crc;
+       jint32_t ino;           /* inode number */
+       jint32_t xid;           /* XATTR identifier number */
+       jint32_t node_crc;
 } __attribute__((packed));
 
 struct jffs2_raw_summary
@@ -163,14 +201,22 @@ struct jffs2_raw_summary
        jint32_t sum_crc;       /* summary information crc */
        jint32_t node_crc;      /* node crc */
        jint32_t sum[0];        /* inode summary info */
-} __attribute__((packed));
+};
 
 union jffs2_node_union
 {
        struct jffs2_raw_inode i;
        struct jffs2_raw_dirent d;
+       struct jffs2_raw_xattr x;
+       struct jffs2_raw_xref r;
        struct jffs2_raw_summary s;
        struct jffs2_unknown_node u;
 };
 
+/* Data payload for device nodes. */
+union jffs2_device_node {
+       jint16_t old;
+       jint32_t new;
+};
+
 #endif /* __LINUX_JFFS2_H__ */
index 5fd20ddd7ae3b3ff4319b5d9e284dcbd6eafb58b..e2d3a18af4566a9cd7dd4e1f123162d894031832 100644 (file)
@@ -111,25 +111,25 @@ struct js_corr {
 #define JS_SET_ALL             8
 
 struct JS_DATA_TYPE {
-       int32_t buttons;
-       int32_t x;
-       int32_t y;
+       __s32 buttons;
+       __s32 x;
+       __s32 y;
 };
 
 struct JS_DATA_SAVE_TYPE_32 {
-       int32_t JS_TIMEOUT;
-       int32_t BUSY;
-       int32_t JS_EXPIRETIME;
-       int32_t JS_TIMELIMIT;
+       __s32 JS_TIMEOUT;
+       __s32 BUSY;
+       __s32 JS_EXPIRETIME;
+       __s32 JS_TIMELIMIT;
        struct JS_DATA_TYPE JS_SAVE;
        struct JS_DATA_TYPE JS_CORR;
 };
 
 struct JS_DATA_SAVE_TYPE_64 {
-       int32_t JS_TIMEOUT;
-       int32_t BUSY;
-       int64_t JS_EXPIRETIME;
-       int64_t JS_TIMELIMIT;
+       __s32 JS_TIMEOUT;
+       __s32 BUSY;
+       __s64 JS_EXPIRETIME;
+       __s64 JS_TIMELIMIT;
        struct JS_DATA_TYPE JS_SAVE;
        struct JS_DATA_TYPE JS_CORR;
 };
index 9bbd04092365a59b7d53f53d97faf73091b15518..54e2549f96bacb1d15433d6bf6b68747e60d9f87 100644 (file)
@@ -5,7 +5,6 @@
 #ifndef _LINUX_KALLSYMS_H
 #define _LINUX_KALLSYMS_H
 
-#include <linux/config.h>
 
 #define KSYM_NAME_LEN 127
 
index b46249082ccacf661902110804ec2192ea733f25..43e895f1cabef24137e213958eeef48bde70ff28 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_KERNEL_STAT_H
 #define _LINUX_KERNEL_STAT_H
 
-#include <linux/config.h>
 #include <asm/irq.h>
 #include <linux/smp.h>
 #include <linux/threads.h>
index e4a231549407817c285bb2a6b18c78fdcd31652f..0db22a1ab474d94edfa5e4f79f95e3f286d7c51e 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #include <linux/stddef.h>
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/compiler.h>
 
index 778adc0fa640ea9c2d3a9d819af5b505ab4dc63f..8bf6702da2a0348e1ac3538ffba7f1954ceffc5b 100644 (file)
@@ -29,7 +29,6 @@
  *             <jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *             <prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/smp.h>
index c08c9983e840bf9587b6f2a7ae7c136d3f56ef7f..932021f872d5feaa71a38d872ab6dcce74f96158 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_LINKAGE_H
 #define _LINUX_LINKAGE_H
 
-#include <linux/config.h>
 #include <asm/linkage.h>
 
 #ifdef __cplusplus
index 995f89dc8c046c4e67a8e44039c42f5ac0eaf229..a8876bc6513b8e5302e8511a7349fffe64ee42a5 100644 (file)
@@ -11,7 +11,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/in.h>
 #include <linux/fs.h>
 #include <linux/kref.h>
index 869b630cba2490a847b2a3fc753a1d49e753aa51..d9d46e4425385d68c1706a75ba5d278a1798e7e4 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef LINUX_LOCKD_NLM_H
 #define LINUX_LOCKD_NLM_H
 
-#include <linux/config.h>
 
 /* Maximum file offset in file_lock.fl_end */
 # define NLM_OFFSET_MAX                ((s32) 0x7fffffff)
index 9065199319d033cc0560c1f91305930980827039..915d6b4f0f89689a81d749b6a87b5b2c0ea2d432 100644 (file)
@@ -11,6 +11,6 @@
 
 struct m48t86_ops
 {
-       void (*writeb)(unsigned char value, unsigned long addr);
-       unsigned char (*readb)(unsigned long addr);
+       void (*writebyte)(unsigned char value, unsigned long addr);
+       unsigned char (*readbyte)(unsigned long addr);
 };
index 6a7621b2b12b0061c9edc3daf3a8dbede1a1451c..72440f0a443d4869ebbbd68690e662687187cf88 100644 (file)
@@ -28,7 +28,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/mmzone.h>
 #include <linux/slab.h>
 #include <linux/rbtree.h>
@@ -36,6 +35,7 @@
 #include <linux/nodemask.h>
 
 struct vm_area_struct;
+struct mm_struct;
 
 #ifdef CONFIG_NUMA
 
index ff0a64073ebccc7b9fb400372a7f46bfe0d19dda..6789c4940c9c919d6091c19f8679e342c0c85cdd 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_MIGRATE_H
 #define _LINUX_MIGRATE_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 #ifdef CONFIG_MIGRATION
index 68f5a0f392dd969a9e063a2e835ecced5ba1c61f..beddc6d3b0f668e2f8af2ecfb2ef6a13062656a0 100644 (file)
@@ -9,7 +9,6 @@
 #define __LINUX_MII_H__
 
 #include <linux/types.h>
-#include <linux/if.h>
 
 /* Generic MII registers. */
 
 #define LPA_1000FULL            0x0800  /* Link partner 1000BASE-T full duplex */
 #define LPA_1000HALF            0x0400  /* Link partner 1000BASE-T half duplex */
 
+/* This structure is used in all SIOCxMIIxxx ioctl calls */
+struct mii_ioctl_data {
+       __u16           phy_id;
+       __u16           reg_num;
+       __u16           val_in;
+       __u16           val_out;
+};
+
+#ifdef __KERNEL__ 
+
+#include <linux/if.h>
+
+struct ethtool_cmd;
+
 struct mii_if_info {
        int phy_id;
        int advertising;
@@ -151,9 +164,6 @@ struct mii_if_info {
        void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
 };
 
-struct ethtool_cmd;
-struct mii_ioctl_data;
-
 extern int mii_link_ok (struct mii_if_info *mii);
 extern int mii_nway_restart (struct mii_if_info *mii);
 extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
@@ -168,16 +178,6 @@ extern int generic_mii_ioctl(struct mii_if_info *mii_if,
                             unsigned int *duplex_changed);
 
 
-
-/* This structure is used in all SIOCxMIIxxx ioctl calls */
-struct mii_ioctl_data {
-       u16             phy_id;
-       u16             reg_num;
-       u16             val_in;
-       u16             val_out;
-};
-
-
 static inline struct mii_ioctl_data *if_mii(struct ifreq *rq)
 {
        return (struct mii_ioctl_data *) &rq->ifr_ifru;
@@ -235,5 +235,5 @@ static inline unsigned int mii_duplex (unsigned int duplex_lock,
        return 0;
 }
 
-
+#endif /* __KERNEL__ */
 #endif /* __LINUX_MII_H__ */
index 1154684209a4458d1507702e1c4a778d942eda94..e2fa375e478e9a920b6a5e07a924cbe7f6016eb8 100644 (file)
@@ -7,7 +7,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/gfp.h>
 #include <linux/list.h>
 #include <linux/mmzone.h>
index 18a5689ef748c569b43dfbaf9fe3bcde0243fc31..87920a0852a37e8945cdfd63bad2f6aa5f58110a 100644 (file)
@@ -1,10 +1,6 @@
 #ifndef _LINUX_MMAN_H
 #define _LINUX_MMAN_H
 
-#include <linux/config.h>
-#include <linux/mm.h>
-
-#include <asm/atomic.h>
 #include <asm/mman.h>
 
 #define MREMAP_MAYMOVE 1
@@ -13,6 +9,12 @@
 #define OVERCOMMIT_GUESS               0
 #define OVERCOMMIT_ALWAYS              1
 #define OVERCOMMIT_NEVER               2
+
+#ifdef __KERNEL__
+#include <linux/mm.h>
+
+#include <asm/atomic.h>
+
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern atomic_t vm_committed_space;
@@ -63,5 +65,5 @@ calc_vm_flag_bits(unsigned long flags)
               _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) |
               _calc_vm_trans(flags, MAP_LOCKED,     VM_LOCKED    );
 }
-
+#endif /* __KERNEL__ */
 #endif /* _LINUX_MMAN_H */
index 36740354d4db474c7034beaff63f558891f1f6bc..9742e3c16222824b1f5702f64039e592543f08f2 100644 (file)
@@ -4,7 +4,6 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/wait.h>
@@ -15,6 +14,7 @@
 #include <linux/seqlock.h>
 #include <linux/nodemask.h>
 #include <asm/atomic.h>
+#include <asm/page.h>
 
 /* Free memory management - zoned buddy allocator.  */
 #ifndef CONFIG_FORCE_MAX_ZONEORDER
index eaec13ddd6670bb8f9d41ef68a3faf3c7d06a5bb..c2d89e037af04b1af73cd9ba2494a20a2d2e8e6a 100644 (file)
@@ -6,7 +6,6 @@
  * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
  * Rewritten again by Rusty Russell, 2002
  */
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
@@ -557,13 +556,4 @@ static inline void module_remove_driver(struct device_driver *driver)
 
 #define __MODULE_STRING(x) __stringify(x)
 
-/* Use symbol_get and symbol_put instead.  You'll thank me. */
-#define HAVE_INTER_MODULE
-extern void __deprecated inter_module_register(const char *,
-               struct module *, const void *);
-extern void __deprecated inter_module_unregister(const char *);
-extern const void * __deprecated inter_module_get_request(const char *,
-               const char *);
-extern void __deprecated inter_module_put(const char *);
-
 #endif /* _LINUX_MODULE_H */
index 903e0ab8101fad230721c7ecd27653b413a5d058..acc7c174ff0091aeb8f46bed30e378633c48ef21 100644 (file)
@@ -2,7 +2,6 @@
 #define _LINUX_MSG_H
 
 #include <linux/ipc.h>
-#include <linux/list.h>
 
 /* ipcs ctl commands */
 #define MSG_STAT 11
@@ -63,6 +62,7 @@ struct msginfo {
 #define MSGSEG (__MSGSEG <= 0xffff ? __MSGSEG : 0xffff)
 
 #ifdef __KERNEL__
+#include <linux/list.h>
 
 /* one msg_msg structure for each message */
 struct msg_msg {
index 23a5689103417141c34d505d2f40b4083b6bbf5a..09bfae6938b3eb855f5a7b0b21f94eb5c4588a4a 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef __MTD_CFI_H__
 #define __MTD_CFI_H__
 
-#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
index d7eaa40e5ab0c72ba419462de70a79520e8f1e3c..6977780e548f96809a2c5df708490f7bae81bff0 100644 (file)
@@ -46,7 +46,7 @@ struct INFTLrecord {
         unsigned int nb_blocks;                /* number of physical blocks */
         unsigned int nb_boot_blocks;   /* number of blocks used by the bios */
         struct erase_info instr;
-        struct nand_oobinfo oobinfo;
+        struct nand_ecclayout oobinfo;
 };
 
 int INFTL_mount(struct INFTLrecord *s);
index 7dfd6e1fcde787f785442b71ca974d4fbbf5a782..28d461d862bda1d042055c463613a1a87338b698 100644 (file)
@@ -5,7 +5,6 @@
 #ifndef __LINUX_MTD_MAP_H__
 #define __LINUX_MTD_MAP_H__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/string.h>
index b6f2fdae65c6c284b9f511d35301af420a049303..9b7a2b525d630edfe03f5f54692f03745d594ac0 100644 (file)
@@ -13,7 +13,6 @@
 #error This is a kernel header. Perhaps include mtd-user.h instead?
 #endif
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/uio.h>
@@ -56,18 +55,69 @@ struct mtd_erase_region_info {
        u_int32_t numblocks;            /* Number of blocks of erasesize in this region */
 };
 
+/*
+ * oob operation modes
+ *
+ * MTD_OOB_PLACE:      oob data are placed at the given offset
+ * MTD_OOB_AUTO:       oob data are automatically placed at the free areas
+ *                     which are defined by the ecclayout
+ * MTD_OOB_RAW:                mode to read raw data+oob in one chunk. The oob data
+ *                     is inserted into the data. Thats a raw image of the
+ *                     flash contents.
+ */
+typedef enum {
+       MTD_OOB_PLACE,
+       MTD_OOB_AUTO,
+       MTD_OOB_RAW,
+} mtd_oob_mode_t;
+
+/**
+ * struct mtd_oob_ops - oob operation operands
+ * @mode:      operation mode
+ *
+ * @len:       number of bytes to write/read. When a data buffer is given
+ *             (datbuf != NULL) this is the number of data bytes. When
+ +             no data buffer is available this is the number of oob bytes.
+ *
+ * @retlen:    number of bytes written/read. When a data buffer is given
+ *             (datbuf != NULL) this is the number of data bytes. When
+ +             no data buffer is available this is the number of oob bytes.
+ *
+ * @ooblen:    number of oob bytes per page
+ * @ooboffs:   offset of oob data in the oob area (only relevant when
+ *             mode = MTD_OOB_PLACE)
+ * @datbuf:    data buffer - if NULL only oob data are read/written
+ * @oobbuf:    oob data buffer
+ */
+struct mtd_oob_ops {
+       mtd_oob_mode_t  mode;
+       size_t          len;
+       size_t          retlen;
+       size_t          ooblen;
+       uint32_t        ooboffs;
+       uint8_t         *datbuf;
+       uint8_t         *oobbuf;
+};
+
 struct mtd_info {
        u_char type;
        u_int32_t flags;
        u_int32_t size;  // Total size of the MTD
 
-       /* "Major" erase size for the device. Naïve users may take this
+       /* "Major" erase size for the device. Naïve users may take this
         * to be the only erase size available, or may use the more detailed
         * information below if they desire
         */
        u_int32_t erasesize;
+       /* Minimal writable flash unit size. In case of NOR flash it is 1 (even
+        * though individual bits can be cleared), in case of NAND flash it is
+        * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
+        * it is of ECC block size, etc. It is illegal to have writesize = 0.
+        * Any driver registering a struct mtd_info must ensure a writesize of
+        * 1 or larger.
+        */
+       u_int32_t writesize;
 
-       u_int32_t oobblock;  // Size of OOB blocks (e.g. 512)
        u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
        u_int32_t ecctype;
        u_int32_t eccsize;
@@ -79,7 +129,6 @@ struct mtd_info {
         * MTD_PROGRAM_REGIONS flag is set.
         * (Maybe we should have an union for those?)
         */
-#define MTD_PROGREGION_SIZE(mtd)  (mtd)->oobblock
 #define MTD_PROGREGION_CTRLMODE_VALID(mtd)  (mtd)->oobsize
 #define MTD_PROGREGION_CTRLMODE_INVALID(mtd)  (mtd)->ecctype
 
@@ -87,9 +136,8 @@ struct mtd_info {
        char *name;
        int index;
 
-       // oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO)
-       struct nand_oobinfo oobinfo;
-       u_int32_t oobavail;  // Number of bytes in OOB area available for fs
+       /* ecc layout structure pointer - read only ! */
+       struct nand_ecclayout *ecclayout;
 
        /* Data for variable erase regions. If numeraseregions is zero,
         * it means that the whole device has erasesize as given above.
@@ -112,11 +160,10 @@ struct mtd_info {
        int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
        int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
 
-       int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
-       int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
-
-       int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-       int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+       int (*read_oob) (struct mtd_info *mtd, loff_t from,
+                        struct mtd_oob_ops *ops);
+       int (*write_oob) (struct mtd_info *mtd, loff_t to,
+                        struct mtd_oob_ops *ops);
 
        /*
         * Methods to access the protection register area, present in some
@@ -130,17 +177,11 @@ struct mtd_info {
        int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
        int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
 
-       /* kvec-based read/write methods. We need these especially for NAND flash,
-          with its limited number of write cycles per erase.
+       /* kvec-based read/write methods.
           NB: The 'count' parameter is the number of _vectors_, each of
           which contains an (ofs, len) tuple.
        */
-       int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen);
-       int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from,
-               size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
        int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
-       int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to,
-               size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
 
        /* Sync */
        void (*sync) (struct mtd_info *mtd);
@@ -159,6 +200,9 @@ struct mtd_info {
 
        struct notifier_block reboot_notifier;  /* default mode before reboot */
 
+       /* ECC status information */
+       struct mtd_ecc_stats ecc_stats;
+
        void *priv;
 
        struct module *owner;
@@ -192,20 +236,6 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
 int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
                      unsigned long count, loff_t from, size_t *retlen);
 
-#define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
-#define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d))
-#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
-#define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args)
-#define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args)
-#define MTD_READV(mtd, args...) (*(mtd->readv))(mtd, args)
-#define MTD_WRITEV(mtd, args...) (*(mtd->writev))(mtd, args)
-#define MTD_READECC(mtd, args...) (*(mtd->read_ecc))(mtd, args)
-#define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
-#define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
-#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
-#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd);  } while (0)
-
-
 #ifdef CONFIG_MTD_PARTITIONS
 void mtd_erase_callback(struct erase_info *instr);
 #else
@@ -226,7 +256,7 @@ static inline void mtd_erase_callback(struct erase_info *instr)
 
 #ifdef CONFIG_MTD_DEBUG
 #define DEBUG(n, args...)                              \
-       do {                                            \
+       do {                                            \
                if (n <= CONFIG_MTD_DEBUG_VERBOSE)      \
                        printk(KERN_INFO args);         \
        } while(0)
index da5e67b3fc70ec8851f5aee64ce9a9b4f7ea6686..66559272ebcb86f2f3f4f05a1f025d232a984663 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- *  Info:
- *   Contains standard defines and IDs for NAND flash devices
+ * Info:
+ *     Contains standard defines and IDs for NAND flash devices
  *
- *  Changelog:
- *   01-31-2000 DMW     Created
- *   09-18-2000 SJH     Moved structure out of the Disk-On-Chip drivers
- *                     so it can be used by other NAND flash device
- *                     drivers. I also changed the copyright since none
- *                     of the original contents of this file are specific
- *                     to DoC devices. David can whack me with a baseball
- *                     bat later if I did something naughty.
- *   10-11-2000 SJH     Added private NAND flash structure for driver
- *   10-24-2000 SJH     Added prototype for 'nand_scan' function
- *   10-29-2001 TG     changed nand_chip structure to support
- *                     hardwarespecific function for accessing control lines
- *   02-21-2002 TG     added support for different read/write adress and
- *                     ready/busy line access function
- *   02-26-2002 TG     added chip_delay to nand_chip structure to optimize
- *                     command delay times for different chips
- *   04-28-2002 TG     OOB config defines moved from nand.c to avoid duplicate
- *                     defines in jffs2/wbuf.c
- *   08-07-2002 TG     forced bad block location to byte 5 of OOB, even if
- *                     CONFIG_MTD_NAND_ECC_JFFS2 is not set
- *   08-10-2002 TG     extensions to nand_chip structure to support HW-ECC
- *
- *   08-29-2002 tglx   nand_chip structure: data_poi for selecting
- *                     internal / fs-driver buffer
- *                     support for 6byte/512byte hardware ECC
- *                     read_ecc, write_ecc extended for different oob-layout
- *                     oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,
- *                     NAND_YAFFS_OOB
- *  11-25-2002 tglx    Added Manufacturer code FUJITSU, NATIONAL
- *                     Split manufacturer and device ID structures
- *
- *  02-08-2004 tglx    added option field to nand structure for chip anomalities
- *  05-25-2004 tglx    added bad block table support, ST-MICRO manufacturer id
- *                     update of nand_chip structure description
- *  01-17-2005 dmarlin added extended commands for AG-AND device and added option
- *                     for BBT_AUTO_REFRESH.
- *  01-20-2005 dmarlin added optional pointer to hardware specific callback for
- *                     extra error status checks.
+ * Changelog:
+ *     See git changelog.
  */
 #ifndef __LINUX_MTD_NAND_H
 #define __LINUX_MTD_NAND_H
 
-#include <linux/config.h>
 #include <linux/wait.h>
 #include <linux/spinlock.h>
 #include <linux/mtd/mtd.h>
@@ -67,10 +30,6 @@ extern int nand_scan (struct mtd_info *mtd, int max_chips);
 /* Free resources held by the NAND device */
 extern void nand_release (struct mtd_info *mtd);
 
-/* Read raw data from the device without ECC */
-extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
-
-
 /* The maximum number of NAND chips in an array */
 #define NAND_MAX_CHIPS         8
 
@@ -79,44 +38,45 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
  * adjust this accordingly.
  */
 #define NAND_MAX_OOBSIZE       64
+#define NAND_MAX_PAGESIZE      2048
 
 /*
  * Constants for hardware specific CLE/ALE/NCE function
-*/
+ *
+ * These are bits which can be or'ed to set/clear multiple
+ * bits in one go.
+ */
 /* Select the chip by setting nCE to low */
-#define NAND_CTL_SETNCE        1
-/* Deselect the chip by setting nCE to high */
-#define NAND_CTL_CLRNCE                2
+#define NAND_NCE               0x01
 /* Select the command latch by setting CLE to high */
-#define NAND_CTL_SETCLE                3
-/* Deselect the command latch by setting CLE to low */
-#define NAND_CTL_CLRCLE                4
+#define NAND_CLE               0x02
 /* Select the address latch by setting ALE to high */
-#define NAND_CTL_SETALE                5
-/* Deselect the address latch by setting ALE to low */
-#define NAND_CTL_CLRALE                6
-/* Set write protection by setting WP to high. Not used! */
-#define NAND_CTL_SETWP         7
-/* Clear write protection by setting WP to low. Not used! */
-#define NAND_CTL_CLRWP         8
+#define NAND_ALE               0x04
+
+#define NAND_CTRL_CLE          (NAND_NCE | NAND_CLE)
+#define NAND_CTRL_ALE          (NAND_NCE | NAND_ALE)
+#define NAND_CTRL_CHANGE       0x80
 
 /*
  * Standard NAND flash commands
  */
 #define NAND_CMD_READ0         0
 #define NAND_CMD_READ1         1
+#define NAND_CMD_RNDOUT                5
 #define NAND_CMD_PAGEPROG      0x10
 #define NAND_CMD_READOOB       0x50
 #define NAND_CMD_ERASE1                0x60
 #define NAND_CMD_STATUS                0x70
 #define NAND_CMD_STATUS_MULTI  0x71
 #define NAND_CMD_SEQIN         0x80
+#define NAND_CMD_RNDIN         0x85
 #define NAND_CMD_READID                0x90
 #define NAND_CMD_ERASE2                0xd0
 #define NAND_CMD_RESET         0xff
 
 /* Extended commands for large page devices */
 #define NAND_CMD_READSTART     0x30
+#define NAND_CMD_RNDOUTSTART   0xE0
 #define NAND_CMD_CACHEDPROG    0x15
 
 /* Extended commands for AG-AND device */
@@ -138,6 +98,8 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
 #define NAND_CMD_STATUS_RESET  0x7f
 #define NAND_CMD_STATUS_CLEAR  0xff
 
+#define NAND_CMD_NONE          -1
+
 /* Status bits */
 #define NAND_STATUS_FAIL       0x01
 #define NAND_STATUS_FAIL_N1    0x02
@@ -148,21 +110,12 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
 /*
  * Constants for ECC_MODES
  */
-
-/* No ECC. Usage is not recommended ! */
-#define NAND_ECC_NONE          0
-/* Software ECC 3 byte ECC per 256 Byte data */
-#define NAND_ECC_SOFT          1
-/* Hardware ECC 3 byte ECC per 256 Byte data */
-#define NAND_ECC_HW3_256       2
-/* Hardware ECC 3 byte ECC per 512 Byte data */
-#define NAND_ECC_HW3_512       3
-/* Hardware ECC 3 byte ECC per 512 Byte data */
-#define NAND_ECC_HW6_512       4
-/* Hardware ECC 8 byte ECC per 512 Byte data */
-#define NAND_ECC_HW8_512       6
-/* Hardware ECC 12 byte ECC per 2048 Byte data */
-#define NAND_ECC_HW12_2048     7
+typedef enum {
+       NAND_ECC_NONE,
+       NAND_ECC_SOFT,
+       NAND_ECC_HW,
+       NAND_ECC_HW_SYNDROME,
+} nand_ecc_modes_t;
 
 /*
  * Constants for Hardware ECC
@@ -201,6 +154,10 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
  * bits from adjacent blocks from 'leaking' in altering data.
  * This happens with the Renesas AG-AND chips, possibly others.  */
 #define BBT_AUTO_REFRESH       0x00000080
+/* Chip does not require ready check on read. True
+ * for all large page devices, as they do not support
+ * autoincrement.*/
+#define NAND_NO_READRDY                0x00000100
 
 /* Options valid for Samsung large page devices */
 #define NAND_SAMSUNG_LP_OPTIONS \
@@ -219,18 +176,12 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_
 /* Use a flash based bad block table. This option is passed to the
  * default bad block table function. */
 #define NAND_USE_FLASH_BBT     0x00010000
-/* The hw ecc generator provides a syndrome instead a ecc value on read
- * This can only work if we have the ecc bytes directly behind the
- * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
-#define NAND_HWECC_SYNDROME    0x00020000
 /* This option skips the bbt scan during initialization. */
-#define NAND_SKIP_BBTSCAN      0x00040000
+#define NAND_SKIP_BBTSCAN      0x00020000
 
 /* Options set by nand scan */
-/* Nand scan has allocated oob_buf */
-#define NAND_OOBBUF_ALLOC      0x40000000
-/* Nand scan has allocated data_buf */
-#define NAND_DATABUF_ALLOC     0x80000000
+/* Nand scan has allocated controller struct */
+#define NAND_CONTROLLER_ALLOC  0x80000000
 
 
 /*
@@ -263,46 +214,103 @@ struct nand_hw_control {
        wait_queue_head_t wq;
 };
 
+/**
+ * struct nand_ecc_ctrl - Control structure for ecc
+ * @mode:      ecc mode
+ * @steps:     number of ecc steps per page
+ * @size:      data bytes per ecc step
+ * @bytes:     ecc bytes per step
+ * @total:     total number of ecc bytes per page
+ * @prepad:    padding information for syndrome based ecc generators
+ * @postpad:   padding information for syndrome based ecc generators
+ * @hwctl:     function to control hardware ecc generator. Must only
+ *             be provided if an hardware ECC is available
+ * @calculate: function for ecc calculation or readback from ecc hardware
+ * @correct:   function for ecc correction, matching to ecc generator (sw/hw)
+ * @read_page: function to read a page according to the ecc generator requirements
+ * @write_page:        function to write a page according to the ecc generator requirements
+ */
+struct nand_ecc_ctrl {
+       nand_ecc_modes_t        mode;
+       int                     steps;
+       int                     size;
+       int                     bytes;
+       int                     total;
+       int                     prepad;
+       int                     postpad;
+       struct nand_ecclayout   *layout;
+       void                    (*hwctl)(struct mtd_info *mtd, int mode);
+       int                     (*calculate)(struct mtd_info *mtd,
+                                            const uint8_t *dat,
+                                            uint8_t *ecc_code);
+       int                     (*correct)(struct mtd_info *mtd, uint8_t *dat,
+                                          uint8_t *read_ecc,
+                                          uint8_t *calc_ecc);
+       int                     (*read_page)(struct mtd_info *mtd,
+                                            struct nand_chip *chip,
+                                            uint8_t *buf);
+       void                    (*write_page)(struct mtd_info *mtd,
+                                             struct nand_chip *chip,
+                                             const uint8_t *buf);
+       int                     (*read_oob)(struct mtd_info *mtd,
+                                           struct nand_chip *chip,
+                                           int page,
+                                           int sndcmd);
+       int                     (*write_oob)(struct mtd_info *mtd,
+                                            struct nand_chip *chip,
+                                            int page);
+};
+
+/**
+ * struct nand_buffers - buffer structure for read/write
+ * @ecccalc:   buffer for calculated ecc
+ * @ecccode:   buffer for ecc read from flash
+ * @oobwbuf:   buffer for write oob data
+ * @databuf:   buffer for data - dynamically sized
+ * @oobrbuf:   buffer to read oob data
+ *
+ * Do not change the order of buffers. databuf and oobrbuf must be in
+ * consecutive order.
+ */
+struct nand_buffers {
+       uint8_t ecccalc[NAND_MAX_OOBSIZE];
+       uint8_t ecccode[NAND_MAX_OOBSIZE];
+       uint8_t oobwbuf[NAND_MAX_OOBSIZE];
+       uint8_t databuf[NAND_MAX_PAGESIZE];
+       uint8_t oobrbuf[NAND_MAX_OOBSIZE];
+};
+
 /**
  * struct nand_chip - NAND Private Flash Chip Data
  * @IO_ADDR_R:         [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
  * @IO_ADDR_W:         [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
  * @read_byte:         [REPLACEABLE] read one byte from the chip
- * @write_byte:                [REPLACEABLE] write one byte to the chip
  * @read_word:         [REPLACEABLE] read one word from the chip
- * @write_word:                [REPLACEABLE] write one word to the chip
  * @write_buf:         [REPLACEABLE] write data from the buffer to the chip
  * @read_buf:          [REPLACEABLE] read data from the chip into the buffer
  * @verify_buf:                [REPLACEABLE] verify buffer contents against the chip data
  * @select_chip:       [REPLACEABLE] select chip nr
  * @block_bad:         [REPLACEABLE] check, if the block is bad
  * @block_markbad:     [REPLACEABLE] mark the block bad
- * @hwcontrol:         [BOARDSPECIFIC] hardwarespecific function for accesing control-lines
+ * @cmd_ctrl:          [BOARDSPECIFIC] hardwarespecific funtion for controlling
+ *                     ALE/CLE/nCE. Also used to write command and address
  * @dev_ready:         [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
  *                     If set to NULL no access to ready/busy is available and the ready/busy information
  *                     is read from the chip status register
  * @cmdfunc:           [REPLACEABLE] hardwarespecific function for writing commands to the chip
  * @waitfunc:          [REPLACEABLE] hardwarespecific function for wait on ready
- * @calculate_ecc:     [REPLACEABLE] function for ecc calculation or readback from ecc hardware
- * @correct_data:      [REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
- * @enable_hwecc:      [BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
- *                     be provided if a hardware ECC is available
+ * @ecc:               [BOARDSPECIFIC] ecc control ctructure
  * @erase_cmd:         [INTERN] erase command write function, selectable due to AND support
  * @scan_bbt:          [REPLACEABLE] function to scan bad block table
- * @eccmode:           [BOARDSPECIFIC] mode of ecc, see defines
- * @eccsize:           [INTERN] databytes used per ecc-calculation
- * @eccbytes:          [INTERN] number of ecc bytes per ecc-calculation step
- * @eccsteps:          [INTERN] number of ecc calculation steps per page
  * @chip_delay:                [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
- * @chip_lock:         [INTERN] spinlock used to protect access to this structure and the chip
  * @wq:                        [INTERN] wait queue to sleep on if a NAND operation is in progress
- * @state:             [INTERN] the current state of the NAND device
+ * @state:             [INTERN] the current state of the NAND device
  * @page_shift:                [INTERN] number of address bits in a page (column address bits)
  * @phys_erase_shift:  [INTERN] number of address bits in a physical eraseblock
  * @bbt_erase_shift:   [INTERN] number of address bits in a bbt entry
  * @chip_shift:                [INTERN] number of address bits in one chip
- * @data_buf:          [INTERN] internal buffer for one page + oob
- * @oob_buf:           [INTERN] oob buffer for one eraseblock
+ * @datbuf:            [INTERN] internal buffer for one page + oob
+ * @oobbuf:            [INTERN] oob buffer for one eraseblock
  * @oobdirty:          [INTERN] indicates that oob_buf must be reinitialized
  * @data_poi:          [INTERN] pointer to a data buffer
  * @options:           [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
@@ -312,12 +320,13 @@ struct nand_hw_control {
  * @chipsize:          [INTERN] the size of one chip for multichip arrays
  * @pagemask:          [INTERN] page number mask = number of (pages / chip) - 1
  * @pagebuf:           [INTERN] holds the pagenumber which is currently in data_buf
- * @autooob:           [REPLACEABLE] the default (auto)placement scheme
+ * @ecclayout:         [REPLACEABLE] the default ecc placement scheme
  * @bbt:               [INTERN] bad block table pointer
  * @bbt_td:            [REPLACEABLE] bad block table descriptor for flash lookup
  * @bbt_md:            [REPLACEABLE] bad block table mirror descriptor
  * @badblock_pattern:  [REPLACEABLE] bad block scan pattern used for initial bad block scan
- * @controller:                [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
+ * @controller:                [REPLACEABLE] a pointer to a hardware controller structure
+ *                     which is shared among multiple independend devices
  * @priv:              [OPTIONAL] pointer to private chip date
  * @errstat:           [OPTIONAL] hardware specific function to perform additional error status checks
  *                     (determine if errors are correctable)
@@ -325,58 +334,57 @@ struct nand_hw_control {
 
 struct nand_chip {
        void  __iomem   *IO_ADDR_R;
-       void  __iomem   *IO_ADDR_W;
+       void  __iomem   *IO_ADDR_W;
 
-       u_char          (*read_byte)(struct mtd_info *mtd);
-       void            (*write_byte)(struct mtd_info *mtd, u_char byte);
+       uint8_t         (*read_byte)(struct mtd_info *mtd);
        u16             (*read_word)(struct mtd_info *mtd);
-       void            (*write_word)(struct mtd_info *mtd, u16 word);
-
-       void            (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
-       void            (*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
-       int             (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
+       void            (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+       void            (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
+       int             (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
        void            (*select_chip)(struct mtd_info *mtd, int chip);
        int             (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
        int             (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
-       void            (*hwcontrol)(struct mtd_info *mtd, int cmd);
-       int             (*dev_ready)(struct mtd_info *mtd);
-       void            (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
-       int             (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
-       int             (*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
-       int             (*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
-       void            (*enable_hwecc)(struct mtd_info *mtd, int mode);
+       void            (*cmd_ctrl)(struct mtd_info *mtd, int dat,
+                                   unsigned int ctrl);
+       int             (*dev_ready)(struct mtd_info *mtd);
+       void            (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
+       int             (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
        void            (*erase_cmd)(struct mtd_info *mtd, int page);
        int             (*scan_bbt)(struct mtd_info *mtd);
-       int             eccmode;
-       int             eccsize;
-       int             eccbytes;
-       int             eccsteps;
-       int             chip_delay;
-       spinlock_t      chip_lock;
-       wait_queue_head_t wq;
-       nand_state_t    state;
-       int             page_shift;
+       int             (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
+
+       int             chip_delay;
+       unsigned int    options;
+
+       int             page_shift;
        int             phys_erase_shift;
        int             bbt_erase_shift;
        int             chip_shift;
-       u_char          *data_buf;
-       u_char          *oob_buf;
-       int             oobdirty;
-       u_char          *data_poi;
-       unsigned int    options;
-       int             badblockpos;
        int             numchips;
        unsigned long   chipsize;
        int             pagemask;
        int             pagebuf;
-       struct nand_oobinfo     *autooob;
+       int             badblockpos;
+
+       nand_state_t    state;
+
+       uint8_t         *oob_poi;
+       struct nand_hw_control  *controller;
+       struct nand_ecclayout   *ecclayout;
+
+       struct nand_ecc_ctrl ecc;
+       struct nand_buffers buffers;
+       struct nand_hw_control hwcontrol;
+
+       struct mtd_oob_ops ops;
+
        uint8_t         *bbt;
        struct nand_bbt_descr   *bbt_td;
        struct nand_bbt_descr   *bbt_md;
+
        struct nand_bbt_descr   *badblock_pattern;
-       struct nand_hw_control  *controller;
+
        void            *priv;
-       int             (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
 };
 
 /*
@@ -388,19 +396,19 @@ struct nand_chip {
 #define NAND_MFR_NATIONAL      0x8f
 #define NAND_MFR_RENESAS       0x07
 #define NAND_MFR_STMICRO       0x20
-#define NAND_MFR_HYNIX          0xad
+#define NAND_MFR_HYNIX         0xad
 
 /**
  * struct nand_flash_dev - NAND Flash Device ID Structure
  *
- * @name:      Identify the device type
- * @id:        device ID code
- * @pagesize:          Pagesize in bytes. Either 256 or 512 or 0
+ * @name:      Identify the device type
+ * @id:                device ID code
+ * @pagesize:  Pagesize in bytes. Either 256 or 512 or 0
  *             If the pagesize is 0, then the real pagesize
  *             and the eraseize are determined from the
  *             extended id bytes in the chip
- * @erasesize:         Size of an erase block in the flash device.
- * @chipsize:          Total chipsize in Mega Bytes
+ * @erasesize: Size of an erase block in the flash device.
+ * @chipsize:  Total chipsize in Mega Bytes
  * @options:   Bitfield to store chip relevant options
  */
 struct nand_flash_dev {
@@ -415,7 +423,7 @@ struct nand_flash_dev {
 /**
  * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
  * @name:      Manufacturer name
- * @id:        manufacturer ID code of device.
+ * @id:                manufacturer ID code of device.
 */
 struct nand_manufacturers {
        int id;
@@ -455,7 +463,7 @@ struct nand_bbt_descr {
        int     veroffs;
        uint8_t version[NAND_MAX_CHIPS];
        int     len;
-       int     maxblocks;
+       int     maxblocks;
        int     reserved_block_code;
        uint8_t *pattern;
 };
@@ -494,14 +502,14 @@ struct nand_bbt_descr {
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS        4
 
-extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
-extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs);
-extern int nand_default_bbt (struct mtd_info *mtd);
-extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);
-extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
-extern int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-                             size_t * retlen, u_char * buf, u_char * oob_buf,
-                             struct nand_oobinfo *oobsel, int flags);
+extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
+extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
+extern int nand_default_bbt(struct mtd_info *mtd);
+extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
+extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
+                          int allowbbt);
+extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
+                       size_t * retlen, uint8_t * buf);
 
 /*
 * Constants for oob configuration
@@ -509,4 +517,53 @@ extern int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
 #define NAND_SMALL_BADBLOCK_POS                5
 #define NAND_LARGE_BADBLOCK_POS                0
 
+/**
+ * struct platform_nand_chip - chip level device structure
+ *
+ * @nr_chips:          max. number of chips to scan for
+ * @chip_offs:         chip number offset
+ * @nr_partitions:     number of partitions pointed to by partitions (or zero)
+ * @partitions:                mtd partition list
+ * @chip_delay:                R/B delay value in us
+ * @options:           Option flags, e.g. 16bit buswidth
+ * @ecclayout:         ecc layout info structure
+ * @priv:              hardware controller specific settings
+ */
+struct platform_nand_chip {
+       int                     nr_chips;
+       int                     chip_offset;
+       int                     nr_partitions;
+       struct mtd_partition    *partitions;
+       struct nand_ecclayout   *ecclayout;
+       int                     chip_delay;
+       unsigned int            options;
+       void                    *priv;
+};
+
+/**
+ * struct platform_nand_ctrl - controller level device structure
+ *
+ * @hwcontrol:         platform specific hardware control structure
+ * @dev_ready:         platform specific function to read ready/busy pin
+ * @select_chip:       platform specific chip select function
+ * @priv_data:         private data to transport driver specific settings
+ *
+ * All fields are optional and depend on the hardware driver requirements
+ */
+struct platform_nand_ctrl {
+       void            (*hwcontrol)(struct mtd_info *mtd, int cmd);
+       int             (*dev_ready)(struct mtd_info *mtd);
+       void            (*select_chip)(struct mtd_info *mtd, int chip);
+       void            *priv;
+};
+
+/* Some helpers to access the data structures */
+static inline
+struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd->priv;
+
+       return chip->priv;
+}
+
 #endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mtd/ndfc.h b/include/linux/mtd/ndfc.h
new file mode 100644 (file)
index 0000000..d0558a9
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  linux/include/linux/mtd/ndfc.h
+ *
+ *  Copyright (c) 2006 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Info:
+ *   Contains defines, datastructures for ndfc nand controller
+ *
+ */
+#ifndef __LINUX_MTD_NDFC_H
+#define __LINUX_MTD_NDFC_H
+
+/* NDFC Register definitions */
+#define NDFC_CMD               0x00
+#define NDFC_ALE               0x04
+#define NDFC_DATA              0x08
+#define NDFC_ECC               0x10
+#define NDFC_BCFG0             0x30
+#define NDFC_BCFG1             0x34
+#define NDFC_BCFG2             0x38
+#define NDFC_BCFG3             0x3c
+#define NDFC_CCR               0x40
+#define NDFC_STAT              0x44
+#define NDFC_HWCTL             0x48
+#define NDFC_REVID             0x50
+
+#define NDFC_STAT_IS_READY     0x01000000
+
+#define NDFC_CCR_RESET_CE      0x80000000 /* CE Reset */
+#define NDFC_CCR_RESET_ECC     0x40000000 /* ECC Reset */
+#define NDFC_CCR_RIE           0x20000000 /* Interrupt Enable on Device Rdy */
+#define NDFC_CCR_REN           0x10000000 /* Enable wait for Rdy in LinearR */
+#define NDFC_CCR_ROMEN         0x08000000 /* Enable ROM In LinearR */
+#define NDFC_CCR_ARE           0x04000000 /* Auto-Read Enable */
+#define NDFC_CCR_BS(x)         (((x) & 0x3) << 24) /* Select Bank on CE[x] */
+#define NDFC_CCR_BS_MASK       0x03000000 /* Select Bank */
+#define NDFC_CCR_ARAC0         0x00000000 /* 3 Addr, 1 Col 2 Row 512b page */
+#define NDFC_CCR_ARAC1         0x00001000 /* 4 Addr, 1 Col 3 Row 512b page */
+#define NDFC_CCR_ARAC2         0x00002000 /* 4 Addr, 2 Col 2 Row 2K page */
+#define NDFC_CCR_ARAC3         0x00003000 /* 5 Addr, 2 Col 3 Row 2K page */
+#define NDFC_CCR_ARAC_MASK     0x00003000 /* Auto-Read mode Addr Cycles */
+#define NDFC_CCR_RPG           0x0000C000 /* Auto-Read Page */
+#define NDFC_CCR_EBCC          0x00000004 /* EBC Configuration Completed */
+#define NDFC_CCR_DHC           0x00000002 /* Direct Hardware Control Enable */
+
+#define NDFC_BxCFG_EN          0x80000000 /* Bank Enable */
+#define NDFC_BxCFG_CED         0x40000000 /* nCE Style */
+#define NDFC_BxCFG_SZ_MASK     0x08000000 /* Bank Size */
+#define NDFC_BxCFG_SZ_8BIT     0x00000000 /* 8bit */
+#define NDFC_BxCFG_SZ_16BIT    0x08000000 /* 16bit */
+
+#define NDFC_MAX_BANKS         4
+
+struct ndfc_controller_settings {
+       uint32_t        ccr_settings;
+       uint64_t        ndfc_erpn;
+};
+
+struct ndfc_chip_settings {
+       uint32_t        bank_settings;
+};
+
+#endif
index d35d2c21ff3e0abd4caa594fdd31e37d506c3a53..bcf2fb3fa4a786300ca2a3d23e470bd25843faa2 100644 (file)
@@ -37,7 +37,7 @@ struct NFTLrecord {
         unsigned int nb_blocks;                /* number of physical blocks */
         unsigned int nb_boot_blocks;   /* number of blocks used by the bios */
         struct erase_info instr;
-       struct nand_oobinfo oobinfo;
+       struct nand_ecclayout oobinfo;
 };
 
 int NFTL_mount(struct NFTLrecord *s);
index 7419b5fab1337a8f55899f219e2d297faef5a064..9ce9a48db444a4cec4889661482281411ea5fc8e 100644 (file)
@@ -35,6 +35,8 @@ typedef enum {
        FL_SYNCING,
        FL_UNLOCKING,
        FL_LOCKING,
+       FL_RESETING,
+       FL_OTPING,
        FL_PM_SUSPENDED,
 } onenand_state_t;
 
@@ -75,7 +77,7 @@ struct onenand_bufferram {
  * @param chip_lock    [INTERN] spinlock used to protect access to this structure and the chip
  * @param wq           [INTERN] wait queue to sleep on if a OneNAND operation is in progress
  * @param state                [INTERN] the current state of the OneNAND device
- * @param autooob      [REPLACEABLE] the default (auto)placement scheme
+ * @param ecclayout    [REPLACEABLE] the default ecc placement scheme
  * @param bbm          [REPLACEABLE] pointer to Bad Block Management
  * @param priv         [OPTIONAL] pointer to private chip date
  */
@@ -111,9 +113,9 @@ struct onenand_chip {
        onenand_state_t         state;
        unsigned char           *page_buf;
 
-       struct nand_oobinfo     *autooob;
+       struct nand_ecclayout   *ecclayout;
 
-       void                    *bbm;
+       void                    *bbm;
 
        void                    *priv;
 };
@@ -130,6 +132,9 @@ struct onenand_chip {
 #define ONENAND_SET_SYS_CFG1(v, this)                                  \
        (this->write_word(v, this->base + ONENAND_REG_SYS_CFG1))
 
+/* Check byte access in OneNAND */
+#define ONENAND_CHECK_BYTE_ACCESS(addr)                (addr & 0x1)
+
 /*
  * Options bits
  */
index d7832ef8ed635e9bb37a182b3ffe766afaf6be3d..4a72818d25453205f64d7e538913885ebd1c2657 100644 (file)
 #define ONENAND_CMD_LOCK_TIGHT         (0x2C)
 #define ONENAND_CMD_ERASE              (0x94)
 #define ONENAND_CMD_RESET              (0xF0)
+#define ONENAND_CMD_OTP_ACCESS         (0x65)
 #define ONENAND_CMD_READID             (0x90)
 
 /* NOTE: Those are not *REAL* commands */
 #define ONENAND_CTRL_ERASE             (1 << 11)
 #define ONENAND_CTRL_ERROR             (1 << 10)
 #define ONENAND_CTRL_RSTB              (1 << 7)
+#define ONENAND_CTRL_OTP_L             (1 << 6)
+#define ONENAND_CTRL_OTP_BL            (1 << 5)
 
 /*
  * Interrupt Status Register F241h (R)
 #define ONENAND_ECC_2BIT               (1 << 1)
 #define ONENAND_ECC_2BIT_ALL           (0xAAAA)
 
+/*
+ * One-Time Programmable (OTP)
+ */
+#define ONENAND_OTP_LOCK_OFFSET                (14)
+
 #endif /* __ONENAND_REG_H */
index b03f512d51b9c96d865cebd5cf4cb85596b4d436..da6b3d6f12a7642442642032f58b4e917ee6b3e4 100644 (file)
@@ -41,7 +41,7 @@ struct mtd_partition {
        u_int32_t size;                 /* partition size */
        u_int32_t offset;               /* offset within the master MTD space */
        u_int32_t mask_flags;           /* master MTD flags to mask out for this partition */
-       struct nand_oobinfo *oobsel;    /* out of band layout for this partition (NAND only)*/
+       struct nand_ecclayout *ecclayout;       /* out of band layout for this partition (NAND only)*/
        struct mtd_info **mtdp;         /* pointer to store the MTD object */
 };
 
index c7b8bcdef013bfd6629a62cf8899ac5153305a82..86831e3594f67f7cdf15f6d4570b69c7b6f7caa4 100644 (file)
  */
 
 #ifndef __LINUX_MTD_PHYSMAP__
-
-#include <linux/config.h>
-
-#if defined(CONFIG_MTD_PHYSMAP)
+#define __LINUX_MTD_PHYSMAP__
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 
-/*
- * The map_info for physmap.  Board can override size, buswidth, phys,
- * (*set_vpp)(), etc in their initial setup routine.
- */
-extern struct map_info physmap_map;
+struct physmap_flash_data {
+       unsigned int            width;
+       void                    (*set_vpp)(struct map_info *, int);
+       unsigned int            nr_parts;
+       struct mtd_partition    *parts;
+};
 
 /*
  * Board needs to specify the exact mapping during their setup time.
  */
-static inline void physmap_configure(unsigned long addr, unsigned long size, int bankwidth, void (*set_vpp)(struct map_info *, int) )
-{
-       physmap_map.phys = addr;
-       physmap_map.size = size;
-       physmap_map.bankwidth = bankwidth;
-       physmap_map.set_vpp = set_vpp;
-}
+void physmap_configure(unsigned long addr, unsigned long size,
+               int bankwidth, void (*set_vpp)(struct map_info *, int) );
 
-#if defined(CONFIG_MTD_PARTITIONS)
+#ifdef CONFIG_MTD_PARTITIONS
 
 /*
  * Machines that wish to do flash partition may want to call this function in
@@ -55,7 +48,5 @@ static inline void physmap_configure(unsigned long addr, unsigned long size, int
 void physmap_set_partitions(struct mtd_partition *parts, int num_parts);
 
 #endif /* defined(CONFIG_MTD_PARTITIONS) */
-#endif /* defined(CONFIG_MTD) */
 
 #endif /* __LINUX_MTD_PHYSMAP__ */
-
index 220d50bb71cd06bd86625e55b98fc77a03543598..e9d40bdde48cba0f5d3083028e152aa6bac60269 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef __LINUX_MTD_XIP_H__
 #define __LINUX_MTD_XIP_H__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_MTD_XIP
 
index a6ce409ec6fcbffd1b00897eec3ed3d739b11aee..1d7cdd20b5530677a8140feed5ac1483089108ca 100644 (file)
@@ -77,11 +77,11 @@ struct nbd_device {
  * server. All data are in network byte order.
  */
 struct nbd_request {
-       u32 magic;
-       u32 type;       /* == READ || == WRITE  */
+       __u32 magic;
+       __u32 type;     /* == READ || == WRITE  */
        char handle[8];
-       u64 from;
-       u32 len;
+       __u64 from;
+       __u32 len;
 }
 #ifdef __GNUC__
        __attribute__ ((packed))
@@ -93,8 +93,8 @@ struct nbd_request {
  * it has completed an I/O request (or an error occurs).
  */
 struct nbd_reply {
-       u32 magic;
-       u32 error;              /* 0 = ok, else error   */
+       __u32 magic;
+       __u32 error;            /* 0 = ok, else error   */
        char handle[8];         /* handle you got from request  */
 };
 #endif
index 96dc237b8f0347571c80601d985785eaaea07cb8..b208f0cd556b4d65a0fe5db4fb99935b3e441a11 100644 (file)
@@ -12,8 +12,6 @@
 #include <linux/in.h>
 #include <linux/types.h>
 
-#include <linux/ncp_fs_i.h>
-#include <linux/ncp_fs_sb.h>
 #include <linux/ipx.h>
 #include <linux/ncp_no.h>
 
@@ -146,7 +144,8 @@ struct ncp_nls_ioctl
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
+#include <linux/ncp_fs_i.h>
+#include <linux/ncp_fs_sb.h>
 
 /* undef because public define in umsdos_fs.h (ncp_fs.h isn't public) */
 #undef PRINTK
index 84a490e5f0a1234e68b0f83caf0e01b5f8d8812a..385e68f5bd93264c96f1e29c3f720f3b3921a8be 100644 (file)
@@ -18,9 +18,7 @@
 #ifndef _LINUX_NET_H
 #define _LINUX_NET_H
 
-#include <linux/config.h>
 #include <linux/wait.h>
-#include <linux/stringify.h>
 #include <asm/socket.h>
 
 struct poll_table_struct;
@@ -57,6 +55,7 @@ typedef enum {
 #define __SO_ACCEPTCON (1 << 16)       /* performed a listen           */
 
 #ifdef __KERNEL__
+#include <linux/stringify.h>
 
 #define SOCK_ASYNC_NOSPACE     0
 #define SOCK_ASYNC_WAITDATA    1
index f4169bbb60eb8036d021ba64e9270f6b5ffcaabb..5e8e2d50429a14c0fed74692e5a1616a842b9295 100644 (file)
@@ -34,9 +34,9 @@
 #include <asm/cache.h>
 #include <asm/byteorder.h>
 
-#include <linux/config.h>
 #include <linux/device.h>
 #include <linux/percpu.h>
+#include <linux/dmaengine.h>
 
 struct divert_blk;
 struct vlan_group;
@@ -311,6 +311,9 @@ struct net_device
 #define NETIF_F_LLTX           4096    /* LockLess TX */
 #define NETIF_F_UFO             8192    /* Can offload UDP Large Send*/
 
+#define NETIF_F_GEN_CSUM       (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
+#define NETIF_F_ALL_CSUM       (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
+
        struct net_device       *next_sched;
 
        /* Interface index. Unique device identifier    */
@@ -406,7 +409,7 @@ struct net_device
  * One part is mostly used on xmit path (device)
  */
        /* hard_start_xmit synchronizer */
-       spinlock_t              xmit_lock ____cacheline_aligned_in_smp;
+       spinlock_t              _xmit_lock ____cacheline_aligned_in_smp;
        /* cpu id of processor entered to hard_start_xmit or -1,
           if nobody entered there.
         */
@@ -593,6 +596,9 @@ struct softnet_data
        struct sk_buff          *completion_queue;
 
        struct net_device       backlog_dev;    /* Sorry. 8) */
+#ifdef CONFIG_NET_DMA
+       struct dma_chan         *net_dma;
+#endif
 };
 
 DECLARE_PER_CPU(struct softnet_data,softnet_data);
@@ -889,11 +895,43 @@ static inline void __netif_rx_complete(struct net_device *dev)
        clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
 }
 
+static inline void netif_tx_lock(struct net_device *dev)
+{
+       spin_lock(&dev->_xmit_lock);
+       dev->xmit_lock_owner = smp_processor_id();
+}
+
+static inline void netif_tx_lock_bh(struct net_device *dev)
+{
+       spin_lock_bh(&dev->_xmit_lock);
+       dev->xmit_lock_owner = smp_processor_id();
+}
+
+static inline int netif_tx_trylock(struct net_device *dev)
+{
+       int err = spin_trylock(&dev->_xmit_lock);
+       if (!err)
+               dev->xmit_lock_owner = smp_processor_id();
+       return err;
+}
+
+static inline void netif_tx_unlock(struct net_device *dev)
+{
+       dev->xmit_lock_owner = -1;
+       spin_unlock(&dev->_xmit_lock);
+}
+
+static inline void netif_tx_unlock_bh(struct net_device *dev)
+{
+       dev->xmit_lock_owner = -1;
+       spin_unlock_bh(&dev->_xmit_lock);
+}
+
 static inline void netif_tx_disable(struct net_device *dev)
 {
-       spin_lock_bh(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
        netif_stop_queue(dev);
-       spin_unlock_bh(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
 }
 
 /* These functions live elsewhere (drivers/net/net_init.c, but related) */
index b31a9bca9361307a6ce997c029634a58e2cd4939..10168e26a8466eb889c3c9c5530a645d85679c25 100644 (file)
@@ -40,7 +40,6 @@
 #endif
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #ifdef CONFIG_NETFILTER
 
 extern void netfilter_init(void);
index 3ff88c8783083fc620a880ecfbdb44d7840cc8f2..d2e4bd7a7a1423b9c23a12f4e048cc89cb391b3a 100644 (file)
@@ -69,6 +69,10 @@ enum ip_conntrack_status {
        /* Connection is dying (removed from lists), can not be unset. */
        IPS_DYING_BIT = 9,
        IPS_DYING = (1 << IPS_DYING_BIT),
+
+       /* Connection has fixed timeout. */
+       IPS_FIXED_TIMEOUT_BIT = 10,
+       IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
 };
 
 /* Connection tracking event bits */
index 668ec946c8e24d47f53d71290e566de54dbc250a..b5883ccee2957b26df1757af390b541ca01a1c3d 100644 (file)
@@ -27,13 +27,15 @@ enum ctattr_type {
        CTA_STATUS,
        CTA_PROTOINFO,
        CTA_HELP,
-       CTA_NAT,
+       CTA_NAT_SRC,
+#define CTA_NAT        CTA_NAT_SRC     /* backwards compatibility */
        CTA_TIMEOUT,
        CTA_MARK,
        CTA_COUNTERS_ORIG,
        CTA_COUNTERS_REPLY,
        CTA_USE,
        CTA_ID,
+       CTA_NAT_DST,
        __CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
diff --git a/include/linux/netfilter/xt_CONNSECMARK.h b/include/linux/netfilter/xt_CONNSECMARK.h
new file mode 100644 (file)
index 0000000..c6bd754
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _XT_CONNSECMARK_H_target
+#define _XT_CONNSECMARK_H_target
+
+enum {
+       CONNSECMARK_SAVE = 1,
+       CONNSECMARK_RESTORE,
+};
+
+struct xt_connsecmark_target_info {
+       u_int8_t mode;
+};
+
+#endif /*_XT_CONNSECMARK_H_target */
diff --git a/include/linux/netfilter/xt_SECMARK.h b/include/linux/netfilter/xt_SECMARK.h
new file mode 100644 (file)
index 0000000..c53fbff
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _XT_SECMARK_H_target
+#define _XT_SECMARK_H_target
+
+/*
+ * This is intended for use by various security subsystems (but not
+ * at the same time).
+ *
+ * 'mode' refers to the specific security subsystem which the
+ * packets are being marked for.
+ */
+#define SECMARK_MODE_SEL       0x01            /* SELinux */
+#define SECMARK_SELCTX_MAX     256
+
+struct xt_secmark_target_selinux_info {
+       u_int32_t selsid;
+       char selctx[SECMARK_SELCTX_MAX];
+};
+
+struct xt_secmark_target_info {
+       u_int8_t mode;
+       union {
+               struct xt_secmark_target_selinux_info sel;
+       } u;
+};
+
+#endif /*_XT_SECMARK_H_target */
index 34f63cf2e2932a4c56cef8eadd8343e385a0d6f0..4c2d9945ca54a50034d488ce8e472e404bafed9b 100644 (file)
@@ -42,7 +42,7 @@ struct ip_conntrack_old_tuple
                } u;
 
                /* The protocol. */
-               u16 protonum;
+               __u16 protonum;
        } dst;
 };
 
diff --git a/include/linux/netfilter/xt_quota.h b/include/linux/netfilter/xt_quota.h
new file mode 100644 (file)
index 0000000..acd7fd7
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _XT_QUOTA_H
+#define _XT_QUOTA_H
+
+enum xt_quota_flags {
+       XT_QUOTA_INVERT         = 0x1,
+};
+#define XT_QUOTA_MASK          0x1
+
+struct xt_quota_info {
+       u_int32_t               flags;
+       u_int32_t               pad;
+       aligned_u64             quota;
+       struct xt_quota_info    *master;
+};
+
+#endif /* _XT_QUOTA_H */
diff --git a/include/linux/netfilter/xt_statistic.h b/include/linux/netfilter/xt_statistic.h
new file mode 100644 (file)
index 0000000..c344e99
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _XT_STATISTIC_H
+#define _XT_STATISTIC_H
+
+enum xt_statistic_mode {
+       XT_STATISTIC_MODE_RANDOM,
+       XT_STATISTIC_MODE_NTH,
+       __XT_STATISTIC_MODE_MAX
+};
+#define XT_STATISTIC_MODE_MAX (__XT_STATISTIC_MODE_MAX - 1)
+
+enum xt_statistic_flags {
+       XT_STATISTIC_INVERT             = 0x1,
+};
+#define XT_STATISTIC_MASK              0x1
+
+struct xt_statistic_info {
+       u_int16_t                       mode;
+       u_int16_t                       flags;
+       union {
+               struct {
+                       u_int32_t       probability;
+               } random;
+               struct {
+                       u_int32_t       every;
+                       u_int32_t       packet;
+                       u_int32_t       count;
+               } nth;
+       } u;
+       struct xt_statistic_info        *master __attribute__((aligned(8)));
+};
+
+#endif /* _XT_STATISTIC_H */
index a3f8977f7f12a179405ce01cd60778d7518cdad1..92bc6ddcbf73221e6ee3c3c70eb9fb1c289fc131 100644 (file)
@@ -5,7 +5,6 @@
  * (C)2002 Rusty Russell IBM -- This code is GPL.
  */
 
-#include <linux/config.h>
 #include <linux/netfilter.h>
 
 /* There is no PF_ARP. */
index a75b84bb9a884db6c71b4153613a8365b980a2a9..87764022cc670050ec0573d2a454f16fabfa61c3 100644 (file)
@@ -4,7 +4,6 @@
 /* bridge-specific defines for netfilter. 
  */
 
-#include <linux/config.h>
 #include <linux/netfilter.h>
 #if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER)
 #include <asm/atomic.h>
index 85301c5e8d246b8093a0e2d788cc68153efa5cab..ce02c984f3bae354307b3a398c62c166dcc8d83b 100644 (file)
@@ -5,7 +5,6 @@
  * (C)1998 Rusty Russell -- This code is GPL.
  */
 
-#include <linux/config.h>
 #include <linux/netfilter.h>
 
 /* only for userspace compatibility */
index d54d7b278e96b599803997b83f9789b4a6329196..51dbec1892c802c3d313c3593fb0d2967a90ad2e 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/netfilter/nf_conntrack_common.h>
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
 #include <linux/bitops.h>
 #include <linux/compiler.h>
@@ -121,6 +120,10 @@ struct ip_conntrack
        u_int32_t mark;
 #endif
 
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+       u_int32_t secmark;
+#endif
+
        /* Traversed often, so hopefully in different cacheline to top */
        /* These are my tuples; original and reply */
        struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
@@ -154,6 +157,7 @@ struct ip_conntrack_expect
        unsigned int flags;
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
+       u_int32_t saved_ip;
        /* This is the original per-proto part, used to map the
         * expected connection the way the recipient expects. */
        union ip_conntrack_manip_proto saved_proto;
@@ -293,6 +297,7 @@ static inline int is_dying(struct ip_conntrack *ct)
 }
 
 extern unsigned int ip_conntrack_htable_size;
+extern int ip_conntrack_checksum;
  
 #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
 
index eace86bd2adbe0462abe44d5c1d6b7d5fc2523b0..3cbff7379002ced59a07d65ab88587767df8b59e 100644 (file)
@@ -71,6 +71,13 @@ extern int (*nat_h245_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
                             unsigned char **data, int dataoff,
                             TransportAddress * addr, u_int16_t port,
                             struct ip_conntrack_expect * exp);
+extern int (*nat_callforwarding_hook) (struct sk_buff ** pskb,
+                                      struct ip_conntrack * ct,
+                                      enum ip_conntrack_info ctinfo,
+                                      unsigned char **data, int dataoff,
+                                      TransportAddress * addr,
+                                      u_int16_t port,
+                                      struct ip_conntrack_expect * exp);
 extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
                             enum ip_conntrack_info ctinfo,
                             unsigned char **data, TransportAddress * addr,
index cc98f7aa5abee04b86cd6dc767fca92cea536bc0..3d4a773799fcf5a0827e3ba4fe3f9c9b583523af 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
+/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006
  *
  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
@@ -412,6 +412,7 @@ typedef struct Facility_UUIE {      /* SEQUENCE */
                eFacility_UUIE_destinationInfo = (1 << 14),
                eFacility_UUIE_h245SecurityMode = (1 << 13),
        } options;
+       TransportAddress alternativeAddress;
        FacilityReason reason;
        TransportAddress h245Address;
        Facility_UUIE_fastStart fastStart;
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
new file mode 100644 (file)
index 0000000..913dad6
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __IP_CONNTRACK_SIP_H__
+#define __IP_CONNTRACK_SIP_H__
+#ifdef __KERNEL__
+
+#define SIP_PORT       5060
+#define SIP_TIMEOUT    3600
+
+#define POS_VIA                0
+#define POS_CONTACT    1
+#define POS_CONTENT    2
+#define POS_MEDIA      3
+#define POS_OWNER      4
+#define POS_CONNECTION 5
+#define POS_REQ_HEADER 6
+#define POS_SDP_HEADER 7
+
+struct sip_header_nfo {
+       const char      *lname;
+       const char      *sname;
+       const char      *ln_str;
+       size_t          lnlen;
+       size_t          snlen;
+       size_t          ln_strlen;
+       int             (*match_len)(const char *, const char *, int *);
+};
+
+extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
+                                      enum ip_conntrack_info ctinfo,
+                                      struct ip_conntrack *ct,
+                                      const char **dptr);
+extern unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
+                                      enum ip_conntrack_info ctinfo,
+                                      struct ip_conntrack_expect *exp,
+                                      const char *dptr);
+
+extern int ct_sip_get_info(const char *dptr, size_t dlen,
+                          unsigned int *matchoff,
+                          unsigned int *matchlen,
+                          struct sip_header_nfo *hnfo);
+extern int ct_sip_lnlen(const char *line, const char *limit);
+extern const char *ct_sip_search(const char *needle, const char *haystack,
+                                 size_t needle_len, size_t haystack_len);
+#endif /* __KERNEL__ */
+#endif /* __IP_CONNTRACK_SIP_H__ */
index 360429f4873755e758018a6915a591aaa6338e84..5d92cf044d919ad511cf4e4d8d5f0e315c2c8ace 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef _LISTHELP_H
 #define _LISTHELP_H
-#include <linux/config.h>
 #include <linux/list.h>
 
 /* Header to do more comprehensive job than linux/list.h; assume list
index ca2ffa6ae1d5ef0da33d8d265c1ac6579217fa3b..54af92c1c70b29c1f0eb9f4369a015714531fa34 100644 (file)
@@ -7,9 +7,6 @@
 #ifndef _LINUX_NFS_H
 #define _LINUX_NFS_H
 
-#include <linux/sunrpc/msg_prot.h>
-#include <linux/string.h>
-
 #define NFS_PROGRAM    100003
 #define NFS_PORT       2049
 #define NFS_MAXDATA    8192
@@ -129,7 +126,10 @@ enum nfs_ftype {
        NFFIFO = 8
 };
 
-#if defined(__KERNEL__)
+#ifdef __KERNEL__
+#include <linux/sunrpc/msg_prot.h>
+#include <linux/string.h>
+
 /*
  * This is the kernel NFS client file handle representation
  */
index 0c1c306cdaec7e77749319f68978e8785d2486dd..1059e6d69d3bc8d38380bf0a213632dd6f729e66 100644 (file)
@@ -14,7 +14,6 @@
 #define _LINUX_NFS4_H
 
 #include <linux/types.h>
-#include <linux/list.h>
 
 #define NFS4_VERIFIER_SIZE     8
 #define NFS4_FHSIZE            128
@@ -97,6 +96,9 @@ enum nfs4_acl_whotype {
        NFS4_ACL_WHO_EVERYONE,
 };
 
+#ifdef __KERNEL__
+#include <linux/list.h>
+
 struct nfs4_ace {
        uint32_t        type;
        uint32_t        flag;
@@ -345,8 +347,6 @@ enum lock_type4 {
 #define NFS4_MINOR_VERSION 0
 #define NFS4_DEBUG 1
 
-#ifdef __KERNEL__
-
 /* Index of predefined Linux client operations */
 
 enum {
index c71227dd43896ff5a64ad6de0258e9e785aa96ad..7e079f8ce18bc0aa09f80b43dc7ccc2a48bd7cb5 100644 (file)
@@ -9,26 +9,6 @@
 #ifndef _LINUX_NFS_FS_H
 #define _LINUX_NFS_FS_H
 
-#include <linux/config.h>
-#include <linux/in.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/rwsem.h>
-#include <linux/wait.h>
-
-#include <linux/nfs_fs_sb.h>
-
-#include <linux/sunrpc/debug.h>
-#include <linux/sunrpc/auth.h>
-#include <linux/sunrpc/clnt.h>
-
-#include <linux/nfs.h>
-#include <linux/nfs2.h>
-#include <linux/nfs3.h>
-#include <linux/nfs4.h>
-#include <linux/nfs_xdr.h>
-#include <linux/rwsem.h>
-#include <linux/mempool.h>
 
 /*
  * Enable debugging support for nfs client.
 #define FLUSH_NOCOMMIT         32      /* Don't send the NFSv3/v4 COMMIT */
 
 #ifdef __KERNEL__
+#include <linux/in.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/rwsem.h>
+#include <linux/wait.h>
+
+#include <linux/nfs_fs_sb.h>
+
+#include <linux/sunrpc/debug.h>
+#include <linux/sunrpc/auth.h>
+#include <linux/sunrpc/clnt.h>
+
+#include <linux/nfs.h>
+#include <linux/nfs2.h>
+#include <linux/nfs3.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_xdr.h>
+#include <linux/rwsem.h>
+#include <linux/mempool.h>
 
 /*
  * NFSv3/v4 Access mode cache entry
index ec7c2e872d728486e851dd14d79d053a41f09124..2dcad295fecef2685ffb4121d4ea977cc6b8c279 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef LINUX_NFSD_NFSD_H
 #define LINUX_NFSD_NFSD_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/unistd.h>
 #include <linux/dirent.h>
index 0798b7781a6e89dbfd258b72e521511cd7d9134a..f9edcd2ff3c828c9496ca4da4f007d326e16ea4e 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <asm/types.h>
 #ifdef __KERNEL__
-# include <linux/config.h>
 # include <linux/types.h>
 # include <linux/string.h>
 # include <linux/fs.h>
index 781efbf94ed359c47b4a9db04aa6d0632a3da787..dae0faea28070a594c49d886458e1ebc4934a477 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <asm/types.h>
 #ifdef __KERNEL__
-# include <linux/config.h>
 # include <linux/types.h>
 # include <linux/in.h>
 #endif 
index e481feb1bfd81e061e3c2488ece336f936fdc9d6..a31a7301b159e8b1b8036a14cf734dd55ec0d0e2 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_NUMA_H
 #define _LINUX_NUMA_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_NODES_SHIFT
 #define NODES_SHIFT     CONFIG_NODES_SHIFT
index 008d736a6c9a59766a7a4114223fd8bddc456ecc..d42737eeee067783195346a34ae3b973cb828fa6 100644 (file)
@@ -96,7 +96,6 @@ typedef enum {
 /* The rest is for the kernel only */
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/jiffies.h>
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
index 4877e35ae2028b97fe58b7756b52196c2d44ce8e..936ef82ed76a6f21cf07b0132da3a12efc748cb9 100644 (file)
@@ -50,7 +50,7 @@
 extern acpi_status pci_osc_control_set(acpi_handle handle, u32 flags);
 extern acpi_status pci_osc_support_set(u32 flags);
 #else
-#if !defined(acpi_status)
+#if !defined(AE_ERROR)
 typedef u32            acpi_status;
 #define AE_ERROR       (acpi_status) (0x0001)
 #endif    
index 3a6a4e37a482f3a6d4e54cc044c1c438d87eb999..6c4bc773f7b7b91c86e23e437b6d176bc58810e5 100644 (file)
@@ -17,8 +17,6 @@
 #ifndef LINUX_PCI_H
 #define LINUX_PCI_H
 
-#include <linux/mod_devicetable.h>
-
 /* Include the pci register defines */
 #include <linux/pci_regs.h>
 
@@ -46,8 +44,9 @@
 
 #ifdef __KERNEL__
 
+#include <linux/mod_devicetable.h>
+
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/list.h>
 #include <linux/errno.h>
@@ -442,6 +441,7 @@ struct pci_dev *pci_find_device_reverse (unsigned int vendor, unsigned int devic
 struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
 int pci_find_capability (struct pci_dev *dev, int cap);
 int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
+int pci_find_ext_capability (struct pci_dev *dev, int cap);
 struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
 
 struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
@@ -662,6 +662,7 @@ static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
 static inline void pci_unregister_driver(struct pci_driver *drv) { }
 static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
 static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; }
+static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
 static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; }
 
 /* Power management related routines */
index d6fe048376ab02010a1709b6dcce4e94f4b70601..bcfe9d4f56aea1ba730f329aaf6f7af084c05f50 100644 (file)
 #define PCI_DEVICE_ID_PLX_DJINN_ITOO   0x1151
 #define PCI_DEVICE_ID_PLX_R753         0x1152
 #define PCI_DEVICE_ID_PLX_OLITEC       0x1187
+#define PCI_DEVICE_ID_PLX_PCI200SYN    0x3196
 #define PCI_DEVICE_ID_PLX_9050         0x9050
 #define PCI_DEVICE_ID_PLX_9080         0x9080
 #define PCI_DEVICE_ID_PLX_GTEK_SERIAL2 0xa001
 #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100         0x034E
 #define PCI_DEVICE_ID_NVIDIA_NVENET_14              0x0372
 #define PCI_DEVICE_ID_NVIDIA_NVENET_15              0x0373
+#define PCI_DEVICE_ID_NVIDIA_NVENET_16              0x03E5
+#define PCI_DEVICE_ID_NVIDIA_NVENET_17              0x03E6
+#define PCI_DEVICE_ID_NVIDIA_NVENET_18              0x03EE
+#define PCI_DEVICE_ID_NVIDIA_NVENET_19              0x03EF
+#define PCI_DEVICE_ID_NVIDIA_NVENET_20              0x0450
+#define PCI_DEVICE_ID_NVIDIA_NVENET_21              0x0451
+#define PCI_DEVICE_ID_NVIDIA_NVENET_22              0x0452
+#define PCI_DEVICE_ID_NVIDIA_NVENET_23              0x0453
 
 #define PCI_VENDOR_ID_IMS              0x10e0
 #define PCI_DEVICE_ID_IMS_TT128                0x9128
 #define PCI_DEVICE_ID_VIA_8380_0       0x0204
 #define PCI_DEVICE_ID_VIA_3238_0       0x0238
 #define PCI_DEVICE_ID_VIA_PT880                0x0258
+#define PCI_DEVICE_ID_VIA_PT880ULTRA   0x0308
 #define PCI_DEVICE_ID_VIA_PX8X0_0      0x0259
 #define PCI_DEVICE_ID_VIA_3269_0       0x0269
 #define PCI_DEVICE_ID_VIA_K8T800PRO_0  0x0282
 
 #define PCI_VENDOR_ID_SAMSUNG          0x144d
 
+#define PCI_VENDOR_ID_MYRICOM          0x14c1
 
 #define PCI_VENDOR_ID_TITAN            0x14D2
 #define PCI_DEVICE_ID_TITAN_010L       0x8001
 #define PCI_DEVICE_ID_TIGON3_5751F     0x167e
 #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_TIGON3_5787      0x169b
 #define PCI_DEVICE_ID_TIGON3_5788      0x169c
 #define PCI_DEVICE_ID_TIGON3_5789      0x169d
 #define PCI_DEVICE_ID_INTEL_80960_RP   0x1960
 #define PCI_DEVICE_ID_INTEL_82840_HB   0x1a21
 #define PCI_DEVICE_ID_INTEL_82845_HB   0x1a30
+#define PCI_DEVICE_ID_INTEL_IOAT       0x1a38
 #define PCI_DEVICE_ID_INTEL_82801AA_0  0x2410
 #define PCI_DEVICE_ID_INTEL_82801AA_1  0x2411
 #define PCI_DEVICE_ID_INTEL_82801AA_3  0x2413
index 682525511c9e90d352f2d46730932e9711ce457e..66b5de404f22fa1c9af9e5224e879bdb6b3f290e 100644 (file)
@@ -6,7 +6,6 @@
  * WARNING: these things are HUGE.  4 kbytes per counter on 32-way P4.
  */
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/smp.h>
 #include <linux/threads.h>
index bac0fb389cf1c094e55f6cb3af4ad8e00c0f913f..d5dd471da22527132782c1a0837d1c4c22167544 100644 (file)
@@ -159,7 +159,7 @@ struct sadb_spirange {
 struct sadb_x_kmprivate {
        uint16_t        sadb_x_kmprivate_len;
        uint16_t        sadb_x_kmprivate_exttype;
-       u_int32_t       sadb_x_kmprivate_reserved;
+       uint32_t        sadb_x_kmprivate_reserved;
 } __attribute__((packed));
 /* sizeof(struct sadb_x_kmprivate) == 8 */
 
index 66be58902b17c1f5a282c6fc5172a7fe61fcc56b..658c1b93d5bb22d4e8efbe30d299e06a2e4ba834 100644 (file)
@@ -23,7 +23,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <asm/atomic.h>
 
index 008932d73c3564db945995b5cc1db52c8811c882..78027c533b94678fce8b685da41dc11fda656234 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __LINUX_PM_LEGACY_H__
 #define __LINUX_PM_LEGACY_H__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PM_LEGACY
 
index 217d3daf73363e98cc5a9674470d080f41dcc16b..ecce5912f4d6149254eaab42dee3b443e20354bb 100644 (file)
@@ -6,7 +6,6 @@
  * Copyright (C) 1998 Paul Mackerras.
  */
 
-#include <linux/config.h>
 
 #define PMU_DRIVER_VERSION     2
 
index 402056cd049d9a7c4ad4b940e58536b554243e4a..c6b13ff850280931ba0ac58813d880499a2708c1 100644 (file)
@@ -42,8 +42,6 @@
 #ifndef _PPP_DEFS_H_
 #define _PPP_DEFS_H_
 
-#include <linux/crc-ccitt.h>
-
 /*
  * The basic PPP frame.
  */
 
 #define PPP_INITFCS    0xffff  /* Initial FCS value */
 #define PPP_GOODFCS    0xf0b8  /* Good final FCS value */
+
+#ifdef __KERNEL__
+#include <linux/crc-ccitt.h>
 #define PPP_FCS(fcs, c) crc_ccitt_byte(fcs, c)
+#endif
 
 /*
  * Extended asyncmap - allows any character to be escaped.
@@ -179,12 +181,4 @@ struct ppp_idle {
     time_t recv_idle;          /* time since last NP packet received */
 };
 
-#ifndef __P
-#ifdef __STDC__
-#define __P(x) x
-#else
-#define __P(x) ()
-#endif
-#endif
-
 #endif /* _PPP_DEFS_H_ */
index 5769d14d1e6ab658b7ab8b2a2c9de117ec2b4838..d0926d63406ca8e76a3d89ddc3f307a43ef6f391 100644 (file)
@@ -6,7 +6,6 @@
  * preempt_count (used for kernel preemption, interrupt count, etc.)
  */
 
-#include <linux/config.h>
 #include <linux/thread_info.h>
 #include <linux/linkage.h>
 
index 4b47a0253425f9be28430757b1275d72a1245dae..5810d28fbed9c193ddc9d550b5eb1c97aee45a55 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_PROC_FS_H
 #define _LINUX_PROC_FS_H
 
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/spinlock.h>
index 1f2fea6640a49212338cb9193080844182147803..e633004ae052876eb9c4415a1f2f32d49611c8a4 100644 (file)
@@ -4,7 +4,6 @@
 #ifdef __KERNEL__
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/cpumask.h>
 #include <asm/errno.h>
index 2dab71e1c3d12565cf428084e7716274b257be57..b8fbf26eb88579265a95e490700bb370d52544d2 100644 (file)
@@ -37,8 +37,6 @@
 
 #include <linux/errno.h>
 #include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
 
 #define __DQUOT_VERSION__      "dquot_6.5.1"
 #define __DQUOT_NUM_VERSION__  6*10000+5*100+1
@@ -133,6 +131,8 @@ struct if_dqinfo {
 };
 
 #ifdef __KERNEL__
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
 
 #include <linux/dqblk_xfs.h>
 #include <linux/dqblk_v1.h>
index 21e5a9124856bbcc6a2c2c3cdf02fff4a56d62d3..5110201a415949e5e10bd8381ff4f38e120320cf 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _LINUX_QUOTAOPS_
 #define _LINUX_QUOTAOPS_
 
-#include <linux/config.h>
 #include <linux/smp_lock.h>
 
 #include <linux/fs.h>
index 4b7cc4fe366d2bc2a028b757edca43b9523ac6a4..f37006f21664877fc138b437df04b210bc81cdb2 100644 (file)
@@ -99,19 +99,36 @@ static inline struct page * rb_insert_page_cache(struct inode * inode,
 
 struct rb_node
 {
-       struct rb_node *rb_parent;
-       int rb_color;
+       unsigned long  rb_parent_color;
 #define        RB_RED          0
 #define        RB_BLACK        1
        struct rb_node *rb_right;
        struct rb_node *rb_left;
-};
+} __attribute__((aligned(sizeof(long))));
+    /* The alignment might seem pointless, but allegedly CRIS needs it */
 
 struct rb_root
 {
        struct rb_node *rb_node;
 };
 
+
+#define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))
+#define rb_color(r)   ((r)->rb_parent_color & 1)
+#define rb_is_red(r)   (!rb_color(r))
+#define rb_is_black(r) rb_color(r)
+#define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
+#define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)
+
+static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
+{
+       rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
+}
+static inline void rb_set_color(struct rb_node *rb, int color)
+{
+       rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
+}
+
 #define RB_ROOT        (struct rb_root) { NULL, }
 #define        rb_entry(ptr, type, member) container_of(ptr, type, member)
 
@@ -131,8 +148,7 @@ extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
 static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
                                struct rb_node ** rb_link)
 {
-       node->rb_parent = parent;
-       node->rb_color = RB_RED;
+       node->rb_parent_color = (unsigned long )parent;
        node->rb_left = node->rb_right = NULL;
 
        *rb_link = node;
index 5353afb11db391671a6957ac0500f09ca0b12b38..5e961035c72576052cec535a48faf0814719f809 100644 (file)
@@ -2,8 +2,6 @@
   File: linux/reiserfs_xattr.h
 */
 
-#include <linux/config.h>
-#include <linux/init.h>
 #include <linux/xattr.h>
 
 /* Magic value in header */
@@ -15,6 +13,7 @@ struct reiserfs_xattr_header {
 };
 
 #ifdef __KERNEL__
+#include <linux/init.h>
 
 struct reiserfs_xattr_handler {
        char *prefix;
index 4bcc1531d6a9d812b774def51f926246393f2d3a..24accb483849c86415406a33ff685bc927900441 100644 (file)
@@ -10,7 +10,6 @@
 #ifndef _LINUX_RELAY_H
 #define _LINUX_RELAY_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
index c7e907faae9cccace8425249a54066f7c4b3a2b3..d93857056cb99b1a45de079ab9e8101231d3f003 100644 (file)
@@ -17,7 +17,6 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/list.h>
 #include <linux/errno.h>
index f54772d0e7f821981e6db96b5586977f3acb5051..7adb2a1aac92603449fe1810944b2c7513a6e393 100644 (file)
@@ -16,7 +16,6 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/list.h>
 #include <linux/errno.h>
index d6b9bcd1384c2767fcef3c2a024ff2c780b65d47..2d4c81a220db21bd91157e06390488a5a1b71f1c 100644 (file)
@@ -4,7 +4,6 @@
  * Declarations for Reverse Mapping functions in mm/rmap.c
  */
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
index df0cdd41085c702f654e86a6c1acc279649f0a42..facd9ee37b76f474543dba4d00ce8c75c0ffe649 100644 (file)
@@ -909,7 +909,6 @@ struct tcamsg
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/mutex.h>
 
 extern size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size);
index bfb98888500290d3c945f93e2f544de1384bcacb..f99fe90732abfe7cc0bdbc0e103fd0b717950bd4 100644 (file)
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <asm/system.h>
index 885a4a02b23c7830653d5cee03ebfda2764c1e3a..3495bd953cc6bfef1c64a7cebb88fa4e9cc2fe3a 100644 (file)
@@ -3,7 +3,6 @@
 #ifndef        _SCC_H
 #define        _SCC_H
 
-#include <linux/config.h>
 
 /* selection of hardware types */
 
index 29b7d4f87d207a69a1b8a2c0167416f1332f030d..267f1525704064422cffa4e85250a967f3bf8d92 100644 (file)
@@ -1,9 +1,46 @@
 #ifndef _LINUX_SCHED_H
 #define _LINUX_SCHED_H
 
+#include <linux/auxvec.h>      /* For AT_VECTOR_SIZE */
+
+/*
+ * cloning flags:
+ */
+#define CSIGNAL                0x000000ff      /* signal mask to be sent at exit */
+#define CLONE_VM       0x00000100      /* set if VM shared between processes */
+#define CLONE_FS       0x00000200      /* set if fs info shared between processes */
+#define CLONE_FILES    0x00000400      /* set if open files shared between processes */
+#define CLONE_SIGHAND  0x00000800      /* set if signal handlers and blocked signals shared */
+#define CLONE_PTRACE   0x00002000      /* set if we want to let tracing continue on the child too */
+#define CLONE_VFORK    0x00004000      /* set if the parent wants the child to wake it up on mm_release */
+#define CLONE_PARENT   0x00008000      /* set if we want to have the same parent as the cloner */
+#define CLONE_THREAD   0x00010000      /* Same thread group? */
+#define CLONE_NEWNS    0x00020000      /* New namespace group? */
+#define CLONE_SYSVSEM  0x00040000      /* share system V SEM_UNDO semantics */
+#define CLONE_SETTLS   0x00080000      /* create a new TLS for the child */
+#define CLONE_PARENT_SETTID    0x00100000      /* set the TID in the parent */
+#define CLONE_CHILD_CLEARTID   0x00200000      /* clear the TID in the child */
+#define CLONE_DETACHED         0x00400000      /* Unused, ignored */
+#define CLONE_UNTRACED         0x00800000      /* set if the tracing process can't force CLONE_PTRACE on this clone */
+#define CLONE_CHILD_SETTID     0x01000000      /* set the TID in the child */
+#define CLONE_STOPPED          0x02000000      /* Start in stopped state */
+
+/*
+ * Scheduling policies
+ */
+#define SCHED_NORMAL           0
+#define SCHED_FIFO             1
+#define SCHED_RR               2
+#define SCHED_BATCH            3
+
+#ifdef __KERNEL__
+
+struct sched_param {
+       int sched_priority;
+};
+
 #include <asm/param.h> /* for HZ */
 
-#include <linux/config.h>
 #include <linux/capability.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
 #include <linux/rcupdate.h>
 #include <linux/futex.h>
 
-#include <linux/auxvec.h>      /* For AT_VECTOR_SIZE */
+#include <linux/time.h>
+#include <linux/param.h>
+#include <linux/resource.h>
+#include <linux/timer.h>
+#include <linux/hrtimer.h>
 
-struct exec_domain;
+#include <asm/processor.h>
 
-/*
- * cloning flags:
- */
-#define CSIGNAL                0x000000ff      /* signal mask to be sent at exit */
-#define CLONE_VM       0x00000100      /* set if VM shared between processes */
-#define CLONE_FS       0x00000200      /* set if fs info shared between processes */
-#define CLONE_FILES    0x00000400      /* set if open files shared between processes */
-#define CLONE_SIGHAND  0x00000800      /* set if signal handlers and blocked signals shared */
-#define CLONE_PTRACE   0x00002000      /* set if we want to let tracing continue on the child too */
-#define CLONE_VFORK    0x00004000      /* set if the parent wants the child to wake it up on mm_release */
-#define CLONE_PARENT   0x00008000      /* set if we want to have the same parent as the cloner */
-#define CLONE_THREAD   0x00010000      /* Same thread group? */
-#define CLONE_NEWNS    0x00020000      /* New namespace group? */
-#define CLONE_SYSVSEM  0x00040000      /* share system V SEM_UNDO semantics */
-#define CLONE_SETTLS   0x00080000      /* create a new TLS for the child */
-#define CLONE_PARENT_SETTID    0x00100000      /* set the TID in the parent */
-#define CLONE_CHILD_CLEARTID   0x00200000      /* clear the TID in the child */
-#define CLONE_DETACHED         0x00400000      /* Unused, ignored */
-#define CLONE_UNTRACED         0x00800000      /* set if the tracing process can't force CLONE_PTRACE on this clone */
-#define CLONE_CHILD_SETTID     0x01000000      /* set the TID in the child */
-#define CLONE_STOPPED          0x02000000      /* Start in stopped state */
+struct exec_domain;
 
 /*
  * List of flags we want to share for kernel threads,
@@ -103,13 +124,6 @@ extern unsigned long nr_uninterruptible(void);
 extern unsigned long nr_active(void);
 extern unsigned long nr_iowait(void);
 
-#include <linux/time.h>
-#include <linux/param.h>
-#include <linux/resource.h>
-#include <linux/timer.h>
-#include <linux/hrtimer.h>
-
-#include <asm/processor.h>
 
 /*
  * Task state bitmask. NOTE! These bits are also
@@ -156,20 +170,6 @@ extern unsigned long nr_iowait(void);
 /* Task command name length */
 #define TASK_COMM_LEN 16
 
-/*
- * Scheduling policies
- */
-#define SCHED_NORMAL           0
-#define SCHED_FIFO             1
-#define SCHED_RR               2
-#define SCHED_BATCH            3
-
-struct sched_param {
-       int sched_priority;
-};
-
-#ifdef __KERNEL__
-
 #include <linux/spinlock.h>
 
 /*
@@ -494,7 +494,7 @@ struct user_struct {
        atomic_t processes;     /* How many processes does this user have? */
        atomic_t files;         /* How many open files does this user have? */
        atomic_t sigpending;    /* How many pending signals does this user have? */
-#ifdef CONFIG_INOTIFY
+#ifdef CONFIG_INOTIFY_USER
        atomic_t inotify_watches; /* How many inotify watches does this user have? */
        atomic_t inotify_devs;  /* How many inotify devs does this user have opened? */
 #endif
index cd2773b29a642bb53c73e7c0dfe798b662b6733c..3e8b1cf54303cf42f155c36630162b3fadcbeded 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_SECCOMP_H
 #define _LINUX_SECCOMP_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SECCOMP
 
index 1bab48f6aeac1e16df3d6edb62cafdfc1db71f41..4dfb1b84a9b3bef236ef041b3005692462d7b51b 100644 (file)
@@ -805,31 +805,37 @@ struct swap_info_struct;
  *     used by the XFRM system.
  *     @sec_ctx contains the security context information being provided by
  *     the user-level policy update program (e.g., setkey).
- *     Allocate a security structure to the xp->selector.security field.
+ *     Allocate a security structure to the xp->security field.
  *     The security field is initialized to NULL when the xfrm_policy is
  *     allocated.
  *     Return 0 if operation was successful (memory to allocate, legal context)
  * @xfrm_policy_clone_security:
  *     @old contains an existing xfrm_policy in the SPD.
  *     @new contains a new xfrm_policy being cloned from old.
- *     Allocate a security structure to the new->selector.security field
- *     that contains the information from the old->selector.security field.
+ *     Allocate a security structure to the new->security field
+ *     that contains the information from the old->security field.
  *     Return 0 if operation was successful (memory to allocate).
  * @xfrm_policy_free_security:
  *     @xp contains the xfrm_policy
- *     Deallocate xp->selector.security.
+ *     Deallocate xp->security.
+ * @xfrm_policy_delete_security:
+ *     @xp contains the xfrm_policy.
+ *     Authorize deletion of xp->security.
  * @xfrm_state_alloc_security:
  *     @x contains the xfrm_state being added to the Security Association
  *     Database by the XFRM system.
  *     @sec_ctx contains the security context information being provided by
  *     the user-level SA generation program (e.g., setkey or racoon).
- *     Allocate a security structure to the x->sel.security field.  The
+ *     Allocate a security structure to the x->security field.  The
  *     security field is initialized to NULL when the xfrm_state is
  *     allocated.
  *     Return 0 if operation was successful (memory to allocate, legal context).
  * @xfrm_state_free_security:
  *     @x contains the xfrm_state.
- *     Deallocate x>sel.security.
+ *     Deallocate x->security.
+ * @xfrm_state_delete_security:
+ *     @x contains the xfrm_state.
+ *     Authorize deletion of x->security.
  * @xfrm_policy_lookup:
  *     @xp contains the xfrm_policy for which the access control is being
  *     checked.
@@ -1298,8 +1304,10 @@ struct security_operations {
        int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
        int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
        void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
+       int (*xfrm_policy_delete_security) (struct xfrm_policy *xp);
        int (*xfrm_state_alloc_security) (struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
        void (*xfrm_state_free_security) (struct xfrm_state *x);
+       int (*xfrm_state_delete_security) (struct xfrm_state *x);
        int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 sk_sid, u8 dir);
 #endif /* CONFIG_SECURITY_NETWORK_XFRM */
 
@@ -2934,11 +2942,21 @@ static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
        security_ops->xfrm_policy_free_security(xp);
 }
 
+static inline int security_xfrm_policy_delete(struct xfrm_policy *xp)
+{
+       return security_ops->xfrm_policy_delete_security(xp);
+}
+
 static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
 {
        return security_ops->xfrm_state_alloc_security(x, sec_ctx);
 }
 
+static inline int security_xfrm_state_delete(struct xfrm_state *x)
+{
+       return security_ops->xfrm_state_delete_security(x);
+}
+
 static inline void security_xfrm_state_free(struct xfrm_state *x)
 {
        security_ops->xfrm_state_free_security(x);
@@ -2963,6 +2981,11 @@ static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
 {
 }
 
+static inline int security_xfrm_policy_delete(struct xfrm_policy *xp)
+{
+       return 0;
+}
+
 static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
 {
        return 0;
@@ -2972,6 +2995,11 @@ static inline void security_xfrm_state_free(struct xfrm_state *x)
 {
 }
 
+static inline int security_xfrm_state_delete(struct xfrm_state *x)
+{
+       return 0;
+}
+
 static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
 {
        return 0;
index 4047bcde44843bfca0b550a0cc901bc95253ad44..aad4e390d6a5e2c9ff7f3fb5b84dc8d41f2e2cb1 100644 (file)
@@ -118,6 +118,27 @@ void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid);
  */
 void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
 
+/**
+ *     selinux_string_to_sid - map a security context string to a security ID
+ *     @str: the security context string to be mapped
+ *     @sid: ID value returned via this.
+ *
+ *     Returns 0 if successful, with the SID stored in sid.  A value
+ *     of zero for sid indicates no SID could be determined (but no error
+ *     occurred).
+ */
+int selinux_string_to_sid(char *str, u32 *sid);
+
+/**
+ *     selinux_relabel_packet_permission - check permission to relabel a packet
+ *     @sid: ID value to be applied to network packet (via SECMARK, most likely)
+ *
+ *     Returns 0 if the current task is allowed to label packets with the
+ *     supplied security ID.  Note that it is implicit that the packet is always
+ *     being relabeled from the default unlabled value, and that the access
+ *     control decision is made in the AVC.
+ */
+int selinux_relabel_packet_permission(u32 sid);
 
 #else
 
@@ -172,6 +193,17 @@ static inline void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
        *sid = 0;
 }
 
+static inline int selinux_string_to_sid(const char *str, u32 *sid)
+{
+       *sid = 0;
+       return 0;
+}
+
+static inline int selinux_relabel_packet_permission(u32 sid)
+{
+       return 0;
+}
+
 #endif /* CONFIG_SECURITY_SELINUX */
 
 #endif /* _LINUX_SELINUX_H */
index 3c1f1120fe8846de2ef1f9a3ec2d4cf47171f8b0..9aaffb0b1d81e9ebfee3c9731209a23fac42223e 100644 (file)
@@ -2,7 +2,6 @@
 #define _LINUX_SEM_H
 
 #include <linux/ipc.h>
-#include <asm/atomic.h>
 
 /* semop flags */
 #define SEM_UNDO        0x1000  /* undo the operation on exit */
@@ -78,6 +77,7 @@ struct  seminfo {
 #define SEMUSZ  20             /* sizeof struct sem_undo */
 
 #ifdef __KERNEL__
+#include <asm/atomic.h>
 
 struct task_struct;
 
index 5a095572881d0757030522bbd5d7dd4467b547ae..7bc5c7c12b541fc2b282180b8b4d458ba9ec8618 100644 (file)
@@ -26,7 +26,6 @@
  * by Keith Owens and Andrea Arcangeli
  */
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/preempt.h>
 
index 2b9e6b9554d577fa49130c4c4e2a4c745d7b3088..e811a615f696c9ad35114b4067d67c6d31344edc 100644 (file)
@@ -19,7 +19,6 @@
  * For definitions of the flags field, see tty.h
  */
 
-#include <linux/config.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
index bd14858121ea2065fdd399c58c48dd6e1f513812..94b9286cf6bdeaa9842286d0d182a2c536f28261 100644 (file)
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/interrupt.h>
 #include <linux/circ_buf.h>
index 70739f51a09f5fe963c89c8bea9e8c1a3a97e36d..1e4ce7225eeef979c26cfc8a8cde48eba797dad2 100644 (file)
@@ -1,12 +1,12 @@
 #ifndef _LINUX_SIGNAL_H
 #define _LINUX_SIGNAL_H
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
 #include <asm/signal.h>
 #include <asm/siginfo.h>
 
 #ifdef __KERNEL__
+#include <linux/list.h>
+#include <linux/spinlock.h>
 
 /*
  * These values of sa_flags are used only by the kernel as part of the
index f8f234708b984c58addf22edcef14a93d29b4df2..66f8819f9568d0f248b363d65478c8b660962c35 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef _LINUX_SKBUFF_H
 #define _LINUX_SKBUFF_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/time.h>
@@ -29,6 +28,7 @@
 #include <linux/net.h>
 #include <linux/textsearch.h>
 #include <net/checksum.h>
+#include <linux/dmaengine.h>
 
 #define HAVE_ALLOC_SKB         /* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB     /* Ditto 8)                */
@@ -209,6 +209,7 @@ enum {
  *     @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *     @tc_index: Traffic control index
  *     @tc_verd: traffic control verdict
+ *     @secmark: security marking
  */
 
 struct sk_buff {
@@ -285,6 +286,12 @@ struct sk_buff {
        __u16                   tc_verd;        /* traffic control verdict */
 #endif
 #endif
+#ifdef CONFIG_NET_DMA
+       dma_cookie_t            dma_cookie;
+#endif
+#ifdef CONFIG_NETWORK_SECMARK
+       __u32                   secmark;
+#endif
 
 
        /* These elements must be at the end, see alloc_skb() for details.  */
@@ -967,15 +974,16 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
 #define NET_SKB_PAD    16
 #endif
 
-extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
+extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
 
 static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
 {
-       if (!skb->data_len) {
-               skb->len  = len;
-               skb->tail = skb->data + len;
-       } else
-               ___pskb_trim(skb, len, 0);
+       if (unlikely(skb->data_len)) {
+               WARN_ON(1);
+               return;
+       }
+       skb->len  = len;
+       skb->tail = skb->data + len;
 }
 
 /**
@@ -985,6 +993,7 @@ static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
  *
  *     Cut the length of a buffer down by removing data from the tail. If
  *     the buffer is already under the length specified it is not modified.
+ *     The skb must be linear.
  */
 static inline void skb_trim(struct sk_buff *skb, unsigned int len)
 {
@@ -995,12 +1004,10 @@ static inline void skb_trim(struct sk_buff *skb, unsigned int len)
 
 static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
 {
-       if (!skb->data_len) {
-               skb->len  = len;
-               skb->tail = skb->data+len;
-               return 0;
-       }
-       return ___pskb_trim(skb, len, 1);
+       if (skb->data_len)
+               return ___pskb_trim(skb, len);
+       __skb_trim(skb, len);
+       return 0;
 }
 
 static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
@@ -1161,18 +1168,34 @@ static inline int skb_can_coalesce(struct sk_buff *skb, int i,
        return 0;
 }
 
+static inline int __skb_linearize(struct sk_buff *skb)
+{
+       return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM;
+}
+
 /**
  *     skb_linearize - convert paged skb to linear one
  *     @skb: buffer to linarize
- *     @gfp: allocation mode
  *
  *     If there is no free memory -ENOMEM is returned, otherwise zero
  *     is returned and the old skb data released.
  */
-extern int __skb_linearize(struct sk_buff *skb, gfp_t gfp);
-static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp)
+static inline int skb_linearize(struct sk_buff *skb)
+{
+       return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0;
+}
+
+/**
+ *     skb_linearize_cow - make sure skb is linear and writable
+ *     @skb: buffer to process
+ *
+ *     If there is no free memory -ENOMEM is returned, otherwise zero
+ *     is returned and the old skb data released.
+ */
+static inline int skb_linearize_cow(struct sk_buff *skb)
 {
-       return __skb_linearize(skb, gfp);
+       return skb_is_nonlinear(skb) || skb_cloned(skb) ?
+              __skb_linearize(skb) : 0;
 }
 
 /**
@@ -1396,5 +1419,23 @@ static inline void nf_reset(struct sk_buff *skb)
 static inline void nf_reset(struct sk_buff *skb) {}
 #endif /* CONFIG_NETFILTER */
 
+#ifdef CONFIG_NETWORK_SECMARK
+static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from)
+{
+       to->secmark = from->secmark;
+}
+
+static inline void skb_init_secmark(struct sk_buff *skb)
+{
+       skb->secmark = 0;
+}
+#else
+static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from)
+{ }
+
+static inline void skb_init_secmark(struct sk_buff *skb)
+{ }
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SKBUFF_H */
index 2d985d59c7b86759663761c3ec333ec196730026..9dc93163e0651fd631790336cc2200c620075bf3 100644 (file)
@@ -11,7 +11,6 @@
 
 typedef struct kmem_cache kmem_cache_t;
 
-#include       <linux/config.h>        /* kmalloc_sizes.h needs CONFIG_ options */
 #include       <linux/gfp.h>
 #include       <linux/init.h>
 #include       <linux/types.h>
index 621a3d3662f328c13c742a96b325307d8dc583e5..367d6c3e8ed4d51e939bbe07e86f9fbc8cca0a1b 100644 (file)
@@ -10,8 +10,6 @@
 #define _LINUX_SMB_FS_H
 
 #include <linux/smb.h>
-#include <linux/smb_fs_i.h>
-#include <linux/smb_fs_sb.h>
 
 /*
  * ioctl commands
@@ -24,6 +22,8 @@
 
 
 #ifdef __KERNEL__
+#include <linux/smb_fs_i.h>
+#include <linux/smb_fs_sb.h>
 
 #include <linux/fs.h>
 #include <linux/pagemap.h>
index e2fa3ab4afc5e9125e0dd6a98e3929b3eeba20fa..c93c3fe4308c898cd2a6fa9939305e9b4203bbc5 100644 (file)
@@ -6,7 +6,6 @@
  *             Alan Cox. <alan@redhat.com>
  */
 
-#include <linux/config.h>
 
 extern void cpu_idle(void);
 
index fa1ff3b165fe167739099c19625282eaa5ecd2e7..cf715a40d833909e9ce04d6bea75a4f7656d2ee2 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __LINUX_SMPLOCK_H
 #define __LINUX_SMPLOCK_H
 
-#include <linux/config.h>
 #ifdef CONFIG_LOCK_KERNEL
 #include <linux/sched.h>
 #include <linux/spinlock.h>
index 9ab2ddd802212667c06c48b317f757ae2677225d..36140909464983b8db555ac6423c463b1934c6e5 100644 (file)
@@ -18,8 +18,6 @@ struct __kernel_sockaddr_storage {
 
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 
-#include <linux/config.h>              /* for CONFIG_COMPAT */
-#include <linux/linkage.h>
 #include <asm/socket.h>                        /* arch-dependent defines       */
 #include <linux/sockios.h>             /* the SIOCxxx I/O controls     */
 #include <linux/uio.h>                 /* iovec support                */
index 799be674794459e9a857a4c7218ad31d0cd05883..ae23beef9cc98be3917ae54f9ce44f91a527c783 100644 (file)
@@ -46,7 +46,6 @@
  *  linux/spinlock.h:     builds the final spin_*() APIs.
  */
 
-#include <linux/config.h>
 #include <linux/preempt.h>
 #include <linux/linkage.h>
 #include <linux/compiler.h>
index 151a803ed0edc61bf983360208889d814881d9ff..5bfc553bdb21f0d5d4353f12c6a13fd802613000 100644 (file)
@@ -4,7 +4,6 @@
    very heavy lock, which is equivalent to grabbing every spinlock
    (and more).  So the "read" side to such a lock is anything which
    diables preeempt. */
-#include <linux/config.h>
 #include <linux/cpu.h>
 #include <asm/system.h>
 
index be4772ed43c005add341102aaae7dcd15d1ed818..a6de332e57d456a6243cc4496aa1b3ddf8491d96 100644 (file)
@@ -11,7 +11,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/xdr.h>
index 1a42d902bc11e0bb9976177765a8ebcc0263648d..e4729aa676547d49926d9fe798204eb7f7910972 100644 (file)
@@ -9,19 +9,6 @@
 #ifndef _LINUX_SUNRPC_DEBUG_H_
 #define _LINUX_SUNRPC_DEBUG_H_
 
-#include <linux/config.h>
-
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-
-/*
- * Enable RPC debugging/profiling.
- */
-#ifdef CONFIG_SYSCTL
-#define  RPC_DEBUG
-#endif
-/* #define  RPC_PROFILE */
-
 /*
  * RPC debug facilities
  */
 
 #ifdef __KERNEL__
 
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+
+/*
+ * Enable RPC debugging/profiling.
+ */
+#ifdef CONFIG_SYSCTL
+#define  RPC_DEBUG
+#endif
+/* #define  RPC_PROFILE */
+
 /*
  * Debugging macros etc
  */
index d93c24b47f3f4ceb82b3fd21d20c52c795e4c174..5fa0f20843078a94c8822ef1a1ace6cc5d0ae2c0 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _LINUX_SUNRPC_STATS_H
 #define _LINUX_SUNRPC_STATS_H
 
-#include <linux/config.h>
 #include <linux/proc_fs.h>
 
 struct rpc_stat {
index 37c1c76fd5472f7aafdbee3a7f36e6806a7e3468..96e31aa64cc7c152f17e182b34801de452004e75 100644 (file)
@@ -6,7 +6,6 @@
 #endif
 #include <linux/swap.h>
 #include <linux/notifier.h>
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/pm.h>
 
index f03c247193022ae3ec7ee7457db7ce3f44cbce80..aca9bfae208f8780dc0d7c0523a6e4280e317403 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_SWAP_H
 #define _LINUX_SWAP_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/linkage.h>
 #include <linux/mmzone.h>
index 60d49e5456e79c273e6732d1fcf0b15dce1159f4..bd67a4413df7b29389f3729073becd4862440605 100644 (file)
@@ -54,7 +54,6 @@ struct compat_stat;
 struct compat_timeval;
 struct robust_list_head;
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/aio_abi.h>
 #include <linux/capability.h>
index 76eaeff76f82dc03f3f42d33d3f3a13983268e9e..cee944dbdcd42539d0af3e322e769882f6da56ad 100644 (file)
@@ -313,6 +313,7 @@ enum
        NET_NF_CONNTRACK_FRAG6_TIMEOUT=29,
        NET_NF_CONNTRACK_FRAG6_LOW_THRESH=30,
        NET_NF_CONNTRACK_FRAG6_HIGH_THRESH=31,
+       NET_NF_CONNTRACK_CHECKSUM=32,
 };
 
 /* /proc/sys/net/ipv4 */
@@ -403,6 +404,8 @@ enum
        NET_TCP_MTU_PROBING=113,
        NET_TCP_BASE_MSS=114,
        NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115,
+       NET_TCP_DMA_COPYBREAK=116,
+       NET_TCP_SLOW_START_AFTER_IDLE=117,
 };
 
 enum {
@@ -491,6 +494,7 @@ enum
        NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD=25,
        NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT=26,
        NET_IPV4_NF_CONNTRACK_COUNT=27,
+       NET_IPV4_NF_CONNTRACK_CHECKSUM=28,
 };
  
 /* /proc/sys/net/ipv6 */
index ea819b89c23508adc0d539c87d38fb85ade1c2c7..4812ff60561cb44cf66625691059dee49fce6347 100644 (file)
@@ -11,7 +11,6 @@
  *     based upon discusions in irc://irc.openprojects.net/#kernelnewbies
  */
 
-#include <linux/config.h>
 
 struct pt_regs;
 struct tty_struct;
index 542d39596bd86f0c7cdc84b58977b4da440590a2..420a689c3fb45c5f088837424f0b3a705a640082 100644 (file)
@@ -18,6 +18,7 @@
 #define _LINUX_TCP_H
 
 #include <linux/types.h>
+#include <linux/dmaengine.h>
 #include <asm/byteorder.h>
 
 struct tcphdr {
@@ -159,7 +160,6 @@ struct tcp_info
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/inet_connection_sock.h>
@@ -233,6 +233,13 @@ struct tcp_sock {
                struct iovec            *iov;
                int                     memory;
                int                     len;
+#ifdef CONFIG_NET_DMA
+               /* members for async copy */
+               struct dma_chan         *dma_chan;
+               int                     wakeup;
+               struct dma_pinned_list  *pinned_list;
+               dma_cookie_t            dma_cookie;
+#endif
        } ucopy;
 
        __u32   snd_wl1;        /* Sequence for window update           */
index e646bcdf26142fd55998efd116089b11346deb3a..38d1a5d6568e8dece38c80cb279f1c4fbbed41a1 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_THREADS_H
 #define _LINUX_THREADS_H
 
-#include <linux/config.h>
 
 /*
  * The default limit for the nr of threads is now in
index 0a485beba9f511ddb935044bee1c7f6696c51214..c982304dbafd4f30faf9764c377b442894f20282 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_TIMER_H
 #define _LINUX_TIMER_H
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
index 03914b7e41b17871aea961f6522ec4ce26a4f8ed..34d3ccff7bbb384d8adc407af0d45966288f20e3 100644 (file)
@@ -53,7 +53,6 @@
 #ifndef _LINUX_TIMEX_H
 #define _LINUX_TIMEX_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/time.h>
 
index f13f49afe198cc0d59e998fe3a6e721d70fca6b4..e898eeb94166ceff151ffbcb5d88b39babeeb52b 100644 (file)
@@ -16,7 +16,6 @@
                   consoles 16 and higher (since it returns a short) */
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/major.h>
 #include <linux/termios.h>
index 1046c7ad86d91f482947a72c4696e4007cbf272f..a5e46e783ffa03ca4d38e918e09f4e8b78367380 100644 (file)
@@ -2,7 +2,6 @@
 #define _LINUX_TYPES_H
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 
 #define BITS_TO_LONGS(bits) \
        (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
index 85a55658831c5f0acdf8edda61921f7df7e14e77..bdd39be094065fa5a53c26864e9db5feb51e5122 100644 (file)
@@ -35,7 +35,6 @@ struct udphdr {
 #define UDP_ENCAP_ESPINUDP     2 /* draft-ietf-ipsec-udp-encaps-06 */
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/types.h>
 
 #include <net/inet_sock.h>
index 843aeaaa79d4a4cb8d68b21ff1518bfe1b8283aa..86b5b4271b5a7b5e9d00c1d2092005eea53f8ae1 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/fs.h>
 
index 10ed9834b82241c5c102504217fc288ff528f4c8..c18c60f3254ec998d33222aa1bd226c1f6314441 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef _LINUX_UNISTD_H_
 #define _LINUX_UNISTD_H_
 
+#ifdef __KERNEL__
 extern int errno;
+#endif
 
 /*
  * Include machine specific syscallX macros
index e34e5e3dce529bff49f09e1565471d7d9c657c85..1f492c0c704743a9c1fbada54d482366f8fad911 100644 (file)
@@ -10,7 +10,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/errno.h>        /* for -ENODEV */
 #include <linux/delay.h>       /* for mdelay() */
 #include <linux/interrupt.h>   /* for in_interrupt() */
index b2d08984a9f759251712cf7169f4404e51e56ac6..608487a62c98f8e1f129350db0a3c70e3e766dd5 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef __LINUX_USB_USUAL_H
 #define __LINUX_USB_USUAL_H
 
-#include <linux/config.h>
 
 /* We should do this for cleanliness... But other usb_foo.h do not do this. */
 /* #include <linux/usb.h> */
index 8859f0b415430186305180cc3c5d35aac1e95abe..7b7aadb690920c2d6dd00c6ea0a4fc32b96f14e4 100644 (file)
@@ -123,6 +123,7 @@ struct usbdevfs_hub_portinfo {
        char port [127];        /* e.g. port 3 connects to device 27 */
 };
 
+#ifdef __KERNEL__
 #ifdef CONFIG_COMPAT
 #include <linux/compat.h>
 struct usbdevfs_urb32 {
@@ -147,6 +148,7 @@ struct usbdevfs_ioctl32 {
        compat_caddr_t data;
 };
 #endif
+#endif /* __KERNEL__ */
 
 #define USBDEVFS_CONTROL           _IOWR('U', 0, struct usbdevfs_ctrltransfer)
 #define USBDEVFS_BULK              _IOWR('U', 2, struct usbdevfs_bulktransfer)
index 1f7ba3629053684d902d45d16cbdfc2122974a2f..057db7d2f4484b45a8cd4be42a5c10ec5509372e 100644 (file)
@@ -13,7 +13,6 @@
 #ifndef _LINUX_VT_BUFFER_H_
 #define _LINUX_VT_BUFFER_H_
 
-#include <linux/config.h>
 
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE)
 #include <asm/vga.h>
index 530ae3f4248ccb6afb3dfe84cee7c1264e32ca38..940d0261a5459078c7283597e63f97c1c2337aa0 100644 (file)
@@ -6,7 +6,6 @@
  * with information needed by the vt package
  */
 
-#include <linux/config.h>
 #include <linux/vt.h>
 #include <linux/kd.h>
 #include <linux/tty.h>
@@ -73,11 +72,6 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
 int vt_waitactive(int vt);
 void change_console(struct vc_data *new_vc);
 void reset_vc(struct vc_data *vc);
-#ifdef CONFIG_VT
-int is_console_suspend_safe(void);
-#else
-static inline int is_console_suspend_safe(void) { return 1; }
-#endif
 
 /*
  * vc_screen.c shares this temporary buffer with the console write code so that
index d28518236b62fea581606ee74c76607743153aad..544e855c7c02d9f6a10607a921d229e909a10efe 100644 (file)
@@ -19,7 +19,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
index 1b6b76a4eb540c815da474250b58e28ce4688e92..2cd05013edfc19e78ae954eb1b1e5abe783674dc 100644 (file)
@@ -44,8 +44,6 @@
 * Jan 02, 1997 Gene Kozin      Initial version (based on wanpipe.h).
 *****************************************************************************/
 
-#include <linux/spinlock.h>       /* Support for SMP Locking */
-
 #ifndef        _ROUTER_H
 #define        _ROUTER_H
 
@@ -457,6 +455,8 @@ typedef struct wanif_conf
 #include <linux/fs.h>          /* support for device drivers */
 #include <linux/proc_fs.h>     /* proc filesystem pragmatics */
 #include <linux/netdevice.h>   /* support for network drivers */
+#include <linux/spinlock.h>     /* Support for SMP Locking */
+
 /*----------------------------------------------------------------------------
  * WAN device data space.
  */
index 6b42cc474c01117e809d81ee9ed8747153cc3512..46a15c7a1a13efcab599605672b206d9e078452b 100644 (file)
@@ -118,6 +118,10 @@ enum
        XFRM_SHARE_UNIQUE       /* Use once */
 };
 
+#define XFRM_MODE_TRANSPORT 0
+#define XFRM_MODE_TUNNEL 1
+#define XFRM_MODE_MAX 2
+
 /* Netlink configuration messages.  */
 enum {
        XFRM_MSG_BASE = 0x10,
index b5994ea56a5a19ba6aae6f297e370ea9bd1b4d60..31329fce1ff5dc6111095a83b2ce961881460e1e 100644 (file)
@@ -7,8 +7,9 @@
 #ifndef __MTD_ABI_H__
 #define __MTD_ABI_H__
 
-#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into
-                   separate files was to avoid #ifdef __KERNEL__ */
+#ifndef __KERNEL__ 
+/* Urgh. The whole point of splitting this out into
+   separate files was to avoid #ifdef __KERNEL__ */
 #define __user
 #endif
 
@@ -28,28 +29,17 @@ struct mtd_oob_buf {
 #define MTD_ROM                        2
 #define MTD_NORFLASH           3
 #define MTD_NANDFLASH          4
-#define MTD_PEROM              5
 #define MTD_DATAFLASH          6
-#define MTD_OTHER              14
-#define MTD_UNKNOWN            15
-
-#define MTD_CLEAR_BITS         1       // Bits can be cleared (flash)
-#define MTD_SET_BITS           2       // Bits can be set
-#define MTD_ERASEABLE          4       // Has an erase function
-#define MTD_WRITEB_WRITEABLE   8       // Direct IO is possible
-#define MTD_VOLATILE           16      // Set for RAMs
-#define MTD_XIP                        32      // eXecute-In-Place possible
-#define MTD_OOB                        64      // Out-of-band data (NAND flash)
-#define MTD_ECC                        128     // Device capable of automatic ECC
-#define MTD_NO_VIRTBLOCKS      256     // Virtual blocks not allowed
-#define MTD_PROGRAM_REGIONS    512     // Configurable Programming Regions
+
+#define MTD_WRITEABLE          0x400   /* Device is writeable */
+#define MTD_BIT_WRITEABLE      0x800   /* Single bits can be flipped */
+#define MTD_NO_ERASE           0x1000  /* No erase necessary */
 
 // Some common devices / combinations of capabilities
 #define MTD_CAP_ROM            0
-#define MTD_CAP_RAM            (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
-#define MTD_CAP_NORFLASH        (MTD_CLEAR_BITS|MTD_ERASEABLE)
-#define MTD_CAP_NANDFLASH       (MTD_CLEAR_BITS|MTD_ERASEABLE|MTD_OOB)
-#define MTD_WRITEABLE          (MTD_CLEAR_BITS|MTD_SET_BITS)
+#define MTD_CAP_RAM            (MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE)
+#define MTD_CAP_NORFLASH       (MTD_WRITEABLE | MTD_BIT_WRITEABLE)
+#define MTD_CAP_NANDFLASH      (MTD_WRITEABLE)
 
 
 // Types of automatic ECC/Checksum available
@@ -74,7 +64,7 @@ struct mtd_info_user {
        uint32_t flags;
        uint32_t size;   // Total size of the MTD
        uint32_t erasesize;
-       uint32_t oobblock;  // Size of OOB blocks (e.g. 512)
+       uint32_t writesize;
        uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
        uint32_t ecctype;
        uint32_t eccsize;
@@ -94,12 +84,12 @@ struct otp_info {
        uint32_t locked;
 };
 
-#define MEMGETINFO              _IOR('M', 1, struct mtd_info_user)
-#define MEMERASE                _IOW('M', 2, struct erase_info_user)
-#define MEMWRITEOOB             _IOWR('M', 3, struct mtd_oob_buf)
-#define MEMREADOOB              _IOWR('M', 4, struct mtd_oob_buf)
-#define MEMLOCK                 _IOW('M', 5, struct erase_info_user)
-#define MEMUNLOCK               _IOW('M', 6, struct erase_info_user)
+#define MEMGETINFO             _IOR('M', 1, struct mtd_info_user)
+#define MEMERASE               _IOW('M', 2, struct erase_info_user)
+#define MEMWRITEOOB            _IOWR('M', 3, struct mtd_oob_buf)
+#define MEMREADOOB             _IOWR('M', 4, struct mtd_oob_buf)
+#define MEMLOCK                        _IOW('M', 5, struct erase_info_user)
+#define MEMUNLOCK              _IOW('M', 6, struct erase_info_user)
 #define MEMGETREGIONCOUNT      _IOR('M', 7, int)
 #define MEMGETREGIONINFO       _IOWR('M', 8, struct region_info_user)
 #define MEMSETOOBSEL           _IOW('M', 9, struct nand_oobinfo)
@@ -109,8 +99,15 @@ struct otp_info {
 #define OTPSELECT              _IOR('M', 13, int)
 #define OTPGETREGIONCOUNT      _IOW('M', 14, int)
 #define OTPGETREGIONINFO       _IOW('M', 15, struct otp_info)
-#define OTPLOCK                _IOR('M', 16, struct otp_info)
+#define OTPLOCK                        _IOR('M', 16, struct otp_info)
+#define ECCGETLAYOUT           _IOR('M', 17, struct nand_ecclayout)
+#define ECCGETSTATS            _IOR('M', 18, struct mtd_ecc_stats)
+#define MTDFILEMODE            _IO('M', 19)
 
+/*
+ * Obsolete legacy interface. Keep it in order not to break userspace
+ * interfaces
+ */
 struct nand_oobinfo {
        uint32_t useecc;
        uint32_t eccbytes;
@@ -118,4 +115,46 @@ struct nand_oobinfo {
        uint32_t eccpos[32];
 };
 
+struct nand_oobfree {
+       uint32_t offset;
+       uint32_t length;
+};
+
+#define MTD_MAX_OOBFREE_ENTRIES        8
+/*
+ * ECC layout control structure. Exported to userspace for
+ * diagnosis and to allow creation of raw images
+ */
+struct nand_ecclayout {
+       uint32_t eccbytes;
+       uint32_t eccpos[64];
+       uint32_t oobavail;
+       struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
+};
+
+/**
+ * struct mtd_ecc_stats - error correction status
+ *
+ * @corrected: number of corrected bits
+ * @failed:    number of uncorrectable errors
+ * @badblocks: number of bad blocks in this partition
+ * @bbtblocks: number of blocks reserved for bad block tables
+ */
+struct mtd_ecc_stats {
+       uint32_t corrected;
+       uint32_t failed;
+       uint32_t badblocks;
+       uint32_t bbtblocks;
+};
+
+/*
+ * Read/write file modes for access to MTD
+ */
+enum mtd_file_modes {
+       MTD_MODE_NORMAL = MTD_OTP_OFF,
+       MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY,
+       MTD_MODE_OTP_USER = MTD_OTP_USER,
+       MTD_MODE_RAW,
+};
+
 #endif /* __MTD_ABI_H__ */
index 1c13fc7161fefaa084ecb9f66f63156c2154e94a..713f34d3e62e184aa6712ee53ac8308412d26593 100644 (file)
@@ -16,5 +16,6 @@ typedef struct mtd_info_user mtd_info_t;
 typedef struct erase_info_user erase_info_t;
 typedef struct region_info_user region_info_t;
 typedef struct nand_oobinfo nand_oobinfo_t;
+typedef struct nand_ecclayout nand_ecclayout_t;
 
 #endif /* __MTD_USER_H__ */
index 750e2508dd90627084e9757363f1d25832047d30..3d71251b3eca70b4e53ca11677b9985abac06bed 100644 (file)
@@ -45,7 +45,6 @@ struct prefix_info {
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/netdevice.h>
 #include <net/if_inet6.h>
 #include <net/ipv6.h>
index 427dac94bc7e38a3e63fb008fa6bb4b12cb04fcf..795f81f9ec7ff9c4e064e085d6c491d351a39f19 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __LINUX_NET_AFUNIX_H
 #define __LINUX_NET_AFUNIX_H
 
-#include <linux/config.h>
 #include <linux/socket.h>
 #include <linux/un.h>
 #include <linux/mutex.h>
index 5bd997487054c3d9125d38ca0f89f5372387164d..7cd528e9d668af3a00b7b5f10c6654ff186b2877 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _AX25_H
 #define _AX25_H 
 
-#include <linux/config.h>
 #include <linux/ax25.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
index 8662b8f43df5d6dc009f068b4b127f6a86589b69..9859b60280d5631571cdbebdf611c28c8e283b48 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef NET_COMPAT_H
 #define NET_COMPAT_H
 
-#include <linux/config.h>
+
+struct sock;
 
 #if defined(CONFIG_COMPAT)
 
@@ -23,7 +24,6 @@ struct compat_cmsghdr {
        compat_int_t    cmsg_type;
 };
 
-struct sock;
 extern int compat_sock_get_timestamp(struct sock *, struct timeval __user *);
 
 #else /* defined(CONFIG_COMPAT) */
index 5161e89017f934cb6be31560961b52906a56dbdd..36d54fc248b001cc1bbd9915039c005931fd14d1 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _NET_DST_H
 #define _NET_DST_H
 
-#include <linux/config.h>
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/rcupdate.h>
index e7c3f20fbafc6de85b683d41588f2d1646ca4989..05f8ff7d9316fe9d881aec2c0238d44221b14b16 100644 (file)
@@ -18,7 +18,6 @@
 #ifndef _ICMP_H
 #define        _ICMP_H
 
-#include <linux/config.h>
 #include <linux/icmp.h>
 
 #include <net/inet_sock.h>
index d5926bfb1fc967132850724040903bbf1cbbe550..d5147770ad474abbe290c20c1a7d97bdf9ab16e7 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>      /* ARRAY_SIZE */
 #include <linux/wireless.h>
 
-#define IEEE80211_VERSION "git-1.1.7"
+#define IEEE80211_VERSION "git-1.1.13"
 
 #define IEEE80211_DATA_LEN             2304
 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
 #define IEEE80211_SCTL_FRAG            0x000F
 #define IEEE80211_SCTL_SEQ             0xFFF0
 
+/* QOS control */
+#define IEEE80211_QCTL_TID             0x000F
+
 /* debug macros */
 
 #ifdef CONFIG_IEEE80211_DEBUG
@@ -1075,6 +1078,7 @@ struct ieee80211_device {
 
        int (*handle_management) (struct net_device * dev,
                                  struct ieee80211_network * network, u16 type);
+       int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb);
 
        /* Typical STA methods */
        int (*handle_auth) (struct net_device * dev,
@@ -1243,7 +1247,8 @@ extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
 extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 extern int ieee80211_tx_frame(struct ieee80211_device *ieee,
-                             struct ieee80211_hdr *frame, int len);
+                             struct ieee80211_hdr *frame, int hdr_len,
+                             int total_len, int encrypt_mpdu);
 
 /* ieee80211_rx.c */
 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
index 052ed596a4e487de798d0513f472ce842b66ba21..7a483ab4022f98cd20d4946dc7f61054d08e30f0 100644 (file)
@@ -86,6 +86,9 @@ struct ieee80211softmac_assoc_info {
        
        /* BSSID we're trying to associate to */
        char bssid[ETH_ALEN];
+
+       /* Rates supported by the network */
+       struct ieee80211softmac_ratesinfo supported_rates;
        
        /* some flags.
         * static_essid is valid if the essid is constant,
@@ -132,23 +135,26 @@ enum {
 struct ieee80211softmac_txrates {
        /* The Bit-Rate to be used for multicast frames. */
        u8 mcast_rate;
-       /* The Bit-Rate to be used for multicast fallback
-        * (If the device supports fallback and hardware-retry)
-        */
-       u8 mcast_fallback;
+
+       /* The Bit-Rate to be used for multicast management frames. */
+       u8 mgt_mcast_rate;
+
        /* The Bit-Rate to be used for any other (normal) data packet. */
        u8 default_rate;
        /* The Bit-Rate to be used for default fallback
         * (If the device supports fallback and hardware-retry)
         */
        u8 default_fallback;
+
+       /* This is the rate that the user asked for */
+       u8 user_rate;
 };
 
 /* Bits for txrates_change callback. */
 #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT             (1 << 0) /* default_rate */
 #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK       (1 << 1) /* default_fallback */
 #define IEEE80211SOFTMAC_TXRATECHG_MCAST               (1 << 2) /* mcast_rate */
-#define IEEE80211SOFTMAC_TXRATECHG_MCAST_FBACK         (1 << 3) /* mcast_fallback */
+#define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST           (1 << 3) /* mgt_mcast_rate */
 
 struct ieee80211softmac_device {
        /* 802.11 structure for data stuff */
@@ -250,6 +256,28 @@ extern void ieee80211softmac_fragment_lost(struct net_device *dev,
  * Note that the rates need to be sorted. */
 extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates);
 
+/* Helper function which advises you the rate at which a frame should be
+ * transmitted at. */
+static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device *mac,
+                                                int is_multicast,
+                                                int is_mgt)
+{
+       struct ieee80211softmac_txrates *txrates = &mac->txrates;
+
+       if (!mac->associated)
+               return txrates->mgt_mcast_rate;
+
+       /* We are associated, sending unicast frame */
+       if (!is_multicast)
+               return txrates->default_rate;
+
+       /* We are associated, sending multicast frame */
+       if (is_mgt)
+               return txrates->mgt_mcast_rate;
+       else
+               return txrates->mcast_rate;
+}
+
 /* Start the SoftMAC. Call this after you initialized the device
  * and it is ready to run.
  */
@@ -282,7 +310,7 @@ extern void ieee80211softmac_stop(struct net_device *dev);
  *     - context set to the context data you want passed
  * The return value is 0, or an error.
  */
-typedef void (*notify_function_ptr)(struct net_device *dev, void *context);
+typedef void (*notify_function_ptr)(struct net_device *dev, int event_type, void *context);
 
 #define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL);
 #define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);
index 3e0be453ecea66020eb20a47681f3988f53caa9b..4ee3ad57283fa3370bd2d1f71cd6ae559b556dbc 100644 (file)
@@ -91,4 +91,9 @@ ieee80211softmac_wx_get_genie(struct net_device *dev,
                              struct iw_request_info *info,
                              union iwreq_data *wrqu,
                              char *extra);
+extern int
+ieee80211softmac_wx_set_mlme(struct net_device *dev,
+                            struct iw_request_info *info,
+                            union iwreq_data *wrqu,
+                            char *extra);
 #endif /* _IEEE80211SOFTMAC_WX */
index 59f0c83d55a243913eec31fefe22433213a8d48b..bc6a71dce984173ebbcf497c4d571cdf2b1815be 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef _INET6_HASHTABLES_H
 #define _INET6_HASHTABLES_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 #include <linux/in6.h>
index 135d80fd658ebf2c8d027440a1e9580f1c2b1ba3..98e0bb3014feac529f6e2fb4d1e34c41ef8ecb49 100644 (file)
@@ -14,7 +14,6 @@
 #ifndef _INET_HASHTABLES_H
 #define _INET_HASHTABLES_H
 
-#include <linux/config.h>
 
 #include <linux/interrupt.h>
 #include <linux/ipv6.h>
index 883eb529ef8ebcf49c77aee0a935782b8d3b34b1..1f4a9a60d4cc472bf521967995e92848ff9e3b1f 100644 (file)
@@ -16,7 +16,6 @@
 #ifndef _INET_SOCK_H
 #define _INET_SOCK_H
 
-#include <linux/config.h>
 
 #include <linux/string.h>
 #include <linux/types.h>
index e837f98fdb50429e3c40b4d200e9a5d7bf7fd0af..600cb543550d8b4f13c7b991b5d8dc308ba144fd 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _INET_TIMEWAIT_SOCK_
 #define _INET_TIMEWAIT_SOCK_
 
-#include <linux/config.h>
 
 #include <linux/list.h>
 #include <linux/module.h>
index 3d2e5ca62a5af1c8ba234523d9886380d7d90564..98f90840077186243bf910db40452ba7cfa881d9 100644 (file)
@@ -22,7 +22,6 @@
 #ifndef _IP_H
 #define _IP_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/ip.h>
 #include <linux/in.h>
@@ -147,7 +146,6 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
 struct ipv4_config
 {
        int     log_martians;
-       int     autoconfig;
        int     no_pmtu_disc;
 };
 
index e000fa2cd5f62824059afb171439120e573bab74..a095d1dec7a4110faa6a9b1cc64a9a062d781e1e 100644 (file)
@@ -16,7 +16,6 @@
 #ifndef _NET_IP_FIB_H
 #define _NET_IP_FIB_H
 
-#include <linux/config.h>
 #include <net/flow.h>
 #include <linux/seq_file.h>
 
index 77225735cbd4c944ec63c2990887c26da3f30a99..ac747b64734c56a9c83054cf5af20e81ed6e19d2 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _NET_IP_MP_ALG_H
 #define _NET_IP_MP_ALG_H
 
-#include <linux/config.h>
 #include <linux/ip_mp_alg.h>
 #include <net/flow.h>
 #include <net/route.h>
index 7d2674fde19a87020a225ada56b64a97c118ff44..3b57b159b653dfe8dee821fef097ca234f73a2d6 100644 (file)
@@ -248,7 +248,6 @@ struct ip_vs_daemon_user {
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/list.h>                 /* for struct list_head */
 #include <linux/spinlock.h>             /* for struct rwlock_t */
 #include <asm/atomic.h>                 /* for struct atomic_t */
index 4abedb8eaece67a43e4a091cca197477c025cc7a..a8fdf7970b370a8aca9f216a72fec4b7b378d60e 100644 (file)
@@ -104,7 +104,6 @@ struct frag_hdr {
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <net/sock.h>
 
 /* sysctls */
index 1880e46ecc9b0774de64e867f4f4cb7e8388eff6..1cb0607fcbb948930d0d395c13d86a0aa2b8db2a 100644 (file)
@@ -26,7 +26,6 @@
 #ifndef NET_IRDA_H
 #define NET_IRDA_H
 
-#include <linux/config.h>
 #include <linux/skbuff.h>              /* struct sk_buff */
 #include <linux/kernel.h>
 #include <linux/if.h>                  /* sa_family_t in <linux/irda.h> */
index 92c828029cd8d46d8a753e3f7a3c54882572be89..0575c59a5c96b203c3d93c4cf0e5027ede827327 100644 (file)
@@ -39,7 +39,6 @@
 #ifndef IRDA_DEVICE_H
 #define IRDA_DEVICE_H
 
-#include <linux/config.h>
 #include <linux/tty.h>
 #include <linux/netdevice.h>
 #include <linux/spinlock.h>
index 2127cae1e0a68d9818daa7c05a368d7b1c2e4b7b..e77eb88d9226b5e991047f3e97f54e02e24a94d5 100644 (file)
@@ -27,7 +27,6 @@
 #ifndef IRLAP_H
 #define IRLAP_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
index c0c895d379ba1b10ed5a7b39e8c4da3405aea23e..11ecfa58a648ff3ad145b8138055f6ac5ad9f54f 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <asm/param.h>  /* for HZ */
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #include <net/irda/irda.h>
index eb3ad158c023b4a616d5943feb639e9ab0be3c24..c463f8bca85601ec457a4bdb1991c7fcb8738efe 100644 (file)
@@ -26,7 +26,6 @@
 #ifndef IRMLP_FRAME_H
 #define IRMLP_FRAME_H
 
-#include <linux/config.h>
 #include <linux/skbuff.h>
 
 #include <net/irda/discovery.h>
index 9ae3d6bc24235d5b4dd5634966d0034d94442b76..cc577dc0a0efb08d689c13e9685cc30a33cece43 100644 (file)
@@ -31,7 +31,6 @@
 #ifndef IRDA_QOS_H
 #define IRDA_QOS_H
 
-#include <linux/config.h>
 #include <linux/skbuff.h>
 
 #include <net/irda/parameters.h>
index 090eaa0d71f9f63e1bb7af74ed4eab391ffa2307..c608812a8e8949e23d7b5804b84167b140fbeda2 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/if.h>
 #include <linux/if_arp.h>
 #include <linux/llc.h>
+#include <linux/etherdevice.h>
 #include <net/llc.h>
 
 #define LLC_DATAUNIT_PRIM      1
@@ -61,8 +62,6 @@
 #define LLC_STATUS_CONFLICT    7 /* disconnect conn */
 #define LLC_STATUS_RESET_DONE  8 /*  */
 
-extern u8 llc_mac_null_var[IFHWADDRLEN];
-
 /**
  *      llc_mac_null - determines if a address is a null mac address
  *      @mac: Mac address to test if null.
@@ -70,16 +69,20 @@ extern u8 llc_mac_null_var[IFHWADDRLEN];
  *      Determines if a given address is a null mac address.  Returns 0 if the
  *      address is not a null mac, 1 if the address is a null mac.
  */
-static __inline__ int llc_mac_null(u8 *mac)
+static inline int llc_mac_null(const u8 *mac)
 {
-       return !memcmp(mac, llc_mac_null_var, IFHWADDRLEN);
+       return is_zero_ether_addr(mac);
 }
 
-static __inline__ int llc_addrany(struct llc_addr *addr)
+static inline int llc_addrany(const struct llc_addr *addr)
 {
        return llc_mac_null(addr->mac) && !addr->lsap;
 }
 
+static inline int llc_mac_multicast(const u8 *mac)
+{
+       return is_multicast_ether_addr(mac);
+}
 /**
  *     llc_mac_match - determines if two mac addresses are the same
  *     @mac1: First mac address to compare.
@@ -89,9 +92,9 @@ static __inline__ int llc_addrany(struct llc_addr *addr)
  *     is not a complete match up to len, 1 if a complete match up to len is
  *     found.
  */
-static __inline__ int llc_mac_match(u8 *mac1, u8 *mac2)
+static inline int llc_mac_match(const u8 *mac1, const u8 *mac2)
 {
-       return !memcmp(mac1, mac2, IFHWADDRLEN);
+       return !compare_ether_addr(mac1, mac2);
 }
 
 extern int llc_establish_connection(struct sock *sk, u8 *lmac,
index 91fa271a00640d5a0147c20f10dadef8aa536965..d3915dabe6de1807a909b309233ec8e0e3b68885 100644 (file)
@@ -37,7 +37,6 @@ enum {
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/icmpv6.h>
 #include <linux/in6.h>
diff --git a/include/net/netdma.h b/include/net/netdma.h
new file mode 100644 (file)
index 0000000..19760eb
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. 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 COPYING.
+ */
+#ifndef NETDMA_H
+#define NETDMA_H
+#include <linux/config.h>
+#ifdef CONFIG_NET_DMA
+#include <linux/dmaengine.h>
+#include <linux/skbuff.h>
+
+static inline struct dma_chan *get_softnet_dma(void)
+{
+       struct dma_chan *chan;
+       rcu_read_lock();
+       chan = rcu_dereference(__get_cpu_var(softnet_data.net_dma));
+       if (chan)
+               dma_chan_get(chan);
+       rcu_read_unlock();
+       return chan;
+}
+
+int dma_skb_copy_datagram_iovec(struct dma_chan* chan,
+               const struct sk_buff *skb, int offset, struct iovec *to,
+               size_t len, struct dma_pinned_list *pinned_list);
+
+#endif /* CONFIG_NET_DMA */
+#endif /* NETDMA_H */
index 916013ca4a5cab431f5f14da31a19a8f3a83761b..1fbd8193d5f13f82b0b035cca412c0ef9ae479ba 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/netfilter/nf_conntrack_common.h>
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/bitops.h>
 #include <linux/compiler.h>
 #include <asm/atomic.h>
@@ -114,6 +113,10 @@ struct nf_conn
        u_int32_t mark;
 #endif
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+       u_int32_t secmark;
+#endif
+
        /* Storage reserved for other modules: */
        union nf_conntrack_proto proto;
 
@@ -285,6 +288,7 @@ static inline int nf_ct_is_dying(struct nf_conn *ct)
 }
 
 extern unsigned int nf_conntrack_htable_size;
+extern int nf_conntrack_checksum;
 
 #define NF_CT_STAT_INC(count) (__get_cpu_var(nf_conntrack_stat).count++)
 
index 3cac19fb36488c40a1c196a659a49e8e874450d8..f1b1482d7200a3a8a1d67e4c6cc41ba62167f125 100644 (file)
@@ -20,6 +20,19 @@ static inline u_int32_t *nf_ct_get_mark(const struct sk_buff *skb,
 }
 #endif /* CONFIG_IP_NF_CONNTRACK_MARK */
 
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+static inline u_int32_t *nf_ct_get_secmark(const struct sk_buff *skb,
+                                          u_int32_t *ctinfo)
+{
+       struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
+
+       if (ct)
+               return &ct->secmark;
+       else
+               return NULL;
+}
+#endif /* CONFIG_IP_NF_CONNTRACK_SECMARK */
+
 #ifdef CONFIG_IP_NF_CT_ACCT
 static inline struct ip_conntrack_counter *
 nf_ct_get_counters(const struct sk_buff *skb)
@@ -70,6 +83,19 @@ static inline u_int32_t *nf_ct_get_mark(const struct sk_buff *skb,
 }
 #endif /* CONFIG_NF_CONNTRACK_MARK */
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static inline u_int32_t *nf_ct_get_secmark(const struct sk_buff *skb,
+                                          u_int32_t *ctinfo)
+{
+       struct nf_conn *ct = nf_ct_get(skb, ctinfo);
+
+       if (ct)
+               return &ct->secmark;
+       else
+               return NULL;
+}
+#endif /* CONFIG_NF_CONNTRACK_MARK */
+
 #ifdef CONFIG_NF_CT_ACCT
 static inline struct ip_conntrack_counter *
 nf_ct_get_counters(const struct sk_buff *skb)
index b225d8472b7e7536fbf4baa610eeec139ee59a4e..cf5e4d2e4c21ce77be2a4f7a8f5fd111d651e469 100644 (file)
@@ -4,7 +4,6 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/bitops.h>
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
index 6dc5970612d74eb822e39e2c50659286df4215ee..bcaee39bd2ffef45091f57e3793addd8d98edae1 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef _PROTOCOL_H
 #define _PROTOCOL_H
 
-#include <linux/config.h>
 #include <linux/in6.h>
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 #include <linux/ipv6.h>
index e67b28a0248c3ce5c8c831634a475ae9017eeafc..e4af59781949f12b0a097fafd06abea7ee841fde 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef _RAW_H
 #define _RAW_H
 
-#include <linux/config.h>
 
 #include <net/protocol.h>
 
@@ -36,7 +35,7 @@ extern rwlock_t raw_v4_lock;
 
 
 extern struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
-                                   unsigned long raddr, unsigned long laddr,
+                                   __be32 raddr, __be32 laddr,
                                    int dif);
 
 extern int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash);
index 2ed4358e3295c2f03595efd9bc9a91c86fa2b496..5ccdbb3d4722ab400281b3692db23f0a212a14f3 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __NET_SCHED_RED_H
 #define __NET_SCHED_RED_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <net/pkt_sched.h>
 #include <net/inet_ecn.h>
index 98c915abdec8791c409ab811df55cdf50421a9ea..c4a068692dcc5e0f79ab58e1fd231043b5726236 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef _ROUTE_H
 #define _ROUTE_H
 
-#include <linux/config.h>
 #include <net/dst.h>
 #include <net/inetpeer.h>
 #include <net/flow.h>
index 7b6ec99867157d430a057b567718642f8581126e..b0e9108a4e18a93b57b899e0aee858069c9fffb2 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __NET_SCHED_GENERIC_H
 #define __NET_SCHED_GENERIC_H
 
-#include <linux/config.h>
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/rcupdate.h>
index aa6033ca7cd859d3614406a54b0d4885e79a94dc..237f82b05e407accab599638be4aea96a291599f 100644 (file)
@@ -63,7 +63,6 @@
  */
 
 
-#include <linux/config.h>
 
 #ifdef TEST_FRAME
 #undef CONFIG_PROC_FS
@@ -255,7 +254,7 @@ extern int sctp_debug_flag;
 #define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
 #define SCTP_ENABLE_DEBUG
 #define SCTP_DISABLE_DEBUG
-#define SCTP_ASSERT(expr, str, func)
+#define SCTP_ASSERT(expr, str, func) BUG_ON(!(expr))
 
 #endif /* SCTP_DEBUG */
 
index 7f4fea173fb1a5bf1c11eb4099f3558c01be2220..5f69158c1006b3b44cdb9e58921b28c0f33a1d13 100644 (file)
@@ -555,7 +555,8 @@ struct sctp_af {
        int             (*to_addr_param) (const union sctp_addr *,
                                          union sctp_addr_param *); 
        int             (*addr_valid)   (union sctp_addr *,
-                                        struct sctp_sock *);
+                                        struct sctp_sock *,
+                                        const struct sk_buff *);
        sctp_scope_t    (*scope) (union sctp_addr *);
        void            (*inaddr_any)   (union sctp_addr *, unsigned short);
        int             (*is_any)       (const union sctp_addr *);
index c9fad6fb629b652d4c27e3965859efe12c3d7895..d10dfecb6cbdd9cee17dda53cbbea251e36d7e52 100644 (file)
@@ -40,7 +40,6 @@
 #ifndef _SOCK_H
 #define _SOCK_H
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/cache.h>
@@ -132,6 +131,7 @@ struct sock_common {
   *    @sk_receive_queue: incoming packets
   *    @sk_wmem_alloc: transmit queue bytes committed
   *    @sk_write_queue: Packet sending queue
+  *    @sk_async_wait_queue: DMA copied packets
   *    @sk_omem_alloc: "o" is "option" or "other"
   *    @sk_wmem_queued: persistent queue size
   *    @sk_forward_alloc: space allocated forward
@@ -205,6 +205,7 @@ struct sock {
        atomic_t                sk_omem_alloc;
        struct sk_buff_head     sk_receive_queue;
        struct sk_buff_head     sk_write_queue;
+       struct sk_buff_head     sk_async_wait_queue;
        int                     sk_wmem_queued;
        int                     sk_forward_alloc;
        gfp_t                   sk_allocation;
@@ -871,10 +872,7 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
                if (filter) {
                        unsigned int pkt_len = sk_run_filter(skb, filter->insns,
                                                             filter->len);
-                       if (!pkt_len)
-                               err = -EPERM;
-                       else
-                               skb_trim(skb, pkt_len);
+                       err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
                }
 
                if (needlock)
@@ -1271,11 +1269,22 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
  * This routine must be called with interrupts disabled or with the socket
  * locked so that the sk_buff queue operation is ok.
 */
-static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb)
+#ifdef CONFIG_NET_DMA
+static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_early)
+{
+       __skb_unlink(skb, &sk->sk_receive_queue);
+       if (!copied_early)
+               __kfree_skb(skb);
+       else
+               __skb_queue_tail(&sk->sk_async_wait_queue, skb);
+}
+#else
+static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_early)
 {
        __skb_unlink(skb, &sk->sk_receive_queue);
        __kfree_skb(skb);
 }
+#endif
 
 extern void sock_enable_timestamp(struct sock *sk);
 extern int sock_get_timestamp(struct sock *, struct timeval __user *);
index 3c989db8a7aa508e6b3c42f5b49e61d9a2ec7691..5f4eb5c79689c8954cab67279057e9cd55cc1a6c 100644 (file)
 #define TCP_DEBUG 1
 #define FASTRETRANS_DEBUG 1
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/tcp.h>
 #include <linux/slab.h>
 #include <linux/cache.h>
 #include <linux/percpu.h>
 #include <linux/skbuff.h>
+#include <linux/dmaengine.h>
 
 #include <net/inet_connection_sock.h>
 #include <net/inet_timewait_sock.h>
@@ -218,6 +218,7 @@ extern int sysctl_tcp_adv_win_scale;
 extern int sysctl_tcp_tw_reuse;
 extern int sysctl_tcp_frto;
 extern int sysctl_tcp_low_latency;
+extern int sysctl_tcp_dma_copybreak;
 extern int sysctl_tcp_nometrics_save;
 extern int sysctl_tcp_moderate_rcvbuf;
 extern int sysctl_tcp_tso_win_divisor;
@@ -225,6 +226,7 @@ extern int sysctl_tcp_abc;
 extern int sysctl_tcp_mtu_probing;
 extern int sysctl_tcp_base_mss;
 extern int sysctl_tcp_workaround_signed_windows;
+extern int sysctl_tcp_slow_start_after_idle;
 
 extern atomic_t tcp_memory_allocated;
 extern atomic_t tcp_sockets_allocated;
@@ -293,6 +295,8 @@ extern int                  tcp_rcv_established(struct sock *sk,
 
 extern void                    tcp_rcv_space_adjust(struct sock *sk);
 
+extern void                    tcp_cleanup_rbuf(struct sock *sk, int copied);
+
 extern int                     tcp_twsk_unique(struct sock *sk,
                                                struct sock *sktw, void *twp);
 
@@ -628,7 +632,7 @@ struct tcp_congestion_ops {
        /* return slow start threshold (required) */
        u32 (*ssthresh)(struct sock *sk);
        /* lower bound for congestion window (optional) */
-       u32 (*min_cwnd)(struct sock *sk);
+       u32 (*min_cwnd)(const struct sock *sk);
        /* do new cwnd calculation (required) */
        void (*cong_avoid)(struct sock *sk, u32 ack,
                           u32 rtt, u32 in_flight, int good_ack);
@@ -663,7 +667,7 @@ extern struct tcp_congestion_ops tcp_init_congestion_ops;
 extern u32 tcp_reno_ssthresh(struct sock *sk);
 extern void tcp_reno_cong_avoid(struct sock *sk, u32 ack,
                                u32 rtt, u32 in_flight, int flag);
-extern u32 tcp_reno_min_cwnd(struct sock *sk);
+extern u32 tcp_reno_min_cwnd(const struct sock *sk);
 extern struct tcp_congestion_ops tcp_reno;
 
 static inline void tcp_set_ca_state(struct sock *sk, const u8 ca_state)
@@ -817,6 +821,12 @@ static inline void tcp_prequeue_init(struct tcp_sock *tp)
        tp->ucopy.len = 0;
        tp->ucopy.memory = 0;
        skb_queue_head_init(&tp->ucopy.prequeue);
+#ifdef CONFIG_NET_DMA
+       tp->ucopy.dma_chan = NULL;
+       tp->ucopy.wakeup = 0;
+       tp->ucopy.pinned_list = NULL;
+       tp->ucopy.dma_cookie = 0;
+#endif
 }
 
 /* Packet is added to VJ-style prequeue for processing in process
index afa508d92c93fdf6b3a4a96946a223c440514750..9c5ee9f20b65b7ef336652fc640331c67bc22c8f 100644 (file)
@@ -20,6 +20,8 @@
 #include <net/ip6_fib.h>
 
 #define XFRM_ALIGN8(len)       (((len) + 7) & ~7)
+#define MODULE_ALIAS_XFRM_MODE(family, encap) \
+       MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
 
 extern struct sock *xfrm_nl;
 extern u32 sysctl_xfrm_aevent_etime;
@@ -164,6 +166,7 @@ struct xfrm_state
        /* Reference to data common to all the instances of this
         * transformer. */
        struct xfrm_type        *type;
+       struct xfrm_mode        *mode;
 
        /* Security context */
        struct xfrm_sec_ctx     *security;
@@ -204,8 +207,8 @@ struct xfrm_type;
 struct xfrm_dst;
 struct xfrm_policy_afinfo {
        unsigned short          family;
-       rwlock_t                lock;
-       struct xfrm_type_map    *type_map;
+       struct xfrm_type        *type_map[IPPROTO_MAX];
+       struct xfrm_mode        *mode_map[XFRM_MODE_MAX];
        struct dst_ops          *dst_ops;
        void                    (*garbage_collect)(void);
        int                     (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);
@@ -232,7 +235,6 @@ extern int __xfrm_state_delete(struct xfrm_state *x);
 
 struct xfrm_state_afinfo {
        unsigned short          family;
-       rwlock_t                lock;
        struct list_head        *state_bydst;
        struct list_head        *state_byspi;
        int                     (*init_flags)(struct xfrm_state *x);
@@ -264,16 +266,24 @@ struct xfrm_type
        u32                     (*get_max_size)(struct xfrm_state *, int size);
 };
 
-struct xfrm_type_map {
-       rwlock_t                lock;
-       struct xfrm_type        *map[256];
-};
-
 extern int xfrm_register_type(struct xfrm_type *type, unsigned short family);
 extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family);
 extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family);
 extern void xfrm_put_type(struct xfrm_type *type);
 
+struct xfrm_mode {
+       int (*input)(struct xfrm_state *x, struct sk_buff *skb);
+       int (*output)(struct sk_buff *skb);
+
+       struct module *owner;
+       unsigned int encap;
+};
+
+extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
+extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
+extern struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family);
+extern void xfrm_put_mode(struct xfrm_mode *mode);
+
 struct xfrm_tmpl
 {
 /* id in template is interpreted as:
index 5e0a01ab22163e96d010552a749023cc9e825fda..ede639812f8a534a66925ff804c26dc0c601effd 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef _LINUX_SS_H
 #define _LINUX_SS_H
 
-#include <linux/config.h>
 #include <linux/device.h>
 #include <linux/sched.h>       /* task_struct, completion */
 #include <linux/mutex.h>
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h
new file mode 100644 (file)
index 0000000..fcb5ba8
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#if !defined(IB_ADDR_H)
+#define IB_ADDR_H
+
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/netdevice.h>
+#include <linux/socket.h>
+#include <rdma/ib_verbs.h>
+
+struct rdma_dev_addr {
+       unsigned char src_dev_addr[MAX_ADDR_LEN];
+       unsigned char dst_dev_addr[MAX_ADDR_LEN];
+       unsigned char broadcast[MAX_ADDR_LEN];
+       enum ib_node_type dev_type;
+};
+
+/**
+ * rdma_translate_ip - Translate a local IP address to an RDMA hardware
+ *   address.
+ */
+int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr);
+
+/**
+ * rdma_resolve_ip - Resolve source and destination IP addresses to
+ *   RDMA hardware addresses.
+ * @src_addr: An optional source address to use in the resolution.  If a
+ *   source address is not provided, a usable address will be returned via
+ *   the callback.
+ * @dst_addr: The destination address to resolve.
+ * @addr: A reference to a data location that will receive the resolved
+ *   addresses.  The data location must remain valid until the callback has
+ *   been invoked.
+ * @timeout_ms: Amount of time to wait for the address resolution to complete.
+ * @callback: Call invoked once address resolution has completed, timed out,
+ *   or been canceled.  A status of 0 indicates success.
+ * @context: User-specified context associated with the call.
+ */
+int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
+                   struct rdma_dev_addr *addr, int timeout_ms,
+                   void (*callback)(int status, struct sockaddr *src_addr,
+                                    struct rdma_dev_addr *addr, void *context),
+                   void *context);
+
+void rdma_addr_cancel(struct rdma_dev_addr *addr);
+
+static inline int ip_addr_size(struct sockaddr *addr)
+{
+       return addr->sa_family == AF_INET6 ?
+              sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+}
+
+static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr)
+{
+       return ((u16)dev_addr->broadcast[8] << 8) | (u16)dev_addr->broadcast[9];
+}
+
+static inline void ib_addr_set_pkey(struct rdma_dev_addr *dev_addr, u16 pkey)
+{
+       dev_addr->broadcast[8] = pkey >> 8;
+       dev_addr->broadcast[9] = (unsigned char) pkey;
+}
+
+static inline union ib_gid *ib_addr_get_sgid(struct rdma_dev_addr *dev_addr)
+{
+       return  (union ib_gid *) (dev_addr->src_dev_addr + 4);
+}
+
+static inline void ib_addr_set_sgid(struct rdma_dev_addr *dev_addr,
+                                   union ib_gid *gid)
+{
+       memcpy(dev_addr->src_dev_addr + 4, gid, sizeof *gid);
+}
+
+static inline union ib_gid *ib_addr_get_dgid(struct rdma_dev_addr *dev_addr)
+{
+       return  (union ib_gid *) (dev_addr->dst_dev_addr + 4);
+}
+
+static inline void ib_addr_set_dgid(struct rdma_dev_addr *dev_addr,
+                                   union ib_gid *gid)
+{
+       memcpy(dev_addr->dst_dev_addr + 4, gid, sizeof *gid);
+}
+
+#endif /* IB_ADDR_H */
index 5bf9834f7dcae588f126a8800f6685654e1bb881..f179d233ffc34f22aa02ee2d928d74c691566938 100644 (file)
@@ -102,4 +102,17 @@ int ib_find_cached_pkey(struct ib_device    *device,
                        u16                  pkey,
                        u16                 *index);
 
+/**
+ * ib_get_cached_lmc - Returns a cached lmc table entry
+ * @device: The device to query.
+ * @port_num: The port number of the device to query.
+ * @lmc: The lmc value for the specified port for that device.
+ *
+ * ib_get_cached_lmc() fetches the specified lmc table entry stored in
+ * the local software cache.
+ */
+int ib_get_cached_lmc(struct ib_device *device,
+                     u8                port_num,
+                     u8                *lmc);
+
 #endif /* _IB_CACHE_H */
index 0a9fcd59eb430966031b7d2aa4bde4b0a94ffb1f..c9b4738be9d68021067b8911c68713362d2d0c9d 100644 (file)
@@ -32,7 +32,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: ib_cm.h 2730 2005-06-28 16:43:03Z sean.hefty $
+ * $Id: ib_cm.h 4311 2005-12-05 18:42:01Z sean.hefty $
  */
 #if !defined(IB_CM_H)
 #define IB_CM_H
@@ -102,7 +102,8 @@ enum ib_cm_data_size {
        IB_CM_APR_INFO_LENGTH            = 72,
        IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE = 216,
        IB_CM_SIDR_REP_PRIVATE_DATA_SIZE = 136,
-       IB_CM_SIDR_REP_INFO_LENGTH       = 72
+       IB_CM_SIDR_REP_INFO_LENGTH       = 72,
+       IB_CM_COMPARE_SIZE               = 64
 };
 
 struct ib_cm_id;
@@ -238,7 +239,6 @@ struct ib_cm_sidr_rep_event_param {
        u32                     qpn;
        void                    *info;
        u8                      info_len;
-
 };
 
 struct ib_cm_event {
@@ -317,6 +317,15 @@ void ib_destroy_cm_id(struct ib_cm_id *cm_id);
 
 #define IB_SERVICE_ID_AGN_MASK __constant_cpu_to_be64(0xFF00000000000000ULL)
 #define IB_CM_ASSIGN_SERVICE_ID __constant_cpu_to_be64(0x0200000000000000ULL)
+#define IB_CMA_SERVICE_ID      __constant_cpu_to_be64(0x0000000001000000ULL)
+#define IB_CMA_SERVICE_ID_MASK __constant_cpu_to_be64(0xFFFFFFFFFF000000ULL)
+#define IB_SDP_SERVICE_ID      __constant_cpu_to_be64(0x0000000000010000ULL)
+#define IB_SDP_SERVICE_ID_MASK __constant_cpu_to_be64(0xFFFFFFFFFFFF0000ULL)
+
+struct ib_cm_compare_data {
+       u8  data[IB_CM_COMPARE_SIZE];
+       u8  mask[IB_CM_COMPARE_SIZE];
+};
 
 /**
  * ib_cm_listen - Initiates listening on the specified service ID for
@@ -330,10 +339,12 @@ void ib_destroy_cm_id(struct ib_cm_id *cm_id);
  *   range of service IDs.  If set to 0, the service ID is matched
  *   exactly.  This parameter is ignored if %service_id is set to
  *   IB_CM_ASSIGN_SERVICE_ID.
+ * @compare_data: This parameter is optional.  It specifies data that must
+ *   appear in the private data of a connection request for the specified
+ *   listen request.
  */
-int ib_cm_listen(struct ib_cm_id *cm_id,
-                __be64 service_id,
-                __be64 service_mask);
+int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask,
+                struct ib_cm_compare_data *compare_data);
 
 struct ib_cm_req_param {
        struct ib_sa_path_rec   *primary_path;
@@ -535,7 +546,6 @@ struct ib_cm_sidr_req_param {
        const void              *private_data;
        u8                      private_data_len;
        u8                      max_cm_retries;
-       u16                     pkey;
 };
 
 /**
@@ -559,7 +569,7 @@ struct ib_cm_sidr_rep_param {
 };
 
 /**
- * ib_send_cm_sidr_rep - Sends a service ID resolution request to the
+ * ib_send_cm_sidr_rep - Sends a service ID resolution reply to the
  *   remote node.
  * @cm_id: Communication identifier associated with the received service ID
  *   resolution request.
diff --git a/include/rdma/ib_marshall.h b/include/rdma/ib_marshall.h
new file mode 100644 (file)
index 0000000..66bf4d7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(IB_USER_MARSHALL_H)
+#define IB_USER_MARSHALL_H
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_sa.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_user_sa.h>
+
+void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
+                            struct ib_qp_attr *src);
+
+void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
+                             struct ib_sa_path_rec *src);
+
+void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst,
+                               struct ib_user_path_rec *src);
+
+#endif /* IB_USER_MARSHALL_H */
index ad63c215efe5b68be3d555fccda212ff09a3358a..c99e4420fd7ec308d9d2826c0bdd0493312bc5dd 100644 (file)
@@ -370,5 +370,12 @@ ib_sa_mcmember_rec_delete(struct ib_device *device, u8 port_num,
                                        context, query);
 }
 
+/**
+ * ib_init_ah_from_path - Initialize address handle attributes based on an SA
+ *   path record.
+ */
+int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
+                        struct ib_sa_path_rec *rec,
+                        struct ib_ah_attr *ah_attr);
 
 #endif /* IB_SA_H */
index 87f60737f69575e2b86426f3cbaa592638dca151..f29af135ba833c841926e33b6d9bac0de42693e9 100644 (file)
@@ -85,6 +85,42 @@ struct ib_smp {
 #define IB_SMP_ATTR_LED_INFO                   __constant_htons(0x0031)
 #define IB_SMP_ATTR_VENDOR_MASK                        __constant_htons(0xFF00)
 
+struct ib_port_info {
+       __be64 mkey;
+       __be64 gid_prefix;
+       __be16 lid;
+       __be16 sm_lid;
+       __be32 cap_mask;
+       __be16 diag_code;
+       __be16 mkey_lease_period;
+       u8 local_port_num;
+       u8 link_width_enabled;
+       u8 link_width_supported;
+       u8 link_width_active;
+       u8 linkspeed_portstate;                 /* 4 bits, 4 bits */
+       u8 portphysstate_linkdown;              /* 4 bits, 4 bits */
+       u8 mkeyprot_resv_lmc;                   /* 2 bits, 3, 3 */
+       u8 linkspeedactive_enabled;             /* 4 bits, 4 bits */
+       u8 neighbormtu_mastersmsl;              /* 4 bits, 4 bits */
+       u8 vlcap_inittype;                      /* 4 bits, 4 bits */
+       u8 vl_high_limit;
+       u8 vl_arb_high_cap;
+       u8 vl_arb_low_cap;
+       u8 inittypereply_mtucap;                /* 4 bits, 4 bits */
+       u8 vlstallcnt_hoqlife;                  /* 3 bits, 5 bits */
+       u8 operationalvl_pei_peo_fpi_fpo;       /* 4 bits, 1, 1, 1, 1 */
+       __be16 mkey_violations;
+       __be16 pkey_violations;
+       __be16 qkey_violations;
+       u8 guid_cap;
+       u8 clientrereg_resv_subnetto;           /* 1 bit, 2 bits, 5 */
+       u8 resv_resptimevalue;                  /* 3 bits, 5 bits */
+       u8 localphyerrors_overrunerrors;        /* 4 bits, 4 bits */
+       __be16 max_credit_hint;
+       u8 resv;
+       u8 link_roundtrip_latency[3];
+};
+
 static inline u8
 ib_get_smp_direction(struct ib_smp *smp)
 {
index 19be116047f676d89b4f336cf7ab30f55e49a7eb..066c20b7cdfbf08019a3f23c7b17e93e4371e49b 100644 (file)
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: ib_user_cm.h 2576 2005-06-09 17:00:30Z libor $
+ * $Id: ib_user_cm.h 4019 2005-11-11 00:33:09Z sean.hefty $
  */
 
 #ifndef IB_USER_CM_H
 #define IB_USER_CM_H
 
-#include <linux/types.h>
+#include <rdma/ib_user_sa.h>
 
 #define IB_USER_CM_ABI_VERSION 4
 
@@ -110,58 +110,6 @@ struct ib_ucm_init_qp_attr {
        __u32 qp_state;
 };
 
-struct ib_ucm_ah_attr {
-       __u8    grh_dgid[16];
-       __u32   grh_flow_label;
-       __u16   dlid;
-       __u16   reserved;
-       __u8    grh_sgid_index;
-       __u8    grh_hop_limit;
-       __u8    grh_traffic_class;
-       __u8    sl;
-       __u8    src_path_bits;
-       __u8    static_rate;
-       __u8    is_global;
-       __u8    port_num;
-};
-
-struct ib_ucm_init_qp_attr_resp {
-       __u32   qp_attr_mask;
-       __u32   qp_state;
-       __u32   cur_qp_state;
-       __u32   path_mtu;
-       __u32   path_mig_state;
-       __u32   qkey;
-       __u32   rq_psn;
-       __u32   sq_psn;
-       __u32   dest_qp_num;
-       __u32   qp_access_flags;
-
-       struct ib_ucm_ah_attr   ah_attr;
-       struct ib_ucm_ah_attr   alt_ah_attr;
-
-       /* ib_qp_cap */
-       __u32   max_send_wr;
-       __u32   max_recv_wr;
-       __u32   max_send_sge;
-       __u32   max_recv_sge;
-       __u32   max_inline_data;
-
-       __u16   pkey_index;
-       __u16   alt_pkey_index;
-       __u8    en_sqd_async_notify;
-       __u8    sq_draining;
-       __u8    max_rd_atomic;
-       __u8    max_dest_rd_atomic;
-       __u8    min_rnr_timer;
-       __u8    port_num;
-       __u8    timeout;
-       __u8    retry_cnt;
-       __u8    rnr_retry;
-       __u8    alt_port_num;
-       __u8    alt_timeout;
-};
-
 struct ib_ucm_listen {
        __be64 service_id;
        __be64 service_mask;
@@ -180,28 +128,6 @@ struct ib_ucm_private_data {
        __u8  reserved[3];
 };
 
-struct ib_ucm_path_rec {
-       __u8  dgid[16];
-       __u8  sgid[16];
-       __be16 dlid;
-       __be16 slid;
-       __u32 raw_traffic;
-       __be32 flow_label;
-       __u32 reversible;
-       __u32 mtu;
-       __be16 pkey;
-       __u8  hop_limit;
-       __u8  traffic_class;
-       __u8  numb_path;
-       __u8  sl;
-       __u8  mtu_selector;
-       __u8  rate_selector;
-       __u8  rate;
-       __u8  packet_life_time_selector;
-       __u8  packet_life_time;
-       __u8  preference;
-};
-
 struct ib_ucm_req {
        __u32 id;
        __u32 qpn;
@@ -274,7 +200,7 @@ struct ib_ucm_sidr_req {
        __be64 sid;
        __u64 data;
        __u64 path;
-       __u16 pkey;
+       __u16 reserved_pkey;
        __u8  len;
        __u8  max_cm_retries;
        __u8  reserved[4];
@@ -304,8 +230,8 @@ struct ib_ucm_event_get {
 };
 
 struct ib_ucm_req_event_resp {
-       struct ib_ucm_path_rec primary_path;
-       struct ib_ucm_path_rec alternate_path;
+       struct ib_user_path_rec primary_path;
+       struct ib_user_path_rec alternate_path;
        __be64                 remote_ca_guid;
        __u32                  remote_qkey;
        __u32                  remote_qpn;
@@ -349,7 +275,7 @@ struct ib_ucm_mra_event_resp {
 };
 
 struct ib_ucm_lap_event_resp {
-       struct ib_ucm_path_rec path;
+       struct ib_user_path_rec path;
 };
 
 struct ib_ucm_apr_event_resp {
diff --git a/include/rdma/ib_user_sa.h b/include/rdma/ib_user_sa.h
new file mode 100644 (file)
index 0000000..6591201
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_SA_H
+#define IB_USER_SA_H
+
+#include <linux/types.h>
+
+struct ib_user_path_rec {
+       __u8    dgid[16];
+       __u8    sgid[16];
+       __be16  dlid;
+       __be16  slid;
+       __u32   raw_traffic;
+       __be32  flow_label;
+       __u32   reversible;
+       __u32   mtu;
+       __be16  pkey;
+       __u8    hop_limit;
+       __u8    traffic_class;
+       __u8    numb_path;
+       __u8    sl;
+       __u8    mtu_selector;
+       __u8    rate_selector;
+       __u8    rate;
+       __u8    packet_life_time_selector;
+       __u8    packet_life_time;
+       __u8    preference;
+};
+
+#endif /* IB_USER_SA_H */
index 338ed433306381c543aa963058804caddb48d7ed..7b5372010f4b0a5168f5b7226389b990fa62aa92 100644 (file)
@@ -32,7 +32,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: ib_user_verbs.h 2708 2005-06-24 17:27:21Z roland $
+ * $Id: ib_user_verbs.h 4019 2005-11-11 00:33:09Z sean.hefty $
  */
 
 #ifndef IB_USER_VERBS_H
@@ -323,6 +323,64 @@ struct ib_uverbs_destroy_cq_resp {
        __u32 async_events_reported;
 };
 
+struct ib_uverbs_global_route {
+       __u8  dgid[16];
+       __u32 flow_label;
+       __u8  sgid_index;
+       __u8  hop_limit;
+       __u8  traffic_class;
+       __u8  reserved;
+};
+
+struct ib_uverbs_ah_attr {
+       struct ib_uverbs_global_route grh;
+       __u16 dlid;
+       __u8  sl;
+       __u8  src_path_bits;
+       __u8  static_rate;
+       __u8  is_global;
+       __u8  port_num;
+       __u8  reserved;
+};
+
+struct ib_uverbs_qp_attr {
+       __u32   qp_attr_mask;
+       __u32   qp_state;
+       __u32   cur_qp_state;
+       __u32   path_mtu;
+       __u32   path_mig_state;
+       __u32   qkey;
+       __u32   rq_psn;
+       __u32   sq_psn;
+       __u32   dest_qp_num;
+       __u32   qp_access_flags;
+
+       struct ib_uverbs_ah_attr ah_attr;
+       struct ib_uverbs_ah_attr alt_ah_attr;
+
+       /* ib_qp_cap */
+       __u32   max_send_wr;
+       __u32   max_recv_wr;
+       __u32   max_send_sge;
+       __u32   max_recv_sge;
+       __u32   max_inline_data;
+
+       __u16   pkey_index;
+       __u16   alt_pkey_index;
+       __u8    en_sqd_async_notify;
+       __u8    sq_draining;
+       __u8    max_rd_atomic;
+       __u8    max_dest_rd_atomic;
+       __u8    min_rnr_timer;
+       __u8    port_num;
+       __u8    timeout;
+       __u8    retry_cnt;
+       __u8    rnr_retry;
+       __u8    alt_port_num;
+       __u8    alt_timeout;
+       __u8    reserved[5];
+};
+
 struct ib_uverbs_create_qp {
        __u64 response;
        __u64 user_handle;
@@ -541,26 +599,6 @@ struct ib_uverbs_post_srq_recv_resp {
        __u32 bad_wr;
 };
 
-struct ib_uverbs_global_route {
-       __u8  dgid[16];
-       __u32 flow_label;
-       __u8  sgid_index;
-       __u8  hop_limit;
-       __u8  traffic_class;
-       __u8  reserved;
-};
-
-struct ib_uverbs_ah_attr {
-       struct ib_uverbs_global_route grh;
-       __u16 dlid;
-       __u8  sl;
-       __u8  src_path_bits;
-       __u8  static_rate;
-       __u8  is_global;
-       __u8  port_num;
-       __u8  reserved;
-};
-
 struct ib_uverbs_create_ah {
        __u64 response;
        __u64 user_handle;
index 6bbf1b364400568b283215e37b6e9bec776dd84b..ee1f3a355666dbddaa388fc3d613bc329c24c9d3 100644 (file)
@@ -260,7 +260,8 @@ enum ib_event_type {
        IB_EVENT_SM_CHANGE,
        IB_EVENT_SRQ_ERR,
        IB_EVENT_SRQ_LIMIT_REACHED,
-       IB_EVENT_QP_LAST_WQE_REACHED
+       IB_EVENT_QP_LAST_WQE_REACHED,
+       IB_EVENT_CLIENT_REREGISTER
 };
 
 struct ib_event {
@@ -696,8 +697,12 @@ struct ib_ucontext {
 struct ib_uobject {
        u64                     user_handle;    /* handle given to us by userspace */
        struct ib_ucontext     *context;        /* associated user context */
+       void                   *object;         /* containing object */
        struct list_head        list;           /* link to context's list */
        u32                     id;             /* index into kernel idr */
+       struct kref             ref;
+       struct rw_semaphore     mutex;          /* protects .live */
+       int                     live;
 };
 
 struct ib_umem {
@@ -827,6 +832,7 @@ struct ib_cache {
        struct ib_event_handler event_handler;
        struct ib_pkey_cache  **pkey_cache;
        struct ib_gid_cache   **gid_cache;
+       u8                     *lmc_cache;
 };
 
 struct ib_device {
@@ -1085,6 +1091,20 @@ int ib_dealloc_pd(struct ib_pd *pd);
  */
 struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
 
+/**
+ * ib_init_ah_from_wc - Initializes address handle attributes from a
+ *   work completion.
+ * @device: Device on which the received message arrived.
+ * @port_num: Port on which the received message arrived.
+ * @wc: Work completion associated with the received message.
+ * @grh: References the received global route header.  This parameter is
+ *   ignored unless the work completion indicates that the GRH is valid.
+ * @ah_attr: Returned attributes that can be used when creating an address
+ *   handle for replying to the message.
+ */
+int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
+                      struct ib_grh *grh, struct ib_ah_attr *ah_attr);
+
 /**
  * ib_create_ah_from_wc - Creates an address handle associated with the
  *   sender of the specified work completion.
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
new file mode 100644 (file)
index 0000000..402c63d
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#if !defined(RDMA_CM_H)
+#define RDMA_CM_H
+
+#include <linux/socket.h>
+#include <linux/in6.h>
+#include <rdma/ib_addr.h>
+#include <rdma/ib_sa.h>
+
+/*
+ * Upon receiving a device removal event, users must destroy the associated
+ * RDMA identifier and release all resources allocated with the device.
+ */
+enum rdma_cm_event_type {
+       RDMA_CM_EVENT_ADDR_RESOLVED,
+       RDMA_CM_EVENT_ADDR_ERROR,
+       RDMA_CM_EVENT_ROUTE_RESOLVED,
+       RDMA_CM_EVENT_ROUTE_ERROR,
+       RDMA_CM_EVENT_CONNECT_REQUEST,
+       RDMA_CM_EVENT_CONNECT_RESPONSE,
+       RDMA_CM_EVENT_CONNECT_ERROR,
+       RDMA_CM_EVENT_UNREACHABLE,
+       RDMA_CM_EVENT_REJECTED,
+       RDMA_CM_EVENT_ESTABLISHED,
+       RDMA_CM_EVENT_DISCONNECTED,
+       RDMA_CM_EVENT_DEVICE_REMOVAL,
+};
+
+enum rdma_port_space {
+       RDMA_PS_SDP  = 0x0001,
+       RDMA_PS_TCP  = 0x0106,
+       RDMA_PS_UDP  = 0x0111,
+       RDMA_PS_SCTP = 0x0183
+};
+
+struct rdma_addr {
+       struct sockaddr src_addr;
+       u8              src_pad[sizeof(struct sockaddr_in6) -
+                               sizeof(struct sockaddr)];
+       struct sockaddr dst_addr;
+       u8              dst_pad[sizeof(struct sockaddr_in6) -
+                               sizeof(struct sockaddr)];
+       struct rdma_dev_addr dev_addr;
+};
+
+struct rdma_route {
+       struct rdma_addr addr;
+       struct ib_sa_path_rec *path_rec;
+       int num_paths;
+};
+
+struct rdma_cm_event {
+       enum rdma_cm_event_type  event;
+       int                      status;
+       void                    *private_data;
+       u8                       private_data_len;
+};
+
+struct rdma_cm_id;
+
+/**
+ * rdma_cm_event_handler - Callback used to report user events.
+ *
+ * Notes: Users may not call rdma_destroy_id from this callback to destroy
+ *   the passed in id, or a corresponding listen id.  Returning a
+ *   non-zero value from the callback will destroy the passed in id.
+ */
+typedef int (*rdma_cm_event_handler)(struct rdma_cm_id *id,
+                                    struct rdma_cm_event *event);
+
+struct rdma_cm_id {
+       struct ib_device        *device;
+       void                    *context;
+       struct ib_qp            *qp;
+       rdma_cm_event_handler    event_handler;
+       struct rdma_route        route;
+       enum rdma_port_space     ps;
+       u8                       port_num;
+};
+
+/**
+ * rdma_create_id - Create an RDMA identifier.
+ *
+ * @event_handler: User callback invoked to report events associated with the
+ *   returned rdma_id.
+ * @context: User specified context associated with the id.
+ * @ps: RDMA port space.
+ */
+struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
+                                 void *context, enum rdma_port_space ps);
+
+void rdma_destroy_id(struct rdma_cm_id *id);
+
+/**
+ * rdma_bind_addr - Bind an RDMA identifier to a source address and
+ *   associated RDMA device, if needed.
+ *
+ * @id: RDMA identifier.
+ * @addr: Local address information.  Wildcard values are permitted.
+ *
+ * This associates a source address with the RDMA identifier before calling
+ * rdma_listen.  If a specific local address is given, the RDMA identifier will
+ * be bound to a local RDMA device.
+ */
+int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr);
+
+/**
+ * rdma_resolve_addr - Resolve destination and optional source addresses
+ *   from IP addresses to an RDMA address.  If successful, the specified
+ *   rdma_cm_id will be bound to a local device.
+ *
+ * @id: RDMA identifier.
+ * @src_addr: Source address information.  This parameter may be NULL.
+ * @dst_addr: Destination address information.
+ * @timeout_ms: Time to wait for resolution to complete.
+ */
+int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+                     struct sockaddr *dst_addr, int timeout_ms);
+
+/**
+ * rdma_resolve_route - Resolve the RDMA address bound to the RDMA identifier
+ *   into route information needed to establish a connection.
+ *
+ * This is called on the client side of a connection.
+ * Users must have first called rdma_resolve_addr to resolve a dst_addr
+ * into an RDMA address before calling this routine.
+ */
+int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms);
+
+/**
+ * rdma_create_qp - Allocate a QP and associate it with the specified RDMA
+ * identifier.
+ *
+ * QPs allocated to an rdma_cm_id will automatically be transitioned by the CMA
+ * through their states.
+ */
+int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
+                  struct ib_qp_init_attr *qp_init_attr);
+
+/**
+ * rdma_destroy_qp - Deallocate the QP associated with the specified RDMA
+ * identifier.
+ *
+ * Users must destroy any QP associated with an RDMA identifier before
+ * destroying the RDMA ID.
+ */
+void rdma_destroy_qp(struct rdma_cm_id *id);
+
+/**
+ * rdma_init_qp_attr - Initializes the QP attributes for use in transitioning
+ *   to a specified QP state.
+ * @id: Communication identifier associated with the QP attributes to
+ *   initialize.
+ * @qp_attr: On input, specifies the desired QP state.  On output, the
+ *   mandatory and desired optional attributes will be set in order to
+ *   modify the QP to the specified state.
+ * @qp_attr_mask: The QP attribute mask that may be used to transition the
+ *   QP to the specified state.
+ *
+ * Users must set the @qp_attr->qp_state to the desired QP state.  This call
+ * will set all required attributes for the given transition, along with
+ * known optional attributes.  Users may override the attributes returned from
+ * this call before calling ib_modify_qp.
+ *
+ * Users that wish to have their QP automatically transitioned through its
+ * states can associate a QP with the rdma_cm_id by calling rdma_create_qp().
+ */
+int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
+                      int *qp_attr_mask);
+
+struct rdma_conn_param {
+       const void *private_data;
+       u8 private_data_len;
+       u8 responder_resources;
+       u8 initiator_depth;
+       u8 flow_control;
+       u8 retry_count;         /* ignored when accepting */
+       u8 rnr_retry_count;
+       /* Fields below ignored if a QP is created on the rdma_cm_id. */
+       u8 srq;
+       u32 qp_num;
+       enum ib_qp_type qp_type;
+};
+
+/**
+ * rdma_connect - Initiate an active connection request.
+ *
+ * Users must have resolved a route for the rdma_cm_id to connect with
+ * by having called rdma_resolve_route before calling this routine.
+ */
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
+
+/**
+ * rdma_listen - This function is called by the passive side to
+ *   listen for incoming connection requests.
+ *
+ * Users must have bound the rdma_cm_id to a local address by calling
+ * rdma_bind_addr before calling this routine.
+ */
+int rdma_listen(struct rdma_cm_id *id, int backlog);
+
+/**
+ * rdma_accept - Called to accept a connection request or response.
+ * @id: Connection identifier associated with the request.
+ * @conn_param: Information needed to establish the connection.  This must be
+ *   provided if accepting a connection request.  If accepting a connection
+ *   response, this parameter must be NULL.
+ *
+ * Typically, this routine is only called by the listener to accept a connection
+ * request.  It must also be called on the active side of a connection if the
+ * user is performing their own QP transitions.
+ */
+int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
+
+/**
+ * rdma_reject - Called to reject a connection request or response.
+ */
+int rdma_reject(struct rdma_cm_id *id, const void *private_data,
+               u8 private_data_len);
+
+/**
+ * rdma_disconnect - This function disconnects the associated QP and
+ *   transitions it into the error state.
+ */
+int rdma_disconnect(struct rdma_cm_id *id);
+
+#endif /* RDMA_CM_H */
+
diff --git a/include/rdma/rdma_cm_ib.h b/include/rdma/rdma_cm_ib.h
new file mode 100644 (file)
index 0000000..e8c3af1
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#if !defined(RDMA_CM_IB_H)
+#define RDMA_CM_IB_H
+
+#include <rdma/rdma_cm.h>
+
+/**
+ * rdma_set_ib_paths - Manually sets the path records used to establish a
+ *   connection.
+ * @id: Connection identifier associated with the request.
+ * @path_rec: Reference to the path record
+ *
+ * This call permits a user to specify routing information for rdma_cm_id's
+ * bound to Infiniband devices.  It is called on the client side of a
+ * connection and replaces the call to rdma_resolve_route.
+ */
+int rdma_set_ib_paths(struct rdma_cm_id *id,
+                     struct ib_sa_path_rec *path_rec, int num_paths);
+
+#endif /* RDMA_CM_IB_H */
index 5626225bd3aec200d9a04728bc56af49a33ad002..6d28b03176570fbcb3b314f1e29122df8d25f0d3 100644 (file)
@@ -27,7 +27,6 @@
 #ifndef SCSI_TRANSPORT_FC_H
 #define SCSI_TRANSPORT_FC_H
 
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <scsi/scsi.h>
 
index 5e1d61913d4ef38f1f800607eb0a000fa71e959a..302680c0c0deacd187fe1c1724ec0078502a8dc7 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef SCSI_TRANSPORT_SPI_H
 #define SCSI_TRANSPORT_SPI_H
 
-#include <linux/config.h>
 #include <linux/transport_class.h>
 #include <linux/mutex.h>
 
index 637f77eccf0c77d491a6c6a4e7d6b54ed115f645..ad178fa78f665a69fba3b4d26e66c9aee9443d75 100644 (file)
@@ -87,6 +87,11 @@ enum srp_login_rej_reason {
        SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED             = 0x00010006
 };
 
+enum {
+       SRP_REV10_IB_IO_CLASS   = 0xff00,
+       SRP_REV16A_IB_IO_CLASS  = 0x0100
+};
+
 struct srp_direct_buf {
        __be64  va;
        __be32  key;
index 89c6a73f39206b06691aee19dab5a29c26327d74..3c522e59a33cf041f75d3fbf82e1ca7ccd6f31af 100644 (file)
@@ -26,7 +26,6 @@
 #include "config.h"
 #endif
 
-#include <linux/config.h>
 
 /* number of supported soundcards */
 #ifdef CONFIG_SND_DYNAMIC_MINORS
index 25e1951a9955ef383c12a2e80f1f6922ddc85041..dec6b1dc37eab02c0c7ed2e498b08db1240b87fb 100644 (file)
@@ -30,13 +30,13 @@ enum HDSP_IO_Type {
 };
 
 struct hdsp_peak_rms {
-       u32 input_peaks[26];
-       u32 playback_peaks[26];
-       u32 output_peaks[28];
-       u64 input_rms[26];
-       u64 playback_rms[26];
+       __u32 input_peaks[26];
+       __u32 playback_peaks[26];
+       __u32 output_peaks[28];
+       __u64 input_rms[26];
+       __u64 playback_rms[26];
        /* These are only used for H96xx cards */
-       u64 output_rms[26];
+       __u64 output_rms[26];
 };
 
 #define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms)
index b913f196131de19549787faf91a413963ada2a2c..f6a42d6c2e2d6e22daade1d3680cc1a088f26d26 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_X86
 struct edid_info {
index 700d6c8eb73657a30efbadc7611e21e23bb10285..b49a5120ca2d6ffc2244fed4515d569aa400c7ec 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef __linux_video_vga_h__
 #define __linux_video_vga_h__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/io.h>
 #ifndef CONFIG_AMIGA
index 3b36a1d536564e742d9d0b8d93f6db11d5a19c83..df864a3582217b648786ff3ad48d2ce64fe6457e 100644 (file)
@@ -182,7 +182,8 @@ config AUDITSYSCALL
        help
          Enable low-overhead system-call auditing infrastructure that
          can be used independently or with another kernel subsystem,
-         such as SELinux.
+         such as SELinux.  To use audit's filesystem watch feature, please
+         ensure that INOTIFY is configured.
 
 config IKCONFIG
        bool "Kernel .config support"
@@ -389,9 +390,6 @@ config SLOB
        default !SLAB
        bool
 
-config OBSOLETE_INTERMODULE
-       tristate
-
 menu "Loadable module support"
 
 config MODULES
index f4b7b9d278cd3bf040cdac1a1ee123401549f103..21b3b8f33a728c505cd7396d9e7517775c07706c 100644 (file)
@@ -409,6 +409,10 @@ void __init prepare_namespace(void)
 
        if (saved_root_name[0]) {
                root_device_name = saved_root_name;
+               if (!strncmp(root_device_name, "mtd", 3)) {
+                       mount_block_root(root_device_name, root_mountflags);
+                       goto out;
+               }
                ROOT_DEV = name_to_dev_t(root_device_name);
                if (strncmp(root_device_name, "/dev/", 5) == 0)
                        root_device_name += 5;
index 41ecbd440feda782dd3ac9949632458c16fd4de8..1511714a95851dc8af01ee2421907c5b0d23725c 100644 (file)
@@ -8,6 +8,8 @@
  * Lockless receive & send, fd based notify:
  *                         Manfred Spraul          (manfred@colorfullife.com)
  *
+ * Audit:                   George Wilson           (ltcgcw@us.ibm.com)
+ *
  * This file is released under the GPL.
  */
 
@@ -24,6 +26,7 @@
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 #include <linux/syscalls.h>
+#include <linux/audit.h>
 #include <linux/signal.h>
 #include <linux/mutex.h>
 
@@ -657,6 +660,10 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
        char *name;
        int fd, error;
 
+       error = audit_mq_open(oflag, mode, u_attr);
+       if (error != 0)
+               return error;
+
        if (IS_ERR(name = getname(u_name)))
                return PTR_ERR(name);
 
@@ -814,6 +821,10 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
        long timeout;
        int ret;
 
+       ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
+       if (ret != 0)
+               return ret;
+
        if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
                return -EINVAL;
 
@@ -896,6 +907,10 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
        struct mqueue_inode_info *info;
        struct ext_wait_queue wait;
 
+       ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
+       if (ret != 0)
+               return ret;
+
        timeout = prepare_timeout(u_abs_timeout);
 
        ret = -EBADF;
@@ -975,6 +990,10 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
        struct mqueue_inode_info *info;
        struct sk_buff *nc;
 
+       ret = audit_mq_notify(mqdes, u_notification);
+       if (ret != 0)
+               return ret;
+
        nc = NULL;
        sock = NULL;
        if (u_notification != NULL) {
@@ -1115,6 +1134,9 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
        omqstat = info->attr;
        omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
        if (u_mqstat) {
+               ret = audit_mq_getsetattr(mqdes, &mqstat);
+               if (ret != 0)
+                       goto out;
                if (mqstat.mq_flags & O_NONBLOCK)
                        filp->f_flags |= O_NONBLOCK;
                else
index 7d1340ccb16b7d333cbbc9d1b2177943d3d63737..00f015a092d292347d781a60bf9f72c71b4381d1 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -454,6 +454,11 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
        err = audit_ipc_obj(ipcp);
        if (err)
                goto out_unlock_up;
+       if (cmd==IPC_SET) {
+               err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode);
+               if (err)
+                       goto out_unlock_up;
+       }
 
        err = -EPERM;
        if (current->euid != ipcp->cuid && 
@@ -468,10 +473,6 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
        switch (cmd) {
        case IPC_SET:
        {
-               err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp);
-               if (err)
-                       goto out_unlock_up;
-
                err = -EPERM;
                if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
                        goto out_unlock_up;
index 7919f8ece6bac8c89cd255b367fa8dfcb722fca5..fce0bc8b5ad6f9c8652883a62c0b5ff2821f3853 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -828,6 +828,11 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
        if (err)
                goto out_unlock;
 
+       if (cmd == IPC_SET) {
+               err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode);
+               if (err)
+                       goto out_unlock;
+       }
        if (current->euid != ipcp->cuid && 
            current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
                err=-EPERM;
@@ -844,9 +849,6 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
                err = 0;
                break;
        case IPC_SET:
-               err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp);
-               if (err)
-                       goto out_unlock;
                ipcp->uid = setbuf.uid;
                ipcp->gid = setbuf.gid;
                ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
index 8098968519026406191014b4cb64ee870e2a721c..4f133d24030f386aa5749455111ec1fbe4da33fe 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -643,7 +643,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
                err = audit_ipc_obj(&(shp->shm_perm));
                if (err)
                        goto out_unlock_up;
-               err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, &(shp->shm_perm));
+               err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode);
                if (err)
                        goto out_unlock_up;
                err=-EPERM;
index 58908f9d156a0c68d2eaf880609e55481a2a2e15..f6ef00f4f90fb9069982c1ef6c986d8bb4e7e346 100644 (file)
@@ -20,7 +20,6 @@ obj-$(CONFIG_SMP) += cpu.o spinlock.o
 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += module.o
-obj-$(CONFIG_OBSOLETE_INTERMODULE) += intermodule.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-$(CONFIG_PM) += power/
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
index df57b493e1cb2c35a8d6fd7f4602751f2ac7fd6d..7dfac7031bd734f6c117e66b660b436b842e41be 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 #include <linux/selinux.h>
+#include <linux/inotify.h>
 
 #include "audit.h"
 
@@ -89,6 +90,7 @@ static int    audit_backlog_wait_overflow = 0;
 /* The identity of the user shutting down the audit system. */
 uid_t          audit_sig_uid = -1;
 pid_t          audit_sig_pid = -1;
+u32            audit_sig_sid = 0;
 
 /* Records can be lost in several ways:
    0) [suppressed in audit_alloc]
@@ -102,6 +104,12 @@ static atomic_t    audit_lost = ATOMIC_INIT(0);
 /* The netlink socket. */
 static struct sock *audit_sock;
 
+/* Inotify handle. */
+struct inotify_handle *audit_ih;
+
+/* Hash for inode-based rules */
+struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
+
 /* The audit_freelist is a list of pre-allocated audit buffers (if more
  * than AUDIT_MAXFREE are in use, the audit buffer is freed instead of
  * being placed on the freelist). */
@@ -114,10 +122,8 @@ static struct task_struct *kauditd_task;
 static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
 static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
 
-/* The netlink socket is only to be read by 1 CPU, which lets us assume
- * that list additions and deletions never happen simultaneously in
- * auditsc.c */
-DEFINE_MUTEX(audit_netlink_mutex);
+/* Serialize requests from userspace. */
+static DEFINE_MUTEX(audit_cmd_mutex);
 
 /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting
  * audit records.  Since printk uses a 1024 byte buffer, this buffer
@@ -250,7 +256,7 @@ static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
                        "audit_rate_limit=%d old=%d by auid=%u",
                        limit, old, loginuid);
        audit_rate_limit = limit;
-       return old;
+       return 0;
 }
 
 static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
@@ -273,7 +279,7 @@ static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
                        "audit_backlog_limit=%d old=%d by auid=%u",
                        limit, old, loginuid);
        audit_backlog_limit = limit;
-       return old;
+       return 0;
 }
 
 static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
@@ -299,7 +305,7 @@ static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
                        "audit_enabled=%d old=%d by auid=%u",
                        state, old, loginuid);
        audit_enabled = state;
-       return old;
+       return 0;
 }
 
 static int audit_set_failure(int state, uid_t loginuid, u32 sid)
@@ -327,7 +333,7 @@ static int audit_set_failure(int state, uid_t loginuid, u32 sid)
                        "audit_failure=%d old=%d by auid=%u",
                        state, old, loginuid);
        audit_failure = state;
-       return old;
+       return 0;
 }
 
 static int kauditd_thread(void *dummy)
@@ -363,9 +369,52 @@ static int kauditd_thread(void *dummy)
                        remove_wait_queue(&kauditd_wait, &wait);
                }
        }
+}
+
+int audit_send_list(void *_dest)
+{
+       struct audit_netlink_list *dest = _dest;
+       int pid = dest->pid;
+       struct sk_buff *skb;
+
+       /* wait for parent to finish and send an ACK */
+       mutex_lock(&audit_cmd_mutex);
+       mutex_unlock(&audit_cmd_mutex);
+
+       while ((skb = __skb_dequeue(&dest->q)) != NULL)
+               netlink_unicast(audit_sock, skb, pid, 0);
+
+       kfree(dest);
+
        return 0;
 }
 
+struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
+                                int multi, void *payload, int size)
+{
+       struct sk_buff  *skb;
+       struct nlmsghdr *nlh;
+       int             len = NLMSG_SPACE(size);
+       void            *data;
+       int             flags = multi ? NLM_F_MULTI : 0;
+       int             t     = done  ? NLMSG_DONE  : type;
+
+       skb = alloc_skb(len, GFP_KERNEL);
+       if (!skb)
+               return NULL;
+
+       nlh              = NLMSG_PUT(skb, pid, seq, t, size);
+       nlh->nlmsg_flags = flags;
+       data             = NLMSG_DATA(nlh);
+       memcpy(data, payload, size);
+       return skb;
+
+nlmsg_failure:                 /* Used by NLMSG_PUT */
+       if (skb)
+               kfree_skb(skb);
+       return NULL;
+}
+
 /**
  * audit_send_reply - send an audit reply message via netlink
  * @pid: process id to send reply to
@@ -383,29 +432,13 @@ void audit_send_reply(int pid, int seq, int type, int done, int multi,
                      void *payload, int size)
 {
        struct sk_buff  *skb;
-       struct nlmsghdr *nlh;
-       int             len = NLMSG_SPACE(size);
-       void            *data;
-       int             flags = multi ? NLM_F_MULTI : 0;
-       int             t     = done  ? NLMSG_DONE  : type;
-
-       skb = alloc_skb(len, GFP_KERNEL);
+       skb = audit_make_reply(pid, seq, type, done, multi, payload, size);
        if (!skb)
                return;
-
-       nlh              = NLMSG_PUT(skb, pid, seq, t, size);
-       nlh->nlmsg_flags = flags;
-       data             = NLMSG_DATA(nlh);
-       memcpy(data, payload, size);
-
        /* Ignore failure. It'll only happen if the sender goes away,
           because our timeout is set to infinite. */
        netlink_unicast(audit_sock, skb, pid, 0);
        return;
-
-nlmsg_failure:                 /* Used by NLMSG_PUT */
-       if (skb)
-               kfree_skb(skb);
 }
 
 /*
@@ -451,7 +484,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        struct audit_buffer     *ab;
        u16                     msg_type = nlh->nlmsg_type;
        uid_t                   loginuid; /* loginuid of sender */
-       struct audit_sig_info   sig_data;
+       struct audit_sig_info   *sig_data;
+       char                    *ctx;
+       u32                     len;
 
        err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
        if (err)
@@ -503,12 +538,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                if (status_get->mask & AUDIT_STATUS_PID) {
                        int old   = audit_pid;
                        if (sid) {
-                               char *ctx = NULL;
-                               u32 len;
-                               int rc;
-                               if ((rc = selinux_ctxid_to_string(
+                               if ((err = selinux_ctxid_to_string(
                                                sid, &ctx, &len)))
-                                       return rc;
+                                       return err;
                                else
                                        audit_log(NULL, GFP_KERNEL,
                                                AUDIT_CONFIG_CHANGE,
@@ -523,10 +555,10 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        audit_pid = status_get->pid;
                }
                if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
-                       audit_set_rate_limit(status_get->rate_limit,
+                       err = audit_set_rate_limit(status_get->rate_limit,
                                                         loginuid, sid);
                if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
-                       audit_set_backlog_limit(status_get->backlog_limit,
+                       err = audit_set_backlog_limit(status_get->backlog_limit,
                                                        loginuid, sid);
                break;
        case AUDIT_USER:
@@ -544,8 +576,6 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                                 "user pid=%d uid=%u auid=%u",
                                                 pid, uid, loginuid);
                                if (sid) {
-                                       char *ctx = NULL;
-                                       u32 len;
                                        if (selinux_ctxid_to_string(
                                                        sid, &ctx, &len)) {
                                                audit_log_format(ab, 
@@ -584,10 +614,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                           loginuid, sid);
                break;
        case AUDIT_SIGNAL_INFO:
-               sig_data.uid = audit_sig_uid;
-               sig_data.pid = audit_sig_pid;
+               err = selinux_ctxid_to_string(audit_sig_sid, &ctx, &len);
+               if (err)
+                       return err;
+               sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
+               if (!sig_data) {
+                       kfree(ctx);
+                       return -ENOMEM;
+               }
+               sig_data->uid = audit_sig_uid;
+               sig_data->pid = audit_sig_pid;
+               memcpy(sig_data->ctx, ctx, len);
+               kfree(ctx);
                audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 
-                               0, 0, &sig_data, sizeof(sig_data));
+                               0, 0, sig_data, sizeof(*sig_data) + len);
+               kfree(sig_data);
                break;
        default:
                err = -EINVAL;
@@ -629,20 +670,30 @@ static void audit_receive(struct sock *sk, int length)
        struct sk_buff  *skb;
        unsigned int qlen;
 
-       mutex_lock(&audit_netlink_mutex);
+       mutex_lock(&audit_cmd_mutex);
 
        for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
                skb = skb_dequeue(&sk->sk_receive_queue);
                audit_receive_skb(skb);
                kfree_skb(skb);
        }
-       mutex_unlock(&audit_netlink_mutex);
+       mutex_unlock(&audit_cmd_mutex);
 }
 
+#ifdef CONFIG_AUDITSYSCALL
+static const struct inotify_operations audit_inotify_ops = {
+       .handle_event   = audit_handle_ievent,
+       .destroy_watch  = audit_free_parent,
+};
+#endif
 
 /* Initialize audit support at boot time. */
 static int __init audit_init(void)
 {
+#ifdef CONFIG_AUDITSYSCALL
+       int i;
+#endif
+
        printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
               audit_default ? "enabled" : "disabled");
        audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive,
@@ -661,6 +712,16 @@ static int __init audit_init(void)
        selinux_audit_set_callback(&selinux_audit_rule_update);
 
        audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
+
+#ifdef CONFIG_AUDITSYSCALL
+       audit_ih = inotify_init(&audit_inotify_ops);
+       if (IS_ERR(audit_ih))
+               audit_panic("cannot initialize inotify handle");
+
+       for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
+               INIT_LIST_HEAD(&audit_inode_hash[i]);
+#endif
+
        return 0;
 }
 __initcall(audit_init);
@@ -690,10 +751,12 @@ static void audit_buffer_free(struct audit_buffer *ab)
                kfree_skb(ab->skb);
 
        spin_lock_irqsave(&audit_freelist_lock, flags);
-       if (++audit_freelist_count > AUDIT_MAXFREE)
+       if (audit_freelist_count > AUDIT_MAXFREE)
                kfree(ab);
-       else
+       else {
+               audit_freelist_count++;
                list_add(&ab->list, &audit_freelist);
+       }
        spin_unlock_irqrestore(&audit_freelist_lock, flags);
 }
 
@@ -988,28 +1051,76 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
        skb_put(skb, len << 1); /* new string is twice the old string */
 }
 
+/*
+ * Format a string of no more than slen characters into the audit buffer,
+ * enclosed in quote marks.
+ */
+static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
+                              const char *string)
+{
+       int avail, new_len;
+       unsigned char *ptr;
+       struct sk_buff *skb;
+
+       BUG_ON(!ab->skb);
+       skb = ab->skb;
+       avail = skb_tailroom(skb);
+       new_len = slen + 3;     /* enclosing quotes + null terminator */
+       if (new_len > avail) {
+               avail = audit_expand(ab, new_len);
+               if (!avail)
+                       return;
+       }
+       ptr = skb->tail;
+       *ptr++ = '"';
+       memcpy(ptr, string, slen);
+       ptr += slen;
+       *ptr++ = '"';
+       *ptr = 0;
+       skb_put(skb, slen + 2); /* don't include null terminator */
+}
+
 /**
- * audit_log_unstrustedstring - log a string that may contain random characters
+ * audit_log_n_unstrustedstring - log a string that may contain random characters
  * @ab: audit_buffer
+ * @len: lenth of string (not including trailing null)
  * @string: string to be logged
  *
  * This code will escape a string that is passed to it if the string
  * contains a control character, unprintable character, double quote mark,
  * or a space. Unescaped strings will start and end with a double quote mark.
  * Strings that are escaped are printed in hex (2 digits per char).
+ *
+ * The caller specifies the number of characters in the string to log, which may
+ * or may not be the entire string.
  */
-void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
+const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
+                                       const char *string)
 {
        const unsigned char *p = string;
 
        while (*p) {
                if (*p == '"' || *p < 0x21 || *p > 0x7f) {
-                       audit_log_hex(ab, string, strlen(string));
-                       return;
+                       audit_log_hex(ab, string, len);
+                       return string + len + 1;
                }
                p++;
        }
-       audit_log_format(ab, "\"%s\"", string);
+       audit_log_n_string(ab, len, string);
+       return p + 1;
+}
+
+/**
+ * audit_log_unstrustedstring - log a string that may contain random characters
+ * @ab: audit_buffer
+ * @string: string to be logged
+ *
+ * Same as audit_log_n_unstrustedstring(), except that strlen is used to
+ * determine string length.
+ */
+const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
+{
+       return audit_log_n_untrustedstring(ab, strlen(string), string);
 }
 
 /* This is a helper-function to print the escaped d_path */
index 6f733920fd32e1cc88fe6840620720ec8cb62978..8323e4132a3308fe2d679eeb167c6c9b9f86a830 100644 (file)
@@ -19,9 +19,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/mutex.h>
 #include <linux/fs.h>
 #include <linux/audit.h>
+#include <linux/skbuff.h>
 
 /* 0 = no checking
    1 = put_count checking
@@ -53,6 +53,18 @@ enum audit_state {
 };
 
 /* Rule lists */
+struct audit_parent;
+
+struct audit_watch {
+       atomic_t                count;  /* reference count */
+       char                    *path;  /* insertion path */
+       dev_t                   dev;    /* associated superblock device */
+       unsigned long           ino;    /* associated inode number */
+       struct audit_parent     *parent; /* associated parent */
+       struct list_head        wlist;  /* entry in parent->watches list */
+       struct list_head        rules;  /* associated rules */
+};
+
 struct audit_field {
        u32                             type;
        u32                             val;
@@ -70,6 +82,9 @@ struct audit_krule {
        u32                     buflen; /* for data alloc on list rules */
        u32                     field_count;
        struct audit_field      *fields;
+       struct audit_field      *inode_f; /* quick access to an inode field */
+       struct audit_watch      *watch; /* associated watch */
+       struct list_head        rlist;  /* entry in audit_watch.rules list */
 };
 
 struct audit_entry {
@@ -78,15 +93,53 @@ struct audit_entry {
        struct audit_krule      rule;
 };
 
-
 extern int audit_pid;
-extern int audit_comparator(const u32 left, const u32 op, const u32 right);
 
+#define AUDIT_INODE_BUCKETS    32
+extern struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
+
+static inline int audit_hash_ino(u32 ino)
+{
+       return (ino & (AUDIT_INODE_BUCKETS-1));
+}
+
+extern int audit_comparator(const u32 left, const u32 op, const u32 right);
+extern int audit_compare_dname_path(const char *dname, const char *path,
+                                   int *dirlen);
+extern struct sk_buff *            audit_make_reply(int pid, int seq, int type,
+                                            int done, int multi,
+                                            void *payload, int size);
 extern void                audit_send_reply(int pid, int seq, int type,
                                             int done, int multi,
                                             void *payload, int size);
 extern void                audit_log_lost(const char *message);
 extern void                audit_panic(const char *message);
-extern struct mutex audit_netlink_mutex;
 
+struct audit_netlink_list {
+       int pid;
+       struct sk_buff_head q;
+};
+
+int audit_send_list(void *);
+
+struct inotify_watch;
+extern void audit_free_parent(struct inotify_watch *);
+extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
+                               const char *, struct inode *);
 extern int selinux_audit_rule_update(void);
+
+#ifdef CONFIG_AUDITSYSCALL
+extern void __audit_signal_info(int sig, struct task_struct *t);
+static inline void audit_signal_info(int sig, struct task_struct *t)
+{
+       if (unlikely(audit_pid && t->tgid == audit_pid))
+               __audit_signal_info(sig, t);
+}
+extern enum audit_state audit_filter_inodes(struct task_struct *,
+                                           struct audit_context *);
+extern void audit_set_auditable(struct audit_context *);
+#else
+#define audit_signal_info(s,t)
+#define audit_filter_inodes(t,c) AUDIT_DISABLED
+#define audit_set_auditable(c)
+#endif
index 7c134906d689c8af18397351089dc01fbbf00461..4c99d2c586edcb2549f27e3e0d18f68e77c48763 100644 (file)
 #include <linux/kernel.h>
 #include <linux/audit.h>
 #include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
 #include <linux/netlink.h>
+#include <linux/sched.h>
+#include <linux/inotify.h>
 #include <linux/selinux.h>
 #include "audit.h"
 
-/* There are three lists of rules -- one to search at task creation
- * time, one to search at syscall entry time, and another to search at
- * syscall exit time. */
+/*
+ * Locking model:
+ *
+ * audit_filter_mutex:
+ *             Synchronizes writes and blocking reads of audit's filterlist
+ *             data.  Rcu is used to traverse the filterlist and access
+ *             contents of structs audit_entry, audit_watch and opaque
+ *             selinux rules during filtering.  If modified, these structures
+ *             must be copied and replace their counterparts in the filterlist.
+ *             An audit_parent struct is not accessed during filtering, so may
+ *             be written directly provided audit_filter_mutex is held.
+ */
+
+/*
+ * Reference counting:
+ *
+ * audit_parent: lifetime is from audit_init_parent() to receipt of an IN_IGNORED
+ *     event.  Each audit_watch holds a reference to its associated parent.
+ *
+ * audit_watch: if added to lists, lifetime is from audit_init_watch() to
+ *     audit_remove_watch().  Additionally, an audit_watch may exist
+ *     temporarily to assist in searching existing filter data.  Each
+ *     audit_krule holds a reference to its associated watch.
+ */
+
+struct audit_parent {
+       struct list_head        ilist;  /* entry in inotify registration list */
+       struct list_head        watches; /* associated watches */
+       struct inotify_watch    wdata;  /* inotify watch data */
+       unsigned                flags;  /* status flags */
+};
+
+/*
+ * audit_parent status flags:
+ *
+ * AUDIT_PARENT_INVALID - set anytime rules/watches are auto-removed due to
+ * a filesystem event to ensure we're adding audit watches to a valid parent.
+ * Technically not needed for IN_DELETE_SELF or IN_UNMOUNT events, as we cannot
+ * receive them while we have nameidata, but must be used for IN_MOVE_SELF which
+ * we can receive while holding nameidata.
+ */
+#define AUDIT_PARENT_INVALID   0x001
+
+/* Audit filter lists, defined in <linux/audit.h> */
 struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
        LIST_HEAD_INIT(audit_filter_list[0]),
        LIST_HEAD_INIT(audit_filter_list[1]),
@@ -41,9 +87,53 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
 #endif
 };
 
+static DEFINE_MUTEX(audit_filter_mutex);
+
+/* Inotify handle */
+extern struct inotify_handle *audit_ih;
+
+/* Inotify events we care about. */
+#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
+
+void audit_free_parent(struct inotify_watch *i_watch)
+{
+       struct audit_parent *parent;
+
+       parent = container_of(i_watch, struct audit_parent, wdata);
+       WARN_ON(!list_empty(&parent->watches));
+       kfree(parent);
+}
+
+static inline void audit_get_watch(struct audit_watch *watch)
+{
+       atomic_inc(&watch->count);
+}
+
+static void audit_put_watch(struct audit_watch *watch)
+{
+       if (atomic_dec_and_test(&watch->count)) {
+               WARN_ON(watch->parent);
+               WARN_ON(!list_empty(&watch->rules));
+               kfree(watch->path);
+               kfree(watch);
+       }
+}
+
+static void audit_remove_watch(struct audit_watch *watch)
+{
+       list_del(&watch->wlist);
+       put_inotify_watch(&watch->parent->wdata);
+       watch->parent = NULL;
+       audit_put_watch(watch); /* match initial get */
+}
+
 static inline void audit_free_rule(struct audit_entry *e)
 {
        int i;
+
+       /* some rules don't have associated watches */
+       if (e->rule.watch)
+               audit_put_watch(e->rule.watch);
        if (e->rule.fields)
                for (i = 0; i < e->rule.field_count; i++) {
                        struct audit_field *f = &e->rule.fields[i];
@@ -60,6 +150,50 @@ static inline void audit_free_rule_rcu(struct rcu_head *head)
        audit_free_rule(e);
 }
 
+/* Initialize a parent watch entry. */
+static struct audit_parent *audit_init_parent(struct nameidata *ndp)
+{
+       struct audit_parent *parent;
+       s32 wd;
+
+       parent = kzalloc(sizeof(*parent), GFP_KERNEL);
+       if (unlikely(!parent))
+               return ERR_PTR(-ENOMEM);
+
+       INIT_LIST_HEAD(&parent->watches);
+       parent->flags = 0;
+
+       inotify_init_watch(&parent->wdata);
+       /* grab a ref so inotify watch hangs around until we take audit_filter_mutex */
+       get_inotify_watch(&parent->wdata);
+       wd = inotify_add_watch(audit_ih, &parent->wdata, ndp->dentry->d_inode,
+                              AUDIT_IN_WATCH);
+       if (wd < 0) {
+               audit_free_parent(&parent->wdata);
+               return ERR_PTR(wd);
+       }
+
+       return parent;
+}
+
+/* Initialize a watch entry. */
+static struct audit_watch *audit_init_watch(char *path)
+{
+       struct audit_watch *watch;
+
+       watch = kzalloc(sizeof(*watch), GFP_KERNEL);
+       if (unlikely(!watch))
+               return ERR_PTR(-ENOMEM);
+
+       INIT_LIST_HEAD(&watch->rules);
+       atomic_set(&watch->count, 1);
+       watch->path = path;
+       watch->dev = (dev_t)-1;
+       watch->ino = (unsigned long)-1;
+
+       return watch;
+}
+
 /* Initialize an audit filterlist entry. */
 static inline struct audit_entry *audit_init_entry(u32 field_count)
 {
@@ -107,6 +241,43 @@ static char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
        return str;
 }
 
+/* Translate an inode field to kernel respresentation. */
+static inline int audit_to_inode(struct audit_krule *krule,
+                                struct audit_field *f)
+{
+       if (krule->listnr != AUDIT_FILTER_EXIT ||
+           krule->watch || krule->inode_f)
+               return -EINVAL;
+
+       krule->inode_f = f;
+       return 0;
+}
+
+/* Translate a watch string to kernel respresentation. */
+static int audit_to_watch(struct audit_krule *krule, char *path, int len,
+                         u32 op)
+{
+       struct audit_watch *watch;
+
+       if (!audit_ih)
+               return -EOPNOTSUPP;
+
+       if (path[0] != '/' || path[len-1] == '/' ||
+           krule->listnr != AUDIT_FILTER_EXIT ||
+           op & ~AUDIT_EQUAL ||
+           krule->inode_f || krule->watch) /* 1 inode # per rule, for hash */
+               return -EINVAL;
+
+       watch = audit_init_watch(path);
+       if (unlikely(IS_ERR(watch)))
+               return PTR_ERR(watch);
+
+       audit_get_watch(watch);
+       krule->watch = watch;
+
+       return 0;
+}
+
 /* Common user-space to kernel rule translation. */
 static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
 {
@@ -128,8 +299,11 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
 #endif
                ;
        }
-       if (rule->action != AUDIT_NEVER && rule->action != AUDIT_POSSIBLE &&
-           rule->action != AUDIT_ALWAYS)
+       if (unlikely(rule->action == AUDIT_POSSIBLE)) {
+               printk(KERN_ERR "AUDIT_POSSIBLE is deprecated\n");
+               goto exit_err;
+       }
+       if (rule->action != AUDIT_NEVER && rule->action != AUDIT_ALWAYS)
                goto exit_err;
        if (rule->field_count > AUDIT_MAX_FIELDS)
                goto exit_err;
@@ -158,6 +332,7 @@ exit_err:
 static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
 {
        struct audit_entry *entry;
+       struct audit_field *f;
        int err = 0;
        int i;
 
@@ -172,14 +347,37 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
                f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
                f->val = rule->values[i];
 
-               if (f->type & AUDIT_UNUSED_BITS ||
-                   f->type == AUDIT_SE_USER ||
-                   f->type == AUDIT_SE_ROLE ||
-                   f->type == AUDIT_SE_TYPE ||
-                   f->type == AUDIT_SE_SEN ||
-                   f->type == AUDIT_SE_CLR) {
-                       err = -EINVAL;
+               err = -EINVAL;
+               switch(f->type) {
+               default:
                        goto exit_free;
+               case AUDIT_PID:
+               case AUDIT_UID:
+               case AUDIT_EUID:
+               case AUDIT_SUID:
+               case AUDIT_FSUID:
+               case AUDIT_GID:
+               case AUDIT_EGID:
+               case AUDIT_SGID:
+               case AUDIT_FSGID:
+               case AUDIT_LOGINUID:
+               case AUDIT_PERS:
+               case AUDIT_ARCH:
+               case AUDIT_MSGTYPE:
+               case AUDIT_DEVMAJOR:
+               case AUDIT_DEVMINOR:
+               case AUDIT_EXIT:
+               case AUDIT_SUCCESS:
+               case AUDIT_ARG0:
+               case AUDIT_ARG1:
+               case AUDIT_ARG2:
+               case AUDIT_ARG3:
+                       break;
+               case AUDIT_INODE:
+                       err = audit_to_inode(&entry->rule, f);
+                       if (err)
+                               goto exit_free;
+                       break;
                }
 
                entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
@@ -196,6 +394,18 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
                }
        }
 
+       f = entry->rule.inode_f;
+       if (f) {
+               switch(f->op) {
+               case AUDIT_NOT_EQUAL:
+                       entry->rule.inode_f = NULL;
+               case AUDIT_EQUAL:
+                       break;
+               default:
+                       goto exit_free;
+               }
+       }
+
 exit_nofree:
        return entry;
 
@@ -210,6 +420,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
 {
        int err = 0;
        struct audit_entry *entry;
+       struct audit_field *f;
        void *bufp;
        size_t remain = datasz - sizeof(struct audit_rule_data);
        int i;
@@ -235,6 +446,29 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                f->se_str = NULL;
                f->se_rule = NULL;
                switch(f->type) {
+               case AUDIT_PID:
+               case AUDIT_UID:
+               case AUDIT_EUID:
+               case AUDIT_SUID:
+               case AUDIT_FSUID:
+               case AUDIT_GID:
+               case AUDIT_EGID:
+               case AUDIT_SGID:
+               case AUDIT_FSGID:
+               case AUDIT_LOGINUID:
+               case AUDIT_PERS:
+               case AUDIT_ARCH:
+               case AUDIT_MSGTYPE:
+               case AUDIT_PPID:
+               case AUDIT_DEVMAJOR:
+               case AUDIT_DEVMINOR:
+               case AUDIT_EXIT:
+               case AUDIT_SUCCESS:
+               case AUDIT_ARG0:
+               case AUDIT_ARG1:
+               case AUDIT_ARG2:
+               case AUDIT_ARG3:
+                       break;
                case AUDIT_SE_USER:
                case AUDIT_SE_ROLE:
                case AUDIT_SE_TYPE:
@@ -260,6 +494,37 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                        } else
                                f->se_str = str;
                        break;
+               case AUDIT_WATCH:
+                       str = audit_unpack_string(&bufp, &remain, f->val);
+                       if (IS_ERR(str))
+                               goto exit_free;
+                       entry->rule.buflen += f->val;
+
+                       err = audit_to_watch(&entry->rule, str, f->val, f->op);
+                       if (err) {
+                               kfree(str);
+                               goto exit_free;
+                       }
+                       break;
+               case AUDIT_INODE:
+                       err = audit_to_inode(&entry->rule, f);
+                       if (err)
+                               goto exit_free;
+                       break;
+               default:
+                       goto exit_free;
+               }
+       }
+
+       f = entry->rule.inode_f;
+       if (f) {
+               switch(f->op) {
+               case AUDIT_NOT_EQUAL:
+                       entry->rule.inode_f = NULL;
+               case AUDIT_EQUAL:
+                       break;
+               default:
+                       goto exit_free;
                }
        }
 
@@ -291,7 +556,7 @@ static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule)
 
        rule = kmalloc(sizeof(*rule), GFP_KERNEL);
        if (unlikely(!rule))
-               return ERR_PTR(-ENOMEM);
+               return NULL;
        memset(rule, 0, sizeof(*rule));
 
        rule->flags = krule->flags | krule->listnr;
@@ -322,7 +587,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
 
        data = kmalloc(sizeof(*data) + krule->buflen, GFP_KERNEL);
        if (unlikely(!data))
-               return ERR_PTR(-ENOMEM);
+               return NULL;
        memset(data, 0, sizeof(*data));
 
        data->flags = krule->flags | krule->listnr;
@@ -343,6 +608,10 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
                        data->buflen += data->values[i] =
                                audit_pack_string(&bufp, f->se_str);
                        break;
+               case AUDIT_WATCH:
+                       data->buflen += data->values[i] =
+                               audit_pack_string(&bufp, krule->watch->path);
+                       break;
                default:
                        data->values[i] = f->val;
                }
@@ -378,6 +647,10 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
                        if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
                                return 1;
                        break;
+               case AUDIT_WATCH:
+                       if (strcmp(a->watch->path, b->watch->path))
+                               return 1;
+                       break;
                default:
                        if (a->fields[i].val != b->fields[i].val)
                                return 1;
@@ -391,6 +664,32 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
        return 0;
 }
 
+/* Duplicate the given audit watch.  The new watch's rules list is initialized
+ * to an empty list and wlist is undefined. */
+static struct audit_watch *audit_dupe_watch(struct audit_watch *old)
+{
+       char *path;
+       struct audit_watch *new;
+
+       path = kstrdup(old->path, GFP_KERNEL);
+       if (unlikely(!path))
+               return ERR_PTR(-ENOMEM);
+
+       new = audit_init_watch(path);
+       if (unlikely(IS_ERR(new))) {
+               kfree(path);
+               goto out;
+       }
+
+       new->dev = old->dev;
+       new->ino = old->ino;
+       get_inotify_watch(&old->parent->wdata);
+       new->parent = old->parent;
+
+out:
+       return new;
+}
+
 /* Duplicate selinux field information.  The se_rule is opaque, so must be
  * re-initialized. */
 static inline int audit_dupe_selinux_field(struct audit_field *df,
@@ -422,8 +721,11 @@ static inline int audit_dupe_selinux_field(struct audit_field *df,
 /* Duplicate an audit rule.  This will be a deep copy with the exception
  * of the watch - that pointer is carried over.  The selinux specific fields
  * will be updated in the copy.  The point is to be able to replace the old
- * rule with the new rule in the filterlist, then free the old rule. */
-static struct audit_entry *audit_dupe_rule(struct audit_krule *old)
+ * rule with the new rule in the filterlist, then free the old rule.
+ * The rlist element is undefined; list manipulations are handled apart from
+ * the initial copy. */
+static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
+                                          struct audit_watch *watch)
 {
        u32 fcount = old->field_count;
        struct audit_entry *entry;
@@ -442,6 +744,8 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old)
        for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
                new->mask[i] = old->mask[i];
        new->buflen = old->buflen;
+       new->inode_f = old->inode_f;
+       new->watch = NULL;
        new->field_count = old->field_count;
        memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
 
@@ -463,68 +767,409 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old)
                }
        }
 
+       if (watch) {
+               audit_get_watch(watch);
+               new->watch = watch;
+       }
+
        return entry;
 }
 
-/* Add rule to given filterlist if not a duplicate.  Protected by
- * audit_netlink_mutex. */
+/* Update inode info in audit rules based on filesystem event. */
+static void audit_update_watch(struct audit_parent *parent,
+                              const char *dname, dev_t dev,
+                              unsigned long ino, unsigned invalidating)
+{
+       struct audit_watch *owatch, *nwatch, *nextw;
+       struct audit_krule *r, *nextr;
+       struct audit_entry *oentry, *nentry;
+       struct audit_buffer *ab;
+
+       mutex_lock(&audit_filter_mutex);
+       list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
+               if (audit_compare_dname_path(dname, owatch->path, NULL))
+                       continue;
+
+               /* If the update involves invalidating rules, do the inode-based
+                * filtering now, so we don't omit records. */
+               if (invalidating &&
+                   audit_filter_inodes(current, current->audit_context) == AUDIT_RECORD_CONTEXT)
+                       audit_set_auditable(current->audit_context);
+
+               nwatch = audit_dupe_watch(owatch);
+               if (unlikely(IS_ERR(nwatch))) {
+                       mutex_unlock(&audit_filter_mutex);
+                       audit_panic("error updating watch, skipping");
+                       return;
+               }
+               nwatch->dev = dev;
+               nwatch->ino = ino;
+
+               list_for_each_entry_safe(r, nextr, &owatch->rules, rlist) {
+
+                       oentry = container_of(r, struct audit_entry, rule);
+                       list_del(&oentry->rule.rlist);
+                       list_del_rcu(&oentry->list);
+
+                       nentry = audit_dupe_rule(&oentry->rule, nwatch);
+                       if (unlikely(IS_ERR(nentry)))
+                               audit_panic("error updating watch, removing");
+                       else {
+                               int h = audit_hash_ino((u32)ino);
+                               list_add(&nentry->rule.rlist, &nwatch->rules);
+                               list_add_rcu(&nentry->list, &audit_inode_hash[h]);
+                       }
+
+                       call_rcu(&oentry->rcu, audit_free_rule_rcu);
+               }
+
+               ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+               audit_log_format(ab, "audit updated rules specifying watch=");
+               audit_log_untrustedstring(ab, owatch->path);
+               audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
+               audit_log_end(ab);
+
+               audit_remove_watch(owatch);
+               goto add_watch_to_parent; /* event applies to a single watch */
+       }
+       mutex_unlock(&audit_filter_mutex);
+       return;
+
+add_watch_to_parent:
+       list_add(&nwatch->wlist, &parent->watches);
+       mutex_unlock(&audit_filter_mutex);
+       return;
+}
+
+/* Remove all watches & rules associated with a parent that is going away. */
+static void audit_remove_parent_watches(struct audit_parent *parent)
+{
+       struct audit_watch *w, *nextw;
+       struct audit_krule *r, *nextr;
+       struct audit_entry *e;
+
+       mutex_lock(&audit_filter_mutex);
+       parent->flags |= AUDIT_PARENT_INVALID;
+       list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
+               list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
+                       e = container_of(r, struct audit_entry, rule);
+                       list_del(&r->rlist);
+                       list_del_rcu(&e->list);
+                       call_rcu(&e->rcu, audit_free_rule_rcu);
+
+                       audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+                                "audit implicitly removed rule from list=%d\n",
+                                 AUDIT_FILTER_EXIT);
+               }
+               audit_remove_watch(w);
+       }
+       mutex_unlock(&audit_filter_mutex);
+}
+
+/* Unregister inotify watches for parents on in_list.
+ * Generates an IN_IGNORED event. */
+static void audit_inotify_unregister(struct list_head *in_list)
+{
+       struct audit_parent *p, *n;
+
+       list_for_each_entry_safe(p, n, in_list, ilist) {
+               list_del(&p->ilist);
+               inotify_rm_watch(audit_ih, &p->wdata);
+               /* the put matching the get in audit_do_del_rule() */
+               put_inotify_watch(&p->wdata);
+       }
+}
+
+/* Find an existing audit rule.
+ * Caller must hold audit_filter_mutex to prevent stale rule data. */
+static struct audit_entry *audit_find_rule(struct audit_entry *entry,
+                                          struct list_head *list)
+{
+       struct audit_entry *e, *found = NULL;
+       int h;
+
+       if (entry->rule.watch) {
+               /* we don't know the inode number, so must walk entire hash */
+               for (h = 0; h < AUDIT_INODE_BUCKETS; h++) {
+                       list = &audit_inode_hash[h];
+                       list_for_each_entry(e, list, list)
+                               if (!audit_compare_rule(&entry->rule, &e->rule)) {
+                                       found = e;
+                                       goto out;
+                               }
+               }
+               goto out;
+       }
+
+       list_for_each_entry(e, list, list)
+               if (!audit_compare_rule(&entry->rule, &e->rule)) {
+                       found = e;
+                       goto out;
+               }
+
+out:
+       return found;
+}
+
+/* Get path information necessary for adding watches. */
+static int audit_get_nd(char *path, struct nameidata **ndp,
+                       struct nameidata **ndw)
+{
+       struct nameidata *ndparent, *ndwatch;
+       int err;
+
+       ndparent = kmalloc(sizeof(*ndparent), GFP_KERNEL);
+       if (unlikely(!ndparent))
+               return -ENOMEM;
+
+       ndwatch = kmalloc(sizeof(*ndwatch), GFP_KERNEL);
+       if (unlikely(!ndwatch)) {
+               kfree(ndparent);
+               return -ENOMEM;
+       }
+
+       err = path_lookup(path, LOOKUP_PARENT, ndparent);
+       if (err) {
+               kfree(ndparent);
+               kfree(ndwatch);
+               return err;
+       }
+
+       err = path_lookup(path, 0, ndwatch);
+       if (err) {
+               kfree(ndwatch);
+               ndwatch = NULL;
+       }
+
+       *ndp = ndparent;
+       *ndw = ndwatch;
+
+       return 0;
+}
+
+/* Release resources used for watch path information. */
+static void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw)
+{
+       if (ndp) {
+               path_release(ndp);
+               kfree(ndp);
+       }
+       if (ndw) {
+               path_release(ndw);
+               kfree(ndw);
+       }
+}
+
+/* Associate the given rule with an existing parent inotify_watch.
+ * Caller must hold audit_filter_mutex. */
+static void audit_add_to_parent(struct audit_krule *krule,
+                               struct audit_parent *parent)
+{
+       struct audit_watch *w, *watch = krule->watch;
+       int watch_found = 0;
+
+       list_for_each_entry(w, &parent->watches, wlist) {
+               if (strcmp(watch->path, w->path))
+                       continue;
+
+               watch_found = 1;
+
+               /* put krule's and initial refs to temporary watch */
+               audit_put_watch(watch);
+               audit_put_watch(watch);
+
+               audit_get_watch(w);
+               krule->watch = watch = w;
+               break;
+       }
+
+       if (!watch_found) {
+               get_inotify_watch(&parent->wdata);
+               watch->parent = parent;
+
+               list_add(&watch->wlist, &parent->watches);
+       }
+       list_add(&krule->rlist, &watch->rules);
+}
+
+/* Find a matching watch entry, or add this one.
+ * Caller must hold audit_filter_mutex. */
+static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
+                          struct nameidata *ndw)
+{
+       struct audit_watch *watch = krule->watch;
+       struct inotify_watch *i_watch;
+       struct audit_parent *parent;
+       int ret = 0;
+
+       /* update watch filter fields */
+       if (ndw) {
+               watch->dev = ndw->dentry->d_inode->i_sb->s_dev;
+               watch->ino = ndw->dentry->d_inode->i_ino;
+       }
+
+       /* The audit_filter_mutex must not be held during inotify calls because
+        * we hold it during inotify event callback processing.  If an existing
+        * inotify watch is found, inotify_find_watch() grabs a reference before
+        * returning.
+        */
+       mutex_unlock(&audit_filter_mutex);
+
+       if (inotify_find_watch(audit_ih, ndp->dentry->d_inode, &i_watch) < 0) {
+               parent = audit_init_parent(ndp);
+               if (IS_ERR(parent)) {
+                       /* caller expects mutex locked */
+                       mutex_lock(&audit_filter_mutex);
+                       return PTR_ERR(parent);
+               }
+       } else
+               parent = container_of(i_watch, struct audit_parent, wdata);
+
+       mutex_lock(&audit_filter_mutex);
+
+       /* parent was moved before we took audit_filter_mutex */
+       if (parent->flags & AUDIT_PARENT_INVALID)
+               ret = -ENOENT;
+       else
+               audit_add_to_parent(krule, parent);
+
+       /* match get in audit_init_parent or inotify_find_watch */
+       put_inotify_watch(&parent->wdata);
+       return ret;
+}
+
+/* Add rule to given filterlist if not a duplicate. */
 static inline int audit_add_rule(struct audit_entry *entry,
-                                 struct list_head *list)
+                                struct list_head *list)
 {
        struct audit_entry *e;
+       struct audit_field *inode_f = entry->rule.inode_f;
+       struct audit_watch *watch = entry->rule.watch;
+       struct nameidata *ndp, *ndw;
+       int h, err, putnd_needed = 0;
+
+       if (inode_f) {
+               h = audit_hash_ino(inode_f->val);
+               list = &audit_inode_hash[h];
+       }
 
-       /* Do not use the _rcu iterator here, since this is the only
-        * addition routine. */
-       list_for_each_entry(e, list, list) {
-               if (!audit_compare_rule(&entry->rule, &e->rule))
-                       return -EEXIST;
+       mutex_lock(&audit_filter_mutex);
+       e = audit_find_rule(entry, list);
+       mutex_unlock(&audit_filter_mutex);
+       if (e) {
+               err = -EEXIST;
+               goto error;
+       }
+
+       /* Avoid calling path_lookup under audit_filter_mutex. */
+       if (watch) {
+               err = audit_get_nd(watch->path, &ndp, &ndw);
+               if (err)
+                       goto error;
+               putnd_needed = 1;
+       }
+
+       mutex_lock(&audit_filter_mutex);
+       if (watch) {
+               /* audit_filter_mutex is dropped and re-taken during this call */
+               err = audit_add_watch(&entry->rule, ndp, ndw);
+               if (err) {
+                       mutex_unlock(&audit_filter_mutex);
+                       goto error;
+               }
+               h = audit_hash_ino((u32)watch->ino);
+               list = &audit_inode_hash[h];
        }
 
        if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
                list_add_rcu(&entry->list, list);
+               entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
        } else {
                list_add_tail_rcu(&entry->list, list);
        }
+       mutex_unlock(&audit_filter_mutex);
 
-       return 0;
+       if (putnd_needed)
+               audit_put_nd(ndp, ndw);
+
+       return 0;
+
+error:
+       if (putnd_needed)
+               audit_put_nd(ndp, ndw);
+       if (watch)
+               audit_put_watch(watch); /* tmp watch, matches initial get */
+       return err;
 }
 
-/* Remove an existing rule from filterlist.  Protected by
- * audit_netlink_mutex. */
+/* Remove an existing rule from filterlist. */
 static inline int audit_del_rule(struct audit_entry *entry,
                                 struct list_head *list)
 {
        struct audit_entry  *e;
+       struct audit_field *inode_f = entry->rule.inode_f;
+       struct audit_watch *watch, *tmp_watch = entry->rule.watch;
+       LIST_HEAD(inotify_list);
+       int h, ret = 0;
+
+       if (inode_f) {
+               h = audit_hash_ino(inode_f->val);
+               list = &audit_inode_hash[h];
+       }
 
-       /* Do not use the _rcu iterator here, since this is the only
-        * deletion routine. */
-       list_for_each_entry(e, list, list) {
-               if (!audit_compare_rule(&entry->rule, &e->rule)) {
-                       list_del_rcu(&e->list);
-                       call_rcu(&e->rcu, audit_free_rule_rcu);
-                       return 0;
+       mutex_lock(&audit_filter_mutex);
+       e = audit_find_rule(entry, list);
+       if (!e) {
+               mutex_unlock(&audit_filter_mutex);
+               ret = -ENOENT;
+               goto out;
+       }
+
+       watch = e->rule.watch;
+       if (watch) {
+               struct audit_parent *parent = watch->parent;
+
+               list_del(&e->rule.rlist);
+
+               if (list_empty(&watch->rules)) {
+                       audit_remove_watch(watch);
+
+                       if (list_empty(&parent->watches)) {
+                               /* Put parent on the inotify un-registration
+                                * list.  Grab a reference before releasing
+                                * audit_filter_mutex, to be released in
+                                * audit_inotify_unregister(). */
+                               list_add(&parent->ilist, &inotify_list);
+                               get_inotify_watch(&parent->wdata);
+                       }
                }
        }
-       return -ENOENT;         /* No matching rule */
+
+       list_del_rcu(&e->list);
+       call_rcu(&e->rcu, audit_free_rule_rcu);
+
+       mutex_unlock(&audit_filter_mutex);
+
+       if (!list_empty(&inotify_list))
+               audit_inotify_unregister(&inotify_list);
+
+out:
+       if (tmp_watch)
+               audit_put_watch(tmp_watch); /* match initial get */
+
+       return ret;
 }
 
 /* List rules using struct audit_rule.  Exists for backward
  * compatibility with userspace. */
-static int audit_list(void *_dest)
+static void audit_list(int pid, int seq, struct sk_buff_head *q)
 {
-       int pid, seq;
-       int *dest = _dest;
+       struct sk_buff *skb;
        struct audit_entry *entry;
        int i;
 
-       pid = dest[0];
-       seq = dest[1];
-       kfree(dest);
-
-       mutex_lock(&audit_netlink_mutex);
-
-       /* The *_rcu iterators not needed here because we are
-          always called with audit_netlink_mutex held. */
+       /* This is a blocking read, so use audit_filter_mutex instead of rcu
+        * iterator to sync with list writers. */
        for (i=0; i<AUDIT_NR_FILTERS; i++) {
                list_for_each_entry(entry, &audit_filter_list[i], list) {
                        struct audit_rule *rule;
@@ -532,33 +1177,41 @@ static int audit_list(void *_dest)
                        rule = audit_krule_to_rule(&entry->rule);
                        if (unlikely(!rule))
                                break;
-                       audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
+                       skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
                                         rule, sizeof(*rule));
+                       if (skb)
+                               skb_queue_tail(q, skb);
                        kfree(rule);
                }
        }
-       audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
-       
-       mutex_unlock(&audit_netlink_mutex);
-       return 0;
+       for (i = 0; i < AUDIT_INODE_BUCKETS; i++) {
+               list_for_each_entry(entry, &audit_inode_hash[i], list) {
+                       struct audit_rule *rule;
+
+                       rule = audit_krule_to_rule(&entry->rule);
+                       if (unlikely(!rule))
+                               break;
+                       skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
+                                        rule, sizeof(*rule));
+                       if (skb)
+                               skb_queue_tail(q, skb);
+                       kfree(rule);
+               }
+       }
+       skb = audit_make_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
+       if (skb)
+               skb_queue_tail(q, skb);
 }
 
 /* List rules using struct audit_rule_data. */
-static int audit_list_rules(void *_dest)
+static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
 {
-       int pid, seq;
-       int *dest = _dest;
+       struct sk_buff *skb;
        struct audit_entry *e;
        int i;
 
-       pid = dest[0];
-       seq = dest[1];
-       kfree(dest);
-
-       mutex_lock(&audit_netlink_mutex);
-
-       /* The *_rcu iterators not needed here because we are
-          always called with audit_netlink_mutex held. */
+       /* This is a blocking read, so use audit_filter_mutex instead of rcu
+        * iterator to sync with list writers. */
        for (i=0; i<AUDIT_NR_FILTERS; i++) {
                list_for_each_entry(e, &audit_filter_list[i], list) {
                        struct audit_rule_data *data;
@@ -566,15 +1219,30 @@ static int audit_list_rules(void *_dest)
                        data = audit_krule_to_data(&e->rule);
                        if (unlikely(!data))
                                break;
-                       audit_send_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
-                                        data, sizeof(*data));
+                       skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
+                                        data, sizeof(*data) + data->buflen);
+                       if (skb)
+                               skb_queue_tail(q, skb);
                        kfree(data);
                }
        }
-       audit_send_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
+       for (i=0; i< AUDIT_INODE_BUCKETS; i++) {
+               list_for_each_entry(e, &audit_inode_hash[i], list) {
+                       struct audit_rule_data *data;
 
-       mutex_unlock(&audit_netlink_mutex);
-       return 0;
+                       data = audit_krule_to_data(&e->rule);
+                       if (unlikely(!data))
+                               break;
+                       skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
+                                        data, sizeof(*data) + data->buflen);
+                       if (skb)
+                               skb_queue_tail(q, skb);
+                       kfree(data);
+               }
+       }
+       skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
+       if (skb)
+               skb_queue_tail(q, skb);
 }
 
 /**
@@ -592,7 +1260,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
                         size_t datasz, uid_t loginuid, u32 sid)
 {
        struct task_struct *tsk;
-       int *dest;
+       struct audit_netlink_list *dest;
        int err = 0;
        struct audit_entry *entry;
 
@@ -605,18 +1273,22 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
                 * happen if we're actually running in the context of auditctl
                 * trying to _send_ the stuff */
                 
-               dest = kmalloc(2 * sizeof(int), GFP_KERNEL);
+               dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL);
                if (!dest)
                        return -ENOMEM;
-               dest[0] = pid;
-               dest[1] = seq;
+               dest->pid = pid;
+               skb_queue_head_init(&dest->q);
 
+               mutex_lock(&audit_filter_mutex);
                if (type == AUDIT_LIST)
-                       tsk = kthread_run(audit_list, dest, "audit_list");
+                       audit_list(pid, seq, &dest->q);
                else
-                       tsk = kthread_run(audit_list_rules, dest,
-                                         "audit_list_rules");
+                       audit_list_rules(pid, seq, &dest->q);
+               mutex_unlock(&audit_filter_mutex);
+
+               tsk = kthread_run(audit_send_list, dest, "audit_send_list");
                if (IS_ERR(tsk)) {
+                       skb_queue_purge(&dest->q);
                        kfree(dest);
                        err = PTR_ERR(tsk);
                }
@@ -632,6 +1304,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
 
                err = audit_add_rule(entry,
                                     &audit_filter_list[entry->rule.listnr]);
+
                if (sid) {
                        char *ctx = NULL;
                        u32 len;
@@ -712,7 +1385,43 @@ int audit_comparator(const u32 left, const u32 op, const u32 right)
        return 0;
 }
 
+/* Compare given dentry name with last component in given path,
+ * return of 0 indicates a match. */
+int audit_compare_dname_path(const char *dname, const char *path,
+                            int *dirlen)
+{
+       int dlen, plen;
+       const char *p;
 
+       if (!dname || !path)
+               return 1;
+
+       dlen = strlen(dname);
+       plen = strlen(path);
+       if (plen < dlen)
+               return 1;
+
+       /* disregard trailing slashes */
+       p = path + plen - 1;
+       while ((*p == '/') && (p > path))
+               p--;
+
+       /* find last path component */
+       p = p - dlen + 1;
+       if (p < path)
+               return 1;
+       else if (p > path) {
+               if (*--p != '/')
+                       return 1;
+               else
+                       p++;
+       }
+
+       /* return length of path's directory component */
+       if (dirlen)
+               *dirlen = p - path;
+       return strncmp(p, dname, dlen);
+}
 
 static int audit_filter_user_rules(struct netlink_skb_parms *cb,
                                   struct audit_krule *rule,
@@ -744,7 +1453,6 @@ static int audit_filter_user_rules(struct netlink_skb_parms *cb,
        }
        switch (rule->action) {
        case AUDIT_NEVER:    *state = AUDIT_DISABLED;       break;
-       case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT;  break;
        case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
        }
        return 1;
@@ -826,32 +1534,65 @@ static inline int audit_rule_has_selinux(struct audit_krule *rule)
 int selinux_audit_rule_update(void)
 {
        struct audit_entry *entry, *n, *nentry;
+       struct audit_watch *watch;
        int i, err = 0;
 
-       /* audit_netlink_mutex synchronizes the writers */
-       mutex_lock(&audit_netlink_mutex);
+       /* audit_filter_mutex synchronizes the writers */
+       mutex_lock(&audit_filter_mutex);
 
        for (i = 0; i < AUDIT_NR_FILTERS; i++) {
                list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
                        if (!audit_rule_has_selinux(&entry->rule))
                                continue;
 
-                       nentry = audit_dupe_rule(&entry->rule);
+                       watch = entry->rule.watch;
+                       nentry = audit_dupe_rule(&entry->rule, watch);
                        if (unlikely(IS_ERR(nentry))) {
                                /* save the first error encountered for the
                                 * return value */
                                if (!err)
                                        err = PTR_ERR(nentry);
                                audit_panic("error updating selinux filters");
+                               if (watch)
+                                       list_del(&entry->rule.rlist);
                                list_del_rcu(&entry->list);
                        } else {
+                               if (watch) {
+                                       list_add(&nentry->rule.rlist,
+                                                &watch->rules);
+                                       list_del(&entry->rule.rlist);
+                               }
                                list_replace_rcu(&entry->list, &nentry->list);
                        }
                        call_rcu(&entry->rcu, audit_free_rule_rcu);
                }
        }
 
-       mutex_unlock(&audit_netlink_mutex);
+       mutex_unlock(&audit_filter_mutex);
 
        return err;
 }
+
+/* Update watch data in audit rules based on inotify events. */
+void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask,
+                        u32 cookie, const char *dname, struct inode *inode)
+{
+       struct audit_parent *parent;
+
+       parent = container_of(i_watch, struct audit_parent, wdata);
+
+       if (mask & (IN_CREATE|IN_MOVED_TO) && inode)
+               audit_update_watch(parent, dname, inode->i_sb->s_dev,
+                                  inode->i_ino, 0);
+       else if (mask & (IN_DELETE|IN_MOVED_FROM))
+               audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1);
+       /* inotify automatically removes the watch and sends IN_IGNORED */
+       else if (mask & (IN_DELETE_SELF|IN_UNMOUNT))
+               audit_remove_parent_watches(parent);
+       /* inotify does not remove the watch, so remove it manually */
+       else if(mask & IN_MOVE_SELF) {
+               audit_remove_parent_watches(parent);
+               inotify_remove_watch_locked(audit_ih, i_watch);
+       } else if (mask & IN_IGNORED)
+               put_inotify_watch(i_watch);
+}
index 1c03a4ed1b27fb8b6f4276b3305ed10907f8f4c3..b097ccb4eb7ea8e10145a29b6f2e1fc14120e0d5 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
  * Copyright 2005 Hewlett-Packard Development Company, L.P.
- * Copyright (C) 2005 IBM Corporation
+ * Copyright (C) 2005, 2006 IBM Corporation
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -29,6 +29,9 @@
  * this file -- see entry.S) is based on a GPL'd patch written by
  * okir@suse.de and Copyright 2003 SuSE Linux AG.
  *
+ * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>,
+ * 2006.
+ *
  * The support of additional filter rules compares (>, <, >=, <=) was
  * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
  *
@@ -49,6 +52,7 @@
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/socket.h>
+#include <linux/mqueue.h>
 #include <linux/audit.h>
 #include <linux/personality.h>
 #include <linux/time.h>
@@ -59,6 +63,8 @@
 #include <linux/list.h>
 #include <linux/tty.h>
 #include <linux/selinux.h>
+#include <linux/binfmts.h>
+#include <linux/syscalls.h>
 
 #include "audit.h"
 
@@ -76,6 +82,9 @@ extern int audit_enabled;
  * path_lookup. */
 #define AUDIT_NAMES_RESERVED 7
 
+/* Indicates that audit should log the full pathname. */
+#define AUDIT_NAME_FULL -1
+
 /* When fs/namei.c:getname() is called, we store the pointer in name and
  * we don't let putname() free it (instead we free all of the saved
  * pointers at syscall exit time).
@@ -83,8 +92,9 @@ extern int audit_enabled;
  * Further, in fs/namei.c:path_lookup() we store the inode and device. */
 struct audit_names {
        const char      *name;
+       int             name_len;       /* number of name's characters to log */
+       unsigned        name_put;       /* call __putname() for this name */
        unsigned long   ino;
-       unsigned long   pino;
        dev_t           dev;
        umode_t         mode;
        uid_t           uid;
@@ -100,6 +110,33 @@ struct audit_aux_data {
 
 #define AUDIT_AUX_IPCPERM      0
 
+struct audit_aux_data_mq_open {
+       struct audit_aux_data   d;
+       int                     oflag;
+       mode_t                  mode;
+       struct mq_attr          attr;
+};
+
+struct audit_aux_data_mq_sendrecv {
+       struct audit_aux_data   d;
+       mqd_t                   mqdes;
+       size_t                  msg_len;
+       unsigned int            msg_prio;
+       struct timespec         abs_timeout;
+};
+
+struct audit_aux_data_mq_notify {
+       struct audit_aux_data   d;
+       mqd_t                   mqdes;
+       struct sigevent         notification;
+};
+
+struct audit_aux_data_mq_getsetattr {
+       struct audit_aux_data   d;
+       mqd_t                   mqdes;
+       struct mq_attr          mqstat;
+};
+
 struct audit_aux_data_ipcctl {
        struct audit_aux_data   d;
        struct ipc_perm         p;
@@ -110,6 +147,13 @@ struct audit_aux_data_ipcctl {
        u32                     osid;
 };
 
+struct audit_aux_data_execve {
+       struct audit_aux_data   d;
+       int argc;
+       int envc;
+       char mem[0];
+};
+
 struct audit_aux_data_socketcall {
        struct audit_aux_data   d;
        int                     nargs;
@@ -148,7 +192,7 @@ struct audit_context {
        struct audit_aux_data *aux;
 
                                /* Save things to print about task_struct */
-       pid_t               pid;
+       pid_t               pid, ppid;
        uid_t               uid, euid, suid, fsuid;
        gid_t               gid, egid, sgid, fsgid;
        unsigned long       personality;
@@ -160,12 +204,13 @@ struct audit_context {
 #endif
 };
 
-
+/* Determine if any context name data matches a rule's watch data */
 /* Compare a task_struct with an audit_rule.  Return 1 on match, 0
  * otherwise. */
 static int audit_filter_rules(struct task_struct *tsk,
                              struct audit_krule *rule,
                              struct audit_context *ctx,
+                             struct audit_names *name,
                              enum audit_state *state)
 {
        int i, j, need_sid = 1;
@@ -179,6 +224,10 @@ static int audit_filter_rules(struct task_struct *tsk,
                case AUDIT_PID:
                        result = audit_comparator(tsk->pid, f->op, f->val);
                        break;
+               case AUDIT_PPID:
+                       if (ctx)
+                               result = audit_comparator(ctx->ppid, f->op, f->val);
+                       break;
                case AUDIT_UID:
                        result = audit_comparator(tsk->uid, f->op, f->val);
                        break;
@@ -224,7 +273,10 @@ static int audit_filter_rules(struct task_struct *tsk,
                        }
                        break;
                case AUDIT_DEVMAJOR:
-                       if (ctx) {
+                       if (name)
+                               result = audit_comparator(MAJOR(name->dev),
+                                                         f->op, f->val);
+                       else if (ctx) {
                                for (j = 0; j < ctx->name_count; j++) {
                                        if (audit_comparator(MAJOR(ctx->names[j].dev),  f->op, f->val)) {
                                                ++result;
@@ -234,7 +286,10 @@ static int audit_filter_rules(struct task_struct *tsk,
                        }
                        break;
                case AUDIT_DEVMINOR:
-                       if (ctx) {
+                       if (name)
+                               result = audit_comparator(MINOR(name->dev),
+                                                         f->op, f->val);
+                       else if (ctx) {
                                for (j = 0; j < ctx->name_count; j++) {
                                        if (audit_comparator(MINOR(ctx->names[j].dev), f->op, f->val)) {
                                                ++result;
@@ -244,16 +299,22 @@ static int audit_filter_rules(struct task_struct *tsk,
                        }
                        break;
                case AUDIT_INODE:
-                       if (ctx) {
+                       if (name)
+                               result = (name->ino == f->val);
+                       else if (ctx) {
                                for (j = 0; j < ctx->name_count; j++) {
-                                       if (audit_comparator(ctx->names[j].ino, f->op, f->val) ||
-                                           audit_comparator(ctx->names[j].pino, f->op, f->val)) {
+                                       if (audit_comparator(ctx->names[j].ino, f->op, f->val)) {
                                                ++result;
                                                break;
                                        }
                                }
                        }
                        break;
+               case AUDIT_WATCH:
+                       if (name && rule->watch->ino != (unsigned long)-1)
+                               result = (name->dev == rule->watch->dev &&
+                                         name->ino == rule->watch->ino);
+                       break;
                case AUDIT_LOGINUID:
                        result = 0;
                        if (ctx)
@@ -294,7 +355,6 @@ static int audit_filter_rules(struct task_struct *tsk,
        }
        switch (rule->action) {
        case AUDIT_NEVER:    *state = AUDIT_DISABLED;       break;
-       case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT;  break;
        case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
        }
        return 1;
@@ -311,7 +371,7 @@ static enum audit_state audit_filter_task(struct task_struct *tsk)
 
        rcu_read_lock();
        list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
-               if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+               if (audit_filter_rules(tsk, &e->rule, NULL, NULL, &state)) {
                        rcu_read_unlock();
                        return state;
                }
@@ -341,8 +401,47 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
                int bit  = AUDIT_BIT(ctx->major);
 
                list_for_each_entry_rcu(e, list, list) {
-                       if ((e->rule.mask[word] & bit) == bit
-                                       && audit_filter_rules(tsk, &e->rule, ctx, &state)) {
+                       if ((e->rule.mask[word] & bit) == bit &&
+                           audit_filter_rules(tsk, &e->rule, ctx, NULL,
+                                              &state)) {
+                               rcu_read_unlock();
+                               return state;
+                       }
+               }
+       }
+       rcu_read_unlock();
+       return AUDIT_BUILD_CONTEXT;
+}
+
+/* At syscall exit time, this filter is called if any audit_names[] have been
+ * collected during syscall processing.  We only check rules in sublists at hash
+ * buckets applicable to the inode numbers in audit_names[].
+ * Regarding audit_state, same rules apply as for audit_filter_syscall().
+ */
+enum audit_state audit_filter_inodes(struct task_struct *tsk,
+                                    struct audit_context *ctx)
+{
+       int i;
+       struct audit_entry *e;
+       enum audit_state state;
+
+       if (audit_pid && tsk->tgid == audit_pid)
+               return AUDIT_DISABLED;
+
+       rcu_read_lock();
+       for (i = 0; i < ctx->name_count; i++) {
+               int word = AUDIT_WORD(ctx->major);
+               int bit  = AUDIT_BIT(ctx->major);
+               struct audit_names *n = &ctx->names[i];
+               int h = audit_hash_ino((u32)n->ino);
+               struct list_head *list = &audit_inode_hash[h];
+
+               if (list_empty(list))
+                       continue;
+
+               list_for_each_entry_rcu(e, list, list) {
+                       if ((e->rule.mask[word] & bit) == bit &&
+                           audit_filter_rules(tsk, &e->rule, ctx, n, &state)) {
                                rcu_read_unlock();
                                return state;
                        }
@@ -352,6 +451,11 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
        return AUDIT_BUILD_CONTEXT;
 }
 
+void audit_set_auditable(struct audit_context *ctx)
+{
+       ctx->auditable = 1;
+}
+
 static inline struct audit_context *audit_get_context(struct task_struct *tsk,
                                                      int return_valid,
                                                      int return_code)
@@ -365,12 +469,22 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
 
        if (context->in_syscall && !context->auditable) {
                enum audit_state state;
+
                state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
+               if (state == AUDIT_RECORD_CONTEXT) {
+                       context->auditable = 1;
+                       goto get_context;
+               }
+
+               state = audit_filter_inodes(tsk, context);
                if (state == AUDIT_RECORD_CONTEXT)
                        context->auditable = 1;
+
        }
 
+get_context:
        context->pid = tsk->pid;
+       context->ppid = sys_getppid();  /* sic.  tsk == current in all cases */
        context->uid = tsk->uid;
        context->gid = tsk->gid;
        context->euid = tsk->euid;
@@ -413,7 +527,7 @@ static inline void audit_free_names(struct audit_context *context)
 #endif
 
        for (i = 0; i < context->name_count; i++) {
-               if (context->names[i].name)
+               if (context->names[i].name && context->names[i].name_put)
                        __putname(context->names[i].name);
        }
        context->name_count = 0;
@@ -606,7 +720,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                tty = "(none)";
        audit_log_format(ab,
                  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
-                 " pid=%d auid=%u uid=%u gid=%u"
+                 " ppid=%d pid=%d auid=%u uid=%u gid=%u"
                  " euid=%u suid=%u fsuid=%u"
                  " egid=%u sgid=%u fsgid=%u tty=%s",
                  context->argv[0],
@@ -614,6 +728,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                  context->argv[2],
                  context->argv[3],
                  context->name_count,
+                 context->ppid,
                  context->pid,
                  context->loginuid,
                  context->uid,
@@ -630,11 +745,48 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        continue; /* audit_panic has been called */
 
                switch (aux->type) {
+               case AUDIT_MQ_OPEN: {
+                       struct audit_aux_data_mq_open *axi = (void *)aux;
+                       audit_log_format(ab,
+                               "oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld "
+                               "mq_msgsize=%ld mq_curmsgs=%ld",
+                               axi->oflag, axi->mode, axi->attr.mq_flags,
+                               axi->attr.mq_maxmsg, axi->attr.mq_msgsize,
+                               axi->attr.mq_curmsgs);
+                       break; }
+
+               case AUDIT_MQ_SENDRECV: {
+                       struct audit_aux_data_mq_sendrecv *axi = (void *)aux;
+                       audit_log_format(ab,
+                               "mqdes=%d msg_len=%zd msg_prio=%u "
+                               "abs_timeout_sec=%ld abs_timeout_nsec=%ld",
+                               axi->mqdes, axi->msg_len, axi->msg_prio,
+                               axi->abs_timeout.tv_sec, axi->abs_timeout.tv_nsec);
+                       break; }
+
+               case AUDIT_MQ_NOTIFY: {
+                       struct audit_aux_data_mq_notify *axi = (void *)aux;
+                       audit_log_format(ab,
+                               "mqdes=%d sigev_signo=%d",
+                               axi->mqdes,
+                               axi->notification.sigev_signo);
+                       break; }
+
+               case AUDIT_MQ_GETSETATTR: {
+                       struct audit_aux_data_mq_getsetattr *axi = (void *)aux;
+                       audit_log_format(ab,
+                               "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
+                               "mq_curmsgs=%ld ",
+                               axi->mqdes,
+                               axi->mqstat.mq_flags, axi->mqstat.mq_maxmsg,
+                               axi->mqstat.mq_msgsize, axi->mqstat.mq_curmsgs);
+                       break; }
+
                case AUDIT_IPC: {
                        struct audit_aux_data_ipcctl *axi = (void *)aux;
                        audit_log_format(ab, 
-                                " qbytes=%lx iuid=%u igid=%u mode=%x",
-                                axi->qbytes, axi->uid, axi->gid, axi->mode);
+                                "ouid=%u ogid=%u mode=%x",
+                                axi->uid, axi->gid, axi->mode);
                        if (axi->osid != 0) {
                                char *ctx = NULL;
                                u32 len;
@@ -652,19 +804,18 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                case AUDIT_IPC_SET_PERM: {
                        struct audit_aux_data_ipcctl *axi = (void *)aux;
                        audit_log_format(ab,
-                               " new qbytes=%lx new iuid=%u new igid=%u new mode=%x",
+                               "qbytes=%lx ouid=%u ogid=%u mode=%x",
                                axi->qbytes, axi->uid, axi->gid, axi->mode);
-                       if (axi->osid != 0) {
-                               char *ctx = NULL;
-                               u32 len;
-                               if (selinux_ctxid_to_string(
-                                               axi->osid, &ctx, &len)) {
-                                       audit_log_format(ab, " osid=%u",
-                                                       axi->osid);
-                                       call_panic = 1;
-                               } else
-                                       audit_log_format(ab, " obj=%s", ctx);
-                               kfree(ctx);
+                       break; }
+
+               case AUDIT_EXECVE: {
+                       struct audit_aux_data_execve *axi = (void *)aux;
+                       int i;
+                       const char *p;
+                       for (i = 0, p = axi->mem; i < axi->argc; i++) {
+                               audit_log_format(ab, "a%d=", i);
+                               p = audit_log_untrustedstring(ab, p);
+                               audit_log_format(ab, "\n");
                        }
                        break; }
 
@@ -700,8 +851,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                }
        }
        for (i = 0; i < context->name_count; i++) {
-               unsigned long ino  = context->names[i].ino;
-               unsigned long pino = context->names[i].pino;
+               struct audit_names *n = &context->names[i];
 
                ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
                if (!ab)
@@ -709,33 +859,47 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 
                audit_log_format(ab, "item=%d", i);
 
-               audit_log_format(ab, " name=");
-               if (context->names[i].name)
-                       audit_log_untrustedstring(ab, context->names[i].name);
-               else
-                       audit_log_format(ab, "(null)");
-
-               if (pino != (unsigned long)-1)
-                       audit_log_format(ab, " parent=%lu",  pino);
-               if (ino != (unsigned long)-1)
-                       audit_log_format(ab, " inode=%lu",  ino);
-               if ((pino != (unsigned long)-1) || (ino != (unsigned long)-1))
-                       audit_log_format(ab, " dev=%02x:%02x mode=%#o" 
-                                        " ouid=%u ogid=%u rdev=%02x:%02x", 
-                                        MAJOR(context->names[i].dev), 
-                                        MINOR(context->names[i].dev), 
-                                        context->names[i].mode, 
-                                        context->names[i].uid, 
-                                        context->names[i].gid, 
-                                        MAJOR(context->names[i].rdev), 
-                                        MINOR(context->names[i].rdev));
-               if (context->names[i].osid != 0) {
+               if (n->name) {
+                       switch(n->name_len) {
+                       case AUDIT_NAME_FULL:
+                               /* log the full path */
+                               audit_log_format(ab, " name=");
+                               audit_log_untrustedstring(ab, n->name);
+                               break;
+                       case 0:
+                               /* name was specified as a relative path and the
+                                * directory component is the cwd */
+                               audit_log_d_path(ab, " name=", context->pwd,
+                                                context->pwdmnt);
+                               break;
+                       default:
+                               /* log the name's directory component */
+                               audit_log_format(ab, " name=");
+                               audit_log_n_untrustedstring(ab, n->name_len,
+                                                           n->name);
+                       }
+               } else
+                       audit_log_format(ab, " name=(null)");
+
+               if (n->ino != (unsigned long)-1) {
+                       audit_log_format(ab, " inode=%lu"
+                                        " dev=%02x:%02x mode=%#o"
+                                        " ouid=%u ogid=%u rdev=%02x:%02x",
+                                        n->ino,
+                                        MAJOR(n->dev),
+                                        MINOR(n->dev),
+                                        n->mode,
+                                        n->uid,
+                                        n->gid,
+                                        MAJOR(n->rdev),
+                                        MINOR(n->rdev));
+               }
+               if (n->osid != 0) {
                        char *ctx = NULL;
                        u32 len;
                        if (selinux_ctxid_to_string(
-                               context->names[i].osid, &ctx, &len)) {
-                               audit_log_format(ab, " osid=%u",
-                                               context->names[i].osid);
+                               n->osid, &ctx, &len)) {
+                               audit_log_format(ab, " osid=%u", n->osid);
                                call_panic = 2;
                        } else
                                audit_log_format(ab, " obj=%s", ctx);
@@ -908,11 +1072,11 @@ void audit_syscall_exit(int valid, long return_code)
  * Add a name to the list of audit names for this context.
  * Called from fs/namei.c:getname().
  */
-void audit_getname(const char *name)
+void __audit_getname(const char *name)
 {
        struct audit_context *context = current->audit_context;
 
-       if (!context || IS_ERR(name) || !name)
+       if (IS_ERR(name) || !name)
                return;
 
        if (!context->in_syscall) {
@@ -925,6 +1089,8 @@ void audit_getname(const char *name)
        }
        BUG_ON(context->name_count >= AUDIT_NAMES);
        context->names[context->name_count].name = name;
+       context->names[context->name_count].name_len = AUDIT_NAME_FULL;
+       context->names[context->name_count].name_put = 1;
        context->names[context->name_count].ino  = (unsigned long)-1;
        ++context->name_count;
        if (!context->pwd) {
@@ -991,11 +1157,10 @@ static void audit_inode_context(int idx, const struct inode *inode)
  * audit_inode - store the inode and device from a lookup
  * @name: name being audited
  * @inode: inode being audited
- * @flags: lookup flags (as used in path_lookup())
  *
  * Called from fs/namei.c:path_lookup().
  */
-void __audit_inode(const char *name, const struct inode *inode, unsigned flags)
+void __audit_inode(const char *name, const struct inode *inode)
 {
        int idx;
        struct audit_context *context = current->audit_context;
@@ -1021,20 +1186,13 @@ void __audit_inode(const char *name, const struct inode *inode, unsigned flags)
                ++context->ino_count;
 #endif
        }
+       context->names[idx].ino   = inode->i_ino;
        context->names[idx].dev   = inode->i_sb->s_dev;
        context->names[idx].mode  = inode->i_mode;
        context->names[idx].uid   = inode->i_uid;
        context->names[idx].gid   = inode->i_gid;
        context->names[idx].rdev  = inode->i_rdev;
        audit_inode_context(idx, inode);
-       if ((flags & LOOKUP_PARENT) && (strcmp(name, "/") != 0) && 
-           (strcmp(name, ".") != 0)) {
-               context->names[idx].ino   = (unsigned long)-1;
-               context->names[idx].pino  = inode->i_ino;
-       } else {
-               context->names[idx].ino   = inode->i_ino;
-               context->names[idx].pino  = (unsigned long)-1;
-       }
 }
 
 /**
@@ -1056,51 +1214,40 @@ void __audit_inode_child(const char *dname, const struct inode *inode,
 {
        int idx;
        struct audit_context *context = current->audit_context;
+       const char *found_name = NULL;
+       int dirlen = 0;
 
        if (!context->in_syscall)
                return;
 
        /* determine matching parent */
-       if (dname)
-               for (idx = 0; idx < context->name_count; idx++)
-                       if (context->names[idx].pino == pino) {
-                               const char *n;
-                               const char *name = context->names[idx].name;
-                               int dlen = strlen(dname);
-                               int nlen = name ? strlen(name) : 0;
-
-                               if (nlen < dlen)
-                                       continue;
-                               
-                               /* disregard trailing slashes */
-                               n = name + nlen - 1;
-                               while ((*n == '/') && (n > name))
-                                       n--;
-
-                               /* find last path component */
-                               n = n - dlen + 1;
-                               if (n < name)
-                                       continue;
-                               else if (n > name) {
-                                       if (*--n != '/')
-                                               continue;
-                                       else
-                                               n++;
-                               }
-
-                               if (strncmp(n, dname, dlen) == 0)
-                                       goto update_context;
+       if (!dname)
+               goto update_context;
+       for (idx = 0; idx < context->name_count; idx++)
+               if (context->names[idx].ino == pino) {
+                       const char *name = context->names[idx].name;
+
+                       if (!name)
+                               continue;
+
+                       if (audit_compare_dname_path(dname, name, &dirlen) == 0) {
+                               context->names[idx].name_len = dirlen;
+                               found_name = name;
+                               break;
                        }
+               }
 
-       /* catch-all in case match not found */
+update_context:
        idx = context->name_count++;
-       context->names[idx].name  = NULL;
-       context->names[idx].pino  = pino;
 #if AUDIT_DEBUG
        context->ino_count++;
 #endif
+       /* Re-use the name belonging to the slot for a matching parent directory.
+        * All names for this context are relinquished in audit_free_names() */
+       context->names[idx].name = found_name;
+       context->names[idx].name_len = AUDIT_NAME_FULL;
+       context->names[idx].name_put = 0;       /* don't call __putname() */
 
-update_context:
        if (inode) {
                context->names[idx].ino   = inode->i_ino;
                context->names[idx].dev   = inode->i_sb->s_dev;
@@ -1109,7 +1256,8 @@ update_context:
                context->names[idx].gid   = inode->i_gid;
                context->names[idx].rdev  = inode->i_rdev;
                audit_inode_context(idx, inode);
-       }
+       } else
+               context->names[idx].ino   = (unsigned long)-1;
 }
 
 /**
@@ -1142,18 +1290,23 @@ void auditsc_get_stamp(struct audit_context *ctx,
  */
 int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 {
-       if (task->audit_context) {
-               struct audit_buffer *ab;
-
-               ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
-               if (ab) {
-                       audit_log_format(ab, "login pid=%d uid=%u "
-                               "old auid=%u new auid=%u",
-                               task->pid, task->uid, 
-                               task->audit_context->loginuid, loginuid);
-                       audit_log_end(ab);
+       struct audit_context *context = task->audit_context;
+
+       if (context) {
+               /* Only log if audit is enabled */
+               if (context->in_syscall) {
+                       struct audit_buffer *ab;
+
+                       ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
+                       if (ab) {
+                               audit_log_format(ab, "login pid=%d uid=%u "
+                                       "old auid=%u new auid=%u",
+                                       task->pid, task->uid,
+                                       context->loginuid, loginuid);
+                               audit_log_end(ab);
+                       }
                }
-               task->audit_context->loginuid = loginuid;
+               context->loginuid = loginuid;
        }
        return 0;
 }
@@ -1170,19 +1323,220 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
 }
 
 /**
- * audit_ipc_obj - record audit data for ipc object
- * @ipcp: ipc permissions
+ * __audit_mq_open - record audit data for a POSIX MQ open
+ * @oflag: open flag
+ * @mode: mode bits
+ * @u_attr: queue attributes
  *
  * Returns 0 for success or NULL context or < 0 on error.
  */
-int audit_ipc_obj(struct kern_ipc_perm *ipcp)
+int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
 {
-       struct audit_aux_data_ipcctl *ax;
+       struct audit_aux_data_mq_open *ax;
+       struct audit_context *context = current->audit_context;
+
+       if (!audit_enabled)
+               return 0;
+
+       if (likely(!context))
+               return 0;
+
+       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+       if (!ax)
+               return -ENOMEM;
+
+       if (u_attr != NULL) {
+               if (copy_from_user(&ax->attr, u_attr, sizeof(ax->attr))) {
+                       kfree(ax);
+                       return -EFAULT;
+               }
+       } else
+               memset(&ax->attr, 0, sizeof(ax->attr));
+
+       ax->oflag = oflag;
+       ax->mode = mode;
+
+       ax->d.type = AUDIT_MQ_OPEN;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
+/**
+ * __audit_mq_timedsend - record audit data for a POSIX MQ timed send
+ * @mqdes: MQ descriptor
+ * @msg_len: Message length
+ * @msg_prio: Message priority
+ * @abs_timeout: Message timeout in absolute time
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
+                       const struct timespec __user *u_abs_timeout)
+{
+       struct audit_aux_data_mq_sendrecv *ax;
+       struct audit_context *context = current->audit_context;
+
+       if (!audit_enabled)
+               return 0;
+
+       if (likely(!context))
+               return 0;
+
+       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+       if (!ax)
+               return -ENOMEM;
+
+       if (u_abs_timeout != NULL) {
+               if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
+                       kfree(ax);
+                       return -EFAULT;
+               }
+       } else
+               memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
+
+       ax->mqdes = mqdes;
+       ax->msg_len = msg_len;
+       ax->msg_prio = msg_prio;
+
+       ax->d.type = AUDIT_MQ_SENDRECV;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
+/**
+ * __audit_mq_timedreceive - record audit data for a POSIX MQ timed receive
+ * @mqdes: MQ descriptor
+ * @msg_len: Message length
+ * @msg_prio: Message priority
+ * @abs_timeout: Message timeout in absolute time
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len,
+                               unsigned int __user *u_msg_prio,
+                               const struct timespec __user *u_abs_timeout)
+{
+       struct audit_aux_data_mq_sendrecv *ax;
+       struct audit_context *context = current->audit_context;
+
+       if (!audit_enabled)
+               return 0;
+
+       if (likely(!context))
+               return 0;
+
+       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+       if (!ax)
+               return -ENOMEM;
+
+       if (u_msg_prio != NULL) {
+               if (get_user(ax->msg_prio, u_msg_prio)) {
+                       kfree(ax);
+                       return -EFAULT;
+               }
+       } else
+               ax->msg_prio = 0;
+
+       if (u_abs_timeout != NULL) {
+               if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
+                       kfree(ax);
+                       return -EFAULT;
+               }
+       } else
+               memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
+
+       ax->mqdes = mqdes;
+       ax->msg_len = msg_len;
+
+       ax->d.type = AUDIT_MQ_SENDRECV;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
+/**
+ * __audit_mq_notify - record audit data for a POSIX MQ notify
+ * @mqdes: MQ descriptor
+ * @u_notification: Notification event
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+
+int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
+{
+       struct audit_aux_data_mq_notify *ax;
+       struct audit_context *context = current->audit_context;
+
+       if (!audit_enabled)
+               return 0;
+
+       if (likely(!context))
+               return 0;
+
+       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+       if (!ax)
+               return -ENOMEM;
+
+       if (u_notification != NULL) {
+               if (copy_from_user(&ax->notification, u_notification, sizeof(ax->notification))) {
+                       kfree(ax);
+                       return -EFAULT;
+               }
+       } else
+               memset(&ax->notification, 0, sizeof(ax->notification));
+
+       ax->mqdes = mqdes;
+
+       ax->d.type = AUDIT_MQ_NOTIFY;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
+/**
+ * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute
+ * @mqdes: MQ descriptor
+ * @mqstat: MQ flags
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
+{
+       struct audit_aux_data_mq_getsetattr *ax;
        struct audit_context *context = current->audit_context;
 
+       if (!audit_enabled)
+               return 0;
+
        if (likely(!context))
                return 0;
 
+       ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+       if (!ax)
+               return -ENOMEM;
+
+       ax->mqdes = mqdes;
+       ax->mqstat = *mqstat;
+
+       ax->d.type = AUDIT_MQ_GETSETATTR;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
+/**
+ * audit_ipc_obj - record audit data for ipc object
+ * @ipcp: ipc permissions
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
+{
+       struct audit_aux_data_ipcctl *ax;
+       struct audit_context *context = current->audit_context;
+
        ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
        if (!ax)
                return -ENOMEM;
@@ -1207,14 +1561,11 @@ int audit_ipc_obj(struct kern_ipc_perm *ipcp)
  *
  * Returns 0 for success or NULL context or < 0 on error.
  */
-int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp)
+int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
 {
        struct audit_aux_data_ipcctl *ax;
        struct audit_context *context = current->audit_context;
 
-       if (likely(!context))
-               return 0;
-
        ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
        if (!ax)
                return -ENOMEM;
@@ -1223,7 +1574,6 @@ int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode,
        ax->uid = uid;
        ax->gid = gid;
        ax->mode = mode;
-       selinux_get_ipc_sid(ipcp, &ax->osid);
 
        ax->d.type = AUDIT_IPC_SET_PERM;
        ax->d.next = context->aux;
@@ -1231,6 +1581,39 @@ int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode,
        return 0;
 }
 
+int audit_bprm(struct linux_binprm *bprm)
+{
+       struct audit_aux_data_execve *ax;
+       struct audit_context *context = current->audit_context;
+       unsigned long p, next;
+       void *to;
+
+       if (likely(!audit_enabled || !context))
+               return 0;
+
+       ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p,
+                               GFP_KERNEL);
+       if (!ax)
+               return -ENOMEM;
+
+       ax->argc = bprm->argc;
+       ax->envc = bprm->envc;
+       for (p = bprm->p, to = ax->mem; p < MAX_ARG_PAGES*PAGE_SIZE; p = next) {
+               struct page *page = bprm->page[p / PAGE_SIZE];
+               void *kaddr = kmap(page);
+               next = (p + PAGE_SIZE) & ~(PAGE_SIZE - 1);
+               memcpy(to, kaddr + (p & (PAGE_SIZE - 1)), next - p);
+               to += next - p;
+               kunmap(page);
+       }
+
+       ax->d.type = AUDIT_EXECVE;
+       ax->d.next = context->aux;
+       context->aux = (void *)ax;
+       return 0;
+}
+
+
 /**
  * audit_socketcall - record audit data for sys_socketcall
  * @nargs: number of args
@@ -1325,19 +1708,20 @@ int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt)
  * If the audit subsystem is being terminated, record the task (pid)
  * and uid that is doing that.
  */
-void audit_signal_info(int sig, struct task_struct *t)
+void __audit_signal_info(int sig, struct task_struct *t)
 {
        extern pid_t audit_sig_pid;
        extern uid_t audit_sig_uid;
-
-       if (unlikely(audit_pid && t->tgid == audit_pid)) {
-               if (sig == SIGTERM || sig == SIGHUP) {
-                       struct audit_context *ctx = current->audit_context;
-                       audit_sig_pid = current->pid;
-                       if (ctx)
-                               audit_sig_uid = ctx->loginuid;
-                       else
-                               audit_sig_uid = current->uid;
-               }
+       extern u32 audit_sig_sid;
+
+       if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
+               struct task_struct *tsk = current;
+               struct audit_context *ctx = tsk->audit_context;
+               audit_sig_pid = tsk->pid;
+               if (ctx)
+                       audit_sig_uid = ctx->loginuid;
+               else
+                       audit_sig_uid = tsk->uid;
+               selinux_get_task_sid(tsk, &audit_sig_sid);
        }
 }
index e95b932822109e6bd517eee9a67876fedc91b426..e06d0c10a24e2f4e054d17c21d032beadf8d1ba6 100644 (file)
@@ -881,14 +881,6 @@ fastcall NORET_TYPE void do_exit(long code)
 
        tsk->flags |= PF_EXITING;
 
-       /*
-        * Make sure we don't try to process any timer firings
-        * while we are already exiting.
-        */
-       tsk->it_virt_expires = cputime_zero;
-       tsk->it_prof_expires = cputime_zero;
-       tsk->it_sched_expires = 0;
-
        if (unlikely(in_atomic()))
                printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
                                current->comm, current->pid,
index b7f0388bd71c80d32eb29f79b0c0319705a8bd7c..18324305724a0b5b6753c1e4dec2219d3e15e9fc 100644 (file)
@@ -393,7 +393,7 @@ static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
        if (base->first == &timer->node)
                base->first = rb_next(&timer->node);
        rb_erase(&timer->node, &base->active);
-       timer->node.rb_parent = HRTIMER_INACTIVE;
+       rb_set_parent(&timer->node, &timer->node);
 }
 
 /*
@@ -456,6 +456,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(hrtimer_start);
 
 /**
  * hrtimer_try_to_cancel - try to deactivate a timer
@@ -484,6 +485,7 @@ int hrtimer_try_to_cancel(struct hrtimer *timer)
        return ret;
 
 }
+EXPORT_SYMBOL_GPL(hrtimer_try_to_cancel);
 
 /**
  * hrtimer_cancel - cancel a timer and wait for the handler to finish.
@@ -504,6 +506,7 @@ int hrtimer_cancel(struct hrtimer *timer)
                cpu_relax();
        }
 }
+EXPORT_SYMBOL_GPL(hrtimer_cancel);
 
 /**
  * hrtimer_get_remaining - get remaining time for the timer
@@ -522,6 +525,7 @@ ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
 
        return rem;
 }
+EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
 
 #ifdef CONFIG_NO_IDLE_HZ
 /**
@@ -578,8 +582,9 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
                clock_id = CLOCK_MONOTONIC;
 
        timer->base = &bases[clock_id];
-       timer->node.rb_parent = HRTIMER_INACTIVE;
+       rb_set_parent(&timer->node, &timer->node);
 }
+EXPORT_SYMBOL_GPL(hrtimer_init);
 
 /**
  * hrtimer_get_res - get the timer resolution for a clock
@@ -599,6 +604,7 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(hrtimer_get_res);
 
 /*
  * Expire the per base hrtimer-queue:
diff --git a/kernel/intermodule.c b/kernel/intermodule.c
deleted file mode 100644 (file)
index 55b1e5b..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Deprecated, do not use.  Moved from module.c to here. --RR */
-
-/* Written by Keith Owens <kaos@ocs.com.au> Oct 2000 */
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-
-/* inter_module functions are always available, even when the kernel is
- * compiled without modules.  Consumers of inter_module_xxx routines
- * will always work, even when both are built into the kernel, this
- * approach removes lots of #ifdefs in mainline code.
- */
-
-static struct list_head ime_list = LIST_HEAD_INIT(ime_list);
-static DEFINE_SPINLOCK(ime_lock);
-static int kmalloc_failed;
-
-struct inter_module_entry {
-       struct list_head list;
-       const char *im_name;
-       struct module *owner;
-       const void *userdata;
-};
-
-/**
- * inter_module_register - register a new set of inter module data.
- * @im_name: an arbitrary string to identify the data, must be unique
- * @owner: module that is registering the data, always use THIS_MODULE
- * @userdata: pointer to arbitrary userdata to be registered
- *
- * Description: Check that the im_name has not already been registered,
- * complain if it has.  For new data, add it to the inter_module_entry
- * list.
- */
-void inter_module_register(const char *im_name, struct module *owner, const void *userdata)
-{
-       struct list_head *tmp;
-       struct inter_module_entry *ime, *ime_new;
-
-       if (!(ime_new = kzalloc(sizeof(*ime), GFP_KERNEL))) {
-               /* Overloaded kernel, not fatal */
-               printk(KERN_ERR
-                       "Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",
-                       im_name);
-               kmalloc_failed = 1;
-               return;
-       }
-       ime_new->im_name = im_name;
-       ime_new->owner = owner;
-       ime_new->userdata = userdata;
-
-       spin_lock(&ime_lock);
-       list_for_each(tmp, &ime_list) {
-               ime = list_entry(tmp, struct inter_module_entry, list);
-               if (strcmp(ime->im_name, im_name) == 0) {
-                       spin_unlock(&ime_lock);
-                       kfree(ime_new);
-                       /* Program logic error, fatal */
-                       printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name);
-                       BUG();
-               }
-       }
-       list_add(&(ime_new->list), &ime_list);
-       spin_unlock(&ime_lock);
-}
-
-/**
- * inter_module_unregister - unregister a set of inter module data.
- * @im_name: an arbitrary string to identify the data, must be unique
- *
- * Description: Check that the im_name has been registered, complain if
- * it has not.  For existing data, remove it from the
- * inter_module_entry list.
- */
-void inter_module_unregister(const char *im_name)
-{
-       struct list_head *tmp;
-       struct inter_module_entry *ime;
-
-       spin_lock(&ime_lock);
-       list_for_each(tmp, &ime_list) {
-               ime = list_entry(tmp, struct inter_module_entry, list);
-               if (strcmp(ime->im_name, im_name) == 0) {
-                       list_del(&(ime->list));
-                       spin_unlock(&ime_lock);
-                       kfree(ime);
-                       return;
-               }
-       }
-       spin_unlock(&ime_lock);
-       if (kmalloc_failed) {
-               printk(KERN_ERR
-                       "inter_module_unregister: no entry for '%s', "
-                       "probably caused by previous kmalloc failure\n",
-                       im_name);
-               return;
-       }
-       else {
-               /* Program logic error, fatal */
-               printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name);
-               BUG();
-       }
-}
-
-/**
- * inter_module_get - return arbitrary userdata from another module.
- * @im_name: an arbitrary string to identify the data, must be unique
- *
- * Description: If the im_name has not been registered, return NULL.
- * Try to increment the use count on the owning module, if that fails
- * then return NULL.  Otherwise return the userdata.
- */
-static const void *inter_module_get(const char *im_name)
-{
-       struct list_head *tmp;
-       struct inter_module_entry *ime;
-       const void *result = NULL;
-
-       spin_lock(&ime_lock);
-       list_for_each(tmp, &ime_list) {
-               ime = list_entry(tmp, struct inter_module_entry, list);
-               if (strcmp(ime->im_name, im_name) == 0) {
-                       if (try_module_get(ime->owner))
-                               result = ime->userdata;
-                       break;
-               }
-       }
-       spin_unlock(&ime_lock);
-       return(result);
-}
-
-/**
- * inter_module_get_request - im get with automatic request_module.
- * @im_name: an arbitrary string to identify the data, must be unique
- * @modname: module that is expected to register im_name
- *
- * Description: If inter_module_get fails, do request_module then retry.
- */
-const void *inter_module_get_request(const char *im_name, const char *modname)
-{
-       const void *result = inter_module_get(im_name);
-       if (!result) {
-               request_module("%s", modname);
-               result = inter_module_get(im_name);
-       }
-       return(result);
-}
-
-/**
- * inter_module_put - release use of data from another module.
- * @im_name: an arbitrary string to identify the data, must be unique
- *
- * Description: If the im_name has not been registered, complain,
- * otherwise decrement the use count on the owning module.
- */
-void inter_module_put(const char *im_name)
-{
-       struct list_head *tmp;
-       struct inter_module_entry *ime;
-
-       spin_lock(&ime_lock);
-       list_for_each(tmp, &ime_list) {
-               ime = list_entry(tmp, struct inter_module_entry, list);
-               if (strcmp(ime->im_name, im_name) == 0) {
-                       if (ime->owner)
-                               module_put(ime->owner);
-                       spin_unlock(&ime_lock);
-                       return;
-               }
-       }
-       spin_unlock(&ime_lock);
-       printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name);
-       BUG();
-}
-
-EXPORT_SYMBOL(inter_module_register);
-EXPORT_SYMBOL(inter_module_unregister);
-EXPORT_SYMBOL(inter_module_get_request);
-EXPORT_SYMBOL(inter_module_put);
-
-MODULE_LICENSE("GPL");
-
index 520f6c59948d24c55721c2a2299defe964efaadf..d38d9ec3276c3069c1259744496e9d2a05fef117 100644 (file)
@@ -555,9 +555,6 @@ static void arm_timer(struct k_itimer *timer, union cpu_time_count now)
        struct cpu_timer_list *next;
        unsigned long i;
 
-       if (CPUCLOCK_PERTHREAD(timer->it_clock) && (p->flags & PF_EXITING))
-               return;
-
        head = (CPUCLOCK_PERTHREAD(timer->it_clock) ?
                p->cpu_timers : p->signal->cpu_timers);
        head += CPUCLOCK_WHICH(timer->it_clock);
@@ -1173,6 +1170,9 @@ static void check_process_timers(struct task_struct *tsk,
                }
                t = tsk;
                do {
+                       if (unlikely(t->flags & PF_EXITING))
+                               continue;
+
                        ticks = cputime_add(cputime_add(t->utime, t->stime),
                                            prof_left);
                        if (!cputime_eq(prof_expires, cputime_zero) &&
@@ -1193,11 +1193,7 @@ static void check_process_timers(struct task_struct *tsk,
                                              t->it_sched_expires > sched)) {
                                t->it_sched_expires = sched;
                        }
-
-                       do {
-                               t = next_thread(t);
-                       } while (unlikely(t->flags & PF_EXITING));
-               } while (t != tsk);
+               } while ((t = next_thread(t)) != tsk);
        }
 }
 
@@ -1289,30 +1285,30 @@ void run_posix_cpu_timers(struct task_struct *tsk)
 
 #undef UNEXPIRED
 
-       BUG_ON(tsk->exit_state);
-
        /*
         * Double-check with locks held.
         */
        read_lock(&tasklist_lock);
-       spin_lock(&tsk->sighand->siglock);
+       if (likely(tsk->signal != NULL)) {
+               spin_lock(&tsk->sighand->siglock);
 
-       /*
-        * Here we take off tsk->cpu_timers[N] and tsk->signal->cpu_timers[N]
-        * all the timers that are firing, and put them on the firing list.
-        */
-       check_thread_timers(tsk, &firing);
-       check_process_timers(tsk, &firing);
+               /*
+                * Here we take off tsk->cpu_timers[N] and tsk->signal->cpu_timers[N]
+                * all the timers that are firing, and put them on the firing list.
+                */
+               check_thread_timers(tsk, &firing);
+               check_process_timers(tsk, &firing);
 
-       /*
-        * We must release these locks before taking any timer's lock.
-        * There is a potential race with timer deletion here, as the
-        * siglock now protects our private firing list.  We have set
-        * the firing flag in each timer, so that a deletion attempt
-        * that gets the timer lock before we do will give it up and
-        * spin until we've taken care of that timer below.
-        */
-       spin_unlock(&tsk->sighand->siglock);
+               /*
+                * We must release these locks before taking any timer's lock.
+                * There is a potential race with timer deletion here, as the
+                * siglock now protects our private firing list.  We have set
+                * the firing flag in each timer, so that a deletion attempt
+                * that gets the timer lock before we do will give it up and
+                * spin until we've taken care of that timer below.
+                */
+               spin_unlock(&tsk->sighand->siglock);
+       }
        read_unlock(&tasklist_lock);
 
        /*
index a6d9ef46009ebdcb37f5b8fc4287d81f02dd089a..0a907f0dc56b3bc0f67e189ded38f64e8ad94ebb 100644 (file)
@@ -86,6 +86,7 @@ static int suspend_prepare(suspend_state_t state)
                        goto Thaw;
        }
 
+       suspend_console();
        if ((error = device_suspend(PMSG_SUSPEND))) {
                printk(KERN_ERR "Some devices failed to suspend\n");
                goto Finish;
@@ -133,6 +134,7 @@ int suspend_enter(suspend_state_t state)
 static void suspend_finish(suspend_state_t state)
 {
        device_resume();
+       resume_console();
        thaw_processes();
        enable_nonboot_cpus();
        if (pm_ops && pm_ops->finish)
index c056f3324432c31152063de1ca820fbcd2f3d92a..19a95561929478ffc99ac1552cf3ab645ec16bc1 100644 (file)
@@ -67,6 +67,7 @@ EXPORT_SYMBOL(oops_in_progress);
  * driver system.
  */
 static DECLARE_MUTEX(console_sem);
+static DECLARE_MUTEX(secondary_console_sem);
 struct console *console_drivers;
 /*
  * This is used for debugging the mess that is the VT code by
@@ -76,7 +77,7 @@ struct console *console_drivers;
  * path in the console code where we end up in places I want
  * locked without the console sempahore held
  */
-static int console_locked;
+static int console_locked, console_suspended;
 
 /*
  * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
@@ -697,6 +698,23 @@ int __init add_preferred_console(char *name, int idx, char *options)
        return 0;
 }
 
+/**
+ * suspend_console - suspend the console subsystem
+ *
+ * This disables printk() while we go into suspend states
+ */
+void suspend_console(void)
+{
+       acquire_console_sem();
+       console_suspended = 1;
+}
+
+void resume_console(void)
+{
+       console_suspended = 0;
+       release_console_sem();
+}
+
 /**
  * acquire_console_sem - lock the console system for exclusive use.
  *
@@ -708,6 +726,10 @@ int __init add_preferred_console(char *name, int idx, char *options)
 void acquire_console_sem(void)
 {
        BUG_ON(in_interrupt());
+       if (console_suspended) {
+               down(&secondary_console_sem);
+               return;
+       }
        down(&console_sem);
        console_locked = 1;
        console_may_schedule = 1;
@@ -750,6 +772,10 @@ void release_console_sem(void)
        unsigned long _con_start, _log_end;
        unsigned long wake_klogd = 0;
 
+       if (console_suspended) {
+               up(&secondary_console_sem);
+               return;
+       }
        for ( ; ; ) {
                spin_lock_irqsave(&logbuf_lock, flags);
                wake_klogd |= log_start - log_end;
index e5f8aea78ffebd71a1322ca8279321aac3b077e6..1b3c921737e219a6f56281db270f8ccfbef0e6ab 100644 (file)
 #include <linux/syscalls.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
-#include <linux/audit.h>
 #include <linux/capability.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/siginfo.h>
+#include "audit.h"     /* audit_signal_info() */
 
 /*
  * SLAB caches for signal bits.
index e82726faeeffb4850cc49cc6e112cf28b143d4cb..0d656e61621dd191a38914f24a1492e82529a24e 100644 (file)
@@ -150,7 +150,7 @@ extern ctl_table random_table[];
 #ifdef CONFIG_UNIX98_PTYS
 extern ctl_table pty_table[];
 #endif
-#ifdef CONFIG_INOTIFY
+#ifdef CONFIG_INOTIFY_USER
 extern ctl_table inotify_table[];
 #endif
 
@@ -1028,7 +1028,7 @@ static ctl_table fs_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_doulongvec_minmax,
        },
-#ifdef CONFIG_INOTIFY
+#ifdef CONFIG_INOTIFY_USER
        {
                .ctl_name       = FS_INOTIFY,
                .procname       = "inotify",
index 2116642f42c62a2f6b02a7238a336d82621ad31f..4b1eb745afa1031fbf0ec9ef84955ef8e201d664 100644 (file)
@@ -140,7 +140,7 @@ struct user_struct * alloc_uid(uid_t uid)
                atomic_set(&new->processes, 0);
                atomic_set(&new->files, 0);
                atomic_set(&new->sigpending, 0);
-#ifdef CONFIG_INOTIFY
+#ifdef CONFIG_INOTIFY_USER
                atomic_set(&new->inotify_watches, 0);
                atomic_set(&new->inotify_devs, 0);
 #endif
index 14b791ac5089727c8430590e63d511201492bb56..1e55ba1c2edfac510c41c87e47e7849f99a5f3b3 100644 (file)
 static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
 {
        struct rb_node *right = node->rb_right;
+       struct rb_node *parent = rb_parent(node);
 
        if ((node->rb_right = right->rb_left))
-               right->rb_left->rb_parent = node;
+               rb_set_parent(right->rb_left, node);
        right->rb_left = node;
 
-       if ((right->rb_parent = node->rb_parent))
+       rb_set_parent(right, parent);
+
+       if (parent)
        {
-               if (node == node->rb_parent->rb_left)
-                       node->rb_parent->rb_left = right;
+               if (node == parent->rb_left)
+                       parent->rb_left = right;
                else
-                       node->rb_parent->rb_right = right;
+                       parent->rb_right = right;
        }
        else
                root->rb_node = right;
-       node->rb_parent = right;
+       rb_set_parent(node, right);
 }
 
 static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
 {
        struct rb_node *left = node->rb_left;
+       struct rb_node *parent = rb_parent(node);
 
        if ((node->rb_left = left->rb_right))
-               left->rb_right->rb_parent = node;
+               rb_set_parent(left->rb_right, node);
        left->rb_right = node;
 
-       if ((left->rb_parent = node->rb_parent))
+       rb_set_parent(left, parent);
+
+       if (parent)
        {
-               if (node == node->rb_parent->rb_right)
-                       node->rb_parent->rb_right = left;
+               if (node == parent->rb_right)
+                       parent->rb_right = left;
                else
-                       node->rb_parent->rb_left = left;
+                       parent->rb_left = left;
        }
        else
                root->rb_node = left;
-       node->rb_parent = left;
+       rb_set_parent(node, left);
 }
 
 void rb_insert_color(struct rb_node *node, struct rb_root *root)
 {
        struct rb_node *parent, *gparent;
 
-       while ((parent = node->rb_parent) && parent->rb_color == RB_RED)
+       while ((parent = rb_parent(node)) && rb_is_red(parent))
        {
-               gparent = parent->rb_parent;
+               gparent = rb_parent(parent);
 
                if (parent == gparent->rb_left)
                {
                        {
                                register struct rb_node *uncle = gparent->rb_right;
-                               if (uncle && uncle->rb_color == RB_RED)
+                               if (uncle && rb_is_red(uncle))
                                {
-                                       uncle->rb_color = RB_BLACK;
-                                       parent->rb_color = RB_BLACK;
-                                       gparent->rb_color = RB_RED;
+                                       rb_set_black(uncle);
+                                       rb_set_black(parent);
+                                       rb_set_red(gparent);
                                        node = gparent;
                                        continue;
                                }
@@ -94,17 +100,17 @@ void rb_insert_color(struct rb_node *node, struct rb_root *root)
                                node = tmp;
                        }
 
-                       parent->rb_color = RB_BLACK;
-                       gparent->rb_color = RB_RED;
+                       rb_set_black(parent);
+                       rb_set_red(gparent);
                        __rb_rotate_right(gparent, root);
                } else {
                        {
                                register struct rb_node *uncle = gparent->rb_left;
-                               if (uncle && uncle->rb_color == RB_RED)
+                               if (uncle && rb_is_red(uncle))
                                {
-                                       uncle->rb_color = RB_BLACK;
-                                       parent->rb_color = RB_BLACK;
-                                       gparent->rb_color = RB_RED;
+                                       rb_set_black(uncle);
+                                       rb_set_black(parent);
+                                       rb_set_red(gparent);
                                        node = gparent;
                                        continue;
                                }
@@ -119,13 +125,13 @@ void rb_insert_color(struct rb_node *node, struct rb_root *root)
                                node = tmp;
                        }
 
-                       parent->rb_color = RB_BLACK;
-                       gparent->rb_color = RB_RED;
+                       rb_set_black(parent);
+                       rb_set_red(gparent);
                        __rb_rotate_left(gparent, root);
                }
        }
 
-       root->rb_node->rb_color = RB_BLACK;
+       rb_set_black(root->rb_node);
 }
 EXPORT_SYMBOL(rb_insert_color);
 
@@ -134,43 +140,40 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
 {
        struct rb_node *other;
 
-       while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node)
+       while ((!node || rb_is_black(node)) && node != root->rb_node)
        {
                if (parent->rb_left == node)
                {
                        other = parent->rb_right;
-                       if (other->rb_color == RB_RED)
+                       if (rb_is_red(other))
                        {
-                               other->rb_color = RB_BLACK;
-                               parent->rb_color = RB_RED;
+                               rb_set_black(other);
+                               rb_set_red(parent);
                                __rb_rotate_left(parent, root);
                                other = parent->rb_right;
                        }
-                       if ((!other->rb_left ||
-                            other->rb_left->rb_color == RB_BLACK)
-                           && (!other->rb_right ||
-                               other->rb_right->rb_color == RB_BLACK))
+                       if ((!other->rb_left || rb_is_black(other->rb_left)) &&
+                           (!other->rb_right || rb_is_black(other->rb_right)))
                        {
-                               other->rb_color = RB_RED;
+                               rb_set_red(other);
                                node = parent;
-                               parent = node->rb_parent;
+                               parent = rb_parent(node);
                        }
                        else
                        {
-                               if (!other->rb_right ||
-                                   other->rb_right->rb_color == RB_BLACK)
+                               if (!other->rb_right || rb_is_black(other->rb_right))
                                {
-                                       register struct rb_node *o_left;
+                                       struct rb_node *o_left;
                                        if ((o_left = other->rb_left))
-                                               o_left->rb_color = RB_BLACK;
-                                       other->rb_color = RB_RED;
+                                               rb_set_black(o_left);
+                                       rb_set_red(other);
                                        __rb_rotate_right(other, root);
                                        other = parent->rb_right;
                                }
-                               other->rb_color = parent->rb_color;
-                               parent->rb_color = RB_BLACK;
+                               rb_set_color(other, rb_color(parent));
+                               rb_set_black(parent);
                                if (other->rb_right)
-                                       other->rb_right->rb_color = RB_BLACK;
+                                       rb_set_black(other->rb_right);
                                __rb_rotate_left(parent, root);
                                node = root->rb_node;
                                break;
@@ -179,38 +182,35 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
                else
                {
                        other = parent->rb_left;
-                       if (other->rb_color == RB_RED)
+                       if (rb_is_red(other))
                        {
-                               other->rb_color = RB_BLACK;
-                               parent->rb_color = RB_RED;
+                               rb_set_black(other);
+                               rb_set_red(parent);
                                __rb_rotate_right(parent, root);
                                other = parent->rb_left;
                        }
-                       if ((!other->rb_left ||
-                            other->rb_left->rb_color == RB_BLACK)
-                           && (!other->rb_right ||
-                               other->rb_right->rb_color == RB_BLACK))
+                       if ((!other->rb_left || rb_is_black(other->rb_left)) &&
+                           (!other->rb_right || rb_is_black(other->rb_right)))
                        {
-                               other->rb_color = RB_RED;
+                               rb_set_red(other);
                                node = parent;
-                               parent = node->rb_parent;
+                               parent = rb_parent(node);
                        }
                        else
                        {
-                               if (!other->rb_left ||
-                                   other->rb_left->rb_color == RB_BLACK)
+                               if (!other->rb_left || rb_is_black(other->rb_left))
                                {
                                        register struct rb_node *o_right;
                                        if ((o_right = other->rb_right))
-                                               o_right->rb_color = RB_BLACK;
-                                       other->rb_color = RB_RED;
+                                               rb_set_black(o_right);
+                                       rb_set_red(other);
                                        __rb_rotate_left(other, root);
                                        other = parent->rb_left;
                                }
-                               other->rb_color = parent->rb_color;
-                               parent->rb_color = RB_BLACK;
+                               rb_set_color(other, rb_color(parent));
+                               rb_set_black(parent);
                                if (other->rb_left)
-                                       other->rb_left->rb_color = RB_BLACK;
+                                       rb_set_black(other->rb_left);
                                __rb_rotate_right(parent, root);
                                node = root->rb_node;
                                break;
@@ -218,7 +218,7 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
                }
        }
        if (node)
-               node->rb_color = RB_BLACK;
+               rb_set_black(node);
 }
 
 void rb_erase(struct rb_node *node, struct rb_root *root)
@@ -238,48 +238,41 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
                while ((left = node->rb_left) != NULL)
                        node = left;
                child = node->rb_right;
-               parent = node->rb_parent;
-               color = node->rb_color;
+               parent = rb_parent(node);
+               color = rb_color(node);
 
                if (child)
-                       child->rb_parent = parent;
-               if (parent)
-               {
-                       if (parent->rb_left == node)
-                               parent->rb_left = child;
-                       else
-                               parent->rb_right = child;
-               }
-               else
-                       root->rb_node = child;
-
-               if (node->rb_parent == old)
+                       rb_set_parent(child, parent);
+               if (parent == old) {
+                       parent->rb_right = child;
                        parent = node;
-               node->rb_parent = old->rb_parent;
-               node->rb_color = old->rb_color;
+               } else
+                       parent->rb_left = child;
+
+               node->rb_parent_color = old->rb_parent_color;
                node->rb_right = old->rb_right;
                node->rb_left = old->rb_left;
 
-               if (old->rb_parent)
+               if (rb_parent(old))
                {
-                       if (old->rb_parent->rb_left == old)
-                               old->rb_parent->rb_left = node;
+                       if (rb_parent(old)->rb_left == old)
+                               rb_parent(old)->rb_left = node;
                        else
-                               old->rb_parent->rb_right = node;
+                               rb_parent(old)->rb_right = node;
                } else
                        root->rb_node = node;
 
-               old->rb_left->rb_parent = node;
+               rb_set_parent(old->rb_left, node);
                if (old->rb_right)
-                       old->rb_right->rb_parent = node;
+                       rb_set_parent(old->rb_right, node);
                goto color;
        }
 
-       parent = node->rb_parent;
-       color = node->rb_color;
+       parent = rb_parent(node);
+       color = rb_color(node);
 
        if (child)
-               child->rb_parent = parent;
+               rb_set_parent(child, parent);
        if (parent)
        {
                if (parent->rb_left == node)
@@ -327,6 +320,8 @@ EXPORT_SYMBOL(rb_last);
 
 struct rb_node *rb_next(struct rb_node *node)
 {
+       struct rb_node *parent;
+
        /* If we have a right-hand child, go down and then left as far
           as we can. */
        if (node->rb_right) {
@@ -342,15 +337,17 @@ struct rb_node *rb_next(struct rb_node *node)
           ancestor is a right-hand child of its parent, keep going
           up. First time it's a left-hand child of its parent, said
           parent is our 'next' node. */
-       while (node->rb_parent && node == node->rb_parent->rb_right)
-               node = node->rb_parent;
+       while ((parent = rb_parent(node)) && node == parent->rb_right)
+               node = parent;
 
-       return node->rb_parent;
+       return parent;
 }
 EXPORT_SYMBOL(rb_next);
 
 struct rb_node *rb_prev(struct rb_node *node)
 {
+       struct rb_node *parent;
+
        /* If we have a left-hand child, go down and then right as far
           as we can. */
        if (node->rb_left) {
@@ -362,17 +359,17 @@ struct rb_node *rb_prev(struct rb_node *node)
 
        /* No left-hand children. Go up till we find an ancestor which
           is a right-hand child of its parent */
-       while (node->rb_parent && node == node->rb_parent->rb_left)
-               node = node->rb_parent;
+       while ((parent = rb_parent(node)) && node == parent->rb_left)
+               node = parent;
 
-       return node->rb_parent;
+       return parent;
 }
 EXPORT_SYMBOL(rb_prev);
 
 void rb_replace_node(struct rb_node *victim, struct rb_node *new,
                     struct rb_root *root)
 {
-       struct rb_node *parent = victim->rb_parent;
+       struct rb_node *parent = rb_parent(victim);
 
        /* Set the surrounding nodes to point to the replacement */
        if (parent) {
@@ -384,9 +381,9 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new,
                root->rb_node = new;
        }
        if (victim->rb_left)
-               victim->rb_left->rb_parent = new;
+               rb_set_parent(victim->rb_left, new);
        if (victim->rb_right)
-               victim->rb_right->rb_parent = new;
+               rb_set_parent(victim->rb_right, new);
 
        /* Copy the pointers/colour from the victim to the replacement */
        *new = *victim;
index 1ae2b2cc3a54148a72489416829cf36a26abd81b..70df5c0d957e482f8055fc2ecc596fc173a11a61 100644 (file)
@@ -91,8 +91,8 @@ static void grow_zone_span(struct zone *zone,
        if (start_pfn < zone->zone_start_pfn)
                zone->zone_start_pfn = start_pfn;
 
-       if (end_pfn > old_zone_end_pfn)
-               zone->spanned_pages = end_pfn - zone->zone_start_pfn;
+       zone->spanned_pages = max(old_zone_end_pfn, end_pfn) -
+                               zone->zone_start_pfn;
 
        zone_span_writeunlock(zone);
 }
@@ -106,8 +106,8 @@ static void grow_pgdat_span(struct pglist_data *pgdat,
        if (start_pfn < pgdat->node_start_pfn)
                pgdat->node_start_pfn = start_pfn;
 
-       if (end_pfn > old_pgdat_end_pfn)
-               pgdat->node_spanned_pages = end_pfn - pgdat->node_start_pfn;
+       pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) -
+                                       pgdat->node_start_pfn;
 }
 
 int online_pages(unsigned long pfn, unsigned long nr_pages)
index 4c5e68e4e9aed7fcf6b31a88d240046ffeb0f899..1e43c8a865ba76924170f34471f32ad5a3cbdfdb 100644 (file)
@@ -1780,6 +1780,7 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
        if (!simple_empty(dentry))
                return -ENOTEMPTY;
 
+       dentry->d_inode->i_nlink--;
        dir->i_nlink--;
        return shmem_unlink(dir, dentry);
 }
@@ -2102,6 +2103,7 @@ static int shmem_fill_super(struct super_block *sb,
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
        sb->s_magic = TMPFS_MAGIC;
        sb->s_op = &shmem_ops;
+       sb->s_time_gran = 1;
 
        inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
        if (!inode)
index d31a06bfbea5c78998e3c68a5a484b98b3e4579f..f1b644eb39d816b3865400caf8d589d458756a17 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -207,11 +207,6 @@ typedef unsigned int kmem_bufctl_t;
 #define        BUFCTL_ACTIVE   (((kmem_bufctl_t)(~0U))-2)
 #define        SLAB_LIMIT      (((kmem_bufctl_t)(~0U))-3)
 
-/* Max number of objs-per-slab for caches which use off-slab slabs.
- * Needed to avoid a possible looping condition in cache_grow().
- */
-static unsigned long offslab_limit;
-
 /*
  * struct slab
  *
@@ -1356,12 +1351,6 @@ void __init kmem_cache_init(void)
                                        NULL, NULL);
                }
 
-               /* Inc off-slab bufctl limit until the ceiling is hit. */
-               if (!(OFF_SLAB(sizes->cs_cachep))) {
-                       offslab_limit = sizes->cs_size - sizeof(struct slab);
-                       offslab_limit /= sizeof(kmem_bufctl_t);
-               }
-
                sizes->cs_dmacachep = kmem_cache_create(names->name_dma,
                                        sizes->cs_size,
                                        ARCH_KMALLOC_MINALIGN,
@@ -1780,6 +1769,7 @@ static void set_up_list3s(struct kmem_cache *cachep, int index)
 static size_t calculate_slab_order(struct kmem_cache *cachep,
                        size_t size, size_t align, unsigned long flags)
 {
+       unsigned long offslab_limit;
        size_t left_over = 0;
        int gfporder;
 
@@ -1791,9 +1781,18 @@ static size_t calculate_slab_order(struct kmem_cache *cachep,
                if (!num)
                        continue;
 
-               /* More than offslab_limit objects will cause problems */
-               if ((flags & CFLGS_OFF_SLAB) && num > offslab_limit)
-                       break;
+               if (flags & CFLGS_OFF_SLAB) {
+                       /*
+                        * Max number of objs-per-slab for caches which
+                        * use off-slab slabs. Needed to avoid a possible
+                        * looping condition in cache_grow().
+                        */
+                       offslab_limit = size - sizeof(struct slab);
+                       offslab_limit /= sizeof(kmem_bufctl_t);
+
+                       if (num > offslab_limit)
+                               break;
+               }
 
                /* Found something acceptable - save it away */
                cachep->num = num;
index 4649a63a8cb6f9c3892e92538b394f754295a90e..440a733fe2e9ea3d1374d4fd72e7bba60e268e05 100644 (file)
@@ -1061,7 +1061,7 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, unsigned long nr_pages,
 loop_again:
        total_scanned = 0;
        nr_reclaimed = 0;
-       sc.may_writepage = !laptop_mode,
+       sc.may_writepage = !laptop_mode;
        sc.nr_mapped = read_page_state(nr_mapped);
 
        inc_page_state(pageoutrun);
index 4193cdcd3ae716df5bb530139a564ea6a0ae2830..c6cec5aa548604c87aa48ce43fd9c2007052f305 100644 (file)
@@ -66,6 +66,13 @@ source "net/ipv6/Kconfig"
 
 endif # if INET
 
+config NETWORK_SECMARK
+       bool "Security Marking"
+       help
+         This enables security marking of network packets, similar
+         to nfmark, but designated for security purposes.
+         If you are unsure how to answer this question, answer N.
+
 menuconfig NETFILTER
        bool "Network packet filtering (replaces ipchains)"
        ---help---
@@ -215,6 +222,21 @@ config NET_PKTGEN
          To compile this code as a module, choose M here: the
          module will be called pktgen.
 
+config NET_TCPPROBE
+       tristate "TCP connection probing"
+       depends on INET && EXPERIMENTAL && PROC_FS && KPROBES
+       ---help---
+       This module allows for capturing the changes to TCP connection
+       state in response to incoming packets. It is used for debugging
+       TCP congestion avoidance modules. If you don't understand
+       what was just said, you don't need it: say N.
+
+       Documentation on how to use the packet generator can be found
+       at http://linux-net.osdl.org/index.php/TcpProbe
+
+       To compile this code as a module, choose M here: the
+       module will be called tcp_probe.
+
 endmenu
 
 endmenu
index 72d8529826646e35018514046c3afac4197885a8..f92f9c94d2c762c51ffe76031c7598e85759a574 100644 (file)
@@ -98,7 +98,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
                printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
                return;
        }
-       spin_lock_bh(&entry->neigh->dev->xmit_lock);    /* block clip_start_xmit() */
+       netif_tx_lock_bh(entry->neigh->dev);    /* block clip_start_xmit() */
        entry->neigh->used = jiffies;
        for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
                if (*walk == clip_vcc) {
@@ -122,7 +122,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
        printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
               "0x%p)\n", entry, clip_vcc);
       out:
-       spin_unlock_bh(&entry->neigh->dev->xmit_lock);
+       netif_tx_unlock_bh(entry->neigh->dev);
 }
 
 /* The neighbour entry n->lock is held. */
index 59556e40e143457abdf3ab0d4af6b609796b2264..f444c12cde5a66d0cf864ef2238de8307d8b2707 100644 (file)
@@ -6,7 +6,7 @@ obj-$(CONFIG_BRIDGE) += bridge.o
 
 bridge-y       := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \
                        br_ioctl.o br_notify.o br_stp.o br_stp_bpdu.o \
-                       br_stp_if.o br_stp_timer.o
+                       br_stp_if.o br_stp_timer.o br_netlink.o
 
 bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o
 
index 12da21afb9ca636bbd438be992cacfa5722b2524..654401ceb2dbdf679522c8ce92c5699c5589c613 100644 (file)
@@ -30,36 +30,46 @@ static struct llc_sap *br_stp_sap;
 
 static int __init br_init(void)
 {
+       int err;
+
        br_stp_sap = llc_sap_open(LLC_SAP_BSPAN, br_stp_rcv);
        if (!br_stp_sap) {
                printk(KERN_ERR "bridge: can't register sap for STP\n");
-               return -EBUSY;
+               return -EADDRINUSE;
        }
 
        br_fdb_init();
 
-#ifdef CONFIG_BRIDGE_NETFILTER
-       if (br_netfilter_init())
-               return 1;
-#endif
+       err = br_netfilter_init();
+       if (err)
+               goto err_out1;
+
+       err = register_netdevice_notifier(&br_device_notifier);
+       if (err)
+               goto err_out2;
+
+       br_netlink_init();
        brioctl_set(br_ioctl_deviceless_stub);
        br_handle_frame_hook = br_handle_frame;
 
        br_fdb_get_hook = br_fdb_get;
        br_fdb_put_hook = br_fdb_put;
 
-       register_netdevice_notifier(&br_device_notifier);
-
        return 0;
+
+err_out2:
+       br_netfilter_fini();
+err_out1:
+       llc_sap_put(br_stp_sap);
+       return err;
 }
 
 static void __exit br_deinit(void)
 {
        rcu_assign_pointer(br_stp_sap->rcv_func, NULL);
 
-#ifdef CONFIG_BRIDGE_NETFILTER
+       br_netlink_fini();
        br_netfilter_fini();
-#endif
        unregister_netdevice_notifier(&br_device_notifier);
        brioctl_set(NULL);
 
index 0c88a2ac32c1bc4fb5144c56696fb04abf708af7..2afdc7c0736c48b6baa39c5e9fa37987a7cdb779 100644 (file)
@@ -145,9 +145,9 @@ static int br_set_tx_csum(struct net_device *dev, u32 data)
        struct net_bridge *br = netdev_priv(dev);
 
        if (data)
-               br->feature_mask |= NETIF_F_IP_CSUM;
+               br->feature_mask |= NETIF_F_NO_CSUM;
        else
-               br->feature_mask &= ~NETIF_F_IP_CSUM;
+               br->feature_mask &= ~NETIF_F_ALL_CSUM;
 
        br_features_recompute(br);
        return 0;
@@ -185,5 +185,5 @@ void br_dev_setup(struct net_device *dev)
        dev->priv_flags = IFF_EBRIDGE;
 
        dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
-               | NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_IP_CSUM;
+               | NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_NO_CSUM;
 }
index 56f3aa47e758f40dab34a007d8eeb50940046190..0dca027ceb80bd3c36d2af4f2fd3d961781cbf81 100644 (file)
 #include <linux/netfilter_bridge.h>
 #include "br_private.h"
 
+/* Don't forward packets to originating port or forwarding diasabled */
 static inline int should_deliver(const struct net_bridge_port *p, 
                                 const struct sk_buff *skb)
 {
-       if (skb->dev == p->dev ||
-           p->state != BR_STATE_FORWARDING)
-               return 0;
-
-       return 1;
+       return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING);
 }
 
 static inline unsigned packet_length(const struct sk_buff *skb)
@@ -55,10 +52,9 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
 
 int br_forward_finish(struct sk_buff *skb)
 {
-       NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
-                       br_dev_queue_push_xmit);
+       return NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
+                      br_dev_queue_push_xmit);
 
-       return 0;
 }
 
 static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
index ad1c7af65ec8dcb944b59d2310df3c9ec539805d..fdec773f5b52630eee65cc548756f138d5c52116 100644 (file)
@@ -300,25 +300,20 @@ int br_add_bridge(const char *name)
        rtnl_lock();
        if (strchr(dev->name, '%')) {
                ret = dev_alloc_name(dev, dev->name);
-               if (ret < 0)
-                       goto err1;
+               if (ret < 0) {
+                       free_netdev(dev);
+                       goto out;
+               }
        }
 
        ret = register_netdevice(dev);
        if (ret)
-               goto err2;
+               goto out;
 
        ret = br_sysfs_addbr(dev);
        if (ret)
-               goto err3;
-       rtnl_unlock();
-       return 0;
-
- err3:
-       unregister_netdev(dev);
- err2:
-       free_netdev(dev);
- err1:
+               unregister_netdevice(dev);
+ out:
        rtnl_unlock();
        return ret;
 }
@@ -377,12 +372,17 @@ void br_features_recompute(struct net_bridge *br)
        struct net_bridge_port *p;
        unsigned long features, checksum;
 
-       features = br->feature_mask &~ NETIF_F_IP_CSUM;
-       checksum = br->feature_mask & NETIF_F_IP_CSUM;
+       checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0;
+       features = br->feature_mask & ~NETIF_F_ALL_CSUM;
 
        list_for_each_entry(p, &br->port_list, list) {
-               if (!(p->dev->features 
-                     & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)))
+               if (checksum & NETIF_F_NO_CSUM &&
+                   !(p->dev->features & NETIF_F_NO_CSUM))
+                       checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
+               if (checksum & NETIF_F_HW_CSUM &&
+                   !(p->dev->features & NETIF_F_HW_CSUM))
+                       checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
+               if (!(p->dev->features & NETIF_F_IP_CSUM))
                        checksum = 0;
                features &= p->dev->features;
        }
index 3da9264449f79d6d517fce1391af3f663bdde3a8..3e41f9d6d51c7f27d167cee06ddff99556c8dca8 100644 (file)
@@ -407,12 +407,8 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
        if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
                if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
                        goto inhdr_error;
-               if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
-                       if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr)))
-                               goto inhdr_error;
-                       if (skb->ip_summed == CHECKSUM_HW)
-                               skb->ip_summed = CHECKSUM_NONE;
-               }
+               if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
+                       goto inhdr_error;
        }
        if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb))
                goto inhdr_error;
@@ -495,11 +491,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
        if (skb->len < len || len < 4 * iph->ihl)
                goto inhdr_error;
 
-       if (skb->len > len) {
-               __pskb_trim(skb, len);
-               if (skb->ip_summed == CHECKSUM_HW)
-                       skb->ip_summed = CHECKSUM_NONE;
-       }
+       pskb_trim_rcsum(skb, len);
 
        nf_bridge_put(skb->nf_bridge);
        if (!nf_bridge_alloc(skb))
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
new file mode 100644 (file)
index 0000000..881d7d1
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ *     Bridge netlink control interface
+ *
+ *     Authors:
+ *     Stephen Hemminger               <shemminger@osdl.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/rtnetlink.h>
+#include "br_private.h"
+
+/*
+ * Create one netlink message for one interface
+ * Contains port and master info as well as carrier and bridge state.
+ */
+static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port,
+                         u32 pid, u32 seq, int event, unsigned int flags)
+{
+       const struct net_bridge *br = port->br;
+       const struct net_device *dev = port->dev;
+       struct ifinfomsg *r;
+       struct nlmsghdr *nlh;
+       unsigned char *b = skb->tail;
+       u32 mtu = dev->mtu;
+       u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
+       u8 portstate = port->state;
+
+       pr_debug("br_fill_info event %d port %s master %s\n",
+                event, dev->name, br->dev->name);
+
+       nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
+       r = NLMSG_DATA(nlh);
+       r->ifi_family = AF_BRIDGE;
+       r->__ifi_pad = 0;
+       r->ifi_type = dev->type;
+       r->ifi_index = dev->ifindex;
+       r->ifi_flags = dev_get_flags(dev);
+       r->ifi_change = 0;
+
+       RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
+
+       RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex);
+
+       if (dev->addr_len)
+               RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
+
+       RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
+       if (dev->ifindex != dev->iflink)
+               RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
+
+
+       RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
+
+       if (event == RTM_NEWLINK)
+               RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate);
+
+       nlh->nlmsg_len = skb->tail - b;
+
+       return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+
+       skb_trim(skb, b - skb->data);
+       return -EINVAL;
+}
+
+/*
+ * Notify listeners of a change in port information
+ */
+void br_ifinfo_notify(int event, struct net_bridge_port *port)
+{
+       struct sk_buff *skb;
+       int err = -ENOMEM;
+
+       pr_debug("bridge notify event=%d\n", event);
+       skb = alloc_skb(NLMSG_SPACE(sizeof(struct ifinfomsg) + 128),
+                       GFP_ATOMIC);
+       if (!skb)
+               goto err_out;
+
+       err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0);
+       if (err)
+               goto err_kfree;
+
+       NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
+       netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
+       return;
+
+err_kfree:
+       kfree_skb(skb);
+err_out:
+       netlink_set_err(rtnl, 0, RTNLGRP_LINK, err);
+}
+
+/*
+ * Dump information about all ports, in response to GETLINK
+ */
+static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct net_device *dev;
+       int idx;
+       int s_idx = cb->args[0];
+       int err = 0;
+
+       read_lock(&dev_base_lock);
+       for (dev = dev_base, idx = 0; dev; dev = dev->next) {
+               struct net_bridge_port *p = dev->br_port;
+
+               /* not a bridge port */
+               if (!p)
+                       continue;
+
+               if (idx < s_idx)
+                       continue;
+
+               err = br_fill_ifinfo(skb, p, NETLINK_CB(cb->skb).pid,
+                                    cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
+               if (err <= 0)
+                       break;
+               ++idx;
+       }
+       read_unlock(&dev_base_lock);
+
+       cb->args[0] = idx;
+
+       return skb->len;
+}
+
+/*
+ * Change state of port (ie from forwarding to blocking etc)
+ * Used by spanning tree in user space.
+ */
+static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
+{
+       struct rtattr  **rta = arg;
+       struct ifinfomsg *ifm = NLMSG_DATA(nlh);
+       struct net_device *dev;
+       struct net_bridge_port *p;
+       u8 new_state;
+
+       if (ifm->ifi_family != AF_BRIDGE)
+               return -EPFNOSUPPORT;
+
+       /* Must pass valid state as PROTINFO */
+       if (rta[IFLA_PROTINFO-1]) {
+               u8 *pstate = RTA_DATA(rta[IFLA_PROTINFO-1]);
+               new_state = *pstate;
+       } else
+               return -EINVAL;
+
+       if (new_state > BR_STATE_BLOCKING)
+               return -EINVAL;
+
+       /* Find bridge port */
+       dev = __dev_get_by_index(ifm->ifi_index);
+       if (!dev)
+               return -ENODEV;
+
+       p = dev->br_port;
+       if (!p)
+               return -EINVAL;
+
+       /* if kernel STP is running, don't allow changes */
+       if (p->br->stp_enabled)
+               return -EBUSY;
+
+       if (!netif_running(dev))
+               return -ENETDOWN;
+
+       if (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)
+               return -ENETDOWN;
+
+       p->state = new_state;
+       br_log_state(p);
+       return 0;
+}
+
+
+static struct rtnetlink_link bridge_rtnetlink_table[RTM_NR_MSGTYPES] = {
+       [RTM_GETLINK - RTM_BASE] = { .dumpit    = br_dump_ifinfo, },
+       [RTM_SETLINK - RTM_BASE] = { .doit      = br_rtm_setlink, },
+};
+
+void __init br_netlink_init(void)
+{
+       rtnetlink_links[PF_BRIDGE] = bridge_rtnetlink_table;
+}
+
+void __exit br_netlink_fini(void)
+{
+       rtnetlink_links[PF_BRIDGE] = NULL;
+}
+
index a43a9c1d50d7daa21c732523e9d2cdb3d36e3a9e..20278494e4da0d11712cfad0ed31f410abc5eb35 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/rtnetlink.h>
 
 #include "br_private.h"
 
@@ -49,6 +50,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
 
        case NETDEV_CHANGEADDR:
                br_fdb_changeaddr(p, dev->dev_addr);
+               br_ifinfo_notify(RTM_NEWLINK, p);
                br_stp_recalculate_bridge_id(br);
                break;
 
index 86ecea7ed372f2623e2a2fb732905fe3d9a0118f..c491fb2f280ebf7b1cf2395371c43d33bf36f43c 100644 (file)
@@ -29,7 +29,7 @@
 
 #define BR_PORT_DEBOUNCE (HZ/10)
 
-#define BR_VERSION     "2.1"
+#define BR_VERSION     "2.2"
 
 typedef struct bridge_id bridge_id;
 typedef struct mac_addr mac_addr;
@@ -192,8 +192,13 @@ extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 extern int br_ioctl_deviceless_stub(unsigned int cmd, void __user *arg);
 
 /* br_netfilter.c */
+#ifdef CONFIG_BRIDGE_NETFILTER
 extern int br_netfilter_init(void);
 extern void br_netfilter_fini(void);
+#else
+#define br_netfilter_init()    (0)
+#define br_netfilter_fini()    do { } while(0)
+#endif
 
 /* br_stp.c */
 extern void br_log_state(const struct net_bridge_port *p);
@@ -232,6 +237,11 @@ extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
 extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
 
 
+/* br_netlink.c */
+extern void br_netlink_init(void);
+extern void br_netlink_fini(void);
+extern void br_ifinfo_notify(int event, struct net_bridge_port *port);
+
 #ifdef CONFIG_SYSFS
 /* br_sysfs_if.c */
 extern struct sysfs_ops brport_sysfs_ops;
index 23dea1422c9a90873c13145ae52f7287afcb9633..14cd025079af0393abba67e7c3704dc2bd688470 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
 #include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
 
 #include "br_private.h"
 #include "br_private_stp.h"
@@ -86,6 +87,7 @@ void br_stp_disable_bridge(struct net_bridge *br)
 void br_stp_enable_port(struct net_bridge_port *p)
 {
        br_init_port(p);
+       br_ifinfo_notify(RTM_NEWLINK, p);
        br_port_state_selection(p->br);
 }
 
@@ -99,6 +101,8 @@ void br_stp_disable_port(struct net_bridge_port *p)
        printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
               br->dev->name, p->port_no, p->dev->name, "disabled");
 
+       br_ifinfo_notify(RTM_DELLINK, p);
+
        wasroot = br_is_root_bridge(br);
        br_become_designated_port(p);
        p->state = BR_STATE_DISABLED;
index 79fe12cced278b0b0b57b2c4041b6ff21936b52b..e9bd2467d5a9362aec0b1488d4e4a58962a4b890 100644 (file)
@@ -16,3 +16,4 @@ obj-$(CONFIG_NET_DIVERT) += dv.o
 obj-$(CONFIG_NET_PKTGEN) += pktgen.o
 obj-$(CONFIG_WIRELESS_EXT) += wireless.o
 obj-$(CONFIG_NETPOLL) += netpoll.o
+obj-$(CONFIG_NET_DMA) += user_dma.o
index 2dce673a039b6f4f71888e4780678b35924e7d3e..ab39fe17cb58bd0a49ce65376e279347a46fe248 100644 (file)
 #include <net/iw_handler.h>
 #include <asm/current.h>
 #include <linux/audit.h>
+#include <linux/dmaengine.h>
 
 /*
  *     The list of packet types we will receive (as opposed to discard)
  *             sure which should go first, but I bet it won't make much
  *             difference if we are running VLANs.  The good news is that
  *             this protocol won't be in the list unless compiled in, so
- *             the average user (w/out VLANs) will not be adversly affected.
+ *             the average user (w/out VLANs) will not be adversely affected.
  *             --BLG
  *
  *             0800    IP
@@ -148,8 +149,14 @@ static DEFINE_SPINLOCK(ptype_lock);
 static struct list_head ptype_base[16];        /* 16 way hashed list */
 static struct list_head ptype_all;             /* Taps */
 
+#ifdef CONFIG_NET_DMA
+static struct dma_client *net_dma_client;
+static unsigned int net_dma_count;
+static spinlock_t net_dma_event_lock;
+#endif
+
 /*
- * The @dev_base list is protected by @dev_base_lock and the rtln
+ * The @dev_base list is protected by @dev_base_lock and the rtnl
  * semaphore.
  *
  * Pure readers hold dev_base_lock for reading.
@@ -641,10 +648,12 @@ int dev_valid_name(const char *name)
  *     @name: name format string
  *
  *     Passed a format string - eg "lt%d" it will try and find a suitable
- *     id. Not efficient for many devices, not called a lot. The caller
- *     must hold the dev_base or rtnl lock while allocating the name and
- *     adding the device in order to avoid duplicates. Returns the number
- *     of the unit assigned or a negative errno code.
+ *     id. It scans list of devices to build up a free map, then chooses
+ *     the first empty slot. The caller must hold the dev_base or rtnl lock
+ *     while allocating the name and adding the device in order to avoid
+ *     duplicates.
+ *     Limited to bits_per_byte * page size devices (ie 32K on most platforms).
+ *     Returns the number of the unit assigned or a negative errno code.
  */
 
 int dev_alloc_name(struct net_device *dev, const char *name)
@@ -744,7 +753,7 @@ int dev_change_name(struct net_device *dev, char *newname)
 }
 
 /**
- *     netdev_features_change - device changes fatures
+ *     netdev_features_change - device changes features
  *     @dev: device to cause notification
  *
  *     Called to indicate a device has changed features.
@@ -1213,75 +1222,15 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
 #define illegal_highdma(dev, skb)      (0)
 #endif
 
-/* Keep head the same: replace data */
-int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask)
-{
-       unsigned int size;
-       u8 *data;
-       long offset;
-       struct skb_shared_info *ninfo;
-       int headerlen = skb->data - skb->head;
-       int expand = (skb->tail + skb->data_len) - skb->end;
-
-       if (skb_shared(skb))
-               BUG();
-
-       if (expand <= 0)
-               expand = 0;
-
-       size = skb->end - skb->head + expand;
-       size = SKB_DATA_ALIGN(size);
-       data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
-       if (!data)
-               return -ENOMEM;
-
-       /* Copy entire thing */
-       if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len))
-               BUG();
-
-       /* Set up shinfo */
-       ninfo = (struct skb_shared_info*)(data + size);
-       atomic_set(&ninfo->dataref, 1);
-       ninfo->tso_size = skb_shinfo(skb)->tso_size;
-       ninfo->tso_segs = skb_shinfo(skb)->tso_segs;
-       ninfo->nr_frags = 0;
-       ninfo->frag_list = NULL;
-
-       /* Offset between the two in bytes */
-       offset = data - skb->head;
-
-       /* Free old data. */
-       skb_release_data(skb);
-
-       skb->head = data;
-       skb->end  = data + size;
-
-       /* Set up new pointers */
-       skb->h.raw   += offset;
-       skb->nh.raw  += offset;
-       skb->mac.raw += offset;
-       skb->tail    += offset;
-       skb->data    += offset;
-
-       /* We are no longer a clone, even if we were. */
-       skb->cloned    = 0;
-
-       skb->tail     += skb->data_len;
-       skb->data_len  = 0;
-       return 0;
-}
-
 #define HARD_TX_LOCK(dev, cpu) {                       \
        if ((dev->features & NETIF_F_LLTX) == 0) {      \
-               spin_lock(&dev->xmit_lock);             \
-               dev->xmit_lock_owner = cpu;             \
+               netif_tx_lock(dev);                     \
        }                                               \
 }
 
 #define HARD_TX_UNLOCK(dev) {                          \
        if ((dev->features & NETIF_F_LLTX) == 0) {      \
-               dev->xmit_lock_owner = -1;              \
-               spin_unlock(&dev->xmit_lock);           \
+               netif_tx_unlock(dev);                   \
        }                                               \
 }
 
@@ -1319,7 +1268,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
        if (skb_shinfo(skb)->frag_list &&
            !(dev->features & NETIF_F_FRAGLIST) &&
-           __skb_linearize(skb, GFP_ATOMIC))
+           __skb_linearize(skb))
                goto out_kfree_skb;
 
        /* Fragmented skb is linearized if device does not support SG,
@@ -1328,14 +1277,14 @@ int dev_queue_xmit(struct sk_buff *skb)
         */
        if (skb_shinfo(skb)->nr_frags &&
            (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) &&
-           __skb_linearize(skb, GFP_ATOMIC))
+           __skb_linearize(skb))
                goto out_kfree_skb;
 
        /* If packet is not checksummed and device does not support
         * checksumming for this protocol, complete checksumming here.
         */
        if (skb->ip_summed == CHECKSUM_HW &&
-           (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
+           (!(dev->features & NETIF_F_GEN_CSUM) &&
             (!(dev->features & NETIF_F_IP_CSUM) ||
              skb->protocol != htons(ETH_P_IP))))
                if (skb_checksum_help(skb, 0))
@@ -1380,8 +1329,8 @@ int dev_queue_xmit(struct sk_buff *skb)
        /* The device has no queue. Common case for software devices:
           loopback, all the sorts of tunnels...
 
-          Really, it is unlikely that xmit_lock protection is necessary here.
-          (f.e. loopback and IP tunnels are clean ignoring statistics
+          Really, it is unlikely that netif_tx_lock protection is necessary
+          here.  (f.e. loopback and IP tunnels are clean ignoring statistics
           counters.)
           However, it is possible, that they rely on protection
           made by us here.
@@ -1844,6 +1793,19 @@ static void net_rx_action(struct softirq_action *h)
                }
        }
 out:
+#ifdef CONFIG_NET_DMA
+       /*
+        * There may not be any more sk_buffs coming right now, so push
+        * any pending DMA copies to hardware
+        */
+       if (net_dma_client) {
+               struct dma_chan *chan;
+               rcu_read_lock();
+               list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node)
+                       dma_async_memcpy_issue_pending(chan);
+               rcu_read_unlock();
+       }
+#endif
        local_irq_enable();
        return;
 
@@ -2196,7 +2158,7 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
  *     @dev: device
  *     @inc: modifier
  *
- *     Add or remove promsicuity from a device. While the count in the device
+ *     Add or remove promiscuity from a device. While the count in the device
  *     remains above zero the interface remains promiscuous. Once it hits zero
  *     the device reverts back to normal filtering operation. A negative inc
  *     value is used to drop promiscuity on the device.
@@ -2783,7 +2745,7 @@ int register_netdevice(struct net_device *dev)
        BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
 
        spin_lock_init(&dev->queue_lock);
-       spin_lock_init(&dev->xmit_lock);
+       spin_lock_init(&dev->_xmit_lock);
        dev->xmit_lock_owner = -1;
 #ifdef CONFIG_NET_CLS_ACT
        spin_lock_init(&dev->ingress_lock);
@@ -2827,9 +2789,7 @@ int register_netdevice(struct net_device *dev)
 
        /* Fix illegal SG+CSUM combinations. */
        if ((dev->features & NETIF_F_SG) &&
-           !(dev->features & (NETIF_F_IP_CSUM |
-                              NETIF_F_NO_CSUM |
-                              NETIF_F_HW_CSUM))) {
+           !(dev->features & NETIF_F_ALL_CSUM)) {
                printk("%s: Dropping NETIF_F_SG since no checksum feature.\n",
                       dev->name);
                dev->features &= ~NETIF_F_SG;
@@ -3122,7 +3082,7 @@ EXPORT_SYMBOL(alloc_netdev);
 void free_netdev(struct net_device *dev)
 {
 #ifdef CONFIG_SYSFS
-       /*  Compatiablity with error handling in drivers */
+       /*  Compatibility with error handling in drivers */
        if (dev->reg_state == NETREG_UNINITIALIZED) {
                kfree((char *)dev - dev->padded);
                return;
@@ -3298,6 +3258,88 @@ static int dev_cpu_callback(struct notifier_block *nfb,
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+#ifdef CONFIG_NET_DMA
+/**
+ * net_dma_rebalance -
+ * This is called when the number of channels allocated to the net_dma_client
+ * changes.  The net_dma_client tries to have one DMA channel per CPU.
+ */
+static void net_dma_rebalance(void)
+{
+       unsigned int cpu, i, n;
+       struct dma_chan *chan;
+
+       lock_cpu_hotplug();
+
+       if (net_dma_count == 0) {
+               for_each_online_cpu(cpu)
+                       rcu_assign_pointer(per_cpu(softnet_data.net_dma, cpu), NULL);
+               unlock_cpu_hotplug();
+               return;
+       }
+
+       i = 0;
+       cpu = first_cpu(cpu_online_map);
+
+       rcu_read_lock();
+       list_for_each_entry(chan, &net_dma_client->channels, client_node) {
+               n = ((num_online_cpus() / net_dma_count)
+                  + (i < (num_online_cpus() % net_dma_count) ? 1 : 0));
+
+               while(n) {
+                       per_cpu(softnet_data.net_dma, cpu) = chan;
+                       cpu = next_cpu(cpu, cpu_online_map);
+                       n--;
+               }
+               i++;
+       }
+       rcu_read_unlock();
+
+       unlock_cpu_hotplug();
+}
+
+/**
+ * netdev_dma_event - event callback for the net_dma_client
+ * @client: should always be net_dma_client
+ * @chan:
+ * @event:
+ */
+static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
+       enum dma_event event)
+{
+       spin_lock(&net_dma_event_lock);
+       switch (event) {
+       case DMA_RESOURCE_ADDED:
+               net_dma_count++;
+               net_dma_rebalance();
+               break;
+       case DMA_RESOURCE_REMOVED:
+               net_dma_count--;
+               net_dma_rebalance();
+               break;
+       default:
+               break;
+       }
+       spin_unlock(&net_dma_event_lock);
+}
+
+/**
+ * netdev_dma_regiser - register the networking subsystem as a DMA client
+ */
+static int __init netdev_dma_register(void)
+{
+       spin_lock_init(&net_dma_event_lock);
+       net_dma_client = dma_async_client_register(netdev_dma_event);
+       if (net_dma_client == NULL)
+               return -ENOMEM;
+
+       dma_async_client_chan_request(net_dma_client, num_online_cpus());
+       return 0;
+}
+
+#else
+static int __init netdev_dma_register(void) { return -ENODEV; }
+#endif /* CONFIG_NET_DMA */
 
 /*
  *     Initialize the DEV module. At boot time this walks the device list and
@@ -3351,6 +3393,8 @@ static int __init net_dev_init(void)
                atomic_set(&queue->backlog_dev.refcnt, 1);
        }
 
+       netdev_dma_register();
+
        dev_boot_phase = 0;
 
        open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
@@ -3369,7 +3413,6 @@ subsys_initcall(net_dev_init);
 EXPORT_SYMBOL(__dev_get_by_index);
 EXPORT_SYMBOL(__dev_get_by_name);
 EXPORT_SYMBOL(__dev_remove_pack);
-EXPORT_SYMBOL(__skb_linearize);
 EXPORT_SYMBOL(dev_valid_name);
 EXPORT_SYMBOL(dev_add_pack);
 EXPORT_SYMBOL(dev_alloc_name);
index 05d60850840e07a0d0beba51baf2b53fb622a883..c57d887da2ef20733e3d7f9c49e0d6b0aa405458 100644 (file)
@@ -62,7 +62,7 @@
  *     Device mc lists are changed by bh at least if IPv6 is enabled,
  *     so that it must be bh protected.
  *
- *     We block accesses to device mc filters with dev->xmit_lock.
+ *     We block accesses to device mc filters with netif_tx_lock.
  */
 
 /*
@@ -93,9 +93,9 @@ static void __dev_mc_upload(struct net_device *dev)
 
 void dev_mc_upload(struct net_device *dev)
 {
-       spin_lock_bh(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
        __dev_mc_upload(dev);
-       spin_unlock_bh(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
 }
 
 /*
@@ -107,7 +107,7 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
        int err = 0;
        struct dev_mc_list *dmi, **dmip;
 
-       spin_lock_bh(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
 
        for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
                /*
@@ -139,13 +139,13 @@ int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
                         */
                        __dev_mc_upload(dev);
                        
-                       spin_unlock_bh(&dev->xmit_lock);
+                       netif_tx_unlock_bh(dev);
                        return 0;
                }
        }
        err = -ENOENT;
 done:
-       spin_unlock_bh(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
        return err;
 }
 
@@ -160,7 +160,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
 
        dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
 
-       spin_lock_bh(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
        for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
                if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
                    dmi->dmi_addrlen == alen) {
@@ -176,7 +176,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
        }
 
        if ((dmi = dmi1) == NULL) {
-               spin_unlock_bh(&dev->xmit_lock);
+               netif_tx_unlock_bh(dev);
                return -ENOMEM;
        }
        memcpy(dmi->dmi_addr, addr, alen);
@@ -189,11 +189,11 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
 
        __dev_mc_upload(dev);
        
-       spin_unlock_bh(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
        return 0;
 
 done:
-       spin_unlock_bh(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
        kfree(dmi1);
        return err;
 }
@@ -204,7 +204,7 @@ done:
 
 void dev_mc_discard(struct net_device *dev)
 {
-       spin_lock_bh(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
        
        while (dev->mc_list != NULL) {
                struct dev_mc_list *tmp = dev->mc_list;
@@ -215,7 +215,7 @@ void dev_mc_discard(struct net_device *dev)
        }
        dev->mc_count = 0;
 
-       spin_unlock_bh(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
 }
 
 #ifdef CONFIG_PROC_FS
@@ -250,7 +250,7 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v)
        struct dev_mc_list *m;
        struct net_device *dev = v;
 
-       spin_lock_bh(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
        for (m = dev->mc_list; m; m = m->next) {
                int i;
 
@@ -262,7 +262,7 @@ static int dev_mc_seq_show(struct seq_file *seq, void *v)
 
                seq_putc(seq, '\n');
        }
-       spin_unlock_bh(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
        return 0;
 }
 
index e6f76106a99b3929c8c56ec5a62a64103b9d0c6b..33ce7ed6afc651206443200ed1d705c73bf01b08 100644 (file)
@@ -30,7 +30,7 @@ u32 ethtool_op_get_link(struct net_device *dev)
 
 u32 ethtool_op_get_tx_csum(struct net_device *dev)
 {
-       return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0;
+       return (dev->features & NETIF_F_ALL_CSUM) != 0;
 }
 
 int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
@@ -551,9 +551,7 @@ static int ethtool_set_sg(struct net_device *dev, char __user *useraddr)
                return -EFAULT;
 
        if (edata.data && 
-           !(dev->features & (NETIF_F_IP_CSUM |
-                              NETIF_F_NO_CSUM |
-                              NETIF_F_HW_CSUM)))
+           !(dev->features & NETIF_F_ALL_CSUM))
                return -EINVAL;
 
        return __ethtool_set_sg(dev, edata.data);
@@ -591,7 +589,7 @@ static int ethtool_set_tso(struct net_device *dev, char __user *useraddr)
 
 static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr)
 {
-       struct ethtool_value edata = { ETHTOOL_GTSO };
+       struct ethtool_value edata = { ETHTOOL_GUFO };
 
        if (!dev->ethtool_ops->get_ufo)
                return -EOPNOTSUPP;
@@ -600,6 +598,7 @@ static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr)
                 return -EFAULT;
        return 0;
 }
+
 static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
 {
        struct ethtool_value edata;
index e8e05cebd95adaeee351c84144d6c51250b503e9..9cb781830380242cc16b9204cfdb103381dc4234 100644 (file)
@@ -273,24 +273,21 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
 
        do {
                npinfo->tries--;
-               spin_lock(&np->dev->xmit_lock);
-               np->dev->xmit_lock_owner = smp_processor_id();
+               netif_tx_lock(np->dev);
 
                /*
                 * network drivers do not expect to be called if the queue is
                 * stopped.
                 */
                if (netif_queue_stopped(np->dev)) {
-                       np->dev->xmit_lock_owner = -1;
-                       spin_unlock(&np->dev->xmit_lock);
+                       netif_tx_unlock(np->dev);
                        netpoll_poll(np);
                        udelay(50);
                        continue;
                }
 
                status = np->dev->hard_start_xmit(skb, np->dev);
-               np->dev->xmit_lock_owner = -1;
-               spin_unlock(&np->dev->xmit_lock);
+               netif_tx_unlock(np->dev);
 
                /* success */
                if(!status) {
index c23e9c06ee237203e792f421aabf6a3005996009..67ed14ddabd2b83a32bef68b002c67298bcc2f42 100644 (file)
@@ -2897,7 +2897,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
                }
        }
 
-       spin_lock_bh(&odev->xmit_lock);
+       netif_tx_lock_bh(odev);
        if (!netif_queue_stopped(odev)) {
 
                atomic_inc(&(pkt_dev->skb->users));
@@ -2942,7 +2942,7 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
                pkt_dev->next_tx_ns = 0;
        }
 
-       spin_unlock_bh(&odev->xmit_lock);
+       netif_tx_unlock_bh(odev);
 
        /* If pkt_dev->count is zero, then run forever */
        if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
index fb3770f9c09405f3dce34e2b429e74d4a9761508..bb7210f4005e1a781908238d0bfbbb30a42838a1 100644 (file)
@@ -464,7 +464,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
        n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
        C(input_dev);
 #endif
-
+       skb_copy_secmark(n, skb);
 #endif
        C(truesize);
        atomic_set(&n->users, 1);
@@ -526,6 +526,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 #endif
        new->tc_index   = old->tc_index;
 #endif
+       skb_copy_secmark(new, old);
        atomic_set(&new->users, 1);
        skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size;
        skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs;
@@ -800,12 +801,10 @@ struct sk_buff *skb_pad(struct sk_buff *skb, int pad)
        return nskb;
 }      
  
-/* Trims skb to length len. It can change skb pointers, if "realloc" is 1.
- * If realloc==0 and trimming is impossible without change of data,
- * it is BUG().
+/* Trims skb to length len. It can change skb pointers.
  */
 
-int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc)
+int ___pskb_trim(struct sk_buff *skb, unsigned int len)
 {
        int offset = skb_headlen(skb);
        int nfrags = skb_shinfo(skb)->nr_frags;
@@ -815,7 +814,6 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc)
                int end = offset + skb_shinfo(skb)->frags[i].size;
                if (end > len) {
                        if (skb_cloned(skb)) {
-                               BUG_ON(!realloc);
                                if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
                                        return -ENOMEM;
                        }
index ed2afdb9ea2df7317794e31a1f034a605e0d9c7d..5d820c3766530a991056050d23be7013107ae20c 100644 (file)
@@ -832,6 +832,9 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
                atomic_set(&newsk->sk_omem_alloc, 0);
                skb_queue_head_init(&newsk->sk_receive_queue);
                skb_queue_head_init(&newsk->sk_write_queue);
+#ifdef CONFIG_NET_DMA
+               skb_queue_head_init(&newsk->sk_async_wait_queue);
+#endif
 
                rwlock_init(&newsk->sk_dst_lock);
                rwlock_init(&newsk->sk_callback_lock);
@@ -1383,6 +1386,9 @@ void sock_init_data(struct socket *sock, struct sock *sk)
        skb_queue_head_init(&sk->sk_receive_queue);
        skb_queue_head_init(&sk->sk_write_queue);
        skb_queue_head_init(&sk->sk_error_queue);
+#ifdef CONFIG_NET_DMA
+       skb_queue_head_init(&sk->sk_async_wait_queue);
+#endif
 
        sk->sk_send_head        =       NULL;
 
diff --git a/net/core/user_dma.c b/net/core/user_dma.c
new file mode 100644 (file)
index 0000000..b7c98db
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Portions based on net/core/datagram.c and copyrighted by their authors.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 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 COPYING.
+ */
+
+/*
+ * This code allows the net stack to make use of a DMA engine for
+ * skb to iovec copies.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/socket.h>
+#include <linux/rtnetlink.h> /* for BUG_TRAP */
+#include <net/tcp.h>
+
+#define NET_DMA_DEFAULT_COPYBREAK 4096
+
+int sysctl_tcp_dma_copybreak = NET_DMA_DEFAULT_COPYBREAK;
+
+/**
+ *     dma_skb_copy_datagram_iovec - Copy a datagram to an iovec.
+ *     @skb - buffer to copy
+ *     @offset - offset in the buffer to start copying from
+ *     @iovec - io vector to copy to
+ *     @len - amount of data to copy from buffer to iovec
+ *     @pinned_list - locked iovec buffer data
+ *
+ *     Note: the iovec is modified during the copy.
+ */
+int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
+                       struct sk_buff *skb, int offset, struct iovec *to,
+                       size_t len, struct dma_pinned_list *pinned_list)
+{
+       int start = skb_headlen(skb);
+       int i, copy = start - offset;
+       dma_cookie_t cookie = 0;
+
+       /* Copy header. */
+       if (copy > 0) {
+               if (copy > len)
+                       copy = len;
+               cookie = dma_memcpy_to_iovec(chan, to, pinned_list,
+                                           skb->data + offset, copy);
+               if (cookie < 0)
+                       goto fault;
+               len -= copy;
+               if (len == 0)
+                       goto end;
+               offset += copy;
+       }
+
+       /* Copy paged appendix. Hmm... why does this look so complicated? */
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               int end;
+
+               BUG_TRAP(start <= offset + len);
+
+               end = start + skb_shinfo(skb)->frags[i].size;
+               copy = end - offset;
+               if ((copy = end - offset) > 0) {
+                       skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+                       struct page *page = frag->page;
+
+                       if (copy > len)
+                               copy = len;
+
+                       cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, page,
+                                       frag->page_offset + offset - start, copy);
+                       if (cookie < 0)
+                               goto fault;
+                       len -= copy;
+                       if (len == 0)
+                               goto end;
+                       offset += copy;
+               }
+               start = end;
+       }
+
+       if (skb_shinfo(skb)->frag_list) {
+               struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+               for (; list; list = list->next) {
+                       int end;
+
+                       BUG_TRAP(start <= offset + len);
+
+                       end = start + list->len;
+                       copy = end - offset;
+                       if (copy > 0) {
+                               if (copy > len)
+                                       copy = len;
+                               cookie = dma_skb_copy_datagram_iovec(chan, list,
+                                               offset - start, to, copy,
+                                               pinned_list);
+                               if (cookie < 0)
+                                       goto fault;
+                               len -= copy;
+                               if (len == 0)
+                                       goto end;
+                               offset += copy;
+                       }
+                       start = end;
+               }
+       }
+
+end:
+       if (!len) {
+               skb->dma_cookie = cookie;
+               return cookie;
+       }
+
+fault:
+       return -EFAULT;
+}
index b5981e5f6b0021294d9c16d14f581964a9e93bc2..8c211c58893b2a6de115110743ed33a88befbe4d 100644 (file)
@@ -452,6 +452,7 @@ found:
                                              (unsigned long long)
                                              avr->dccpavr_ack_ackno);
                                dccp_ackvec_throw_record(av, avr);
+                               break;
                        }
                        /*
                         * If it wasn't received, continue scanning... we might
index 2e0ee8355c415d24d13644e20ecb6d8e837d10c1..5317fd3e66910ca25f5d73bf9dbd63e7fe400183 100644 (file)
@@ -719,7 +719,7 @@ int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                }
                dccp_pr_debug("packet_type=%s\n",
                              dccp_packet_name(dh->dccph_type));
-               sk_eat_skb(sk, skb);
+               sk_eat_skb(sk, skb, 0);
 verify_sock_status:
                if (sock_flag(sk, SOCK_DONE)) {
                        len = 0;
@@ -773,7 +773,7 @@ verify_sock_status:
                }
        found_fin_ok:
                if (!(flags & MSG_PEEK))
-                       sk_eat_skb(sk, skb);
+                       sk_eat_skb(sk, skb, 0);
                break;
        } while (1);
 out:
index 547523b41c8168e6c9b67dd25964cfe1aeccfc4c..a2ba9db1c37643aa5fd6d22359661a5564f3c9b0 100644 (file)
@@ -801,8 +801,7 @@ got_it:
                 * We linearize everything except data segments here.
                 */
                if (cb->nsp_flags & ~0x60) {
-                       if (unlikely(skb_is_nonlinear(skb)) &&
-                           skb_linearize(skb, GFP_ATOMIC) != 0)
+                       if (unlikely(skb_linearize(skb)))
                                goto free_out;
                }
 
index e172cf98d7fc3bdfda1831f06fed18fa20e097c6..5abf7057af00db705d4ec019a2c670312d6cdd5c 100644 (file)
@@ -629,8 +629,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
                        padlen);
 
         if (flags & DN_RT_PKT_CNTL) {
-               if (unlikely(skb_is_nonlinear(skb)) &&
-                   skb_linearize(skb, GFP_ATOMIC) != 0)
+               if (unlikely(skb_linearize(skb)))
                        goto dump_it;
 
                 switch(flags & DN_RT_CNTL_MSK) {
index 69b74a9a0fc3a3cb0908782fd77e14e3cc2a885e..7cef1d8ace2738145978eef5c1cbeae226656db0 100644 (file)
@@ -3,6 +3,5 @@
 #
 
 obj-y                                  += eth.o
-obj-$(CONFIG_SYSCTL)                   += sysctl_net_ether.o
 obj-$(subst m,y,$(CONFIG_IPX))         += pe2.o
 obj-$(subst m,y,$(CONFIG_ATALK))       += pe2.o
diff --git a/net/ethernet/sysctl_net_ether.c b/net/ethernet/sysctl_net_ether.c
deleted file mode 100644 (file)
index 66b39fc..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* -*- linux-c -*-
- * sysctl_net_ether.c: sysctl interface to net Ethernet subsystem.
- *
- * Begun April 1, 1996, Mike Shaver.
- * Added /proc/sys/net/ether directory entry (empty =) ). [MS]
- */
-
-#include <linux/mm.h>
-#include <linux/sysctl.h>
-#include <linux/if_ether.h>
-
-ctl_table ether_table[] = {
-       {0}
-};
index 93def94c1b3253e6fca9c960f39be0c5b2404998..3fa5df2e1f0baeceb229fb95a6bd6dd0c2ff081c 100644 (file)
@@ -501,8 +501,11 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
 static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
 {
        struct ieee80211_hdr_4addr *hdr11;
+       u16 stype;
 
        hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
+       stype  = WLAN_FC_GET_STYPE(le16_to_cpu(hdr11->frame_ctl));
+
        switch (le16_to_cpu(hdr11->frame_ctl) &
                (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
        case IEEE80211_FCTL_TODS:
@@ -523,7 +526,13 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
                break;
        }
 
-       hdr[12] = 0;            /* priority */
+       if (stype & IEEE80211_STYPE_QOS_DATA) {
+               const struct ieee80211_hdr_3addrqos *qoshdr =
+                       (struct ieee80211_hdr_3addrqos *)skb->data;
+               hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID;
+       } else
+               hdr[12] = 0;            /* priority */
+
        hdr[13] = hdr[14] = hdr[15] = 0;        /* reserved */
 }
 
index 604b7b0097bce98dd71f120b77a86ad9363fa438..2bf567fd5a17143a096518def05a21cf2f5ccdbc 100644 (file)
@@ -369,7 +369,6 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 
        /* Put this code here so that we avoid duplicating it in all
         * Rx paths. - Jean II */
-#ifdef CONFIG_WIRELESS_EXT
 #ifdef IW_WIRELESS_SPY         /* defined in iw_handler.h */
        /* If spy monitoring on */
        if (ieee->spy_data.spy_number > 0) {
@@ -398,7 +397,6 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
                wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
        }
 #endif                         /* IW_WIRELESS_SPY */
-#endif                         /* CONFIG_WIRELESS_EXT */
 
 #ifdef NOT_YET
        hostap_update_rx_stats(local->ap, hdr, rx_stats);
@@ -1692,8 +1690,8 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                                     WLAN_FC_GET_STYPE(le16_to_cpu
                                                       (header->frame_ctl)));
 
-               IEEE80211_WARNING("%s: IEEE80211_REASSOC_REQ received\n",
-                                 ieee->dev->name);
+               IEEE80211_DEBUG_MGMT("%s: IEEE80211_REASSOC_REQ received\n",
+                                    ieee->dev->name);
                if (ieee->handle_reassoc_request != NULL)
                        ieee->handle_reassoc_request(ieee->dev,
                                                    (struct ieee80211_reassoc_request *)
@@ -1705,8 +1703,8 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                                     WLAN_FC_GET_STYPE(le16_to_cpu
                                                       (header->frame_ctl)));
 
-               IEEE80211_WARNING("%s: IEEE80211_ASSOC_REQ received\n",
-                                 ieee->dev->name);
+               IEEE80211_DEBUG_MGMT("%s: IEEE80211_ASSOC_REQ received\n",
+                                    ieee->dev->name);
                if (ieee->handle_assoc_request != NULL)
                        ieee->handle_assoc_request(ieee->dev);
                break;
@@ -1722,10 +1720,10 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
                IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
                                     WLAN_FC_GET_STYPE(le16_to_cpu
                                                       (header->frame_ctl)));
-               IEEE80211_WARNING("%s: Unknown management packet: %d\n",
-                                 ieee->dev->name,
-                                 WLAN_FC_GET_STYPE(le16_to_cpu
-                                                   (header->frame_ctl)));
+               IEEE80211_DEBUG_MGMT("%s: Unknown management packet: %d\n",
+                                    ieee->dev->name,
+                                    WLAN_FC_GET_STYPE(le16_to_cpu
+                                                      (header->frame_ctl)));
                break;
        }
 }
index 8b4332f533945c4109d31debed4aebcbf310a9f9..6a5de1b84459c147864406522e7c682a03e473ca 100644 (file)
@@ -220,13 +220,43 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
        return txb;
 }
 
+static int ieee80211_classify(struct sk_buff *skb)
+{
+       struct ethhdr *eth;
+       struct iphdr *ip;
+
+       eth = (struct ethhdr *)skb->data;
+       if (eth->h_proto != __constant_htons(ETH_P_IP))
+               return 0;
+
+       ip = skb->nh.iph;
+       switch (ip->tos & 0xfc) {
+       case 0x20:
+               return 2;
+       case 0x40:
+               return 1;
+       case 0x60:
+               return 3;
+       case 0x80:
+               return 4;
+       case 0xa0:
+               return 5;
+       case 0xc0:
+               return 6;
+       case 0xe0:
+               return 7;
+       default:
+               return 0;
+       }
+}
+
 /* Incoming skb is converted to a txb which consists of
  * a block of 802.11 fragment packets (stored as skbs) */
 int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ieee80211_device *ieee = netdev_priv(dev);
        struct ieee80211_txb *txb = NULL;
-       struct ieee80211_hdr_3addr *frag_hdr;
+       struct ieee80211_hdr_3addrqos *frag_hdr;
        int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
            rts_required;
        unsigned long flags;
@@ -234,9 +264,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
        int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
        int bytes, fc, hdr_len;
        struct sk_buff *skb_frag;
-       struct ieee80211_hdr_3addr header = {   /* Ensure zero initialized */
+       struct ieee80211_hdr_3addrqos header = {/* Ensure zero initialized */
                .duration_id = 0,
-               .seq_ctl = 0
+               .seq_ctl = 0,
+               .qos_ctl = 0
        };
        u8 dest[ETH_ALEN], src[ETH_ALEN];
        struct ieee80211_crypt_data *crypt;
@@ -282,12 +313,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
        memcpy(dest, skb->data, ETH_ALEN);
        memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
 
-       /* Advance the SKB to the start of the payload */
-       skb_pull(skb, sizeof(struct ethhdr));
-
-       /* Determine total amount of storage required for TXB packets */
-       bytes = skb->len + SNAP_SIZE + sizeof(u16);
-
        if (host_encrypt || host_build_iv)
                fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
                    IEEE80211_FCTL_PROTECTED;
@@ -306,9 +331,23 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
                memcpy(header.addr2, src, ETH_ALEN);
                memcpy(header.addr3, ieee->bssid, ETH_ALEN);
        }
-       header.frame_ctl = cpu_to_le16(fc);
        hdr_len = IEEE80211_3ADDR_LEN;
 
+       if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) {
+               fc |= IEEE80211_STYPE_QOS_DATA;
+               hdr_len += 2;
+
+               skb->priority = ieee80211_classify(skb);
+               header.qos_ctl |= skb->priority & IEEE80211_QCTL_TID;
+       }
+       header.frame_ctl = cpu_to_le16(fc);
+
+       /* Advance the SKB to the start of the payload */
+       skb_pull(skb, sizeof(struct ethhdr));
+
+       /* Determine total amount of storage required for TXB packets */
+       bytes = skb->len + SNAP_SIZE + sizeof(u16);
+
        /* Encrypt msdu first on the whole data packet. */
        if ((host_encrypt || host_encrypt_msdu) &&
            crypt && crypt->ops && crypt->ops->encrypt_msdu) {
@@ -402,7 +441,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
        if (rts_required) {
                skb_frag = txb->fragments[0];
                frag_hdr =
-                   (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
+                   (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
 
                /*
                 * Set header frame_ctl to the RTS.
@@ -433,7 +472,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
                                    crypt->ops->extra_mpdu_prefix_len);
 
                frag_hdr =
-                   (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
+                   (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
                memcpy(frag_hdr, &header, hdr_len);
 
                /* If this is not the last fragment, then add the MOREFRAGS
@@ -516,7 +555,8 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 /* Incoming 802.11 strucure is converted to a TXB
  * a block of 802.11 fragment packets (stored as skbs) */
 int ieee80211_tx_frame(struct ieee80211_device *ieee,
-                      struct ieee80211_hdr *frame, int len)
+                      struct ieee80211_hdr *frame, int hdr_len, int total_len,
+                      int encrypt_mpdu)
 {
        struct ieee80211_txb *txb = NULL;
        unsigned long flags;
@@ -526,6 +566,9 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
 
        spin_lock_irqsave(&ieee->lock, flags);
 
+       if (encrypt_mpdu && !ieee->sec.encrypt)
+               encrypt_mpdu = 0;
+
        /* If there is no driver handler to take the TXB, dont' bother
         * creating it... */
        if (!ieee->hard_start_xmit) {
@@ -533,32 +576,41 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
                goto success;
        }
 
-       if (unlikely(len < 24)) {
+       if (unlikely(total_len < 24)) {
                printk(KERN_WARNING "%s: skb too small (%d).\n",
-                      ieee->dev->name, len);
+                      ieee->dev->name, total_len);
                goto success;
        }
 
+       if (encrypt_mpdu)
+               frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+
        /* When we allocate the TXB we allocate enough space for the reserve
         * and full fragment bytes (bytes_per_frag doesn't include prefix,
         * postfix, header, FCS, etc.) */
-       txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC);
+       txb = ieee80211_alloc_txb(1, total_len, ieee->tx_headroom, GFP_ATOMIC);
        if (unlikely(!txb)) {
                printk(KERN_WARNING "%s: Could not allocate TXB\n",
                       ieee->dev->name);
                goto failed;
        }
        txb->encrypted = 0;
-       txb->payload_size = len;
+       txb->payload_size = total_len;
 
        skb_frag = txb->fragments[0];
 
-       memcpy(skb_put(skb_frag, len), frame, len);
+       memcpy(skb_put(skb_frag, total_len), frame, total_len);
 
        if (ieee->config &
            (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
                skb_put(skb_frag, 4);
 
+       /* To avoid overcomplicating things, we do the corner-case frame
+        * encryption in software. The only real situation where encryption is
+        * needed here is during software-based shared key authentication. */
+       if (encrypt_mpdu)
+               ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
+
       success:
        spin_unlock_irqrestore(&ieee->lock, flags);
 
index b885fd189403e8da67ae0dd967b94a7f45ae9df9..a78c4f845f66a88f3a2f95fb59adc8790c6af723 100644 (file)
@@ -50,7 +50,8 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
        char *p;
        struct iw_event iwe;
        int i, j;
-       u8 max_rate, rate;
+       char *current_val;      /* For rates */
+       u8 rate;
 
        /* First entry *MUST* be the AP MAC address */
        iwe.cmd = SIOCGIWAP;
@@ -107,9 +108,13 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
        start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
 
        /* Add basic and extended rates */
-       max_rate = 0;
-       p = custom;
-       p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
+       /* Rate : stuffing multiple values in a single event require a bit
+        * more of magic - Jean II */
+       current_val = start + IW_EV_LCP_LEN;
+       iwe.cmd = SIOCGIWRATE;
+       /* Those two flags are ignored... */
+       iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
        for (i = 0, j = 0; i < network->rates_len;) {
                if (j < network->rates_ex_len &&
                    ((network->rates_ex[j] & 0x7F) <
@@ -117,28 +122,21 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
                        rate = network->rates_ex[j++] & 0x7F;
                else
                        rate = network->rates[i++] & 0x7F;
-               if (rate > max_rate)
-                       max_rate = rate;
-               p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-                             "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+               /* Bit rate given in 500 kb/s units (+ 0x80) */
+               iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
+               /* Add new value to event */
+               current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);
        }
        for (; j < network->rates_ex_len; j++) {
                rate = network->rates_ex[j] & 0x7F;
-               p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-                             "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
-               if (rate > max_rate)
-                       max_rate = rate;
+               /* Bit rate given in 500 kb/s units (+ 0x80) */
+               iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
+               /* Add new value to event */
+               current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);
        }
-
-       iwe.cmd = SIOCGIWRATE;
-       iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-       iwe.u.bitrate.value = max_rate * 500000;
-       start = iwe_stream_add_event(start, stop, &iwe, IW_EV_PARAM_LEN);
-
-       iwe.cmd = IWEVCUSTOM;
-       iwe.u.data.length = p - custom;
-       if (iwe.u.data.length)
-               start = iwe_stream_add_point(start, stop, &iwe, custom);
+       /* Check if we added any rate */
+       if((current_val - start) > IW_EV_LCP_LEN)
+               start = current_val;
 
        /* Add quality statistics */
        iwe.cmd = IWEVQUAL;
@@ -505,7 +503,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
        len = sec->key_sizes[key];
        memcpy(keybuf, sec->keys[key], len);
 
-       erq->length = (len >= 0 ? len : 0);
+       erq->length = len;
        erq->flags |= IW_ENCODE_ENABLED;
 
        if (ieee->open_wep)
index f2a27cc6ecb1fc653fa7643e543cd1e7dfb4a3f8..2811651cb13404b114f09b23ea8a38124a18953e 100644 (file)
@@ -2,6 +2,7 @@ config IEEE80211_SOFTMAC
        tristate "Software MAC add-on to the IEEE 802.11 networking stack"
        depends on IEEE80211 && EXPERIMENTAL
        select WIRELESS_EXT
+       select IEEE80211_CRYPT_WEP
        ---help---
        This option enables the hardware independent software MAC addon
        for the IEEE 802.11 networking stack.
index 57ea9f6f465c50679ff62af18dec5f0dc9f8b42f..5e9a90651d04f5433225357dad60ac5c396218d2 100644 (file)
@@ -82,51 +82,52 @@ ieee80211softmac_assoc_timeout(void *d)
        ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
 }
 
-/* Sends out a disassociation request to the desired AP */
-static void
-ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
+void
+ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
 {
        unsigned long flags;
+
+       spin_lock_irqsave(&mac->lock, flags);
+       if (mac->associnfo.associating)
+               cancel_delayed_work(&mac->associnfo.timeout);
+
+       netif_carrier_off(mac->dev);
+
+       mac->associated = 0;
+       mac->associnfo.bssvalid = 0;
+       mac->associnfo.associating = 0;
+       ieee80211softmac_init_txrates(mac);
+       ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
+       spin_unlock_irqrestore(&mac->lock, flags);
+}
+
+/* Sends out a disassociation request to the desired AP */
+void
+ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason)
+{
        struct ieee80211softmac_network *found;
 
        if (mac->associnfo.bssvalid && mac->associated) {
                found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
                if (found)
                        ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
-       } else if (mac->associnfo.associating) {
-               cancel_delayed_work(&mac->associnfo.timeout);
        }
 
-       /* Change our state */
-       spin_lock_irqsave(&mac->lock, flags);
-       /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
-       mac->associated = 0;
-       mac->associnfo.associating = 0;
-       ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
-       spin_unlock_irqrestore(&mac->lock, flags);
+       ieee80211softmac_disassoc(mac);
 }
 
 static inline int
 we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len)
 {
-       int idx, search, found;
-       u8 rate, search_rate;
+       int idx;
+       u8 rate;
 
        for (idx = 0; idx < (from_len); idx++) {
                rate = (from)[idx];
                if (!(rate & IEEE80211_BASIC_RATE_MASK))
                        continue;
-               found = 0;
                rate &= ~IEEE80211_BASIC_RATE_MASK;
-               for (search = 0; search < mac->ratesinfo.count; search++) {
-                       search_rate = mac->ratesinfo.rates[search];
-                       search_rate &= ~IEEE80211_BASIC_RATE_MASK;
-                       if (rate == search_rate) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found)
+               if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
                        return 0;
        }
        return 1;
@@ -163,12 +164,28 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne
 }
 
 static void
-ieee80211softmac_assoc_notify(struct net_device *dev, void *context)
+ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context)
 {
        struct ieee80211softmac_device *mac = ieee80211_priv(dev);
        ieee80211softmac_assoc_work((void*)mac);
 }
 
+static void
+ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void *context)
+{
+       struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+
+       switch (event_type) {
+       case IEEE80211SOFTMAC_EVENT_AUTHENTICATED:
+               ieee80211softmac_assoc_work((void*)mac);
+               break;
+       case IEEE80211SOFTMAC_EVENT_AUTH_FAILED:
+       case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT:
+               ieee80211softmac_disassoc(mac);
+               break;
+       }
+}
+
 /* This function is called to handle userspace requests (asynchronously) */
 void
 ieee80211softmac_assoc_work(void *d)
@@ -176,14 +193,18 @@ ieee80211softmac_assoc_work(void *d)
        struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
        struct ieee80211softmac_network *found = NULL;
        struct ieee80211_network *net = NULL, *best = NULL;
+       int bssvalid;
        unsigned long flags;
-       
+
+       /* ieee80211_disassoc might clear this */
+       bssvalid = mac->associnfo.bssvalid;
+
        /* meh */
        if (mac->associated)
-               ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
+               ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
 
        /* try to find the requested network in our list, if we found one already */
-       if (mac->associnfo.bssvalid || mac->associnfo.bssfixed)
+       if (bssvalid || mac->associnfo.bssfixed)
                found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);       
        
        /* Search the ieee80211 networks for this network if we didn't find it by bssid,
@@ -244,7 +265,7 @@ ieee80211softmac_assoc_work(void *d)
                         * Maybe we can hope to have more memory after scanning finishes ;)
                         */
                        dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
-                       ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify, NULL);
+                       ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
                        if (ieee80211softmac_start_scan(mac))
                                dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
                        return;
@@ -279,7 +300,7 @@ ieee80211softmac_assoc_work(void *d)
                 * otherwise adding the notification would be racy. */
                if (!ieee80211softmac_auth_req(mac, found)) {
                        dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n");
-                       ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify, NULL, GFP_KERNEL);
+                       ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
                } else {
                        printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
                        ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
@@ -297,6 +318,9 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
        struct ieee80211softmac_network *net)
 {
        mac->associnfo.associating = 0;
+       mac->associnfo.supported_rates = net->supported_rates;
+       ieee80211softmac_recalc_txrates(mac);
+
        mac->associated = 1;
        if (mac->set_bssid_filter)
                mac->set_bssid_filter(mac->dev, net->bssid);
@@ -380,7 +404,6 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
                                 struct ieee80211_disassoc *disassoc)
 {
        struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-       unsigned long flags;
 
        if (unlikely(!mac->running))
                return -ENODEV;
@@ -392,14 +415,11 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
                return 0;
 
        dprintk(KERN_INFO PFX "got disassoc frame\n");
-       netif_carrier_off(dev);
-       spin_lock_irqsave(&mac->lock, flags);
-       mac->associnfo.bssvalid = 0;
-       mac->associated = 0;
-       ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
+       ieee80211softmac_disassoc(mac);
+
+       /* try to reassociate */
        schedule_work(&mac->associnfo.work);
-       spin_unlock_irqrestore(&mac->lock, flags);
-       
+
        return 0;
 }
 
index 06e332624665e8d456c505a376788993451d4ccb..90b8484e509b8505cae70e6e61357a52bc1fedda 100644 (file)
@@ -107,6 +107,7 @@ ieee80211softmac_auth_queue(void *data)
        printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid));
        /* Remove this item from the queue */
        spin_lock_irqsave(&mac->lock, flags);
+       net->authenticating = 0;
        ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
        cancel_delayed_work(&auth->work); /* just to make sure... */
        list_del(&auth->list);
@@ -212,13 +213,13 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
                        aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; 
                        spin_unlock_irqrestore(&mac->lock, flags);
 
-                       /* Switch to correct channel for this network */
-                       mac->set_channel(mac->dev, net->channel);
-                       
-                       /* Send our response (How to encrypt?) */
+                       /* Send our response */
                        ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
-                       break;
+                       return 0;
                case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
+                       kfree(net->challenge);
+                       net->challenge = NULL;
+                       net->challenge_len = 0;
                        /* Check the status code of the response */
                        switch(auth->status) {
                        case WLAN_STATUS_SUCCESS:
@@ -229,6 +230,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
                                spin_unlock_irqrestore(&mac->lock, flags);
                                printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n", 
                                        MAC_ARG(net->bssid));
+                               ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
                                break;
                        default:
                                printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n", 
@@ -279,6 +281,9 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
        struct list_head *list_ptr;
        unsigned long flags;
 
+       /* deauthentication implies disassociation */
+       ieee80211softmac_disassoc(mac);
+
        /* Lock and reset status flags */
        spin_lock_irqsave(&mac->lock, flags);
        net->authenticating = 0;
index 8cc8f3f0f8e73d3809556a6cb30c3c8cf588c111..f34fa2ef666b5fa56247f060bae06a2d94f7f06e 100644 (file)
@@ -38,7 +38,8 @@
  * The event context is private and can only be used from
  * within this module. Its meaning varies with the event
  * type:
- *  SCAN_FINISHED:     no special meaning
+ *  SCAN_FINISHED,
+ *  DISASSOCIATED:     NULL
  *  ASSOCIATED,
  *  ASSOCIATE_FAILED,
  *  ASSOCIATE_TIMEOUT,
  */
 
 static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
-       "scan finished",
-       "associated",
+       NULL, /* scan finished */
+       NULL, /* associated */
        "associating failed",
        "associating timed out",
        "authenticated",
        "authenticating failed",
        "authenticating timed out",
        "associating failed because no suitable network was found",
-       "disassociated",
+       NULL, /* disassociated */
 };
 
 
@@ -77,7 +78,7 @@ ieee80211softmac_notify_callback(void *d)
        struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
        kfree(d);
        
-       event.fun(event.mac->dev, event.context);
+       event.fun(event.mac->dev, event.event_type, event.context);
 }
 
 int
@@ -136,30 +137,24 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve
                int we_event;
                char *msg = NULL;
 
+               memset(&wrqu, '\0', sizeof (union iwreq_data));
+
                switch(event) {
                case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
                        network = (struct ieee80211softmac_network *)event_ctx;
-                       wrqu.data.length = 0;
-                       wrqu.data.flags = 0;
                        memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
-                       wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-                       we_event = SIOCGIWAP;
-                       break;
+                       /* fall through */
                case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
-                       wrqu.data.length = 0;
-                       wrqu.data.flags = 0;
-                       memset(&wrqu, '\0', sizeof (union iwreq_data));
                        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
                        we_event = SIOCGIWAP;
                        break;
                case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
-                       wrqu.data.length = 0;
-                       wrqu.data.flags = 0;
-                       memset(&wrqu, '\0', sizeof (union iwreq_data));
                        we_event = SIOCGIWSCAN;
                        break;
                default:
                        msg = event_descriptions[event];
+                       if (!msg)
+                               msg = "SOFTMAC EVENT BUG";
                        wrqu.data.length = strlen(msg);
                        we_event = IWEVCUSTOM;
                        break;
@@ -172,6 +167,9 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve
                        if ((eventptr->event_type == event || eventptr->event_type == -1)
                                && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
                                list_del(&eventptr->list);
+                               /* User may have subscribed to ANY event, so
+                                * we tell them which event triggered it. */
+                               eventptr->event_type = event;
                                schedule_work(&eventptr->work);
                        }
                }
index cc6cd56c85b100af93a7216442c4a6d9ade20e36..09541611e48ceec609d8c66db1173f757676ccc7 100644 (file)
@@ -149,6 +149,56 @@ ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
         * shouldn't the sequence number be in ieee80211? */
 }
 
+static u16
+ieee80211softmac_capabilities(struct ieee80211softmac_device *mac,
+       struct ieee80211softmac_network *net)
+{
+       u16 capability = 0;
+
+       /* ESS and IBSS bits are set according to the current mode */
+       switch (mac->ieee->iw_mode) {
+       case IW_MODE_INFRA:
+               capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+               break;
+       case IW_MODE_ADHOC:
+               capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
+               break;
+       case IW_MODE_AUTO:
+               capability = net->capabilities &
+                       (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
+               break;
+       default:
+               /* bleh. we don't ever go to these modes */
+               printk(KERN_ERR PFX "invalid iw_mode!\n");
+               break;
+       }
+
+       /* CF Pollable / CF Poll Request */
+       /* Needs to be implemented, for now, the 0's == not supported */
+
+       /* Privacy Bit */
+       capability |= mac->ieee->sec.level ?
+               cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
+
+       /* Short Preamble */
+       /* Always supported: we probably won't ever be powering devices which
+        * dont support this... */
+       capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+
+       /* PBCC */
+       /* Not widely used */
+
+       /* Channel Agility */
+       /* Not widely used */
+
+       /* Short Slot */
+       /* Will be implemented later */
+
+       /* DSSS-OFDM */
+       /* Not widely used */
+
+       return capability;
+}
 
 /*****************************************************************************
  * Create Management packets
@@ -179,27 +229,6 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
                return 0;
        ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
 
-       /* Fill in capability Info */
-       switch (mac->ieee->iw_mode) {
-       case IW_MODE_INFRA:
-               (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
-               break;
-       case IW_MODE_ADHOC:
-               (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
-               break;
-       case IW_MODE_AUTO:
-               (*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
-               break;
-       default:
-               /* bleh. we don't ever go to these modes */
-               printk(KERN_ERR PFX "invalid iw_mode!\n");
-               break;
-       }
-       /* Need to add this
-       (*pkt)->capability |= mac->ieee->short_slot ? 
-                       cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
-        */
-       (*pkt)->capability |= mac->ieee->sec.level ? cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
        /* Fill in Listen Interval (?) */
        (*pkt)->listen_interval = cpu_to_le16(10);
        
@@ -239,17 +268,9 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
                return 0;
        ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
 
-       /* Fill in capability Info */
-       (*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ? 
-                               cpu_to_le16(WLAN_CAPABILITY_ESS) :
-                               cpu_to_le16(WLAN_CAPABILITY_IBSS);
-       /*
-       (*pkt)->capability |= mac->ieee->short_slot ? 
-                       cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
-        */
-       (*pkt)->capability |= mac->ieee->sec.level ?
-                       cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
-               
+       /* Fill in the capabilities */
+       (*pkt)->capability = ieee80211softmac_capabilities(mac, net);
+
        /* Fill in Listen Interval (?) */
        (*pkt)->listen_interval = cpu_to_le16(10);
        /* Fill in the current AP MAC */
@@ -268,26 +289,27 @@ ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
 static u32
 ieee80211softmac_auth(struct ieee80211_auth **pkt, 
        struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
-       u16 transaction, u16 status)
+       u16 transaction, u16 status, int *encrypt_mpdu)
 {
        u8 *data;
+       int auth_mode = mac->ieee->sec.auth_mode;
+       int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY
+               && transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE);
+
        /* Allocate Packet */
        (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt(
                2 +             /* Auth Algorithm */
                2 +             /* Auth Transaction Seq */
                2 +             /* Status Code */
                 /* Challenge Text IE */
-               mac->ieee->open_wep ? 0 : 
-               1 + 1 + WLAN_AUTH_CHALLENGE_LEN
-       );      
+               is_shared_response ? 0 : 1 + 1 + net->challenge_len
+       );
        if (unlikely((*pkt) == NULL))
                return 0;
        ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
                
        /* Algorithm */
-       (*pkt)->algorithm = mac->ieee->open_wep ? 
-               cpu_to_le16(WLAN_AUTH_OPEN) :
-               cpu_to_le16(WLAN_AUTH_SHARED_KEY);
+       (*pkt)->algorithm = cpu_to_le16(auth_mode);
        /* Transaction */
        (*pkt)->transaction = cpu_to_le16(transaction);
        /* Status */
@@ -295,18 +317,20 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt,
        
        data = (u8 *)(*pkt)->info_element;
        /* Challenge Text */
-       if(!mac->ieee->open_wep){
+       if (is_shared_response) {
                *data = MFIE_TYPE_CHALLENGE;
                data++;
                
                /* Copy the challenge in */
-               // *data = challenge length
-               // data += sizeof(u16);
-               // memcpy(data, challenge, challenge length);
-               // data += challenge length;
-               
-               /* Add the full size to the packet length */
-       }
+               *data = net->challenge_len;
+               data++;
+               memcpy(data, net->challenge, net->challenge_len);
+               data += net->challenge_len;
+
+               /* Make sure this frame gets encrypted with the shared key */
+               *encrypt_mpdu = 1;
+       } else
+               *encrypt_mpdu = 0;
 
        /* Return the packet size */
        return (data - (u8 *)(*pkt));
@@ -396,6 +420,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
 {
        void *pkt = NULL;
        u32 pkt_size = 0;
+       int encrypt_mpdu = 0;
 
        switch(type) {
        case IEEE80211_STYPE_ASSOC_REQ:
@@ -405,7 +430,7 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
                pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
                break;
        case IEEE80211_STYPE_AUTH:
-               pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16));
+               pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu);
                break;
        case IEEE80211_STYPE_DISASSOC:
        case IEEE80211_STYPE_DEAUTH:
@@ -434,52 +459,8 @@ ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
         * or get rid of it alltogether?
         * Does this work for you now?
         */
-       ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, pkt_size);
-
-       kfree(pkt);
-       return 0;
-}
-
-
-/* Create an rts/cts frame */
-static u32
-ieee80211softmac_rts_cts(struct ieee80211_hdr_2addr **pkt,
-       struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, 
-       u32 type)
-{
-       /* Allocate Packet */
-       (*pkt) = kmalloc(IEEE80211_2ADDR_LEN, GFP_ATOMIC);      
-       memset(*pkt, 0, IEEE80211_2ADDR_LEN);
-       if((*pkt) == NULL)
-               return 0;
-       ieee80211softmac_hdr_2addr(mac, (*pkt), type, net->bssid);
-       return IEEE80211_2ADDR_LEN;
-}
-
-
-/* Sends a control packet */
-static int
-ieee80211softmac_send_ctl_frame(struct ieee80211softmac_device *mac,
-       struct ieee80211softmac_network *net, u32 type, u32 arg)
-{
-       void *pkt = NULL;
-       u32 pkt_size = 0;
-       
-       switch(type) {
-       case IEEE80211_STYPE_RTS:
-       case IEEE80211_STYPE_CTS:
-               pkt_size = ieee80211softmac_rts_cts((struct ieee80211_hdr_2addr **)(&pkt), mac, net, type);
-               break;
-       default:
-               printkl(KERN_DEBUG PFX "Unsupported Control Frame type: %i\n", type);
-               return -EINVAL;
-       }
-
-       if(pkt_size == 0)
-               return -ENOMEM;
-       
-       /* Send the packet to the ieee80211 layer for tx */
-       ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *) pkt, pkt_size);
+       ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt,
+               IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu);
 
        kfree(pkt);
        return 0;
index 6252be2c0db9af8a60e35e503e94a2bab0e482f2..4b2e57d12418a901185b6124ac3104dbd0e8d69a 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "ieee80211softmac_priv.h"
 #include <linux/sort.h>
+#include <linux/etherdevice.h>
 
 struct net_device *alloc_ieee80211softmac(int sizeof_priv)
 {
@@ -61,14 +62,6 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
        softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
        softmac->stop_scan = ieee80211softmac_stop_scan_implementation;
 
-       //TODO: The mcast rate has to be assigned dynamically somewhere (in scanning, association. Not sure...)
-       //      It has to be set to the highest rate all stations in the current network can handle.
-       softmac->txrates.mcast_rate = IEEE80211_CCK_RATE_1MB;
-       softmac->txrates.mcast_fallback = IEEE80211_CCK_RATE_1MB;
-       /* This is reassigned in ieee80211softmac_start to sane values. */
-       softmac->txrates.default_rate = IEEE80211_CCK_RATE_1MB;
-       softmac->txrates.default_fallback = IEEE80211_CCK_RATE_1MB;
-
        /* to start with, we can't send anything ... */
        netif_carrier_off(dev);
        
@@ -170,15 +163,82 @@ static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *m
        }
 }
 
-void ieee80211softmac_start(struct net_device *dev)
+int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate)
+{
+       int search;
+       u8 search_rate;
+
+       for (search = 0; search < ri->count; search++) {
+               search_rate = ri->rates[search];
+               search_rate &= ~IEEE80211_BASIC_RATE_MASK;
+               if (rate == search_rate)
+                       return 1;
+       }
+
+       return 0;
+}
+
+/* Finds the highest rate which is:
+ *  1. Present in ri (optionally a basic rate)
+ *  2. Supported by the device
+ *  3. Less than or equal to the user-defined rate
+ */
+static u8 highest_supported_rate(struct ieee80211softmac_device *mac,
+       struct ieee80211softmac_ratesinfo *ri, int basic_only)
+{
+       u8 user_rate = mac->txrates.user_rate;
+       int i;
+
+       if (ri->count == 0) {
+               dprintk(KERN_ERR PFX "empty ratesinfo?\n");
+               return IEEE80211_CCK_RATE_1MB;
+       }
+
+       for (i = ri->count - 1; i >= 0; i--) {
+               u8 rate = ri->rates[i];
+               if (basic_only && !(rate & IEEE80211_BASIC_RATE_MASK))
+                       continue;
+               rate &= ~IEEE80211_BASIC_RATE_MASK;
+               if (rate > user_rate)
+                       continue;
+               if (ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
+                       return rate;
+       }
+
+       /* If we haven't found a suitable rate by now, just trust the user */
+       return user_rate;
+}
+
+void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
+{
+       struct ieee80211softmac_txrates *txrates = &mac->txrates;
+       struct ieee80211softmac_txrates oldrates;
+       u32 change = 0;
+
+       if (mac->txrates_change)
+               oldrates = mac->txrates;
+
+       change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+       txrates->default_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 0);
+
+       change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+       txrates->default_fallback = lower_rate(mac, txrates->default_rate);
+
+       change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
+       txrates->mcast_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 1);
+
+       if (mac->txrates_change)
+               mac->txrates_change(mac->dev, change, &oldrates);
+
+}
+
+void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac)
 {
-       struct ieee80211softmac_device *mac = ieee80211_priv(dev);
        struct ieee80211_device *ieee = mac->ieee;
        u32 change = 0;
+       struct ieee80211softmac_txrates *txrates = &mac->txrates;
        struct ieee80211softmac_txrates oldrates;
 
-       ieee80211softmac_start_check_rates(mac);
-
        /* TODO: We need some kind of state machine to lower the default rates
         *       if we loose too many packets.
         */
@@ -193,22 +253,37 @@ void ieee80211softmac_start(struct net_device *dev)
           more reliable. Note similar logic in
           ieee80211softmac_wx_set_rate() */     
        if (ieee->modulation & IEEE80211_CCK_MODULATION) {
-               mac->txrates.default_rate = IEEE80211_CCK_RATE_11MB;
-               change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-               mac->txrates.default_fallback = IEEE80211_CCK_RATE_5MB;
-               change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+               txrates->user_rate = IEEE80211_CCK_RATE_11MB;
        } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
-               mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB;
-               change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-               mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB;
-               change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+               txrates->user_rate = IEEE80211_OFDM_RATE_54MB;
        } else
                assert(0);
+
+       txrates->default_rate = IEEE80211_CCK_RATE_1MB;
+       change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+
+       txrates->default_fallback = IEEE80211_CCK_RATE_1MB;
+       change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+
+       txrates->mcast_rate = IEEE80211_CCK_RATE_1MB;
+       change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
+
+       txrates->mgt_mcast_rate = IEEE80211_CCK_RATE_1MB;
+       change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
+
        if (mac->txrates_change)
-               mac->txrates_change(dev, change, &oldrates);
+               mac->txrates_change(mac->dev, change, &oldrates);
 
        mac->running = 1;
 }
+
+void ieee80211softmac_start(struct net_device *dev)
+{
+       struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+
+       ieee80211softmac_start_check_rates(mac);
+       ieee80211softmac_init_txrates(mac);
+}
 EXPORT_SYMBOL_GPL(ieee80211softmac_start);
 
 void ieee80211softmac_stop(struct net_device *dev)
index 65d9816c8ecc0569ca63085c2753e5e1e954c014..fa1f8e3acfc07f0370567e026bef2d4379eeeedc 100644 (file)
@@ -116,7 +116,10 @@ ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
        struct ieee80211softmac_essid *essid);
 
 /* Rates related */
+int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate);
 u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta);
+void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac);
+void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac);
 static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
        return ieee80211softmac_lower_rate_delta(mac, rate, 1);
 }
@@ -150,6 +153,8 @@ int ieee80211softmac_handle_disassoc(struct net_device * dev,
 int ieee80211softmac_handle_reassoc_req(struct net_device * dev,
                                        struct ieee80211_reassoc_request * reassoc);
 void ieee80211softmac_assoc_timeout(void *d);
+void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason);
+void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac);
 
 /* some helper functions */
 static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm)
index 27edb2b5581ab535ffd7f79c5b257dcaa5d36324..22aa6199185b4161c820f9ca351a24e0450cda7c 100644 (file)
@@ -211,8 +211,8 @@ ieee80211softmac_wx_set_rate(struct net_device *net_dev,
        if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
                goto out_unlock;
 
-       mac->txrates.default_rate = rate;
-       mac->txrates.default_fallback = lower_rate(mac, rate);
+       mac->txrates.user_rate = rate;
+       ieee80211softmac_recalc_txrates(mac);
        err = 0;
 
 out_unlock:    
@@ -431,3 +431,35 @@ ieee80211softmac_wx_get_genie(struct net_device *dev,
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
 
+int
+ieee80211softmac_wx_set_mlme(struct net_device *dev,
+                            struct iw_request_info *info,
+                            union iwreq_data *wrqu,
+                            char *extra)
+{
+       struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+       struct iw_mlme *mlme = (struct iw_mlme *)extra;
+       u16 reason = cpu_to_le16(mlme->reason_code);
+       struct ieee80211softmac_network *net;
+
+       if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
+               printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
+               return -EINVAL;
+       }
+
+       switch (mlme->cmd) {
+       case IW_MLME_DEAUTH:
+               net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
+               if (!net) {
+                       printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
+                       return -EINVAL;
+               }
+               return ieee80211softmac_deauth_req(mac, net, reason);
+       case IW_MLME_DISASSOC:
+               ieee80211softmac_send_disassoc_req(mac, reason);
+               return 0;
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);
index e40f75322377a84049cccec186cf4f07a01f7211..da33393be45f3d2e4d964dcdb9dbde58e59a1d84 100644 (file)
@@ -414,6 +414,24 @@ config INET_TUNNEL
        tristate
        default n
 
+config INET_XFRM_MODE_TRANSPORT
+       tristate "IP: IPsec transport mode"
+       default y
+       select XFRM
+       ---help---
+         Support for IPsec transport mode.
+
+         If unsure, say Y.
+
+config INET_XFRM_MODE_TUNNEL
+       tristate "IP: IPsec tunnel mode"
+       default y
+       select XFRM
+       ---help---
+         Support for IPsec tunnel mode.
+
+         If unsure, say Y.
+
 config INET_DIAG
        tristate "INET: socket monitoring interface"
        default y
@@ -532,6 +550,38 @@ config TCP_CONG_SCALABLE
        properties, though is known to have fairness issues.
        See http://www-lce.eng.cam.ac.uk/~ctk21/scalable/
 
+config TCP_CONG_LP
+       tristate "TCP Low Priority"
+       depends on EXPERIMENTAL
+       default n
+       ---help---
+       TCP Low Priority (TCP-LP), a distributed algorithm whose goal is
+       to utiliza only the excess network bandwidth as compared to the
+       ``fair share`` of bandwidth as targeted by TCP.
+       See http://www-ece.rice.edu/networks/TCP-LP/
+
+config TCP_CONG_VENO
+       tristate "TCP Veno"
+       depends on EXPERIMENTAL
+       default n
+       ---help---
+       TCP Veno is a sender-side only enhancement of TCP to obtain better
+       throughput over wireless networks. TCP Veno makes use of state
+       distinguishing to circumvent the difficult judgment of the packet loss
+       type. TCP Veno cuts down less congestion window in response to random
+       loss packets.
+       See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
+
+config TCP_CONG_COMPOUND
+       tristate "TCP Compound"
+       depends on EXPERIMENTAL
+       default n
+       ---help---
+       TCP Compound is a sender-side only change to TCP that uses
+       a mixed Reno/Vegas approach to calculate the cwnd.
+       For further details look here:
+         ftp://ftp.research.microsoft.com/pub/tr/TR-2005-86.pdf
+
 endmenu
 
 config TCP_CONG_BIC
index 9ef50a0b9d2c7b871145f759c52cdd6ade6e5520..38b8039bdd55ff4267b8e82da20543110393f5fe 100644 (file)
@@ -24,6 +24,8 @@ obj-$(CONFIG_INET_ESP) += esp4.o
 obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
 obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
 obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
+obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
+obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
 obj-$(CONFIG_IP_PNP) += ipconfig.o
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_IP_VS) += ipvs/
 obj-$(CONFIG_INET_DIAG) += inet_diag.o 
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
 obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
+obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
 obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
 obj-$(CONFIG_TCP_CONG_CUBIC) += tcp_cubic.o
 obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
@@ -41,7 +44,10 @@ obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o
 obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybla.o
 obj-$(CONFIG_TCP_CONG_HTCP) += tcp_htcp.o
 obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o
+obj-$(CONFIG_TCP_CONG_VENO) += tcp_veno.o
 obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
+obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
+obj-$(CONFIG_TCP_CONG_COMPOUND) += tcp_compound.o
 
 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
                      xfrm4_output.o
index e2e4771fa4c6d42b8b7e19cdac07abd022e65b53..c7782230080d21d76a7ffa70ef6df2eb6358df1b 100644 (file)
@@ -119,6 +119,7 @@ error:
 static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
 {
        int ah_hlen;
+       int ihl;
        struct iphdr *iph;
        struct ip_auth_hdr *ah;
        struct ah_data *ahp;
@@ -149,13 +150,14 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
        ah = (struct ip_auth_hdr*)skb->data;
        iph = skb->nh.iph;
 
-       memcpy(work_buf, iph, iph->ihl*4);
+       ihl = skb->data - skb->nh.raw;
+       memcpy(work_buf, iph, ihl);
 
        iph->ttl = 0;
        iph->tos = 0;
        iph->frag_off = 0;
        iph->check = 0;
-       if (iph->ihl != 5) {
+       if (ihl > sizeof(*iph)) {
                u32 dummy;
                if (ip_clear_mutable_options(iph, &dummy))
                        goto out;
@@ -164,7 +166,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
                u8 auth_data[MAX_AH_AUTH_LEN];
                
                memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
-               skb_push(skb, skb->data - skb->nh.raw);
+               skb_push(skb, ihl);
                ahp->icv(ahp, skb, ah->auth_data);
                if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
                        x->stats.integrity_failed++;
@@ -172,11 +174,8 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
                }
        }
        ((struct iphdr*)work_buf)->protocol = ah->nexthdr;
-       skb->nh.raw = skb_pull(skb, ah_hlen);
-       memcpy(skb->nh.raw, work_buf, iph->ihl*4);
-       skb->nh.iph->tot_len = htons(skb->len);
-       skb_pull(skb, skb->nh.iph->ihl*4);
-       skb->h.raw = skb->data;
+       skb->h.raw = memcpy(skb->nh.raw += ah_hlen, work_buf, ihl);
+       __skb_pull(skb, ah_hlen + ihl);
 
        return 0;
 
index 9d1881c07a32ae9dffcc1b0efa26bb2b5a698fda..9bbdd4494551347b43bce292bb4406198aec4b18 100644 (file)
@@ -143,10 +143,9 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
        int alen = esp->auth.icv_trunc_len;
        int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
        int nfrags;
-       int encap_len = 0;
+       int ihl;
        u8 nexthdr[2];
        struct scatterlist *sg;
-       u8 workbuf[60];
        int padlen;
 
        if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
@@ -177,7 +176,6 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
        skb->ip_summed = CHECKSUM_NONE;
 
        esph = (struct ip_esp_hdr*)skb->data;
-       iph = skb->nh.iph;
 
        /* Get ivec. This can be wrong, check against another impls. */
        if (esp->conf.ivlen)
@@ -204,12 +202,12 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
 
        /* ... check padding bits here. Silly. :-) */ 
 
+       iph = skb->nh.iph;
+       ihl = iph->ihl * 4;
+
        if (x->encap) {
                struct xfrm_encap_tmpl *encap = x->encap;
-               struct udphdr *uh;
-
-               uh = (struct udphdr *)(iph + 1);
-               encap_len = (void*)esph - (void*)uh;
+               struct udphdr *uh = (void *)(skb->nh.raw + ihl);
 
                /*
                 * 1) if the NAT-T peer's IP or port changed then
@@ -246,11 +244,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
 
        iph->protocol = nexthdr[1];
        pskb_trim(skb, skb->len - alen - padlen - 2);
-       memcpy(workbuf, skb->nh.raw, iph->ihl*4);
-       skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);
-       skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
-       memcpy(skb->nh.raw, workbuf, iph->ihl*4);
-       skb->nh.iph->tot_len = htons(skb->len);
+       skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - ihl;
 
        return 0;
 
index cdde963909603aae61b7398afb09112dde407e52..31387abf53a21630ebbd9c2cc9993cfa715a2ade 100644 (file)
@@ -666,3 +666,4 @@ void __init ip_fib_init(void)
 }
 
 EXPORT_SYMBOL(inet_addr_type);
+EXPORT_SYMBOL(ip_dev_find);
index 2a0455911ee0a9c9119472c01d4d4717f58e190b..017900172f7d5fc01505b2ac9ea90f7628c4042c 100644 (file)
@@ -730,7 +730,6 @@ out_err:
 static void icmp_redirect(struct sk_buff *skb)
 {
        struct iphdr *iph;
-       unsigned long ip;
 
        if (skb->len < sizeof(struct iphdr))
                goto out_err;
@@ -742,7 +741,6 @@ static void icmp_redirect(struct sk_buff *skb)
                goto out;
 
        iph = (struct iphdr *)skb->data;
-       ip = iph->daddr;
 
        switch (skb->h.icmph->code & 7) {
        case ICMP_REDIR_NET:
@@ -752,7 +750,8 @@ static void icmp_redirect(struct sk_buff *skb)
                 */
        case ICMP_REDIR_HOST:
        case ICMP_REDIR_HOSTTOS:
-               ip_rt_redirect(skb->nh.iph->saddr, ip, skb->h.icmph->un.gateway,
+               ip_rt_redirect(skb->nh.iph->saddr, iph->daddr,
+                              skb->h.icmph->un.gateway,
                               iph->saddr, skb->dev);
                break;
        }
index d512239a14731a0690e184f6340221f06c4a0b18..ab680c851aa204b5e2f1b2ee18dc023b7630764f 100644 (file)
@@ -2361,7 +2361,7 @@ static int igmp_mc_seq_show(struct seq_file *seq, void *v)
                }
 
                seq_printf(seq,
-                          "\t\t\t\t%08lX %5d %d:%08lX\t\t%d\n",
+                          "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n",
                           im->multiaddr, im->users,
                           im->tm_running, im->tm_running ?
                           jiffies_to_clock_t(im->timer.expires-jiffies) : 0,
index 0923add122b415b8000d46fbad28fcffe217e0cc..9f0bb529ab70af99e2c79ee61521d38d19f9e1e0 100644 (file)
@@ -116,6 +116,7 @@ sr_failed:
 
 too_many_hops:
         /* Tell the sender its packet died... */
+        IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
         icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
 drop:
        kfree_skb(skb);
index cff9c3a72daf254013b7ae80cb5761e04a733a2f..8538aac3d14805545b500f366a0cc433b3200ef1 100644 (file)
@@ -410,6 +410,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
        nf_bridge_get(to->nf_bridge);
 #endif
 #endif
+       skb_copy_secmark(to, from);
 }
 
 /*
@@ -839,7 +840,7 @@ int ip_append_data(struct sock *sk,
         */
        if (transhdrlen &&
            length + fragheaderlen <= mtu &&
-           rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) &&
+           rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
            !exthdrlen)
                csummode = CHECKSUM_HW;
 
index 95278b22b669ab895903fe039fa3e7d2e1f56a25..3ed8b57a1002c307d4fd74f021d6177de3d9aefe 100644 (file)
@@ -45,7 +45,6 @@ static LIST_HEAD(ipcomp_tfms_list);
 static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err, plen, dlen;
-       struct iphdr *iph;
        struct ipcomp_data *ipcd = x->data;
        u8 *start, *scratch;
        struct crypto_tfm *tfm;
@@ -74,8 +73,6 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
                
        skb_put(skb, dlen - plen);
        memcpy(skb->data, scratch, dlen);
-       iph = skb->nh.iph;
-       iph->tot_len = htons(dlen + iph->ihl * 4);
 out:   
        put_cpu();
        return err;
@@ -83,34 +80,21 @@ out:
 
 static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-       u8 nexthdr;
-       int err = 0;
+       int err = -ENOMEM;
        struct iphdr *iph;
-       union {
-               struct iphdr    iph;
-               char            buf[60];
-       } tmp_iph;
-
+       struct ip_comp_hdr *ipch;
 
-       if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
-           skb_linearize(skb, GFP_ATOMIC) != 0) {
-               err = -ENOMEM;
+       if (skb_linearize_cow(skb))
                goto out;
-       }
 
        skb->ip_summed = CHECKSUM_NONE;
 
        /* Remove ipcomp header and decompress original payload */      
        iph = skb->nh.iph;
-       memcpy(&tmp_iph, iph, iph->ihl * 4);
-       nexthdr = *(u8 *)skb->data;
-       skb_pull(skb, sizeof(struct ip_comp_hdr));
-       skb->nh.raw += sizeof(struct ip_comp_hdr);
-       memcpy(skb->nh.raw, &tmp_iph, tmp_iph.iph.ihl * 4);
-       iph = skb->nh.iph;
-       iph->tot_len = htons(ntohs(iph->tot_len) - sizeof(struct ip_comp_hdr));
-       iph->protocol = nexthdr;
-       skb->h.raw = skb->data;
+       ipch = (void *)skb->data;
+       iph->protocol = ipch->nexthdr;
+       skb->h.raw = skb->nh.raw + sizeof(*ipch);
+       __skb_pull(skb, sizeof(*ipch));
        err = ipcomp_decompress(x, skb);
 
 out:   
@@ -171,10 +155,8 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
                goto out_ok;
        }
 
-       if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
-           skb_linearize(skb, GFP_ATOMIC) != 0) {
+       if (skb_linearize_cow(skb))
                goto out_ok;
-       }
        
        err = ipcomp_compress(x, skb);
        iph = skb->nh.iph;
index 3d560dec63ab5dacf2d848191bb62f0069276d7f..e1d7f5fbc52634550908485439d6ebbac7d8fb2e 100644 (file)
@@ -55,6 +55,18 @@ config IP_NF_CONNTRACK_MARK
          of packets, but this mark value is kept in the conntrack session
          instead of the individual packets.
        
+config IP_NF_CONNTRACK_SECMARK
+       bool  'Connection tracking security mark support'
+       depends on IP_NF_CONNTRACK && NETWORK_SECMARK
+       help
+         This option enables security markings to be applied to
+         connections.  Typically they are copied to connections from
+         packets using the CONNSECMARK target and copied back from
+         connections to packets with the same target, with the packets
+         being originally labeled via SECMARK.
+
+         If unsure, say 'N'.
+
 config IP_NF_CONNTRACK_EVENTS
        bool "Connection tracking events (EXPERIMENTAL)"
        depends on EXPERIMENTAL && IP_NF_CONNTRACK
@@ -142,6 +154,8 @@ config IP_NF_TFTP
 config IP_NF_AMANDA
        tristate "Amanda backup protocol support"
        depends on IP_NF_CONNTRACK
+       select TEXTSEARCH
+       select TEXTSEARCH_KMP
        help
          If you are running the Amanda backup package <http://www.amanda.org/>
          on this machine or machines that will be MASQUERADED through this
@@ -170,8 +184,8 @@ config IP_NF_PPTP
          Documentation/modules.txt.  If unsure, say `N'.
 
 config IP_NF_H323
-       tristate  'H.323 protocol support'
-       depends on IP_NF_CONNTRACK
+       tristate  'H.323 protocol support (EXPERIMENTAL)'
+       depends on IP_NF_CONNTRACK && EXPERIMENTAL
        help
          H.323 is a VoIP signalling protocol from ITU-T. As one of the most
          important VoIP protocols, it is widely used by voice hardware and
@@ -181,14 +195,26 @@ config IP_NF_H323
          With this module you can support H.323 on a connection tracking/NAT
          firewall.
 
-         This module supports RAS, Fast-start, H.245 tunnelling, RTP/RTCP
-         and T.120 based data and applications including audio, video, FAX,
-         chat, whiteboard, file transfer, etc. For more information, please
-         see http://nath323.sourceforge.net/.
+         This module supports RAS, Fast Start, H.245 Tunnelling, Call
+         Forwarding, RTP/RTCP and T.120 based audio, video, fax, chat,
+         whiteboard, file transfer, etc. For more information, please
+         visit http://nath323.sourceforge.net/.
 
          If you want to compile it as a module, say 'M' here and read
          Documentation/modules.txt.  If unsure, say 'N'.
 
+config IP_NF_SIP
+       tristate "SIP protocol support (EXPERIMENTAL)"
+       depends on IP_NF_CONNTRACK && EXPERIMENTAL
+       help
+         SIP is an application-layer control protocol that can establish,
+         modify, and terminate multimedia sessions (conferences) such as
+         Internet telephony calls. With the ip_conntrack_sip and
+         the ip_nat_sip modules you can support the protocol on a connection
+         tracking/NATing firewall.
+
+         To compile it as a module, choose M here.  If unsure, say Y.
+
 config IP_NF_QUEUE
        tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
        help
@@ -501,6 +527,12 @@ config IP_NF_NAT_H323
        default IP_NF_NAT if IP_NF_H323=y
        default m if IP_NF_H323=m
 
+config IP_NF_NAT_SIP
+       tristate
+       depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
+       default IP_NF_NAT if IP_NF_SIP=y
+       default m if IP_NF_SIP=m
+
 # mangle + specific targets
 config IP_NF_MANGLE
        tristate "Packet mangling"
index 461cb1eb5de79cfe6050b7291ff12d86110054c1..3ded4a3af59c37c650cb750ed312b55aa367167f 100644 (file)
@@ -31,6 +31,7 @@ obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
+obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o
 obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
 
 # NAT helpers 
@@ -40,6 +41,7 @@ obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
+obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
 
 # generic IP tables 
 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
index a604b1ccfdaa8c83b86f00744296f26afad07d98..0a7bd7f04061f89b55f1e2b7a596f5b0b17ca15f 100644 (file)
  *     this value.
  *
  */
-
-#include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/netfilter.h>
-#include <linux/ip.h>
 #include <linux/moduleparam.h>
+#include <linux/textsearch.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
 #include <linux/udp.h>
-#include <net/checksum.h>
-#include <net/udp.h>
 
+#include <linux/netfilter.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
 
 static unsigned int master_timeout = 300;
+static char *ts_algo = "kmp";
 
 MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
 MODULE_DESCRIPTION("Amanda connection tracking module");
 MODULE_LICENSE("GPL");
 module_param(master_timeout, uint, 0600);
 MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
-
-static const char *conns[] = { "DATA ", "MESG ", "INDEX " };
-
-/* This is slow, but it's simple. --RR */
-static char *amanda_buffer;
-static DEFINE_SPINLOCK(amanda_buffer_lock);
+module_param(ts_algo, charp, 0400);
+MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)");
 
 unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
                                   enum ip_conntrack_info ctinfo,
@@ -52,12 +48,48 @@ unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
                                   struct ip_conntrack_expect *exp);
 EXPORT_SYMBOL_GPL(ip_nat_amanda_hook);
 
+enum amanda_strings {
+       SEARCH_CONNECT,
+       SEARCH_NEWLINE,
+       SEARCH_DATA,
+       SEARCH_MESG,
+       SEARCH_INDEX,
+};
+
+static struct {
+       char                    *string;
+       size_t                  len;
+       struct ts_config        *ts;
+} search[] = {
+       [SEARCH_CONNECT] = {
+               .string = "CONNECT ",
+               .len    = 8,
+       },
+       [SEARCH_NEWLINE] = {
+               .string = "\n",
+               .len    = 1,
+       },
+       [SEARCH_DATA] = {
+               .string = "DATA ",
+               .len    = 5,
+       },
+       [SEARCH_MESG] = {
+               .string = "MESG ",
+               .len    = 5,
+       },
+       [SEARCH_INDEX] = {
+               .string = "INDEX ",
+               .len    = 6,
+       },
+};
+
 static int help(struct sk_buff **pskb,
                 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
+       struct ts_state ts;
        struct ip_conntrack_expect *exp;
-       char *data, *data_limit, *tmp;
-       unsigned int dataoff, i;
+       unsigned int dataoff, start, stop, off, i;
+       char pbuf[sizeof("65535")], *tmp;
        u_int16_t port, len;
        int ret = NF_ACCEPT;
 
@@ -77,29 +109,34 @@ static int help(struct sk_buff **pskb,
                return NF_ACCEPT;
        }
 
-       spin_lock_bh(&amanda_buffer_lock);
-       skb_copy_bits(*pskb, dataoff, amanda_buffer, (*pskb)->len - dataoff);
-       data = amanda_buffer;
-       data_limit = amanda_buffer + (*pskb)->len - dataoff;
-       *data_limit = '\0';
-
-       /* Search for the CONNECT string */
-       data = strstr(data, "CONNECT ");
-       if (!data)
+       memset(&ts, 0, sizeof(ts));
+       start = skb_find_text(*pskb, dataoff, (*pskb)->len,
+                             search[SEARCH_CONNECT].ts, &ts);
+       if (start == UINT_MAX)
                goto out;
-       data += strlen("CONNECT ");
+       start += dataoff + search[SEARCH_CONNECT].len;
 
-       /* Only search first line. */   
-       if ((tmp = strchr(data, '\n')))
-               *tmp = '\0';
+       memset(&ts, 0, sizeof(ts));
+       stop = skb_find_text(*pskb, start, (*pskb)->len,
+                            search[SEARCH_NEWLINE].ts, &ts);
+       if (stop == UINT_MAX)
+               goto out;
+       stop += start;
 
-       for (i = 0; i < ARRAY_SIZE(conns); i++) {
-               char *match = strstr(data, conns[i]);
-               if (!match)
+       for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) {
+               memset(&ts, 0, sizeof(ts));
+               off = skb_find_text(*pskb, start, stop, search[i].ts, &ts);
+               if (off == UINT_MAX)
                        continue;
-               tmp = data = match + strlen(conns[i]);
-               port = simple_strtoul(data, &data, 10);
-               len = data - tmp;
+               off += start + search[i].len;
+
+               len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off);
+               if (skb_copy_bits(*pskb, off, pbuf, len))
+                       break;
+               pbuf[len] = '\0';
+
+               port = simple_strtoul(pbuf, &tmp, 10);
+               len = tmp - pbuf;
                if (port == 0 || len > 5)
                        break;
 
@@ -125,8 +162,7 @@ static int help(struct sk_buff **pskb,
                exp->mask.dst.u.tcp.port = 0xFFFF;
 
                if (ip_nat_amanda_hook)
-                       ret = ip_nat_amanda_hook(pskb, ctinfo,
-                                                tmp - amanda_buffer,
+                       ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff,
                                                 len, exp);
                else if (ip_conntrack_expect_related(exp) != 0)
                        ret = NF_DROP;
@@ -134,12 +170,11 @@ static int help(struct sk_buff **pskb,
        }
 
 out:
-       spin_unlock_bh(&amanda_buffer_lock);
        return ret;
 }
 
 static struct ip_conntrack_helper amanda_helper = {
-       .max_expected = ARRAY_SIZE(conns),
+       .max_expected = 3,
        .timeout = 180,
        .me = THIS_MODULE,
        .help = help,
@@ -155,26 +190,36 @@ static struct ip_conntrack_helper amanda_helper = {
 
 static void __exit ip_conntrack_amanda_fini(void)
 {
+       int i;
+
        ip_conntrack_helper_unregister(&amanda_helper);
-       kfree(amanda_buffer);
+       for (i = 0; i < ARRAY_SIZE(search); i++)
+               textsearch_destroy(search[i].ts);
 }
 
 static int __init ip_conntrack_amanda_init(void)
 {
-       int ret;
-
-       amanda_buffer = kmalloc(65536, GFP_KERNEL);
-       if (!amanda_buffer)
-               return -ENOMEM;
-
-       ret = ip_conntrack_helper_register(&amanda_helper);
-       if (ret < 0) {
-               kfree(amanda_buffer);
-               return ret;
+       int ret, i;
+
+       ret = -ENOMEM;
+       for (i = 0; i < ARRAY_SIZE(search); i++) {
+               search[i].ts = textsearch_prepare(ts_algo, search[i].string,
+                                                 search[i].len,
+                                                 GFP_KERNEL, TS_AUTOLOAD);
+               if (search[i].ts == NULL)
+                       goto err;
        }
+       ret = ip_conntrack_helper_register(&amanda_helper);
+       if (ret < 0)
+               goto err;
        return 0;
 
-
+err:
+       for (; i >= 0; i--) {
+               if (search[i].ts)
+                       textsearch_destroy(search[i].ts);
+       }
+       return ret;
 }
 
 module_init(ip_conntrack_amanda_init);
index 979a2eac6f003101438ecd518b1c4d9c2c365bf8..7e4cf9a4d15f8509a4362466d7a4f26ef081f782 100644 (file)
@@ -723,6 +723,9 @@ init_conntrack(struct ip_conntrack_tuple *tuple,
     defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
                /* this is ugly, but there is no other place where to put it */
                conntrack->nat.masq_index = exp->master->nat.masq_index;
+#endif
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+               conntrack->secmark = exp->master->secmark;
 #endif
                nf_conntrack_get(&conntrack->master->ct_general);
                CONNTRACK_STAT_INC(expect_new);
@@ -1130,6 +1133,12 @@ void __ip_ct_refresh_acct(struct ip_conntrack *ct,
 
        write_lock_bh(&ip_conntrack_lock);
 
+       /* Only update if this is not a fixed timeout */
+       if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) {
+               write_unlock_bh(&ip_conntrack_lock);
+               return;
+       }
+
        /* If not in hash table, timer will not be active yet */
        if (!is_confirmed(ct)) {
                ct->timeout.expires = extra_jiffies;
@@ -1318,6 +1327,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
                        .tuple.dst.u.tcp.port;
                sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL]
                        .tuple.dst.ip;
+               memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
 
                DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
                       NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
index 3e542bf28a9dff7f27093305ddf3f84bdacba04c..4dcf526c394498c061bb4757d5f6d1e320b547e8 100644 (file)
@@ -56,37 +56,48 @@ static int try_eprt(const char *, size_t, u_int32_t [], char);
 static int try_epsv_response(const char *, size_t, u_int32_t [], char);
 
 static const struct ftp_search {
-       enum ip_conntrack_dir dir;
        const char *pattern;
        size_t plen;
        char skip;
        char term;
        enum ip_ct_ftp_type ftptype;
        int (*getnum)(const char *, size_t, u_int32_t[], char);
-} search[] = {
-       {
-               IP_CT_DIR_ORIGINAL,
-               "PORT", sizeof("PORT") - 1, ' ', '\r',
-               IP_CT_FTP_PORT,
-               try_rfc959,
+} search[IP_CT_DIR_MAX][2] = {
+       [IP_CT_DIR_ORIGINAL] = {
+               {
+                       .pattern        =  "PORT",
+                       .plen           = sizeof("PORT") - 1,
+                       .skip           = ' ',
+                       .term           = '\r',
+                       .ftptype        = IP_CT_FTP_PORT,
+                       .getnum         = try_rfc959,
+               },
+               {
+                       .pattern        = "EPRT",
+                       .plen           = sizeof("EPRT") - 1,
+                       .skip           = ' ',
+                       .term           = '\r',
+                       .ftptype        = IP_CT_FTP_EPRT,
+                       .getnum         = try_eprt,
+               },
        },
-       {
-               IP_CT_DIR_REPLY,
-               "227 ", sizeof("227 ") - 1, '(', ')',
-               IP_CT_FTP_PASV,
-               try_rfc959,
-       },
-       {
-               IP_CT_DIR_ORIGINAL,
-               "EPRT", sizeof("EPRT") - 1, ' ', '\r',
-               IP_CT_FTP_EPRT,
-               try_eprt,
-       },
-       {
-               IP_CT_DIR_REPLY,
-               "229 ", sizeof("229 ") - 1, '(', ')',
-               IP_CT_FTP_EPSV,
-               try_epsv_response,
+       [IP_CT_DIR_REPLY] = {
+               {
+                       .pattern        = "227 ",
+                       .plen           = sizeof("227 ") - 1,
+                       .skip           = '(',
+                       .term           = ')',
+                       .ftptype        = IP_CT_FTP_PASV,
+                       .getnum         = try_rfc959,
+               },
+               {
+                       .pattern        = "229 ",
+                       .plen           = sizeof("229 ") - 1,
+                       .skip           = '(',
+                       .term           = ')',
+                       .ftptype        = IP_CT_FTP_EPSV,
+                       .getnum         = try_epsv_response,
+               },
        },
 };
 
@@ -346,17 +357,15 @@ static int help(struct sk_buff **pskb,
        array[2] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 8) & 0xFF;
        array[3] = ntohl(ct->tuplehash[dir].tuple.src.ip) & 0xFF;
 
-       for (i = 0; i < ARRAY_SIZE(search); i++) {
-               if (search[i].dir != dir) continue;
-
+       for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
                found = find_pattern(fb_ptr, (*pskb)->len - dataoff,
-                                    search[i].pattern,
-                                    search[i].plen,
-                                    search[i].skip,
-                                    search[i].term,
+                                    search[dir][i].pattern,
+                                    search[dir][i].plen,
+                                    search[dir][i].skip,
+                                    search[dir][i].term,
                                     &matchoff, &matchlen,
                                     array,
-                                    search[i].getnum);
+                                    search[dir][i].getnum);
                if (found) break;
        }
        if (found == -1) {
@@ -366,7 +375,7 @@ static int help(struct sk_buff **pskb,
                   this case. */
                if (net_ratelimit())
                        printk("conntrack_ftp: partial %s %u+%u\n",
-                              search[i].pattern,
+                              search[dir][i].pattern,
                               ntohl(th->seq), datalen);
                ret = NF_DROP;
                goto out;
@@ -426,7 +435,7 @@ static int help(struct sk_buff **pskb,
        /* Now, NAT might want to mangle the packet, and register the
         * (possibly changed) expectation itself. */
        if (ip_nat_ftp_hook)
-               ret = ip_nat_ftp_hook(pskb, ctinfo, search[i].ftptype,
+               ret = ip_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
                                      matchoff, matchlen, exp, &seq);
        else {
                /* Can't expect this?  Best to drop packet now. */
index 518f581d39ece6058670ad9efda9df57d2191e68..0665674218c6987c0956f015be4069d41897a174 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
 #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
 #include <linux/moduleparam.h>
+#include <linux/ctype.h>
+#include <linux/inet.h>
 
 #if 0
 #define DEBUGP printk
@@ -38,6 +40,12 @@ static int gkrouted_only = 1;
 module_param(gkrouted_only, int, 0600);
 MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
 
+static int callforward_filter = 1;
+module_param(callforward_filter, bool, 0600);
+MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
+                                    "if both endpoints are on different sides "
+                                    "(determined by routing information)");
+
 /* Hooks for NAT */
 int (*set_h245_addr_hook) (struct sk_buff ** pskb,
                           unsigned char **data, int dataoff,
@@ -77,6 +85,12 @@ int (*nat_h245_hook) (struct sk_buff ** pskb,
                      unsigned char **data, int dataoff,
                      TransportAddress * addr, u_int16_t port,
                      struct ip_conntrack_expect * exp);
+int (*nat_callforwarding_hook) (struct sk_buff ** pskb,
+                               struct ip_conntrack * ct,
+                               enum ip_conntrack_info ctinfo,
+                               unsigned char **data, int dataoff,
+                               TransportAddress * addr, u_int16_t port,
+                               struct ip_conntrack_expect * exp);
 int (*nat_q931_hook) (struct sk_buff ** pskb,
                      struct ip_conntrack * ct,
                      enum ip_conntrack_info ctinfo,
@@ -683,6 +697,92 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
        return ret;
 }
 
+/* Forwarding declaration */
+void ip_conntrack_q931_expect(struct ip_conntrack *new,
+                             struct ip_conntrack_expect *this);
+
+/****************************************************************************/
+static int expect_callforwarding(struct sk_buff **pskb,
+                                struct ip_conntrack *ct,
+                                enum ip_conntrack_info ctinfo,
+                                unsigned char **data, int dataoff,
+                                TransportAddress * addr)
+{
+       int dir = CTINFO2DIR(ctinfo);
+       int ret = 0;
+       u_int32_t ip;
+       u_int16_t port;
+       struct ip_conntrack_expect *exp = NULL;
+
+       /* Read alternativeAddress */
+       if (!get_h225_addr(*data, addr, &ip, &port) || port == 0)
+               return 0;
+
+       /* If the calling party is on the same side of the forward-to party,
+        * we don't need to track the second call */
+       if (callforward_filter) {
+               struct rtable *rt1, *rt2;
+               struct flowi fl1 = {
+                       .fl4_dst = ip,
+               };
+               struct flowi fl2 = {
+                       .fl4_dst = ct->tuplehash[!dir].tuple.src.ip,
+               };
+
+               if (ip_route_output_key(&rt1, &fl1) == 0) {
+                       if (ip_route_output_key(&rt2, &fl2) == 0) {
+                               if (rt1->rt_gateway == rt2->rt_gateway &&
+                                   rt1->u.dst.dev  == rt2->u.dst.dev)
+                                       ret = 1;
+                               dst_release(&rt2->u.dst);
+                       }
+                       dst_release(&rt1->u.dst);
+               }
+               if (ret) {
+                       DEBUGP("ip_ct_q931: Call Forwarding not tracked\n");
+                       return 0;
+               }
+       }
+
+       /* Create expect for the second call leg */
+       if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
+               return -1;
+       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
+       exp->tuple.src.u.tcp.port = 0;
+       exp->tuple.dst.ip = ip;
+       exp->tuple.dst.u.tcp.port = htons(port);
+       exp->tuple.dst.protonum = IPPROTO_TCP;
+       exp->mask.src.ip = 0xFFFFFFFF;
+       exp->mask.src.u.tcp.port = 0;
+       exp->mask.dst.ip = 0xFFFFFFFF;
+       exp->mask.dst.u.tcp.port = 0xFFFF;
+       exp->mask.dst.protonum = 0xFF;
+       exp->flags = 0;
+
+       if (ct->tuplehash[dir].tuple.src.ip !=
+           ct->tuplehash[!dir].tuple.dst.ip && nat_callforwarding_hook) {
+               /* Need NAT */
+               ret = nat_callforwarding_hook(pskb, ct, ctinfo, data, dataoff,
+                                             addr, port, exp);
+       } else {                /* Conntrack only */
+               exp->expectfn = ip_conntrack_q931_expect;
+
+               if (ip_conntrack_expect_related(exp) == 0) {
+                       DEBUGP("ip_ct_q931: expect Call Forwarding "
+                              "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+                              NIPQUAD(exp->tuple.src.ip),
+                              ntohs(exp->tuple.src.u.tcp.port),
+                              NIPQUAD(exp->tuple.dst.ip),
+                              ntohs(exp->tuple.dst.u.tcp.port));
+               } else
+                       ret = -1;
+       }
+
+       ip_conntrack_expect_put(exp);
+
+       return ret;
+}
+
 /****************************************************************************/
 static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
                         enum ip_conntrack_info ctinfo,
@@ -878,6 +978,15 @@ static int process_facility(struct sk_buff **pskb, struct ip_conntrack *ct,
 
        DEBUGP("ip_ct_q931: Facility\n");
 
+       if (facility->reason.choice == eFacilityReason_callForwarded) {
+               if (facility->options & eFacility_UUIE_alternativeAddress)
+                       return expect_callforwarding(pskb, ct, ctinfo, data,
+                                                    dataoff,
+                                                    &facility->
+                                                    alternativeAddress);
+               return 0;
+       }
+
        if (facility->options & eFacility_UUIE_h245Address) {
                ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
                                  &facility->h245Address);
@@ -1677,7 +1786,6 @@ static int __init init(void)
                fini();
                return ret;
        }
-
        DEBUGP("ip_ct_h323: init success\n");
        return 0;
 }
@@ -1696,6 +1804,7 @@ EXPORT_SYMBOL_GPL(set_ras_addr_hook);
 EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
 EXPORT_SYMBOL_GPL(nat_t120_hook);
 EXPORT_SYMBOL_GPL(nat_h245_hook);
+EXPORT_SYMBOL_GPL(nat_callforwarding_hook);
 EXPORT_SYMBOL_GPL(nat_q931_hook);
 
 MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
index 022c47b9f6c996a586d6e1314424ab0a8f84fc58..4b359618beddfa6661cbdbd5cf8bfcc6c843237b 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
+/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006
  *
  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
@@ -1069,8 +1069,8 @@ static field_t _Facility_UUIE_fastStart[] = {     /* SEQUENCE OF */
 
 static field_t _Facility_UUIE[] = {    /* SEQUENCE */
        {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
-       {FNAME("alternativeAddress") CHOICE, 3, 7, 7, SKIP | EXT | OPT, 0,
-        _TransportAddress},
+       {FNAME("alternativeAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
+        offsetof(Facility_UUIE, alternativeAddress), _TransportAddress},
        {FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
         _Facility_UUIE_alternativeAliasAddress},
        {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
index 7d3ba4302e9e3ef0463c79d7e175eed53eb6e4d0..8ccfe17bb253353693bb745c5c9fceff8ffa7de1 100644 (file)
@@ -469,8 +469,8 @@ pptp_inbound_pkt(struct sk_buff **pskb,
                        DEBUGP("%s but no session\n", pptp_msg_name[msg]);
                        break;
                }
-               if (info->sstate != PPTP_CALL_IN_REP
-                   && info->sstate != PPTP_CALL_IN_CONF) {
+               if (info->cstate != PPTP_CALL_IN_REP
+                   && info->cstate != PPTP_CALL_IN_CONF) {
                        DEBUGP("%s but never sent IN_CALL_REPLY\n",
                                pptp_msg_name[msg]);
                        break;
index 01bd7cab936762208bbd5b678bc57d981d1cf1ae..33891bb1fde438a97c5d85516b3c25bb826d1ba4 100644 (file)
@@ -399,38 +399,54 @@ nfattr_failure:
 static int ctnetlink_done(struct netlink_callback *cb)
 {
        DEBUGP("entered %s\n", __FUNCTION__);
+       if (cb->args[1])
+               ip_conntrack_put((struct ip_conntrack *)cb->args[1]);
        return 0;
 }
 
 static int
 ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
-       struct ip_conntrack *ct = NULL;
+       struct ip_conntrack *ct, *last;
        struct ip_conntrack_tuple_hash *h;
        struct list_head *i;
-       u_int32_t *id = (u_int32_t *) &cb->args[1];
 
        DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__, 
                        cb->args[0], *id);
 
        read_lock_bh(&ip_conntrack_lock);
-       for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++, *id = 0) {
+       for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) {
+restart:
+               last = (struct ip_conntrack *)cb->args[1];
                list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) {
                        h = (struct ip_conntrack_tuple_hash *) i;
                        if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
                                continue;
                        ct = tuplehash_to_ctrack(h);
-                       if (ct->id <= *id)
-                               continue;
+                       if (last != NULL) {
+                               if (ct == last) {
+                                       ip_conntrack_put(last);
+                                       cb->args[1] = 0;
+                                       last = NULL;
+                               } else
+                                       continue;
+                       }
                        if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
                                                cb->nlh->nlmsg_seq,
                                                IPCTNL_MSG_CT_NEW,
-                                               1, ct) < 0)
+                                               1, ct) < 0) {
+                               nf_conntrack_get(&ct->ct_general);
+                               cb->args[1] = (unsigned long)ct;
                                goto out;
-                       *id = ct->id;
+                       }
+               }
+               if (last != NULL) {
+                       ip_conntrack_put(last);
+                       cb->args[1] = 0;
+                       goto restart;
                }
        }
-out:   
+out:
        read_unlock_bh(&ip_conntrack_lock);
 
        DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
@@ -629,7 +645,7 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = {
 };
 
 static inline int
-ctnetlink_parse_nat(struct nfattr *cda[],
+ctnetlink_parse_nat(struct nfattr *nat,
                    const struct ip_conntrack *ct, struct ip_nat_range *range)
 {
        struct nfattr *tb[CTA_NAT_MAX];
@@ -639,7 +655,7 @@ ctnetlink_parse_nat(struct nfattr *cda[],
 
        memset(range, 0, sizeof(*range));
        
-       nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]);
+       nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
 
        if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
                return -EINVAL;
@@ -854,39 +870,30 @@ ctnetlink_change_status(struct ip_conntrack *ct, struct nfattr *cda[])
                /* ASSURED bit can only be set */
                return -EINVAL;
 
-       if (cda[CTA_NAT-1]) {
+       if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
 #ifndef CONFIG_IP_NF_NAT_NEEDED
                return -EINVAL;
 #else
-               unsigned int hooknum;
                struct ip_nat_range range;
 
-               if (ctnetlink_parse_nat(cda, ct, &range) < 0)
-                       return -EINVAL;
-
-               DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n", 
-                      NIPQUAD(range.min_ip), NIPQUAD(range.max_ip),
-                      htons(range.min.all), htons(range.max.all));
-               
-               /* This is tricky but it works. ip_nat_setup_info needs the
-                * hook number as parameter, so let's do the correct 
-                * conversion and run away */
-               if (status & IPS_SRC_NAT_DONE)
-                       hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */
-               else if (status & IPS_DST_NAT_DONE)
-                       hooknum = NF_IP_PRE_ROUTING;  /* IP_NAT_MANIP_DST */
-               else 
-                       return -EINVAL; /* Missing NAT flags */
-
-               DEBUGP("NAT status: %lu\n", 
-                      status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
-               
-               if (ip_nat_initialized(ct, HOOK2MANIP(hooknum)))
-                       return -EEXIST;
-               ip_nat_setup_info(ct, &range, hooknum);
-
-                DEBUGP("NAT status after setup_info: %lu\n",
-                       ct->status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
+               if (cda[CTA_NAT_DST-1]) {
+                       if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
+                                               &range) < 0)
+                               return -EINVAL;
+                       if (ip_nat_initialized(ct,
+                                              HOOK2MANIP(NF_IP_PRE_ROUTING)))
+                               return -EEXIST;
+                       ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
+               }
+               if (cda[CTA_NAT_SRC-1]) {
+                       if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
+                                               &range) < 0)
+                               return -EINVAL;
+                       if (ip_nat_initialized(ct,
+                                              HOOK2MANIP(NF_IP_POST_ROUTING)))
+                               return -EEXIST;
+                       ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
+               }
 #endif
        }
 
@@ -1106,7 +1113,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
        /* implicit 'else' */
 
        /* we only allow nat config for new conntracks */
-       if (cda[CTA_NAT-1]) {
+       if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
                err = -EINVAL;
                goto out_unlock;
        }
index 56794797d55b9eedce61b7542ceae00a627d68ae..21ee124c04636d686f1e3e360e4cb5f7d21c68f4 100644 (file)
@@ -77,10 +77,10 @@ static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
 }
 
 /* look up the source key for a given tuple */
-static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
+static __be16 gre_keymap_lookup(struct ip_conntrack_tuple *t)
 {
        struct ip_ct_gre_keymap *km;
-       u_int32_t key = 0;
+       __be16 key = 0;
 
        read_lock_bh(&ip_ct_gre_lock);
        km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
@@ -190,7 +190,7 @@ static int gre_pkt_to_tuple(const struct sk_buff *skb,
                           struct ip_conntrack_tuple *tuple)
 {
        struct gre_hdr_pptp _pgrehdr, *pgrehdr;
-       u_int32_t srckey;
+       __be16 srckey;
        struct gre_hdr _grehdr, *grehdr;
 
        /* first only delinearize old RFC1701 GRE header */
index d8b14a9010a650c1805359afd40fc2d2e9732f55..23f1c504586dbf9930dd010181b1f31f44715896 100644 (file)
@@ -224,7 +224,7 @@ icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
        }
 
        /* See ip_conntrack_proto_tcp.c */
-       if (hooknum == NF_IP_PRE_ROUTING &&
+       if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
            nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
                if (LOG_INVALID(IPPROTO_ICMP))
                        nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
index 062b252b58ad2f7e581cb61a350cbd39b23ecf06..c5c2ce5cdeb88205ea3a17dc48d12dea4af3a5c3 100644 (file)
@@ -870,7 +870,7 @@ static int tcp_error(struct sk_buff *skb,
         * and moreover root might send raw packets.
         */
        /* FIXME: Source route IP option packets --RR */
-       if (hooknum == NF_IP_PRE_ROUTING &&
+       if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
            nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
                if (LOG_INVALID(IPPROTO_TCP))
                        nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
index 70899868783bc1d7366037f3ff240dce8befb9b6..9b2c16b4d2ffdce020abb9a9ee1a7a941d7bf90a 100644 (file)
@@ -120,7 +120,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
         * because the semantic of CHECKSUM_HW is different there 
         * and moreover root might send raw packets.
         * FIXME: Source route IP option packets --RR */
-       if (hooknum == NF_IP_PRE_ROUTING &&
+       if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
            nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
                if (LOG_INVALID(IPPROTO_UDP))
                        nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
new file mode 100644 (file)
index 0000000..fc87ce0
--- /dev/null
@@ -0,0 +1,471 @@
+/* SIP extension for IP connection tracking.
+ *
+ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
+ * based on RR's ip_conntrack_ftp.c and other modules.
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
+MODULE_DESCRIPTION("SIP connection tracking helper");
+
+#define MAX_PORTS      8
+static unsigned short ports[MAX_PORTS];
+static int ports_c;
+module_param_array(ports, ushort, &ports_c, 0400);
+MODULE_PARM_DESC(ports, "port numbers of sip servers");
+
+static unsigned int sip_timeout = SIP_TIMEOUT;
+module_param(sip_timeout, uint, 0600);
+MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
+
+unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
+                               enum ip_conntrack_info ctinfo,
+                               struct ip_conntrack *ct,
+                               const char **dptr);
+EXPORT_SYMBOL_GPL(ip_nat_sip_hook);
+
+unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
+                               enum ip_conntrack_info ctinfo,
+                               struct ip_conntrack_expect *exp,
+                               const char *dptr);
+EXPORT_SYMBOL_GPL(ip_nat_sdp_hook);
+
+int ct_sip_get_info(const char *dptr, size_t dlen,
+                               unsigned int *matchoff,
+                               unsigned int *matchlen,
+                               struct sip_header_nfo *hnfo);
+EXPORT_SYMBOL_GPL(ct_sip_get_info);
+
+
+static int digits_len(const char *dptr, const char *limit, int *shift);
+static int epaddr_len(const char *dptr, const char *limit, int *shift);
+static int skp_digits_len(const char *dptr, const char *limit, int *shift);
+static int skp_epaddr_len(const char *dptr, const char *limit, int *shift);
+
+struct sip_header_nfo ct_sip_hdrs[] = {
+       {       /* Via header */
+               .lname          = "Via:",
+               .lnlen          = sizeof("Via:") - 1,
+               .sname          = "\r\nv:",
+               .snlen          = sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */
+               .ln_str         = "UDP ",
+               .ln_strlen      = sizeof("UDP ") - 1,
+               .match_len      = epaddr_len,
+       },
+       {       /* Contact header */
+               .lname          = "Contact:",
+               .lnlen          = sizeof("Contact:") - 1,
+               .sname          = "\r\nm:",
+               .snlen          = sizeof("\r\nm:") - 1,
+               .ln_str         = "sip:",
+               .ln_strlen      = sizeof("sip:") - 1,
+               .match_len      = skp_epaddr_len
+       },
+       {       /* Content length header */
+               .lname          = "Content-Length:",
+               .lnlen          = sizeof("Content-Length:") - 1,
+               .sname          = "\r\nl:",
+               .snlen          = sizeof("\r\nl:") - 1,
+               .ln_str         = ":",
+               .ln_strlen      = sizeof(":") - 1,
+               .match_len      = skp_digits_len
+       },
+       {       /* SDP media info */
+               .lname          = "\nm=",
+               .lnlen          = sizeof("\nm=") - 1,
+               .sname          = "\rm=",
+               .snlen          = sizeof("\rm=") - 1,
+               .ln_str         = "audio ",
+               .ln_strlen      = sizeof("audio ") - 1,
+               .match_len      = digits_len
+       },
+       {       /* SDP owner address*/
+               .lname          = "\no=",
+               .lnlen          = sizeof("\no=") - 1,
+               .sname          = "\ro=",
+               .snlen          = sizeof("\ro=") - 1,
+               .ln_str         = "IN IP4 ",
+               .ln_strlen      = sizeof("IN IP4 ") - 1,
+               .match_len      = epaddr_len
+       },
+       {       /* SDP connection info */
+               .lname          = "\nc=",
+               .lnlen          = sizeof("\nc=") - 1,
+               .sname          = "\rc=",
+               .snlen          = sizeof("\rc=") - 1,
+               .ln_str         = "IN IP4 ",
+               .ln_strlen      = sizeof("IN IP4 ") - 1,
+               .match_len      = epaddr_len
+       },
+       {       /* Requests headers */
+               .lname          = "sip:",
+               .lnlen          = sizeof("sip:") - 1,
+               .sname          = "sip:",
+               .snlen          = sizeof("sip:") - 1, /* yes, i know.. ;) */
+               .ln_str         = "@",
+               .ln_strlen      = sizeof("@") - 1,
+               .match_len      = epaddr_len
+       },
+       {       /* SDP version header */
+               .lname          = "\nv=",
+               .lnlen          = sizeof("\nv=") - 1,
+               .sname          = "\rv=",
+               .snlen          = sizeof("\rv=") - 1,
+               .ln_str         = "=",
+               .ln_strlen      = sizeof("=") - 1,
+               .match_len      = digits_len
+       }
+};
+EXPORT_SYMBOL_GPL(ct_sip_hdrs);
+
+/* get line lenght until first CR or LF seen. */
+int ct_sip_lnlen(const char *line, const char *limit)
+{
+       const char *k = line;
+
+       while ((line <= limit) && (*line == '\r' || *line == '\n'))
+               line++;
+
+       while (line <= limit) {
+               if (*line == '\r' || *line == '\n')
+                       break;
+               line++;
+       }
+       return line - k;
+}
+EXPORT_SYMBOL_GPL(ct_sip_lnlen);
+
+/* Linear string search, case sensitive. */
+const char *ct_sip_search(const char *needle, const char *haystack,
+                          size_t needle_len, size_t haystack_len)
+{
+       const char *limit = haystack + (haystack_len - needle_len);
+
+       while (haystack <= limit) {
+               if (memcmp(haystack, needle, needle_len) == 0)
+                       return haystack;
+               haystack++;
+       }
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(ct_sip_search);
+
+static int digits_len(const char *dptr, const char *limit, int *shift)
+{
+       int len = 0;
+       while (dptr <= limit && isdigit(*dptr)) {
+               dptr++;
+               len++;
+       }
+       return len;
+}
+
+/* get digits lenght, skiping blank spaces. */
+static int skp_digits_len(const char *dptr, const char *limit, int *shift)
+{
+       for (; dptr <= limit && *dptr == ' '; dptr++)
+               (*shift)++;
+
+       return digits_len(dptr, limit, shift);
+}
+
+/* Simple ipaddr parser.. */
+static int parse_ipaddr(const char *cp,        const char **endp,
+                       u_int32_t *ipaddr, const char *limit)
+{
+       unsigned long int val;
+       int i, digit = 0;
+
+       for (i = 0, *ipaddr = 0; cp <= limit && i < 4; i++) {
+               digit = 0;
+               if (!isdigit(*cp))
+                       break;
+
+               val = simple_strtoul(cp, (char **)&cp, 10);
+               if (val > 0xFF)
+                       return -1;
+
+               ((u_int8_t *)ipaddr)[i] = val;
+               digit = 1;
+
+               if (*cp != '.')
+                       break;
+               cp++;
+       }
+       if (!digit)
+               return -1;
+
+       if (endp)
+               *endp = cp;
+
+       return 0;
+}
+
+/* skip ip address. returns it lenght. */
+static int epaddr_len(const char *dptr, const char *limit, int *shift)
+{
+       const char *aux = dptr;
+       u_int32_t ip;
+
+       if (parse_ipaddr(dptr, &dptr, &ip, limit) < 0) {
+               DEBUGP("ip: %s parse failed.!\n", dptr);
+               return 0;
+       }
+
+       /* Port number */
+       if (*dptr == ':') {
+               dptr++;
+               dptr += digits_len(dptr, limit, shift);
+       }
+       return dptr - aux;
+}
+
+/* get address length, skiping user info. */
+static int skp_epaddr_len(const char *dptr, const char *limit, int *shift)
+{
+       int s = *shift;
+
+       for (; dptr <= limit && *dptr != '@'; dptr++)
+               (*shift)++;
+
+       if (*dptr == '@') {
+               dptr++;
+               (*shift)++;
+       } else
+               *shift = s;
+
+       return epaddr_len(dptr, limit, shift);
+}
+
+/* Returns 0 if not found, -1 error parsing. */
+int ct_sip_get_info(const char *dptr, size_t dlen,
+                   unsigned int *matchoff,
+                   unsigned int *matchlen,
+                   struct sip_header_nfo *hnfo)
+{
+       const char *limit, *aux, *k = dptr;
+       int shift = 0;
+
+       limit = dptr + (dlen - hnfo->lnlen);
+
+       while (dptr <= limit) {
+               if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
+                   (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
+                       dptr++;
+                       continue;
+               }
+               aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
+                                   ct_sip_lnlen(dptr, limit));
+               if (!aux) {
+                       DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
+                              hnfo->lname);
+                       return -1;
+               }
+               aux += hnfo->ln_strlen;
+
+               *matchlen = hnfo->match_len(aux, limit, &shift);
+               if (!*matchlen)
+                       return -1;
+
+               *matchoff = (aux - k) + shift;
+
+               DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname,
+                      *matchlen);
+               return 1;
+       }
+       DEBUGP("%s header not found.\n", hnfo->lname);
+       return 0;
+}
+
+static int set_expected_rtp(struct sk_buff **pskb,
+                           struct ip_conntrack *ct,
+                           enum ip_conntrack_info ctinfo,
+                           u_int32_t ipaddr, u_int16_t port,
+                           const char *dptr)
+{
+       struct ip_conntrack_expect *exp;
+       enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+       int ret;
+
+       exp = ip_conntrack_expect_alloc(ct);
+       if (exp == NULL)
+               return NF_DROP;
+
+       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
+       exp->tuple.src.u.udp.port = 0;
+       exp->tuple.dst.ip = ipaddr;
+       exp->tuple.dst.u.udp.port = htons(port);
+       exp->tuple.dst.protonum = IPPROTO_UDP;
+
+       exp->mask.src.ip = 0xFFFFFFFF;
+       exp->mask.src.u.udp.port = 0;
+       exp->mask.dst.ip = 0xFFFFFFFF;
+       exp->mask.dst.u.udp.port = 0xFFFF;
+       exp->mask.dst.protonum = 0xFF;
+
+       exp->expectfn = NULL;
+       exp->flags = 0;
+
+       if (ip_nat_sdp_hook)
+               ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr);
+       else {
+               if (ip_conntrack_expect_related(exp) != 0)
+                       ret = NF_DROP;
+               else
+                       ret = NF_ACCEPT;
+       }
+       ip_conntrack_expect_put(exp);
+
+       return ret;
+}
+
+static int sip_help(struct sk_buff **pskb,
+                   struct ip_conntrack *ct,
+                   enum ip_conntrack_info ctinfo)
+{
+       unsigned int dataoff, datalen;
+       const char *dptr;
+       int ret = NF_ACCEPT;
+       int matchoff, matchlen;
+       u_int32_t ipaddr;
+       u_int16_t port;
+
+       /* No Data ? */
+       dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+       if (dataoff >= (*pskb)->len) {
+               DEBUGP("skb->len = %u\n", (*pskb)->len);
+               return NF_ACCEPT;
+        }
+
+       ip_ct_refresh(ct, *pskb, sip_timeout * HZ);
+
+       if (!skb_is_nonlinear(*pskb))
+               dptr = (*pskb)->data + dataoff;
+       else {
+               DEBUGP("Copy of skbuff not supported yet.\n");
+               goto out;
+       }
+
+       if (ip_nat_sip_hook) {
+               if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) {
+                       ret = NF_DROP;
+                       goto out;
+               }
+       }
+
+       /* After this point NAT, could have mangled skb, so
+          we need to recalculate payload lenght. */
+       datalen = (*pskb)->len - dataoff;
+
+       if (datalen < (sizeof("SIP/2.0 200") - 1))
+               goto out;
+
+       /* RTP info only in some SDP pkts */
+       if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
+           memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
+               goto out;
+       }
+       /* Get ip and port address from SDP packet. */
+       if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
+                           &ct_sip_hdrs[POS_CONNECTION]) > 0) {
+
+               /* We'll drop only if there are parse problems. */
+               if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
+                                dptr + datalen) < 0) {
+                       ret = NF_DROP;
+                       goto out;
+               }
+               if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
+                                   &ct_sip_hdrs[POS_MEDIA]) > 0) {
+
+                       port = simple_strtoul(dptr + matchoff, NULL, 10);
+                       if (port < 1024) {
+                               ret = NF_DROP;
+                               goto out;
+                       }
+                       ret = set_expected_rtp(pskb, ct, ctinfo,
+                                              ipaddr, port, dptr);
+               }
+       }
+out:
+       return ret;
+}
+
+static struct ip_conntrack_helper sip[MAX_PORTS];
+static char sip_names[MAX_PORTS][10];
+
+static void fini(void)
+{
+       int i;
+       for (i = 0; i < ports_c; i++) {
+               DEBUGP("unregistering helper for port %d\n", ports[i]);
+               ip_conntrack_helper_unregister(&sip[i]);
+       }
+}
+
+static int __init init(void)
+{
+       int i, ret;
+       char *tmpname;
+
+       if (ports_c == 0)
+               ports[ports_c++] = SIP_PORT;
+
+       for (i = 0; i < ports_c; i++) {
+               /* Create helper structure */
+               memset(&sip[i], 0, sizeof(struct ip_conntrack_helper));
+
+               sip[i].tuple.dst.protonum = IPPROTO_UDP;
+               sip[i].tuple.src.u.udp.port = htons(ports[i]);
+               sip[i].mask.src.u.udp.port = 0xFFFF;
+               sip[i].mask.dst.protonum = 0xFF;
+               sip[i].max_expected = 1;
+               sip[i].timeout = 3 * 60; /* 3 minutes */
+               sip[i].me = THIS_MODULE;
+               sip[i].help = sip_help;
+
+               tmpname = &sip_names[i][0];
+               if (ports[i] == SIP_PORT)
+                       sprintf(tmpname, "sip");
+               else
+                       sprintf(tmpname, "sip-%d", i);
+               sip[i].name = tmpname;
+
+               DEBUGP("port #%d: %d\n", i, ports[i]);
+
+               ret = ip_conntrack_helper_register(&sip[i]);
+               if (ret) {
+                       printk("ERROR registering helper for port %d\n",
+                               ports[i]);
+                       fini();
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+module_init(init);
+module_exit(fini);
index 929d61f7be91589b6ce2022ffd01dfc68767dc31..88445aac3f280c06c02924e817c9987ee5191cfb 100644 (file)
@@ -189,6 +189,11 @@ static int ct_seq_show(struct seq_file *s, void *v)
                return -ENOSPC;
 #endif
 
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+       if (seq_printf(s, "secmark=%u ", conntrack->secmark))
+               return -ENOSPC;
+#endif
+
        if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
                return -ENOSPC;
 
@@ -417,7 +422,7 @@ static unsigned int ip_conntrack_help(unsigned int hooknum,
 
        /* This is where we call the helper: as the packet goes out. */
        ct = ip_conntrack_get(*pskb, &ctinfo);
-       if (ct && ct->helper) {
+       if (ct && ct->helper && ctinfo != IP_CT_RELATED + IP_CT_IS_REPLY) {
                unsigned int ret;
                ret = ct->helper->help(pskb, ct, ctinfo);
                if (ret != NF_ACCEPT)
@@ -564,6 +569,8 @@ extern unsigned int ip_ct_generic_timeout;
 static int log_invalid_proto_min = 0;
 static int log_invalid_proto_max = 255;
 
+int ip_conntrack_checksum = 1;
+
 static struct ctl_table_header *ip_ct_sysctl_header;
 
 static ctl_table ip_ct_sysctl_table[] = {
@@ -591,6 +598,14 @@ static ctl_table ip_ct_sysctl_table[] = {
                .mode           = 0444,
                .proc_handler   = &proc_dointvec,
        },
+       {
+               .ctl_name       = NET_IPV4_NF_CONNTRACK_CHECKSUM,
+               .procname       = "ip_conntrack_checksum",
+               .data           = &ip_conntrack_checksum,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
        {
                .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
                .procname       = "ip_conntrack_tcp_timeout_syn_sent",
@@ -946,6 +961,7 @@ EXPORT_SYMBOL_GPL(__ip_conntrack_helper_find_byname);
 EXPORT_SYMBOL_GPL(ip_conntrack_proto_find_get);
 EXPORT_SYMBOL_GPL(ip_conntrack_proto_put);
 EXPORT_SYMBOL_GPL(__ip_conntrack_proto_find);
+EXPORT_SYMBOL_GPL(ip_conntrack_checksum);
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
     defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
 EXPORT_SYMBOL_GPL(ip_ct_port_tuple_to_nfattr);
index d45663d137a72b576e306dfe4cb1c671a057c307..419b878fb467276ac3f885fdae6f1228118591a3 100644 (file)
@@ -486,6 +486,80 @@ static int nat_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
        return 0;
 }
 
+/****************************************************************************/
+static void ip_nat_callforwarding_expect(struct ip_conntrack *new,
+                                        struct ip_conntrack_expect *this)
+{
+       struct ip_nat_range range;
+
+       /* This must be a fresh one. */
+       BUG_ON(new->status & IPS_NAT_DONE_MASK);
+
+       /* Change src to where master sends to */
+       range.flags = IP_NAT_RANGE_MAP_IPS;
+       range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
+
+       /* hook doesn't matter, but it has to do source manip */
+       ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
+
+       /* For DST manip, map port here to where it's expected. */
+       range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+       range.min = range.max = this->saved_proto;
+       range.min_ip = range.max_ip = this->saved_ip;
+
+       /* hook doesn't matter, but it has to do destination manip */
+       ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
+
+       ip_conntrack_q931_expect(new, this);
+}
+
+/****************************************************************************/
+static int nat_callforwarding(struct sk_buff **pskb, struct ip_conntrack *ct,
+                             enum ip_conntrack_info ctinfo,
+                             unsigned char **data, int dataoff,
+                             TransportAddress * addr, u_int16_t port,
+                             struct ip_conntrack_expect *exp)
+{
+       int dir = CTINFO2DIR(ctinfo);
+       u_int16_t nated_port;
+
+       /* Set expectations for NAT */
+       exp->saved_ip = exp->tuple.dst.ip;
+       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
+       exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+       exp->expectfn = ip_nat_callforwarding_expect;
+       exp->dir = !dir;
+
+       /* Try to get same port: if not, try to change it. */
+       for (nated_port = port; nated_port != 0; nated_port++) {
+               exp->tuple.dst.u.tcp.port = htons(nated_port);
+               if (ip_conntrack_expect_related(exp) == 0)
+                       break;
+       }
+
+       if (nated_port == 0) {  /* No port available */
+               if (net_ratelimit())
+                       printk("ip_nat_q931: out of TCP ports\n");
+               return 0;
+       }
+
+       /* Modify signal */
+       if (!set_h225_addr(pskb, data, dataoff, addr,
+                          ct->tuplehash[!dir].tuple.dst.ip,
+                          nated_port) == 0) {
+               ip_conntrack_unexpect_related(exp);
+               return -1;
+       }
+
+       /* Success */
+       DEBUGP("ip_nat_q931: expect Call Forwarding "
+              "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+              NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+              NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+       return 0;
+}
+
 /****************************************************************************/
 static int __init init(void)
 {
@@ -496,6 +570,7 @@ static int __init init(void)
        BUG_ON(nat_rtp_rtcp_hook != NULL);
        BUG_ON(nat_t120_hook != NULL);
        BUG_ON(nat_h245_hook != NULL);
+       BUG_ON(nat_callforwarding_hook != NULL);
        BUG_ON(nat_q931_hook != NULL);
 
        set_h245_addr_hook = set_h245_addr;
@@ -505,6 +580,7 @@ static int __init init(void)
        nat_rtp_rtcp_hook = nat_rtp_rtcp;
        nat_t120_hook = nat_t120;
        nat_h245_hook = nat_h245;
+       nat_callforwarding_hook = nat_callforwarding;
        nat_q931_hook = nat_q931;
 
        DEBUGP("ip_nat_h323: init success\n");
@@ -521,6 +597,7 @@ static void __exit fini(void)
        nat_rtp_rtcp_hook = NULL;
        nat_t120_hook = NULL;
        nat_h245_hook = NULL;
+       nat_callforwarding_hook = NULL;
        nat_q931_hook = NULL;
        synchronize_net();
 }
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
new file mode 100644 (file)
index 0000000..6ffba63
--- /dev/null
@@ -0,0 +1,249 @@
+/* SIP extension for UDP NAT alteration.
+ *
+ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
+ * based on RR's ip_nat_ftp.c and other modules.
+ *
+ * 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/skbuff.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
+MODULE_DESCRIPTION("SIP NAT helper");
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+extern struct sip_header_nfo ct_sip_hdrs[];
+
+static unsigned int mangle_sip_packet(struct sk_buff **pskb,
+                                     enum ip_conntrack_info ctinfo,
+                                     struct ip_conntrack *ct,
+                                     const char **dptr, size_t dlen,
+                                     char *buffer, int bufflen,
+                                     struct sip_header_nfo *hnfo)
+{
+       unsigned int matchlen, matchoff;
+
+       if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0)
+               return 0;
+
+       if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+                                     matchoff, matchlen, buffer, bufflen))
+               return 0;
+
+       /* We need to reload this. Thanks Patrick. */
+       *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+       return 1;
+}
+
+static unsigned int ip_nat_sip(struct sk_buff **pskb,
+                              enum ip_conntrack_info ctinfo,
+                              struct ip_conntrack *ct,
+                              const char **dptr)
+{
+       enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+       char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+       unsigned int bufflen, dataoff;
+       u_int32_t ip;
+       u_int16_t port;
+
+       dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+       ip   = ct->tuplehash[!dir].tuple.dst.ip;
+       port = ct->tuplehash[!dir].tuple.dst.u.udp.port;
+       bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port));
+
+       /* short packet ? */
+       if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1))
+               return 0;
+
+       /* Basic rules: requests and responses. */
+       if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) {
+               const char *aux;
+
+               if ((ctinfo) < IP_CT_IS_REPLY) {
+                       mangle_sip_packet(pskb, ctinfo, ct, dptr,
+                                         (*pskb)->len - dataoff,
+                                         buffer, bufflen,
+                                         &ct_sip_hdrs[POS_CONTACT]);
+                       return 1;
+               }
+
+               if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
+                                      (*pskb)->len - dataoff,
+                                      buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
+                       return 0;
+
+               /* This search should ignore case, but later.. */
+               aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
+                                   (*pskb)->len - dataoff);
+               if (!aux)
+                       return 0;
+
+               if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
+                   ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff)))
+                       return 1;
+
+               return mangle_sip_packet(pskb, ctinfo, ct, dptr,
+                                        (*pskb)->len - dataoff,
+                                        buffer, bufflen,
+                                        &ct_sip_hdrs[POS_CONTACT]);
+       }
+       if ((ctinfo) < IP_CT_IS_REPLY) {
+               if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
+                                      (*pskb)->len - dataoff,
+                                      buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
+                       return 0;
+
+               /* Mangle Contact if exists only. - watch udp_nat_mangle()! */
+               mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
+                                 buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
+               return 1;
+       }
+       /* This mangle requests headers. */
+       return mangle_sip_packet(pskb, ctinfo, ct, dptr,
+                                ct_sip_lnlen(*dptr,
+                                             *dptr + (*pskb)->len - dataoff),
+                                buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]);
+}
+
+static int mangle_content_len(struct sk_buff **pskb,
+                             enum ip_conntrack_info ctinfo,
+                             struct ip_conntrack *ct,
+                             const char *dptr)
+{
+       unsigned int dataoff, matchoff, matchlen;
+       char buffer[sizeof("65536")];
+       int bufflen;
+
+       dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+       /* Get actual SDP lenght */
+       if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
+                           &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) {
+
+               /* since ct_sip_get_info() give us a pointer passing 'v='
+                  we need to add 2 bytes in this count. */
+               int c_len = (*pskb)->len - dataoff - matchoff + 2;
+
+               /* Now, update SDP lenght */
+               if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
+                                   &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) {
+
+                       bufflen = sprintf(buffer, "%u", c_len);
+
+                       return ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+                                                       matchoff, matchlen,
+                                                       buffer, bufflen);
+               }
+       }
+       return 0;
+}
+
+static unsigned int mangle_sdp(struct sk_buff **pskb,
+                              enum ip_conntrack_info ctinfo,
+                              struct ip_conntrack *ct,
+                              u_int32_t newip, u_int16_t port,
+                              const char *dptr)
+{
+       char buffer[sizeof("nnn.nnn.nnn.nnn")];
+       unsigned int dataoff, bufflen;
+
+       dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+       /* Mangle owner and contact info. */
+       bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
+       if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+                              buffer, bufflen, &ct_sip_hdrs[POS_OWNER]))
+               return 0;
+
+       if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+                              buffer, bufflen, &ct_sip_hdrs[POS_CONNECTION]))
+               return 0;
+
+       /* Mangle media port. */
+       bufflen = sprintf(buffer, "%u", port);
+       if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+                              buffer, bufflen, &ct_sip_hdrs[POS_MEDIA]))
+               return 0;
+
+       return mangle_content_len(pskb, ctinfo, ct, dptr);
+}
+
+/* So, this packet has hit the connection tracking matching code.
+   Mangle it, and change the expectation to match the new version. */
+static unsigned int ip_nat_sdp(struct sk_buff **pskb,
+                              enum ip_conntrack_info ctinfo,
+                              struct ip_conntrack_expect *exp,
+                              const char *dptr)
+{
+       struct ip_conntrack *ct = exp->master;
+       enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+       u_int32_t newip;
+       u_int16_t port;
+
+       DEBUGP("ip_nat_sdp():\n");
+
+       /* Connection will come from reply */
+       newip = ct->tuplehash[!dir].tuple.dst.ip;
+
+       exp->tuple.dst.ip = newip;
+       exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
+       exp->dir = !dir;
+
+       /* When you see the packet, we need to NAT it the same as the
+          this one. */
+       exp->expectfn = ip_nat_follow_master;
+
+       /* Try to get same port: if not, try to change it. */
+       for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
+               exp->tuple.dst.u.udp.port = htons(port);
+               if (ip_conntrack_expect_related(exp) == 0)
+                       break;
+       }
+
+       if (port == 0)
+               return NF_DROP;
+
+       if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
+               ip_conntrack_unexpect_related(exp);
+               return NF_DROP;
+       }
+       return NF_ACCEPT;
+}
+
+static void __exit fini(void)
+{
+       ip_nat_sip_hook = NULL;
+       ip_nat_sdp_hook = NULL;
+       /* Make sure noone calls it, meanwhile. */
+       synchronize_net();
+}
+
+static int __init init(void)
+{
+       BUG_ON(ip_nat_sip_hook);
+       BUG_ON(ip_nat_sdp_hook);
+       ip_nat_sip_hook = ip_nat_sip;
+       ip_nat_sdp_hook = ip_nat_sdp;
+       return 0;
+}
+
+module_init(init);
+module_exit(fini);
index c33244263b9035a688c73816487a89c4a5381d62..d20d557f915affc383308ebc793fbdcca8a8bf15 100644 (file)
@@ -1348,4 +1348,4 @@ static void __exit ip_nat_snmp_basic_fini(void)
 module_init(ip_nat_snmp_basic_init);
 module_exit(ip_nat_snmp_basic_fini);
 
-module_param(debug, bool, 0600);
+module_param(debug, int, 0600);
index aad9d28c8d7123dd2a5f8a043fa3658d9970185e..dbc83c5d7aa666f0521722460dbb6ce1f789e8a4 100644 (file)
@@ -241,25 +241,17 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
        struct iphdr *iph = skb->nh.iph;
        unsigned long hashval;
        u_int16_t sport, dport;
-       struct tcphdr *th;
-       struct udphdr *uh;
-       struct icmphdr *ih;
+       u_int16_t *ports;
 
        switch (iph->protocol) {
        case IPPROTO_TCP:
-               th = (void *)iph+iph->ihl*4;
-               sport = ntohs(th->source);
-               dport = ntohs(th->dest);
-               break;
        case IPPROTO_UDP:
-               uh = (void *)iph+iph->ihl*4;
-               sport = ntohs(uh->source);
-               dport = ntohs(uh->dest);
-               break;
+       case IPPROTO_SCTP:
+       case IPPROTO_DCCP:
        case IPPROTO_ICMP:
-               ih = (void *)iph+iph->ihl*4;
-               sport = ntohs(ih->un.echo.id);
-               dport = (ih->type<<8)|ih->code;
+               ports = (void *)iph+iph->ihl*4;
+               sport = ports[0];
+               dport = ports[1];
                break;
        default:
                if (net_ratelimit()) {
index 0bba3c2bb786b831ae9c3bb68213181395ea266e..431a3ce6f7b74b04df91966882811b8508a88d50 100644 (file)
@@ -147,6 +147,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
        /* This packet will not be the same as the other: clear nf fields */
        nf_reset(nskb);
        nskb->nfmark = 0;
+       skb_init_secmark(nskb);
 
        tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
 
index 7c6836c4646e12e772c952d42e0372b5b5c23d34..92980ab8ce489dacaad95a4c259c19855e0cfd01 100644 (file)
@@ -28,9 +28,6 @@
 #include <linux/jhash.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include <linux/sctp.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/list.h>
@@ -83,6 +80,7 @@ struct ipt_hashlimit_htable {
        /* used internally */
        spinlock_t lock;                /* lock for list_head */
        u_int32_t rnd;                  /* random seed for hash */
+       int rnd_initialized;
        struct timer_list timer;        /* timer for gc */
        atomic_t count;                 /* number entries in table */
 
@@ -137,8 +135,10 @@ __dsthash_alloc_init(struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
 
        /* initialize hash with random val at the time we allocate
         * the first hashtable entry */
-       if (!ht->rnd)
+       if (!ht->rnd_initialized) {
                get_random_bytes(&ht->rnd, 4);
+               ht->rnd_initialized = 1;
+       }
 
        if (ht->cfg.max &&
            atomic_read(&ht->count) >= ht->cfg.max) {
@@ -217,7 +217,7 @@ static int htable_create(struct ipt_hashlimit_info *minfo)
 
        atomic_set(&hinfo->count, 0);
        atomic_set(&hinfo->use, 1);
-       hinfo->rnd = 0;
+       hinfo->rnd_initialized = 0;
        spin_lock_init(&hinfo->lock);
        hinfo->pde = create_proc_entry(minfo->name, 0, hashlimit_procdir);
        if (!hinfo->pde) {
@@ -381,49 +381,6 @@ static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
                dh->rateinfo.credit = dh->rateinfo.credit_cap;
 }
 
-static inline int get_ports(const struct sk_buff *skb, int offset, 
-                           u16 ports[2])
-{
-       union {
-               struct tcphdr th;
-               struct udphdr uh;
-               sctp_sctphdr_t sctph;
-       } hdr_u, *ptr_u;
-
-       /* Must not be a fragment. */
-       if (offset)
-               return 1;
-
-       /* Must be big enough to read ports (both UDP and TCP have
-          them at the start). */
-       ptr_u = skb_header_pointer(skb, skb->nh.iph->ihl*4, 8, &hdr_u); 
-       if (!ptr_u)
-               return 1;
-
-       switch (skb->nh.iph->protocol) {
-               case IPPROTO_TCP:
-                       ports[0] = ptr_u->th.source;
-                       ports[1] = ptr_u->th.dest;
-                       break;
-               case IPPROTO_UDP:
-                       ports[0] = ptr_u->uh.source;
-                       ports[1] = ptr_u->uh.dest;
-                       break;
-               case IPPROTO_SCTP:
-                       ports[0] = ptr_u->sctph.source;
-                       ports[1] = ptr_u->sctph.dest;
-                       break;
-               default:
-                       /* all other protocols don't supprot per-port hash
-                        * buckets */
-                       ports[0] = ports[1] = 0;
-                       break;
-       }
-
-       return 0;
-}
-
-
 static int
 hashlimit_match(const struct sk_buff *skb,
                const struct net_device *in,
@@ -449,8 +406,22 @@ hashlimit_match(const struct sk_buff *skb,
                dst.src_ip = skb->nh.iph->saddr;
        if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT
            ||hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT) {
-               u_int16_t ports[2];
-               if (get_ports(skb, offset, ports)) {
+               u_int16_t _ports[2], *ports;
+
+               switch (skb->nh.iph->protocol) {
+               case IPPROTO_TCP:
+               case IPPROTO_UDP:
+               case IPPROTO_SCTP:
+               case IPPROTO_DCCP:
+                       ports = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+                                                  sizeof(_ports), &_ports);
+                       break;
+               default:
+                       _ports[0] = _ports[1] = 0;
+                       ports = _ports;
+                       break;
+               }
+               if (!ports) {
                        /* We've been asked to examine this packet, and we
                          can't.  Hence, no choice but to drop. */
                        *hotdrop = 1;
@@ -561,7 +532,7 @@ static void
 hashlimit_destroy(const struct xt_match *match, void *matchinfo,
                  unsigned int matchsize)
 {
-       struct ipt_hashlimit_info *r = (struct ipt_hashlimit_info *) matchinfo;
+       struct ipt_hashlimit_info *r = matchinfo;
 
        htable_put(r->hinfo);
 }
index b847ee409efbb7146987f526998ccb8ea51422fe..61a2139f9cfd24f5b138b5cbacfe526b3e4fec0f 100644 (file)
-/* Kernel module to check if the source address has been seen recently. */
-/* Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org */
-/* Author: Stephen Frost <sfrost@snowman.net> */
-/* Project Page: http://snowman.net/projects/ipt_recent/ */
-/* This software is distributed under the terms of the GPL, Version 2 */
-/* This copyright does not cover user programs that use kernel services
- * by normal system calls. */
-
-#include <linux/module.h>
-#include <linux/skbuff.h>
+/*
+ * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This is a replacement of the old ipt_recent module, which carried the
+ * following copyright notice:
+ *
+ * Author: Stephen Frost <sfrost@snowman.net>
+ * Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org
+ */
+#include <linux/init.h>
+#include <linux/moduleparam.h>
 #include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <asm/uaccess.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
 #include <linux/ctype.h>
-#include <linux/ip.h>
-#include <linux/vmalloc.h>
-#include <linux/moduleparam.h>
+#include <linux/list.h>
+#include <linux/random.h>
+#include <linux/jhash.h>
+#include <linux/bitops.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
 
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_recent.h>
 
-#undef DEBUG
-#define HASH_LOG 9
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("IP tables recently seen matching module");
+MODULE_LICENSE("GPL");
 
-/* Defaults, these can be overridden on the module command-line. */
 static unsigned int ip_list_tot = 100;
 static unsigned int ip_pkt_list_tot = 20;
 static unsigned int ip_list_hash_size = 0;
 static unsigned int ip_list_perms = 0644;
-#ifdef DEBUG
-static int debug = 1;
-#endif
-
-static char version[] =
-KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>.  http://snowman.net/projects/ipt_recent/\n";
-
-MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
-MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
-MODULE_LICENSE("GPL");
 module_param(ip_list_tot, uint, 0400);
 module_param(ip_pkt_list_tot, uint, 0400);
 module_param(ip_list_hash_size, uint, 0400);
 module_param(ip_list_perms, uint, 0400);
-#ifdef DEBUG
-module_param(debug, bool, 0600);
-MODULE_PARM_DESC(debug,"enable debugging output");
-#endif
-MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
-MODULE_PARM_DESC(ip_pkt_list_tot,"number of packets per IP to remember");
-MODULE_PARM_DESC(ip_list_hash_size,"size of hash table used to look up IPs");
-MODULE_PARM_DESC(ip_list_perms,"permissions on /proc/net/ipt_recent/* files");
-
-/* Structure of our list of recently seen addresses. */
-struct recent_ip_list {
-       u_int32_t addr;
-       u_int8_t  ttl;
-       unsigned long last_seen;
-       unsigned long *last_pkts;
-       u_int32_t oldest_pkt;
-       u_int32_t hash_entry;
-       u_int32_t time_pos;
-};
-
-struct time_info_list {
-       u_int32_t position;
-       u_int32_t time;
+MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list");
+MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP to remember (max. 255)");
+MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs");
+MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/ipt_recent/* files");
+
+
+struct recent_entry {
+       struct list_head        list;
+       struct list_head        lru_list;
+       u_int32_t               addr;
+       u_int8_t                ttl;
+       u_int8_t                index;
+       u_int16_t               nstamps;
+       unsigned long           stamps[0];
 };
 
-/* Structure of our linked list of tables of recent lists. */
-struct recent_ip_tables {
-       char name[IPT_RECENT_NAME_LEN];
-       int count;
-       int time_pos;
-       struct recent_ip_list *table;
-       struct recent_ip_tables *next;
-       spinlock_t list_lock;
-       int *hash_table;
-       struct time_info_list *time_info;
+struct recent_table {
+       struct list_head        list;
+       char                    name[IPT_RECENT_NAME_LEN];
 #ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *status_proc;
-#endif /* CONFIG_PROC_FS */
+       struct proc_dir_entry   *proc;
+#endif
+       unsigned int            refcnt;
+       unsigned int            entries;
+       struct list_head        lru_list;
+       struct list_head        iphash[0];
 };
 
-/* Our current list of addresses we have recently seen.
- * Only added to on a --set, and only updated on --set || --update 
- */
-static struct recent_ip_tables *r_tables = NULL;
-
-/* We protect r_list with this spinlock so two processors are not modifying
- * the list at the same time. 
- */
+static LIST_HEAD(tables);
 static DEFINE_SPINLOCK(recent_lock);
+static DEFINE_MUTEX(recent_mutex);
 
 #ifdef CONFIG_PROC_FS
-/* Our /proc/net/ipt_recent entry */
-static struct proc_dir_entry *proc_net_ipt_recent = NULL;
-#endif
-
-/* Function declaration for later. */
-static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop);
-
-/* Function to hash a given address into the hash table of table_size size */
-static int hash_func(unsigned int addr, int table_size)
-{
-       int result = 0;
-       unsigned int value = addr;
-       do { result ^= value; } while((value >>= HASH_LOG));
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": %d = hash_func(%u,%d)\n",
-                        result & (table_size - 1),
-                        addr,
-                        table_size);
+static struct proc_dir_entry   *proc_dir;
+static struct file_operations  recent_fops;
 #endif
 
-       return(result & (table_size - 1));
-}
+static u_int32_t hash_rnd;
+static int hash_rnd_initted;
 
-#ifdef CONFIG_PROC_FS
-/* This is the function which produces the output for our /proc output
- * interface which lists each IP address, the last seen time and the 
- * other recent times the address was seen.
- */
-
-static int ip_recent_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+static unsigned int recent_entry_hash(u_int32_t addr)
 {
-       int len = 0, count, last_len = 0, pkt_count;
-       off_t pos = 0;
-       off_t begin = 0;
-       struct recent_ip_tables *curr_table;
-
-       curr_table = (struct recent_ip_tables*) data;
-
-       spin_lock_bh(&curr_table->list_lock);
-       for(count = 0; count < ip_list_tot; count++) {
-               if(!curr_table->table[count].addr) continue;
-               last_len = len;
-               len += sprintf(buffer+len,"src=%u.%u.%u.%u ",NIPQUAD(curr_table->table[count].addr));
-               len += sprintf(buffer+len,"ttl: %u ",curr_table->table[count].ttl);
-               len += sprintf(buffer+len,"last_seen: %lu ",curr_table->table[count].last_seen);
-               len += sprintf(buffer+len,"oldest_pkt: %u ",curr_table->table[count].oldest_pkt);
-               len += sprintf(buffer+len,"last_pkts: %lu",curr_table->table[count].last_pkts[0]);
-               for(pkt_count = 1; pkt_count < ip_pkt_list_tot; pkt_count++) {
-                       if(!curr_table->table[count].last_pkts[pkt_count]) break;
-                       len += sprintf(buffer+len,", %lu",curr_table->table[count].last_pkts[pkt_count]);
-               }
-               len += sprintf(buffer+len,"\n");
-               pos = begin + len;
-               if(pos < offset) { len = 0; begin = pos; }
-               if(pos > offset + length) { len = last_len; break; }
+       if (!hash_rnd_initted) {
+               get_random_bytes(&hash_rnd, 4);
+               hash_rnd_initted = 1;
        }
-
-       *start = buffer + (offset - begin);
-       len -= (offset - begin);
-       if(len > length) len = length;
-
-       spin_unlock_bh(&curr_table->list_lock);
-       return len;
+       return jhash_1word(addr, hash_rnd) & (ip_list_hash_size - 1);
 }
 
-/* ip_recent_ctrl provides an interface for users to modify the table
- * directly.  This allows adding entries, removing entries, and
- * flushing the entire table.
- * This is done by opening up the appropriate table for writing and
- * sending one of:
- * xx.xx.xx.xx   -- Add entry to table with current time
- * +xx.xx.xx.xx  -- Add entry to table with current time
- * -xx.xx.xx.xx  -- Remove entry from table
- * clear         -- Flush table, remove all entries
- */
-
-static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned long size, void *data)
+static struct recent_entry *
+recent_entry_lookup(const struct recent_table *table, u_int32_t addr, u_int8_t ttl)
 {
-       static const u_int32_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
-       u_int32_t val;
-       int base, used = 0;
-       char c, *cp;
-       union iaddr {
-               uint8_t bytes[4];
-               uint32_t word;
-       } res;
-       uint8_t *pp = res.bytes;
-       int digit;
-
-       char buffer[20];
-       int len, check_set = 0, count;
-       u_int32_t addr = 0;
-       struct sk_buff *skb;
-       struct ipt_recent_info *info;
-       struct recent_ip_tables *curr_table;
-
-       curr_table = (struct recent_ip_tables*) data;
-
-       if(size > 20) len = 20; else len = size;
-
-       if(copy_from_user(buffer,input,len)) return -EFAULT;
-
-       if(len < 20) buffer[len] = '\0';
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl len: %d, input: `%.20s'\n",len,buffer);
-#endif
+       struct recent_entry *e;
+       unsigned int h;
+
+       h = recent_entry_hash(addr);
+       list_for_each_entry(e, &table->iphash[h], list)
+               if (e->addr == addr && (ttl == e->ttl || !ttl || !e->ttl))
+                       return e;
+       return NULL;
+}
 
-       cp = buffer;
-       while(isspace(*cp)) { cp++; used++; if(used >= len-5) return used; }
+static void recent_entry_remove(struct recent_table *t, struct recent_entry *e)
+{
+       list_del(&e->list);
+       list_del(&e->lru_list);
+       kfree(e);
+       t->entries--;
+}
 
-       /* Check if we are asked to flush the entire table */
-       if(!memcmp(cp,"clear",5)) {
-               used += 5;
-               spin_lock_bh(&curr_table->list_lock);
-               curr_table->time_pos = 0;
-               for(count = 0; count < ip_list_hash_size; count++) {
-                       curr_table->hash_table[count] = -1;
-               }
-               for(count = 0; count < ip_list_tot; count++) {
-                       curr_table->table[count].last_seen = 0;
-                       curr_table->table[count].addr = 0;
-                       curr_table->table[count].ttl = 0;
-                       memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
-                       curr_table->table[count].oldest_pkt = 0;
-                       curr_table->table[count].time_pos = 0;
-                       curr_table->time_info[count].position = count;
-                       curr_table->time_info[count].time = 0;
-               }
-               spin_unlock_bh(&curr_table->list_lock);
-               return used;
-       }
+static struct recent_entry *
+recent_entry_init(struct recent_table *t, u_int32_t addr, u_int8_t ttl)
+{
+       struct recent_entry *e;
 
-        check_set = IPT_RECENT_SET;
-       switch(*cp) {
-               case '+': check_set = IPT_RECENT_SET; cp++; used++; break;
-               case '-': check_set = IPT_RECENT_REMOVE; cp++; used++; break;
-               default: if(!isdigit(*cp)) return (used+1); break;
+       if (t->entries >= ip_list_tot) {
+               e = list_entry(t->lru_list.next, struct recent_entry, lru_list);
+               recent_entry_remove(t, e);
        }
+       e = kmalloc(sizeof(*e) + sizeof(e->stamps[0]) * ip_pkt_list_tot,
+                   GFP_ATOMIC);
+       if (e == NULL)
+               return NULL;
+       e->addr      = addr;
+       e->ttl       = ttl;
+       e->stamps[0] = jiffies;
+       e->nstamps   = 1;
+       e->index     = 1;
+       list_add_tail(&e->list, &t->iphash[recent_entry_hash(addr)]);
+       list_add_tail(&e->lru_list, &t->lru_list);
+       t->entries++;
+       return e;
+}
 
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl cp: `%c', check_set: %d\n",*cp,check_set);
-#endif
-       /* Get addr (effectively inet_aton()) */
-       /* Shamelessly stolen from libc, a function in the kernel for doing
-        * this would, of course, be greatly preferred, but our options appear
-        * to be rather limited, so we will just do it ourselves here.
-        */
-       res.word = 0;
-
-       c = *cp;
-       for(;;) {
-               if(!isdigit(c)) return used;
-               val = 0; base = 10; digit = 0;
-               if(c == '0') {
-                       c = *++cp;
-                       if(c == 'x' || c == 'X') base = 16, c = *++cp;
-                       else { base = 8; digit = 1; }
-               }
-               for(;;) {
-                       if(isascii(c) && isdigit(c)) {
-                               if(base == 8 && (c == '8' || c == '0')) return used;
-                               val = (val * base) + (c - '0');
-                               c = *++cp;
-                               digit = 1;
-                       } else if(base == 16 && isascii(c) && isxdigit(c)) {
-                               val = (val << 4) | (c + 10 - (islower(c) ? 'a' : 'A'));
-                               c = *++cp;
-                               digit = 1;
-                       } else break;
-               }
-               if(c == '.') {
-                       if(pp > res.bytes + 2 || val > 0xff) return used;
-                       *pp++ = val;
-                       c = *++cp;
-               } else break;
-       }
-       used = cp - buffer;
-       if(c != '\0' && (!isascii(c) || !isspace(c))) return used;
-       if(c == '\n') used++;
-       if(!digit) return used;
+static void recent_entry_update(struct recent_table *t, struct recent_entry *e)
+{
+       e->stamps[e->index++] = jiffies;
+       if (e->index > e->nstamps)
+               e->nstamps = e->index;
+       e->index %= ip_pkt_list_tot;
+       list_move_tail(&e->lru_list, &t->lru_list);
+}
 
-       if(val > max[pp - res.bytes]) return used;
-       addr = res.word | htonl(val);
+static struct recent_table *recent_table_lookup(const char *name)
+{
+       struct recent_table *t;
 
-       if(!addr && check_set == IPT_RECENT_SET) return used;
+       list_for_each_entry(t, &tables, list)
+               if (!strcmp(t->name, name))
+                       return t;
+       return NULL;
+}
 
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl c: %c, addr: %u used: %d\n",c,addr,used);
-#endif
+static void recent_table_flush(struct recent_table *t)
+{
+       struct recent_entry *e, *next;
+       unsigned int i;
 
-       /* Set up and just call match */
-       info = kmalloc(sizeof(struct ipt_recent_info),GFP_KERNEL);
-       if(!info) { return -ENOMEM; }
-       info->seconds = 0;
-       info->hit_count = 0;
-       info->check_set = check_set;
-       info->invert = 0;
-       info->side = IPT_RECENT_SOURCE;
-       strncpy(info->name,curr_table->name,IPT_RECENT_NAME_LEN);
-       info->name[IPT_RECENT_NAME_LEN-1] = '\0';
-
-       skb = kmalloc(sizeof(struct sk_buff),GFP_KERNEL);
-       if (!skb) {
-               used = -ENOMEM;
-               goto out_free_info;
-       }
-       skb->nh.iph = kmalloc(sizeof(struct iphdr),GFP_KERNEL);
-       if (!skb->nh.iph) {
-               used = -ENOMEM;
-               goto out_free_skb;
+       for (i = 0; i < ip_list_hash_size; i++) {
+               list_for_each_entry_safe(e, next, &t->iphash[i], list)
+                       recent_entry_remove(t, e);
        }
-
-       skb->nh.iph->saddr = addr;
-       skb->nh.iph->daddr = 0;
-       /* Clear ttl since we have no way of knowing it */
-       skb->nh.iph->ttl = 0;
-       match(skb,NULL,NULL,NULL,info,0,0,NULL);
-
-       kfree(skb->nh.iph);
-out_free_skb:
-       kfree(skb);
-out_free_info:
-       kfree(info);
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": Leaving ip_recent_ctrl addr: %u used: %d\n",addr,used);
-#endif
-       return used;
 }
 
-#endif /* CONFIG_PROC_FS */
-
-/* 'match' is our primary function, called by the kernel whenever a rule is
- * hit with our module as an option to it.
- * What this function does depends on what was specifically asked of it by
- * the user:
- * --set -- Add or update last seen time of the source address of the packet
- *   -- matchinfo->check_set == IPT_RECENT_SET
- * --rcheck -- Just check if the source address is in the list
- *   -- matchinfo->check_set == IPT_RECENT_CHECK
- * --update -- If the source address is in the list, update last_seen
- *   -- matchinfo->check_set == IPT_RECENT_UPDATE
- * --remove -- If the source address is in the list, remove it
- *   -- matchinfo->check_set == IPT_RECENT_REMOVE
- * --seconds -- Option to --rcheck/--update, only match if last_seen within seconds
- *   -- matchinfo->seconds
- * --hitcount -- Option to --rcheck/--update, only match if seen hitcount times
- *   -- matchinfo->hit_count
- * --seconds and --hitcount can be combined
- */
 static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop)
+ipt_recent_match(const struct sk_buff *skb,
+                const struct net_device *in, const struct net_device *out,
+                const struct xt_match *match, const void *matchinfo,
+                int offset, unsigned int protoff, int *hotdrop)
 {
-       int pkt_count, hits_found, ans;
-       unsigned long now;
        const struct ipt_recent_info *info = matchinfo;
-       u_int32_t addr = 0, time_temp;
-       u_int8_t ttl = skb->nh.iph->ttl;
-       int *hash_table;
-       int orig_hash_result, hash_result, temp, location = 0, time_loc, end_collision_chain = -1;
-       struct time_info_list *time_info;
-       struct recent_ip_tables *curr_table;
-       struct recent_ip_tables *last_table;
-       struct recent_ip_list *r_list;
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": match() called\n");
-#endif
-
-       /* Default is false ^ info->invert */
-       ans = info->invert;
+       struct recent_table *t;
+       struct recent_entry *e;
+       u_int32_t addr;
+       u_int8_t ttl;
+       int ret = info->invert;
 
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": match(): name = '%s'\n",info->name);
-#endif
+       if (info->side == IPT_RECENT_DEST)
+               addr = skb->nh.iph->daddr;
+       else
+               addr = skb->nh.iph->saddr;
 
-       /* if out != NULL then routing has been done and TTL changed.
-        * We change it back here internally for match what came in before routing. */
-       if(out) ttl++;
+       ttl = skb->nh.iph->ttl;
+       /* use TTL as seen before forwarding */
+       if (out && !skb->sk)
+               ttl++;
 
-       /* Find the right table */
        spin_lock_bh(&recent_lock);
-       curr_table = r_tables;
-       while( (last_table = curr_table) && strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (curr_table = curr_table->next) );
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": match(): table found('%s')\n",info->name);
-#endif
-
-       spin_unlock_bh(&recent_lock);
-
-       /* Table with this name not found, match impossible */
-       if(!curr_table) { return ans; }
-
-       /* Make sure no one is changing the list while we work with it */
-       spin_lock_bh(&curr_table->list_lock);
-
-       r_list = curr_table->table;
-       if(info->side == IPT_RECENT_DEST) addr = skb->nh.iph->daddr; else addr = skb->nh.iph->saddr;
-
-       if(!addr) { 
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": match() address (%u) invalid, leaving.\n",addr);
-#endif
-               spin_unlock_bh(&curr_table->list_lock);
-               return ans;
-       }
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": match(): checking table, addr: %u, ttl: %u, orig_ttl: %u\n",addr,ttl,skb->nh.iph->ttl);
-#endif
-
-       /* Get jiffies now in case they changed while we were waiting for a lock */
-       now = jiffies;
-       hash_table = curr_table->hash_table;
-       time_info = curr_table->time_info;
-
-       orig_hash_result = hash_result = hash_func(addr,ip_list_hash_size);
-       /* Hash entry at this result used */
-       /* Check for TTL match if requested.  If TTL is zero then a match would never
-        * happen, so match regardless of existing TTL in that case.  Zero means the
-        * entry was added via the /proc interface anyway, so we will just use the
-        * first TTL we get for that IP address. */
-       if(info->check_set & IPT_RECENT_TTL) {
-               while(hash_table[hash_result] != -1 && !(r_list[hash_table[hash_result]].addr == addr &&
-                       (!r_list[hash_table[hash_result]].ttl || r_list[hash_table[hash_result]].ttl == ttl))) {
-                       /* Collision in hash table */
-                       hash_result = (hash_result + 1) % ip_list_hash_size;
-               }
-       } else {
-               while(hash_table[hash_result] != -1 && r_list[hash_table[hash_result]].addr != addr) {
-                       /* Collision in hash table */
-                       hash_result = (hash_result + 1) % ip_list_hash_size;
-               }
-       }
-
-       if(hash_table[hash_result] == -1 && !(info->check_set & IPT_RECENT_SET)) {
-               /* IP not in list and not asked to SET */
-               spin_unlock_bh(&curr_table->list_lock);
-               return ans;
-       }
-
-       /* Check if we need to handle the collision, do not need to on REMOVE */
-       if(orig_hash_result != hash_result && !(info->check_set & IPT_RECENT_REMOVE)) {
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision in hash table. (or: %d,hr: %d,oa: %u,ha: %u)\n",
-                                orig_hash_result,
-                                hash_result,
-                                r_list[hash_table[orig_hash_result]].addr,
-                                addr);
-#endif
-
-               /* We had a collision.
-                * orig_hash_result is where we started, hash_result is where we ended up.
-                * So, swap them because we are likely to see the same guy again sooner */
-#ifdef DEBUG
-               if(debug) {
-                 printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[orig_hash_result] = %d\n",hash_table[orig_hash_result]);
-                 printk(KERN_INFO RECENT_NAME ": match(): Collision; r_list[hash_table[orig_hash_result]].hash_entry = %d\n",
-                               r_list[hash_table[orig_hash_result]].hash_entry);
-               }
-#endif
-
-               r_list[hash_table[orig_hash_result]].hash_entry = hash_result;
-
-
-               temp = hash_table[orig_hash_result];
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[hash_result] = %d\n",hash_table[hash_result]);
-#endif
-               hash_table[orig_hash_result] = hash_table[hash_result];
-               hash_table[hash_result] = temp;
-               temp = hash_result;
-               hash_result = orig_hash_result;
-               orig_hash_result = temp;
-               time_info[r_list[hash_table[orig_hash_result]].time_pos].position = hash_table[orig_hash_result];
-               if(hash_table[hash_result] != -1) {
-                       r_list[hash_table[hash_result]].hash_entry = hash_result;
-                       time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
-               }
-
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision handled.\n");
-#endif
+       t = recent_table_lookup(info->name);
+       e = recent_entry_lookup(t, addr,
+                               info->check_set & IPT_RECENT_TTL ? ttl : 0);
+       if (e == NULL) {
+               if (!(info->check_set & IPT_RECENT_SET))
+                       goto out;
+               e = recent_entry_init(t, addr, ttl);
+               if (e == NULL)
+                       *hotdrop = 1;
+               ret ^= 1;
+               goto out;
        }
 
-       if(hash_table[hash_result] == -1) {
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": match(): New table entry. (hr: %d,ha: %u)\n",
-                                hash_result, addr);
-#endif
-
-               /* New item found and IPT_RECENT_SET, so we need to add it */
-               location = time_info[curr_table->time_pos].position;
-               hash_table[r_list[location].hash_entry] = -1;
-               hash_table[hash_result] = location;
-               memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
-               r_list[location].time_pos = curr_table->time_pos;
-               r_list[location].addr = addr;
-               r_list[location].ttl = ttl;
-               r_list[location].last_seen = now;
-               r_list[location].oldest_pkt = 1;
-               r_list[location].last_pkts[0] = now;
-               r_list[location].hash_entry = hash_result;
-               time_info[curr_table->time_pos].time = r_list[location].last_seen;
-               curr_table->time_pos = (curr_table->time_pos + 1) % ip_list_tot;
-
-               ans = !info->invert;
-       } else {
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": match(): Existing table entry. (hr: %d,ha: %u)\n",
-                                hash_result,
-                                addr);
-#endif
-
-               /* Existing item found */
-               location = hash_table[hash_result];
-               /* We have a match on address, now to make sure it meets all requirements for a
-                * full match. */
-               if(info->check_set & IPT_RECENT_CHECK || info->check_set & IPT_RECENT_UPDATE) {
-                       if(!info->seconds && !info->hit_count) ans = !info->invert; else ans = info->invert;
-                       if(info->seconds && !info->hit_count) {
-                               if(time_before_eq(now,r_list[location].last_seen+info->seconds*HZ)) ans = !info->invert; else ans = info->invert;
-                       }
-                       if(info->seconds && info->hit_count) {
-                               for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {
-                                       if(r_list[location].last_pkts[pkt_count] == 0) break;
-                                       if(time_before_eq(now,r_list[location].last_pkts[pkt_count]+info->seconds*HZ)) hits_found++;
-                               }
-                               if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
-                       }
-                       if(info->hit_count && !info->seconds) {
-                               for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {
-                                       if(r_list[location].last_pkts[pkt_count] == 0) break;
-                                       hits_found++;
-                               }
-                               if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
+       if (info->check_set & IPT_RECENT_SET)
+               ret ^= 1;
+       else if (info->check_set & IPT_RECENT_REMOVE) {
+               recent_entry_remove(t, e);
+               ret ^= 1;
+       } else if (info->check_set & (IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) {
+               unsigned long t = jiffies - info->seconds * HZ;
+               unsigned int i, hits = 0;
+
+               for (i = 0; i < e->nstamps; i++) {
+                       if (info->seconds && time_after(t, e->stamps[i]))
+                               continue;
+                       if (++hits >= info->hit_count) {
+                               ret ^= 1;
+                               break;
                        }
                }
-#ifdef DEBUG
-               if(debug) {
-                       if(ans)
-                               printk(KERN_INFO RECENT_NAME ": match(): match addr: %u\n",addr);
-                       else
-                               printk(KERN_INFO RECENT_NAME ": match(): no match addr: %u\n",addr);
-               }
-#endif
-
-               /* If and only if we have been asked to SET, or to UPDATE (on match) do we add the
-                * current timestamp to the last_seen. */
-               if((info->check_set & IPT_RECENT_SET && (ans = !info->invert)) || (info->check_set & IPT_RECENT_UPDATE && ans)) {
-#ifdef DEBUG
-                       if(debug) printk(KERN_INFO RECENT_NAME ": match(): SET or UPDATE; updating time info.\n");
-#endif
-                       /* Have to update our time info */
-                       time_loc = r_list[location].time_pos;
-                       time_info[time_loc].time = now;
-                       time_info[time_loc].position = location;
-                       while((time_info[(time_loc+1) % ip_list_tot].time < time_info[time_loc].time) && ((time_loc+1) % ip_list_tot) != curr_table->time_pos) {
-                               time_temp = time_info[time_loc].time;
-                               time_info[time_loc].time = time_info[(time_loc+1)%ip_list_tot].time;
-                               time_info[(time_loc+1)%ip_list_tot].time = time_temp;
-                               time_temp = time_info[time_loc].position;
-                               time_info[time_loc].position = time_info[(time_loc+1)%ip_list_tot].position;
-                               time_info[(time_loc+1)%ip_list_tot].position = time_temp;
-                               r_list[time_info[time_loc].position].time_pos = time_loc;
-                               r_list[time_info[(time_loc+1)%ip_list_tot].position].time_pos = (time_loc+1)%ip_list_tot;
-                               time_loc = (time_loc+1) % ip_list_tot;
-                       }
-                       r_list[location].time_pos = time_loc;
-                       r_list[location].ttl = ttl;
-                       r_list[location].last_pkts[r_list[location].oldest_pkt] = now;
-                       r_list[location].oldest_pkt = ++r_list[location].oldest_pkt % ip_pkt_list_tot;
-                       r_list[location].last_seen = now;
-               }
-               /* If we have been asked to remove the entry from the list, just set it to 0 */
-               if(info->check_set & IPT_RECENT_REMOVE) {
-#ifdef DEBUG
-                       if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; clearing entry (or: %d, hr: %d).\n",orig_hash_result,hash_result);
-#endif
-                       /* Check if this is part of a collision chain */
-                       while(hash_table[(orig_hash_result+1) % ip_list_hash_size] != -1) {
-                               orig_hash_result++;
-                               if(hash_func(r_list[hash_table[orig_hash_result]].addr,ip_list_hash_size) == hash_result) {
-                                       /* Found collision chain, how deep does this rabbit hole go? */
-#ifdef DEBUG
-                                       if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; found collision chain.\n");
-#endif
-                                       end_collision_chain = orig_hash_result;
-                               }
-                       }
-                       if(end_collision_chain != -1) {
-#ifdef DEBUG
-                               if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; part of collision chain, moving to end.\n");
-#endif
-                               /* Part of a collision chain, swap it with the end of the chain
-                                * before removing. */
-                               r_list[hash_table[end_collision_chain]].hash_entry = hash_result;
-                               temp = hash_table[end_collision_chain];
-                               hash_table[end_collision_chain] = hash_table[hash_result];
-                               hash_table[hash_result] = temp;
-                               time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
-                               hash_result = end_collision_chain;
-                               r_list[hash_table[hash_result]].hash_entry = hash_result;
-                               time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
-                       }
-                       location = hash_table[hash_result];
-                       hash_table[r_list[location].hash_entry] = -1;
-                       time_loc = r_list[location].time_pos;
-                       time_info[time_loc].time = 0;
-                       time_info[time_loc].position = location;
-                       while((time_info[(time_loc+1) % ip_list_tot].time < time_info[time_loc].time) && ((time_loc+1) % ip_list_tot) != curr_table->time_pos) {
-                               time_temp = time_info[time_loc].time;
-                               time_info[time_loc].time = time_info[(time_loc+1)%ip_list_tot].time;
-                               time_info[(time_loc+1)%ip_list_tot].time = time_temp;
-                               time_temp = time_info[time_loc].position;
-                               time_info[time_loc].position = time_info[(time_loc+1)%ip_list_tot].position;
-                               time_info[(time_loc+1)%ip_list_tot].position = time_temp;
-                               r_list[time_info[time_loc].position].time_pos = time_loc;
-                               r_list[time_info[(time_loc+1)%ip_list_tot].position].time_pos = (time_loc+1)%ip_list_tot;
-                               time_loc = (time_loc+1) % ip_list_tot;
-                       }
-                       r_list[location].time_pos = time_loc;
-                       r_list[location].last_seen = 0;
-                       r_list[location].addr = 0;
-                       r_list[location].ttl = 0;
-                       memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
-                       r_list[location].oldest_pkt = 0;
-                       ans = !info->invert;
-               }
-               spin_unlock_bh(&curr_table->list_lock);
-               return ans;
        }
 
-       spin_unlock_bh(&curr_table->list_lock);
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": match() left.\n");
-#endif
-       return ans;
+       if (info->check_set & IPT_RECENT_SET ||
+           (info->check_set & IPT_RECENT_UPDATE && ret)) {
+               recent_entry_update(t, e);
+               e->ttl = ttl;
+       }
+out:
+       spin_unlock_bh(&recent_lock);
+       return ret;
 }
 
-/* This function is to verify that the rule given during the userspace iptables
- * command is correct.
- * If the command is valid then we check if the table name referred to by the
- * rule exists, if not it is created.
- */
 static int
-checkentry(const char *tablename,
-           const void *ip,
-          const struct xt_match *match,
-           void *matchinfo,
-           unsigned int matchsize,
-           unsigned int hook_mask)
+ipt_recent_checkentry(const char *tablename, const void *ip,
+                     const struct xt_match *match, void *matchinfo,
+                     unsigned int matchsize, unsigned int hook_mask)
 {
-       int flag = 0, c;
-       unsigned long *hold;
        const struct ipt_recent_info *info = matchinfo;
-       struct recent_ip_tables *curr_table, *find_table, *last_table;
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n");
-#endif
-
-       /* seconds and hit_count only valid for CHECK/UPDATE */
-       if(info->check_set & IPT_RECENT_SET) { flag++; if(info->seconds || info->hit_count) return 0; }
-       if(info->check_set & IPT_RECENT_REMOVE) { flag++; if(info->seconds || info->hit_count) return 0; }
-       if(info->check_set & IPT_RECENT_CHECK) flag++;
-       if(info->check_set & IPT_RECENT_UPDATE) flag++;
-
-       /* One and only one of these should ever be set */
-       if(flag != 1) return 0;
-
-       /* Name must be set to something */
-       if(!info->name || !info->name[0]) return 0;
+       struct recent_table *t;
+       unsigned i;
+       int ret = 0;
 
-       /* Things look good, create a list for this if it does not exist */
-       /* Lock the linked list while we play with it */
-       spin_lock_bh(&recent_lock);
-
-       /* Look for an entry with this name already created */
-       /* Finds the end of the list and the entry before the end if current name does not exist */
-       find_table = r_tables;
-       while( (last_table = find_table) && strncmp(info->name,find_table->name,IPT_RECENT_NAME_LEN) && (find_table = find_table->next) );
+       if (hweight8(info->check_set &
+                    (IPT_RECENT_SET | IPT_RECENT_REMOVE |
+                     IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) != 1)
+               return 0;
+       if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) &&
+           (info->seconds || info->hit_count))
+               return 0;
+       if (info->name[0] == '\0' ||
+           strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
+               return 0;
 
-       /* If a table already exists just increment the count on that table and return */
-       if(find_table) { 
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: table found (%s), incrementing count.\n",info->name);
-#endif
-               find_table->count++;
-               spin_unlock_bh(&recent_lock);
-               return 1;
+       mutex_lock(&recent_mutex);
+       t = recent_table_lookup(info->name);
+       if (t != NULL) {
+               t->refcnt++;
+               ret = 1;
+               goto out;
        }
 
-       spin_unlock_bh(&recent_lock);
-
-       /* Table with this name not found */
-       /* Allocate memory for new linked list item */
-
-#ifdef DEBUG
-       if(debug) {
-               printk(KERN_INFO RECENT_NAME ": checkentry: no table found (%s)\n",info->name);
-               printk(KERN_INFO RECENT_NAME ": checkentry: Allocationg %d for link-list entry.\n",sizeof(struct recent_ip_tables));
+       t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
+                   GFP_KERNEL);
+       if (t == NULL)
+               goto out;
+       t->refcnt = 1;
+       strcpy(t->name, info->name);
+       INIT_LIST_HEAD(&t->lru_list);
+       for (i = 0; i < ip_list_hash_size; i++)
+               INIT_LIST_HEAD(&t->iphash[i]);
+#ifdef CONFIG_PROC_FS
+       t->proc = create_proc_entry(t->name, ip_list_perms, proc_dir);
+       if (t->proc == NULL) {
+               kfree(t);
+               goto out;
        }
+       t->proc->proc_fops = &recent_fops;
+       t->proc->data      = t;
 #endif
+       spin_lock_bh(&recent_lock);
+       list_add_tail(&t->list, &tables);
+       spin_unlock_bh(&recent_lock);
+       ret = 1;
+out:
+       mutex_unlock(&recent_mutex);
+       return ret;
+}
 
-       curr_table = vmalloc(sizeof(struct recent_ip_tables));
-       if(curr_table == NULL) return 0;
-
-       spin_lock_init(&curr_table->list_lock);
-       curr_table->next = NULL;
-       curr_table->count = 1;
-       curr_table->time_pos = 0;
-       strncpy(curr_table->name,info->name,IPT_RECENT_NAME_LEN);
-       curr_table->name[IPT_RECENT_NAME_LEN-1] = '\0';
-
-       /* Allocate memory for this table and the list of packets in each entry. */
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for table (%s).\n",
-                       sizeof(struct recent_ip_list)*ip_list_tot,
-                       info->name);
-#endif
-
-       curr_table->table = vmalloc(sizeof(struct recent_ip_list)*ip_list_tot);
-       if(curr_table->table == NULL) { vfree(curr_table); return 0; }
-       memset(curr_table->table,0,sizeof(struct recent_ip_list)*ip_list_tot);
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for pkt_list.\n",
-                       sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
-#endif
-
-       hold = vmalloc(sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: After pkt_list allocation.\n");
-#endif
-       if(hold == NULL) { 
-               printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for pkt_list.\n");
-               vfree(curr_table->table); 
-               vfree(curr_table);
-               return 0;
-       }
-       for(c = 0; c < ip_list_tot; c++) {
-               curr_table->table[c].last_pkts = hold + c*ip_pkt_list_tot;
-       }
+static void
+ipt_recent_destroy(const struct xt_match *match, void *matchinfo,
+                  unsigned int matchsize)
+{
+       const struct ipt_recent_info *info = matchinfo;
+       struct recent_table *t;
 
-       /* Allocate memory for the hash table */
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for hash_table.\n",
-                       sizeof(int)*ip_list_hash_size);
+       mutex_lock(&recent_mutex);
+       t = recent_table_lookup(info->name);
+       if (--t->refcnt == 0) {
+               spin_lock_bh(&recent_lock);
+               list_del(&t->list);
+               spin_unlock_bh(&recent_lock);
+               recent_table_flush(t);
+#ifdef CONFIG_PROC_FS
+               remove_proc_entry(t->name, proc_dir);
 #endif
-
-       curr_table->hash_table = vmalloc(sizeof(int)*ip_list_hash_size);
-       if(!curr_table->hash_table) {
-               printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for hash_table.\n");
-               vfree(hold);
-               vfree(curr_table->table); 
-               vfree(curr_table);
-               return 0;
-       }
-
-       for(c = 0; c < ip_list_hash_size; c++) {
-               curr_table->hash_table[c] = -1;
+               kfree(t);
        }
+       mutex_unlock(&recent_mutex);
+}
 
-       /* Allocate memory for the time info */
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for time_info.\n",
-                       sizeof(struct time_info_list)*ip_list_tot);
-#endif
+#ifdef CONFIG_PROC_FS
+struct recent_iter_state {
+       struct recent_table     *table;
+       unsigned int            bucket;
+};
 
-       curr_table->time_info = vmalloc(sizeof(struct time_info_list)*ip_list_tot);
-       if(!curr_table->time_info) {
-               printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for time_info.\n");
-               vfree(curr_table->hash_table);
-               vfree(hold);
-               vfree(curr_table->table); 
-               vfree(curr_table);
-               return 0;
-       }
-       for(c = 0; c < ip_list_tot; c++) {
-               curr_table->time_info[c].position = c;
-               curr_table->time_info[c].time = 0;
-       }
+static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       struct recent_iter_state *st = seq->private;
+       struct recent_table *t = st->table;
+       struct recent_entry *e;
+       loff_t p = *pos;
 
-       /* Put the new table in place */
        spin_lock_bh(&recent_lock);
-       find_table = r_tables;
-       while( (last_table = find_table) && strncmp(info->name,find_table->name,IPT_RECENT_NAME_LEN) && (find_table = find_table->next) );
-
-       /* If a table already exists just increment the count on that table and return */
-       if(find_table) { 
-               find_table->count++;    
-               spin_unlock_bh(&recent_lock);
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: table found (%s), created by other process.\n",info->name);
-#endif
-               vfree(curr_table->time_info);
-               vfree(curr_table->hash_table);
-               vfree(hold);
-               vfree(curr_table->table);
-               vfree(curr_table);
-               return 1;
-       }
-       if(!last_table) r_tables = curr_table; else last_table->next = curr_table;
-
-       spin_unlock_bh(&recent_lock);
 
-#ifdef CONFIG_PROC_FS
-       /* Create our proc 'status' entry. */
-       curr_table->status_proc = create_proc_entry(curr_table->name, ip_list_perms, proc_net_ipt_recent);
-       if (!curr_table->status_proc) {
-               vfree(hold);
-               printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for /proc entry.\n");
-               /* Destroy the created table */
-               spin_lock_bh(&recent_lock);
-               last_table = NULL;
-               curr_table = r_tables;
-               if(!curr_table) {
-#ifdef DEBUG
-                       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, no tables.\n");
-#endif
-                       spin_unlock_bh(&recent_lock);
-                       return 0;
-               }
-               while( strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
-               if(!curr_table) {
-#ifdef DEBUG
-                       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, table already destroyed.\n");
-#endif
-                       spin_unlock_bh(&recent_lock);
-                       return 0;
+       for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++) {
+               list_for_each_entry(e, &t->iphash[st->bucket], list) {
+                       if (p-- == 0)
+                               return e;
                }
-               if(last_table) last_table->next = curr_table->next; else r_tables = curr_table->next;
-               spin_unlock_bh(&recent_lock);
-               vfree(curr_table->time_info);
-               vfree(curr_table->hash_table);
-               vfree(curr_table->table);
-               vfree(curr_table);
-               return 0;
        }
-       
-       curr_table->status_proc->owner = THIS_MODULE;
-       curr_table->status_proc->data = curr_table;
-       wmb();
-       curr_table->status_proc->read_proc = ip_recent_get_info;
-       curr_table->status_proc->write_proc = ip_recent_ctrl;
-#endif /* CONFIG_PROC_FS */
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() left.\n");
-#endif
+       return NULL;
+}
 
-       return 1;
+static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       struct recent_iter_state *st = seq->private;
+       struct recent_table *t = st->table;
+       struct recent_entry *e = v;
+       struct list_head *head = e->list.next;
+
+       while (head == &t->iphash[st->bucket]) {
+               if (++st->bucket >= ip_list_hash_size)
+                       return NULL;
+               head = t->iphash[st->bucket].next;
+       }
+       (*pos)++;
+       return list_entry(head, struct recent_entry, list);
 }
 
-/* This function is called in the event that a rule matching this module is
- * removed.
- * When this happens we need to check if there are no other rules matching
- * the table given.  If that is the case then we remove the table and clean
- * up its memory.
- */
-static void
-destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
+static void recent_seq_stop(struct seq_file *s, void *v)
 {
-       const struct ipt_recent_info *info = matchinfo;
-       struct recent_ip_tables *curr_table, *last_table;
+       spin_unlock_bh(&recent_lock);
+}
 
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": destroy() entered.\n");
-#endif
+static int recent_seq_show(struct seq_file *seq, void *v)
+{
+       struct recent_entry *e = v;
+       unsigned int i;
+
+       i = (e->index - 1) % ip_pkt_list_tot;
+       seq_printf(seq, "src=%u.%u.%u.%u ttl: %u last_seen: %lu oldest_pkt: %u",
+                  NIPQUAD(e->addr), e->ttl, e->stamps[i], e->index);
+       for (i = 0; i < e->nstamps; i++)
+               seq_printf(seq, "%s %lu", i ? "," : "", e->stamps[i]);
+       seq_printf(seq, "\n");
+       return 0;
+}
 
-       if(matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return;
+static struct seq_operations recent_seq_ops = {
+       .start          = recent_seq_start,
+       .next           = recent_seq_next,
+       .stop           = recent_seq_stop,
+       .show           = recent_seq_show,
+};
 
-       /* Lock the linked list while we play with it */
-       spin_lock_bh(&recent_lock);
+static int recent_seq_open(struct inode *inode, struct file *file)
+{
+       struct proc_dir_entry *pde = PDE(inode);
+       struct seq_file *seq;
+       struct recent_iter_state *st;
+       int ret;
+
+       st = kzalloc(sizeof(*st), GFP_KERNEL);
+       if (st == NULL)
+               return -ENOMEM;
+       ret = seq_open(file, &recent_seq_ops);
+       if (ret)
+               kfree(st);
+       st->table    = pde->data;
+       seq          = file->private_data;
+       seq->private = st;
+       return ret;
+}
 
-       /* Look for an entry with this name already created */
-       /* Finds the end of the list and the entry before the end if current name does not exist */
-       last_table = NULL;
-       curr_table = r_tables;
-       if(!curr_table) { 
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": destroy() No tables found, leaving.\n");
-#endif
+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 recent_table *t = pde->data;
+       struct recent_entry *e;
+       char buf[sizeof("+255.255.255.255")], *c = buf;
+       u_int32_t addr;
+       int add;
+
+       if (size > sizeof(buf))
+               size = sizeof(buf);
+       if (copy_from_user(buf, input, size))
+               return -EFAULT;
+       while (isspace(*c))
+               c++;
+
+       if (size - (c - buf) < 5)
+               return c - buf;
+       if (!strncmp(c, "clear", 5)) {
+               c += 5;
+               spin_lock_bh(&recent_lock);
+               recent_table_flush(t);
                spin_unlock_bh(&recent_lock);
-               return;
+               return c - buf;
        }
-       while( strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
 
-       /* If a table does not exist then do nothing and return */
-       if(!curr_table) { 
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table not found, leaving.\n");
-#endif
-               spin_unlock_bh(&recent_lock);
-               return;
+       switch (*c) {
+       case '-':
+               add = 0;
+               c++;
+               break;
+       case '+':
+               c++;
+       default:
+               add = 1;
+               break;
        }
+       addr = in_aton(c);
 
-       curr_table->count--;
-
-       /* If count is still non-zero then there are still rules referenceing it so we do nothing */
-       if(curr_table->count) { 
-#ifdef DEBUG
-               if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table found, non-zero count, leaving.\n");
-#endif
-               spin_unlock_bh(&recent_lock);
-               return;
+       spin_lock_bh(&recent_lock);
+       e = recent_entry_lookup(t, addr, 0);
+       if (e == NULL) {
+               if (add)
+                       recent_entry_init(t, addr, 0);
+       } else {
+               if (add)
+                       recent_entry_update(t, e);
+               else
+                       recent_entry_remove(t, e);
        }
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table found, zero count, removing.\n");
-#endif
-
-       /* Count must be zero so we remove this table from the list */
-       if(last_table) last_table->next = curr_table->next; else r_tables = curr_table->next;
-
        spin_unlock_bh(&recent_lock);
+       return size;
+}
 
-       /* lock to make sure any late-runners still using this after we removed it from
-        * the list finish up then remove everything */
-       spin_lock_bh(&curr_table->list_lock);
-       spin_unlock_bh(&curr_table->list_lock);
-
-#ifdef CONFIG_PROC_FS
-       if(curr_table->status_proc) remove_proc_entry(curr_table->name,proc_net_ipt_recent);
+static struct file_operations recent_fops = {
+       .open           = recent_seq_open,
+       .read           = seq_read,
+       .write          = recent_proc_write,
+       .release        = seq_release_private,
+       .owner          = THIS_MODULE,
+};
 #endif /* CONFIG_PROC_FS */
-       vfree(curr_table->table[0].last_pkts);
-       vfree(curr_table->table);
-       vfree(curr_table->hash_table);
-       vfree(curr_table->time_info);
-       vfree(curr_table);
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": destroy() left.\n");
-#endif
 
-       return;
-}
-
-/* This is the structure we pass to ipt_register to register our
- * module with iptables.
- */
 static struct ipt_match recent_match = {
        .name           = "recent",
-       .match          = match,
+       .match          = ipt_recent_match,
        .matchsize      = sizeof(struct ipt_recent_info),
-       .checkentry     = checkentry,
-       .destroy        = destroy,
-       .me             = THIS_MODULE
+       .checkentry     = ipt_recent_checkentry,
+       .destroy        = ipt_recent_destroy,
+       .me             = THIS_MODULE,
 };
 
-/* Kernel module initialization. */
 static int __init ipt_recent_init(void)
 {
-       int err, count;
+       int err;
 
-       printk(version);
-#ifdef CONFIG_PROC_FS
-       proc_net_ipt_recent = proc_mkdir("ipt_recent",proc_net);
-       if(!proc_net_ipt_recent) return -ENOMEM;
-#endif
-
-       if(ip_list_hash_size && ip_list_hash_size <= ip_list_tot) {
-         printk(KERN_WARNING RECENT_NAME ": ip_list_hash_size too small, resetting to default.\n");
-         ip_list_hash_size = 0;
-       }
-
-       if(!ip_list_hash_size) {
-               ip_list_hash_size = ip_list_tot*3;
-               count = 2*2;
-               while(ip_list_hash_size > count) count = count*2;
-               ip_list_hash_size = count;
-       }
-
-#ifdef DEBUG
-       if(debug) printk(KERN_INFO RECENT_NAME ": ip_list_hash_size: %d\n",ip_list_hash_size);
-#endif
+       if (!ip_list_tot || !ip_pkt_list_tot || ip_pkt_list_tot > 255)
+               return -EINVAL;
+       ip_list_hash_size = 1 << fls(ip_list_tot);
 
        err = ipt_register_match(&recent_match);
+#ifdef CONFIG_PROC_FS
        if (err)
-               remove_proc_entry("ipt_recent", proc_net);
+               return err;
+       proc_dir = proc_mkdir("ipt_recent", proc_net);
+       if (proc_dir == NULL) {
+               ipt_unregister_match(&recent_match);
+               err = -ENOMEM;
+       }
+#endif
        return err;
 }
 
-/* Kernel module destruction. */
-static void __exit ipt_recent_fini(void)
+static void __exit ipt_recent_exit(void)
 {
+       BUG_ON(!list_empty(&tables));
        ipt_unregister_match(&recent_match);
-
-       remove_proc_entry("ipt_recent",proc_net);
+#ifdef CONFIG_PROC_FS
+       remove_proc_entry("ipt_recent", proc_net);
+#endif
 }
 
-/* Register our module with the kernel. */
 module_init(ipt_recent_init);
-module_exit(ipt_recent_fini);
+module_exit(ipt_recent_exit);
index 5bc9f64d7b5b06f9bf1d5a2d8c3923f6fdaccfb9..8cc8e1b3677894283bd047121a179fce74d80b8e 100644 (file)
@@ -145,7 +145,7 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
 
        /* This is where we call the helper: as the packet goes out. */
        ct = nf_ct_get(*pskb, &ctinfo);
-       if (!ct)
+       if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
                return NF_ACCEPT;
 
        help = nfct_help(ct);
@@ -348,6 +348,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
                        .tuple.dst.u.tcp.port;
                sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL]
                        .tuple.dst.u3.ip;
+               memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
 
                DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
                       NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
index 4b0d361cc6e69fbb178b8fc82f47631a86053527..663a73ee3f2fc96019c5118e9b7246429cf6fa09 100644 (file)
@@ -235,7 +235,7 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff,
        }
 
        /* See ip_conntrack_proto_tcp.c */
-       if (hooknum == NF_IP_PRE_ROUTING &&
+       if (nf_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
            nf_ip_checksum(skb, hooknum, dataoff, 0)) {
                if (LOG_INVALID(IPPROTO_ICMP))
                        nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
index fc2562415555f255f89a538298e079a467708e41..bd221ec3f81eb668390d9e811712c8bc3da6fdfd 100644 (file)
@@ -103,7 +103,7 @@ static void raw_v4_unhash(struct sock *sk)
 }
 
 struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
-                            unsigned long raddr, unsigned long laddr,
+                            __be32 raddr, __be32 laddr,
                             int dif)
 {
        struct hlist_node *node;
index 6b6c3adfcf00954185c03c651c74cc911314122f..ce4cd5f355116e2d0d30e96aff51a2f6f2c0e90f 100644 (file)
@@ -181,14 +181,6 @@ ctl_table ipv4_table[] = {
                .proc_handler   = &ipv4_doint_and_flush,
                .strategy       = &ipv4_doint_and_flush_strategy,
        },
-        {
-               .ctl_name       = NET_IPV4_AUTOCONFIG,
-               .procname       = "ip_autoconfig",
-               .data           = &ipv4_config.autoconfig,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec
-       },
         {
                .ctl_name       = NET_IPV4_NO_PMTU_DISC,
                .procname       = "ip_no_pmtu_disc",
@@ -688,6 +680,24 @@ ctl_table ipv4_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec
        },
+#ifdef CONFIG_NET_DMA
+       {
+               .ctl_name       = NET_TCP_DMA_COPYBREAK,
+               .procname       = "tcp_dma_copybreak",
+               .data           = &sysctl_tcp_dma_copybreak,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+       },
+#endif
+       {
+               .ctl_name       = NET_TCP_SLOW_START_AFTER_IDLE,
+               .procname       = "tcp_slow_start_after_idle",
+               .data           = &sysctl_tcp_slow_start_after_idle,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec
+       },
        { .ctl_name = 0 }
 };
 
index e2b7b80550371dd836d3b32635c999b2a46f6fcc..74998f250071c20c21549b06ae2cf20341bc50c0 100644 (file)
 #include <net/tcp.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
-
+#include <net/netdma.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -622,14 +622,10 @@ ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset,
        ssize_t res;
        struct sock *sk = sock->sk;
 
-#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
-
        if (!(sk->sk_route_caps & NETIF_F_SG) ||
-           !(sk->sk_route_caps & TCP_ZC_CSUM_FLAGS))
+           !(sk->sk_route_caps & NETIF_F_ALL_CSUM))
                return sock_no_sendpage(sock, page, offset, size, flags);
 
-#undef TCP_ZC_CSUM_FLAGS
-
        lock_sock(sk);
        TCP_CHECK_TIMER(sk);
        res = do_tcp_sendpages(sk, &page, offset, size, flags);
@@ -726,9 +722,7 @@ new_segment:
                                /*
                                 * Check whether we can use HW checksum.
                                 */
-                               if (sk->sk_route_caps &
-                                   (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM |
-                                    NETIF_F_HW_CSUM))
+                               if (sk->sk_route_caps & NETIF_F_ALL_CSUM)
                                        skb->ip_summed = CHECKSUM_HW;
 
                                skb_entail(sk, tp, skb);
@@ -937,7 +931,7 @@ static int tcp_recv_urg(struct sock *sk, long timeo,
  * calculation of whether or not we must ACK for the sake of
  * a window update.
  */
-static void cleanup_rbuf(struct sock *sk, int copied)
+void tcp_cleanup_rbuf(struct sock *sk, int copied)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        int time_to_ack = 0;
@@ -1072,11 +1066,11 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
                                break;
                }
                if (skb->h.th->fin) {
-                       sk_eat_skb(sk, skb);
+                       sk_eat_skb(sk, skb, 0);
                        ++seq;
                        break;
                }
-               sk_eat_skb(sk, skb);
+               sk_eat_skb(sk, skb, 0);
                if (!desc->count)
                        break;
        }
@@ -1086,7 +1080,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
 
        /* Clean up data we have read: This will do ACK frames. */
        if (copied)
-               cleanup_rbuf(sk, copied);
+               tcp_cleanup_rbuf(sk, copied);
        return copied;
 }
 
@@ -1110,6 +1104,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        int target;             /* Read at least this many bytes */
        long timeo;
        struct task_struct *user_recv = NULL;
+       int copied_early = 0;
 
        lock_sock(sk);
 
@@ -1133,6 +1128,17 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
 
+#ifdef CONFIG_NET_DMA
+       tp->ucopy.dma_chan = NULL;
+       preempt_disable();
+       if ((len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
+           !sysctl_tcp_low_latency && __get_cpu_var(softnet_data.net_dma)) {
+               preempt_enable_no_resched();
+               tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len);
+       } else
+               preempt_enable_no_resched();
+#endif
+
        do {
                struct sk_buff *skb;
                u32 offset;
@@ -1220,7 +1226,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        }
                }
 
-               cleanup_rbuf(sk, copied);
+               tcp_cleanup_rbuf(sk, copied);
 
                if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) {
                        /* Install new reader */
@@ -1274,6 +1280,10 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                } else
                        sk_wait_data(sk, &timeo);
 
+#ifdef CONFIG_NET_DMA
+               tp->ucopy.wakeup = 0;
+#endif
+
                if (user_recv) {
                        int chunk;
 
@@ -1329,13 +1339,39 @@ do_prequeue:
                }
 
                if (!(flags & MSG_TRUNC)) {
-                       err = skb_copy_datagram_iovec(skb, offset,
-                                                     msg->msg_iov, used);
-                       if (err) {
-                               /* Exception. Bailout! */
-                               if (!copied)
-                                       copied = -EFAULT;
-                               break;
+#ifdef CONFIG_NET_DMA
+                       if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
+                               tp->ucopy.dma_chan = get_softnet_dma();
+
+                       if (tp->ucopy.dma_chan) {
+                               tp->ucopy.dma_cookie = dma_skb_copy_datagram_iovec(
+                                       tp->ucopy.dma_chan, skb, offset,
+                                       msg->msg_iov, used,
+                                       tp->ucopy.pinned_list);
+
+                               if (tp->ucopy.dma_cookie < 0) {
+
+                                       printk(KERN_ALERT "dma_cookie < 0\n");
+
+                                       /* Exception. Bailout! */
+                                       if (!copied)
+                                               copied = -EFAULT;
+                                       break;
+                               }
+                               if ((offset + used) == skb->len)
+                                       copied_early = 1;
+
+                       } else
+#endif
+                       {
+                               err = skb_copy_datagram_iovec(skb, offset,
+                                               msg->msg_iov, used);
+                               if (err) {
+                                       /* Exception. Bailout! */
+                                       if (!copied)
+                                               copied = -EFAULT;
+                                       break;
+                               }
                        }
                }
 
@@ -1355,15 +1391,19 @@ skip_copy:
 
                if (skb->h.th->fin)
                        goto found_fin_ok;
-               if (!(flags & MSG_PEEK))
-                       sk_eat_skb(sk, skb);
+               if (!(flags & MSG_PEEK)) {
+                       sk_eat_skb(sk, skb, copied_early);
+                       copied_early = 0;
+               }
                continue;
 
        found_fin_ok:
                /* Process the FIN. */
                ++*seq;
-               if (!(flags & MSG_PEEK))
-                       sk_eat_skb(sk, skb);
+               if (!(flags & MSG_PEEK)) {
+                       sk_eat_skb(sk, skb, copied_early);
+                       copied_early = 0;
+               }
                break;
        } while (len > 0);
 
@@ -1386,12 +1426,42 @@ skip_copy:
                tp->ucopy.len = 0;
        }
 
+#ifdef CONFIG_NET_DMA
+       if (tp->ucopy.dma_chan) {
+               struct sk_buff *skb;
+               dma_cookie_t done, used;
+
+               dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+
+               while (dma_async_memcpy_complete(tp->ucopy.dma_chan,
+                                                tp->ucopy.dma_cookie, &done,
+                                                &used) == DMA_IN_PROGRESS) {
+                       /* do partial cleanup of sk_async_wait_queue */
+                       while ((skb = skb_peek(&sk->sk_async_wait_queue)) &&
+                              (dma_async_is_complete(skb->dma_cookie, done,
+                                                     used) == DMA_SUCCESS)) {
+                               __skb_dequeue(&sk->sk_async_wait_queue);
+                               kfree_skb(skb);
+                       }
+               }
+
+               /* Safe to free early-copied skbs now */
+               __skb_queue_purge(&sk->sk_async_wait_queue);
+               dma_chan_put(tp->ucopy.dma_chan);
+               tp->ucopy.dma_chan = NULL;
+       }
+       if (tp->ucopy.pinned_list) {
+               dma_unpin_iovec_pages(tp->ucopy.pinned_list);
+               tp->ucopy.pinned_list = NULL;
+       }
+#endif
+
        /* According to UNIX98, msg_name/msg_namelen are ignored
         * on connected socket. I was just happy when found this 8) --ANK
         */
 
        /* Clean up data we have read: This will do ACK frames. */
-       cleanup_rbuf(sk, copied);
+       tcp_cleanup_rbuf(sk, copied);
 
        TCP_CHECK_TIMER(sk);
        release_sock(sk);
@@ -1658,6 +1728,9 @@ int tcp_disconnect(struct sock *sk, int flags)
        __skb_queue_purge(&sk->sk_receive_queue);
        sk_stream_writequeue_purge(sk);
        __skb_queue_purge(&tp->out_of_order_queue);
+#ifdef CONFIG_NET_DMA
+       __skb_queue_purge(&sk->sk_async_wait_queue);
+#endif
 
        inet->dport = 0;
 
@@ -1858,7 +1931,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
                            (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) &&
                            inet_csk_ack_scheduled(sk)) {
                                icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
-                               cleanup_rbuf(sk, 1);
+                               tcp_cleanup_rbuf(sk, 1);
                                if (!(val & 1))
                                        icsk->icsk_ack.pingpong = 1;
                        }
index 035f2092d73ac93a639b0122ed1c8b51867dae0b..b2d9021ad22bfb0bef5d6c59a5ea2d4dc178fa01 100644 (file)
@@ -198,12 +198,6 @@ static u32 bictcp_undo_cwnd(struct sock *sk)
        return max(tp->snd_cwnd, ca->last_max_cwnd);
 }
 
-static u32 bictcp_min_cwnd(struct sock *sk)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-       return tp->snd_ssthresh;
-}
-
 static void bictcp_state(struct sock *sk, u8 new_state)
 {
        if (new_state == TCP_CA_Loss)
@@ -231,7 +225,6 @@ static struct tcp_congestion_ops bictcp = {
        .cong_avoid     = bictcp_cong_avoid,
        .set_state      = bictcp_state,
        .undo_cwnd      = bictcp_undo_cwnd,
-       .min_cwnd       = bictcp_min_cwnd,
        .pkts_acked     = bictcp_acked,
        .owner          = THIS_MODULE,
        .name           = "bic",
diff --git a/net/ipv4/tcp_compound.c b/net/ipv4/tcp_compound.c
new file mode 100644 (file)
index 0000000..bc54f7e
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * TCP Vegas congestion control
+ *
+ * This is based on the congestion detection/avoidance scheme described in
+ *    Lawrence S. Brakmo and Larry L. Peterson.
+ *    "TCP Vegas: End to end congestion avoidance on a global internet."
+ *    IEEE Journal on Selected Areas in Communication, 13(8):1465--1480,
+ *    October 1995. Available from:
+ *     ftp://ftp.cs.arizona.edu/xkernel/Papers/jsac.ps
+ *
+ * See http://www.cs.arizona.edu/xkernel/ for their implementation.
+ * The main aspects that distinguish this implementation from the
+ * Arizona Vegas implementation are:
+ *   o We do not change the loss detection or recovery mechanisms of
+ *     Linux in any way. Linux already recovers from losses quite well,
+ *     using fine-grained timers, NewReno, and FACK.
+ *   o To avoid the performance penalty imposed by increasing cwnd
+ *     only every-other RTT during slow start, we increase during
+ *     every RTT during slow start, just like Reno.
+ *   o Largely to allow continuous cwnd growth during slow start,
+ *     we use the rate at which ACKs come back as the "actual"
+ *     rate, rather than the rate at which data is sent.
+ *   o To speed convergence to the right rate, we set the cwnd
+ *     to achieve the right ("actual") rate when we exit slow start.
+ *   o To filter out the noise caused by delayed ACKs, we use the
+ *     minimum RTT sample observed during the last RTT to calculate
+ *     the actual rate.
+ *   o When the sender re-starts from idle, it waits until it has
+ *     received ACKs for an entire flight of new data before making
+ *     a cwnd adjustment decision. The original Vegas implementation
+ *     assumed senders never went idle.
+ *
+ *
+ *   TCP Compound based on TCP Vegas
+ *
+ *   further details can be found here:
+ *      ftp://ftp.research.microsoft.com/pub/tr/TR-2005-86.pdf
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/inet_diag.h>
+
+#include <net/tcp.h>
+
+/* Default values of the Vegas variables, in fixed-point representation
+ * with V_PARAM_SHIFT bits to the right of the binary point.
+ */
+#define V_PARAM_SHIFT 1
+
+#define TCP_COMPOUND_ALPHA          3U
+#define TCP_COMPOUND_BETA           1U
+#define TCP_COMPOUND_GAMMA         30
+#define TCP_COMPOUND_ZETA           1
+
+/* TCP compound variables */
+struct compound {
+       u32 beg_snd_nxt;        /* right edge during last RTT */
+       u32 beg_snd_una;        /* left edge  during last RTT */
+       u32 beg_snd_cwnd;       /* saves the size of the cwnd */
+       u8 doing_vegas_now;     /* if true, do vegas for this RTT */
+       u16 cntRTT;             /* # of RTTs measured within last RTT */
+       u32 minRTT;             /* min of RTTs measured within last RTT (in usec) */
+       u32 baseRTT;            /* the min of all Vegas RTT measurements seen (in usec) */
+
+       u32 cwnd;
+       u32 dwnd;
+};
+
+/* There are several situations when we must "re-start" Vegas:
+ *
+ *  o when a connection is established
+ *  o after an RTO
+ *  o after fast recovery
+ *  o when we send a packet and there is no outstanding
+ *    unacknowledged data (restarting an idle connection)
+ *
+ * In these circumstances we cannot do a Vegas calculation at the
+ * end of the first RTT, because any calculation we do is using
+ * stale info -- both the saved cwnd and congestion feedback are
+ * stale.
+ *
+ * Instead we must wait until the completion of an RTT during
+ * which we actually receive ACKs.
+ */
+static inline void vegas_enable(struct sock *sk)
+{
+       const struct tcp_sock *tp = tcp_sk(sk);
+       struct compound *vegas = inet_csk_ca(sk);
+
+       /* Begin taking Vegas samples next time we send something. */
+       vegas->doing_vegas_now = 1;
+
+       /* Set the beginning of the next send window. */
+       vegas->beg_snd_nxt = tp->snd_nxt;
+
+       vegas->cntRTT = 0;
+       vegas->minRTT = 0x7fffffff;
+}
+
+/* Stop taking Vegas samples for now. */
+static inline void vegas_disable(struct sock *sk)
+{
+       struct compound *vegas = inet_csk_ca(sk);
+
+       vegas->doing_vegas_now = 0;
+}
+
+static void tcp_compound_init(struct sock *sk)
+{
+       struct compound *vegas = inet_csk_ca(sk);
+       const struct tcp_sock *tp = tcp_sk(sk);
+
+       vegas->baseRTT = 0x7fffffff;
+       vegas_enable(sk);
+
+       vegas->dwnd = 0;
+       vegas->cwnd = tp->snd_cwnd;
+}
+
+/* Do RTT sampling needed for Vegas.
+ * Basically we:
+ *   o min-filter RTT samples from within an RTT to get the current
+ *     propagation delay + queuing delay (we are min-filtering to try to
+ *     avoid the effects of delayed ACKs)
+ *   o min-filter RTT samples from a much longer window (forever for now)
+ *     to find the propagation delay (baseRTT)
+ */
+static void tcp_compound_rtt_calc(struct sock *sk, u32 usrtt)
+{
+       struct compound *vegas = inet_csk_ca(sk);
+       u32 vrtt = usrtt + 1;   /* Never allow zero rtt or baseRTT */
+
+       /* Filter to find propagation delay: */
+       if (vrtt < vegas->baseRTT)
+               vegas->baseRTT = vrtt;
+
+       /* Find the min RTT during the last RTT to find
+        * the current prop. delay + queuing delay:
+        */
+
+       vegas->minRTT = min(vegas->minRTT, vrtt);
+       vegas->cntRTT++;
+}
+
+static void tcp_compound_state(struct sock *sk, u8 ca_state)
+{
+
+       if (ca_state == TCP_CA_Open)
+               vegas_enable(sk);
+       else
+               vegas_disable(sk);
+}
+
+
+/* 64bit divisor, dividend and result. dynamic precision */
+static inline u64 div64_64(u64 dividend, u64 divisor)
+{
+       u32 d = divisor;
+
+       if (divisor > 0xffffffffULL) {
+               unsigned int shift = fls(divisor >> 32);
+
+               d = divisor >> shift;
+               dividend >>= shift;
+       }
+
+       /* avoid 64 bit division if possible */
+       if (dividend >> 32)
+               do_div(dividend, d);
+       else
+               dividend = (u32) dividend / d;
+
+       return dividend;
+}
+
+/* calculate the quartic root of "a" using Newton-Raphson */
+static u32 qroot(u64 a)
+{
+       u32 x, x1;
+
+       /* Initial estimate is based on:
+        * qrt(x) = exp(log(x) / 4)
+        */
+       x = 1u << (fls64(a) >> 2);
+
+       /*
+        * Iteration based on:
+        *                         3
+        * x    = ( 3 * x  +  a / x  ) / 4
+        *  k+1          k         k
+        */
+       do {
+               u64 x3 = x;
+
+               x1 = x;
+               x3 *= x;
+               x3 *= x;
+
+               x = (3 * x + (u32) div64_64(a, x3)) / 4;
+       } while (abs(x1 - x) > 1);
+
+       return x;
+}
+
+
+/*
+ * If the connection is idle and we are restarting,
+ * then we don't want to do any Vegas calculations
+ * until we get fresh RTT samples.  So when we
+ * restart, we reset our Vegas state to a clean
+ * slate. After we get acks for this flight of
+ * packets, _then_ we can make Vegas calculations
+ * again.
+ */
+static void tcp_compound_cwnd_event(struct sock *sk, enum tcp_ca_event event)
+{
+       if (event == CA_EVENT_CWND_RESTART || event == CA_EVENT_TX_START)
+               tcp_compound_init(sk);
+}
+
+static void tcp_compound_cong_avoid(struct sock *sk, u32 ack,
+                                   u32 seq_rtt, u32 in_flight, int flag)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct compound *vegas = inet_csk_ca(sk);
+       u8 inc = 0;
+
+       if (vegas->cwnd + vegas->dwnd > tp->snd_cwnd) {
+               if (vegas->cwnd > tp->snd_cwnd || vegas->dwnd > tp->snd_cwnd) {
+                       vegas->cwnd = tp->snd_cwnd;
+                       vegas->dwnd = 0;
+               } else
+                       vegas->cwnd = tp->snd_cwnd - vegas->dwnd;
+
+       }
+
+       if (!tcp_is_cwnd_limited(sk, in_flight))
+               return;
+
+       if (vegas->cwnd <= tp->snd_ssthresh)
+               inc = 1;
+       else if (tp->snd_cwnd_cnt < tp->snd_cwnd)
+               tp->snd_cwnd_cnt++;
+
+       if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+               inc = 1;
+               tp->snd_cwnd_cnt = 0;
+       }
+
+       if (inc && tp->snd_cwnd < tp->snd_cwnd_clamp)
+               vegas->cwnd++;
+
+       /* The key players are v_beg_snd_una and v_beg_snd_nxt.
+        *
+        * These are so named because they represent the approximate values
+        * of snd_una and snd_nxt at the beginning of the current RTT. More
+        * precisely, they represent the amount of data sent during the RTT.
+        * At the end of the RTT, when we receive an ACK for v_beg_snd_nxt,
+        * we will calculate that (v_beg_snd_nxt - v_beg_snd_una) outstanding
+        * bytes of data have been ACKed during the course of the RTT, giving
+        * an "actual" rate of:
+        *
+        *     (v_beg_snd_nxt - v_beg_snd_una) / (rtt duration)
+        *
+        * Unfortunately, v_beg_snd_una is not exactly equal to snd_una,
+        * because delayed ACKs can cover more than one segment, so they
+        * don't line up nicely with the boundaries of RTTs.
+        *
+        * Another unfortunate fact of life is that delayed ACKs delay the
+        * advance of the left edge of our send window, so that the number
+        * of bytes we send in an RTT is often less than our cwnd will allow.
+        * So we keep track of our cwnd separately, in v_beg_snd_cwnd.
+        */
+
+       if (after(ack, vegas->beg_snd_nxt)) {
+               /* Do the Vegas once-per-RTT cwnd adjustment. */
+               u32 old_wnd, old_snd_cwnd;
+
+               /* Here old_wnd is essentially the window of data that was
+                * sent during the previous RTT, and has all
+                * been acknowledged in the course of the RTT that ended
+                * with the ACK we just received. Likewise, old_snd_cwnd
+                * is the cwnd during the previous RTT.
+                */
+               if (!tp->mss_cache)
+                       return;
+
+               old_wnd = (vegas->beg_snd_nxt - vegas->beg_snd_una) /
+                   tp->mss_cache;
+               old_snd_cwnd = vegas->beg_snd_cwnd;
+
+               /* Save the extent of the current window so we can use this
+                * at the end of the next RTT.
+                */
+               vegas->beg_snd_una = vegas->beg_snd_nxt;
+               vegas->beg_snd_nxt = tp->snd_nxt;
+               vegas->beg_snd_cwnd = tp->snd_cwnd;
+
+               /* We do the Vegas calculations only if we got enough RTT
+                * samples that we can be reasonably sure that we got
+                * at least one RTT sample that wasn't from a delayed ACK.
+                * If we only had 2 samples total,
+                * then that means we're getting only 1 ACK per RTT, which
+                * means they're almost certainly delayed ACKs.
+                * If  we have 3 samples, we should be OK.
+                */
+
+               if (vegas->cntRTT > 2) {
+                       u32 rtt, target_cwnd, diff;
+                       u32 brtt, dwnd;
+
+                       /* We have enough RTT samples, so, using the Vegas
+                        * algorithm, we determine if we should increase or
+                        * decrease cwnd, and by how much.
+                        */
+
+                       /* Pluck out the RTT we are using for the Vegas
+                        * calculations. This is the min RTT seen during the
+                        * last RTT. Taking the min filters out the effects
+                        * of delayed ACKs, at the cost of noticing congestion
+                        * a bit later.
+                        */
+                       rtt = vegas->minRTT;
+
+                       /* Calculate the cwnd we should have, if we weren't
+                        * going too fast.
+                        *
+                        * This is:
+                        *     (actual rate in segments) * baseRTT
+                        * We keep it as a fixed point number with
+                        * V_PARAM_SHIFT bits to the right of the binary point.
+                        */
+                       if (!rtt)
+                               return;
+
+                       brtt = vegas->baseRTT;
+                       target_cwnd = ((old_wnd * brtt)
+                                      << V_PARAM_SHIFT) / rtt;
+
+                       /* Calculate the difference between the window we had,
+                        * and the window we would like to have. This quantity
+                        * is the "Diff" from the Arizona Vegas papers.
+                        *
+                        * Again, this is a fixed point number with
+                        * V_PARAM_SHIFT bits to the right of the binary
+                        * point.
+                        */
+
+                       diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd;
+
+                       dwnd = vegas->dwnd;
+
+                       if (diff < (TCP_COMPOUND_GAMMA << V_PARAM_SHIFT)) {
+                               u64 v;
+                               u32 x;
+
+                               /*
+                                * The TCP Compound paper describes the choice
+                                * of "k" determines the agressiveness,
+                                * ie. slope of the response function.
+                                *
+                                * For same value as HSTCP would be 0.8
+                                * but for computaional reasons, both the
+                                * original authors and this implementation
+                                * use 0.75.
+                                */
+                               v = old_wnd;
+                               x = qroot(v * v * v) >> TCP_COMPOUND_ALPHA;
+                               if (x > 1)
+                                       dwnd = x - 1;
+                               else
+                                       dwnd = 0;
+
+                               dwnd += vegas->dwnd;
+
+                       } else if ((dwnd << V_PARAM_SHIFT) <
+                                  (diff * TCP_COMPOUND_BETA))
+                               dwnd = 0;
+                       else
+                               dwnd =
+                                   ((dwnd << V_PARAM_SHIFT) -
+                                    (diff *
+                                     TCP_COMPOUND_BETA)) >> V_PARAM_SHIFT;
+
+                       vegas->dwnd = dwnd;
+
+               }
+
+               /* Wipe the slate clean for the next RTT. */
+               vegas->cntRTT = 0;
+               vegas->minRTT = 0x7fffffff;
+       }
+
+       tp->snd_cwnd = vegas->cwnd + vegas->dwnd;
+}
+
+/* Extract info for Tcp socket info provided via netlink. */
+static void tcp_compound_get_info(struct sock *sk, u32 ext, struct sk_buff *skb)
+{
+       const struct compound *ca = inet_csk_ca(sk);
+       if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
+               struct tcpvegas_info *info;
+
+               info = RTA_DATA(__RTA_PUT(skb, INET_DIAG_VEGASINFO,
+                                         sizeof(*info)));
+
+               info->tcpv_enabled = ca->doing_vegas_now;
+               info->tcpv_rttcnt = ca->cntRTT;
+               info->tcpv_rtt = ca->baseRTT;
+               info->tcpv_minrtt = ca->minRTT;
+       rtattr_failure:;
+       }
+}
+
+static struct tcp_congestion_ops tcp_compound = {
+       .init           = tcp_compound_init,
+       .ssthresh       = tcp_reno_ssthresh,
+       .cong_avoid     = tcp_compound_cong_avoid,
+       .rtt_sample     = tcp_compound_rtt_calc,
+       .set_state      = tcp_compound_state,
+       .cwnd_event     = tcp_compound_cwnd_event,
+       .get_info       = tcp_compound_get_info,
+
+       .owner          = THIS_MODULE,
+       .name           = "compound",
+};
+
+static int __init tcp_compound_register(void)
+{
+       BUG_ON(sizeof(struct compound) > ICSK_CA_PRIV_SIZE);
+       tcp_register_congestion_control(&tcp_compound);
+       return 0;
+}
+
+static void __exit tcp_compound_unregister(void)
+{
+       tcp_unregister_congestion_control(&tcp_compound);
+}
+
+module_init(tcp_compound_register);
+module_exit(tcp_compound_unregister);
+
+MODULE_AUTHOR("Angelo P. Castellani, Stephen Hemminger");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Compound");
index 91c2f41c7f580e6cfe5682964676ca5bd334f853..857eefc52aab900c6a52f759f04d028f0af27516 100644 (file)
@@ -38,7 +38,7 @@ int tcp_register_congestion_control(struct tcp_congestion_ops *ca)
        int ret = 0;
 
        /* all algorithms must implement ssthresh and cong_avoid ops */
-       if (!ca->ssthresh || !ca->cong_avoid || !ca->min_cwnd) {
+       if (!ca->ssthresh || !ca->cong_avoid) {
                printk(KERN_ERR "TCP %s does not implement required ops\n",
                       ca->name);
                return -EINVAL;
@@ -251,8 +251,8 @@ u32 tcp_reno_ssthresh(struct sock *sk)
 }
 EXPORT_SYMBOL_GPL(tcp_reno_ssthresh);
 
-/* Lower bound on congestion window. */
-u32 tcp_reno_min_cwnd(struct sock *sk)
+/* Lower bound on congestion window with halving. */
+u32 tcp_reno_min_cwnd(const struct sock *sk)
 {
        const struct tcp_sock *tp = tcp_sk(sk);
        return tp->snd_ssthresh/2;
index 31a4986dfbf77baf7d439f4a1c775891fa29fc81..78b7a6b9e4defed2a15d99ee6cc7356e52f69042 100644 (file)
@@ -325,11 +325,6 @@ static u32 bictcp_undo_cwnd(struct sock *sk)
        return max(tcp_sk(sk)->snd_cwnd, ca->last_max_cwnd);
 }
 
-static u32 bictcp_min_cwnd(struct sock *sk)
-{
-       return tcp_sk(sk)->snd_ssthresh;
-}
-
 static void bictcp_state(struct sock *sk, u8 new_state)
 {
        if (new_state == TCP_CA_Loss)
@@ -357,7 +352,6 @@ static struct tcp_congestion_ops cubictcp = {
        .cong_avoid     = bictcp_cong_avoid,
        .set_state      = bictcp_state,
        .undo_cwnd      = bictcp_undo_cwnd,
-       .min_cwnd       = bictcp_min_cwnd,
        .pkts_acked     = bictcp_acked,
        .owner          = THIS_MODULE,
        .name           = "cubic",
index b72fa55dfb84d114484bf6f7d1b4751449d9c4e3..1120245b237341bb9e8d4664e0a9f2eb2ab824af 100644 (file)
@@ -98,6 +98,10 @@ struct hstcp {
        u32     ai;
 };
 
+static int max_ssthresh = 100;
+module_param(max_ssthresh, int, 0644);
+MODULE_PARM_DESC(max_ssthresh, "limited slow start threshold (RFC3742)");
+
 static void hstcp_init(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
@@ -119,9 +123,23 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt,
        if (!tcp_is_cwnd_limited(sk, in_flight))
                return;
 
-       if (tp->snd_cwnd <= tp->snd_ssthresh)
-               tcp_slow_start(tp);
-       else {
+       if (tp->snd_cwnd <= tp->snd_ssthresh) {
+               /* RFC3742: limited slow start
+                * the window is increased by 1/K MSS for each arriving ACK,
+                * for K = int(cwnd/(0.5 max_ssthresh))
+                */
+               if (max_ssthresh > 0 && tp->snd_cwnd > max_ssthresh) {
+                       u32 k = max(tp->snd_cwnd / (max_ssthresh >> 1), 1U);
+                       if (++tp->snd_cwnd_cnt >= k) {
+                               if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+                                       tp->snd_cwnd++;
+                               tp->snd_cwnd_cnt = 0;
+                       }
+               } else {
+                       if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+                               tp->snd_cwnd++;
+               }
+       } else {
                /* Update AIMD parameters */
                if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) {
                        while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
@@ -135,7 +153,8 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt,
 
                /* Do additive increase */
                if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
-                       tp->snd_cwnd_cnt += ca->ai;
+                       /* cwnd = cwnd + a(w) / cwnd */
+                       tp->snd_cwnd_cnt += ca->ai + 1;
                        if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
                                tp->snd_cwnd_cnt -= tp->snd_cwnd;
                                tp->snd_cwnd++;
index 1b2ff53f98ed2cb2801429c707579fac66baab5a..3d92c185926702ce4db03bced99ae286903ddc61 100644 (file)
@@ -246,14 +246,6 @@ static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
        }
 }
 
-/* Lower bound on congestion window. */
-static u32 htcp_min_cwnd(struct sock *sk)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-       return tp->snd_ssthresh;
-}
-
-
 static void htcp_init(struct sock *sk)
 {
        struct htcp *ca = inet_csk_ca(sk);
@@ -285,7 +277,6 @@ static void htcp_state(struct sock *sk, u8 new_state)
 static struct tcp_congestion_ops htcp = {
        .init           = htcp_init,
        .ssthresh       = htcp_recalc_ssthresh,
-       .min_cwnd       = htcp_min_cwnd,
        .cong_avoid     = htcp_cong_avoid,
        .set_state      = htcp_state,
        .undo_cwnd      = htcp_cwnd_undo,
index 4a538bc1683d69827f46952a537841bb4360b58c..e08245bdda3a384ebd4e2583ca366d3048643482 100644 (file)
@@ -71,6 +71,7 @@
 #include <net/inet_common.h>
 #include <linux/ipsec.h>
 #include <asm/unaligned.h>
+#include <net/netdma.h>
 
 int sysctl_tcp_timestamps = 1;
 int sysctl_tcp_window_scaling = 1;
@@ -1649,7 +1650,7 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_sock *tp)
         * Hence, we can detect timed out packets during fast
         * retransmit without falling to slow start.
         */
-       if (tcp_head_timedout(sk, tp)) {
+       if (!IsReno(tp) && tcp_head_timedout(sk, tp)) {
                struct sk_buff *skb;
 
                skb = tp->scoreboard_skb_hint ? tp->scoreboard_skb_hint
@@ -1662,8 +1663,6 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_sock *tp)
                        if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
                                TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
                                tp->lost_out += tcp_skb_pcount(skb);
-                               if (IsReno(tp))
-                                       tcp_remove_reno_sacks(sk, tp, tcp_skb_pcount(skb) + 1);
 
                                /* clear xmit_retrans hint */
                                if (tp->retransmit_skb_hint &&
@@ -1690,17 +1689,26 @@ static inline void tcp_moderate_cwnd(struct tcp_sock *tp)
        tp->snd_cwnd_stamp = tcp_time_stamp;
 }
 
+/* Lower bound on congestion window is slow start threshold
+ * unless congestion avoidance choice decides to overide it.
+ */
+static inline u32 tcp_cwnd_min(const struct sock *sk)
+{
+       const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops;
+
+       return ca_ops->min_cwnd ? ca_ops->min_cwnd(sk) : tcp_sk(sk)->snd_ssthresh;
+}
+
 /* Decrease cwnd each second ack. */
 static void tcp_cwnd_down(struct sock *sk)
 {
-       const struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        int decr = tp->snd_cwnd_cnt + 1;
 
        tp->snd_cwnd_cnt = decr&1;
        decr >>= 1;
 
-       if (decr && tp->snd_cwnd > icsk->icsk_ca_ops->min_cwnd(sk))
+       if (decr && tp->snd_cwnd > tcp_cwnd_min(sk))
                tp->snd_cwnd -= decr;
 
        tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
@@ -3787,6 +3795,50 @@ static inline int tcp_checksum_complete_user(struct sock *sk, struct sk_buff *sk
                __tcp_checksum_complete_user(sk, skb);
 }
 
+#ifdef CONFIG_NET_DMA
+static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, int hlen)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       int chunk = skb->len - hlen;
+       int dma_cookie;
+       int copied_early = 0;
+
+       if (tp->ucopy.wakeup)
+               return 0;
+
+       if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
+               tp->ucopy.dma_chan = get_softnet_dma();
+
+       if (tp->ucopy.dma_chan && skb->ip_summed == CHECKSUM_UNNECESSARY) {
+
+               dma_cookie = dma_skb_copy_datagram_iovec(tp->ucopy.dma_chan,
+                       skb, hlen, tp->ucopy.iov, chunk, tp->ucopy.pinned_list);
+
+               if (dma_cookie < 0)
+                       goto out;
+
+               tp->ucopy.dma_cookie = dma_cookie;
+               copied_early = 1;
+
+               tp->ucopy.len -= chunk;
+               tp->copied_seq += chunk;
+               tcp_rcv_space_adjust(sk);
+
+               if ((tp->ucopy.len == 0) ||
+                   (tcp_flag_word(skb->h.th) & TCP_FLAG_PSH) ||
+                   (atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1))) {
+                       tp->ucopy.wakeup = 1;
+                       sk->sk_data_ready(sk, 0);
+               }
+       } else if (chunk > 0) {
+               tp->ucopy.wakeup = 1;
+               sk->sk_data_ready(sk, 0);
+       }
+out:
+       return copied_early;
+}
+#endif /* CONFIG_NET_DMA */
+
 /*
  *     TCP receive function for the ESTABLISHED state. 
  *
@@ -3888,8 +3940,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
                                    tp->rcv_nxt == tp->rcv_wup)
                                        tcp_store_ts_recent(tp);
 
-                               tcp_rcv_rtt_measure_ts(sk, skb);
-
                                /* We know that such packets are checksummed
                                 * on entry.
                                 */
@@ -3903,14 +3953,23 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
                        }
                } else {
                        int eaten = 0;
+                       int copied_early = 0;
 
-                       if (tp->ucopy.task == current &&
-                           tp->copied_seq == tp->rcv_nxt &&
-                           len - tcp_header_len <= tp->ucopy.len &&
-                           sock_owned_by_user(sk)) {
-                               __set_current_state(TASK_RUNNING);
+                       if (tp->copied_seq == tp->rcv_nxt &&
+                           len - tcp_header_len <= tp->ucopy.len) {
+#ifdef CONFIG_NET_DMA
+                               if (tcp_dma_try_early_copy(sk, skb, tcp_header_len)) {
+                                       copied_early = 1;
+                                       eaten = 1;
+                               }
+#endif
+                               if (tp->ucopy.task == current && sock_owned_by_user(sk) && !copied_early) {
+                                       __set_current_state(TASK_RUNNING);
 
-                               if (!tcp_copy_to_iovec(sk, skb, tcp_header_len)) {
+                                       if (!tcp_copy_to_iovec(sk, skb, tcp_header_len))
+                                               eaten = 1;
+                               }
+                               if (eaten) {
                                        /* Predicted packet is in window by definition.
                                         * seq == rcv_nxt and rcv_wup <= rcv_nxt.
                                         * Hence, check seq<=rcv_wup reduces to:
@@ -3926,8 +3985,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
                                        __skb_pull(skb, tcp_header_len);
                                        tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
                                        NET_INC_STATS_BH(LINUX_MIB_TCPHPHITSTOUSER);
-                                       eaten = 1;
                                }
+                               if (copied_early)
+                                       tcp_cleanup_rbuf(sk, skb->len);
                        }
                        if (!eaten) {
                                if (tcp_checksum_complete_user(sk, skb))
@@ -3968,6 +4028,11 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 
                        __tcp_ack_snd_check(sk, 0);
 no_ack:
+#ifdef CONFIG_NET_DMA
+                       if (copied_early)
+                               __skb_queue_tail(&sk->sk_async_wait_queue, skb);
+                       else
+#endif
                        if (eaten)
                                __kfree_skb(skb);
                        else
index 672950e54c498a2cddf1f86b3321363be991e3ef..25ecc6e2478b5eb9a5ad64b4ed61b4e7a937bc0f 100644 (file)
@@ -71,6 +71,7 @@
 #include <net/inet_common.h>
 #include <net/timewait_sock.h>
 #include <net/xfrm.h>
+#include <net/netdma.h>
 
 #include <linux/inet.h>
 #include <linux/ipv6.h>
@@ -1091,8 +1092,18 @@ process:
        bh_lock_sock(sk);
        ret = 0;
        if (!sock_owned_by_user(sk)) {
-               if (!tcp_prequeue(sk, skb))
+#ifdef CONFIG_NET_DMA
+               struct tcp_sock *tp = tcp_sk(sk);
+               if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
+                       tp->ucopy.dma_chan = get_softnet_dma();
+               if (tp->ucopy.dma_chan)
                        ret = tcp_v4_do_rcv(sk, skb);
+               else
+#endif
+               {
+                       if (!tcp_prequeue(sk, skb))
+                       ret = tcp_v4_do_rcv(sk, skb);
+               }
        } else
                sk_add_backlog(sk, skb);
        bh_unlock_sock(sk);
@@ -1296,6 +1307,11 @@ int tcp_v4_destroy_sock(struct sock *sk)
        /* Cleans up our, hopefully empty, out_of_order_queue. */
        __skb_queue_purge(&tp->out_of_order_queue);
 
+#ifdef CONFIG_NET_DMA
+       /* Cleans up our sk_async_wait_queue */
+       __skb_queue_purge(&sk->sk_async_wait_queue);
+#endif
+
        /* Clean prequeue, it must be empty really */
        __skb_queue_purge(&tp->ucopy.prequeue);
 
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
new file mode 100644 (file)
index 0000000..1f977b6
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * TCP Low Priority (TCP-LP)
+ *
+ * TCP Low Priority is a distributed algorithm whose goal is to utilize only
+ *   the excess network bandwidth as compared to the ``fair share`` of
+ *   bandwidth as targeted by TCP. Available from:
+ *     http://www.ece.rice.edu/~akuzma/Doc/akuzma/TCP-LP.pdf
+ *
+ * Original Author:
+ *   Aleksandar Kuzmanovic <akuzma@northwestern.edu>
+ *
+ * See http://www-ece.rice.edu/networks/TCP-LP/ for their implementation.
+ * As of 2.6.13, Linux supports pluggable congestion control algorithms.
+ * Due to the limitation of the API, we take the following changes from
+ * the original TCP-LP implementation:
+ *   o We use newReno in most core CA handling. Only add some checking
+ *     within cong_avoid.
+ *   o Error correcting in remote HZ, therefore remote HZ will be keeped
+ *     on checking and updating.
+ *   o Handling calculation of One-Way-Delay (OWD) within rtt_sample, sicne
+ *     OWD have a similar meaning as RTT. Also correct the buggy formular.
+ *   o Handle reaction for Early Congestion Indication (ECI) within
+ *     pkts_acked, as mentioned within pseudo code.
+ *   o OWD is handled in relative format, where local time stamp will in
+ *     tcp_time_stamp format.
+ *
+ * Port from 2.4.19 to 2.6.16 as module by:
+ *   Wong Hoi Sing Edison <hswong3i@gmail.com>
+ *   Hung Hing Lun <hlhung3i@gmail.com>
+ *
+ * Version: $Id: tcp_lp.c,v 1.22 2006-05-02 18:18:19 hswong3i Exp $
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+/* resolution of owd */
+#define LP_RESOL       1000
+
+/**
+ * enum tcp_lp_state
+ * @LP_VALID_RHZ: is remote HZ valid?
+ * @LP_VALID_OWD: is OWD valid?
+ * @LP_WITHIN_THR: are we within threshold?
+ * @LP_WITHIN_INF: are we within inference?
+ *
+ * TCP-LP's state flags.
+ * We create this set of state flag mainly for debugging.
+ */
+enum tcp_lp_state {
+       LP_VALID_RHZ = (1 << 0),
+       LP_VALID_OWD = (1 << 1),
+       LP_WITHIN_THR = (1 << 3),
+       LP_WITHIN_INF = (1 << 4),
+};
+
+/**
+ * struct lp
+ * @flag: TCP-LP state flag
+ * @sowd: smoothed OWD << 3
+ * @owd_min: min OWD
+ * @owd_max: max OWD
+ * @owd_max_rsv: resrved max owd
+ * @remote_hz: estimated remote HZ
+ * @remote_ref_time: remote reference time
+ * @local_ref_time: local reference time
+ * @last_drop: time for last active drop
+ * @inference: current inference
+ *
+ * TCP-LP's private struct.
+ * We get the idea from original TCP-LP implementation where only left those we
+ * found are really useful.
+ */
+struct lp {
+       u32 flag;
+       u32 sowd;
+       u32 owd_min;
+       u32 owd_max;
+       u32 owd_max_rsv;
+       u32 remote_hz;
+       u32 remote_ref_time;
+       u32 local_ref_time;
+       u32 last_drop;
+       u32 inference;
+};
+
+/**
+ * tcp_lp_init
+ *
+ * Init all required variables.
+ * Clone the handling from Vegas module implementation.
+ */
+static void tcp_lp_init(struct sock *sk)
+{
+       struct lp *lp = inet_csk_ca(sk);
+
+       lp->flag = 0;
+       lp->sowd = 0;
+       lp->owd_min = 0xffffffff;
+       lp->owd_max = 0;
+       lp->owd_max_rsv = 0;
+       lp->remote_hz = 0;
+       lp->remote_ref_time = 0;
+       lp->local_ref_time = 0;
+       lp->last_drop = 0;
+       lp->inference = 0;
+}
+
+/**
+ * tcp_lp_cong_avoid
+ *
+ * Implementation of cong_avoid.
+ * Will only call newReno CA when away from inference.
+ * From TCP-LP's paper, this will be handled in additive increasement.
+ */
+static void tcp_lp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight,
+                             int flag)
+{
+       struct lp *lp = inet_csk_ca(sk);
+
+       if (!(lp->flag & LP_WITHIN_INF))
+               tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag);
+}
+
+/**
+ * tcp_lp_remote_hz_estimator
+ *
+ * Estimate remote HZ.
+ * We keep on updating the estimated value, where original TCP-LP
+ * implementation only guest it for once and use forever.
+ */
+static u32 tcp_lp_remote_hz_estimator(struct sock *sk)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct lp *lp = inet_csk_ca(sk);
+       s64 rhz = lp->remote_hz << 6;   /* remote HZ << 6 */
+       s64 m = 0;
+
+       /* not yet record reference time
+        * go away!! record it before come back!! */
+       if (lp->remote_ref_time == 0 || lp->local_ref_time == 0)
+               goto out;
+
+       /* we can't calc remote HZ with no different!! */
+       if (tp->rx_opt.rcv_tsval == lp->remote_ref_time
+           || tp->rx_opt.rcv_tsecr == lp->local_ref_time)
+               goto out;
+
+       m = HZ * (tp->rx_opt.rcv_tsval -
+                 lp->remote_ref_time) / (tp->rx_opt.rcv_tsecr -
+                                         lp->local_ref_time);
+       if (m < 0)
+               m = -m;
+
+       if (rhz != 0) {
+               m -= rhz >> 6;  /* m is now error in remote HZ est */
+               rhz += m;       /* 63/64 old + 1/64 new */
+       } else
+               rhz = m << 6;
+
+       /* record time for successful remote HZ calc */
+       lp->flag |= LP_VALID_RHZ;
+
+ out:
+       /* record reference time stamp */
+       lp->remote_ref_time = tp->rx_opt.rcv_tsval;
+       lp->local_ref_time = tp->rx_opt.rcv_tsecr;
+
+       return rhz >> 6;
+}
+
+/**
+ * tcp_lp_owd_calculator
+ *
+ * Calculate one way delay (in relative format).
+ * Original implement OWD as minus of remote time difference to local time
+ * difference directly. As this time difference just simply equal to RTT, when
+ * the network status is stable, remote RTT will equal to local RTT, and result
+ * OWD into zero.
+ * It seems to be a bug and so we fixed it.
+ */
+static u32 tcp_lp_owd_calculator(struct sock *sk)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct lp *lp = inet_csk_ca(sk);
+       s64 owd = 0;
+
+       lp->remote_hz = tcp_lp_remote_hz_estimator(sk);
+
+       if (lp->flag & LP_VALID_RHZ) {
+               owd =
+                   tp->rx_opt.rcv_tsval * (LP_RESOL / lp->remote_hz) -
+                   tp->rx_opt.rcv_tsecr * (LP_RESOL / HZ);
+               if (owd < 0)
+                       owd = -owd;
+       }
+
+       if (owd > 0)
+               lp->flag |= LP_VALID_OWD;
+       else
+               lp->flag &= ~LP_VALID_OWD;
+
+       return owd;
+}
+
+/**
+ * tcp_lp_rtt_sample
+ *
+ * Implementation or rtt_sample.
+ * Will take the following action,
+ *   1. calc OWD,
+ *   2. record the min/max OWD,
+ *   3. calc smoothed OWD (SOWD).
+ * Most ideas come from the original TCP-LP implementation.
+ */
+static void tcp_lp_rtt_sample(struct sock *sk, u32 usrtt)
+{
+       struct lp *lp = inet_csk_ca(sk);
+       s64 mowd = tcp_lp_owd_calculator(sk);
+
+       /* sorry that we don't have valid data */
+       if (!(lp->flag & LP_VALID_RHZ) || !(lp->flag & LP_VALID_OWD))
+               return;
+
+       /* record the next min owd */
+       if (mowd < lp->owd_min)
+               lp->owd_min = mowd;
+
+       /* always forget the max of the max
+        * we just set owd_max as one below it */
+       if (mowd > lp->owd_max) {
+               if (mowd > lp->owd_max_rsv) {
+                       if (lp->owd_max_rsv == 0)
+                               lp->owd_max = mowd;
+                       else
+                               lp->owd_max = lp->owd_max_rsv;
+                       lp->owd_max_rsv = mowd;
+               } else
+                       lp->owd_max = mowd;
+       }
+
+       /* calc for smoothed owd */
+       if (lp->sowd != 0) {
+               mowd -= lp->sowd >> 3;  /* m is now error in owd est */
+               lp->sowd += mowd;       /* owd = 7/8 owd + 1/8 new */
+       } else
+               lp->sowd = mowd << 3;   /* take the measured time be owd */
+}
+
+/**
+ * tcp_lp_pkts_acked
+ *
+ * Implementation of pkts_acked.
+ * Deal with active drop under Early Congestion Indication.
+ * Only drop to half and 1 will be handle, because we hope to use back
+ * newReno in increase case.
+ * We work it out by following the idea from TCP-LP's paper directly
+ */
+static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct lp *lp = inet_csk_ca(sk);
+
+       /* calc inference */
+       if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
+               lp->inference = 3 * (tcp_time_stamp - tp->rx_opt.rcv_tsecr);
+
+       /* test if within inference */
+       if (lp->last_drop && (tcp_time_stamp - lp->last_drop < lp->inference))
+               lp->flag |= LP_WITHIN_INF;
+       else
+               lp->flag &= ~LP_WITHIN_INF;
+
+       /* test if within threshold */
+       if (lp->sowd >> 3 <
+           lp->owd_min + 15 * (lp->owd_max - lp->owd_min) / 100)
+               lp->flag |= LP_WITHIN_THR;
+       else
+               lp->flag &= ~LP_WITHIN_THR;
+
+       pr_debug("TCP-LP: %05o|%5u|%5u|%15u|%15u|%15u\n", lp->flag,
+                tp->snd_cwnd, lp->remote_hz, lp->owd_min, lp->owd_max,
+                lp->sowd >> 3);
+
+       if (lp->flag & LP_WITHIN_THR)
+               return;
+
+       /* FIXME: try to reset owd_min and owd_max here
+        * so decrease the chance the min/max is no longer suitable
+        * and will usually within threshold when whithin inference */
+       lp->owd_min = lp->sowd >> 3;
+       lp->owd_max = lp->sowd >> 2;
+       lp->owd_max_rsv = lp->sowd >> 2;
+
+       /* happened within inference
+        * drop snd_cwnd into 1 */
+       if (lp->flag & LP_WITHIN_INF)
+               tp->snd_cwnd = 1U;
+
+       /* happened after inference
+        * cut snd_cwnd into half */
+       else
+               tp->snd_cwnd = max(tp->snd_cwnd >> 1U, 1U);
+
+       /* record this drop time */
+       lp->last_drop = tcp_time_stamp;
+}
+
+static struct tcp_congestion_ops tcp_lp = {
+       .init = tcp_lp_init,
+       .ssthresh = tcp_reno_ssthresh,
+       .cong_avoid = tcp_lp_cong_avoid,
+       .min_cwnd = tcp_reno_min_cwnd,
+       .rtt_sample = tcp_lp_rtt_sample,
+       .pkts_acked = tcp_lp_pkts_acked,
+
+       .owner = THIS_MODULE,
+       .name = "lp"
+};
+
+static int __init tcp_lp_register(void)
+{
+       BUG_ON(sizeof(struct lp) > ICSK_CA_PRIV_SIZE);
+       return tcp_register_congestion_control(&tcp_lp);
+}
+
+static void __exit tcp_lp_unregister(void)
+{
+       tcp_unregister_congestion_control(&tcp_lp);
+}
+
+module_init(tcp_lp_register);
+module_exit(tcp_lp_unregister);
+
+MODULE_AUTHOR("Wong Hoi Sing Edison, Hung Hing Lun");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Low Priority");
index 743016baa04867473a022008367aa05a61bac284..07bb5a2b375ec0b02e1be3774a474fbeae24a808 100644 (file)
@@ -59,6 +59,9 @@ int sysctl_tcp_tso_win_divisor = 3;
 int sysctl_tcp_mtu_probing = 0;
 int sysctl_tcp_base_mss = 512;
 
+/* By default, RFC2861 behavior.  */
+int sysctl_tcp_slow_start_after_idle = 1;
+
 static void update_send_head(struct sock *sk, struct tcp_sock *tp,
                             struct sk_buff *skb)
 {
@@ -138,7 +141,8 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
        struct inet_connection_sock *icsk = inet_csk(sk);
        const u32 now = tcp_time_stamp;
 
-       if (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto)
+       if (sysctl_tcp_slow_start_after_idle &&
+           (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto))
                tcp_cwnd_restart(sk, __sk_dst_get(sk));
 
        tp->lsndtime = now;
@@ -642,7 +646,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
  * eventually). The difference is that pulled data not copied, but
  * immediately discarded.
  */
-static unsigned char *__pskb_trim_head(struct sk_buff *skb, int len)
+static void __pskb_trim_head(struct sk_buff *skb, int len)
 {
        int i, k, eat;
 
@@ -667,7 +671,6 @@ static unsigned char *__pskb_trim_head(struct sk_buff *skb, int len)
        skb->tail = skb->data;
        skb->data_len -= len;
        skb->len = skb->data_len;
-       return skb->tail;
 }
 
 int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
@@ -676,12 +679,11 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
            pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
                return -ENOMEM;
 
-       if (len <= skb_headlen(skb)) {
+       /* If len == headlen, we avoid __skb_pull to preserve alignment. */
+       if (unlikely(len < skb_headlen(skb)))
                __skb_pull(skb, len);
-       } else {
-               if (__pskb_trim_head(skb, len-skb_headlen(skb)) == NULL)
-                       return -ENOMEM;
-       }
+       else
+               __pskb_trim_head(skb, len - skb_headlen(skb));
 
        TCP_SKB_CB(skb)->seq += len;
        skb->ip_summed = CHECKSUM_HW;
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
new file mode 100644 (file)
index 0000000..d7d517a
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * tcpprobe - Observe the TCP flow with kprobes.
+ *
+ * The idea for this came from Werner Almesberger's umlsim
+ * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/socket.h>
+#include <linux/tcp.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <linux/kfifo.h>
+#include <linux/vmalloc.h>
+
+#include <net/tcp.h>
+
+MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_DESCRIPTION("TCP cwnd snooper");
+MODULE_LICENSE("GPL");
+
+static int port = 0;
+MODULE_PARM_DESC(port, "Port to match (0=all)");
+module_param(port, int, 0);
+
+static int bufsize = 64*1024;
+MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
+module_param(bufsize, int, 0);
+
+static const char procname[] = "tcpprobe";
+
+struct {
+       struct kfifo  *fifo;
+       spinlock_t    lock;
+       wait_queue_head_t wait;
+       struct timeval tstart;
+} tcpw;
+
+static void printl(const char *fmt, ...)
+{
+       va_list args;
+       int len;
+       struct timeval now;
+       char tbuf[256];
+
+       va_start(args, fmt);
+       do_gettimeofday(&now);
+
+       now.tv_sec -= tcpw.tstart.tv_sec;
+       now.tv_usec -= tcpw.tstart.tv_usec;
+       if (now.tv_usec < 0) {
+               --now.tv_sec;
+               now.tv_usec += 1000000;
+       }
+
+       len = sprintf(tbuf, "%lu.%06lu ",
+                     (unsigned long) now.tv_sec,
+                     (unsigned long) now.tv_usec);
+       len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
+       va_end(args);
+
+       kfifo_put(tcpw.fifo, tbuf, len);
+       wake_up(&tcpw.wait);
+}
+
+static int jtcp_sendmsg(struct kiocb *iocb, struct sock *sk,
+                       struct msghdr *msg, size_t size)
+{
+       const struct tcp_sock *tp = tcp_sk(sk);
+       const struct inet_sock *inet = inet_sk(sk);
+
+       if (port == 0 || ntohs(inet->dport) == port ||
+           ntohs(inet->sport) == port) {
+               printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %#x %#x %u %u %u\n",
+                      NIPQUAD(inet->saddr), ntohs(inet->sport),
+                      NIPQUAD(inet->daddr), ntohs(inet->dport),
+                      size, tp->snd_nxt, tp->snd_una,
+                      tp->snd_cwnd, tcp_current_ssthresh(sk),
+                      tp->snd_wnd);
+       }
+
+       jprobe_return();
+       return 0;
+}
+
+static struct jprobe tcp_send_probe = {
+       .kp = { .addr = (kprobe_opcode_t *) &tcp_sendmsg, },
+       .entry = (kprobe_opcode_t *) &jtcp_sendmsg,
+};
+
+
+static int tcpprobe_open(struct inode * inode, struct file * file)
+{
+       kfifo_reset(tcpw.fifo);
+       do_gettimeofday(&tcpw.tstart);
+       return 0;
+}
+
+static ssize_t tcpprobe_read(struct file *file, char __user *buf,
+                            size_t len, loff_t *ppos)
+{
+       int error = 0, cnt;
+       unsigned char *tbuf;
+
+       if (!buf || len < 0)
+               return -EINVAL;
+
+       if (len == 0)
+               return 0;
+
+       tbuf = vmalloc(len);
+       if (!tbuf)
+               return -ENOMEM;
+
+       error = wait_event_interruptible(tcpw.wait,
+                                        __kfifo_len(tcpw.fifo) != 0);
+       if (error)
+               return error;
+
+       cnt = kfifo_get(tcpw.fifo, tbuf, len);
+       error = copy_to_user(buf, tbuf, cnt);
+
+       vfree(tbuf);
+
+       return error ? error : cnt;
+}
+
+static struct file_operations tcpprobe_fops = {
+       .owner   = THIS_MODULE,
+       .open    = tcpprobe_open,
+       .read    = tcpprobe_read,
+};
+
+static __init int tcpprobe_init(void)
+{
+       int ret = -ENOMEM;
+
+       init_waitqueue_head(&tcpw.wait);
+       spin_lock_init(&tcpw.lock);
+       tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock);
+
+       if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
+               goto err0;
+
+       ret = register_jprobe(&tcp_send_probe);
+       if (ret)
+               goto err1;
+
+       pr_info("TCP watch registered (port=%d)\n", port);
+       return 0;
+ err1:
+       proc_net_remove(procname);
+ err0:
+       kfifo_free(tcpw.fifo);
+       return ret;
+}
+module_init(tcpprobe_init);
+
+static __exit void tcpprobe_exit(void)
+{
+       kfifo_free(tcpw.fifo);
+       proc_net_remove(procname);
+       unregister_jprobe(&tcp_send_probe);
+
+}
+module_exit(tcpprobe_exit);
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c
new file mode 100644 (file)
index 0000000..11b42a7
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * TCP Veno congestion control
+ *
+ * This is based on the congestion detection/avoidance scheme described in
+ *    C. P. Fu, S. C. Liew.
+ *    "TCP Veno: TCP Enhancement for Transmission over Wireless Access Networks."
+ *    IEEE Journal on Selected Areas in Communication,
+ *    Feb. 2003.
+ *     See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/inet_diag.h>
+
+#include <net/tcp.h>
+
+/* Default values of the Veno variables, in fixed-point representation
+ * with V_PARAM_SHIFT bits to the right of the binary point.
+ */
+#define V_PARAM_SHIFT 1
+static const int beta = 3 << V_PARAM_SHIFT;
+
+/* Veno variables */
+struct veno {
+       u8 doing_veno_now;      /* if true, do veno for this rtt */
+       u16 cntrtt;             /* # of rtts measured within last rtt */
+       u32 minrtt;             /* min of rtts measured within last rtt (in usec) */
+       u32 basertt;            /* the min of all Veno rtt measurements seen (in usec) */
+       u32 inc;                /* decide whether to increase cwnd */
+       u32 diff;               /* calculate the diff rate */
+};
+
+/* There are several situations when we must "re-start" Veno:
+ *
+ *  o when a connection is established
+ *  o after an RTO
+ *  o after fast recovery
+ *  o when we send a packet and there is no outstanding
+ *    unacknowledged data (restarting an idle connection)
+ *
+ */
+static inline void veno_enable(struct sock *sk)
+{
+       struct veno *veno = inet_csk_ca(sk);
+
+       /* turn on Veno */
+       veno->doing_veno_now = 1;
+
+       veno->minrtt = 0x7fffffff;
+}
+
+static inline void veno_disable(struct sock *sk)
+{
+       struct veno *veno = inet_csk_ca(sk);
+
+       /* turn off Veno */
+       veno->doing_veno_now = 0;
+}
+
+static void tcp_veno_init(struct sock *sk)
+{
+       struct veno *veno = inet_csk_ca(sk);
+
+       veno->basertt = 0x7fffffff;
+       veno->inc = 1;
+       veno_enable(sk);
+}
+
+/* Do rtt sampling needed for Veno. */
+static void tcp_veno_rtt_calc(struct sock *sk, u32 usrtt)
+{
+       struct veno *veno = inet_csk_ca(sk);
+       u32 vrtt = usrtt + 1;   /* Never allow zero rtt or basertt */
+
+       /* Filter to find propagation delay: */
+       if (vrtt < veno->basertt)
+               veno->basertt = vrtt;
+
+       /* Find the min rtt during the last rtt to find
+        * the current prop. delay + queuing delay:
+        */
+       veno->minrtt = min(veno->minrtt, vrtt);
+       veno->cntrtt++;
+}
+
+static void tcp_veno_state(struct sock *sk, u8 ca_state)
+{
+       if (ca_state == TCP_CA_Open)
+               veno_enable(sk);
+       else
+               veno_disable(sk);
+}
+
+/*
+ * If the connection is idle and we are restarting,
+ * then we don't want to do any Veno calculations
+ * until we get fresh rtt samples.  So when we
+ * restart, we reset our Veno state to a clean
+ * state. After we get acks for this flight of
+ * packets, _then_ we can make Veno calculations
+ * again.
+ */
+static void tcp_veno_cwnd_event(struct sock *sk, enum tcp_ca_event event)
+{
+       if (event == CA_EVENT_CWND_RESTART || event == CA_EVENT_TX_START)
+               tcp_veno_init(sk);
+}
+
+static void tcp_veno_cong_avoid(struct sock *sk, u32 ack,
+                               u32 seq_rtt, u32 in_flight, int flag)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct veno *veno = inet_csk_ca(sk);
+
+       if (!veno->doing_veno_now)
+               return tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag);
+
+       /* limited by applications */
+       if (!tcp_is_cwnd_limited(sk, in_flight))
+               return;
+
+       /* We do the Veno calculations only if we got enough rtt samples */
+       if (veno->cntrtt <= 2) {
+               /* We don't have enough rtt samples to do the Veno
+                * calculation, so we'll behave like Reno.
+                */
+               tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag);
+       } else {
+               u32 rtt, target_cwnd;
+
+               /* We have enough rtt samples, so, using the Veno
+                * algorithm, we determine the state of the network.
+                */
+
+               rtt = veno->minrtt;
+
+               target_cwnd = ((tp->snd_cwnd * veno->basertt)
+                              << V_PARAM_SHIFT) / rtt;
+
+               veno->diff = (tp->snd_cwnd << V_PARAM_SHIFT) - target_cwnd;
+
+               if (tp->snd_cwnd <= tp->snd_ssthresh) {
+                       /* Slow start.  */
+                       tcp_slow_start(tp);
+               } else {
+                       /* Congestion avoidance. */
+                       if (veno->diff < beta) {
+                               /* In the "non-congestive state", increase cwnd
+                                *  every rtt.
+                                */
+                               if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+                                       if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+                                               tp->snd_cwnd++;
+                                       tp->snd_cwnd_cnt = 0;
+                               } else
+                                       tp->snd_cwnd_cnt++;
+                       } else {
+                               /* In the "congestive state", increase cwnd
+                                * every other rtt.
+                                */
+                               if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+                                       if (veno->inc
+                                           && tp->snd_cwnd <
+                                           tp->snd_cwnd_clamp) {
+                                               tp->snd_cwnd++;
+                                               veno->inc = 0;
+                                       } else
+                                               veno->inc = 1;
+                                       tp->snd_cwnd_cnt = 0;
+                               } else
+                                       tp->snd_cwnd_cnt++;
+                       }
+
+               }
+               if (tp->snd_cwnd < 2)
+                       tp->snd_cwnd = 2;
+               else if (tp->snd_cwnd > tp->snd_cwnd_clamp)
+                       tp->snd_cwnd = tp->snd_cwnd_clamp;
+       }
+       /* Wipe the slate clean for the next rtt. */
+       /* veno->cntrtt = 0; */
+       veno->minrtt = 0x7fffffff;
+}
+
+/* Veno MD phase */
+static u32 tcp_veno_ssthresh(struct sock *sk)
+{
+       const struct tcp_sock *tp = tcp_sk(sk);
+       struct veno *veno = inet_csk_ca(sk);
+
+       if (veno->diff < beta)
+               /* in "non-congestive state", cut cwnd by 1/5 */
+               return max(tp->snd_cwnd * 4 / 5, 2U);
+       else
+               /* in "congestive state", cut cwnd by 1/2 */
+               return max(tp->snd_cwnd >> 1U, 2U);
+}
+
+static struct tcp_congestion_ops tcp_veno = {
+       .init           = tcp_veno_init,
+       .ssthresh       = tcp_veno_ssthresh,
+       .cong_avoid     = tcp_veno_cong_avoid,
+       .rtt_sample     = tcp_veno_rtt_calc,
+       .set_state      = tcp_veno_state,
+       .cwnd_event     = tcp_veno_cwnd_event,
+
+       .owner          = THIS_MODULE,
+       .name           = "veno",
+};
+
+static int __init tcp_veno_register(void)
+{
+       BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE);
+       tcp_register_congestion_control(&tcp_veno);
+       return 0;
+}
+
+static void __exit tcp_veno_unregister(void)
+{
+       tcp_unregister_congestion_control(&tcp_veno);
+}
+
+module_init(tcp_veno_register);
+module_exit(tcp_veno_unregister);
+
+MODULE_AUTHOR("Bin Zhou, Cheng Peng Fu");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Veno");
index 0c340c3756c2e06082f9cd400a53498614239fae..4247da1384bfb25487b51add257cb8d852ec8327 100644 (file)
@@ -1,7 +1,24 @@
 /*
- * TCP Westwood+
+ * TCP Westwood+: end-to-end bandwidth estimation for TCP
  *
- *     Angelo Dell'Aera:       TCP Westwood+ support
+ *      Angelo Dell'Aera: author of the first version of TCP Westwood+ in Linux 2.4
+ *
+ * Support at http://c3lab.poliba.it/index.php/Westwood
+ * Main references in literature:
+ *
+ * - Mascolo S, Casetti, M. Gerla et al.
+ *   "TCP Westwood: bandwidth estimation for TCP" Proc. ACM Mobicom 2001
+ *
+ * - A. Grieco, s. Mascolo
+ *   "Performance evaluation of New Reno, Vegas, Westwood+ TCP" ACM Computer
+ *     Comm. Review, 2004
+ *
+ * - A. Dell'Aera, L. Grieco, S. Mascolo.
+ *   "Linux 2.4 Implementation of Westwood+ TCP with Rate-Halving :
+ *    A Performance Evaluation Over the Internet" (ICC 2004), Paris, June 2004
+ *
+ * Westwood+ employs end-to-end bandwidth measurement to set cwnd and
+ * ssthresh after packet loss. The probing phase is as the original Reno.
  */
 
 #include <linux/config.h>
@@ -22,6 +39,8 @@ struct westwood {
        u32    accounted;
        u32    rtt;
        u32    rtt_min;          /* minimum observed RTT */
+       u8     first_ack;        /* flag which infers that this is the first ack */
+       u8     reset_rtt_min;    /* Reset RTT min to next RTT sample*/
 };
 
 
@@ -49,9 +68,11 @@ static void tcp_westwood_init(struct sock *sk)
         w->bw_est = 0;
         w->accounted = 0;
         w->cumul_ack = 0;
+       w->reset_rtt_min = 1;
        w->rtt_min = w->rtt = TCP_WESTWOOD_INIT_RTT;
        w->rtt_win_sx = tcp_time_stamp;
        w->snd_una = tcp_sk(sk)->snd_una;
+       w->first_ack = 1;
 }
 
 /*
@@ -63,10 +84,16 @@ static inline u32 westwood_do_filter(u32 a, u32 b)
        return (((7 * a) + b) >> 3);
 }
 
-static inline void westwood_filter(struct westwood *w, u32 delta)
+static void westwood_filter(struct westwood *w, u32 delta)
 {
-       w->bw_ns_est = westwood_do_filter(w->bw_ns_est, w->bk / delta);
-       w->bw_est = westwood_do_filter(w->bw_est, w->bw_ns_est);
+       /* If the filter is empty fill it with the first sample of bandwidth  */
+       if (w->bw_ns_est == 0 && w->bw_est == 0) {
+               w->bw_ns_est = w->bk / delta;
+               w->bw_est = w->bw_ns_est;
+       } else {
+               w->bw_ns_est = westwood_do_filter(w->bw_ns_est, w->bk / delta);
+               w->bw_est = westwood_do_filter(w->bw_est, w->bw_ns_est);
+       }
 }
 
 /*
@@ -91,6 +118,15 @@ static void westwood_update_window(struct sock *sk)
        struct westwood *w = inet_csk_ca(sk);
        s32 delta = tcp_time_stamp - w->rtt_win_sx;
 
+       /* Initialize w->snd_una with the first acked sequence number in order
+        * to fix mismatch between tp->snd_una and w->snd_una for the first
+        * bandwidth sample
+        */
+        if (w->first_ack) {
+               w->snd_una = tcp_sk(sk)->snd_una;
+               w->first_ack = 0;
+       }
+
        /*
         * See if a RTT-window has passed.
         * Be careful since if RTT is less than
@@ -108,6 +144,16 @@ static void westwood_update_window(struct sock *sk)
        }
 }
 
+static inline void update_rtt_min(struct westwood *w)
+{
+       if (w->reset_rtt_min) {
+               w->rtt_min = w->rtt;
+               w->reset_rtt_min = 0;   
+       } else
+               w->rtt_min = min(w->rtt, w->rtt_min);
+}
+
+
 /*
  * @westwood_fast_bw
  * It is called when we are in fast path. In particular it is called when
@@ -123,7 +169,7 @@ static inline void westwood_fast_bw(struct sock *sk)
 
        w->bk += tp->snd_una - w->snd_una;
        w->snd_una = tp->snd_una;
-       w->rtt_min = min(w->rtt, w->rtt_min);
+       update_rtt_min(w);
 }
 
 /*
@@ -162,12 +208,6 @@ static inline u32 westwood_acked_count(struct sock *sk)
        return w->cumul_ack;
 }
 
-static inline u32 westwood_bw_rttmin(const struct sock *sk)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-       const struct westwood *w = inet_csk_ca(sk);
-       return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
-}
 
 /*
  * TCP Westwood
@@ -175,9 +215,11 @@ static inline u32 westwood_bw_rttmin(const struct sock *sk)
  * in packets we use mss_cache). Rttmin is guaranteed to be >= 2
  * so avoids ever returning 0.
  */
-static u32 tcp_westwood_cwnd_min(struct sock *sk)
+static u32 tcp_westwood_bw_rttmin(const struct sock *sk)
 {
-       return westwood_bw_rttmin(sk);
+       const struct tcp_sock *tp = tcp_sk(sk);
+       const struct westwood *w = inet_csk_ca(sk);
+       return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
 }
 
 static void tcp_westwood_event(struct sock *sk, enum tcp_ca_event event)
@@ -191,17 +233,19 @@ static void tcp_westwood_event(struct sock *sk, enum tcp_ca_event event)
                break;
 
        case CA_EVENT_COMPLETE_CWR:
-               tp->snd_cwnd = tp->snd_ssthresh = westwood_bw_rttmin(sk);
+               tp->snd_cwnd = tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
                break;
 
        case CA_EVENT_FRTO:
-               tp->snd_ssthresh = westwood_bw_rttmin(sk);
+               tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
+               /* Update RTT_min when next ack arrives */
+               w->reset_rtt_min = 1;
                break;
 
        case CA_EVENT_SLOW_ACK:
                westwood_update_window(sk);
                w->bk += westwood_acked_count(sk);
-               w->rtt_min = min(w->rtt, w->rtt_min);
+               update_rtt_min(w);
                break;
 
        default:
@@ -235,7 +279,7 @@ static struct tcp_congestion_ops tcp_westwood = {
        .init           = tcp_westwood_init,
        .ssthresh       = tcp_reno_ssthresh,
        .cong_avoid     = tcp_reno_cong_avoid,
-       .min_cwnd       = tcp_westwood_cwnd_min,
+       .min_cwnd       = tcp_westwood_bw_rttmin,
        .cwnd_event     = tcp_westwood_event,
        .get_info       = tcp_westwood_info,
        .pkts_acked     = tcp_westwood_pkts_acked,
index 3e174c83bfe7a805fe40d446d7114124453b0d9f..817ed84511a6f67051800f6a140ab1a1f34d2eaf 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/string.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
-#include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 
@@ -24,15 +23,6 @@ int xfrm4_rcv(struct sk_buff *skb)
 
 EXPORT_SYMBOL(xfrm4_rcv);
 
-static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
-{
-       struct iphdr *outer_iph = skb->nh.iph;
-       struct iphdr *inner_iph = skb->h.ipiph;
-
-       if (INET_ECN_is_ce(outer_iph->tos))
-               IP_ECN_set_ce(inner_iph);
-}
-
 static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
 {
        switch (nexthdr) {
@@ -113,24 +103,10 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 
                xfrm_vec[xfrm_nr++] = x;
 
-               iph = skb->nh.iph;
+               if (x->mode->input(x, skb))
+                       goto drop;
 
                if (x->props.mode) {
-                       if (iph->protocol != IPPROTO_IPIP)
-                               goto drop;
-                       if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-                               goto drop;
-                       if (skb_cloned(skb) &&
-                           pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-                               goto drop;
-                       if (x->props.flags & XFRM_STATE_DECAP_DSCP)
-                               ipv4_copy_dscp(iph, skb->h.ipiph);
-                       if (!(x->props.flags & XFRM_STATE_NOECN))
-                               ipip_ecn_decapsulate(skb);
-                       skb->mac.raw = memmove(skb->data - skb->mac_len,
-                                              skb->mac.raw, skb->mac_len);
-                       skb->nh.raw = skb->data;
-                       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
                        decaps = 1;
                        break;
                }
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
new file mode 100644 (file)
index 0000000..a9e6b3d
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * xfrm4_mode_transport.c - Transport mode encapsulation for IPv4.
+ *
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+/* Add encapsulation header.
+ *
+ * The IP header will be moved forward to make space for the encapsulation
+ * header.
+ *
+ * On exit, skb->h will be set to the start of the payload to be processed
+ * by x->type->output and skb->nh will be set to the top IP header.
+ */
+static int xfrm4_transport_output(struct sk_buff *skb)
+{
+       struct xfrm_state *x;
+       struct iphdr *iph;
+       int ihl;
+
+       iph = skb->nh.iph;
+       skb->h.ipiph = iph;
+
+       ihl = iph->ihl * 4;
+       skb->h.raw += ihl;
+
+       x = skb->dst->xfrm;
+       skb->nh.raw = memmove(skb_push(skb, x->props.header_len), iph, ihl);
+       return 0;
+}
+
+/* Remove encapsulation header.
+ *
+ * The IP header will be moved over the top of the encapsulation header.
+ *
+ * On entry, skb->h shall point to where the IP header should be and skb->nh
+ * shall be set to where the IP header currently is.  skb->data shall point
+ * to the start of the payload.
+ */
+static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int ihl = skb->data - skb->h.raw;
+
+       if (skb->h.raw != skb->nh.raw)
+               skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl);
+       skb->nh.iph->tot_len = htons(skb->len + ihl);
+       skb->h.raw = skb->data;
+       return 0;
+}
+
+static struct xfrm_mode xfrm4_transport_mode = {
+       .input = xfrm4_transport_input,
+       .output = xfrm4_transport_output,
+       .owner = THIS_MODULE,
+       .encap = XFRM_MODE_TRANSPORT,
+};
+
+static int __init xfrm4_transport_init(void)
+{
+       return xfrm_register_mode(&xfrm4_transport_mode, AF_INET);
+}
+
+static void __exit xfrm4_transport_exit(void)
+{
+       int err;
+
+       err = xfrm_unregister_mode(&xfrm4_transport_mode, AF_INET);
+       BUG_ON(err);
+}
+
+module_init(xfrm4_transport_init);
+module_exit(xfrm4_transport_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
new file mode 100644 (file)
index 0000000..f8d880b
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * xfrm4_mode_tunnel.c - Tunnel mode encapsulation for IPv4.
+ *
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/inet_ecn.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
+{
+       struct iphdr *outer_iph = skb->nh.iph;
+       struct iphdr *inner_iph = skb->h.ipiph;
+
+       if (INET_ECN_is_ce(outer_iph->tos))
+               IP_ECN_set_ce(inner_iph);
+}
+
+/* Add encapsulation header.
+ *
+ * The top IP header will be constructed per RFC 2401.  The following fields
+ * in it shall be filled in by x->type->output:
+ *      tot_len
+ *      check
+ *
+ * On exit, skb->h will be set to the start of the payload to be processed
+ * by x->type->output and skb->nh will be set to the top IP header.
+ */
+static int xfrm4_tunnel_output(struct sk_buff *skb)
+{
+       struct dst_entry *dst = skb->dst;
+       struct xfrm_state *x = dst->xfrm;
+       struct iphdr *iph, *top_iph;
+       int flags;
+
+       iph = skb->nh.iph;
+       skb->h.ipiph = iph;
+
+       skb->nh.raw = skb_push(skb, x->props.header_len);
+       top_iph = skb->nh.iph;
+
+       top_iph->ihl = 5;
+       top_iph->version = 4;
+
+       /* DS disclosed */
+       top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
+
+       flags = x->props.flags;
+       if (flags & XFRM_STATE_NOECN)
+               IP_ECN_clear(top_iph);
+
+       top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
+               0 : (iph->frag_off & htons(IP_DF));
+       if (!top_iph->frag_off)
+               __ip_select_ident(top_iph, dst->child, 0);
+
+       top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
+
+       top_iph->saddr = x->props.saddr.a4;
+       top_iph->daddr = x->id.daddr.a4;
+       top_iph->protocol = IPPROTO_IPIP;
+
+       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+       return 0;
+}
+
+static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+       struct iphdr *iph = skb->nh.iph;
+       int err = -EINVAL;
+
+       if (iph->protocol != IPPROTO_IPIP)
+               goto out;
+       if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+               goto out;
+
+       if (skb_cloned(skb) &&
+           (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+               goto out;
+
+       if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+               ipv4_copy_dscp(iph, skb->h.ipiph);
+       if (!(x->props.flags & XFRM_STATE_NOECN))
+               ipip_ecn_decapsulate(skb);
+       skb->mac.raw = memmove(skb->data - skb->mac_len,
+                              skb->mac.raw, skb->mac_len);
+       skb->nh.raw = skb->data;
+       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+       err = 0;
+
+out:
+       return err;
+}
+
+static struct xfrm_mode xfrm4_tunnel_mode = {
+       .input = xfrm4_tunnel_input,
+       .output = xfrm4_tunnel_output,
+       .owner = THIS_MODULE,
+       .encap = XFRM_MODE_TUNNEL,
+};
+
+static int __init xfrm4_tunnel_init(void)
+{
+       return xfrm_register_mode(&xfrm4_tunnel_mode, AF_INET);
+}
+
+static void __exit xfrm4_tunnel_exit(void)
+{
+       int err;
+
+       err = xfrm_unregister_mode(&xfrm4_tunnel_mode, AF_INET);
+       BUG_ON(err);
+}
+
+module_init(xfrm4_tunnel_init);
+module_exit(xfrm4_tunnel_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TUNNEL);
index 4ef8efaf6a67f8515015e25d50e2900f63dca637..ac9d91d4bb0563c2e471bfa5483c901ac38bac64 100644 (file)
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/netfilter_ipv4.h>
-#include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 #include <net/icmp.h>
 
-/* Add encapsulation header.
- *
- * In transport mode, the IP header will be moved forward to make space
- * for the encapsulation header.
- *
- * In tunnel mode, the top IP header will be constructed per RFC 2401.
- * The following fields in it shall be filled in by x->type->output:
- *     tot_len
- *     check
- *
- * On exit, skb->h will be set to the start of the payload to be processed
- * by x->type->output and skb->nh will be set to the top IP header.
- */
-static void xfrm4_encap(struct sk_buff *skb)
-{
-       struct dst_entry *dst = skb->dst;
-       struct xfrm_state *x = dst->xfrm;
-       struct iphdr *iph, *top_iph;
-       int flags;
-
-       iph = skb->nh.iph;
-       skb->h.ipiph = iph;
-
-       skb->nh.raw = skb_push(skb, x->props.header_len);
-       top_iph = skb->nh.iph;
-
-       if (!x->props.mode) {
-               skb->h.raw += iph->ihl*4;
-               memmove(top_iph, iph, iph->ihl*4);
-               return;
-       }
-
-       top_iph->ihl = 5;
-       top_iph->version = 4;
-
-       /* DS disclosed */
-       top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
-
-       flags = x->props.flags;
-       if (flags & XFRM_STATE_NOECN)
-               IP_ECN_clear(top_iph);
-
-       top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
-               0 : (iph->frag_off & htons(IP_DF));
-       if (!top_iph->frag_off)
-               __ip_select_ident(top_iph, dst->child, 0);
-
-       top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
-
-       top_iph->saddr = x->props.saddr.a4;
-       top_iph->daddr = x->id.daddr.a4;
-       top_iph->protocol = IPPROTO_IPIP;
-
-       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
-}
-
 static int xfrm4_tunnel_check_size(struct sk_buff *skb)
 {
        int mtu, ret = 0;
@@ -121,7 +64,9 @@ static int xfrm4_output_one(struct sk_buff *skb)
                if (err)
                        goto error;
 
-               xfrm4_encap(skb);
+               err = x->mode->output(skb);
+               if (err)
+                       goto error;
 
                err = x->type->output(x, skb);
                if (err)
index 8604c747bca5fa3d1353159e906ddfcec0da1290..c0465284dfacba4dccd0063e357e865301023d40 100644 (file)
@@ -17,8 +17,6 @@
 static struct dst_ops xfrm4_dst_ops;
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
 
-static struct xfrm_type_map xfrm4_type_map = { .lock = RW_LOCK_UNLOCKED };
-
 static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
 {
        return __ip_route_output_key((struct rtable**)dst, fl);
@@ -237,9 +235,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
 
 static inline int xfrm4_garbage_collect(void)
 {
-       read_lock(&xfrm4_policy_afinfo.lock);
        xfrm4_policy_afinfo.garbage_collect();
-       read_unlock(&xfrm4_policy_afinfo.lock);
        return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2);
 }
 
@@ -299,8 +295,6 @@ static struct dst_ops xfrm4_dst_ops = {
 
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
        .family =               AF_INET,
-       .lock =                 RW_LOCK_UNLOCKED,
-       .type_map =             &xfrm4_type_map,
        .dst_ops =              &xfrm4_dst_ops,
        .dst_lookup =           xfrm4_dst_lookup,
        .find_bundle =          __xfrm4_find_bundle,
index dbabf81a9b7b4d19389c8d85e3b686026e33dd33..81e1751c966e1008256d01bfc845588038147523 100644 (file)
@@ -131,7 +131,6 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto,
 
 static struct xfrm_state_afinfo xfrm4_state_afinfo = {
        .family                 = AF_INET,
-       .lock                   = RW_LOCK_UNLOCKED,
        .init_flags             = xfrm4_init_flags,
        .init_tempsel           = __xfrm4_init_tempsel,
        .state_lookup           = __xfrm4_state_lookup,
index f8a107ab5592e58116660e64e43de4d0696a7066..e923d4dea4188e4bd2f4d4b8d4dba10eee411bb5 100644 (file)
@@ -106,6 +106,26 @@ config INET6_TUNNEL
        tristate
        default n
 
+config INET6_XFRM_MODE_TRANSPORT
+       tristate "IPv6: IPsec transport mode"
+       depends on IPV6
+       default IPV6
+       select XFRM
+       ---help---
+         Support for IPsec transport mode.
+
+         If unsure, say Y.
+
+config INET6_XFRM_MODE_TUNNEL
+       tristate "IPv6: IPsec tunnel mode"
+       depends on IPV6
+       default IPV6
+       select XFRM
+       ---help---
+         Support for IPsec tunnel mode.
+
+         If unsure, say Y.
+
 config IPV6_TUNNEL
        tristate "IPv6: IPv6-in-IPv6 tunnel"
        select INET6_TUNNEL
index a760b0988fbbf65de3ca7bafda85b6baed90b3c4..386e0a6269481330fc74be675de7bfd1800e20dc 100644 (file)
@@ -20,6 +20,8 @@ obj-$(CONFIG_INET6_ESP) += esp6.o
 obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o
 obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o
 obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
+obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o
+obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
 obj-$(CONFIG_NETFILTER)        += netfilter/
 
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
index 445006ee452281733917bb84f31da513f21c8ed6..c2c26fa0943df9e8e7a3e107ffec095c9b08c003 100644 (file)
@@ -2860,6 +2860,11 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
 }
 
+/* Maximum length of ifa_cacheinfo attributes */
+#define INET6_IFADDR_RTA_SPACE \
+               RTA_SPACE(16) /* IFA_ADDRESS */ + \
+               RTA_SPACE(sizeof(struct ifa_cacheinfo)) /* CACHEINFO */
+
 static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
                             u32 pid, u32 seq, int event, unsigned int flags)
 {
@@ -3092,7 +3097,7 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
 static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
 {
        struct sk_buff *skb;
-       int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);
+       int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE);
 
        skb = alloc_skb(size, GFP_ATOMIC);
        if (!skb) {
@@ -3142,6 +3147,17 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
 #endif
 }
 
+/* Maximum length of ifinfomsg attributes */
+#define INET6_IFINFO_RTA_SPACE \
+               RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \
+               RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ + \
+               RTA_SPACE(sizeof(u32)) /* MTU */ + \
+               RTA_SPACE(sizeof(int)) /* LINK */ + \
+               RTA_SPACE(0) /* PROTINFO */ + \
+               RTA_SPACE(sizeof(u32)) /* FLAGS */ + \
+               RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \
+               RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */
+
 static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 
                             u32 pid, u32 seq, int event, unsigned int flags)
 {
@@ -3235,8 +3251,7 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
 {
        struct sk_buff *skb;
-       /* 128 bytes ?? */
-       int size = NLMSG_SPACE(sizeof(struct ifinfomsg)+128);
+       int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE);
        
        skb = alloc_skb(size, GFP_ATOMIC);
        if (!skb) {
@@ -3252,6 +3267,11 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
        netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC);
 }
 
+/* Maximum length of prefix_cacheinfo attributes */
+#define INET6_PREFIX_RTA_SPACE \
+               RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \
+               RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */
+
 static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
                        struct prefix_info *pinfo, u32 pid, u32 seq, 
                        int event, unsigned int flags)
@@ -3296,7 +3316,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
                         struct prefix_info *pinfo)
 {
        struct sk_buff *skb;
-       int size = NLMSG_SPACE(sizeof(struct prefixmsg)+128);
+       int size = NLMSG_SPACE(sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE);
 
        skb = alloc_skb(size, GFP_ATOMIC);
        if (!skb) {
index 6778173a3dda85d666f1508c77aa7895dedd801a..d31c0d6c04488c90cf7c8972851c9f526aa1f1f0 100644 (file)
@@ -292,7 +292,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
 
                memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
                memset(ah->auth_data, 0, ahp->icv_trunc_len);
-               skb_push(skb, skb->data - skb->nh.raw);
+               skb_push(skb, hdr_len);
                ahp->icv(ahp, skb, ah->auth_data);
                if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
                        LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n");
@@ -301,12 +301,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
                }
        }
 
-       skb->nh.raw = skb_pull(skb, ah_hlen);
-       memcpy(skb->nh.raw, tmp_hdr, hdr_len);
-       skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
-       skb_pull(skb, hdr_len);
-       skb->h.raw = skb->data;
-
+       skb->h.raw = memcpy(skb->nh.raw += ah_hlen, tmp_hdr, hdr_len);
+       __skb_pull(skb, ah_hlen + hdr_len);
 
        kfree(tmp_hdr);
 
index 22f04607903759bd59eae8c1d11b49d3c58c1582..a15a6f320f7000c5b512ff3f6f3085a33016c3df 100644 (file)
@@ -142,25 +142,17 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
 
        int hdr_len = skb->h.raw - skb->nh.raw;
        int nfrags;
-       unsigned char *tmp_hdr = NULL;
        int ret = 0;
 
        if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) {
                ret = -EINVAL;
-               goto out_nofree;
+               goto out;
        }
 
        if (elen <= 0 || (elen & (blksize-1))) {
                ret = -EINVAL;
-               goto out_nofree;
-       }
-
-       tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
-       if (!tmp_hdr) {
-               ret = -ENOMEM;
-               goto out_nofree;
+               goto out;
        }
-       memcpy(tmp_hdr, skb->nh.raw, hdr_len);
 
        /* If integrity check is required, do this. */
         if (esp->auth.icv_full_len) {
@@ -222,16 +214,12 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
                /* ... check padding bits here. Silly. :-) */ 
 
                pskb_trim(skb, skb->len - alen - padlen - 2);
-               skb->h.raw = skb_pull(skb, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen);
-               skb->nh.raw += sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
-               memcpy(skb->nh.raw, tmp_hdr, hdr_len);
-               skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
                ret = nexthdr[1];
        }
 
+       skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - hdr_len;
+
 out:
-       kfree(tmp_hdr);
-out_nofree:
        return ret;
 }
 
index e46048974f37d217e4182f6ca20b252b0c137c53..d29620f4910e1e17d6290c961681c7e075be9746 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/in6.h>
 #include <linux/tcp.h>
 #include <linux/route.h>
+#include <linux/module.h>
 
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
@@ -458,6 +459,7 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
        nf_bridge_get(to->nf_bridge);
 #endif
 #endif
+       skb_copy_secmark(to, from);
 }
 
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
@@ -488,6 +490,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 
        return offset;
 }
+EXPORT_SYMBOL_GPL(ip6_find_1stfragopt);
 
 static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
index 48636436028ab2b1ce1b1dfee0bce70b545e0799..f28cd37feed3132444f84609cfaaed24ecfe3ede 100644 (file)
@@ -65,38 +65,25 @@ static LIST_HEAD(ipcomp6_tfms_list);
 
 static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-       int err = 0;
-       u8 nexthdr = 0;
-       int hdr_len = skb->h.raw - skb->nh.raw;
-       unsigned char *tmp_hdr = NULL;
+       int err = -ENOMEM;
        struct ipv6hdr *iph;
+       struct ipv6_comp_hdr *ipch;
        int plen, dlen;
        struct ipcomp_data *ipcd = x->data;
        u8 *start, *scratch;
        struct crypto_tfm *tfm;
        int cpu;
 
-       if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
-               skb_linearize(skb, GFP_ATOMIC) != 0) {
-               err = -ENOMEM;
+       if (skb_linearize_cow(skb))
                goto out;
-       }
 
        skb->ip_summed = CHECKSUM_NONE;
 
        /* Remove ipcomp header and decompress original payload */
        iph = skb->nh.ipv6h;
-       tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
-       if (!tmp_hdr)
-               goto out;
-       memcpy(tmp_hdr, iph, hdr_len);
-       nexthdr = *(u8 *)skb->data;
-       skb_pull(skb, sizeof(struct ipv6_comp_hdr)); 
-       skb->nh.raw += sizeof(struct ipv6_comp_hdr);
-       memcpy(skb->nh.raw, tmp_hdr, hdr_len);
-       iph = skb->nh.ipv6h;
-       iph->payload_len = htons(ntohs(iph->payload_len) - sizeof(struct ipv6_comp_hdr));
-       skb->h.raw = skb->data;
+       ipch = (void *)skb->data;
+       skb->h.raw = skb->nh.raw + sizeof(*ipch);
+       __skb_pull(skb, sizeof(*ipch));
 
        /* decompression */
        plen = skb->len;
@@ -125,18 +112,11 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
 
        skb_put(skb, dlen - plen);
        memcpy(skb->data, scratch, dlen);
+       err = ipch->nexthdr;
 
-       iph = skb->nh.ipv6h;
-       iph->payload_len = htons(skb->len);
-       
 out_put_cpu:
        put_cpu();
 out:
-       kfree(tmp_hdr);
-       if (err)
-               goto error_out;
-       return nexthdr;
-error_out:
        return err;
 }
 
@@ -159,10 +139,8 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
                goto out_ok;
        }
 
-       if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
-               skb_linearize(skb, GFP_ATOMIC) != 0) {
+       if (skb_linearize_cow(skb))
                goto out_ok;
-       }
 
        /* compression */
        plen = skb->len - hdr_len;
index 93bae36f2663e03370e8016da83ae4a43843e6ad..2a71c3b669f17993b562cd1875a7b4f04e082b38 100644 (file)
@@ -189,7 +189,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
 
        /* This is where we call the helper: as the packet goes out. */
        ct = nf_ct_get(*pskb, &ctinfo);
-       if (!ct)
+       if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
                goto out;
 
        help = nfct_help(ct);
index 86c6703265d09b9cf976d95917e1ca2225a6274b..ef18a7b7014b1c31cd9e6bae5518bdc1a390b070 100644 (file)
@@ -233,7 +233,7 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
                return -NF_ACCEPT;
        }
 
-       if (hooknum == NF_IP6_PRE_ROUTING &&
+       if (nf_conntrack_checksum && hooknum == NF_IP6_PRE_ROUTING &&
            nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
                nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
                              "nf_ct_icmpv6: ICMPv6 checksum failed\n");
index 3e319035f82df0d6a429ad47ec88e83991038fa8..c32a029e43f0530a3c5e58c764ea3eef16247646 100644 (file)
@@ -456,13 +456,9 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
                DEBUGP("queue: message is too short.\n");
                goto err;
        }
-       if (end-offset < skb->len) {
-               if (pskb_trim(skb, end - offset)) {
-                       DEBUGP("Can't trim\n");
-                       goto err;
-               }
-               if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-                       skb->ip_summed = CHECKSUM_NONE;
+       if (pskb_trim_rcsum(skb, end - offset)) {
+               DEBUGP("Can't trim\n");
+               goto err;
        }
 
        /* Find out which fragments are in front and at the back of us
index 0190e39096b978692349bd0dbd3e5271a828fab3..8a777932786d7d4c0975fd6941489039abad3d06 100644 (file)
@@ -280,10 +280,13 @@ static int inline rt6_check_neigh(struct rt6_info *rt)
 {
        struct neighbour *neigh = rt->rt6i_nexthop;
        int m = 0;
-       if (neigh) {
+       if (rt->rt6i_flags & RTF_NONEXTHOP ||
+           !(rt->rt6i_flags & RTF_GATEWAY))
+               m = 1;
+       else if (neigh) {
                read_lock_bh(&neigh->lock);
                if (neigh->nud_state & NUD_VALID)
-                       m = 1;
+                       m = 2;
                read_unlock_bh(&neigh->lock);
        }
        return m;
@@ -292,15 +295,18 @@ static int inline rt6_check_neigh(struct rt6_info *rt)
 static int rt6_score_route(struct rt6_info *rt, int oif,
                           int strict)
 {
-       int m = rt6_check_dev(rt, oif);
+       int m, n;
+               
+       m = rt6_check_dev(rt, oif);
        if (!m && (strict & RT6_SELECT_F_IFACE))
                return -1;
 #ifdef CONFIG_IPV6_ROUTER_PREF
        m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
 #endif
-       if (rt6_check_neigh(rt))
+       n = rt6_check_neigh(rt);
+       if (n > 1)
                m |= 16;
-       else if (strict & RT6_SELECT_F_REACHABLE)
+       else if (!n && strict & RT6_SELECT_F_REACHABLE)
                return -1;
        return m;
 }
index 301eee726b0ff64eb8e3dc24b4432550e28de876..a50eb306e9e277605e4202cc14cacdf026357b59 100644 (file)
@@ -1218,8 +1218,16 @@ process:
        bh_lock_sock(sk);
        ret = 0;
        if (!sock_owned_by_user(sk)) {
-               if (!tcp_prequeue(sk, skb))
-                       ret = tcp_v6_do_rcv(sk, skb);
+#ifdef CONFIG_NET_DMA
+                struct tcp_sock *tp = tcp_sk(sk);
+                if (tp->ucopy.dma_chan)
+                        ret = tcp_v6_do_rcv(sk, skb);
+                else
+#endif
+               {
+                       if (!tcp_prequeue(sk, skb))
+                               ret = tcp_v6_do_rcv(sk, skb);
+               }
        } else
                sk_add_backlog(sk, skb);
        bh_unlock_sock(sk);
index 00cfdee18dcac1e6fa5a95223c029426974a7f6c..0405d74ff910098f54d23a042bf3995a4a99e593 100644 (file)
 #include <linux/string.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
-#include <net/dsfield.h>
-#include <net/inet_ecn.h>
-#include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
-{
-       struct ipv6hdr *outer_iph = skb->nh.ipv6h;
-       struct ipv6hdr *inner_iph = skb->h.ipv6h;
-
-       if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
-               IP6_ECN_set_ce(inner_iph);
-}
-
 int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
 {
        int err;
@@ -81,21 +69,10 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
 
                xfrm_vec[xfrm_nr++] = x;
 
+               if (x->mode->input(x, skb))
+                       goto drop;
+
                if (x->props.mode) { /* XXX */
-                       if (nexthdr != IPPROTO_IPV6)
-                               goto drop;
-                       if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
-                               goto drop;
-                       if (skb_cloned(skb) &&
-                           pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-                               goto drop;
-                       if (x->props.flags & XFRM_STATE_DECAP_DSCP)
-                               ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
-                       if (!(x->props.flags & XFRM_STATE_NOECN))
-                               ipip6_ecn_decapsulate(skb);
-                       skb->mac.raw = memmove(skb->data - skb->mac_len,
-                                              skb->mac.raw, skb->mac_len);
-                       skb->nh.raw = skb->data;
                        decaps = 1;
                        break;
                }
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
new file mode 100644 (file)
index 0000000..711d713
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * xfrm6_mode_transport.c - Transport mode encapsulation for IPv6.
+ *
+ * Copyright (C) 2002 USAGI/WIDE Project
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+
+/* Add encapsulation header.
+ *
+ * The IP header and mutable extension headers will be moved forward to make
+ * space for the encapsulation header.
+ *
+ * On exit, skb->h will be set to the start of the encapsulation header to be
+ * filled in by x->type->output and skb->nh will be set to the nextheader field
+ * of the extension header directly preceding the encapsulation header, or in
+ * its absence, that of the top IP header.  The value of skb->data will always
+ * point to the top IP header.
+ */
+static int xfrm6_transport_output(struct sk_buff *skb)
+{
+       struct xfrm_state *x = skb->dst->xfrm;
+       struct ipv6hdr *iph;
+       u8 *prevhdr;
+       int hdr_len;
+
+       skb_push(skb, x->props.header_len);
+       iph = skb->nh.ipv6h;
+
+       hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
+       skb->nh.raw = prevhdr - x->props.header_len;
+       skb->h.raw = skb->data + hdr_len;
+       memmove(skb->data, iph, hdr_len);
+       return 0;
+}
+
+/* Remove encapsulation header.
+ *
+ * The IP header will be moved over the top of the encapsulation header.
+ *
+ * On entry, skb->h shall point to where the IP header should be and skb->nh
+ * shall be set to where the IP header currently is.  skb->data shall point
+ * to the start of the payload.
+ */
+static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int ihl = skb->data - skb->h.raw;
+
+       if (skb->h.raw != skb->nh.raw)
+               skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl);
+       skb->nh.ipv6h->payload_len = htons(skb->len + ihl -
+                                          sizeof(struct ipv6hdr));
+       skb->h.raw = skb->data;
+       return 0;
+}
+
+static struct xfrm_mode xfrm6_transport_mode = {
+       .input = xfrm6_transport_input,
+       .output = xfrm6_transport_output,
+       .owner = THIS_MODULE,
+       .encap = XFRM_MODE_TRANSPORT,
+};
+
+static int __init xfrm6_transport_init(void)
+{
+       return xfrm_register_mode(&xfrm6_transport_mode, AF_INET6);
+}
+
+static void __exit xfrm6_transport_exit(void)
+{
+       int err;
+
+       err = xfrm_unregister_mode(&xfrm6_transport_mode, AF_INET6);
+       BUG_ON(err);
+}
+
+module_init(xfrm6_transport_init);
+module_exit(xfrm6_transport_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
new file mode 100644 (file)
index 0000000..8af79be
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * xfrm6_mode_tunnel.c - Tunnel mode encapsulation for IPv6.
+ *
+ * Copyright (C) 2002 USAGI/WIDE Project
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dsfield.h>
+#include <net/dst.h>
+#include <net/inet_ecn.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+
+static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
+{
+       struct ipv6hdr *outer_iph = skb->nh.ipv6h;
+       struct ipv6hdr *inner_iph = skb->h.ipv6h;
+
+       if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
+               IP6_ECN_set_ce(inner_iph);
+}
+
+/* Add encapsulation header.
+ *
+ * The top IP header will be constructed per RFC 2401.  The following fields
+ * in it shall be filled in by x->type->output:
+ *     payload_len
+ *
+ * On exit, skb->h will be set to the start of the encapsulation header to be
+ * filled in by x->type->output and skb->nh will be set to the nextheader field
+ * of the extension header directly preceding the encapsulation header, or in
+ * its absence, that of the top IP header.  The value of skb->data will always
+ * point to the top IP header.
+ */
+static int xfrm6_tunnel_output(struct sk_buff *skb)
+{
+       struct dst_entry *dst = skb->dst;
+       struct xfrm_state *x = dst->xfrm;
+       struct ipv6hdr *iph, *top_iph;
+       int dsfield;
+
+       skb_push(skb, x->props.header_len);
+       iph = skb->nh.ipv6h;
+
+       skb->nh.raw = skb->data;
+       top_iph = skb->nh.ipv6h;
+       skb->nh.raw = &top_iph->nexthdr;
+       skb->h.ipv6h = top_iph + 1;
+
+       top_iph->version = 6;
+       top_iph->priority = iph->priority;
+       top_iph->flow_lbl[0] = iph->flow_lbl[0];
+       top_iph->flow_lbl[1] = iph->flow_lbl[1];
+       top_iph->flow_lbl[2] = iph->flow_lbl[2];
+       dsfield = ipv6_get_dsfield(top_iph);
+       dsfield = INET_ECN_encapsulate(dsfield, dsfield);
+       if (x->props.flags & XFRM_STATE_NOECN)
+               dsfield &= ~INET_ECN_MASK;
+       ipv6_change_dsfield(top_iph, 0, dsfield);
+       top_iph->nexthdr = IPPROTO_IPV6; 
+       top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
+       ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
+       ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
+       return 0;
+}
+
+static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int err = -EINVAL;
+
+       if (skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPV6)
+               goto out;
+       if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+               goto out;
+
+       if (skb_cloned(skb) &&
+           (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+               goto out;
+
+       if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+               ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
+       if (!(x->props.flags & XFRM_STATE_NOECN))
+               ipip6_ecn_decapsulate(skb);
+       skb->mac.raw = memmove(skb->data - skb->mac_len,
+                              skb->mac.raw, skb->mac_len);
+       skb->nh.raw = skb->data;
+       err = 0;
+
+out:
+       return err;
+}
+
+static struct xfrm_mode xfrm6_tunnel_mode = {
+       .input = xfrm6_tunnel_input,
+       .output = xfrm6_tunnel_output,
+       .owner = THIS_MODULE,
+       .encap = XFRM_MODE_TUNNEL,
+};
+
+static int __init xfrm6_tunnel_init(void)
+{
+       return xfrm_register_mode(&xfrm6_tunnel_mode, AF_INET6);
+}
+
+static void __exit xfrm6_tunnel_exit(void)
+{
+       int err;
+
+       err = xfrm_unregister_mode(&xfrm6_tunnel_mode, AF_INET6);
+       BUG_ON(err);
+}
+
+module_init(xfrm6_tunnel_init);
+module_exit(xfrm6_tunnel_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TUNNEL);
index 80242172a5df260815b087bd80f6160c71615119..16e84254a252e60daeb29821acc12429fd66520b 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/icmpv6.h>
 #include <linux/netfilter_ipv6.h>
-#include <net/dsfield.h>
-#include <net/inet_ecn.h>
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-/* Add encapsulation header.
- *
- * In transport mode, the IP header and mutable extension headers will be moved
- * forward to make space for the encapsulation header.
- *
- * In tunnel mode, the top IP header will be constructed per RFC 2401.
- * The following fields in it shall be filled in by x->type->output:
- *     payload_len
- *
- * On exit, skb->h will be set to the start of the encapsulation header to be
- * filled in by x->type->output and skb->nh will be set to the nextheader field
- * of the extension header directly preceding the encapsulation header, or in
- * its absence, that of the top IP header.  The value of skb->data will always
- * point to the top IP header.
- */
-static void xfrm6_encap(struct sk_buff *skb)
-{
-       struct dst_entry *dst = skb->dst;
-       struct xfrm_state *x = dst->xfrm;
-       struct ipv6hdr *iph, *top_iph;
-       int dsfield;
-
-       skb_push(skb, x->props.header_len);
-       iph = skb->nh.ipv6h;
-
-       if (!x->props.mode) {
-               u8 *prevhdr;
-               int hdr_len;
-
-               hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
-               skb->nh.raw = prevhdr - x->props.header_len;
-               skb->h.raw = skb->data + hdr_len;
-               memmove(skb->data, iph, hdr_len);
-               return;
-       }
-
-       skb->nh.raw = skb->data;
-       top_iph = skb->nh.ipv6h;
-       skb->nh.raw = &top_iph->nexthdr;
-       skb->h.ipv6h = top_iph + 1;
-
-       top_iph->version = 6;
-       top_iph->priority = iph->priority;
-       top_iph->flow_lbl[0] = iph->flow_lbl[0];
-       top_iph->flow_lbl[1] = iph->flow_lbl[1];
-       top_iph->flow_lbl[2] = iph->flow_lbl[2];
-       dsfield = ipv6_get_dsfield(top_iph);
-       dsfield = INET_ECN_encapsulate(dsfield, dsfield);
-       if (x->props.flags & XFRM_STATE_NOECN)
-               dsfield &= ~INET_ECN_MASK;
-       ipv6_change_dsfield(top_iph, 0, dsfield);
-       top_iph->nexthdr = IPPROTO_IPV6; 
-       top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
-       ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
-       ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
-}
-
 static int xfrm6_tunnel_check_size(struct sk_buff *skb)
 {
        int mtu, ret = 0;
@@ -118,7 +59,9 @@ static int xfrm6_output_one(struct sk_buff *skb)
                if (err)
                        goto error;
 
-               xfrm6_encap(skb);
+               err = x->mode->output(skb);
+               if (err)
+                       goto error;
 
                err = x->type->output(x, skb);
                if (err)
index 88c840f1beb678a373284799dc6f8a693fd89544..ee715f2691e9cd49018c4bb64ec27135a8c85298 100644 (file)
@@ -23,8 +23,6 @@
 static struct dst_ops xfrm6_dst_ops;
 static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
 
-static struct xfrm_type_map xfrm6_type_map = { .lock = RW_LOCK_UNLOCKED };
-
 static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
 {
        int err = 0;
@@ -249,9 +247,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl)
 
 static inline int xfrm6_garbage_collect(void)
 {
-       read_lock(&xfrm6_policy_afinfo.lock);
        xfrm6_policy_afinfo.garbage_collect();
-       read_unlock(&xfrm6_policy_afinfo.lock);
        return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2);
 }
 
@@ -311,8 +307,6 @@ static struct dst_ops xfrm6_dst_ops = {
 
 static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
        .family =               AF_INET6,
-       .lock =                 RW_LOCK_UNLOCKED,
-       .type_map =             &xfrm6_type_map,
        .dst_ops =              &xfrm6_dst_ops,
        .dst_lookup =           xfrm6_dst_lookup,
        .find_bundle =          __xfrm6_find_bundle,
index a5723024d3b372d8df6503cd05e6cfde488fc79e..b33296b3f6de5ddd25a818ba6ae306444770cfe8 100644 (file)
@@ -135,7 +135,6 @@ __xfrm6_find_acq(u8 mode, u32 reqid, u8 proto,
 
 static struct xfrm_state_afinfo xfrm6_state_afinfo = {
        .family                 = AF_INET6,
-       .lock                   = RW_LOCK_UNLOCKED,
        .init_tempsel           = __xfrm6_init_tempsel,
        .state_lookup           = __xfrm6_state_lookup,
        .find_acq               = __xfrm6_find_acq,
index a394c6fe19a26839e07dbed3f7015224d03c1161..bba3431cd9a5b5ad707a32fd534ba1e4d2af8b95 100644 (file)
@@ -238,7 +238,7 @@ int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
        }       
 
        /* Apply checksum. Not allowed on 802.3 links. */
-       if (sk->sk_no_check || intrfc->if_dlink_type == IPX_FRAME_8023)
+       if (sk->sk_no_check || intrfc->if_dlink_type == htons(IPX_FRAME_8023))
                ipx->ipx_checksum = 0xFFFF;
        else
                ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
index 7029618f5719fa6659bd096c7d7a0345b29dff70..a16528657b4c6a0a7e584df36e051cdcff6706ec 100644 (file)
@@ -884,7 +884,8 @@ static void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
        if (now) {
                /* Send down empty frame to trigger speed change */
                skb = dev_alloc_skb(0);
-               irlap_queue_xmit(self, skb);
+               if (skb)
+                       irlap_queue_xmit(self, skb);
        }
 }
 
index c19e9ce05a3a117d9a404140c735ea8a5c766d47..57ea160f470b8d433fbb2b0c2240520a0806115e 100644 (file)
@@ -44,6 +44,8 @@
 #include <net/irda/irlmp.h>
 #include <net/irda/irlmp_frame.h>
 
+#include <asm/unaligned.h>
+
 static __u8 irlmp_find_free_slsap(void);
 static int irlmp_slsap_inuse(__u8 slsap_sel);
 
@@ -840,6 +842,7 @@ void irlmp_do_expiry(void)
 void irlmp_do_discovery(int nslots)
 {
        struct lap_cb *lap;
+       __u16 *data_hintsp;
 
        /* Make sure the value is sane */
        if ((nslots != 1) && (nslots != 6) && (nslots != 8) && (nslots != 16)){
@@ -849,7 +852,8 @@ void irlmp_do_discovery(int nslots)
        }
 
        /* Construct new discovery info to be used by IrLAP, */
-       u16ho(irlmp->discovery_cmd.data.hints) = irlmp->hints.word;
+       data_hintsp = (__u16 *) irlmp->discovery_cmd.data.hints;
+       put_unaligned(irlmp->hints.word, data_hintsp);
 
        /*
         *  Set character set for device name (we use ASCII), and
index 859582275cabd42747d652c73a2e7307e393ca87..d5e2121ea20775001af804c6504377c05c8c5d69 100644 (file)
@@ -1454,21 +1454,23 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
        if (x == NULL)
                return -ESRCH;
 
+       if ((err = security_xfrm_state_delete(x)))
+               goto out;
+
        if (xfrm_state_kern(x)) {
-               xfrm_state_put(x);
-               return -EPERM;
+               err = -EPERM;
+               goto out;
        }
        
        err = xfrm_state_delete(x);
-       if (err < 0) {
-               xfrm_state_put(x);
-               return err;
-       }
+       if (err < 0)
+               goto out;
 
        c.seq = hdr->sadb_msg_seq;
        c.pid = hdr->sadb_msg_pid;
        c.event = XFRM_MSG_DELSA;
        km_state_notify(x, &c);
+out:
        xfrm_state_put(x);
 
        return err;
@@ -2274,11 +2276,14 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
 
        err = 0;
 
+       if ((err = security_xfrm_policy_delete(xp)))
+               goto out;
        c.seq = hdr->sadb_msg_seq;
        c.pid = hdr->sadb_msg_pid;
        c.event = XFRM_MSG_DELPOLICY;
        km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
 
+out:
        xfrm_pol_put(xp);
        return err;
 }
index 5a04db745c8d64394ce074cdecaa69d84ede0aa0..75c9b1480801e2a52cc81ac96fbcfe21cbcc918e 100644 (file)
@@ -674,7 +674,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        lock_sock(sk);
        copied = -ENOTCONN;
-       if (sk->sk_state == TCP_LISTEN)
+       if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
                goto out;
 
        timeo = sock_rcvtimeo(sk, nonblock);
@@ -733,7 +733,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                        if (sk->sk_shutdown & RCV_SHUTDOWN)
                                break;
 
-                       if (sk->sk_state == TCP_CLOSE) {
+                       if (sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_CLOSE) {
                                if (!sock_flag(sk, SOCK_DONE)) {
                                        /*
                                         * This occurs when user tries to read
@@ -789,7 +789,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
                        continue;
 
                if (!(flags & MSG_PEEK)) {
-                       sk_eat_skb(sk, skb);
+                       sk_eat_skb(sk, skb, 0);
                        *seq = 0;
                }
        } while (len > 0);
index ba90f7f0801ad5fbe9006a3da96234a71b6b7042..5ae47be7dde0def38ae98d29a0805dd8f231373d 100644 (file)
@@ -26,8 +26,6 @@
 #include <net/llc_c_st.h>
 #include <net/tcp_states.h>
 
-u8 llc_mac_null_var[IFHWADDRLEN];
-
 /**
  *     llc_build_and_send_pkt - Connection data sending for upper layers.
  *     @sk: connection
index d62e0f9b9da3edca21a8292bc321764aa1866187..94d2368ade92c6368eec7121e26b2dbea4e04a65 100644 (file)
@@ -142,6 +142,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
        struct llc_sap *sap;
        struct llc_pdu_sn *pdu;
        int dest;
+       int (*rcv)(struct sk_buff *, struct net_device *,
+                  struct packet_type *, struct net_device *);
 
        /*
         * When the interface is in promisc. mode, drop all the crap that it
@@ -169,9 +171,11 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
         * First the upper layer protocols that don't need the full
         * LLC functionality
         */
-       if (sap->rcv_func) {
-               sap->rcv_func(skb, dev, pt, orig_dev);
-               goto out_put;
+       rcv = rcu_dereference(sap->rcv_func);
+       if (rcv) {
+               struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
+               if (cskb)
+                       rcv(cskb, dev, pt, orig_dev);
        }
        dest = llc_pdu_type(skb);
        if (unlikely(!dest || !llc_type_handlers[dest - 1]))
index 4029ceee9b9168d2f7b09e1eb1d64316f8544234..20c4eb5c1ac6829f425382d87cb1d3d52052865b 100644 (file)
@@ -282,7 +282,7 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb)
  *     mac, and local sap. Returns pointer for socket found, %NULL otherwise.
  */
 static struct sock *llc_lookup_dgram(struct llc_sap *sap,
-                                    struct llc_addr *laddr)
+                                    const struct llc_addr *laddr)
 {
        struct sock *rc;
        struct hlist_node *node;
@@ -304,19 +304,62 @@ found:
        return rc;
 }
 
+/**
+ *     llc_sap_mcast - Deliver multicast PDU's to all matching datagram sockets.
+ *     @sap: SAP
+ *     @laddr: address of local LLC (MAC + SAP)
+ *
+ *     Search socket list of the SAP and finds connections with same sap.
+ *     Deliver clone to each.
+ */
+static void llc_sap_mcast(struct llc_sap *sap,
+                         const struct llc_addr *laddr,
+                         struct sk_buff *skb)
+{
+       struct sock *sk;
+       struct hlist_node *node;
+
+       read_lock_bh(&sap->sk_list.lock);
+       sk_for_each(sk, node, &sap->sk_list.list) {
+               struct llc_sock *llc = llc_sk(sk);
+               struct sk_buff *skb1;
+
+               if (sk->sk_type != SOCK_DGRAM)
+                       continue;
+
+               if (llc->laddr.lsap != laddr->lsap)
+                       continue;
+
+               skb1 = skb_clone(skb, GFP_ATOMIC);
+               if (!skb1)
+                       break;
+
+               sock_hold(sk);
+               skb_set_owner_r(skb1, sk);
+               llc_sap_rcv(sap, skb1);
+               sock_put(sk);
+       }
+       read_unlock_bh(&sap->sk_list.lock);
+}
+
+
 void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
 {
        struct llc_addr laddr;
-       struct sock *sk;
 
        llc_pdu_decode_da(skb, laddr.mac);
        llc_pdu_decode_dsap(skb, &laddr.lsap);
 
-       sk = llc_lookup_dgram(sap, &laddr);
-       if (sk) {
-               skb_set_owner_r(skb, sk);
-               llc_sap_rcv(sap, skb);
-               sock_put(sk);
-       } else
+       if (llc_mac_multicast(laddr.mac)) {
+               llc_sap_mcast(sap, &laddr, skb);
                kfree_skb(skb);
+       } else {
+               struct sock *sk = llc_lookup_dgram(sap, &laddr);
+               if (sk) {
+                       skb_set_owner_r(skb, sk);
+                       llc_sap_rcv(sap, skb);
+                       sock_put(sk);
+               } else
+                       kfree_skb(skb);
+       }
 }
index e2893effdfaae040cf514d79a958847aaa170339..b1622b7de1cfb0a6f3b4c0cf496622321b668cd6 100644 (file)
@@ -60,6 +60,18 @@ config NF_CONNTRACK_MARK
          of packets, but this mark value is kept in the conntrack session
          instead of the individual packets.
 
+config NF_CONNTRACK_SECMARK
+       bool  'Connection tracking security mark support'
+       depends on NF_CONNTRACK && NETWORK_SECMARK
+       help
+         This option enables security markings to be applied to
+         connections.  Typically they are copied to connections from
+         packets using the CONNSECMARK target and copied back from
+         connections to packets with the same target, with the packets
+         being originally labeled via SECMARK.
+
+         If unsure, say 'N'.
+
 config NF_CONNTRACK_EVENTS
        bool "Connection tracking events (EXPERIMENTAL)"
        depends on EXPERIMENTAL && NF_CONNTRACK
@@ -174,6 +186,26 @@ config NETFILTER_XT_TARGET_NOTRACK
          If you want to compile it as a module, say M here and read
          <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_TARGET_SECMARK
+       tristate '"SECMARK" target support'
+       depends on NETFILTER_XTABLES && NETWORK_SECMARK
+       help
+         The SECMARK target allows security marking of network
+         packets, for use with security subsystems.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
+config NETFILTER_XT_TARGET_CONNSECMARK
+       tristate '"CONNSECMARK" target support'
+       depends on NETFILTER_XTABLES && (NF_CONNTRACK_SECMARK || IP_NF_CONNTRACK_SECMARK)
+       help
+         The CONNSECMARK target copies security markings from packets
+         to connections, and restores security markings from connections
+         to packets (if the packets are not already marked).  This would
+         normally be used in conjunction with the SECMARK target.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_COMMENT
        tristate  '"comment" match support'
        depends on NETFILTER_XTABLES
@@ -329,6 +361,16 @@ config NETFILTER_XT_MATCH_PKTTYPE
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_QUOTA
+       tristate '"quota" match support'
+       depends on NETFILTER_XTABLES
+       help
+         This option adds a `quota' match, which allows to match on a
+         byte counter.
+
+         If you want to compile it as a module, say M here and read
+         <file:Documentation/modules.txt>.  If unsure, say `N'.
+
 config NETFILTER_XT_MATCH_REALM
        tristate  '"realm" match support'
        depends on NETFILTER_XTABLES
@@ -365,6 +407,12 @@ config NETFILTER_XT_MATCH_STATE
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_STATISTIC
+       tristate '"statistic" match support'
+       depends on NETFILTER_XTABLES
+       help
+         statistic module
+
 config NETFILTER_XT_MATCH_STRING
        tristate  '"string" match support'
        depends on NETFILTER_XTABLES
index 95b7e416512dbc56b8d5e16f51db57756c3bc21a..6fa4b75804586330017661850d2a9d99962f5b1a 100644 (file)
@@ -28,6 +28,8 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
 
 # matches
 obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
@@ -44,9 +46,11 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
index f9b83f91371ac27ac2c127fea81ed0bbc6e4f0c5..cd299f4b7db1989c5e5d1897698d987c370db48a 100644 (file)
@@ -989,6 +989,9 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
                conntrack->master = exp->master;
 #ifdef CONFIG_NF_CONNTRACK_MARK
                conntrack->mark = exp->master->mark;
+#endif
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+               conntrack->secmark = exp->master->secmark;
 #endif
                nf_conntrack_get(&conntrack->master->ct_general);
                NF_CT_STAT_INC(expect_new);
@@ -1396,6 +1399,12 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
 
        write_lock_bh(&nf_conntrack_lock);
 
+       /* Only update if this is not a fixed timeout */
+       if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) {
+               write_unlock_bh(&nf_conntrack_lock);
+               return;
+       }
+
        /* If not in hash table, timer will not be active yet */
        if (!nf_ct_is_confirmed(ct)) {
                ct->timeout.expires = extra_jiffies;
index e38a4b5a3089004288da71fffba41bdc96bd5c60..11d3be2435364ca09063026e09becee25c7b1939 100644 (file)
@@ -67,37 +67,48 @@ static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
                             char);
 
 static struct ftp_search {
-       enum ip_conntrack_dir dir;
        const char *pattern;
        size_t plen;
        char skip;
        char term;
        enum ip_ct_ftp_type ftptype;
        int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char);
-} search[] = {
-       {
-               IP_CT_DIR_ORIGINAL,
-               "PORT", sizeof("PORT") - 1, ' ', '\r',
-               IP_CT_FTP_PORT,
-               try_rfc959,
+} search[IP_CT_DIR_MAX][2] = {
+       [IP_CT_DIR_ORIGINAL] = {
+               {
+                       .pattern        = "PORT",
+                       .plen           = sizeof("PORT") - 1,
+                       .skip           = ' ',
+                       .term           = '\r',
+                       .ftptype        = IP_CT_FTP_PORT,
+                       .getnum         = try_rfc959,
+               },
+               {
+                       .pattern        = "EPRT",
+                       .plen           = sizeof("EPRT") - 1,
+                       .skip           = ' ',
+                       .term           = '\r',
+                       .ftptype        = IP_CT_FTP_EPRT,
+                       .getnum         = try_eprt,
+               },
        },
-       {
-               IP_CT_DIR_REPLY,
-               "227 ", sizeof("227 ") - 1, '(', ')',
-               IP_CT_FTP_PASV,
-               try_rfc959,
-       },
-       {
-               IP_CT_DIR_ORIGINAL,
-               "EPRT", sizeof("EPRT") - 1, ' ', '\r',
-               IP_CT_FTP_EPRT,
-               try_eprt,
-       },
-       {
-               IP_CT_DIR_REPLY,
-               "229 ", sizeof("229 ") - 1, '(', ')',
-               IP_CT_FTP_EPSV,
-               try_epsv_response,
+       [IP_CT_DIR_REPLY] = {
+               {
+                       .pattern        = "227 ",
+                       .plen           = sizeof("227 ") - 1,
+                       .skip           = '(',
+                       .term           = ')',
+                       .ftptype        = IP_CT_FTP_PASV,
+                       .getnum         = try_rfc959,
+               },
+               {
+                       .pattern        = "229 ",
+                       .plen           = sizeof("229 ") - 1,
+                       .skip           = '(',
+                       .term           = ')',
+                       .ftptype        = IP_CT_FTP_EPSV,
+                       .getnum         = try_epsv_response,
+               },
        },
 };
 
@@ -492,17 +503,15 @@ static int help(struct sk_buff **pskb,
        memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
               sizeof(cmd.u3.all));
 
-       for (i = 0; i < ARRAY_SIZE(search); i++) {
-               if (search[i].dir != dir) continue;
-
+       for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
                found = find_pattern(fb_ptr, datalen,
-                                    search[i].pattern,
-                                    search[i].plen,
-                                    search[i].skip,
-                                    search[i].term,
+                                    search[dir][i].pattern,
+                                    search[dir][i].plen,
+                                    search[dir][i].skip,
+                                    search[dir][i].term,
                                     &matchoff, &matchlen,
                                     &cmd,
-                                    search[i].getnum);
+                                    search[dir][i].getnum);
                if (found) break;
        }
        if (found == -1) {
@@ -512,7 +521,7 @@ static int help(struct sk_buff **pskb,
                   this case. */
                if (net_ratelimit())
                        printk("conntrack_ftp: partial %s %u+%u\n",
-                              search[i].pattern,
+                              search[dir][i].pattern,
                               ntohl(th->seq), datalen);
                ret = NF_DROP;
                goto out;
@@ -597,7 +606,7 @@ static int help(struct sk_buff **pskb,
        /* Now, NAT might want to mangle the packet, and register the
         * (possibly changed) expectation itself. */
        if (nf_nat_ftp_hook)
-               ret = nf_nat_ftp_hook(pskb, ctinfo, search[i].ftptype,
+               ret = nf_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
                                      matchoff, matchlen, exp, &seq);
        else {
                /* Can't expect this?  Best to drop packet now. */
index bd10eb944b656aa5f91b807eee4a96a5c92fbf3e..b8c7c567c9df5a0c3a27e6cbf01680854a7b8914 100644 (file)
@@ -407,6 +407,8 @@ nfattr_failure:
 
 static int ctnetlink_done(struct netlink_callback *cb)
 {
+       if (cb->args[1])
+               nf_ct_put((struct nf_conn *)cb->args[1]);
        DEBUGP("entered %s\n", __FUNCTION__);
        return 0;
 }
@@ -416,10 +418,9 @@ static int ctnetlink_done(struct netlink_callback *cb)
 static int
 ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
-       struct nf_conn *ct = NULL;
+       struct nf_conn *ct, *last;
        struct nf_conntrack_tuple_hash *h;
        struct list_head *i;
-       u_int32_t *id = (u_int32_t *) &cb->args[1];
        struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
        u_int8_t l3proto = nfmsg->nfgen_family;
 
@@ -427,7 +428,9 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
                        cb->args[0], *id);
 
        read_lock_bh(&nf_conntrack_lock);
-       for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++, *id = 0) {
+       for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
+restart:
+               last = (struct nf_conn *)cb->args[1];
                list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
                        h = (struct nf_conntrack_tuple_hash *) i;
                        if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
@@ -438,17 +441,30 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
                         * then dump everything. */
                        if (l3proto && L3PROTO(ct) != l3proto)
                                continue;
-                       if (ct->id <= *id)
-                               continue;
+                       if (last != NULL) {
+                               if (ct == last) {
+                                       nf_ct_put(last);
+                                       cb->args[1] = 0;
+                                       last = NULL;
+                               } else
+                                       continue;
+                       }
                        if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
                                                cb->nlh->nlmsg_seq,
                                                IPCTNL_MSG_CT_NEW,
-                                               1, ct) < 0)
+                                               1, ct) < 0) {
+                               nf_conntrack_get(&ct->ct_general);
+                               cb->args[1] = (unsigned long)ct;
                                goto out;
-                       *id = ct->id;
+                       }
+               }
+               if (last != NULL) {
+                       nf_ct_put(last);
+                       cb->args[1] = 0;
+                       goto restart;
                }
        }
-out:   
+out:
        read_unlock_bh(&nf_conntrack_lock);
 
        DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
@@ -641,7 +657,7 @@ static const size_t cta_min_nat[CTA_NAT_MAX] = {
 };
 
 static inline int
-ctnetlink_parse_nat(struct nfattr *cda[],
+ctnetlink_parse_nat(struct nfattr *nat,
                    const struct nf_conn *ct, struct ip_nat_range *range)
 {
        struct nfattr *tb[CTA_NAT_MAX];
@@ -651,7 +667,7 @@ ctnetlink_parse_nat(struct nfattr *cda[],
 
        memset(range, 0, sizeof(*range));
        
-       nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]);
+       nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
 
        if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
                return -EINVAL;
@@ -866,39 +882,30 @@ ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
                /* ASSURED bit can only be set */
                return -EINVAL;
 
-       if (cda[CTA_NAT-1]) {
+       if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
 #ifndef CONFIG_IP_NF_NAT_NEEDED
                return -EINVAL;
 #else
-               unsigned int hooknum;
                struct ip_nat_range range;
 
-               if (ctnetlink_parse_nat(cda, ct, &range) < 0)
-                       return -EINVAL;
-
-               DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n", 
-                      NIPQUAD(range.min_ip), NIPQUAD(range.max_ip),
-                      htons(range.min.all), htons(range.max.all));
-               
-               /* This is tricky but it works. ip_nat_setup_info needs the
-                * hook number as parameter, so let's do the correct 
-                * conversion and run away */
-               if (status & IPS_SRC_NAT_DONE)
-                       hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */
-               else if (status & IPS_DST_NAT_DONE)
-                       hooknum = NF_IP_PRE_ROUTING;  /* IP_NAT_MANIP_DST */
-               else 
-                       return -EINVAL; /* Missing NAT flags */
-
-               DEBUGP("NAT status: %lu\n", 
-                      status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
-               
-               if (ip_nat_initialized(ct, HOOK2MANIP(hooknum)))
-                       return -EEXIST;
-               ip_nat_setup_info(ct, &range, hooknum);
-
-                DEBUGP("NAT status after setup_info: %lu\n",
-                       ct->status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
+               if (cda[CTA_NAT_DST-1]) {
+                       if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
+                                               &range) < 0)
+                               return -EINVAL;
+                       if (ip_nat_initialized(ct,
+                                              HOOK2MANIP(NF_IP_PRE_ROUTING)))
+                               return -EEXIST;
+                       ip_nat_setup_info(ct, &range, hooknum);
+               }
+               if (cda[CTA_NAT_SRC-1]) {
+                       if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
+                                               &range) < 0)
+                               return -EINVAL;
+                       if (ip_nat_initialized(ct,
+                                              HOOK2MANIP(NF_IP_POST_ROUTING)))
+                               return -EEXIST;
+                       ip_nat_setup_info(ct, &range, hooknum);
+               }
 #endif
        }
 
@@ -1122,7 +1129,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
        /* implicit 'else' */
 
        /* we only allow nat config for new conntracks */
-       if (cda[CTA_NAT-1]) {
+       if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
                err = -EINVAL;
                goto out_unlock;
        }
index 69899f27d26aad61b8eb09d5fd6d7a4118b0c10f..12fb7c0a15098e9050e1779f41f2acd1939a086d 100644 (file)
@@ -828,8 +828,9 @@ static int tcp_error(struct sk_buff *skb,
         * and moreover root might send raw packets.
         */
        /* FIXME: Source route IP option packets --RR */
-       if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
-            (pf == PF_INET6 && hooknum  == NF_IP6_PRE_ROUTING)) &&
+       if (nf_conntrack_checksum &&
+           ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
+            (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
            nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
                if (LOG_INVALID(IPPROTO_TCP))
                        nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
index d93edbfde9e30a27c111fa0a540d4f82374f368b..ae07ebe3ab3754cd85099715d46c118aeaf5b122 100644 (file)
@@ -134,7 +134,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff,
         * because the semantic of CHECKSUM_HW is different there
         * and moreover root might send raw packets.
         * FIXME: Source route IP option packets --RR */
-       if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
+       if (nf_conntrack_checksum &&
+           ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
             (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
            nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
                if (LOG_INVALID(IPPROTO_UDP))
index 408960c6a544489b2d269ed7a4809895b43fe440..e34c574f035133b509a402d4880a2b1f5bf035a8 100644 (file)
@@ -213,6 +213,11 @@ static int ct_seq_show(struct seq_file *s, void *v)
                return -ENOSPC;
 #endif
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+       if (seq_printf(s, "secmark=%u ", conntrack->secmark))
+               return -ENOSPC;
+#endif
+
        if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
                return -ENOSPC;
        
@@ -455,6 +460,8 @@ extern unsigned int nf_ct_generic_timeout;
 static int log_invalid_proto_min = 0;
 static int log_invalid_proto_max = 255;
 
+int nf_conntrack_checksum = 1;
+
 static struct ctl_table_header *nf_ct_sysctl_header;
 
 static ctl_table nf_ct_sysctl_table[] = {
@@ -482,6 +489,14 @@ static ctl_table nf_ct_sysctl_table[] = {
                .mode           = 0444,
                .proc_handler   = &proc_dointvec,
        },
+       {
+               .ctl_name       = NET_NF_CONNTRACK_CHECKSUM,
+               .procname       = "nf_conntrack_checksum",
+               .data           = &nf_conntrack_checksum,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
        {
                .ctl_name       = NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
                .procname       = "nf_conntrack_tcp_timeout_syn_sent",
@@ -851,6 +866,7 @@ EXPORT_SYMBOL(nf_ct_proto_put);
 EXPORT_SYMBOL(nf_ct_l3proto_find_get);
 EXPORT_SYMBOL(nf_ct_l3proto_put);
 EXPORT_SYMBOL(nf_ct_l3protos);
+EXPORT_SYMBOL_GPL(nf_conntrack_checksum);
 EXPORT_SYMBOL(nf_conntrack_expect_alloc);
 EXPORT_SYMBOL(nf_conntrack_expect_put);
 EXPORT_SYMBOL(nf_conntrack_expect_related);
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
new file mode 100644 (file)
index 0000000..8c011e0
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * This module is used to copy security markings from packets
+ * to connections, and restore security markings from connections
+ * back to packets.  This would normally be performed in conjunction
+ * with the SECMARK target and state match.
+ *
+ * Based somewhat on CONNMARK:
+ *   Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ *    by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_CONNSECMARK.h>
+#include <net/netfilter/nf_conntrack_compat.h>
+
+#define PFX "CONNSECMARK: "
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
+MODULE_DESCRIPTION("ip[6]tables CONNSECMARK module");
+MODULE_ALIAS("ipt_CONNSECMARK");
+MODULE_ALIAS("ip6t_CONNSECMARK");
+
+/*
+ * If the packet has a security mark and the connection does not, copy
+ * the security mark from the packet to the connection.
+ */
+static void secmark_save(struct sk_buff *skb)
+{
+       if (skb->secmark) {
+               u32 *connsecmark;
+               enum ip_conntrack_info ctinfo;
+
+               connsecmark = nf_ct_get_secmark(skb, &ctinfo);
+               if (connsecmark && !*connsecmark)
+                       if (*connsecmark != skb->secmark)
+                               *connsecmark = skb->secmark;
+       }
+}
+
+/*
+ * If packet has no security mark, and the connection does, restore the
+ * security mark from the connection to the packet.
+ */
+static void secmark_restore(struct sk_buff *skb)
+{
+       if (!skb->secmark) {
+               u32 *connsecmark;
+               enum ip_conntrack_info ctinfo;
+
+               connsecmark = nf_ct_get_secmark(skb, &ctinfo);
+               if (connsecmark && *connsecmark)
+                       if (skb->secmark != *connsecmark)
+                               skb->secmark = *connsecmark;
+       }
+}
+
+static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
+                          const struct net_device *out, unsigned int hooknum,
+                          const struct xt_target *target,
+                          const void *targinfo, void *userinfo)
+{
+       struct sk_buff *skb = *pskb;
+       const struct xt_connsecmark_target_info *info = targinfo;
+
+       switch (info->mode) {
+       case CONNSECMARK_SAVE:
+               secmark_save(skb);
+               break;
+
+       case CONNSECMARK_RESTORE:
+               secmark_restore(skb);
+               break;
+
+       default:
+               BUG();
+       }
+
+       return XT_CONTINUE;
+}
+
+static int checkentry(const char *tablename, const void *entry,
+                     const struct xt_target *target, void *targinfo,
+                     unsigned int targinfosize, unsigned int hook_mask)
+{
+       struct xt_connsecmark_target_info *info = targinfo;
+
+       switch (info->mode) {
+       case CONNSECMARK_SAVE:
+       case CONNSECMARK_RESTORE:
+               break;
+
+       default:
+               printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
+               return 0;
+       }
+
+       return 1;
+}
+
+static struct xt_target ipt_connsecmark_reg = {
+       .name           = "CONNSECMARK",
+       .target         = target,
+       .targetsize     = sizeof(struct xt_connsecmark_target_info),
+       .table          = "mangle",
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE,
+       .family         = AF_INET,
+       .revision       = 0,
+};
+
+static struct xt_target ip6t_connsecmark_reg = {
+       .name           = "CONNSECMARK",
+       .target         = target,
+       .targetsize     = sizeof(struct xt_connsecmark_target_info),
+       .table          = "mangle",
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE,
+       .family         = AF_INET6,
+       .revision       = 0,
+};
+
+static int __init xt_connsecmark_init(void)
+{
+       int err;
+
+       need_conntrack();
+
+       err = xt_register_target(&ipt_connsecmark_reg);
+       if (err)
+               return err;
+
+       err = xt_register_target(&ip6t_connsecmark_reg);
+       if (err)
+               xt_unregister_target(&ipt_connsecmark_reg);
+
+       return err;
+}
+
+static void __exit xt_connsecmark_fini(void)
+{
+       xt_unregister_target(&ip6t_connsecmark_reg);
+       xt_unregister_target(&ipt_connsecmark_reg);
+}
+
+module_init(xt_connsecmark_init);
+module_exit(xt_connsecmark_fini);
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
new file mode 100644 (file)
index 0000000..c2ce9c4
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Module for modifying the secmark field of the skb, for use by
+ * security subsystems.
+ *
+ * Based on the nfmark match by:
+ * (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
+ *
+ * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/selinux.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_SECMARK.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
+MODULE_DESCRIPTION("ip[6]tables SECMARK modification module");
+MODULE_ALIAS("ipt_SECMARK");
+MODULE_ALIAS("ip6t_SECMARK");
+
+#define PFX "SECMARK: "
+
+static u8 mode;
+
+static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
+                          const struct net_device *out, unsigned int hooknum,
+                          const struct xt_target *target,
+                          const void *targinfo, void *userinfo)
+{
+       u32 secmark = 0;
+       const struct xt_secmark_target_info *info = targinfo;
+
+       BUG_ON(info->mode != mode);
+
+       switch (mode) {
+       case SECMARK_MODE_SEL:
+               secmark = info->u.sel.selsid;
+               break;
+
+       default:
+               BUG();
+       }
+
+       if ((*pskb)->secmark != secmark)
+               (*pskb)->secmark = secmark;
+
+       return XT_CONTINUE;
+}
+
+static int checkentry_selinux(struct xt_secmark_target_info *info)
+{
+       int err;
+       struct xt_secmark_target_selinux_info *sel = &info->u.sel;
+
+       err = selinux_string_to_sid(sel->selctx, &sel->selsid);
+       if (err) {
+               if (err == -EINVAL)
+                       printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n",
+                              sel->selctx);
+               return 0;
+       }
+
+       if (!sel->selsid) {
+               printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n",
+                      sel->selctx);
+               return 0;
+       }
+
+       err = selinux_relabel_packet_permission(sel->selsid);
+       if (err) {
+               printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
+               return 0;
+       }
+
+       return 1;
+}
+
+static int checkentry(const char *tablename, const void *entry,
+                     const struct xt_target *target, void *targinfo,
+                     unsigned int targinfosize, unsigned int hook_mask)
+{
+       struct xt_secmark_target_info *info = targinfo;
+
+       if (mode && mode != info->mode) {
+               printk(KERN_INFO PFX "mode already set to %hu cannot mix with "
+                      "rules for mode %hu\n", mode, info->mode);
+               return 0;
+       }
+
+       switch (info->mode) {
+       case SECMARK_MODE_SEL:
+               if (!checkentry_selinux(info))
+                       return 0;
+               break;
+
+       default:
+               printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
+               return 0;
+       }
+
+       if (!mode)
+               mode = info->mode;
+       return 1;
+}
+
+static struct xt_target ipt_secmark_reg = {
+       .name           = "SECMARK",
+       .target         = target,
+       .targetsize     = sizeof(struct xt_secmark_target_info),
+       .table          = "mangle",
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE,
+       .family         = AF_INET,
+       .revision       = 0,
+};
+
+static struct xt_target ip6t_secmark_reg = {
+       .name           = "SECMARK",
+       .target         = target,
+       .targetsize     = sizeof(struct xt_secmark_target_info),
+       .table          = "mangle",
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE,
+       .family         = AF_INET6,
+       .revision       = 0,
+};
+
+static int __init xt_secmark_init(void)
+{
+       int err;
+
+       err = xt_register_target(&ipt_secmark_reg);
+       if (err)
+               return err;
+
+       err = xt_register_target(&ip6t_secmark_reg);
+       if (err)
+               xt_unregister_target(&ipt_secmark_reg);
+
+       return err;
+}
+
+static void __exit xt_secmark_fini(void)
+{
+       xt_unregister_target(&ip6t_secmark_reg);
+       xt_unregister_target(&ipt_secmark_reg);
+}
+
+module_init(xt_secmark_init);
+module_exit(xt_secmark_fini);
index dc26a27cbcafc2df58bad0ca5687a71d0aa29edf..56324c8aff0a76c9507fc4133dd5ad194d360bfb 100644 (file)
@@ -58,7 +58,7 @@ checkentry(const char *tablename,
           unsigned int matchsize,
           unsigned int hook_mask)
 {
-       struct xt_connmark_info *cm = (struct xt_connmark_info *)matchinfo;
+       struct xt_connmark_info *cm = matchinfo;
 
        if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
                printk(KERN_WARNING "connmark: only support 32bit mark\n");
index dfb10b648e570c0fce716bdae0644349f66357b9..2e2f825dad4c35744d0121aafbe1e74e7bd362c5 100644 (file)
@@ -101,8 +101,7 @@ match(const struct sk_buff *skb,
       unsigned int protoff,
       int *hotdrop)
 {
-       const struct xt_dccp_info *info = 
-                               (const struct xt_dccp_info *)matchinfo;
+       const struct xt_dccp_info *info = matchinfo;
        struct dccp_hdr _dh, *dh;
 
        if (offset)
index 8b385a34886de4fdbf9c324377dc1348a20e815c..876bc57977381bc62ffd6c11c077cd3570428e1f 100644 (file)
@@ -42,7 +42,7 @@ checkentry(const char *tablename,
            unsigned int matchsize,
            unsigned int hook_mask)
 {
-       struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo;
+       const struct xt_mark_info *minfo = matchinfo;
 
        if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
                printk(KERN_WARNING "mark: only supports 32bit mark\n");
index b56cd2baaac22aaf9f7df6622da957201a70f573..1ff0a25396e75251844da5aae739b4062323c88e 100644 (file)
@@ -1,4 +1,4 @@
-/* Kernel module to match one of a list of TCP/UDP ports: ports are in
+/* Kernel module to match one of a list of TCP/UDP/SCTP/DCCP ports: ports are in
    the same place so we can treat them as equal. */
 
 /* (C) 1999-2001 Paul `Rusty' Russell
@@ -160,8 +160,9 @@ check(u_int16_t proto,
       u_int8_t match_flags,
       u_int8_t count)
 {
-       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
-       return (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
+       /* Must specify supported protocol, no unknown flags or bad count */
+       return (proto == IPPROTO_TCP || proto == IPPROTO_UDP
+               || proto == IPPROTO_SCTP || proto == IPPROTO_DCCP)
                && !(ip_invflags & XT_INV_PROTO)
                && (match_flags == XT_MULTIPORT_SOURCE
                    || match_flags == XT_MULTIPORT_DESTINATION
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
new file mode 100644 (file)
index 0000000..4cdba74
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * netfilter module to enforce network quotas
+ *
+ * Sam Johnston <samj@samj.net>
+ */
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_quota.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
+
+static DEFINE_SPINLOCK(quota_lock);
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in, const struct net_device *out,
+      const struct xt_match *match, const void *matchinfo,
+      int offset, unsigned int protoff, int *hotdrop)
+{
+       struct xt_quota_info *q = ((struct xt_quota_info *)matchinfo)->master;
+       int ret = q->flags & XT_QUOTA_INVERT ? 1 : 0;
+
+       spin_lock_bh(&quota_lock);
+       if (q->quota >= skb->len) {
+               q->quota -= skb->len;
+               ret ^= 1;
+       } else {
+               /* we do not allow even small packets from now on */
+               q->quota = 0;
+       }
+       spin_unlock_bh(&quota_lock);
+
+       return ret;
+}
+
+static int
+checkentry(const char *tablename, const void *entry,
+          const struct xt_match *match, void *matchinfo,
+          unsigned int matchsize, unsigned int hook_mask)
+{
+       struct xt_quota_info *q = (struct xt_quota_info *)matchinfo;
+
+       if (q->flags & ~XT_QUOTA_MASK)
+               return 0;
+       /* For SMP, we only want to use one set of counters. */
+       q->master = q;
+       return 1;
+}
+
+static struct xt_match quota_match = {
+       .name           = "quota",
+       .family         = AF_INET,
+       .match          = match,
+       .matchsize      = sizeof(struct xt_quota_info),
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE
+};
+
+static struct xt_match quota_match6 = {
+       .name           = "quota",
+       .family         = AF_INET6,
+       .match          = match,
+       .matchsize      = sizeof(struct xt_quota_info),
+       .checkentry     = checkentry,
+       .me             = THIS_MODULE
+};
+
+static int __init xt_quota_init(void)
+{
+       int ret;
+
+       ret = xt_register_match(&quota_match);
+       if (ret)
+               goto err1;
+       ret = xt_register_match(&quota_match6);
+       if (ret)
+               goto err2;
+       return ret;
+
+err2:
+       xt_unregister_match(&quota_match);
+err1:
+       return ret;
+}
+
+static void __exit xt_quota_fini(void)
+{
+       xt_unregister_match(&quota_match6);
+       xt_unregister_match(&quota_match);
+}
+
+module_init(xt_quota_init);
+module_exit(xt_quota_fini);
index 34bd87259a09fea8b84671104c6a314cad5aafbd..b5110e5b54b046989fb3d7fa1abb3b5d437419b9 100644 (file)
@@ -129,11 +129,9 @@ match(const struct sk_buff *skb,
       unsigned int protoff,
       int *hotdrop)
 {
-       const struct xt_sctp_info *info;
+       const struct xt_sctp_info *info = matchinfo;
        sctp_sctphdr_t _sh, *sh;
 
-       info = (const struct xt_sctp_info *)matchinfo;
-
        if (offset) {
                duprintf("Dropping non-first fragment.. FIXME\n");
                return 0;
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
new file mode 100644 (file)
index 0000000..de1037f
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on ipt_random and ipt_nth by Fabrice MARIE <fabrice@netfilter.org>.
+ */
+
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/net.h>
+
+#include <linux/netfilter/xt_statistic.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("xtables statistical match module");
+MODULE_ALIAS("ipt_statistic");
+MODULE_ALIAS("ip6t_statistic");
+
+static DEFINE_SPINLOCK(nth_lock);
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in, const struct net_device *out,
+      const struct xt_match *match, const void *matchinfo,
+      int offset, unsigned int protoff, int *hotdrop)
+{
+       struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
+       int ret = info->flags & XT_STATISTIC_INVERT ? 1 : 0;
+
+       switch (info->mode) {
+       case XT_STATISTIC_MODE_RANDOM:
+               if ((net_random() & 0x7FFFFFFF) < info->u.random.probability)
+                       ret ^= 1;
+               break;
+       case XT_STATISTIC_MODE_NTH:
+               info = info->master;
+               spin_lock_bh(&nth_lock);
+               if (info->u.nth.count++ == info->u.nth.every) {
+                       info->u.nth.count = 0;
+                       ret ^= 1;
+               }
+               spin_unlock_bh(&nth_lock);
+               break;
+       }
+
+       return ret;
+}
+
+static int
+checkentry(const char *tablename, const void *entry,
+          const struct xt_match *match, void *matchinfo,
+          unsigned int matchsize, unsigned int hook_mask)
+{
+       struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
+
+       if (info->mode > XT_STATISTIC_MODE_MAX ||
+           info->flags & ~XT_STATISTIC_MASK)
+               return 0;
+       info->master = info;
+       return 1;
+}
+
+static struct xt_match statistic_match = {
+       .name           = "statistic",
+       .match          = match,
+       .matchsize      = sizeof(struct xt_statistic_info),
+       .checkentry     = checkentry,
+       .family         = AF_INET,
+       .me             = THIS_MODULE,
+};
+
+static struct xt_match statistic_match6 = {
+       .name           = "statistic",
+       .match          = match,
+       .matchsize      = sizeof(struct xt_statistic_info),
+       .checkentry     = checkentry,
+       .family         = AF_INET6,
+       .me             = THIS_MODULE,
+};
+
+static int __init xt_statistic_init(void)
+{
+       int ret;
+
+       ret = xt_register_match(&statistic_match);
+       if (ret)
+               goto err1;
+
+       ret = xt_register_match(&statistic_match6);
+       if (ret)
+               goto err2;
+       return ret;
+err2:
+       xt_unregister_match(&statistic_match);
+err1:
+       return ret;
+}
+
+static void __exit xt_statistic_fini(void)
+{
+       xt_unregister_match(&statistic_match6);
+       xt_unregister_match(&statistic_match);
+}
+
+module_init(xt_statistic_init);
+module_exit(xt_statistic_fini);
index 79d9ea6964ba0a284de74cf2386ed89ab7a9a3da..0ebb6ac2c8c769a2b1a19075d10dc35a1143a32a 100644 (file)
@@ -30,8 +30,8 @@ static int match(const struct sk_buff *skb,
                 unsigned int protoff,
                 int *hotdrop)
 {
+       const struct xt_string_info *conf = matchinfo;
        struct ts_state state;
-       struct xt_string_info *conf = (struct xt_string_info *) matchinfo;
 
        memset(&state, 0, sizeof(struct ts_state));
 
index 138ea92ed268457b99d9c6b44a1a9580cc7c016a..b1e4c5e20ac709c971fd68c8a4b8c573d4c94468 100644 (file)
@@ -72,9 +72,9 @@ void qdisc_unlock_tree(struct net_device *dev)
    dev->queue_lock serializes queue accesses for this device
    AND dev->qdisc pointer itself.
 
-   dev->xmit_lock serializes accesses to device driver.
+   netif_tx_lock serializes accesses to device driver.
 
-   dev->queue_lock and dev->xmit_lock are mutually exclusive,
+   dev->queue_lock and netif_tx_lock are mutually exclusive,
    if one is grabbed, another must be free.
  */
 
@@ -108,7 +108,7 @@ int qdisc_restart(struct net_device *dev)
                 * will be requeued.
                 */
                if (!nolock) {
-                       if (!spin_trylock(&dev->xmit_lock)) {
+                       if (!netif_tx_trylock(dev)) {
                        collision:
                                /* So, someone grabbed the driver. */
                                
@@ -126,8 +126,6 @@ int qdisc_restart(struct net_device *dev)
                                __get_cpu_var(netdev_rx_stat).cpu_collision++;
                                goto requeue;
                        }
-                       /* Remember that the driver is grabbed by us. */
-                       dev->xmit_lock_owner = smp_processor_id();
                }
                
                {
@@ -142,8 +140,7 @@ int qdisc_restart(struct net_device *dev)
                                ret = dev->hard_start_xmit(skb, dev);
                                if (ret == NETDEV_TX_OK) { 
                                        if (!nolock) {
-                                               dev->xmit_lock_owner = -1;
-                                               spin_unlock(&dev->xmit_lock);
+                                               netif_tx_unlock(dev);
                                        }
                                        spin_lock(&dev->queue_lock);
                                        return -1;
@@ -157,8 +154,7 @@ int qdisc_restart(struct net_device *dev)
                        /* NETDEV_TX_BUSY - we need to requeue */
                        /* Release the driver */
                        if (!nolock) { 
-                               dev->xmit_lock_owner = -1;
-                               spin_unlock(&dev->xmit_lock);
+                               netif_tx_unlock(dev);
                        } 
                        spin_lock(&dev->queue_lock);
                        q = dev->qdisc;
@@ -187,7 +183,7 @@ static void dev_watchdog(unsigned long arg)
 {
        struct net_device *dev = (struct net_device *)arg;
 
-       spin_lock(&dev->xmit_lock);
+       netif_tx_lock(dev);
        if (dev->qdisc != &noop_qdisc) {
                if (netif_device_present(dev) &&
                    netif_running(dev) &&
@@ -203,7 +199,7 @@ static void dev_watchdog(unsigned long arg)
                                dev_hold(dev);
                }
        }
-       spin_unlock(&dev->xmit_lock);
+       netif_tx_unlock(dev);
 
        dev_put(dev);
 }
@@ -227,17 +223,17 @@ void __netdev_watchdog_up(struct net_device *dev)
 
 static void dev_watchdog_up(struct net_device *dev)
 {
-       spin_lock_bh(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
        __netdev_watchdog_up(dev);
-       spin_unlock_bh(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
 }
 
 static void dev_watchdog_down(struct net_device *dev)
 {
-       spin_lock_bh(&dev->xmit_lock);
+       netif_tx_lock_bh(dev);
        if (del_timer(&dev->watchdog_timer))
                dev_put(dev);
-       spin_unlock_bh(&dev->xmit_lock);
+       netif_tx_unlock_bh(dev);
 }
 
 void netif_carrier_on(struct net_device *dev)
@@ -582,7 +578,7 @@ void dev_deactivate(struct net_device *dev)
        while (test_bit(__LINK_STATE_SCHED, &dev->state))
                yield();
 
-       spin_unlock_wait(&dev->xmit_lock);
+       spin_unlock_wait(&dev->_xmit_lock);
 }
 
 void dev_init_scheduler(struct net_device *dev)
index 79b8ef34c6e4c9b14d5d877ba64f0a496701e316..4c16ad57a3e49141335a2812b4c7bc3e976e9b46 100644 (file)
@@ -302,20 +302,17 @@ restart:
 
                switch (teql_resolve(skb, skb_res, slave)) {
                case 0:
-                       if (spin_trylock(&slave->xmit_lock)) {
-                               slave->xmit_lock_owner = smp_processor_id();
+                       if (netif_tx_trylock(slave)) {
                                if (!netif_queue_stopped(slave) &&
                                    slave->hard_start_xmit(skb, slave) == 0) {
-                                       slave->xmit_lock_owner = -1;
-                                       spin_unlock(&slave->xmit_lock);
+                                       netif_tx_unlock(slave);
                                        master->slaves = NEXT_SLAVE(q);
                                        netif_wake_queue(dev);
                                        master->stats.tx_packets++;
                                        master->stats.tx_bytes += len;
                                        return 0;
                                }
-                               slave->xmit_lock_owner = -1;
-                               spin_unlock(&slave->xmit_lock);
+                               netif_tx_unlock(slave);
                        }
                        if (netif_queue_stopped(dev))
                                busy = 1;
index 1662f9cc869e0a1cd463b7f3575c0c243dfc4ded..42b66e74bbb504cf38b7ea088895ab49a7446280 100644 (file)
@@ -141,7 +141,8 @@ int sctp_rcv(struct sk_buff *skb)
        __skb_pull(skb, skb->h.raw - skb->data);
        if (skb->len < sizeof(struct sctphdr))
                goto discard_it;
-       if (sctp_rcv_checksum(skb) < 0)
+       if ((skb->ip_summed != CHECKSUM_UNNECESSARY) &&
+           (sctp_rcv_checksum(skb) < 0))
                goto discard_it;
 
        skb_pull(skb, sizeof(struct sctphdr));
@@ -170,7 +171,8 @@ int sctp_rcv(struct sk_buff *skb)
         * IP broadcast addresses cannot be used in an SCTP transport
         * address."
         */
-       if (!af->addr_valid(&src, NULL) || !af->addr_valid(&dest, NULL))
+       if (!af->addr_valid(&src, NULL, skb) ||
+           !af->addr_valid(&dest, NULL, skb))
                goto discard_it;
 
        asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
index c20d282fac06372cb70276c6d424c4d4f0c96428..8ef08070c8b679b4702b922181b0186691335bfd 100644 (file)
@@ -523,7 +523,9 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
  * Return 0 - If the address is a non-unicast or an illegal address.
  * Return 1 - If the address is a unicast.
  */
-static int sctp_v6_addr_valid(union sctp_addr *addr, struct sctp_sock *sp)
+static int sctp_v6_addr_valid(union sctp_addr *addr,
+                             struct sctp_sock *sp,
+                             const struct sk_buff *skb)
 {
        int ret = ipv6_addr_type(&addr->v6.sin6_addr);
 
@@ -537,7 +539,7 @@ static int sctp_v6_addr_valid(union sctp_addr *addr, struct sctp_sock *sp)
                if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
                        return 0;
                sctp_v6_map_v4(addr);
-               return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp);
+               return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp, skb);
        }
 
        /* Is this a non-unicast address */
index 437cba7260a4a1a6970546cbf36f650114a785ab..cdc5a393676657691a2421b573235fde8318b0f8 100644 (file)
@@ -295,14 +295,14 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        struct sctp_transport *tp = packet->transport;
        struct sctp_association *asoc = tp->asoc;
        struct sctphdr *sh;
-       __u32 crc32;
+       __u32 crc32 = 0;
        struct sk_buff *nskb;
        struct sctp_chunk *chunk, *tmp;
        struct sock *sk;
        int err = 0;
        int padding;            /* How much padding do we need?  */
        __u8 has_data = 0;
-       struct dst_entry *dst;
+       struct dst_entry *dst = tp->dst;
 
        SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
 
@@ -327,6 +327,19 @@ int sctp_packet_transmit(struct sctp_packet *packet)
         */
        skb_set_owner_w(nskb, sk);
 
+       /* The 'obsolete' field of dst is set to 2 when a dst is freed. */
+       if (!dst || (dst->obsolete > 1)) {
+               dst_release(dst);
+               sctp_transport_route(tp, NULL, sctp_sk(sk));
+               if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) {
+                       sctp_assoc_sync_pmtu(asoc);
+               }
+       }
+       nskb->dst = dst_clone(tp->dst);
+       if (!nskb->dst)
+               goto no_route;
+       dst = nskb->dst;
+
        /* Build the SCTP header.  */
        sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
        sh->source = htons(packet->source_port);
@@ -350,7 +363,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
         * Note: Adler-32 is no longer applicable, as has been replaced
         * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
         */
-       crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
+       if (!(dst->dev->features & NETIF_F_NO_CSUM))
+               crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
 
        /**
         * 6.10 Bundling
@@ -402,9 +416,14 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                if (padding)
                        memset(skb_put(chunk->skb, padding), 0, padding);
 
-               crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len),
-                                              chunk->skb->data,
-                                              chunk->skb->len, crc32);
+               if (dst->dev->features & NETIF_F_NO_CSUM)
+                       memcpy(skb_put(nskb, chunk->skb->len),
+                              chunk->skb->data, chunk->skb->len);
+               else
+                       crc32 = sctp_update_copy_cksum(skb_put(nskb,
+                                                       chunk->skb->len),
+                                               chunk->skb->data,
+                                               chunk->skb->len, crc32);
 
                SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n",
                                  "*** Chunk", chunk,
@@ -427,7 +446,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        }
 
        /* Perform final transformation on checksum. */
-       crc32 = sctp_end_cksum(crc32);
+       if (!(dst->dev->features & NETIF_F_NO_CSUM))
+               crc32 = sctp_end_cksum(crc32);
 
        /* 3) Put the resultant value into the checksum field in the
         *    common header, and leave the rest of the bits unchanged.
@@ -477,20 +497,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                }
        }
 
-       dst = tp->dst;
-       /* The 'obsolete' field of dst is set to 2 when a dst is freed. */
-       if (!dst || (dst->obsolete > 1)) {
-               dst_release(dst);
-               sctp_transport_route(tp, NULL, sctp_sk(sk));
-               if (asoc->param_flags & SPP_PMTUD_ENABLE) {
-                       sctp_assoc_sync_pmtu(asoc);
-               }
-       }
-
-       nskb->dst = dst_clone(tp->dst);
-       if (!nskb->dst)
-               goto no_route;
-
        SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n",
                          nskb->len);
 
index f148f9576dd226035b3b6c34d439d7558818ce4a..e5faa351aaadeffd1f1b5a2bc1636c39384d0cae 100644 (file)
@@ -1262,6 +1262,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
                                if (!tchunk->tsn_gap_acked &&
                                    !tchunk->resent &&
                                    tchunk->rtt_in_progress) {
+                                       tchunk->rtt_in_progress = 0;
                                        rtt = jiffies - tchunk->sent_at;
                                        sctp_transport_update_rto(transport,
                                                                  rtt);
index 2088aa992b7abf91e3dd5391789efc7cc228eb03..816c033d78865464a8826c8ab2ae102b633a2e31 100644 (file)
@@ -365,12 +365,18 @@ static int sctp_v4_is_any(const union sctp_addr *addr)
  * Return 0 - If the address is a non-unicast or an illegal address.
  * Return 1 - If the address is a unicast.
  */
-static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_sock *sp)
+static int sctp_v4_addr_valid(union sctp_addr *addr,
+                             struct sctp_sock *sp,
+                             const struct sk_buff *skb)
 {
        /* Is this a non-unicast address or a unusable SCTP address? */
        if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr))
                return 0;
 
+       /* Is this a broadcast address? */
+       if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST)
+               return 0;
+
        return 1;
 }
 
index 8bc279219a72ca3b8e4e107eaeba562e87a79e4a..9e58144f4851129b7b9c6465c597a3a00bea0b46 100644 (file)
@@ -5293,10 +5293,18 @@ static int sctp_eat_data(const struct sctp_association *asoc,
         * seems a bit troublesome in that frag_point varies based on
         * PMTU.  In cases, such as loopback, this might be a rather
         * large spill over.
+        * NOTE: If we have a full receive buffer here, we only renege if
+        * our receiver can still make progress without the tsn being
+        * received. We do this because in the event that the associations
+        * receive queue is empty we are filling a leading gap, and since
+        * reneging moves the gap to the end of the tsn stream, we are likely
+        * to stall again very shortly. Avoiding the renege when we fill a
+        * leading gap is a good heuristic for avoiding such steady state
+        * stalls.
         */
        if (!asoc->rwnd || asoc->rwnd_over ||
            (datalen > asoc->rwnd + asoc->frag_point) ||
-           rcvbuf_over) {
+           (rcvbuf_over && (!skb_queue_len(&sk->sk_receive_queue)))) {
 
                /* If this is the next TSN, consider reneging to make
                 * room.   Note: Playing nice with a confused sender.  A
index 174d4d35e951590d7bef5d10df113afe36f88ae6..b811691c35bf4eba764efa3eba3b0daeac6eca64 100644 (file)
@@ -172,7 +172,7 @@ static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
                return -EINVAL;
 
        /* Is this a valid SCTP address?  */
-       if (!af->addr_valid(addr, sctp_sk(sk)))
+       if (!af->addr_valid(addr, sctp_sk(sk), NULL))
                return -EINVAL;
 
        if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr)))
@@ -2530,8 +2530,32 @@ static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, int o
 
        /* Set the values to the specific association */
        if (asoc) {
-               if (assocparams.sasoc_asocmaxrxt != 0)
+               if (assocparams.sasoc_asocmaxrxt != 0) {
+                       __u32 path_sum = 0;
+                       int   paths = 0;
+                       struct list_head *pos;
+                       struct sctp_transport *peer_addr;
+
+                       list_for_each(pos, &asoc->peer.transport_addr_list) {
+                               peer_addr = list_entry(pos,
+                                               struct sctp_transport,
+                                               transports);
+                               path_sum += peer_addr->pathmaxrxt;
+                               paths++;
+                       }
+
+                       /* Only validate asocmaxrxt if we have more then
+                        * one path/transport.  We do this because path
+                        * retransmissions are only counted when we have more
+                        * then one path.
+                        */
+                       if (paths > 1 &&
+                           assocparams.sasoc_asocmaxrxt > path_sum)
+                               return -EINVAL;
+
                        asoc->max_retrans = assocparams.sasoc_asocmaxrxt;
+               }
+
                if (assocparams.sasoc_cookie_life != 0) {
                        asoc->cookie_life.tv_sec =
                                        assocparams.sasoc_cookie_life / 1000;
index ba97f974f57c3bb8c5109d547e9f9644a9609d26..ee236784a6bb91ea8bbf3787b776aabf65971ae9 100644 (file)
@@ -51,6 +51,8 @@
 static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
                                       struct sctp_association *asoc);
 static void sctp_ulpevent_release_data(struct sctp_ulpevent *event);
+static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event);
+
 
 /* Initialize an ULP event from an given skb.  */
 SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
@@ -883,6 +885,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
 static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
 {
        struct sk_buff *skb, *frag;
+       unsigned int    len;
 
        /* Current stack structures assume that the rcv buffer is
         * per socket.   For UDP style sockets this is not true as
@@ -892,7 +895,30 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
         */
 
        skb = sctp_event2skb(event);
-       sctp_assoc_rwnd_increase(event->asoc, skb_headlen(skb));
+       len = skb->len;
+
+       if (!skb->data_len)
+               goto done;
+
+       /* Don't forget the fragments. */
+       for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {
+               /* NOTE:  skb_shinfos are recursive. Although IP returns
+                * skb's with only 1 level of fragments, SCTP reassembly can
+                * increase the levels.
+                */
+               sctp_ulpevent_release_frag_data(sctp_skb2event(frag));
+       }
+
+done:
+       sctp_assoc_rwnd_increase(event->asoc, len);
+       sctp_ulpevent_release_owner(event);
+}
+
+static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event)
+{
+       struct sk_buff *skb, *frag;
+
+       skb = sctp_event2skb(event);
 
        if (!skb->data_len)
                goto done;
@@ -903,7 +929,7 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
                 * skb's with only 1 level of fragments, SCTP reassembly can
                 * increase the levels.
                 */
-               sctp_ulpevent_release_data(sctp_skb2event(frag));
+               sctp_ulpevent_release_frag_data(sctp_skb2event(frag));
        }
 
 done:
index 55538f6b60ffc56648687f9f72fd7d0ebafe6af3..58a1b6b42dddba6c85c10330bacdb48f7438e4f4 100644 (file)
@@ -37,14 +37,6 @@ struct ctl_table net_table[] = {
                .mode           = 0555,
                .child          = core_table,
        },
-#ifdef CONFIG_NET
-       {
-               .ctl_name       = NET_ETHER,
-               .procname       = "ethernet",
-               .mode           = 0555,
-               .child          = ether_table,
-       },
-#endif
 #ifdef CONFIG_INET
        {
                .ctl_name       = NET_IPV4,
index b469c8b54613354a495db0fc4996aa5916e53829..b8936926c24b84dba699540b54b0630f2002d439 100644 (file)
@@ -46,45 +46,43 @@ static DEFINE_SPINLOCK(xfrm_policy_gc_lock);
 
 static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
 static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
+static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family);
+static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo);
 
 int xfrm_register_type(struct xfrm_type *type, unsigned short family)
 {
-       struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
-       struct xfrm_type_map *typemap;
+       struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
+       struct xfrm_type **typemap;
        int err = 0;
 
        if (unlikely(afinfo == NULL))
                return -EAFNOSUPPORT;
        typemap = afinfo->type_map;
 
-       write_lock_bh(&typemap->lock);
-       if (likely(typemap->map[type->proto] == NULL))
-               typemap->map[type->proto] = type;
+       if (likely(typemap[type->proto] == NULL))
+               typemap[type->proto] = type;
        else
                err = -EEXIST;
-       write_unlock_bh(&typemap->lock);
-       xfrm_policy_put_afinfo(afinfo);
+       xfrm_policy_unlock_afinfo(afinfo);
        return err;
 }
 EXPORT_SYMBOL(xfrm_register_type);
 
 int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
 {
-       struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
-       struct xfrm_type_map *typemap;
+       struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
+       struct xfrm_type **typemap;
        int err = 0;
 
        if (unlikely(afinfo == NULL))
                return -EAFNOSUPPORT;
        typemap = afinfo->type_map;
 
-       write_lock_bh(&typemap->lock);
-       if (unlikely(typemap->map[type->proto] != type))
+       if (unlikely(typemap[type->proto] != type))
                err = -ENOENT;
        else
-               typemap->map[type->proto] = NULL;
-       write_unlock_bh(&typemap->lock);
-       xfrm_policy_put_afinfo(afinfo);
+               typemap[type->proto] = NULL;
+       xfrm_policy_unlock_afinfo(afinfo);
        return err;
 }
 EXPORT_SYMBOL(xfrm_unregister_type);
@@ -92,7 +90,7 @@ EXPORT_SYMBOL(xfrm_unregister_type);
 struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
 {
        struct xfrm_policy_afinfo *afinfo;
-       struct xfrm_type_map *typemap;
+       struct xfrm_type **typemap;
        struct xfrm_type *type;
        int modload_attempted = 0;
 
@@ -102,11 +100,9 @@ retry:
                return NULL;
        typemap = afinfo->type_map;
 
-       read_lock(&typemap->lock);
-       type = typemap->map[proto];
+       type = typemap[proto];
        if (unlikely(type && !try_module_get(type->owner)))
                type = NULL;
-       read_unlock(&typemap->lock);
        if (!type && !modload_attempted) {
                xfrm_policy_put_afinfo(afinfo);
                request_module("xfrm-type-%d-%d",
@@ -142,6 +138,89 @@ void xfrm_put_type(struct xfrm_type *type)
        module_put(type->owner);
 }
 
+int xfrm_register_mode(struct xfrm_mode *mode, int family)
+{
+       struct xfrm_policy_afinfo *afinfo;
+       struct xfrm_mode **modemap;
+       int err;
+
+       if (unlikely(mode->encap >= XFRM_MODE_MAX))
+               return -EINVAL;
+
+       afinfo = xfrm_policy_lock_afinfo(family);
+       if (unlikely(afinfo == NULL))
+               return -EAFNOSUPPORT;
+
+       err = -EEXIST;
+       modemap = afinfo->mode_map;
+       if (likely(modemap[mode->encap] == NULL)) {
+               modemap[mode->encap] = mode;
+               err = 0;
+       }
+
+       xfrm_policy_unlock_afinfo(afinfo);
+       return err;
+}
+EXPORT_SYMBOL(xfrm_register_mode);
+
+int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
+{
+       struct xfrm_policy_afinfo *afinfo;
+       struct xfrm_mode **modemap;
+       int err;
+
+       if (unlikely(mode->encap >= XFRM_MODE_MAX))
+               return -EINVAL;
+
+       afinfo = xfrm_policy_lock_afinfo(family);
+       if (unlikely(afinfo == NULL))
+               return -EAFNOSUPPORT;
+
+       err = -ENOENT;
+       modemap = afinfo->mode_map;
+       if (likely(modemap[mode->encap] == mode)) {
+               modemap[mode->encap] = NULL;
+               err = 0;
+       }
+
+       xfrm_policy_unlock_afinfo(afinfo);
+       return err;
+}
+EXPORT_SYMBOL(xfrm_unregister_mode);
+
+struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
+{
+       struct xfrm_policy_afinfo *afinfo;
+       struct xfrm_mode *mode;
+       int modload_attempted = 0;
+
+       if (unlikely(encap >= XFRM_MODE_MAX))
+               return NULL;
+
+retry:
+       afinfo = xfrm_policy_get_afinfo(family);
+       if (unlikely(afinfo == NULL))
+               return NULL;
+
+       mode = afinfo->mode_map[encap];
+       if (unlikely(mode && !try_module_get(mode->owner)))
+               mode = NULL;
+       if (!mode && !modload_attempted) {
+               xfrm_policy_put_afinfo(afinfo);
+               request_module("xfrm-mode-%d-%d", family, encap);
+               modload_attempted = 1;
+               goto retry;
+       }
+
+       xfrm_policy_put_afinfo(afinfo);
+       return mode;
+}
+
+void xfrm_put_mode(struct xfrm_mode *mode)
+{
+       module_put(mode->owner);
+}
+
 static inline unsigned long make_jiffies(long secs)
 {
        if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
@@ -1306,17 +1385,31 @@ static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
                return NULL;
        read_lock(&xfrm_policy_afinfo_lock);
        afinfo = xfrm_policy_afinfo[family];
-       if (likely(afinfo != NULL))
-               read_lock(&afinfo->lock);
-       read_unlock(&xfrm_policy_afinfo_lock);
+       if (unlikely(!afinfo))
+               read_unlock(&xfrm_policy_afinfo_lock);
        return afinfo;
 }
 
 static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
-       if (unlikely(afinfo == NULL))
-               return;
-       read_unlock(&afinfo->lock);
+       read_unlock(&xfrm_policy_afinfo_lock);
+}
+
+static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family)
+{
+       struct xfrm_policy_afinfo *afinfo;
+       if (unlikely(family >= NPROTO))
+               return NULL;
+       write_lock_bh(&xfrm_policy_afinfo_lock);
+       afinfo = xfrm_policy_afinfo[family];
+       if (unlikely(!afinfo))
+               write_unlock_bh(&xfrm_policy_afinfo_lock);
+       return afinfo;
+}
+
+static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo)
+{
+       write_unlock_bh(&xfrm_policy_afinfo_lock);
 }
 
 static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
index 93a2f36ad3db7b30a681f726e31c6240d030d6ed..17b29ec3c41779d70562113ed1219e68ff3ae5fc 100644 (file)
@@ -77,6 +77,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
        kfree(x->ealg);
        kfree(x->calg);
        kfree(x->encap);
+       if (x->mode)
+               xfrm_put_mode(x->mode);
        if (x->type) {
                x->type->destructor(x);
                xfrm_put_type(x->type);
@@ -1103,17 +1105,14 @@ static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
                return NULL;
        read_lock(&xfrm_state_afinfo_lock);
        afinfo = xfrm_state_afinfo[family];
-       if (likely(afinfo != NULL))
-               read_lock(&afinfo->lock);
-       read_unlock(&xfrm_state_afinfo_lock);
+       if (unlikely(!afinfo))
+               read_unlock(&xfrm_state_afinfo_lock);
        return afinfo;
 }
 
 static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
 {
-       if (unlikely(afinfo == NULL))
-               return;
-       read_unlock(&afinfo->lock);
+       read_unlock(&xfrm_state_afinfo_lock);
 }
 
 /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
@@ -1196,6 +1195,10 @@ int xfrm_init_state(struct xfrm_state *x)
        if (err)
                goto error;
 
+       x->mode = xfrm_get_mode(x->props.mode, family);
+       if (x->mode == NULL)
+               goto error;
+
        x->km.state = XFRM_STATE_VALID;
 
 error:
index 81d1005830f4d23d88ba4b06c4932fef1f060345..c21dc26141eae947f921e881016cbd64da735c64 100644 (file)
@@ -427,23 +427,25 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
        if (x == NULL)
                return -ESRCH;
 
+       if ((err = security_xfrm_state_delete(x)) != 0)
+               goto out;
+
        if (xfrm_state_kern(x)) {
-               xfrm_state_put(x);
-               return -EPERM;
+               err = -EPERM;
+               goto out;
        }
 
        err = xfrm_state_delete(x);
-       if (err < 0) {
-               xfrm_state_put(x);
-               return err;
-       }
+       if (err < 0)
+               goto out;
 
        c.seq = nlh->nlmsg_seq;
        c.pid = nlh->nlmsg_pid;
        c.event = nlh->nlmsg_type;
        km_state_notify(x, &c);
-       xfrm_state_put(x);
 
+out:
+       xfrm_state_put(x);
        return err;
 }
 
@@ -1055,6 +1057,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
                                              MSG_DONTWAIT);
                }
        } else {
+               if ((err = security_xfrm_policy_delete(xp)) != 0)
+                       goto out;
                c.data.byid = p->index;
                c.event = nlh->nlmsg_type;
                c.seq = nlh->nlmsg_seq;
@@ -1064,6 +1068,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
 
        xfrm_pol_put(xp);
 
+out:
        return err;
 }
 
index 8ccccccc12acd78f72395dabd4f1c4aade37e784..64f6da0f422e2ceff980ea0a7117fb9b75d9be10 100644 (file)
@@ -810,6 +810,11 @@ static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp)
 {
 }
 
+static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
+{
+       return 0;
+}
+
 static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
 {
        return 0;
@@ -819,6 +824,11 @@ static void dummy_xfrm_state_free_security(struct xfrm_state *x)
 {
 }
 
+static int dummy_xfrm_state_delete_security(struct xfrm_state *x)
+{
+       return 0;
+}
+
 static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
 {
        return 0;
@@ -1024,8 +1034,10 @@ void security_fixup_ops (struct security_operations *ops)
        set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
        set_to_dummy_if_null(ops, xfrm_policy_clone_security);
        set_to_dummy_if_null(ops, xfrm_policy_free_security);
+       set_to_dummy_if_null(ops, xfrm_policy_delete_security);
        set_to_dummy_if_null(ops, xfrm_state_alloc_security);
        set_to_dummy_if_null(ops, xfrm_state_free_security);
+       set_to_dummy_if_null(ops, xfrm_state_delete_security);
        set_to_dummy_if_null(ops, xfrm_policy_lookup);
 #endif /* CONFIG_SECURITY_NETWORK_XFRM */
 #ifdef CONFIG_KEYS
index b6061fa29da7fc7eb5278530ebb26769dc4ebcde..3fdc49c6a02cde37607fbf792bfc2068fd773860 100644 (file)
@@ -211,12 +211,12 @@ static inline void key_alloc_serial(struct key *key)
                        key->serial = 2;
                key_serial_next = key->serial + 1;
 
-               if (!parent->rb_parent)
+               if (!rb_parent(parent))
                        p = &key_serial_tree.rb_node;
-               else if (parent->rb_parent->rb_left == parent)
-                       p = &parent->rb_parent->rb_left;
+               else if (rb_parent(parent)->rb_left == parent)
+                       p = &(rb_parent(parent)->rb_left);
                else
-                       p = &parent->rb_parent->rb_right;
+                       p = &(rb_parent(parent)->rb_right);
 
                parent = rb_next(parent);
                if (!parent)
index f636f53ca5444ccabdd231e5be72d8bbe976838e..814ddc42f1f4636e19daa7f50d57686bc5ea9257 100644 (file)
@@ -1,6 +1,7 @@
 config SECURITY_SELINUX
        bool "NSA SELinux Support"
        depends on SECURITY_NETWORK && AUDIT && NET && INET
+       select NETWORK_SECMARK
        default n
        help
          This selects NSA Security-Enhanced Linux (SELinux).
@@ -95,3 +96,31 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE
          via /selinux/checkreqprot if authorized by policy.
 
          If you are unsure how to answer this question, answer 1.
+
+config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
+       bool "NSA SELinux enable new secmark network controls by default"
+       depends on SECURITY_SELINUX
+       default n
+       help
+         This option determines whether the new secmark-based network
+         controls will be enabled by default.  If not, the old internal
+         per-packet controls will be enabled by default, preserving
+         old behavior.
+
+         If you enable the new controls, you will need updated
+         SELinux userspace libraries, tools and policy.  Typically,
+         your distribution will provide these and enable the new controls
+         in the kernel they also distribute.
+
+         Note that this option can be overriden at boot with the
+         selinux_compat_net parameter, and after boot via
+         /selinux/compat_net.  See Documentation/kernel-parameters.txt
+         for details on this parameter.
+
+         If you enable the new network controls, you will likely
+         also require the SECMARK and CONNSECMARK targets, as
+         well as any conntrack helpers for protocols which you
+         wish to control.
+
+         If you are unsure what do do here, select N.
+
index ae4c73eb30857d769f64ae731b7345d2c374bc0d..9d7737db5e51751be1b7f040dacf44ed405ec0db 100644 (file)
@@ -72,3 +72,25 @@ void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
        *sid = 0;
 }
 
+int selinux_string_to_sid(char *str, u32 *sid)
+{
+       if (selinux_enabled)
+               return security_context_to_sid(str, strlen(str), sid);
+       else {
+               *sid = 0;
+               return 0;
+       }
+}
+EXPORT_SYMBOL_GPL(selinux_string_to_sid);
+
+int selinux_relabel_packet_permission(u32 sid)
+{
+       if (selinux_enabled) {
+               struct task_security_struct *tsec = current->security;
+
+               return avc_has_perm(tsec->sid, sid, SECCLASS_PACKET,
+                                   PACKET__RELABELTO, NULL);
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(selinux_relabel_packet_permission);
index 21dad415b8960d7e389a7e4d8376a9972b0e7abe..54adc9d31e9248ae3b1ca00ed0cc166a533c814e 100644 (file)
@@ -80,6 +80,7 @@
 
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
+extern int selinux_compat_net;
 
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
 int selinux_enforcing = 0;
@@ -696,6 +697,8 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
                return SECCLASS_PACKET_SOCKET;
        case PF_KEY:
                return SECCLASS_KEY_SOCKET;
+       case PF_APPLETALK:
+               return SECCLASS_APPLETALK_SOCKET;
        }
 
        return SECCLASS_SOCKET;
@@ -3214,47 +3217,17 @@ static int selinux_socket_unix_may_send(struct socket *sock,
        return 0;
 }
 
-static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
+               struct avc_audit_data *ad, u32 sock_sid, u16 sock_class,
+               u16 family, char *addrp, int len)
 {
-       u16 family;
-       char *addrp;
-       int len, err = 0;
+       int err = 0;
        u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
-       u32 sock_sid = 0;
-       u16 sock_class = 0;
-       struct socket *sock;
-       struct net_device *dev;
-       struct avc_audit_data ad;
 
-       family = sk->sk_family;
-       if (family != PF_INET && family != PF_INET6)
+       if (!skb->dev)
                goto out;
 
-       /* Handle mapped IPv4 packets arriving via IPv6 sockets */
-       if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
-               family = PF_INET;
-
-       read_lock_bh(&sk->sk_callback_lock);
-       sock = sk->sk_socket;
-       if (sock) {
-               struct inode *inode;
-               inode = SOCK_INODE(sock);
-               if (inode) {
-                       struct inode_security_struct *isec;
-                       isec = inode->i_security;
-                       sock_sid = isec->sid;
-                       sock_class = isec->sclass;
-               }
-       }
-       read_unlock_bh(&sk->sk_callback_lock);
-       if (!sock_sid)
-               goto out;
-
-       dev = skb->dev;
-       if (!dev)
-               goto out;
-
-       err = sel_netif_sids(dev, &if_sid, NULL);
+       err = sel_netif_sids(skb->dev, &if_sid, NULL);
        if (err)
                goto out;
 
@@ -3277,44 +3250,88 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                break;
        }
 
-       AVC_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = dev->name;
-       ad.u.net.family = family;
-
-       err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
-       if (err)
-               goto out;
-
-       err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, &ad);
+       err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
        if (err)
                goto out;
        
-       /* Fixme: this lookup is inefficient */
        err = security_node_sid(family, addrp, len, &node_sid);
        if (err)
                goto out;
        
-       err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, &ad);
+       err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, ad);
        if (err)
                goto out;
 
        if (recv_perm) {
                u32 port_sid;
 
-               /* Fixme: make this more efficient */
                err = security_port_sid(sk->sk_family, sk->sk_type,
-                                       sk->sk_protocol, ntohs(ad.u.net.sport),
+                                       sk->sk_protocol, ntohs(ad->u.net.sport),
                                        &port_sid);
                if (err)
                        goto out;
 
                err = avc_has_perm(sock_sid, port_sid,
-                                  sock_class, recv_perm, &ad);
+                                  sock_class, recv_perm, ad);
        }
 
-       if (!err)
-               err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+out:
+       return err;
+}
+
+static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+       u16 family;
+       u16 sock_class = 0;
+       char *addrp;
+       int len, err = 0;
+       u32 sock_sid = 0;
+       struct socket *sock;
+       struct avc_audit_data ad;
 
+       family = sk->sk_family;
+       if (family != PF_INET && family != PF_INET6)
+               goto out;
+
+       /* Handle mapped IPv4 packets arriving via IPv6 sockets */
+       if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
+               family = PF_INET;
+
+       read_lock_bh(&sk->sk_callback_lock);
+       sock = sk->sk_socket;
+       if (sock) {
+               struct inode *inode;
+               inode = SOCK_INODE(sock);
+               if (inode) {
+                       struct inode_security_struct *isec;
+                       isec = inode->i_security;
+                       sock_sid = isec->sid;
+                       sock_class = isec->sclass;
+               }
+       }
+       read_unlock_bh(&sk->sk_callback_lock);
+       if (!sock_sid)
+               goto out;
+
+       AVC_AUDIT_DATA_INIT(&ad, NET);
+       ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
+       ad.u.net.family = family;
+
+       err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
+       if (err)
+               goto out;
+
+       if (selinux_compat_net)
+               err = selinux_sock_rcv_skb_compat(sk, skb, &ad, sock_sid,
+                                                 sock_class, family,
+                                                 addrp, len);
+       else
+               err = avc_has_perm(sock_sid, skb->secmark, SECCLASS_PACKET,
+                                  PACKET__RECV, &ad);
+       if (err)
+               goto out;
+
+       err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
 out:   
        return err;
 }
@@ -3454,42 +3471,18 @@ out:
 
 #ifdef CONFIG_NETFILTER
 
-static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
-                                              struct sk_buff **pskb,
-                                              const struct net_device *in,
-                                              const struct net_device *out,
-                                              int (*okfn)(struct sk_buff *),
-                                              u16 family)
+static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev,
+                                           struct inode_security_struct *isec,
+                                           struct avc_audit_data *ad,
+                                           u16 family, char *addrp, int len)
 {
-       char *addrp;
-       int len, err = NF_ACCEPT;
+       int err;
        u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
-       struct sock *sk;
-       struct socket *sock;
-       struct inode *inode;
-       struct sk_buff *skb = *pskb;
-       struct inode_security_struct *isec;
-       struct avc_audit_data ad;
-       struct net_device *dev = (struct net_device *)out;
        
-       sk = skb->sk;
-       if (!sk)
-               goto out;
-               
-       sock = sk->sk_socket;
-       if (!sock)
-               goto out;
-               
-       inode = SOCK_INODE(sock);
-       if (!inode)
-               goto out;
-
        err = sel_netif_sids(dev, &if_sid, NULL);
        if (err)
                goto out;
 
-       isec = inode->i_security;
-       
        switch (isec->sclass) {
        case SECCLASS_UDP_SOCKET:
                netif_perm = NETIF__UDP_SEND;
@@ -3509,55 +3502,88 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
                break;
        }
 
-
-       AVC_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = dev->name;
-       ad.u.net.family = family;
-
-       err = selinux_parse_skb(skb, &ad, &addrp,
-                               &len, 0) ? NF_DROP : NF_ACCEPT;
-       if (err != NF_ACCEPT)
-               goto out;
-
-       err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF,
-                          netif_perm, &ad) ? NF_DROP : NF_ACCEPT;
-       if (err != NF_ACCEPT)
+       err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
+       if (err)
                goto out;
                
-       /* Fixme: this lookup is inefficient */
-       err = security_node_sid(family, addrp, len,
-                               &node_sid) ? NF_DROP : NF_ACCEPT;
-       if (err != NF_ACCEPT)
+       err = security_node_sid(family, addrp, len, &node_sid);
+       if (err)
                goto out;
        
-       err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE,
-                          node_perm, &ad) ? NF_DROP : NF_ACCEPT;
-       if (err != NF_ACCEPT)
+       err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad);
+       if (err)
                goto out;
 
        if (send_perm) {
                u32 port_sid;
                
-               /* Fixme: make this more efficient */
                err = security_port_sid(sk->sk_family,
                                        sk->sk_type,
                                        sk->sk_protocol,
-                                       ntohs(ad.u.net.dport),
-                                       &port_sid) ? NF_DROP : NF_ACCEPT;
-               if (err != NF_ACCEPT)
+                                       ntohs(ad->u.net.dport),
+                                       &port_sid);
+               if (err)
                        goto out;
 
                err = avc_has_perm(isec->sid, port_sid, isec->sclass,
-                                  send_perm, &ad) ? NF_DROP : NF_ACCEPT;
+                                  send_perm, ad);
        }
+out:
+       return err;
+}
+
+static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
+                                              struct sk_buff **pskb,
+                                              const struct net_device *in,
+                                              const struct net_device *out,
+                                              int (*okfn)(struct sk_buff *),
+                                              u16 family)
+{
+       char *addrp;
+       int len, err = 0;
+       struct sock *sk;
+       struct socket *sock;
+       struct inode *inode;
+       struct sk_buff *skb = *pskb;
+       struct inode_security_struct *isec;
+       struct avc_audit_data ad;
+       struct net_device *dev = (struct net_device *)out;
 
-       if (err != NF_ACCEPT)
+       sk = skb->sk;
+       if (!sk)
                goto out;
 
-       err = selinux_xfrm_postroute_last(isec->sid, skb);
+       sock = sk->sk_socket;
+       if (!sock)
+               goto out;
 
+       inode = SOCK_INODE(sock);
+       if (!inode)
+               goto out;
+
+       isec = inode->i_security;
+
+       AVC_AUDIT_DATA_INIT(&ad, NET);
+       ad.u.net.netif = dev->name;
+       ad.u.net.family = family;
+
+       err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
+       if (err)
+               goto out;
+
+       if (selinux_compat_net)
+               err = selinux_ip_postroute_last_compat(sk, dev, isec, &ad,
+                                                      family, addrp, len);
+       else
+               err = avc_has_perm(isec->sid, skb->secmark, SECCLASS_PACKET,
+                                  PACKET__SEND, &ad);
+
+       if (err)
+               goto out;
+
+       err = selinux_xfrm_postroute_last(isec->sid, skb);
 out:
-       return err;
+       return err ? NF_DROP : NF_ACCEPT;
 }
 
 static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum,
@@ -4374,8 +4400,10 @@ static struct security_operations selinux_ops = {
        .xfrm_policy_alloc_security =   selinux_xfrm_policy_alloc,
        .xfrm_policy_clone_security =   selinux_xfrm_policy_clone,
        .xfrm_policy_free_security =    selinux_xfrm_policy_free,
+       .xfrm_policy_delete_security =  selinux_xfrm_policy_delete,
        .xfrm_state_alloc_security =    selinux_xfrm_state_alloc,
        .xfrm_state_free_security =     selinux_xfrm_state_free,
+       .xfrm_state_delete_security =   selinux_xfrm_state_delete,
        .xfrm_policy_lookup =           selinux_xfrm_policy_lookup,
 #endif
 };
@@ -4422,6 +4450,7 @@ void selinux_complete_init(void)
 
        /* Set up any superblocks initialized prior to the policy load. */
        printk(KERN_INFO "SELinux:  Setting up existing superblocks.\n");
+       spin_lock(&sb_lock);
        spin_lock(&sb_security_lock);
 next_sb:
        if (!list_empty(&superblock_security_head)) {
@@ -4430,19 +4459,20 @@ next_sb:
                                           struct superblock_security_struct,
                                           list);
                struct super_block *sb = sbsec->sb;
-               spin_lock(&sb_lock);
                sb->s_count++;
-               spin_unlock(&sb_lock);
                spin_unlock(&sb_security_lock);
+               spin_unlock(&sb_lock);
                down_read(&sb->s_umount);
                if (sb->s_root)
                        superblock_doinit(sb, NULL);
                drop_super(sb);
+               spin_lock(&sb_lock);
                spin_lock(&sb_security_lock);
                list_del_init(&sbsec->list);
                goto next_sb;
        }
        spin_unlock(&sb_security_lock);
+       spin_unlock(&sb_lock);
 }
 
 /* SELinux requires early initialization in order to label
index b0e6b12931c98c760727e34d50d0b600004510a0..a68fdd55597f636290cc9dd93c11680b1f452147 100644 (file)
@@ -29,3 +29,4 @@
    S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL)
    S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
    S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL)
+   S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL)
index 591e98d9315a238ab0d98f81646e4087ddd9fcf8..70ee65a588170f48041de266f142520873b01c9b 100644 (file)
    S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto")
    S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom")
    S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext")
+   S_(SECCLASS_PACKET, PACKET__SEND, "send")
+   S_(SECCLASS_PACKET, PACKET__RECV, "recv")
+   S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto")
index d7f02edf3930c6a4226961c23995aa7e9abaa58e..1d9cf3d306bc95069c43235131acf6cef4be392d 100644 (file)
 #define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG   0x00100000UL
 #define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND  0x00200000UL
 
+#define APPLETALK_SOCKET__IOCTL                   0x00000001UL
+#define APPLETALK_SOCKET__READ                    0x00000002UL
+#define APPLETALK_SOCKET__WRITE                   0x00000004UL
+#define APPLETALK_SOCKET__CREATE                  0x00000008UL
+#define APPLETALK_SOCKET__GETATTR                 0x00000010UL
+#define APPLETALK_SOCKET__SETATTR                 0x00000020UL
+#define APPLETALK_SOCKET__LOCK                    0x00000040UL
+#define APPLETALK_SOCKET__RELABELFROM             0x00000080UL
+#define APPLETALK_SOCKET__RELABELTO               0x00000100UL
+#define APPLETALK_SOCKET__APPEND                  0x00000200UL
+#define APPLETALK_SOCKET__BIND                    0x00000400UL
+#define APPLETALK_SOCKET__CONNECT                 0x00000800UL
+#define APPLETALK_SOCKET__LISTEN                  0x00001000UL
+#define APPLETALK_SOCKET__ACCEPT                  0x00002000UL
+#define APPLETALK_SOCKET__GETOPT                  0x00004000UL
+#define APPLETALK_SOCKET__SETOPT                  0x00008000UL
+#define APPLETALK_SOCKET__SHUTDOWN                0x00010000UL
+#define APPLETALK_SOCKET__RECVFROM                0x00020000UL
+#define APPLETALK_SOCKET__SENDTO                  0x00040000UL
+#define APPLETALK_SOCKET__RECV_MSG                0x00080000UL
+#define APPLETALK_SOCKET__SEND_MSG                0x00100000UL
+#define APPLETALK_SOCKET__NAME_BIND               0x00200000UL
+
+#define PACKET__SEND                              0x00000001UL
+#define PACKET__RECV                              0x00000002UL
+#define PACKET__RELABELTO                         0x00000004UL
index 77b2c5996f355add1b9a4d7698cb7728daa60879..3aec75fee4f7b723fa5b02c634d51fc33ce5a7b7 100644 (file)
@@ -58,3 +58,5 @@
     S_("nscd")
     S_("association")
     S_("netlink_kobject_uevent_socket")
+    S_("appletalk_socket")
+    S_("packet")
index eb9f50823f6e132c78557f16cc20963bb247226f..a0eb9e281d185f886de232cbc8ad37795d653cf1 100644 (file)
@@ -60,6 +60,8 @@
 #define SECCLASS_NSCD                                    53
 #define SECCLASS_ASSOCIATION                             54
 #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET           55
+#define SECCLASS_APPLETALK_SOCKET                        56
+#define SECCLASS_PACKET                                  57
 
 /*
  * Security identifier indices for initial entities
index c10f1fc415026257cdec73e7a1bd99eefb8b876d..c96498a10eb8bb466ba88116faa901af75eb73ff 100644 (file)
@@ -9,8 +9,10 @@
 int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
 int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
 void selinux_xfrm_policy_free(struct xfrm_policy *xp);
+int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
 int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
 void selinux_xfrm_state_free(struct xfrm_state *x);
+int selinux_xfrm_state_delete(struct xfrm_state *x);
 int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir);
 
 /*
@@ -49,7 +51,7 @@ static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
 
 static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
 {
-       return NF_ACCEPT;
+       return 0;
 }
 
 static inline int selinux_socket_getpeer_stream(struct sock *sk)
index a4efc966f065eae8599ee034a3ac760efca0d92f..2e73d3279f2dbd63d0e8a2e67a199410086353b3 100644 (file)
 
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 
+#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
+#define SELINUX_COMPAT_NET_VALUE 0
+#else
+#define SELINUX_COMPAT_NET_VALUE 1
+#endif
+
+int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
+
 static int __init checkreqprot_setup(char *str)
 {
        selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
@@ -45,6 +53,13 @@ static int __init checkreqprot_setup(char *str)
 }
 __setup("checkreqprot=", checkreqprot_setup);
 
+static int __init selinux_compat_net_setup(char *str)
+{
+       selinux_compat_net = simple_strtoul(str,NULL,0) ? 1 : 0;
+       return 1;
+}
+__setup("selinux_compat_net=", selinux_compat_net_setup);
+
 
 static DEFINE_MUTEX(sel_mutex);
 
@@ -85,6 +100,7 @@ enum sel_inos {
        SEL_AVC,        /* AVC management directory */
        SEL_MEMBER,     /* compute polyinstantiation membership decision */
        SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
+       SEL_COMPAT_NET, /* whether to use old compat network packet controls */
 };
 
 #define TMPBUFLEN      12
@@ -364,6 +380,55 @@ static struct file_operations sel_checkreqprot_ops = {
        .write          = sel_write_checkreqprot,
 };
 
+static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
+                                  size_t count, loff_t *ppos)
+{
+       char tmpbuf[TMPBUFLEN];
+       ssize_t length;
+
+       length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
+       return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
+                                   size_t count, loff_t *ppos)
+{
+       char *page;
+       ssize_t length;
+       int new_value;
+
+       length = task_has_security(current, SECURITY__LOAD_POLICY);
+       if (length)
+               return length;
+
+       if (count >= PAGE_SIZE)
+               return -ENOMEM;
+       if (*ppos != 0) {
+               /* No partial writes. */
+               return -EINVAL;
+       }
+       page = (char*)get_zeroed_page(GFP_KERNEL);
+       if (!page)
+               return -ENOMEM;
+       length = -EFAULT;
+       if (copy_from_user(page, buf, count))
+               goto out;
+
+       length = -EINVAL;
+       if (sscanf(page, "%d", &new_value) != 1)
+               goto out;
+
+       selinux_compat_net = new_value ? 1 : 0;
+       length = count;
+out:
+       free_page((unsigned long) page);
+       return length;
+}
+static struct file_operations sel_compat_net_ops = {
+       .read           = sel_read_compat_net,
+       .write          = sel_write_compat_net,
+};
+
 /*
  * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
  */
@@ -1219,6 +1284,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
                [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
                [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
                [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
+               [SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
                /* last one */ {""}
        };
        ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
index c284dbb8b8c02fbba51aa562d5e4fd4551e641f3..e9548bc049e1d9020161b92fb362743ee7261957 100644 (file)
@@ -1980,7 +1980,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
                break;
        case AUDIT_SE_SEN:
        case AUDIT_SE_CLR:
-               level = (op == AUDIT_SE_SEN ?
+               level = (field == AUDIT_SE_SEN ?
                         &ctxt->range.level[0] : &ctxt->range.level[1]);
                switch (op) {
                case AUDIT_EQUAL:
index abe99d8813765a977405de8246d42f9597c34341..6633fb05931353502c350974551a1a1a33cd1bc7 100644 (file)
@@ -132,10 +132,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_us
                goto out;
 
        /*
-        * Does the subject have permission to set security or permission to
-        * do the relabel?
-        * Must be permitted to relabel from default socket type (process type)
-        * to specified context
+        * Does the subject have permission to set security context?
         */
        rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
                          SECCLASS_ASSOCIATION,
@@ -200,6 +197,23 @@ void selinux_xfrm_policy_free(struct xfrm_policy *xp)
                kfree(ctx);
 }
 
+/*
+ * LSM hook implementation that authorizes deletion of labeled policies.
+ */
+int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
+{
+       struct task_security_struct *tsec = current->security;
+       struct xfrm_sec_ctx *ctx = xp->security;
+       int rc = 0;
+
+       if (ctx)
+               rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
+                                 SECCLASS_ASSOCIATION,
+                                 ASSOCIATION__SETCONTEXT, NULL);
+
+       return rc;
+}
+
 /*
  * LSM hook implementation that allocs and transfers sec_ctx spec to
  * xfrm_state.
@@ -292,6 +306,23 @@ u32 selinux_socket_getpeer_dgram(struct sk_buff *skb)
        return SECSID_NULL;
 }
 
+ /*
+  * LSM hook implementation that authorizes deletion of labeled SAs.
+  */
+int selinux_xfrm_state_delete(struct xfrm_state *x)
+{
+       struct task_security_struct *tsec = current->security;
+       struct xfrm_sec_ctx *ctx = x->security;
+       int rc = 0;
+
+       if (ctx)
+               rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
+                                 SECCLASS_ASSOCIATION,
+                                 ASSOCIATION__SETCONTEXT, NULL);
+
+       return rc;
+}
+
 /*
  * LSM hook that controls access to unlabelled packets.  If
  * a xfrm_state is authorizable (defined by macro) then it was
@@ -356,18 +387,12 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
                        struct xfrm_state *x = dst_test->xfrm;
 
                        if (x && selinux_authorizable_xfrm(x))
-                               goto accept;
+                               goto out;
                }
        }
 
        rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
                          ASSOCIATION__SENDTO, NULL);
-       if (rc)
-               goto drop;
-
-accept:
-       return NF_ACCEPT;
-
-drop:
-       return NF_DROP;
+out:
+       return rc;
 }
index 558c6ed443beb1a3a6611f880846a44619f2e69e..080ab036b67a791c49b8ed3073dc63489cea8637 100644 (file)
@@ -98,8 +98,8 @@ config SOUND_HAL2
        tristate "SGI HAL2 sound (EXPERIMENTAL)"
        depends on SOUND_PRIME && SGI_IP22 && EXPERIMENTAL
        help
-         Say Y or M if you have an SGI Indy system and want to be able to
-         use it's on-board A2 audio system.
+         Say Y or M if you have an SGI Indy or Indigo2 system and want to be able to
+         use its on-board A2 audio system.
 
 config SOUND_IT8172
        tristate "IT8172G Sound"