linux-cvs-patches
[Top] [All Lists]

CVS Update@linux-mips.org: linux

To: linux-cvs-patches@linux-mips.org
Subject: CVS Update@linux-mips.org: linux
From: ralf@linux-mips.org
Date: Thu, 19 May 2005 13:09:19 +0100
Reply-to: linux-mips@linux-mips.org
Sender: linux-cvs-patches-bounce@linux-mips.org
CVSROOT:        /home/cvs
Module name:    linux
Changes by:     ralf@ftp.linux-mips.org 05/05/19 13:08:54

Modified files:
        .              : CREDITS MAINTAINERS Makefile 
        Documentation  : 00-INDEX Changes dontdiff 
                         feature-removal-schedule.txt pci.txt 
        Documentation/DocBook: Makefile kernel-api.tmpl 
        Documentation/RCU: RTFP.txt UP.txt checklist.txt listRCU.txt 
                           rcu.txt 
        Documentation/aoe: aoe.txt status.sh 
        Documentation/filesystems: Locking proc.txt 
        Documentation/i386: zero-page.txt 
        Documentation/networking: DLINK.txt netdevices.txt 
        Documentation/power: pci.txt 
        Documentation/s390: cds.txt 
        arch/alpha     : Kconfig 
        arch/alpha/kernel: osf_sys.c ptrace.c systbls.S 
        arch/arm       : Kconfig 
        arch/arm/boot/compressed: head.S 
        arch/arm/common: rtctime.c 
        arch/arm/configs: ixdp2800_defconfig 
        arch/arm/kernel: Makefile asm-offsets.c entry-armv.S 
                         entry-common.S entry-header.S head.S process.c 
                         ptrace.c sys_arm.c traps.c vmlinux.lds.S 
        arch/arm/mach-clps711x: Kconfig 
        arch/arm/mach-footbridge: Kconfig 
        arch/arm/mach-imx: Kconfig generic.c 
        arch/arm/mach-integrator: core.c integrator_cp.c leds.c time.c 
        arch/arm/mach-ixp2000: ixdp2800.c pci.c 
        arch/arm/mach-ixp4xx: common-pci.c 
        arch/arm/mach-pxa: generic.c sleep.S 
        arch/arm/mm    : Kconfig abort-ev6.S mm-armv.c 
        arch/arm26     : Kconfig 
        arch/arm26/kernel: ptrace.c 
        arch/arm26/mm  : small_page.c 
        arch/cris/arch-v10/kernel: ptrace.c 
        arch/frv/kernel: ptrace.c 
        arch/h8300/kernel: ptrace.c 
        arch/i386      : Kconfig Makefile 
        arch/i386/boot : bootsect.S setup.S video.S 
        arch/i386/boot/compressed: misc.c 
        arch/i386/kernel: Makefile apic.c entry.S head.S i386_ksyms.c 
                          io_apic.c kprobes.c nmi.c process.c ptrace.c 
                          reboot.c smpboot.c time.c time_hpet.c traps.c 
                          vm86.c 
        arch/i386/kernel/acpi: boot.c 
        arch/i386/kernel/cpu: amd.c proc.c 
        arch/i386/kernel/cpu/mtrr: cyrix.c generic.c main.c 
        arch/i386/kernel/timers: timer_hpet.c timer_tsc.c 
        arch/i386/oprofile: nmi_timer_int.c 
        arch/i386/pci  : irq.c 
        arch/ia64      : Kconfig 
        arch/ia64/configs: sn2_defconfig tiger_defconfig 
        arch/ia64/hp/common: sba_iommu.c 
        arch/ia64/ia32 : ia32_signal.c 
        arch/ia64/kernel: acpi.c entry.S fsys.S head.S iosapic.c 
                          irq_ia64.c mca_asm.S mca_drv.c mca_drv_asm.S 
                          perfmon.c perfmon_default_smpl.c process.c 
                          ptrace.c setup.c signal.c smpboot.c sys_ia64.c 
                          unwind.c 
        arch/ia64/lib  : flush.S memcpy_mck.S memset.S 
        arch/ia64/mm   : contig.c discontig.c fault.c init.c 
        arch/ia64/sn/include/pci: pcibr_provider.h 
        arch/ia64/sn/kernel: Makefile bte.c bte_error.c huberror.c 
                             io_init.c irq.c mca.c setup.c 
        arch/ia64/sn/kernel/sn2: sn_hwperf.c 
        arch/ia64/sn/pci: Makefile pci_dma.c 
        arch/ia64/sn/pci/pcibr: pcibr_ate.c pcibr_dma.c pcibr_provider.c 
                                pcibr_reg.c 
        arch/m32r/kernel: ptrace.c 
        arch/m68k/kernel: ptrace.c 
        arch/m68knommu : Kconfig 
        arch/m68knommu/kernel: ptrace.c 
        arch/mips      : defconfig 
        arch/mips/configs: atlas_defconfig capcella_defconfig 
                           cobalt_defconfig db1000_defconfig 
                           db1100_defconfig db1500_defconfig 
                           db1550_defconfig ddb5476_defconfig 
                           ddb5477_defconfig decstation_defconfig 
                           e55_defconfig ev64120_defconfig 
                           ev96100_defconfig ip22_defconfig 
                           ip27_defconfig ip32_defconfig 
                           it8172_defconfig ivr_defconfig 
                           jaguar-atx_defconfig jmr3927_defconfig 
                           lasat200_defconfig malta_defconfig 
                           mpc30x_defconfig ocelot_3_defconfig 
                           ocelot_c_defconfig ocelot_defconfig 
                           ocelot_g_defconfig osprey_defconfig 
                           pb1100_defconfig pb1500_defconfig 
                           pb1550_defconfig rm200_defconfig 
                           sb1250-swarm_defconfig sead_defconfig 
                           tb0226_defconfig tb0229_defconfig 
                           workpad_defconfig yosemite_defconfig 
        arch/mips/kernel: ptrace.c syscall.c 
        arch/parisc    : Kconfig 
        arch/parisc/kernel: ptrace.c sys_parisc.c syscall_table.S 
        arch/ppc       : Kconfig Makefile 
        arch/ppc/boot/images: Makefile 
        arch/ppc/kernel: Makefile align.c cpu_setup_6xx.S entry.S head.S 
                         head_44x.S head_booke.h head_fsl_booke.S misc.S 
                         pci.c ptrace.c setup.c signal.c traps.c 
                         vmlinux.lds.S 
        arch/ppc/platforms: chrp_pci.c chrp_setup.c pmac_cache.S 
                            pmac_feature.c pmac_low_i2c.c pmac_sleep.S 
                            pmac_smp.c pmac_time.c radstone_ppc7d.c 
                            radstone_ppc7d.h 
        arch/ppc/platforms/4xx: ebony.c luan.c ocotea.c 
        arch/ppc/syslib: cpm2_pic.c m8260_pci.c mpc52xx_pci.c 
                         ppc85xx_setup.c 
        arch/ppc64     : Kconfig Kconfig.debug Makefile 
        arch/ppc64/boot: addnote.c main.c 
        arch/ppc64/kernel: HvLpEvent.c misc.S nvram.c pSeries_hvCall.S 
                           pSeries_smp.c pci.c prom.c prom_init.c 
                           ptrace.c ptrace32.c rtas_flash.c scanlog.c 
                           signal.c signal32.c smp.c time.c xics.c 
        arch/ppc64/kernel/vdso32: Makefile cacheflush.S gettimeofday.S 
                                  vdso32.lds.S 
        arch/ppc64/kernel/vdso64: Makefile cacheflush.S vdso64.lds.S 
        arch/ppc64/mm  : hash_low.S hash_native.c hash_utils.c 
                         hugetlbpage.c imalloc.c init.c slb.c stab.c 
        arch/ppc64/xmon: ppc-opc.c 
        arch/s390      : defconfig 
        arch/s390/kernel: compat_ioctl.c ptrace.c s390_ksyms.c setup.c 
                          time.c vtime.c 
        arch/s390/mm   : cmm.c init.c 
        arch/sh        : Kconfig 
        arch/sh/kernel : ptrace.c 
        arch/sh64/kernel: ptrace.c sys_sh64.c syscalls.S 
        arch/sparc/kernel: process.c ptrace.c sparc_ksyms.c 
        arch/sparc/prom: memory.c sun4prom.c 
        arch/sparc64   : Kconfig 
        arch/sparc64/kernel: irq.c process.c ptrace.c sparc64_ksyms.c 
                             time.c 
        arch/sparc64/mm: init.c 
        arch/um        : Kconfig Kconfig_i386 Kconfig_x86_64 Makefile 
                         Makefile-i386 Makefile-x86_64 defconfig 
        arch/um/drivers: chan_kern.c line.c ssl.c stdio_console.c 
                         ubd_kern.c xterm_kern.c 
        arch/um/include: kern_util.h line.h os.h skas_ptrace.h 
                         user_util.h 
        arch/um/include/sysdep-i386: checksum.h ptrace.h sigcontext.h 
                                     signal.h syscalls.h 
        arch/um/include/sysdep-x86_64: ptrace.h sigcontext.h signal.h 
                                       syscalls.h 
        arch/um/kernel : Makefile irq.c ksyms.c process.c process_kern.c 
                         ptrace.c sigio_user.c syscall_kern.c 
                         time_kern.c trap_kern.c trap_user.c um_arch.c 
        arch/um/kernel/skas: process.c process_kern.c trap_user.c 
                             uaccess.c 
        arch/um/kernel/skas/include: mode_kern-skas.h skas.h 
                                     uaccess-skas.h 
        arch/um/kernel/skas/util: Makefile mk_ptregs-i386.c 
                                  mk_ptregs-x86_64.c 
        arch/um/kernel/tt: Makefile mem.c process_kern.c syscall_user.c 
                           tracer.c trap_user.c 
        arch/um/kernel/tt/include: mode_kern-tt.h uaccess-tt.h 
        arch/um/os-Linux: process.c signal.c 
        arch/um/os-Linux/sys-i386: registers.c 
        arch/um/os-Linux/util: Makefile mk_user_constants.c 
        arch/um/scripts: Makefile.rules 
        arch/um/sys-i386: Makefile checksum.S delay.c ksyms.c ldt.c 
                          ptrace.c signal.c 
        arch/um/sys-i386/util: Makefile mk_sc.c 
        arch/um/sys-ppc: ptrace.c 
        arch/um/sys-x86_64: Makefile delay.c ptrace.c signal.c 
                            syscalls.c 
        arch/um/sys-x86_64/util: Makefile mk_sc.c 
        arch/um/util   : Makefile 
        arch/v850/kernel: ptrace.c 
        arch/x86_64    : Kconfig 
        arch/x86_64/boot: bootsect.S setup.S 
        arch/x86_64/ia32: vsyscall.lds 
        arch/x86_64/kernel: e820.c early_printk.c entry.S head64.c 
                            io_apic.c kprobes.c module.c nmi.c process.c 
                            ptrace.c setup.c setup64.c signal.c 
                            sys_x86_64.c x8664_ksyms.c 
        arch/x86_64/lib: getuser.S putuser.S 
        crypto         : Kconfig 
        drivers/acpi   : processor_idle.c scan.c 
        drivers/atm    : eni.c fore200e.c he.c he.h 
        drivers/base   : bus.c core.c platform.c 
        drivers/block  : DAC960.c DAC960.h Kconfig floppy.c genhd.c 
                         nbd.c noop-iosched.c 
        drivers/block/aoe: aoe.h aoeblk.c aoedev.c aoenet.c 
        drivers/cdrom  : cdrom.c cdu31a.c mcdx.c sbpcd.c 
        drivers/char   : Kconfig Makefile dtlk.c hangcheck-timer.c 
                         keyboard.c s3c2410-rtc.c snsc.c snsc.h sonypi.c 
                         specialix.c stallion.c tty_io.c vt_ioctl.c 
        drivers/char/agp: ali-agp.c amd-k7-agp.c amd64-agp.c ati-agp.c 
                          backend.c efficeon-agp.c frontend.c 
                          nvidia-agp.c sis-agp.c sworks-agp.c via-agp.c 
        drivers/char/ipmi: ipmi_bt_sm.c ipmi_msghandler.c ipmi_si_intf.c 
                           ipmi_si_sm.h ipmi_watchdog.c 
        drivers/char/rio: rio_linux.c 
        drivers/char/tpm: tpm.c 
        drivers/cpufreq: cpufreq.c 
        drivers/i2c/busses: Kconfig i2c-mpc.c 
        drivers/ide/pci: sis5513.c 
        drivers/ide/ppc: pmac.c 
        drivers/ieee1394: ohci1394.c 
        drivers/infiniband/hw/mthca: mthca_memfree.c 
        drivers/input/joystick: spaceorb.c 
        drivers/input/keyboard: atkbd.c 
        drivers/isdn/capi: capi.c kcapi_proc.c 
        drivers/isdn/divert: isdn_divert.c 
        drivers/isdn/hisax: hfc4s8s_l1.c 
        drivers/isdn/i4l: isdn_ppp.c 
        drivers/macintosh: adbhid.c via-pmu.c 
        drivers/md     : dm-crypt.c dm-emc.c dm-hw-handler.c dm-mpath.c 
                         dm-path-selector.c dm-table.c dm-zero.c dm.c 
                         md.c multipath.c raid1.c raid10.c raid5.c 
                         raid6main.c 
        drivers/media/common: ir-common.c 
        drivers/media/dvb/frontends: cx22702.c cx22702.h 
        drivers/media/video: Kconfig bttv-driver.c bttv-i2c.c msp3400.c 
                             tuner-core.c tvaudio.c 
        drivers/media/video/cx88: cx88-core.c cx88-dvb.c cx88-i2c.c 
                                  cx88-vbi.c cx88-video.c cx88.h 
        drivers/media/video/saa7134: saa6752hs.c saa7134-cards.c 
                                     saa7134-dvb.c saa7134-empress.c 
                                     saa7134-input.c 
        drivers/mmc    : Kconfig 
        drivers/net    : 3c59x.c Kconfig Space.c gt96100eth.h hp100.c 
                         loopback.c mv643xx_eth.c ppp_deflate.c 
                         ppp_generic.c r8169.c slip.c sunbmac.c sunhme.c 
                         sunlance.c sunqe.c tg3.c tg3.h 
        drivers/net/appletalk: Kconfig cops.c cops_ffdrv.h cops_ltdrv.h 
                               ltpc.c 
        drivers/net/arcnet: capmode.c 
        drivers/net/hamradio: 6pack.c Kconfig baycom_epp.c bpqether.c 
                              dmascc.c hdlcdrv.c mkiss.c scc.c yam.c 
        drivers/net/irda: Kconfig 
        drivers/net/wan: Kconfig cycx_x25.c pc300_drv.c pc300_tty.c 
                         sdla_chdlc.c x25_asy.c 
        drivers/oprofile: oprofile_files.c 
        drivers/parport: Kconfig parport_pc.c 
        drivers/pci    : hotplug.c msi.c pci-acpi.c pci-driver.c 
                         pci-sysfs.c pci.c probe.c proc.c quirks.c rom.c 
        drivers/pci/hotplug: ibmphp.h ibmphp_hpc.c ibmphp_pci.c 
                             pci_hotplug.h pciehp_core.c 
                             pcihp_skeleton.c 
        drivers/pcmcia : pd6729.c ti113x.h 
        drivers/pnp    : manager.c 
        drivers/pnp/pnpacpi: rsparser.c 
        drivers/pnp/pnpbios: rsparser.c 
        drivers/s390/block: dasd.c dasd_cmb.c dasd_devmap.c dasd_eckd.c 
                            dasd_genhd.c dasd_int.h dasd_ioctl.c 
                            dasd_proc.c 
        drivers/s390/cio: airq.c cio.c device_ops.c qdio.h 
        drivers/s390/crypto: z90main.c 
        drivers/s390/net: smsgiucv.c smsgiucv.h 
        drivers/s390/scsi: zfcp_aux.c zfcp_def.h 
        drivers/sbus/char: rtc.c 
        drivers/scsi   : Kconfig NCR53C9x.c esp.c pas16.c pluto.c scsi.c 
                         scsi_error.c scsi_scan.c scsi_transport_spi.c 
                         sr_ioctl.c sym53c416.c ultrastor.c 
        drivers/scsi/aacraid: linit.c 
        drivers/scsi/aic7xxx: aic7xxx_osm.c aic7xxx_osm.h 
        drivers/scsi/qla2xxx: qla_attr.c qla_gbl.h qla_os.c qla_sup.c 
        drivers/scsi/sym53c8xx_2: sym_glue.c 
        drivers/serial : 21285.c 8250.c 8250_hp300.c 8250_pci.c 
                         amba-pl010.c amba-pl011.c clps711x.c imx.c 
                         ioc4_serial.c mpsc.c mpsc.h s3c2410.c sa1100.c 
                         serial_cs.c serial_lh7a40x.c sn_console.c 
                         sunsab.c sunsu.c 
        drivers/serial/jsm: jsm.h jsm_neo.c jsm_tty.c 
        drivers/telephony: ixj.c ixj.h 
        drivers/usb/core: message.c urb.c usb.c 
        drivers/usb/gadget: ether.c inode.c lh7a40x_udc.c serial.c 
        drivers/usb/host: ehci-hcd.c ehci-hub.c ehci.h hc_crisv10.c 
                          sl811-hcd.c 
        drivers/usb/image: mdc800.c microtek.c 
        drivers/usb/input: aiptek.c ati_remote.c mtouchusb.c usbkbd.c 
        drivers/usb/media: ov511.c sn9c102_core.c sn9c102_sensor.h 
        drivers/usb/media/pwc: pwc-ctrl.c pwc-if.c pwc-ioctl.h pwc.h 
        drivers/usb/misc: legousbtower.c 
        drivers/usb/misc/sisusbvga: sisusb.c 
        drivers/usb/net: pegasus.c usbnet.c zd1201.c 
        drivers/usb/serial: Kconfig Makefile cypress_m8.c ftdi_sio.c 
                            ftdi_sio.h io_usbvend.h keyspan_usa90msg.h 
        drivers/usb/storage: debug.c shuttle_usbat.c unusual_devs.h 
        drivers/video  : Kconfig Makefile amba-clcd.c cyber2000fb.c 
                         fbcmap.c fbmem.c fbmon.c fbsysfs.c imsttfb.c 
                         radeonfb.c tcx.c tdfxfb.c tgafb.c vesafb.c 
        drivers/video/aty: radeon_base.c 
        drivers/video/console: fbcon.c vgacon.c 
        drivers/video/i810: i810_main.c 
        drivers/video/intelfb: intelfbdrv.c 
        drivers/video/logo: Kconfig 
        drivers/video/nvidia: nvidia.c 
        drivers/video/savage: savagefb_driver.c 
        drivers/video/sis: init.c init.h init301.c init301.h sis_main.c 
        fs             : aio.c bad_inode.c binfmt_elf.c bio.c 
                         block_dev.c buffer.c char_dev.c compat.c 
                         dcache.c eventpoll.c exec.c fcntl.c 
                         fs-writeback.c inode.c locks.c mbcache.c 
                         mpage.c namei.c select.c seq_file.c 
        fs/afs         : file.c 
        fs/autofs4     : autofs_i.h expire.c inode.c waitq.c 
        fs/cifs        : AUTHORS CHANGES README TODO cifs_debug.c 
                         cifs_fs_sb.h cifs_unicode.c cifsencrypt.c 
                         cifsfs.c cifsfs.h cifsglob.h cifspdu.h 
                         cifsproto.h cifssmb.c connect.c dir.c fcntl.c 
                         file.c inode.c ioctl.c link.c misc.c netmisc.c 
                         readdir.c smberr.h transport.c xattr.c 
        fs/ext3        : inode.c 
        fs/hfs         : mdb.c super.c 
        fs/hfsplus     : super.c 
        fs/hostfs      : hostfs_kern.c 
        fs/isofs       : compress.c dir.c export.c inode.c joliet.c 
                         namei.c rock.c util.c 
        fs/jffs2       : compr_rubin.c compr_zlib.c file.c 
        fs/jfs         : inode.c jfs_dmap.c jfs_dtree.c jfs_imap.c 
                         jfs_incore.h jfs_logmgr.c jfs_logmgr.h 
                         jfs_metapage.c jfs_metapage.h jfs_mount.c 
                         jfs_txnmgr.c jfs_umount.c jfs_xtree.c resize.c 
                         super.c 
        fs/nfs         : idmap.c inode.c 
        fs/nls         : nls_base.c 
        fs/partitions  : msdos.c 
        fs/proc        : base.c 
        fs/reiserfs    : bitmap.c dir.c file.c inode.c item_ops.c 
                         journal.c namei.c objectid.c procfs.c stree.c 
                         super.c 
        fs/sysfs       : file.c 
        fs/udf         : file.c inode.c udftime.c 
        fs/xfs         : Makefile xfs_dfrag.c xfs_iget.c xfs_inode.c 
                         xfs_inode.h xfs_iomap.c xfs_iomap.h xfs_mount.c 
                         xfs_mount.h xfs_types.h xfs_utils.c xfs_utils.h 
                         xfs_vfsops.c xfs_vnodeops.c 
        fs/xfs/linux-2.6: xfs_aops.c xfs_buf.c xfs_file.c xfs_lrw.c 
                          xfs_vnode.c xfs_vnode.h 
        include/asm-alpha: bug.h errno.h siginfo.h signal.h unistd.h 
        include/asm-arm: bug.h io.h pgtable.h processor.h rtc.h signal.h 
                         string.h thread_info.h unistd.h 
        include/asm-arm/arch-cl7500: vmalloc.h 
        include/asm-arm/arch-clps711x: vmalloc.h 
        include/asm-arm/arch-ebsa110: vmalloc.h 
        include/asm-arm/arch-ebsa285: vmalloc.h 
        include/asm-arm/arch-epxa10db: vmalloc.h 
        include/asm-arm/arch-h720x: vmalloc.h 
        include/asm-arm/arch-imx: vmalloc.h 
        include/asm-arm/arch-integrator: cm.h platform.h vmalloc.h 
        include/asm-arm/arch-iop3xx: vmalloc.h 
        include/asm-arm/arch-ixp2000: platform.h vmalloc.h 
        include/asm-arm/arch-ixp4xx: vmalloc.h 
        include/asm-arm/arch-l7200: vmalloc.h 
        include/asm-arm/arch-lh7a40x: vmalloc.h 
        include/asm-arm/arch-omap: vmalloc.h 
        include/asm-arm/arch-pxa: vmalloc.h 
        include/asm-arm/arch-rpc: vmalloc.h 
        include/asm-arm/arch-s3c2410: regs-iis.h regs-mem.h regs-spi.h 
                                      uncompress.h vmalloc.h 
        include/asm-arm/arch-sa1100: vmalloc.h 
        include/asm-arm/arch-shark: vmalloc.h 
        include/asm-arm/arch-versatile: vmalloc.h 
        include/asm-arm/hardware: amba_clcd.h clock.h 
        include/asm-arm26: bug.h signal.h 
        include/asm-cris: page.h signal.h 
        include/asm-frv: bug.h pgtable.h signal.h 
        include/asm-generic: bug.h errno.h resource.h sections.h 
                             siginfo.h unaligned.h 
        include/asm-h8300: signal.h 
        include/asm-i386: apic.h bug.h checksum.h cpufeature.h e820.h 
                          floppy.h hpet.h module.h pgtable.h setup.h 
                          signal.h string.h system.h 
        include/asm-ia64: bitops.h bug.h gcc_intrin.h hw_irq.h pal.h 
                          perfmon.h pgalloc.h processor.h sal.h 
                          siginfo.h signal.h smp.h 
        include/asm-ia64/sn: addrs.h arch.h bte.h geo.h l1.h nodepda.h 
                             pda.h shub_mmr.h shubio.h sn_cpuid.h 
                             sn_sal.h types.h 
        include/asm-m32r: signal.h 
        include/asm-m68k: bug.h signal.h 
        include/asm-m68knommu: MC68328.h MC68EZ328.h MC68VZ328.h 
                               signal.h 
        include/asm-mips: bug.h siginfo.h signal.h 
        include/asm-parisc: bug.h errno.h floppy.h signal.h uaccess.h 
        include/asm-ppc: bug.h hydra.h pci-bridge.h pmac_feature.h 
                         reg_booke.h sigcontext.h signal.h 
        include/asm-ppc64: a.out.h bug.h elf.h mmu.h mmu_context.h 
                           page.h pgalloc.h pgtable.h signal.h 
                           spinlock.h xics.h 
        include/asm-s390: bug.h cmb.h debug.h page.h processor.h 
                          ptrace.h siginfo.h signal.h 
        include/asm-sh : bug.h checksum.h floppy.h signal.h 
        include/asm-sh64: bug.h checksum.h signal.h 
        include/asm-sparc: bug.h errno.h floppy.h mxcc.h signal.h 
                           uaccess.h 
        include/asm-sparc64: bug.h errno.h mostek.h parport.h pgalloc.h 
                             pgtable.h siginfo.h signal.h spinlock.h 
        include/asm-um : archparam-i386.h archparam-ppc.h 
                         archparam-x86_64.h common.lds.S delay.h 
                         fixmap.h ipc.h linkage.h page.h 
                         pgtable-3level.h pgtable.h processor-generic.h 
                         processor-i386.h processor-x86_64.h 
                         ptrace-i386.h ptrace-x86_64.h setup.h 
                         thread_info.h 
        include/asm-v850: bug.h signal.h 
        include/asm-x86_64: apic.h bootsetup.h bug.h cpufeature.h e820.h 
                            floppy.h siginfo.h signal.h unistd.h 
        include/linux  : audit.h auto_fs4.h awe_voice.h binfmts.h 
                         compiler-gcc2.h compiler.h cpufreq.h edd.h 
                         etherdevice.h fb.h fddidevice.h fs.h gfp.h 
                         hippidevice.h if.h if_arp.h if_ltalk.h input.h 
                         iso_fs.h ixjuser.h kernel.h kprobes.h mm.h 
                         mpage.h net.h netdevice.h netfilter_ipv4.h 
                         netlink.h page-flags.h pci.h pci_ids.h 
                         rcupdate.h reiserfs_acl.h reiserfs_fs.h 
                         reiserfs_xattr.h rtnetlink.h sched.h signal.h 
                         skbuff.h slab.h sockios.h soundcard.h 
                         syscalls.h sysctl.h trdevice.h xfrm.h 
        include/net    : addrconf.h ax25.h icmp.h ip.h ipv6.h 
                         pkt_sched.h route.h sock.h tcp.h udp.h xfrm.h 
        include/net/sctp: sm.h structs.h 
        include/video  : edid.h tdfx.h 
        init           : Kconfig 
        ipc            : mqueue.c shm.c 
        kernel         : Makefile audit.c auditsc.c exit.c futex.c 
                         itimer.c kallsyms.c kprobes.c kthread.c 
                         module.c panic.c printk.c profile.c ptrace.c 
                         rcupdate.c sched.c signal.c stop_machine.c 
                         sys.c sys_ni.c sysctl.c time.c timer.c 
        kernel/power   : swsusp.c 
        lib            : Kconfig.debug kobject.c rwsem-spinlock.c 
                         rwsem.c sort.c string.c 
        mm             : filemap.c highmem.c mempolicy.c mempool.c 
                         mmap.c mremap.c page-writeback.c page_alloc.c 
                         rmap.c slab.c swap_state.c truncate.c vmalloc.c 
        net            : socket.c 
        net/802        : fddi.c hippi.c 
        net/8021q      : vlanproc.c 
        net/appletalk  : dev.c 
        net/atm        : common.c resources.c signaling.c 
        net/ax25       : af_ax25.c ax25_ds_subr.c ax25_ip.c ax25_out.c 
                         ax25_subr.c 
        net/bluetooth  : af_bluetooth.c hci_conn.c hci_core.c 
                         hci_event.c hci_sock.c l2cap.c sco.c 
        net/bluetooth/bnep: sock.c 
        net/bluetooth/cmtp: capi.c core.c sock.c 
        net/bluetooth/hidp: core.c sock.c 
        net/bluetooth/rfcomm: sock.c 
        net/core       : datagram.c dev.c iovec.c link_watch.c 
                         neighbour.c netfilter.c rtnetlink.c scm.c 
                         skbuff.c sock.c stream.c 
        net/decnet     : dn_dev.c 
        net/decnet/netfilter: dn_rtmsg.c 
        net/ethernet   : eth.c 
        net/ipv4       : af_inet.c devinet.c ip_input.c ip_output.c 
                         multipath_wrandom.c protocol.c raw.c route.c 
                         tcp.c tcp_diag.c tcp_input.c tcp_ipv4.c 
                         tcp_minisocks.c tcp_output.c tcp_timer.c udp.c 
                         xfrm4_policy.c 
        net/ipv4/netfilter: ip_conntrack_ftp.c ip_conntrack_proto_tcp.c 
                            ip_conntrack_standalone.c ip_nat_core.c 
                            ip_nat_standalone.c ip_queue.c iptable_raw.c 
        net/ipv6       : addrconf.c af_inet6.c exthdrs_core.c icmp.c 
                         raw.c route.c tcp_ipv6.c xfrm6_policy.c 
        net/ipv6/netfilter: ip6_queue.c 
        net/irda       : irda_device.c 
        net/netlink    : af_netlink.c 
        net/packet     : af_packet.c 
        net/sched      : Kconfig Makefile act_api.c cls_fw.c sch_api.c 
                         sch_generic.c sch_htb.c sch_netem.c 
        net/sctp       : endpointola.c ipv6.c output.c protocol.c 
                         sm_make_chunk.c sm_statefuns.c socket.c 
                         sysctl.c 
        net/sunrpc     : xdr.c 
        net/unix       : af_unix.c 
        net/wanrouter  : wanmain.c 
        net/xfrm       : xfrm_policy.c xfrm_state.c xfrm_user.c 
        scripts        : kallsyms.c kernel-doc patch-kernel 
        scripts/kconfig: Makefile conf.c confdata.c gconf.c lkc.h 
                         mconf.c menu.c qconf.cc 
        scripts/mod    : file2alias.c 
        security/selinux: hooks.c nlmsgtab.c 
        security/selinux/include: av_perm_to_string.h av_permissions.h 
        sound/isa      : Kconfig 
        sound/oss      : ac97_codec.c msnd_pinnacle.c sonicvibes.c 
        sound/pci      : intel8x0.c via82xx.c 
        sound/pci/hda  : hda_intel.c 
        sound/ppc      : Kconfig Makefile pmac.c pmac.h powermac.c 
                         tumbler.c 
Added files:
        Documentation/DocBook: stylesheet.xsl 
        arch/i386/kernel: reboot_fixups.c syscall_table.S 
        arch/ia64/sn/kernel: tiocx.c xp_main.c xp_nofault.S xpc.h 
                             xpc_channel.c xpc_main.c xpc_partition.c 
                             xpnet.c 
        arch/ia64/sn/pci: tioca_provider.c 
        arch/ppc/kernel: fpu.S 
        arch/ppc64/kernel/vdso32: note.S 
        arch/ppc64/kernel/vdso64: note.S 
        arch/um/include: common-offsets.h 
        arch/um/include/sysdep-i386: faultinfo.h skas_ptrace.h 
        arch/um/include/sysdep-ia64: skas_ptrace.h 
        arch/um/include/sysdep-ppc: skas_ptrace.h 
        arch/um/include/sysdep-x86_64: faultinfo.h skas_ptrace.h 
        arch/um/kernel : vmlinux.lds.S 
        arch/um/sys-i386: kernel-offsets.c sys_call_table.S 
                          user-offsets.c 
        arch/um/sys-i386/util: mk_thread.c 
        arch/um/sys-x86_64: kernel-offsets.c ksyms.c syscall_table.c 
                            um_module.c user-offsets.c 
        arch/um/sys-x86_64/util: mk_thread.c 
        arch/um/util   : mk_constants.c mk_task.c 
        drivers/char   : mbcs.c mbcs.h snsc_event.c 
        drivers/usb/serial: airprime.c hp4x.c 
        drivers/video  : imxfb.c imxfb.h 
        fs/isofs       : isofs.h 
        include/asm-arm/arch-imx: imxfb.h 
        include/asm-generic: signal.h 
        include/asm-ia64/sn: pcibus_provider_defs.h pcidev.h tioca.h 
                             tioca_provider.h tiocx.h xp.h 
        include/asm-ppc64: imalloc.h 
        include/asm-um : elf-i386.h elf-ppc.h elf-x86_64.h 
        include/linux  : patchkey.h reboot_fixups.h 
        include/linux/tc_act: tc_defact.h 
        include/net    : act_generic.h 
        include/net/tc_act: tc_defact.h 
        net/sched      : simple.c 
        scripts/kconfig: POTFILES.in kxgettext.c 
        sound/ppc      : toonie.c 
Removed files:
        Documentation/BK-usage: 00-INDEX bk-kernel-howto.txt bk-make-sum 
                                bksend bz64wrap cpcset cset-to-linus 
                                csets-to-patches gcapatch unbz64wrap 
        Documentation/DocBook: tulip-user.tmpl via-audio.tmpl 
        arch/ia64/sn/include/pci: pcibus_provider_defs.h pcidev.h 
        arch/ppc64/boot: start.c 
        arch/um/kernel : sys_call_table.c 
        arch/um/sys-i386/util: mk_thread_kern.c mk_thread_user.c 
        arch/um/sys-x86_64/util: mk_thread_kern.c mk_thread_user.c 
        arch/um/util   : mk_constants_kern.c mk_constants_user.c 
                         mk_task_kern.c mk_task_user.c 
        drivers/video/intelfb: intelfbdrv.h 
        include/asm-ia64/sn: fetchop.h sn_fru.h sndrv.h 
        include/linux  : iso_fs_i.h iso_fs_sb.h 
        scripts        : makeman split-man 

Log message:
        Merge with Linux 2.6.12-rc4.

diff -urN linux/CREDITS linux/CREDITS
--- linux/CREDITS       2005/04/29 11:14:59     1.142
+++ linux/CREDITS       2005/05/19 12:08:04     1.143
@@ -339,7 +339,7 @@
 D: dsp56k device driver
 
 N: Ross Biro
-E: bir7@leland.Stanford.Edu
+E: ross.biro@gmail.com
 D: Original author of the Linux networking code
 
 N: Anton Blanchard
diff -urN linux/MAINTAINERS linux/MAINTAINERS
--- linux/MAINTAINERS   2005/04/29 11:14:59     1.179
+++ linux/MAINTAINERS   2005/05/19 12:08:04     1.180
@@ -1699,7 +1699,9 @@
 M:     proski@gnu.org
 P:     David Gibson
 M:     hermes@gibson.dropbear.id.au
-W:     http://www.ozlabs.org/people/dgibson/dldwd
+L:     orinoco-users@lists.sourceforge.net
+L:     orinoco-devel@lists.sourceforge.net
+W:     http://www.nongnu.org/orinoco/
 S:     Maintained
 
 PARALLEL PORT SUPPORT
@@ -2113,6 +2115,13 @@
 L:     alsa-devel@alsa-project.org
 S:     Maintained
 
+TPM DEVICE DRIVER
+P:     Kylene Hall
+M:     kjhall@us.ibm.com
+W:     http://tpmdd.sourceforge.net
+L:     tpmdd-devel@lists.sourceforge.net
+S:     Maintained
+
 UltraSPARC (sparc64):
 P:     David S. Miller
 M:     davem@davemloft.net
diff -urN linux/Makefile linux/Makefile
--- linux/Makefile      2005/04/29 11:14:59     1.250
+++ linux/Makefile      2005/05/19 12:08:04     1.251
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 12
-EXTRAVERSION =-rc3
+EXTRAVERSION =-rc4
 NAME=Woozy Numbat
 
 # *DOCUMENTATION*
@@ -330,9 +330,7 @@
 PERL           = perl
 CHECK          = sparse
 
-NOSTDINC_FLAGS  = -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__
-CHECKFLAGS     += $(NOSTDINC_FLAGS)
 MODFLAGS       = -DMODULE
 CFLAGS_MODULE   = $(MODFLAGS)
 AFLAGS_MODULE   = $(MODFLAGS)
@@ -529,6 +527,10 @@
 
 include $(srctree)/arch/$(ARCH)/Makefile
 
+# arch Makefile may override CC so keep this after arch Makefile is included
+NOSTDINC_FLAGS := -nostdinc -isystem $(shell $(CC) -print-file-name=include)
+CHECKFLAGS     += $(NOSTDINC_FLAGS)
+
 # warn about C99 declaration after statement
 #CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
 
@@ -1186,8 +1188,8 @@
 quiet_cmd_tags = MAKE   $@
 define cmd_tags
        rm -f $@; \
-       CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I 
__initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL"`; \
-       $(all-sources) | xargs ctags $$CTAGSF -a --extra=+f
+       CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I 
__initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
+       $(all-sources) | xargs ctags $$CTAGSF -a
 endef
 
 TAGS: FORCE
diff -urN linux/Documentation/00-INDEX linux/Documentation/00-INDEX
--- linux/Documentation/00-INDEX        2005/01/13 14:05:14     1.26
+++ linux/Documentation/00-INDEX        2005/05/19 12:08:05     1.27
@@ -12,8 +12,6 @@
 
 00-INDEX
        - this file.
-BK-usage/
-       - directory with info on BitKeeper.
 BUG-HUNTING
        - brute force method of doing binary search of patches to find bug.
 Changes
diff -urN linux/Documentation/Changes linux/Documentation/Changes
--- linux/Documentation/Changes 2005/03/18 17:36:42     1.82
+++ linux/Documentation/Changes 2005/05/19 12:08:05     1.83
@@ -357,14 +357,14 @@
 ----------
 o  <http://sourceforge.net/projects/linuxquota/>
 
-Jade
-----
-o  <ftp://ftp.jclark.com/pub/jade/jade-1.2.1.tar.gz>
-
 DocBook Stylesheets
 -------------------
 o  <http://nwalsh.com/docbook/dsssl/>
 
+XMLTO XSLT Frontend
+-------------------
+o  <http://cyberelk.net/tim/xmlto/>
+
 Intel P6 microcode
 ------------------
 o  <http://www.urbanmyth.org/microcode/>
diff -urN linux/Documentation/dontdiff linux/Documentation/dontdiff
--- linux/Documentation/dontdiff        2005/04/29 11:14:59     1.1
+++ linux/Documentation/dontdiff        2005/05/19 12:08:05     1.2
@@ -1,137 +1,140 @@
-.*
+*.a
+*.aux
+*.bin
+*.cpio
+*.css
+*.dvi
+*.eps
+*.gif
+*.grep
+*.grp
+*.gz
+*.html
+*.jpeg
+*.ko
+*.log
+*.lst
+*.mod.c
+*.o
+*.orig
+*.out
+*.pdf
+*.png
+*.ps
+*.rej
+*.s
+*.sgml
+*.so
+*.tex
+*.ver
+*.xml
+*_MODULES
+*_vga16.c
+*cscope*
 *~
+.*
+.cscope
+53c700_d.h
 53c8xx_d.h*
-*.a
+BitKeeper
+COPYING
+CREDITS
+CVS
+ChangeSet
+Kerntypes
+MODS.txt
+Module.symvers
+PENDING
+SCCS
+System.map*
+TAGS
 aic7*reg.h*
-aic7*seq.h*
 aic7*reg_print.c*
-53c700_d.h
+aic7*seq.h*
 aicasm
 aicdb.h*
 asm
 asm_offsets.*
 autoconf.h*
-*.aux
 bbootsect
-*.bin
 bin2c
 binkernel.spec
-BitKeeper
 bootsect
 bsetup
 btfixupprep
 build
 bvmlinux
 bzImage*
-ChangeSet
 classlist.h*
-compile.h*
 comp*.log
+compile.h*
 config
 config-*
 config_data.h*
 conmakehash
 consolemap_deftbl.c*
-COPYING
-CREDITS
-.cscope
-*cscope*
+crc32table.h*
 cscope.*
-*.out
-*.css
-CVS
 defkeymap.c*
 devlist.h*
 docproc
 dummy_sym.c*
-*.dvi
-*.eps
+elfconfig.h*
 filelist
 fixdep
 fore200e_mkfirm
 fore200e_pca_fw.c*
 gen-devlist
-gen_init_cpio
-gen_crc32table
-crc32table.h*
-*.cpio
 gen-kdb_cmds.c*
-gentbl
+gen_crc32table
+gen_init_cpio
 genksyms
-*.gif
-*.gz
-*.html
+gentbl
 ikconfig.h*
 initramfs_list
-*.jpeg
+kallsyms
 kconfig
 kconfig.tk
-Kerntypes
 keywords.c*
 ksym.c*
 ksym.h*
-kallsyms
-mk_elfconfig
-elfconfig.h*
-modpost
-pnmtologo
-logo_*.c
-*.log
 lex.c*
+logo_*.c
 logo_*_clut224.c
 logo_*_mono.c
 lxdialog
 make_times_h
 map
+maui_boot.h
+mk_elfconfig
 mkdep
-*_MODULES
-MODS.txt
+mktables
+modpost
 modversions.h*
-Module.symvers
-*.mod.c
-*.o
-*.ko
-*.orig
-*.lst
-*.grp
-*.grep
+offsets.h
 oui.c*
-mktables
-raid6tables.c
-raid6int*.c
-raid6altivec*.c
-wanxlfw.inc
-maui_boot.h
-pss_boot.h
-trix_boot.h
-*.pdf
 parse.c*
 parse.h*
-PENDING
+pnmtologo
 ppc_defs.h*
 promcon_tbl.c*
-*.png
-*.ps
-*.rej
-SCCS
+pss_boot.h
+raid6altivec*.c
+raid6int*.c
+raid6tables.c
 setup
-*.s
-*.so
-*.sgml
 sim710_d.h*
 sm_tbl*
 split-include
-System.map*
 tags
-TAGS
-*.tex
 times.h*
 tkparse
-*.ver
+trix_boot.h
 version.h*
-*_vga16.c
 vmlinux
-vmlinux.lds
 vmlinux-*
+vmlinux.lds
 vsyscall.lds
+wanxlfw.inc
+uImage
 zImage
diff -urN linux/Documentation/feature-removal-schedule.txt 
linux/Documentation/feature-removal-schedule.txt
--- linux/Documentation/feature-removal-schedule.txt    2005/04/29 11:14:59     
1.5
+++ linux/Documentation/feature-removal-schedule.txt    2005/05/19 12:08:05     
1.6
@@ -48,3 +48,18 @@
 Why:   Replaced by ->compat_ioctl in file_operations and other method
        vecors.
 Who:   Andi Kleen <ak@muc.de>, Christoph Hellwig <hch@lst.de>
+
+---------------------------
+
+What:  RCU API moves to EXPORT_SYMBOL_GPL
+When:  April 2006
+Files: include/linux/rcupdate.h, kernel/rcupdate.c
+Why:   Outside of Linux, the only implementations of anything even
+       vaguely resembling RCU that I am aware of are in DYNIX/ptx,
+       VM/XA, Tornado, and K42.  I do not expect anyone to port binary
+       drivers or kernel modules from any of these, since the first two
+       are owned by IBM and the last two are open-source research OSes.
+       So these will move to GPL after a grace period to allow
+       people, who might be using implementations that I am not aware
+       of, to adjust to this upcoming change.
+Who:   Paul E. McKenney <paulmck@us.ibm.com>
diff -urN linux/Documentation/pci.txt linux/Documentation/pci.txt
--- linux/Documentation/pci.txt 2005/03/18 17:36:43     1.26
+++ linux/Documentation/pci.txt 2005/05/19 12:08:05     1.27
@@ -279,6 +279,7 @@
 pci_for_each_bus()             Superseded by pci_find_next_bus()
 pci_find_device()              Superseded by pci_get_device()
 pci_find_subsys()              Superseded by pci_get_subsys()
+pci_find_slot()                        Superseded by pci_get_slot()
 pcibios_find_class()           Superseded by pci_get_class()
 pci_find_class()               Superseded by pci_get_class()
 pci_(read|write)_*_nodev()     Superseded by pci_bus_(read|write)_*()
diff -urN linux/Documentation/BK-usage/00-INDEX 
linux/Documentation/BK-usage/00-INDEX
--- linux/Documentation/BK-usage/Attic/00-INDEX 2005-05-19 13:08:05.305488000 
+0100     1.2
+++ linux/Documentation/BK-usage/Attic/00-INDEX 1970/01/01 00:00:00+0100
@@ -1,51 +0,0 @@
-bk-kernel-howto.txt: Description of kernel workflow under BitKeeper
-
-bk-make-sum: Create summary of changesets in one repository and not
-another, typically in preparation to be sent to an upstream maintainer.
-Typical usage:
-       cd my-updated-repo
-       bk-make-sum ~/repo/original-repo
-       mv /tmp/linus.txt ../original-repo.txt
-
-bksend: Create readable text output containing summary of changes, GNU
-patch of the changes, and BK metadata of changes (as needed for proper
-importing into BitKeeper by an upstream maintainer).  This output is
-suitable for emailing BitKeeper changes.  The recipient of this output
-may pipe it directly to 'bk receive'.
-
-bz64wrap: helper script. Uncompressed input is piped to this script,
-which compresses its input, and then outputs the uu-/base64-encoded
-version of the compressed input.
-
-cpcset: Copy changeset between unrelated repositories.
-Attempts to preserve changeset user, user address, description, in
-addition to the changeset (the patch) itself.
-Typical usage:
-       cd my-updated-repo
-       bk changes      # looking for a changeset...
-       cpcset 1.1511 . ../another-repo
-
-csets-to-patches: Produces a delta of two BK repositories, in the form
-of individual files, each containing a single cset as a GNU patch.
-Output is several files, each with the filename "/tmp/rev-$REV.patch"
-Typical usage:
-       cd my-updated-repo
-       bk changes -L ~/repo/original-repo 2>&1 | \
-               perl csets-to-patches
-
-cset-to-linus: Produces a delta of two BK repositories, in the form of
-changeset descriptions, with 'diffstat' output created for each
-individual changset.
-Typical usage:
-       cd my-updated-repo
-       bk changes -L ~/repo/original-repo 2>&1 | \
-               perl cset-to-linus > summary.txt
-
-gcapatch:  Generates patch containing changes in local repository.
-Typical usage:
-       cd my-updated-repo
-       gcapatch > foo.patch
-
-unbz64wrap: Reverse an encoded, compressed data stream created by
-bz64wrap into an uncompressed, typically text/plain output.
-
diff -urN linux/Documentation/BK-usage/bk-kernel-howto.txt 
linux/Documentation/BK-usage/bk-kernel-howto.txt
--- linux/Documentation/BK-usage/Attic/bk-kernel-howto.txt      2005-05-19 
13:08:05.317652000 +0100     1.6
+++ linux/Documentation/BK-usage/Attic/bk-kernel-howto.txt      1970/01/01 
00:00:00+0100
@@ -1,283 +0,0 @@
-
-                  Doing the BK Thing, Penguin-Style
-
-
-
-
-This set of notes is intended mainly for kernel developers, occasional
-or full-time, but sysadmins and power users may find parts of it useful
-as well.  It assumes at least a basic familiarity with CVS, both at a
-user level (use on the cmd line) and at a higher level (client-server model).
-Due to the author's background, an operation may be described in terms
-of CVS, or in terms of how that operation differs from CVS.
-
-This is -not- intended to be BitKeeper documentation.  Always run
-"bk help <command>" or in X "bk helptool <command>" for reference
-documentation.
-
-
-BitKeeper Concepts
-------------------
-
-In the true nature of the Internet itself, BitKeeper is a distributed
-system.  When applied to revision control, this means doing away with
-client-server, and changing to a parent-child model... essentially
-peer-to-peer.  On the developer's end, this also represents a
-fundamental disruption in the standard workflow of changes, commits,
-and merges.  You will need to take a few minutes to think about
-how to best work under BitKeeper, and re-optimize things a bit.
-In some sense it is a bit radical, because it might described as
-tossing changes out into a maelstrom and having them magically
-land at the right destination... but I'm getting ahead of myself.
-
-Let's start with this progression:
-Each BitKeeper source tree on disk is a repository unto itself.
-Each repository has a parent (except the root/original, of course).
-Each repository contains a set of a changesets ("csets").
-Each cset is one or more changed files, bundled together.
-
-Each tree is a repository, so all changes are checked into the local
-tree.  When a change is checked in, all modified files are grouped
-into a logical unit, the changeset.  Internally, BK links these
-changesets in a tree, representing various converging and diverging
-lines of development.  These changesets are the bread and butter of
-the BK system.
-
-After the concept of changesets, the next thing you need to get used
-to is having multiple copies of source trees lying around.  This -really-
-takes some getting used to, for some people.  Separate source trees
-are the means in BitKeeper by which you delineate parallel lines
-of development, both minor and major.  What would be branches in
-CVS become separate source trees, or "clones" in BitKeeper [heh,
-or Star Wars] terminology.
-
-Clones and changesets are the tools from which most of the power of
-BitKeeper is derived.  As mentioned earlier, each clone has a parent,
-the tree used as the source when the new clone was created.  In a
-CVS-like setup, the parent would be a remote server on the Internet,
-and the child is your local clone of that tree.
-
-Once you have established a common baseline between two source trees --
-a common parent -- then you can merge changesets between those two
-trees with ease.  Merging changes into a tree is called a "pull", and
-is analagous to 'cvs update'.  A pull downloads all the changesets in
-the remote tree you do not have, and merges them.  Sending changes in
-one tree to another tree is called a "push".  Push sends all changes
-in the local tree the remote does not yet have, and merges them.
-
-From these concepts come some initial command examples:
-
-1) bk clone -q http://linux.bkbits.net/linux-2.5 linus-2.5
-Download a 2.5 stock kernel tree, naming it "linus-2.5" in the local dir.
-The "-q" disables listing every single file as it is downloaded.
-
-2) bk clone -ql linus-2.5 alpha-2.5
-Create a separate source tree for the Alpha AXP architecture.
-The "-l" uses hard links instead of copying data, since both trees are
-on the local disk.  You can also replace the above with "bk lclone -q ..."
-
-You only clone a tree -once-.  After cloning the tree lives a long time
-on disk, being updating by pushes and pulls.
-
-3) cd alpha-2.5 ; bk pull http://gkernel.bkbits.net/alpha-2.5
-Download changes in "alpha-2.5" repository which are not present
-in the local repository, and merge them into the source tree.
-
-4) bk -r co -q
-Because every tree is a repository, files must be checked out before
-they will be in their standard places in the source tree.
-
-5)     bk vi fs/inode.c                                # example change...
-       bk citool                                       # checkin, using X tool
-       bk push bk://gkernel@bkbits.net/alpha-2.5       # upload change
-Typical example of a BK sequence that would replace the analagous CVS
-situation,
-       vi fs/inode.c
-       cvs commit
-
-As this is just supposed to be a quick BK intro, for more in-depth
-tutorials, live working demos, and docs, see http://www.bitkeeper.com/
-
-
-
-BK and Kernel Development Workflow
-----------------------------------
-Currently the latest 2.5 tree is available via "bk clone $URL"
-and "bk pull $URL" at http://linux.bkbits.net/linux-2.5
-This should change in a few weeks to a kernel.org URL.
-
-
-A big part of using BitKeeper is organizing the various trees you have
-on your local disk, and organizing the flow of changes among those
-trees, and remote trees.  If one were to graph the relationships between
-a desired BK setup, you are likely to see a few-many-few graph, like
-this:
-
-                   linux-2.5
-                       |
-              merge-to-linus-2.5
-                /    |      |
-               /     |      |
-       vm-hacks  bugfixes  filesys   personal-hacks
-             \       |      |          /
-              \      |      |         /
-               \     |      |        /
-                testing-and-validation
-
-Since a "bk push" sends all changes not in the target tree, and
-since a "bk pull" receives all changes not in the source tree, you want
-to make sure you are only pushing specific changes to the desired tree,
-not all changes from "peer parent" trees.  For example, pushing a change
-from the testing-and-validation tree would probably be a bad idea,
-because it will push all changes from vm-hacks, bugfixes, filesys, and
-personal-hacks trees into the target tree.
-
-One would typically work on only one "theme" at a time, either
-vm-hacks or bugfixes or filesys, keeping those changes isolated in
-their own tree during development, and only merge the isolated with
-other changes when going upstream (to Linus or other maintainers) or
-downstream (to your "union" trees, like testing-and-validation above).
-
-It should be noted that some of this separation is not just recommended
-practice, it's actually [for now] -enforced- by BitKeeper.  BitKeeper
-requires that changesets maintain a certain order, which is the reason
-that "bk push" sends all local changesets the remote doesn't have.  This
-separation may look like a lot of wasted disk space at first, but it
-helps when two unrelated changes may "pollute" the same area of code, or
-don't follow the same pace of development, or any other of the standard
-reasons why one creates a development branch.
-
-Small development branches (clones) will appear and disappear:
-
-       -------- A --------- B --------- C --------- D -------
-                 \                                 /
-                  -----short-term devel branch-----
-
-While long-term branches will parallel a tree (or trees), with period
-merge points.  In this first example, we pull from a tree (pulls,
-"\") periodically, such as what occurs when tracking changes in a
-vendor tree, never pushing changes back up the line:
-
-       -------- A --------- B --------- C --------- D -------
-                 \                       \           \
-                  ----long-term devel branch-----------------
-
-And then a more common case in Linux kernel development, a long term
-branch with periodic merges back into the tree (pushes, "/"):
-
-       -------- A --------- B --------- C --------- D -------
-                 \                       \         / \
-                  ----long-term devel branch-----------------
-
-
-
-
-
-Submitting Changes to Linus
----------------------------
-There's a bit of an art, or style, of submitting changes to Linus.
-Since Linus's tree is now (you might say) fully integrated into the
-distributed BitKeeper system, there are several prerequisites to
-properly submitting a BitKeeper change.  All these prereq's are just
-general cleanliness of BK usage, so as people become experts at BK, feel
-free to optimize this process further (assuming Linus agrees, of
-course).
-
-
-
-0) Make sure your tree was originally cloned from the linux-2.5 tree
-created by Linus.  If your tree does not have this as its ancestor, it
-is impossible to reliably exchange changesets.
-
-
-
-1) Pay attention to your commit text.  The commit message that
-accompanies each changeset you submit will live on forever in history,
-and is used by Linus to accurately summarize the changes in each
-pre-patch.  Remember that there is no context, so
-       "fix for new scheduler changes"
-would be too vague, but
-       "fix mips64 arch for new scheduler switch_to(), TIF_xxx semantics"
-would be much better.
-
-You can and should use the command "bk comment -C<rev>" to update the
-commit text, and improve it after the fact.  This is very useful for
-development: poor, quick descriptions during development, which get
-cleaned up using "bk comment" before issuing the "bk push" to submit the
-changes.
-
-
-
-2) Include an Internet-available URL for Linus to pull from, such as
-
-       Pull from:  http://gkernel.bkbits.net/net-drivers-2.5
-
-
-
-3) Include a summary and "diffstat -p1" of each changeset that will be
-downloaded, when Linus issues a "bk pull".  The author auto-generates
-these summaries using "bk changes -L <parent>", to obtain a listing
-of all the pending-to-send changesets, and their commit messages.
-
-It is important to show Linus what he will be downloading when he issues
-a "bk pull", to reduce the time required to sift the changes once they
-are downloaded to Linus's local machine.
-
-IMPORTANT NOTE:  One of the features of BK is that your repository does
-not have to be up to date, in order for Linus to receive your changes.
-It is considered a courtesy to keep your repository fairly recent, to
-lessen any potential merge work Linus may need to do.
-
-
-4) Split up your changes.  Each maintainer<->Linus situation is likely
-to be slightly different here, so take this just as general advice.  The
-author splits up changes according to "themes" when merging with Linus.
-Simultaneous pushes from local development go to special trees which
-exist solely to house changes "queued" for Linus.  Example of the trees:
-
-       net-drivers-2.5 -- on-going net driver maintenance
-       vm-2.5 -- VM-related changes
-       fs-2.5 -- filesystem-related changes
-
-Linus then has much more freedom for pulling changes.  He could (for
-example) issue a "bk pull" on vm-2.5 and fs-2.5 trees, to merge their
-changes, but hold off net-drivers-2.5 because of a change that needs
-more discussion.
-
-Other maintainers may find that a single linus-pull-from tree is
-adequate for passing BK changesets to him.
-
-
-
-Frequently Answered Questions
------------------------------
-1) How do I change the e-mail address shown in the changelog?
-A. When you run "bk citool" or "bk commit", set environment
-   variables BK_USER and BK_HOST to the desired username
-   and host/domain name.
-
-
-2) How do I use tags / get a diff between two kernel versions?
-A. Pass the tags Linus uses to 'bk export'.
-
-ChangeSets are in a forward-progressing order, so it's pretty easy
-to get a snapshot starting and ending at any two points in time.
-Linus puts tags on each release and pre-release, so you could use
-these two examples:
-
-    bk export -tpatch -hdu -rv2.5.4,v2.5.5 | less
-        # creates patch-2.5.5 essentially
-    bk export -tpatch -du -rv2.5.5-pre1,v2.5.5 | less
-        # changes from pre1 to final
-
-A tag is just an alias for a specific changeset... and since changesets
-are ordered, a tag is thus a marker for a specific point in time (or
-specific state of the tree).
-
-
-3) Is there an easy way to generate One Big Patch versus mainline,
-   for my long-lived kernel branch?
-A. Yes.  This requires BK 3.x, though.
-
-       bk export -tpatch -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+
-
diff -urN linux/Documentation/BK-usage/bk-make-sum 
linux/Documentation/BK-usage/bk-make-sum
--- linux/Documentation/BK-usage/Attic/bk-make-sum      2005-05-19 
13:08:05.330605000 +0100     1.2
+++ linux/Documentation/BK-usage/Attic/bk-make-sum      1970/01/01 00:00:00+0100
@@ -1,34 +0,0 @@
-#!/bin/sh -e
-# DIR=$HOME/BK/axp-2.5
-# cd $DIR
-
-LINUS_REPO=$1
-DIRBASE=`basename $PWD`
-
-{
-cat <<EOT
-Please do a
-
-       bk pull bk://gkernel.bkbits.net/$DIRBASE
-
-This will update the following files:
-
-EOT
-
-bk export -tpatch -hdu -r`bk repogca $LINUS_REPO`,+ | diffstat -p1 2>/dev/null
-
-cat <<EOT
-
-through these ChangeSets:
-
-EOT
-
-bk changes -L -d'$unless(:MERGE:){ChangeSet|:CSETREV:\n}' $LINUS_REPO |
-bk -R prs -h -d'$unless(:MERGE:){<:P:@:HOST:> (:D: :I:)\n$each(:C:){   
(:C:)\n}\n}' -
-
-} > /tmp/linus.txt
-
-cat <<EOT
-Mail text in /tmp/linus.txt; please check and send using your favourite
-mailer.
-EOT
diff -urN linux/Documentation/BK-usage/bksend 
linux/Documentation/BK-usage/bksend
--- linux/Documentation/BK-usage/Attic/bksend   2005-05-19 13:08:05.341670000 
+0100     1.2
+++ linux/Documentation/BK-usage/Attic/bksend   1970/01/01 00:00:00+0100
@@ -1,36 +0,0 @@
-#!/bin/sh
-# A script to format BK changeset output in a manner that is easy to read.
-# Andreas Dilger <adilger@turbolabs.com>  13/02/2002
-#
-# Add diffstat output after Changelog <adilger@turbolabs.com>   21/02/2002
-
-PROG=bksend
-
-usage() {
-       echo "usage: $PROG -r<rev>"
-       echo -e "\twhere <rev> is of the form '1.23', '1.23..', '1.23..1.27',"
-       echo -e "\tor '+' to indicate the most recent revision"
-
-       exit 1
-}
-
-case $1 in
--r) REV=$2; shift ;;
--r*) REV=`echo $1 | sed 's/^-r//'` ;;
-*) echo "$PROG: no revision given, you probably don't want that";;
-esac
-
-[ -z "$REV" ] && usage
-
-echo "You can import this changeset into BK by piping this whole message to:"
-echo "'| bk receive [path to repository]' or apply the patch as usual."
-
-SEP="\n===================================================================\n\n"
-echo -e $SEP
-env PAGER=/bin/cat bk changes -r$REV
-echo
-bk export -tpatch -du -h -r$REV | diffstat
-echo; echo
-bk export -tpatch -du -h -r$REV
-echo -e $SEP
-bk send -wgzip_uu -r$REV -
diff -urN linux/Documentation/BK-usage/bz64wrap 
linux/Documentation/BK-usage/bz64wrap
--- linux/Documentation/BK-usage/Attic/bz64wrap 2005-05-19 13:08:05.352750000 
+0100     1.1
+++ linux/Documentation/BK-usage/Attic/bz64wrap 1970/01/01 00:00:00+0100
@@ -1,41 +0,0 @@
-#!/bin/sh
-
-# bz64wrap - the sending side of a bzip2 | base64 stream
-# Andreas Dilger <adilger@clusterfs.com>   Jan 2002
-
-
-PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin
-
-# A program to generate base64 encoding on stdout
-BASE64_ENCODE="uuencode -m /dev/stdout"
-BASE64_BEGIN=
-BASE64_END=
-
-BZIP=NO
-BASE64=NO
-
-# Test if we have the bzip program installed
-bzip2 -c /dev/null > /dev/null 2>&1 && BZIP=YES
-
-# Test if uuencode can handle the -m (MIME) encoding option
-$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES
-
-if [ $BASE64 = NO ]; then
-       BASE64_ENCODE=mimencode
-       BASE64_BEGIN="begin-base64 644 -"
-       BASE64_END="===="
-
-       $BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES
-fi
-
-if [ $BZIP = NO -o $BASE64 = NO ]; then
-       echo "$0: can't use bz64 encoding: bzip2=$BZIP, $BASE64_ENCODE=$BASE64"
-       exit 1
-fi
-
-# Sadly, mimencode does not appear to have good "begin" and "end" markers
-# like uuencode does, and it is picky about getting the right start/end of
-# the base64 stream, so we handle this internally.
-echo "$BASE64_BEGIN"
-bzip2 -9 | $BASE64_ENCODE
-echo "$BASE64_END"
diff -urN linux/Documentation/BK-usage/cpcset 
linux/Documentation/BK-usage/cpcset
--- linux/Documentation/BK-usage/Attic/cpcset   2005-05-19 13:08:05.363636000 
+0100     1.1
+++ linux/Documentation/BK-usage/Attic/cpcset   1970/01/01 00:00:00+0100
@@ -1,36 +0,0 @@
-#!/bin/sh
-#
-# Purpose: Copy changeset patch and description from one
-#         repository to another, unrelated one.
-#
-# usage:  cpcset [revision] [from-repository] [to-repository]
-#
-
-REV=$1
-FROM=$2
-TO=$3
-TMPF=/tmp/cpcset.$$
-
-rm -f $TMPF*
-
-CWD_SAVE=`pwd`
-cd $FROM
-bk changes -r$REV                      |       \
-       grep -v '^ChangeSet'            |       \
-       sed -e 's/^  //g' > $TMPF.log
-
-USERHOST=`bk changes -r$REV | grep '^ChangeSet' | awk '{print $4}'`
-export BK_USER=`echo $USERHOST | awk '-F@' '{print $1}'`
-export BK_HOST=`echo $USERHOST | awk '-F@' '{print $2}'`
-
-bk export -tpatch -hdu -r$REV > $TMPF.patch && \
-cd $CWD_SAVE && \
-cd $TO && \
-bk import -tpatch -CFR -y"`cat $TMPF.log`" $TMPF.patch . && \
-bk commit -y"`cat $TMPF.log`"
-
-rm -f $TMPF*
-
-echo changeset $REV copied.
-echo ""
-
diff -urN linux/Documentation/BK-usage/cset-to-linus 
linux/Documentation/BK-usage/cset-to-linus
--- linux/Documentation/BK-usage/Attic/cset-to-linus    2005-05-19 
13:08:05.374609000 +0100     1.2
+++ linux/Documentation/BK-usage/Attic/cset-to-linus    1970/01/01 00:00:00+0100
@@ -1,49 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-
-my ($lhs, $rev, $tmp, $rhs, $s);
-my @cset_text = ();
-my @pipe_text = ();
-my $have_cset = 0;
-
-while (<>) {
-       next if /^---/;
-
-       if (($lhs, $tmp, $rhs) = (/^(ChangeSet\@)([^,]+)(, .*)$/)) {
-               &cset_rev if ($have_cset);
-
-               $rev = $tmp;
-               $have_cset = 1;
-
-               push(@cset_text, $_);
-       }
-
-       elsif ($have_cset) {
-               push(@cset_text, $_);
-       }
-}
-&cset_rev if ($have_cset);
-exit(0);
-
-
-sub cset_rev {
-       my $empty_cset = 0;
-
-       open PIPE, "bk export -tpatch -hdu -r $rev | diffstat -p1 2>/dev/null 
|" or die;
-       while ($s = <PIPE>) {
-               $empty_cset = 1 if ($s =~ /0 files changed/);
-               push(@pipe_text, $s);
-       }
-       close(PIPE);
-
-       if (! $empty_cset) {
-               print @cset_text;
-               print @pipe_text;
-               print "\n\n";
-       }
-
-       @pipe_text = ();
-       @cset_text = ();
-}
-
diff -urN linux/Documentation/BK-usage/csets-to-patches 
linux/Documentation/BK-usage/csets-to-patches
--- linux/Documentation/BK-usage/Attic/csets-to-patches 2005-05-19 
13:08:05.385710000 +0100     1.2
+++ linux/Documentation/BK-usage/Attic/csets-to-patches 1970/01/01 00:00:00+0100
@@ -1,44 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-
-my ($lhs, $rev, $tmp, $rhs, $s);
-my @cset_text = ();
-my @pipe_text = ();
-my $have_cset = 0;
-
-while (<>) {
-       next if /^---/;
-
-       if (($lhs, $tmp, $rhs) = (/^(ChangeSet\@)([^,]+)(, .*)$/)) {
-               &cset_rev if ($have_cset);
-
-               $rev = $tmp;
-               $have_cset = 1;
-
-               push(@cset_text, $_);
-       }
-
-       elsif ($have_cset) {
-               push(@cset_text, $_);
-       }
-}
-&cset_rev if ($have_cset);
-exit(0);
-
-
-sub cset_rev {
-       my $empty_cset = 0;
-
-       system("bk export -tpatch -du -r $rev > /tmp/rev-$rev.patch");
-
-       if (! $empty_cset) {
-               print @cset_text;
-               print @pipe_text;
-               print "\n\n";
-       }
-
-       @pipe_text = ();
-       @cset_text = ();
-}
-
diff -urN linux/Documentation/BK-usage/gcapatch 
linux/Documentation/BK-usage/gcapatch
--- linux/Documentation/BK-usage/Attic/gcapatch 2005-05-19 13:08:05.396415000 
+0100     1.1
+++ linux/Documentation/BK-usage/Attic/gcapatch 1970/01/01 00:00:00+0100
@@ -1,8 +0,0 @@
-#!/bin/sh
-#
-# Purpose: Generate GNU diff of local changes versus canonical top-of-tree
-#
-# Usage: gcapatch > foo.patch
-#
-
-bk export -tpatch -hdu -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+
diff -urN linux/Documentation/BK-usage/unbz64wrap 
linux/Documentation/BK-usage/unbz64wrap
--- linux/Documentation/BK-usage/Attic/unbz64wrap       2005-05-19 
13:08:05.406972000 +0100     1.2
+++ linux/Documentation/BK-usage/Attic/unbz64wrap       1970/01/01 00:00:00+0100
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-# unbz64wrap - the receiving side of a bzip2 | base64 stream
-# Andreas Dilger <adilger@clusterfs.com>   Jan 2002
-
-# Sadly, mimencode does not appear to have good "begin" and "end" markers
-# like uuencode does, and it is picky about getting the right start/end of
-# the base64 stream, so we handle this explicitly here.
-
-PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin
-
-if mimencode -u < /dev/null > /dev/null 2>&1 ; then
-       SHOW=
-       while read LINE; do
-               case $LINE in
-               begin-base64*) SHOW=YES ;;
-               ====) SHOW= ;;
-               *) [ "$SHOW" ] && echo "$LINE" ;;
-               esac
-       done | mimencode -u | bunzip2
-       exit $?
-else
-       cat - | uudecode -o /dev/stdout | bunzip2
-       exit $?
-fi
diff -urN linux/Documentation/DocBook/stylesheet.xsl 
linux/Documentation/DocBook/stylesheet.xsl
--- linux/Documentation/DocBook/stylesheet.xsl  1970/01/01 00:00:00
+++ linux/Documentation/DocBook/stylesheet.xsl  2005-05-19 13:08:05.488570000 
+0100     1.1
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform"; version="1.0">
+<param name="chunk.quietly">1</param>
+<param name="funcsynopsis.style">ansi</param>
+</stylesheet>
diff -urN linux/Documentation/DocBook/Makefile 
linux/Documentation/DocBook/Makefile
--- linux/Documentation/DocBook/Makefile        2005/03/18 17:36:43     1.48
+++ linux/Documentation/DocBook/Makefile        2005/05/19 12:08:05     1.49
@@ -7,10 +7,9 @@
 # list of DOCBOOKS.
 
 DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
-           kernel-hacking.xml kernel-locking.xml via-audio.xml \
-           deviceiobook.xml procfs-guide.xml tulip-user.xml \
-           writing_usb_driver.xml scsidrivers.xml sis900.xml \
-           kernel-api.xml journal-api.xml lsm.xml usb.xml \
+           kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
+           procfs-guide.xml writing_usb_driver.xml scsidrivers.xml \
+           sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
            gadget.xml libata.xml mtdnand.xml librs.xml
 
 ###
@@ -42,14 +41,16 @@
 mandocs: $(MAN)
 
 installmandocs: mandocs
-       $(MAKEMAN) install Documentation/DocBook/man
+       mkdir -p /usr/local/man/man9/
+       install Documentation/DocBook/man/*.9.gz /usr/local/man/man9/
 
 ###
 #External programs used
 KERNELDOC = scripts/kernel-doc
 DOCPROC   = scripts/basic/docproc
-SPLITMAN  = $(PERL) $(srctree)/scripts/split-man
-MAKEMAN   = $(PERL) $(srctree)/scripts/makeman
+
+XMLTOFLAGS = -m Documentation/DocBook/stylesheet.xsl
+#XMLTOFLAGS += --skip-validation
 
 ###
 # DOCPROC is used for two purposes:
@@ -96,45 +97,44 @@
 # Rules to generate postscript, PDF and HTML
 # db2html creates a directory. Generate a html file used for timestamp
 
-quiet_cmd_db2ps = DB2PS   $@
-      cmd_db2ps = db2ps -o $(dir $@) $<
+quiet_cmd_db2ps = XMLTO    $@
+      cmd_db2ps = xmlto ps $(XMLTOFLAGS) -o $(dir $@) $<
 %.ps : %.xml
-       @(which db2ps > /dev/null 2>&1) || \
-        (echo "*** You need to install DocBook stylesheets ***"; \
+       @(which xmlto > /dev/null 2>&1) || \
+        (echo "*** You need to install xmlto ***"; \
          exit 1)
        $(call cmd,db2ps)
 
-quiet_cmd_db2pdf = DB2PDF  $@
-      cmd_db2pdf = db2pdf -o $(dir $@) $<
+quiet_cmd_db2pdf = XMLTO   $@
+      cmd_db2pdf = xmlto pdf $(XMLTOFLAGS) -o $(dir $@) $<
 %.pdf : %.xml
-       @(which db2pdf > /dev/null 2>&1) || \
-        (echo "*** You need to install DocBook stylesheets ***"; \
+       @(which xmlto > /dev/null 2>&1) || \
+        (echo "*** You need to install xmlto ***"; \
          exit 1)
        $(call cmd,db2pdf)
 
-quiet_cmd_db2html = DB2HTML $@
-      cmd_db2html = db2html -o $(patsubst %.html,%,$@) $< &&                 \
-               echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/book1.html"> \
+quiet_cmd_db2html = XMLTO  $@
+      cmd_db2html = xmlto xhtml $(XMLTOFLAGS) -o $(patsubst %.html,%,$@) $< && 
\
+               echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \
          Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
 
 %.html:        %.xml
-       @(which db2html > /dev/null 2>&1) || \
-        (echo "*** You need to install DocBook stylesheets ***"; \
+       @(which xmlto > /dev/null 2>&1) || \
+        (echo "*** You need to install xmlto ***"; \
          exit 1)
        @rm -rf $@ $(patsubst %.html,%,$@)
        $(call cmd,db2html)
        @if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \
             cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi
 
-###
-# Rule to generate man files - output is placed in the man subdirectory
-
-%.9:   %.xml
-ifneq ($(KBUILD_SRC),)
-       $(Q)mkdir -p $(objtree)/Documentation/DocBook/man
-endif
-       $(SPLITMAN) $< $(objtree)/Documentation/DocBook/man 
"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)"
-       $(MAKEMAN) convert $(objtree)/Documentation/DocBook/man $<
+quiet_cmd_db2man = XMLTO   $@
+      cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o 
$(obj)/man $< ; gzip -f $(obj)/man/*.9; fi
+%.9 : %.xml
+       @(which xmlto > /dev/null 2>&1) || \
+        (echo "*** You need to install xmlto ***"; \
+         exit 1)
+       $(call cmd,db2man)
+       @touch $@
 
 ###
 # Rules to generate postscripts and PNG imgages from .fig format files
diff -urN linux/Documentation/DocBook/kernel-api.tmpl 
linux/Documentation/DocBook/kernel-api.tmpl
--- linux/Documentation/DocBook/kernel-api.tmpl 2005/03/18 17:36:43     1.38
+++ linux/Documentation/DocBook/kernel-api.tmpl 2005/05/19 12:08:05     1.39
@@ -49,13 +49,33 @@
 !Iinclude/asm-i386/unaligned.h
      </sect1>
 
-<!-- FIXME:
-  kernel/sched.c has no docs, which stuffs up the sgml.  Comment
-  out until somebody adds docs.  KAO
      <sect1><title>Delaying, scheduling, and timer routines</title>
-X!Ekernel/sched.c
+!Iinclude/linux/sched.h
+!Ekernel/sched.c
+!Ekernel/timer.c
+     </sect1>
+     <sect1><title>Internal Functions</title>
+!Ikernel/exit.c
+!Ikernel/signal.c
      </sect1>
-KAO -->
+
+     <sect1><title>Kernel objects manipulation</title>
+<!--
+X!Iinclude/linux/kobject.h
+-->
+!Elib/kobject.c
+     </sect1>
+
+     <sect1><title>Kernel utility functions</title>
+!Iinclude/linux/kernel.h
+<!-- This needs to clean up to make kernel-doc happy
+X!Ekernel/printk.c
+ -->
+!Ekernel/panic.c
+!Ekernel/sys.c
+!Ekernel/rcupdate.c
+     </sect1>
+
   </chapter>
 
   <chapter id="adt">
@@ -81,7 +101,9 @@
 !Elib/vsprintf.c
      </sect1>
      <sect1><title>String Manipulation</title>
-!Ilib/string.c
+<!-- All functions are exported at now
+X!Ilib/string.c
+ -->
 !Elib/string.c
      </sect1>
      <sect1><title>Bit Operations</title>
@@ -98,6 +120,25 @@
 !Iinclude/asm-i386/uaccess.h
 !Iarch/i386/lib/usercopy.c
      </sect1>
+     <sect1><title>More Memory Management Functions</title>
+!Iinclude/linux/rmap.h
+!Emm/readahead.c
+!Emm/filemap.c
+!Emm/memory.c
+!Emm/vmalloc.c
+!Emm/mempool.c
+!Emm/page-writeback.c
+!Emm/truncate.c
+     </sect1>
+  </chapter>
+
+
+  <chapter id="ipc">
+     <title>Kernel IPC facilities</title>
+
+     <sect1><title>IPC utilities</title>
+!Iipc/util.c
+     </sect1>
   </chapter>
 
   <chapter id="kfifo">
@@ -114,6 +155,10 @@
      <sect1><title>sysctl interface</title>
 !Ekernel/sysctl.c
      </sect1>
+
+     <sect1><title>proc filesystem interface</title>
+!Ifs/proc/base.c
+     </sect1>
   </chapter>
 
   <chapter id="debugfs">
@@ -127,6 +172,10 @@
 
   <chapter id="vfs">
      <title>The Linux VFS</title>
+     <sect1><title>The Filesystem types</title>
+!Iinclude/linux/fs.h
+!Einclude/linux/fs.h
+     </sect1>
      <sect1><title>The Directory Cache</title>
 !Efs/dcache.c
 !Iinclude/linux/dcache.h
@@ -142,13 +191,31 @@
 !Efs/locks.c
 !Ifs/locks.c
      </sect1>
+     <sect1><title>Other Functions</title>
+!Efs/mpage.c
+!Efs/namei.c
+!Efs/buffer.c
+!Efs/bio.c
+!Efs/seq_file.c
+!Efs/filesystems.c
+!Efs/fs-writeback.c
+!Efs/block_dev.c
+     </sect1>
   </chapter>
 
   <chapter id="netcore">
      <title>Linux Networking</title>
+     <sect1><title>Networking Base Types</title>
+!Iinclude/linux/net.h
+     </sect1>
      <sect1><title>Socket Buffer Functions</title>
 !Iinclude/linux/skbuff.h
+!Iinclude/net/sock.h
+!Enet/socket.c
 !Enet/core/skbuff.c
+!Enet/core/sock.c
+!Enet/core/datagram.c
+!Enet/core/stream.c
      </sect1>
      <sect1><title>Socket Filter</title>
 !Enet/core/filter.c
@@ -158,6 +225,14 @@
 !Enet/core/gen_stats.c
 !Enet/core/gen_estimator.c
      </sect1>
+     <sect1><title>SUN RPC subsystem</title>
+<!-- The !D functionality is not perfect, garbage has to be protected by 
comments
+!Dnet/sunrpc/sunrpc_syms.c
+-->
+!Enet/sunrpc/xdr.c
+!Enet/sunrpc/svcsock.c
+!Enet/sunrpc/sched.c
+     </sect1>
   </chapter>
 
   <chapter id="netdev">
@@ -194,11 +269,26 @@
 !Iarch/i386/kernel/irq.c
      </sect1>
 
+     <sect1><title>Resources Management</title>
+!Ekernel/resource.c
+     </sect1>
+
      <sect1><title>MTRR Handling</title>
 !Earch/i386/kernel/cpu/mtrr/main.c
      </sect1>
      <sect1><title>PCI Support Library</title>
 !Edrivers/pci/pci.c
+!Edrivers/pci/pci-driver.c
+!Edrivers/pci/remove.c
+!Edrivers/pci/pci-acpi.c
+<!-- kerneldoc does not understand to __devinit
+X!Edrivers/pci/search.c
+ -->
+!Edrivers/pci/msi.c
+!Edrivers/pci/bus.c
+!Edrivers/pci/hotplug.c
+!Edrivers/pci/probe.c
+!Edrivers/pci/rom.c
      </sect1>
      <sect1><title>PCI Hotplug Support Library</title>
 !Edrivers/pci/hotplug/pci_hotplug_core.c
@@ -223,6 +313,14 @@
 !Efs/devfs/base.c
   </chapter>
 
+  <chapter id="sysfs">
+     <title>The Filesystem for Exporting Kernel Objects</title>
+!Efs/sysfs/file.c
+!Efs/sysfs/dir.c
+!Efs/sysfs/symlink.c
+!Efs/sysfs/bin.c
+  </chapter>
+
   <chapter id="security">
      <title>Security Framework</title>
 !Esecurity/security.c
@@ -233,6 +331,61 @@
 !Ekernel/power/pm.c
   </chapter>
 
+  <chapter id="devdrivers">
+     <title>Device drivers infrastructure</title>
+     <sect1><title>Device Drivers Base</title>
+<!--
+X!Iinclude/linux/device.h
+-->
+!Edrivers/base/driver.c
+!Edrivers/base/class_simple.c
+!Edrivers/base/core.c
+!Edrivers/base/firmware_class.c
+!Edrivers/base/transport_class.c
+!Edrivers/base/dmapool.c
+<!-- Cannot be included, because
+     attribute_container_add_class_device_adapter
+ and attribute_container_classdev_to_container
+     exceed allowed 44 characters maximum
+X!Edrivers/base/attribute_container.c
+-->
+!Edrivers/base/sys.c
+<!--
+X!Edrivers/base/interface.c
+-->
+!Edrivers/base/platform.c
+!Edrivers/base/bus.c
+     </sect1>
+     <sect1><title>Device Drivers Power Management</title>
+!Edrivers/base/power/main.c
+!Edrivers/base/power/resume.c
+!Edrivers/base/power/suspend.c
+     </sect1>
+     <sect1><title>Device Drivers ACPI Support</title>
+<!-- Internal functions only
+X!Edrivers/acpi/sleep/main.c
+X!Edrivers/acpi/sleep/wakeup.c
+X!Edrivers/acpi/motherboard.c
+X!Edrivers/acpi/bus.c
+-->
+!Edrivers/acpi/scan.c
+<!-- No correct structured comments
+X!Edrivers/acpi/pci_bind.c
+-->
+     </sect1>
+     <sect1><title>Device drivers PnP support</title>
+!Edrivers/pnp/core.c
+<!-- No correct structured comments
+X!Edrivers/pnp/system.c
+ -->
+!Edrivers/pnp/card.c
+!Edrivers/pnp/driver.c
+!Edrivers/pnp/manager.c
+!Edrivers/pnp/support.c
+     </sect1>
+  </chapter>
+
+
   <chapter id="blkdev">
      <title>Block Devices</title>
 !Edrivers/block/ll_rw_blk.c
@@ -250,7 +403,23 @@
 
   <chapter id="snddev">
      <title>Sound Devices</title>
+!Iinclude/sound/core.h
 !Esound/sound_core.c
+!Iinclude/sound/pcm.h
+!Esound/core/pcm.c
+!Esound/core/device.c
+!Esound/core/info.c
+!Esound/core/rawmidi.c
+!Esound/core/sound.c
+!Esound/core/memory.c
+!Esound/core/pcm_memory.c
+!Esound/core/init.c
+!Esound/core/isadma.c
+!Esound/core/control.c
+!Esound/core/pcm_lib.c
+!Esound/core/hwdep.c
+!Esound/core/pcm_native.c
+!Esound/core/memalloc.c
 <!-- FIXME: Removed for now since no structured comments in source
 X!Isound/sound_firmware.c
 -->
@@ -258,6 +427,7 @@
 
   <chapter id="uart16x50">
      <title>16x50 UART Driver</title>
+!Iinclude/linux/serial_core.h
 !Edrivers/serial/serial_core.c
 !Edrivers/serial/8250.c
   </chapter>
@@ -310,9 +480,11 @@
      <sect1><title>Frame Buffer Memory</title>
 !Edrivers/video/fbmem.c
      </sect1>
+<!--
      <sect1><title>Frame Buffer Console</title>
-!Edrivers/video/console/fbcon.c
+X!Edrivers/video/console/fbcon.c
      </sect1>
+-->
      <sect1><title>Frame Buffer Colormap</title>
 !Edrivers/video/fbcmap.c
      </sect1>
diff -urN linux/Documentation/DocBook/tulip-user.tmpl 
linux/Documentation/DocBook/tulip-user.tmpl
--- linux/Documentation/DocBook/Attic/tulip-user.tmpl   2005-05-19 
13:08:05.539302000 +0100     1.4
+++ linux/Documentation/DocBook/Attic/tulip-user.tmpl   1970/01/01 00:00:00+0100
@@ -1,327 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; []>
-
-<book id="TulipUserGuide">
- <bookinfo>
-  <title>Tulip Driver User's Guide</title>
-  
-  <authorgroup>
-   <author>
-    <firstname>Jeff</firstname>
-    <surname>Garzik</surname>
-    <affiliation>
-     <address>
-      <email>jgarzik@pobox.com</email>
-     </address>
-    </affiliation>
-   </author>
-  </authorgroup>
-
-  <copyright>
-   <year>2001</year>
-   <holder>Jeff Garzik</holder>
-  </copyright>
-
-  <legalnotice>
-   <para>
-     This documentation 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.
-   </para>
-      
-   <para>
-     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.
-   </para>
-      
-   <para>
-     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
-   </para>
-      
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
- </bookinfo>
-
- <toc></toc>
-
-  <chapter id="intro">
-    <title>Introduction</title>
-<para>
-The Tulip Ethernet Card Driver
-is maintained by Jeff Garzik (<email>jgarzik@pobox.com</email>).
-</para>
-
-<para>
-The Tulip driver was developed by Donald Becker and changed by
-Jeff Garzik, Takashi Manabe and a cast of thousands.
-</para>
-
-<para>
-For 2.4.x and later kernels, the Linux Tulip driver is available at
-<ulink 
url="http://sourceforge.net/projects/tulip/";>http://sourceforge.net/projects/tulip/</ulink>
-</para>
-
-<para>
-       This driver is for the Digital "Tulip" Ethernet adapter interface.
-       It should work with most DEC 21*4*-based chips/ethercards, as well as
-       with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX.
-</para>
-
-<para>
-        The original author may be reached as becker@scyld.com, or C/O
-        Scyld Computing Corporation,
-        410 Severn Ave., Suite 210,
-        Annapolis MD 21403
-</para>
-
-<para>
-       Additional information on Donald Becker's tulip.c
-       is available at <ulink 
url="http://www.scyld.com/network/tulip.html";>http://www.scyld.com/network/tulip.html</ulink>
-</para>
-
-  </chapter>
-
-  <chapter id="drvr-compat">
-    <title>Driver Compatibility</title>
-
-<para>
-This device driver is designed for the DECchip "Tulip", Digital's
-single-chip ethernet controllers for PCI (now owned by Intel).
-Supported members of the family
-are the 21040, 21041, 21140, 21140A, 21142, and 21143.  Similar work-alike
-chips from Lite-On, Macronics, ASIX, Compex and other listed below are also
-supported.
-</para>
-
-<para>
-These chips are used on at least 140 unique PCI board designs.  The great
-number of chips and board designs supported is the reason for the
-driver size and complexity.  Almost of the increasing complexity is in the
-board configuration and media selection code.  There is very little
-increasing in the operational critical path length.
-</para>
-  </chapter>
-
-  <chapter id="board-settings">
-    <title>Board-specific Settings</title>
-
-<para>
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS preferably should assign the
-PCI INTA signal to an otherwise unused system IRQ line.
-</para>
-
-<para>
-Some boards have EEPROMs tables with default media entry.  The factory default
-is usually "autoselect".  This should only be overridden when using
-transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)
-for forcing full-duplex when used with old link partners that do not do
-autonegotiation.
-</para>
-  </chapter>
-
-  <chapter id="driver-operation">
-    <title>Driver Operation</title>
-
-<sect1><title>Ring buffers</title>
-
-<para>
-The Tulip can use either ring buffers or lists of Tx and Rx descriptors.
-This driver uses statically allocated rings of Rx and Tx descriptors, set at
-compile time by RX/TX_RING_SIZE.  This version of the driver allocates skbuffs
-for the Rx ring buffers at open() time and passes the skb->data field to the
-Tulip as receive data buffers.  When an incoming frame is less than
-RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
-copied to the new skbuff.  When the incoming frame is larger, the skbuff is
-passed directly up the protocol stack and replaced by a newly allocated
-skbuff.
-</para>
-
-<para>
-The RX_COPYBREAK value is chosen to trade-off the memory wasted by
-using a full-sized skbuff for small frames vs. the copying costs of larger
-frames.  For small frames the copying cost is negligible (esp. considering
-that we are pre-loading the cache with immediately useful header
-information).  For large frames the copying cost is non-trivial, and the
-larger copy might flush the cache of useful data.  A subtle aspect of this
-choice is that the Tulip only receives into longword aligned buffers, thus
-the IP header at offset 14 isn't longword aligned for further processing.
-Copied frames are put into the new skbuff at an offset of "+2", thus copying
-has the beneficial effect of aligning the IP header and preloading the
-cache.
-</para>
-
-</sect1>
-
-<sect1><title>Synchronization</title>
-<para>
-The driver runs as two independent, single-threaded flows of control.  One
-is the send-packet routine, which enforces single-threaded use by the
-dev->tbusy flag.  The other thread is the interrupt handler, which is single
-threaded by the hardware and other software.
-</para>
-
-<para>
-The send packet thread has partial control over the Tx ring and 'dev->tbusy'
-flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
-the 'tp->tx_full' flag.
-</para>
-
-<para>
-The interrupt handler has exclusive control over the Rx ring and records stats
-from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
-we can't avoid the interrupt overhead by having the Tx routine reap the Tx
-stats.)         After reaping the stats, it marks the queue entry as empty by 
setting
-the 'base' to zero.     Iff the 'tp->tx_full' flag is set, it clears both the
-tx_full and tbusy flags.
-</para>
-
-</sect1>
-
-  </chapter>
-
-  <chapter id="errata">
-    <title>Errata</title>
-
-<para>
-The old DEC databooks were light on details.
-The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last
-register of the set CSR12-15 written.  Hmmm, now how is that possible?
-</para>
-
-<para>
-The DEC SROM format is very badly designed not precisely defined, leading to
-part of the media selection junkheap below.  Some boards do not have EEPROM
-media tables and need to be patched up.  Worse, other boards use the DEC
-design kit media table when it isn't correct for their board.
-</para>
-
-<para>
-We cannot use MII interrupts because there is no defined GPIO pin to attach
-them.  The MII transceiver status is polled using an kernel timer.
-</para>
-  </chapter>
-
-  <chapter id="changelog">
-    <title>Driver Change History</title>
-
-    <sect1><title>Version 0.9.14 (February 20, 2001)</title>
-    <itemizedlist>
-    <listitem><para>Fix PNIC problems (Manfred Spraul)</para></listitem>
-    <listitem><para>Add new PCI id for Accton comet</para></listitem>
-    <listitem><para>Support Davicom tulips</para></listitem>
-    <listitem><para>Fix oops in eeprom parsing</para></listitem>
-    <listitem><para>Enable workarounds for early PCI chipsets</para></listitem>
-    <listitem><para>IA64, hppa csr0 support</para></listitem>
-    <listitem><para>Support media types 5, 6</para></listitem>
-    <listitem><para>Interpret a bit more of the 21142 SROM extended media type 
3</para></listitem>
-    <listitem><para>Add missing delay in eeprom reading</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.11 (November 3, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Eliminate extra bus accesses when sharing interrupts 
(prumpf)</para></listitem>
-    <listitem><para>Barrier following ownership descriptor bit flip 
(prumpf)</para></listitem>
-    <listitem><para>Endianness fixes for >14 addresses in setup frames 
(prumpf)</para></listitem>
-    <listitem><para>Report link beat to kernel/userspace via netif_carrier_*. 
(kuznet)</para></listitem>
-    <listitem><para>Better spinlocking in set_rx_mode.</para></listitem>
-    <listitem><para>Fix I/O resource request failure error messages (DaveM 
catch)</para></listitem>
-    <listitem><para>Handle DMA allocation failure.</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.10 (September 6, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Simple interrupt mitigation (via jamal)</para></listitem>
-    <listitem><para>More PCI ids</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.9 (August 11, 2000)</title>
-    <itemizedlist>
-    <listitem><para>More PCI ids</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.8 (July 13, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Correct signed/unsigned comparison for dummy frame 
index</para></listitem>
-    <listitem><para>Remove outdated references to struct 
enet_statistics</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.7 (June 17, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Timer cleanups (Andrew Morton)</para></listitem>
-    <listitem><para>Alpha compile fix (somebody?)</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.6 (May 31, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Revert 21143-related support flag patch</para></listitem>
-    <listitem><para>Add HPPA/media-table debugging printk</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.5 (May 30, 2000)</title>
-    <itemizedlist>
-    <listitem><para>HPPA support (willy@puffingroup)</para></listitem>
-    <listitem><para>CSR6 bits and tulip.h cleanup (Chris 
Smith)</para></listitem>
-    <listitem><para>Improve debugging messages a bit</para></listitem>
-    <listitem><para>Add delay after CSR13 write in 
t21142_start_nway</para></listitem>
-    <listitem><para>Remove unused ETHER_STATS code</para></listitem>
-    <listitem><para>Convert 'extern inline' to 'static inline' in tulip.h 
(Chris Smith)</para></listitem>
-    <listitem><para>Update DS21143 support flags in 
tulip_chip_info[]</para></listitem>
-    <listitem><para>Use spin_lock_irq, not _irqsave/restore, in 
tulip_start_xmit()</para></listitem>
-    <listitem><para>Add locking to set_rx_mode()</para></listitem>
-    <listitem><para>Fix race with chip setting DescOwned bit (Hal 
Murray)</para></listitem>
-    <listitem><para>Request 100% of PIO and MMIO resource space assigned to 
card</para></listitem>
-    <listitem><para>Remove error message from pci_enable_device 
failure</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.4.3 (April 14, 2000)</title>
-    <itemizedlist>
-    <listitem><para>mod_timer fix (Hal Murray)</para></listitem>
-    <listitem><para>PNIC2 resuscitation (Chris Smith)</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.4.2 (March 21, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Fix 21041 CSR7, CSR13/14/15 handling</para></listitem>
-    <listitem><para>Merge some PCI ids from tulip 0.91x</para></listitem>
-    <listitem><para>Merge some HAS_xxx flags and flag settings from tulip 
0.91x</para></listitem>
-    <listitem><para>asm/io.h fix (submitted by many) and 
cleanup</para></listitem>
-    <listitem><para>s/HAS_NWAY143/HAS_NWAY/</para></listitem>
-    <listitem><para>Cleanup 21041 mode reporting</para></listitem>
-    <listitem><para>Small code cleanups</para></listitem>
-    </itemizedlist>
-    </sect1>
-
-    <sect1><title>Version 0.9.4.1 (March 18, 2000)</title>
-    <itemizedlist>
-    <listitem><para>Finish PCI DMA conversion (davem)</para></listitem>
-    <listitem><para>Do not netif_start_queue() at end of tulip_tx_timeout() 
(kuznet)</para></listitem>
-    <listitem><para>PCI DMA fix (kuznet)</para></listitem>
-    <listitem><para>eeprom.c code cleanup</para></listitem>
-    <listitem><para>Remove Xircom Tulip crud</para></listitem>
-    </itemizedlist>
-    </sect1>
-  </chapter>
-
-</book>
diff -urN linux/Documentation/DocBook/via-audio.tmpl 
linux/Documentation/DocBook/via-audio.tmpl
--- linux/Documentation/DocBook/Attic/via-audio.tmpl    2005-05-19 
13:08:05.552510000 +0100     1.8
+++ linux/Documentation/DocBook/Attic/via-audio.tmpl    1970/01/01 00:00:00+0100
@@ -1,597 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-       "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; []>
-
-<book id="ViaAudioGuide">
- <bookinfo>
-  <title>Via 686 Audio Driver for Linux</title>
-  
-  <authorgroup>
-   <author>
-    <firstname>Jeff</firstname>
-    <surname>Garzik</surname>
-   </author>
-  </authorgroup>
-
-  <copyright>
-   <year>1999-2001</year>
-   <holder>Jeff Garzik</holder>
-  </copyright>
-
-  <legalnotice>
-   <para>
-     This documentation 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.
-   </para>
-      
-   <para>
-     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.
-   </para>
-      
-   <para>
-     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
-   </para>
-      
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
- </bookinfo>
-
-<toc></toc>
-
-  <chapter id="intro">
-      <title>Introduction</title>
-  <para>
-       The Via VT82C686A "super southbridge" chips contain
-       AC97-compatible audio logic which features dual 16-bit stereo
-       PCM sound channels (full duplex), plus a third PCM channel intended for 
use
-       in hardware-assisted FM synthesis.
-  </para>
-  <para>
-       The current Linux kernel audio driver for this family of chips
-       supports audio playback and recording, but hardware-assisted
-       FM features, and hardware buffer direct-access (mmap)
-       support are not yet available.
-  </para>
-  <para>
-       This driver supports any Linux kernel version after 2.4.10.
-  </para>
-  <para>
-       Please send bug reports to the mailing list 
<email>linux-via@gtf.org</email>.
-       To subscribe, e-mail <email>majordomo@gtf.org</email> with
-  </para>
-  <programlisting>
-       subscribe linux-via
-  </programlisting>
-  <para>
-       in the body of the message.
-  </para>
-  </chapter>
-  
-  <chapter id="install">
-      <title>Driver Installation</title>
-  <para>
-       To use this audio driver, select the
-       CONFIG_SOUND_VIA82CXXX option in the section Sound during kernel 
configuration.
-       Follow the usual kernel procedures for rebuilding the kernel,
-       or building and installing driver modules.
-  </para>
-  <para>
-       To make this driver the default audio driver, you can add the
-       following to your /etc/conf.modules file:
-  </para>
-  <programlisting>
-       alias sound via82cxxx_audio
-  </programlisting>
-  <para>
-       Note that soundcore and ac97_codec support modules
-       are also required for working audio, in addition to
-       the via82cxxx_audio module itself.
-  </para>
-  </chapter>
-  
-  <chapter id="reportbug">
-      <title>Submitting a bug report</title>
-  <sect1 id="bugrepdesc"><title>Description of problem</title>
-  <para>
-       Describe the application you were using to play/record sound, and how
-       to reproduce the problem.
-  </para>
-  </sect1>
-  <sect1 id="bugrepdiag"><title>Diagnostic output</title>
-  <para>
-       Obtain the via-audio-diag diagnostics program from
-       http://sf.net/projects/gkernel/ and provide a dump of the
-       audio chip's registers while the problem is occurring.  Sample command 
line:
-  </para>
-  <programlisting>
-       ./via-audio-diag -aps > diag-output.txt
-  </programlisting>
-  </sect1>
-  <sect1 id="bugrepdebug"><title>Driver debug output</title>
-  <para>
-       Define <constant>VIA_DEBUG</constant> at the beginning of the driver, 
then capture and email
-       the kernel log output.  This can be viewed in the system kernel log (if
-       enabled), or via the dmesg program.  Sample command line:
-  </para>
-  <programlisting>
-       dmesg > /tmp/dmesg-output.txt
-  </programlisting>
-  </sect1>
-  <sect1 id="bugrepprintk"><title>Bigger kernel message buffer</title>
-  <para>
-       If you wish to increase the size of the buffer displayed by dmesg, then
-       change the <constant>LOG_BUF_LEN</constant> macro at the top of 
linux/kernel/printk.c, recompile
-       your kernel, and pass the <constant>LOG_BUF_LEN</constant> value to 
dmesg.  Sample command line with
-       <constant>LOG_BUF_LEN</constant> == 32768:
-  </para>
-  <programlisting>
-       dmesg -s 32768 > /tmp/dmesg-output.txt
-  </programlisting>
-  </sect1>
-  </chapter>
-  
-  <chapter id="bugs">
-     <title>Known Bugs And Assumptions</title>
-  <para>
-  <variablelist>
-    <varlistentry><term>Low volume</term>
-    <listitem>
-    <para>
-       Volume too low on many systems.  Workaround:  use mixer program
-       such as xmixer to increase volume.
-    </para>
-    </listitem></varlistentry>
-
-  </variablelist>
-       
-  </para>
-  </chapter>
-
-  <chapter id="thanks">
-      <title>Thanks</title>
-  <para>
-       Via for providing e-mail support, specs, and NDA'd source code.
-  </para>
-  <para>
-       MandrakeSoft for providing hacking time.
-  </para>
-  <para>
-       AC97 mixer interface fixes and debugging by Ron Cemer 
<email>roncemer@gte.net</email>.
-  </para>
-  <para>
-       Rui Sousa <email>rui.sousa@conexant.com</email>, for bugfixing
-       MMAP support, and several other notable fixes that resulted from
-       his hard work and testing.
-  </para>
-  <para>
-       Adrian Cox <email>adrian@humboldt.co.uk</email>, for bugfixing
-       MMAP support, and several other notable fixes that resulted from
-       his hard work and testing.
-  </para>
-  <para>
-       Thomas Sailer for further bugfixes.
-  </para>
-  </chapter>
-  
-  <chapter id="notes">
-     <title>Random Notes</title>
-  <para>
-       Two /proc pseudo-files provide diagnostic information.  This is 
generally
-       not useful to most users.  Power users can disable 
CONFIG_SOUND_VIA82CXXX_PROCFS,
-       and remove the /proc support code.  Once
-       version 2.0.0 is released, the /proc support code will be disabled by
-       default.  Available /proc pseudo-files:
-  </para>
-  <programlisting>
-       /proc/driver/via/0/info
-       /proc/driver/via/0/ac97
-  </programlisting>
-  <para>
-       This driver by default supports all PCI audio devices which report
-       a vendor id of 0x1106, and a device id of 0x3058.  Subsystem vendor
-       and device ids are not examined.
-  </para>
-  <para>
-       GNU indent formatting options:
-  <programlisting>
--kr -i8 -ts8 -br -ce -bap -sob -l80 -pcs -cs -ss -bs -di1 -nbc -lp -psl
-  </programlisting>
-  </para>
-  <para>
-       Via has graciously donated e-mail support and source code to help 
further
-       the development of this driver.  Their assistance has been invaluable
-       in the design and coding of the next major version of this driver.
-  </para>
-  <para>
-       The Via audio chip apparently provides a second PCM scatter-gather
-       DMA channel just for FM data, but does not have a full hardware MIDI
-       processor.  I haven't put much thought towards a solution here, but it
-       might involve using SoftOSS midi wave table, or simply disabling MIDI
-       support altogether and using the FM PCM channel as a second (input? 
output?)
-  </para>
-  </chapter>
-
-  <chapter id="changelog">
-      <title>Driver ChangeLog</title>
-
-<sect1 id="version191"><title>
-Version 1.9.1
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    DSP read/write bugfixes from Thomas Sailer.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Add new PCI id for single-channel use of Via 8233.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Other bug fixes, tweaks, new ioctls.
-    </para>
-   </listitem>
-
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version1115"><title>
-Version 1.1.15
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    Support for variable fragment size and variable fragment number (Rui
-    Sousa)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Fixes for the SPEED, STEREO, CHANNELS, FMT ioctls when in read &amp;
-    write mode (Rui Sousa)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Mmaped sound is now fully functional. (Rui Sousa)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Make sure to enable PCI device before reading any of its PCI
-    config information. (fixes potential hotplug problems)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Clean up code a bit and add more internal function documentation.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    AC97 codec access fixes (Adrian Cox)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Big endian fixes (Adrian Cox)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    MIDI support (Adrian Cox)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Detect and report locked-rate AC97 codecs.  If your hardware only
-    supports 48Khz (locked rate), then your recording/playback software
-    must upsample or downsample accordingly.  The hardware cannot do it.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Use new pci_request_regions and pci_disable_device functions in
-    kernel 2.4.6.
-    </para>
-   </listitem>
-
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version1114"><title>
-Version 1.1.14
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    Use VM_RESERVE when available, to eliminate unnecessary page faults.
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version1112"><title>
-Version 1.1.12
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    mmap bug fixes from Linus.
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version1111"><title>
-Version 1.1.11
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    Many more bug fixes.  mmap enabled by default, but may still be buggy.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Uses new and spiffy method of mmap'ing the DMA buffer, based
-    on a suggestion from Linus.
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version1110"><title>
-Version 1.1.10
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    Many bug fixes.  mmap enabled by default, but may still be buggy.
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version119"><title>
-Version 1.1.9
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-    Redesign and rewrite audio playback implementation.  (faster and smaller, 
hopefully)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Implement recording and full duplex (DSP_CAP_DUPLEX) support.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Make procfs support optional.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Quick interrupt status check, to lessen overhead in interrupt
-    sharing situations.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Add mmap(2) support.  Disabled for now, it is still buggy and experimental.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Surround all syscalls with a semaphore for cheap and easy SMP protection.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Fix bug in channel shutdown (hardware channel reset) code.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Remove unnecessary spinlocks (better performance).
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Eliminate "unknown AFMT" message by using a different method
-    of selecting the best AFMT_xxx sound sample format for use.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Support for realtime hardware pointer position reporting
-    (DSP_CAP_REALTIME, SNDCTL_DSP_GETxPTR ioctls)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Support for capture/playback triggering
-    (DSP_CAP_TRIGGER, SNDCTL_DSP_SETTRIGGER ioctls)
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    SNDCTL_DSP_SETDUPLEX and SNDCTL_DSP_POST ioctls now handled.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Rewrite open(2) and close(2) logic to allow only one user at
-    a time.  All other open(2) attempts will sleep until they succeed.
-    FIXME: open(O_RDONLY) and open(O_WRONLY) should be allowed to succeed.
-    </para>
-   </listitem>
-
-   <listitem>
-    <para>
-    Reviewed code to ensure that SMP and multiple audio devices
-    are fully supported.
-    </para>
-   </listitem>
-
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version118"><title>
-Version 1.1.8
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
-       Clean up interrupt handler output.  Fixes the following kernel error 
message:
-    </para>
-       <programlisting>
-       unhandled interrupt ...
-       </programlisting>
-   </listitem>
-
-   <listitem>
-    <para>
-       Convert documentation to DocBook, so that PDF, HTML and PostScript 
(.ps) output is readily
-       available.
-    </para>
-   </listitem>
-
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version117"><title>
-Version 1.1.7
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
- Fix module unload bug where mixer device left registered
-  after driver exit
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version116"><title>
-Version 1.1.6
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
- Rewrite via_set_rate to mimic ALSA basic AC97 rate setting
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Remove much dead code
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Complete spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Fix build problem in via_dsp_ioctl
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Optimize included headers to eliminate headers found in linux/sound
-       </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version115"><title>
-Version 1.1.5
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
- Disable some overly-verbose debugging code
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Remove unnecessary sound locks
-   </para>
-   </listitem>
-   <listitem>
-    <para>
- Fix some ioctls for better time resolution
-    </para>
-   </listitem>
-   <listitem>
-    <para>
- Begin spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-<sect1 id="version114"><title>
-Version 1.1.4
-</title>
-  <itemizedlist spacing="compact">
-   <listitem>
-    <para>
- Completed rewrite of driver.  Eliminated SoundBlaster compatibility
-  completely, and now uses the much-faster scatter-gather DMA engine.
-    </para>
-   </listitem>
-  </itemizedlist>
-</sect1>
-
-  </chapter>
-  
-  <chapter id="intfunctions">
-     <title>Internal Functions</title>
-!Isound/oss/via82cxxx_audio.c
-  </chapter>
-
-</book>
-
-
diff -urN linux/Documentation/RCU/RTFP.txt linux/Documentation/RCU/RTFP.txt
--- linux/Documentation/RCU/RTFP.txt    2004/10/12 01:45:39     1.2
+++ linux/Documentation/RCU/RTFP.txt    2005/05/19 12:08:05     1.3
@@ -108,8 +108,9 @@
 2004 has seen a Linux-Journal article on use of RCU in dcache
 [McKenney04a], a performance comparison of locking to RCU on several
 different CPUs [McKenney04b], a dissertation describing use of RCU in a
-number of operating-system kernels [PaulEdwardMcKenneyPhD], and a paper
-describing how to make RCU safe for soft-realtime applications [Sarma04c].
+number of operating-system kernels [PaulEdwardMcKenneyPhD], a paper
+describing how to make RCU safe for soft-realtime applications [Sarma04c],
+and a paper describing SELinux performance with RCU [JamesMorris04b].
 
 
 Bibtex Entries
@@ -341,6 +342,17 @@
 ,pages="18-26"
 }
 
+@techreport{Friedberg03a
+,author="Stuart A. Friedberg"
+,title="Lock-Free Wild Card Search Data Structure and Method"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="2003"
+,number="US Patent 6,662,184 (contributed under GPL)"
+,month="December"
+,pages="112"
+}
+
 @article{McKenney04a
 ,author="Paul E. McKenney and Dipankar Sarma and Maneesh Soni"
 ,title="Scaling dcache with {RCU}"
@@ -373,6 +385,9 @@
 ,school="OGI School of Science and Engineering at
 Oregon Health and Sciences University"
 ,year="2004"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/RCUdissertation.2004.07.14e1.pdf}
+[Viewed October 15, 2004]"
 }
 
 @Conference{Sarma04c
@@ -385,3 +400,13 @@
 ,month="June"
 ,pages="182-191"
 }
+
+@unpublished{JamesMorris04b
+,Author="James Morris"
+,Title="Recent Developments in {SELinux} Kernel Performance"
+,month="December"
+,year="2004"
+,note="Available:
+\url{http://www.livejournal.com/users/james_morris/2153.html}
+[Viewed December 10, 2004]"
+}
diff -urN linux/Documentation/RCU/UP.txt linux/Documentation/RCU/UP.txt
--- linux/Documentation/RCU/UP.txt      2004/10/12 01:45:39     1.2
+++ linux/Documentation/RCU/UP.txt      2005/05/19 12:08:05     1.3
@@ -2,11 +2,11 @@
 
 
 A common misconception is that, on UP systems, the call_rcu() primitive
-may immediately invoke its function, and that the synchronize_kernel
+may immediately invoke its function, and that the synchronize_rcu()
 primitive may return immediately.  The basis of this misconception
 is that since there is only one CPU, it should not be necessary to
 wait for anything else to get done, since there are no other CPUs for
-anything else to be happening on.  Although this approach will sort of
+anything else to be happening on.  Although this approach will -sort- -of-
 work a surprising amount of the time, it is a very bad idea in general.
 This document presents two examples that demonstrate exactly how bad an
 idea this is.
@@ -44,14 +44,14 @@
 underlying RCU, namely that call_rcu() defers invoking its arguments until
 all RCU read-side critical sections currently executing have completed.
 
-Quick Quiz: why is it -not- legal to invoke synchronize_kernel() in
+Quick Quiz: why is it -not- legal to invoke synchronize_rcu() in
 this case?
 
 
 Summary
 
 Permitting call_rcu() to immediately invoke its arguments or permitting
-synchronize_kernel() to immediately return breaks RCU, even on a UP system.
+synchronize_rcu() to immediately return breaks RCU, even on a UP system.
 So do not do it!  Even on a UP system, the RCU infrastructure -must-
 respect grace periods.
 
diff -urN linux/Documentation/RCU/checklist.txt 
linux/Documentation/RCU/checklist.txt
--- linux/Documentation/RCU/checklist.txt       2004/09/19 12:30:00     1.1
+++ linux/Documentation/RCU/checklist.txt       2005/05/19 12:08:05     1.2
@@ -32,7 +32,10 @@
        them -- even x86 allows reads to be reordered), and be prepared
        to explain why this added complexity is worthwhile.  If you
        choose #c, be prepared to explain how this single task does not
-       become a major bottleneck on big multiprocessor machines.
+       become a major bottleneck on big multiprocessor machines (for
+       example, if the task is updating information relating to itself
+       that other tasks can read, there by definition can be no
+       bottleneck).
 
 2.     Do the RCU read-side critical sections make proper use of
        rcu_read_lock() and friends?  These primitives are needed
@@ -89,27 +92,34 @@
                "_rcu()" list-traversal primitives, such as the
                list_for_each_entry_rcu().
 
-       b.      If the list macros are being used, the list_del_rcu(),
-               list_add_tail_rcu(), and list_del_rcu() primitives must
-               be used in order to prevent weakly ordered machines from
-               misordering structure initialization and pointer planting.
+       b.      If the list macros are being used, the list_add_tail_rcu()
+               and list_add_rcu() primitives must be used in order
+               to prevent weakly ordered machines from misordering
+               structure initialization and pointer planting.
                Similarly, if the hlist macros are being used, the
-               hlist_del_rcu() and hlist_add_head_rcu() primitives
-               are required.
+               hlist_add_head_rcu() primitive is required.
 
-       c.      Updates must ensure that initialization of a given
+       c.      If the list macros are being used, the list_del_rcu()
+               primitive must be used to keep list_del()'s pointer
+               poisoning from inflicting toxic effects on concurrent
+               readers.  Similarly, if the hlist macros are being used,
+               the hlist_del_rcu() primitive is required.
+
+               The list_replace_rcu() primitive may be used to
+               replace an old structure with a new one in an
+               RCU-protected list.
+
+       d.      Updates must ensure that initialization of a given
                structure happens before pointers to that structure are
                publicized.  Use the rcu_assign_pointer() primitive
                when publicizing a pointer to a structure that can
                be traversed by an RCU read-side critical section.
 
-               [The rcu_assign_pointer() primitive is in process.]
-
 5.     If call_rcu(), or a related primitive such as call_rcu_bh(),
        is used, the callback function must be written to be called
        from softirq context.  In particular, it cannot block.
 
-6.     Since synchronize_kernel() blocks, it cannot be called from
+6.     Since synchronize_rcu() can block, it cannot be called from
        any sort of irq context.
 
 7.     If the updater uses call_rcu(), then the corresponding readers
@@ -125,9 +135,9 @@
        such cases is a must, of course!  And the jury is still out on
        whether the increased speed is worth it.
 
-8.     Although synchronize_kernel() is a bit slower than is call_rcu(),
+8.     Although synchronize_rcu() is a bit slower than is call_rcu(),
        it usually results in simpler code.  So, unless update performance
-       is important or the updaters cannot block, synchronize_kernel()
+       is important or the updaters cannot block, synchronize_rcu()
        should be used in preference to call_rcu().
 
 9.     All RCU list-traversal primitives, which include
@@ -155,3 +165,14 @@
        you -must- use the "_rcu()" variants of the list macros.
        Failing to do so will break Alpha and confuse people reading
        your code.
+
+11.    Note that synchronize_rcu() -only- guarantees to wait until
+       all currently executing rcu_read_lock()-protected RCU read-side
+       critical sections complete.  It does -not- necessarily guarantee
+       that all currently running interrupts, NMIs, preempt_disable()
+       code, or idle loops will complete.  Therefore, if you do not have
+       rcu_read_lock()-protected read-side critical sections, do -not-
+       use synchronize_rcu().
+
+       If you want to wait for some of these other things, you might
+       instead need to use synchronize_irq() or synchronize_sched().
diff -urN linux/Documentation/RCU/listRCU.txt 
linux/Documentation/RCU/listRCU.txt
--- linux/Documentation/RCU/listRCU.txt 2004/11/15 11:49:12     1.3
+++ linux/Documentation/RCU/listRCU.txt 2005/05/19 12:08:05     1.4
@@ -32,6 +32,7 @@
                enum audit_state   state;
 
                read_lock(&auditsc_lock);
+               /* Note: audit_netlink_sem held by caller. */
                list_for_each_entry(e, &audit_tsklist, list) {
                        if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
                                read_unlock(&auditsc_lock);
@@ -55,6 +56,7 @@
                enum audit_state   state;
 
                rcu_read_lock();
+               /* Note: audit_netlink_sem held by caller. */
                list_for_each_entry_rcu(e, &audit_tsklist, list) {
                        if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
                                rcu_read_unlock();
@@ -139,12 +141,15 @@
 a spin_lock() and a spin_unlock(), but in this case, all callers hold
 audit_netlink_sem, so no additional locking is required.  The auditsc_lock
 can therefore be eliminated, since use of RCU eliminates the need for
-writers to exclude readers.
+writers to exclude readers.  Normally, the write_lock() calls would
+be converted into spin_lock() calls.
 
 The list_del(), list_add(), and list_add_tail() primitives have been
 replaced by list_del_rcu(), list_add_rcu(), and list_add_tail_rcu().
 The _rcu() list-manipulation primitives add memory barriers that are
-needed on weakly ordered CPUs (most of them!).
+needed on weakly ordered CPUs (most of them!).  The list_del_rcu()
+primitive omits the pointer poisoning debug-assist code that would
+otherwise cause concurrent readers to fail spectacularly.
 
 So, when readers can tolerate stale data and when entries are either added
 or deleted, without in-place modification, it is very easy to use RCU!
@@ -166,6 +171,7 @@
                struct audit_newentry *ne;
 
                write_lock(&auditsc_lock);
+               /* Note: audit_netlink_sem held by caller. */
                list_for_each_entry(e, list, list) {
                        if (!audit_compare_rule(rule, &e->rule)) {
                                e->rule.action = newaction;
@@ -199,8 +205,7 @@
                                audit_copy_rule(&ne->rule, &e->rule);
                                ne->rule.action = newaction;
                                ne->rule.file_count = newfield_count;
-                               list_add_rcu(ne, e);
-                               list_del(e);
+                               list_replace_rcu(e, ne);
                                call_rcu(&e->rcu, audit_free_rule, e);
                                return 0;
                        }
diff -urN linux/Documentation/RCU/rcu.txt linux/Documentation/RCU/rcu.txt
--- linux/Documentation/RCU/rcu.txt     2004/10/12 01:45:39     1.2
+++ linux/Documentation/RCU/rcu.txt     2005/05/19 12:08:05     1.3
@@ -43,7 +43,9 @@
 
 o      How can I see where RCU is currently used in the Linux kernel?
 
-       Search for "rcu_read_lock", "call_rcu", and "synchronize_kernel".
+       Search for "rcu_read_lock", "rcu_read_unlock", "call_rcu",
+       "rcu_read_lock_bh", "rcu_read_unlock_bh", "call_rcu_bh",
+       "synchronize_rcu", and "synchronize_net".
 
 o      What guidelines should I follow when writing code that uses RCU?
 
diff -urN linux/Documentation/aoe/aoe.txt linux/Documentation/aoe/aoe.txt
--- linux/Documentation/aoe/aoe.txt     2005/03/18 17:36:43     1.3
+++ linux/Documentation/aoe/aoe.txt     2005/05/19 12:08:05     1.4
@@ -4,6 +4,16 @@
 
   It has many tips and hints!
 
+The aoetools are userland programs that are designed to work with this
+driver.  The aoetools are on sourceforge.
+
+  http://aoetools.sourceforge.net/
+
+The scripts in this Documentation/aoe directory are intended to
+document the use of the driver and are not necessary if you install
+the aoetools.
+
+
 CREATING DEVICE NODES
 
   Users of udev should find the block device nodes created
@@ -35,14 +45,15 @@
 
   "echo eth2 eth4 > /dev/etherd/interfaces" tells the aoe driver to
   limit ATA over Ethernet traffic to eth2 and eth4.  AoE traffic from
-  untrusted networks should be ignored as a matter of security.
+  untrusted networks should be ignored as a matter of security.  See
+  also the aoe_iflist driver option described below.
 
   "echo > /dev/etherd/discover" tells the driver to find out what AoE
   devices are available.
 
   These character devices may disappear and be replaced by sysfs
-  counterparts, so distribution maintainers are encouraged to create
-  scripts that use these devices.
+  counterparts.  Using the commands in aoetools insulates users from
+  these implementation details.
 
   The block devices are named like this:
 
@@ -66,7 +77,8 @@
   through which we are communicating with the remote AoE device.
 
   There is a script in this directory that formats this information
-  in a convenient way.
+  in a convenient way.  Users with aoetools can use the aoe-stat
+  command.
 
   root@makki root# sh Documentation/aoe/status.sh 
      e10.0            eth3              up
@@ -89,3 +101,23 @@
       e4.7            eth1              up
       e4.8            eth1              up
       e4.9            eth1              up
+
+  Use /sys/module/aoe/parameters/aoe_iflist (or better, the driver
+  option discussed below) instead of /dev/etherd/interfaces to limit
+  AoE traffic to the network interfaces in the given
+  whitespace-separated list.  Unlike the old character device, the
+  sysfs entry can be read from as well as written to.
+
+  It's helpful to trigger discovery after setting the list of allowed
+  interfaces.  The aoetools package provides an aoe-discover script
+  for this purpose.  You can also directly use the
+  /dev/etherd/discover special file described above.
+
+DRIVER OPTIONS
+
+  There is a boot option for the built-in aoe driver and a
+  corresponding module parameter, aoe_iflist.  Without this option,
+  all network interfaces may be used for ATA over Ethernet.  Here is a
+  usage example for the module parameter.
+
+    modprobe aoe_iflist="eth1 eth3"
diff -urN linux/Documentation/aoe/status.sh linux/Documentation/aoe/status.sh
--- linux/Documentation/aoe/status.sh   2005/03/18 17:36:43     1.3
+++ linux/Documentation/aoe/status.sh   2005/05/19 12:08:05     1.4
@@ -14,10 +14,6 @@
        echo "$me Error: sysfs is not mounted" 1>&2
        exit 1
 }
-test -z "`lsmod | grep '^aoe'`" && {
-       echo  "$me Error: aoe module is not loaded" 1>&2
-       exit 1
-}
 
 for d in `ls -d $sysd/block/etherd* 2>/dev/null | grep -v p` end; do
        # maybe ls comes up empty, so we use "end"
diff -urN linux/Documentation/filesystems/Locking 
linux/Documentation/filesystems/Locking
--- linux/Documentation/filesystems/Locking     2005/03/18 17:36:44     1.37
+++ linux/Documentation/filesystems/Locking     2005/05/19 12:08:05     1.38
@@ -219,8 +219,12 @@
 If the filesytem is called for sync then it must wait on any
 in-progress I/O and then start new I/O.
 
-The filesystem should unlock the page synchronously, before returning
-to the caller.
+The filesystem should unlock the page synchronously, before returning to the
+caller, unless ->writepage() returns special WRITEPAGE_ACTIVATE
+value. WRITEPAGE_ACTIVATE means that page cannot really be written out
+currently, and VM should stop calling ->writepage() on this page for some
+time. VM does this by moving page to the head of the active list, hence the
+name.
 
 Unless the filesystem is going to redirty_page_for_writepage(), unlock the page
 and return zero, writepage *must* run set_page_writeback() against the page,
diff -urN linux/Documentation/filesystems/proc.txt 
linux/Documentation/filesystems/proc.txt
--- linux/Documentation/filesystems/proc.txt    2005/03/18 17:36:44     1.33
+++ linux/Documentation/filesystems/proc.txt    2005/05/19 12:08:05     1.34
@@ -909,16 +909,6 @@
 Represents the  number of free inodes. Ie. The number of inuse inodes is
 (nr_inodes - nr_free_inodes).
 
-super-nr and super-max
-----------------------
-
-Again, super  block structures are allocated by the kernel, but not freed. The
-file super-max  contains  the  maximum  number  of super block handlers, where
-super-nr shows the number of currently allocated ones.
-
-Every mounted file system needs a super block, so if you plan to mount lots of
-file systems, you may want to increase these numbers.
-
 aio-nr and aio-max-nr
 ---------------------
 
diff -urN linux/Documentation/i386/zero-page.txt 
linux/Documentation/i386/zero-page.txt
--- linux/Documentation/i386/zero-page.txt      2005/01/13 14:05:15     1.10
+++ linux/Documentation/i386/zero-page.txt      2005/05/19 12:08:05     1.11
@@ -79,6 +79,6 @@
 0x22c   unsigned long  ramdisk_max
 0x230   16 bytes       trampoline
 0x290 - 0x2cf          EDD_MBR_SIG_BUFFER (edd.S)
-0x2d0 - 0x600          E820MAP
-0x600 - 0x7ff          EDDBUF (edd.S) for disk signature read sector
-0x600 - 0x7eb          EDDBUF (edd.S) for edd data
+0x2d0 - 0xd00          E820MAP
+0xd00 - 0xeff          EDDBUF (edd.S) for disk signature read sector
+0xd00 - 0xeeb          EDDBUF (edd.S) for edd data
diff -urN linux/Documentation/networking/DLINK.txt 
linux/Documentation/networking/DLINK.txt
--- linux/Documentation/networking/DLINK.txt    2003/08/15 15:14:29     1.5
+++ linux/Documentation/networking/DLINK.txt    2005/05/19 12:08:05     1.6
@@ -178,10 +178,9 @@
        7. ACKNOWLEDGMENTS.
 
        These drivers wouldn't have been done without the base
-       (and support) from Ross Biro <bir7@leland.stanford.edu>,
-       and D-Link Systems Inc.  The driver relies upon GPL-ed
-       source from D-Link Systems Inc. and from Russel Nelson at
-       Crynwr Software <nelson@crynwr.com>.
+       (and support) from Ross Biro, and D-Link Systems Inc.
+       The driver relies upon GPL-ed source from D-Link Systems Inc.
+       and from Russel Nelson at Crynwr Software <nelson@crynwr.com>.
 
        Additional input also from:
        Donald Becker <becker@super.org>, Alan Cox <A.Cox@swansea.ac.uk>
diff -urN linux/Documentation/networking/netdevices.txt 
linux/Documentation/networking/netdevices.txt
--- linux/Documentation/networking/netdevices.txt       2005/02/07 02:54:30     
1.7
+++ linux/Documentation/networking/netdevices.txt       2005/05/19 12:08:05     
1.8
@@ -51,6 +51,8 @@
        set_multicast_list
        Context: BHs disabled
        Notes: netif_queue_stopped() is guaranteed false
+               Interrupts must be enabled when calling hard_start_xmit.
+                (Interrupts must also be enabled when enabling the BH handler.)
        Return codes: 
        o NETDEV_TX_OK everything ok. 
        o NETDEV_TX_BUSY Cannot transmit packet, try later 
diff -urN linux/Documentation/power/pci.txt linux/Documentation/power/pci.txt
--- linux/Documentation/power/pci.txt   2004/10/25 20:44:09     1.5
+++ linux/Documentation/power/pci.txt   2005/05/19 12:08:06     1.6
@@ -165,40 +165,9 @@
 These functions are intended for use by individual drivers, and are defined in 
 struct pci_driver:
 
-        int  (*save_state) (struct pci_dev *dev, u32 state);
-        int  (*suspend) (struct pci_dev *dev, u32 state);
+        int  (*suspend) (struct pci_dev *dev, pm_message_t state);
         int  (*resume) (struct pci_dev *dev);
-        int  (*enable_wake) (struct pci_dev *dev, u32 state, int enable);
-
-
-save_state
-----------
-
-Usage:
-
-if (dev->driver && dev->driver->save_state)
-       dev->driver->save_state(dev,state);
-
-The driver should use this callback to save device state. It should take into
-account the current state of the device and the requested state in order to
-avoid any unnecessary operations.
-
-For example, a video card that supports all 4 states (D0-D3), all controller
-context is preserved when entering D1, but the screen is placed into a low 
power
-state (blanked). 
-
-The driver can also interpret this function as a notification that it may be
-entering a sleep state in the near future. If it knows that the device cannot
-enter the requested state, either because of lack of support for it, or because
-the device is middle of some critical operation, then it should fail.
-
-This function should not be used to set any state in the device or the driver
-because the device may not actually enter the sleep state (e.g. another driver
-later causes causes a global state transition to fail).
-
-Note that in intermediate low power states, a device's I/O and memory spaces 
may
-be disabled and may not be available in subsequent transitions to lower power
-states.
+        int  (*enable_wake) (struct pci_dev *dev, pci_power_t state, int 
enable);
 
 
 suspend
diff -urN linux/Documentation/s390/cds.txt linux/Documentation/s390/cds.txt
--- linux/Documentation/s390/cds.txt    2003/06/05 00:04:29     1.11
+++ linux/Documentation/s390/cds.txt    2005/05/19 12:08:06     1.12
@@ -56,12 +56,16 @@
    read device characteristics
    
 read_conf_data()
+read_conf_data_lpm()
    read configuration data.
 
 ccw_device_get_ciw()
    get commands from extended sense data.
 
 ccw_device_start()     
+ccw_device_start_timeout()
+ccw_device_start_key()
+ccw_device_start_key_timeout()
    initiate an I/O request.
 
 ccw_device_resume()
@@ -197,19 +201,21 @@
           operational.
 
 
-read_conf_data() - Read Configuration Data
+read_conf_data(), read_conf_data_lpm() - Read Configuration Data
 
 Retrieve the device dependent configuration data. Please have a look at your 
 device dependent I/O commands for the device specific layout of the node 
-descriptor elements. 
+descriptor elements. read_conf_data_lpm() will retrieve the configuration data
+for a specific path.
 
-The function is meant to be called with an irq handler in place; that is,
+The function is meant to be called with the device already enabled; that is,
 at earliest during set_online() processing.
 
 The function may be called enabled or disabled, but the device must not be
 locked
 
-int read_conf_data(struct ccw_device, void **buffer, int *length, __u8 lpm);
+int read_conf_data(struct ccw_device, void **buffer, int *length);
+int read_conf_data_lpm(struct ccw_device, void **buffer, int *length, __u8 
lpm);
 
 cdev   - the ccw_device the data is requested for.
 buffer - Pointer to a buffer pointer. The read_conf_data() routine
@@ -263,6 +269,25 @@
                     unsigned long intparm,
                     __u8 lpm,
                     unsigned long flags);
+int ccw_device_start_timeout(struct ccw_device *cdev,
+                            struct ccw1 *cpa,
+                            unsigned long intparm,
+                            __u8 lpm,
+                            unsigned long flags,
+                            int expires);
+int ccw_device_start_key(struct ccw_device *cdev,
+                        struct ccw1 *cpa,
+                        unsigned long intparm,
+                        __u8 lpm,
+                        __u8 key,
+                        unsigned long flags);
+int ccw_device_start_key_timeout(struct ccw_device *cdev,
+                                struct ccw1 *cpa,
+                                unsigned long intparm,
+                                __u8 lpm,
+                                __u8 key,
+                                unsigned long flags,
+                                int expires);
 
 cdev         : ccw_device the I/O is destined for
 cpa          : logical start address of channel program
@@ -272,7 +297,12 @@
                particular I/O request.
 lpm          : defines the channel path to be used for a specific I/O
                request. A value of 0 will make cio use the opm.
+key         : the storage key to use for the I/O (useful for operating on a
+              storage with a storage key != default key)
 flag         : defines the action to be performed for I/O processing
+expires      : timeout value in jiffies. The common I/O layer will terminate
+              the running program after this and call the interrupt handler
+              with ERR_PTR(-ETIMEDOUT) as irb.
 
 Possible flag values are :
 
@@ -327,6 +357,13 @@
 interrupt will be presented to indicate I/O completion as the I/O request was
 never started, even though ccw_device_start() returned with successful 
completion.
 
+The irb may contain an error value, and the device driver should check for this
+first:
+
+-ETIMEDOUT: the common I/O layer terminated the request after the specified
+            timeout value
+-EIO:       the common I/O layer terminated the request due to an error state
+
 If the concurrent sense flag in the extended status word in the irb is set, the
 field irb->scsw.count describes the numer of device specific sense bytes
 available in the extended control word irb->scsw.ecw[0]. No device sensing by
diff -urN linux/arch/alpha/Kconfig linux/arch/alpha/Kconfig
--- linux/arch/alpha/Kconfig    2005/01/13 14:05:17     1.30
+++ linux/arch/alpha/Kconfig    2005/05/19 12:08:06     1.31
@@ -280,6 +280,10 @@
          (MCA) or VESA.  ISA is an older system, now being displaced by PCI;
          newer boards don't support it.  If you have ISA, say Y, otherwise N.
 
+config ISA_DMA_API
+       bool
+       default y
+
 config PCI
        bool
        depends on !ALPHA_JENSEN
diff -urN linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- linux/arch/alpha/kernel/osf_sys.c   2005/03/18 17:36:45     1.54
+++ linux/arch/alpha/kernel/osf_sys.c   2005/05/19 12:08:06     1.55
@@ -457,22 +457,6 @@
        return 0;
 }
 
-asmlinkage long
-osf_shmat(int shmid, void __user *shmaddr, int shmflg)
-{
-       unsigned long raddr;
-       long err;
-
-       err = do_shmat(shmid, shmaddr, shmflg, &raddr);
-
-       /*
-        * This works because all user-level addresses are
-        * non-negative longs!
-        */
-       return err ? err : (long)raddr;
-}
-
-
 /*
  * The following stuff should move into a header file should it ever
  * be labeled "officially supported."  Right now, there is just enough
diff -urN linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
--- linux/arch/alpha/kernel/ptrace.c    2004/10/25 20:44:09     1.29
+++ linux/arch/alpha/kernel/ptrace.c    2005/05/19 12:08:06     1.30
@@ -14,6 +14,7 @@
 #include <linux/user.h>
 #include <linux/slab.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -335,7 +336,7 @@
                /* continue and stop at next (return from) syscall */
        case PTRACE_CONT:    /* restart after signal. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                if (request == PTRACE_SYSCALL)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -365,7 +366,7 @@
 
        case PTRACE_SINGLESTEP:  /* execute single instruction. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                /* Mark single stepping.  */
                child->thread_info->bpt_nsaved = -1;
diff -urN linux/arch/alpha/kernel/systbls.S linux/arch/alpha/kernel/systbls.S
--- linux/arch/alpha/kernel/systbls.S   2004/10/12 01:45:39     1.12
+++ linux/arch/alpha/kernel/systbls.S   2005/05/19 12:08:06     1.13
@@ -227,7 +227,7 @@
        .quad sys_semop
        .quad osf_utsname
        .quad sys_lchown
-       .quad osf_shmat
+       .quad sys_shmat
        .quad sys_shmctl                        /* 210 */
        .quad sys_shmdt
        .quad sys_shmget
@@ -458,6 +458,9 @@
        .quad sys_mq_notify
        .quad sys_mq_getsetattr
        .quad sys_waitid
+       .quad sys_add_key
+       .quad sys_request_key                   /* 440 */
+       .quad sys_keyctl
 
        .size sys_call_table, . - sys_call_table
        .type sys_call_table, @object
diff -urN linux/arch/arm/Kconfig linux/arch/arm/Kconfig
--- linux/arch/arm/Kconfig      2005/04/08 18:57:47     1.46
+++ linux/arch/arm/Kconfig      2005/05/19 12:08:06     1.47
@@ -85,6 +85,7 @@
 config ARCH_CLPS7500
        bool "Cirrus-CL-PS7500FE"
        select TIMER_ACORN
+       select ISA
 
 config ARCH_CLPS711X
        bool "CLPS711x/EP721x-based"
@@ -96,6 +97,7 @@
 
 config ARCH_EBSA110
        bool "EBSA-110"
+       select ISA
        help
          This is an evaluation board for the StrongARM processor available
          from Digital. It has limited hardware on-board, including an onboard
@@ -120,13 +122,16 @@
 
 config ARCH_IOP3XX
        bool "IOP3xx-based"
+       select PCI
 
 config ARCH_IXP4XX
        bool "IXP4xx-based"
        select DMABOUNCE
+       select PCI
 
 config ARCH_IXP2000
        bool "IXP2400/2800-based"
+       select PCI
 
 config ARCH_L7200
        bool "LinkUp-L7200"
@@ -155,6 +160,8 @@
 
 config ARCH_SA1100
        bool "SA1100-based"
+       select ISA
+       select DISCONTIGMEM
 
 config ARCH_S3C2410
        bool "Samsung S3C2410"
@@ -165,6 +172,9 @@
 
 config ARCH_SHARK
        bool "Shark"
+       select ISA
+       select ISA_DMA
+       select PCI
 
 config ARCH_LH7A40X
        bool "Sharp LH7A40X"
@@ -252,8 +262,6 @@
 
 config ISA
        bool
-       depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || 
ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 || ARCH_MX1ADS
-       default y
        help
          Find out whether you have ISA slots on your motherboard.  ISA is the
          name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -263,12 +271,13 @@
 
 config ISA_DMA
        bool
-       depends on FOOTBRIDGE_HOST || ARCH_SHARK
+
+config ISA_DMA_API
+       bool
        default y
 
 config PCI
        bool "PCI support" if ARCH_INTEGRATOR_AP
-       default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || 
ARCH_IXP4XX || ARCH_IXP2000
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
@@ -296,7 +305,7 @@
 
 config SMP
        bool "Symmetric Multi-Processing (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && n
+       depends on EXPERIMENTAL #&& n
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
@@ -336,8 +345,7 @@
 
 config DISCONTIGMEM
        bool
-       depends on ARCH_EDB7211 || ARCH_SA1100 || (ARCH_LH7A40X && 
!LH7A40X_CONTIGMEM)
-       default y
+       default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
        help
          Say Y to support efficient handling of discontiguous physical memory,
          for architectures which are either NUMA (Non-Uniform Memory Access)
diff -urN linux/arch/arm/boot/compressed/head.S 
linux/arch/arm/boot/compressed/head.S
--- linux/arch/arm/boot/compressed/head.S       2004/12/04 18:15:57     1.36
+++ linux/arch/arm/boot/compressed/head.S       2005/05/19 12:08:06     1.37
@@ -18,48 +18,30 @@
  * Please select one of the following when turning on debugging.
  */
 #ifdef DEBUG
-#if defined(CONFIG_DEBUG_DC21285_PORT)
-               .macro  loadsp, rb
-               mov     \rb, #0x42000000
-               .endm
-               .macro  writeb, rb
-               str     \rb, [r3, #0x160]
-               .endm
-#elif defined(CONFIG_DEBUG_ICEDCC)
+
+#include <asm/arch/debug-macro.S>
+
+#if defined(CONFIG_DEBUG_ICEDCC)
                .macro  loadsp, rb
                .endm
-               .macro writeb, rb
-               mcr     p14, 0, \rb, c0, c1, 0
-               .endm
-#elif defined(CONFIG_FOOTBRIDGE)
-               .macro  loadsp, rb
-               mov     \rb, #0x7c000000
+               .macro writeb, ch, rb
+               mcr     p14, 0, \ch, c0, c1, 0
                .endm
-               .macro  writeb, rb
-               strb    \rb, [r3, #0x3f8]
+#else
+               .macro  writeb, ch, rb
+               senduart \ch, \rb
                .endm
-#elif defined(CONFIG_ARCH_RPC)
+
+#if defined(CONFIG_FOOTBRIDGE) || \
+    defined(CONFIG_ARCH_RPC) || \
+    defined(CONFIG_ARCH_INTEGRATOR) || \
+    defined(CONFIG_ARCH_PXA) || \
+    defined(CONFIG_ARCH_IXP4XX) || \
+    defined(CONFIG_ARCH_IXP2000) || \
+    defined(CONFIG_ARCH_LH7A40X) || \
+    defined(CONFIG_ARCH_OMAP)
                .macro  loadsp, rb
-               mov     \rb, #0x03000000
-               orr     \rb, \rb, #0x00010000
-               .endm
-               .macro  writeb, rb
-               strb    \rb, [r3, #0x3f8 << 2]
-               .endm
-#elif defined(CONFIG_ARCH_INTEGRATOR)
-               .macro  loadsp, rb
-               mov     \rb, #0x16000000
-               .endm
-               .macro  writeb, rb
-               strb    \rb, [r3, #0]
-               .endm
-#elif defined(CONFIG_ARCH_PXA) /* Xscale-type */
-               .macro  loadsp, rb
-               mov     \rb, #0x40000000
-               orr     \rb, \rb, #0x00100000
-               .endm
-               .macro  writeb, rb
-               strb    \rb, [r3, #0]
+               addruart \rb
                .endm
 #elif defined(CONFIG_ARCH_SA1100)
                .macro  loadsp, rb
@@ -70,65 +52,22 @@
                add     \rb, \rb, #0x00010000   @ Ser1
 #  endif
                .endm
-               .macro  writeb, rb
-               str     \rb, [r3, #0x14]        @ UTDR
-               .endm
-#elif defined(CONFIG_ARCH_IXP4XX)
-               .macro  loadsp, rb
-               mov     \rb, #0xc8000000
-               .endm
-               .macro  writeb, rb
-               str     \rb, [r3, #0]
-#elif defined(CONFIG_ARCH_IXP2000)
-               .macro  loadsp, rb
-               mov     \rb, #0xc0000000
-               orr     \rb, \rb, #0x00030000
-               .endm
-               .macro  writeb, rb
-               str     \rb, [r3, #0]
-               .endm
-#elif defined(CONFIG_ARCH_LH7A40X)
-               .macro  loadsp, rb
-               ldr     \rb, =0x80000700        @ UART2 UARTBASE
-               .endm
-               .macro  writeb, rb
-               strb    \rb, [r3, #0]
-               .endm
-#elif defined(CONFIG_ARCH_OMAP)
-               .macro  loadsp, rb
-               mov     \rb, #0xff000000        @ physical base address
-               add     \rb, \rb, #0x00fb0000
-#if defined(CONFIG_OMAP_LL_DEBUG_UART2) || defined(CONFIG_OMAP_LL_DEBUG_UART3)
-               add     \rb, \rb, #0x00000800
-#endif
-#ifdef CONFIG_OMAP_LL_DEBUG_UART3
-               add     \rb, \rb, #0x00009000
-#endif
-               .endm
-               .macro  writeb, rb
-               strb    \rb, [r3]
-               .endm
 #elif defined(CONFIG_ARCH_IOP331)
                .macro loadsp, rb
                 mov    \rb, #0xff000000
                 orr     \rb, \rb, #0x00ff0000
                 orr     \rb, \rb, #0x0000f700   @ location of the UART
                .endm
-               .macro  writeb, rb
-               str     \rb, [r3, #0]
-               .endm
 #elif defined(CONFIG_ARCH_S3C2410)
-                       .macro loadsp, rb
+               .macro loadsp, rb
                mov     \rb, #0x50000000
                add     \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT
                .endm
-               .macro  writeb, rb
-               strb    \rb, [r3, #0x20]
-               .endm
 #else
 #error no serial architecture defined
 #endif
 #endif
+#endif
 
                .macro  kputc,val
                mov     r0, \val
@@ -734,7 +673,7 @@
 1:             ldrb    r2, [r0], #1
                teq     r2, #0
                moveq   pc, lr
-2:             writeb  r2
+2:             writeb  r2, r3
                mov     r1, #0x00020000
 3:             subs    r1, r1, #1
                bne     3b
diff -urN linux/arch/arm/common/rtctime.c linux/arch/arm/common/rtctime.c
--- linux/arch/arm/common/rtctime.c     2005/03/18 17:36:45     1.5
+++ linux/arch/arm/common/rtctime.c     2005/05/19 12:08:06     1.6
@@ -141,10 +141,10 @@
        next->tm_sec = alrm->tm_sec;
 }
 
-static inline void rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm)
+static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm)
 {
        memset(tm, 0, sizeof(struct rtc_time));
-       ops->read_time(tm);
+       return ops->read_time(tm);
 }
 
 static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm)
@@ -163,8 +163,7 @@
        int ret = -EINVAL;
        if (ops->read_alarm) {
                memset(alrm, 0, sizeof(struct rtc_wkalrm));
-               ops->read_alarm(alrm);
-               ret = 0;
+               ret = ops->read_alarm(alrm);
        }
        return ret;
 }
@@ -283,7 +282,9 @@
                break;
 
        case RTC_RD_TIME:
-               rtc_read_time(ops, &tm);
+               ret = rtc_read_time(ops, &tm);
+               if (ret)
+                       break;
                ret = copy_to_user(uarg, &tm, sizeof(tm));
                if (ret)
                        ret = -EFAULT;
@@ -424,15 +425,15 @@
        struct rtc_time tm;
        char *p = page;
 
-       rtc_read_time(ops, &tm);
-
-       p += sprintf(p,
-               "rtc_time\t: %02d:%02d:%02d\n"
-               "rtc_date\t: %04d-%02d-%02d\n"
-               "rtc_epoch\t: %04lu\n",
-               tm.tm_hour, tm.tm_min, tm.tm_sec,
-               tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-               rtc_epoch);
+       if (rtc_read_time(ops, &tm) == 0) {
+               p += sprintf(p,
+                       "rtc_time\t: %02d:%02d:%02d\n"
+                       "rtc_date\t: %04d-%02d-%02d\n"
+                       "rtc_epoch\t: %04lu\n",
+                       tm.tm_hour, tm.tm_min, tm.tm_sec,
+                       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+                       rtc_epoch);
+       }
 
        if (rtc_read_alarm(ops, &alrm) == 0) {
                p += sprintf(p, "alrm_time\t: ");
diff -urN linux/arch/arm/configs/ixdp2800_defconfig 
linux/arch/arm/configs/ixdp2800_defconfig
--- linux/arch/arm/configs/ixdp2800_defconfig   2005/04/08 18:57:49     1.2
+++ linux/arch/arm/configs/ixdp2800_defconfig   2005/05/19 12:08:06     1.3
@@ -133,7 +133,7 @@
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/nfs ip=bootp mem=64M@0x0 
pci=firmware"
+CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/nfs ip=bootp mem=64M@0x0"
 # CONFIG_XIP_KERNEL is not set
 
 #
diff -urN linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile
--- linux/arch/arm/kernel/Makefile      2005/01/13 14:05:18     1.41
+++ linux/arch/arm/kernel/Makefile      2005/05/19 12:08:06     1.42
@@ -31,8 +31,3 @@
 obj-$(CONFIG_DEBUG_LL) += debug.o
 
 extra-y := $(head-y) init_task.o vmlinux.lds
-
-# Spell out some dependencies that aren't automatically figured out
-$(obj)/entry-armv.o:   $(obj)/entry-header.S include/asm-arm/constants.h
-$(obj)/entry-common.o:         $(obj)/entry-header.S 
include/asm-arm/constants.h \
-                       $(obj)/calls.S
diff -urN linux/arch/arm/kernel/asm-offsets.c 
linux/arch/arm/kernel/asm-offsets.c
--- linux/arch/arm/kernel/asm-offsets.c 2005/02/07 02:54:30     1.12
+++ linux/arch/arm/kernel/asm-offsets.c 2005/05/19 12:08:06     1.13
@@ -64,6 +64,26 @@
   DEFINE(TI_VFPSTATE,          offsetof(struct thread_info, vfpstate));
   DEFINE(TI_IWMMXT_STATE,      (offsetof(struct thread_info, fpstate)+4)&~7);
   BLANK();
+  DEFINE(S_R0,                 offsetof(struct pt_regs, ARM_r0));
+  DEFINE(S_R1,                 offsetof(struct pt_regs, ARM_r1));
+  DEFINE(S_R2,                 offsetof(struct pt_regs, ARM_r2));
+  DEFINE(S_R3,                 offsetof(struct pt_regs, ARM_r3));
+  DEFINE(S_R4,                 offsetof(struct pt_regs, ARM_r4));
+  DEFINE(S_R5,                 offsetof(struct pt_regs, ARM_r5));
+  DEFINE(S_R6,                 offsetof(struct pt_regs, ARM_r6));
+  DEFINE(S_R7,                 offsetof(struct pt_regs, ARM_r7));
+  DEFINE(S_R8,                 offsetof(struct pt_regs, ARM_r8));
+  DEFINE(S_R9,                 offsetof(struct pt_regs, ARM_r9));
+  DEFINE(S_R10,                        offsetof(struct pt_regs, ARM_r10));
+  DEFINE(S_FP,                 offsetof(struct pt_regs, ARM_fp));
+  DEFINE(S_IP,                 offsetof(struct pt_regs, ARM_ip));
+  DEFINE(S_SP,                 offsetof(struct pt_regs, ARM_sp));
+  DEFINE(S_LR,                 offsetof(struct pt_regs, ARM_lr));
+  DEFINE(S_PC,                 offsetof(struct pt_regs, ARM_pc));
+  DEFINE(S_PSR,                        offsetof(struct pt_regs, ARM_cpsr));
+  DEFINE(S_OLD_R0,             offsetof(struct pt_regs, ARM_ORIG_r0));
+  DEFINE(S_FRAME_SIZE,         sizeof(struct pt_regs));
+  BLANK();
 #if __LINUX_ARM_ARCH__ >= 6
   DEFINE(MM_CONTEXT_ID,                offsetof(struct mm_struct, context.id));
   BLANK();
diff -urN linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S
--- linux/arch/arm/kernel/entry-armv.S  2005/04/08 18:57:50     1.65
+++ linux/arch/arm/kernel/entry-armv.S  2005/05/19 12:08:06     1.66
@@ -14,12 +14,12 @@
  *  it to save wrong values...  Be aware!
  */
 #include <linux/config.h>
-#include <linux/init.h>
 
-#include <asm/thread_info.h>
 #include <asm/glue.h>
-#include <asm/ptrace.h>
 #include <asm/vfpmacros.h>
+#include <asm/hardware.h>              /* should be moved into entry-macro.S */
+#include <asm/arch/irqs.h>             /* should be moved into entry-macro.S */
+#include <asm/arch/entry-macro.S>
 
 #include "entry-header.S"
 
@@ -118,7 +118,7 @@
        @
        @ IRQs off again before pulling preserved data off the stack
        @
-       disable_irq r0
+       disable_irq
 
        @
        @ restore SPSR and restart the instruction
@@ -198,7 +198,7 @@
        @
        @ IRQs off again before pulling preserved data off the stack
        @
-1:     disable_irq r0
+1:     disable_irq
 
        @
        @ restore SPSR and restart the instruction
@@ -232,7 +232,7 @@
        @
        @ IRQs off again before pulling preserved data off the stack
        @
-       disable_irq r0
+       disable_irq
 
        @
        @ restore SPSR and restart the instruction
@@ -269,6 +269,12 @@
        add     r5, sp, #S_PC
        ldmia   r7, {r2 - r4}                   @ Get USR pc, cpsr
 
+#if __LINUX_ARM_ARCH__ < 6
+       @ make sure our user space atomic helper is aborted
+       cmp     r2, #VIRT_OFFSET
+       bichs   r3, r3, #PSR_Z_BIT
+#endif
+
        @
        @ We are now ready to fill in the remaining blanks on the stack:
        @
@@ -316,7 +322,7 @@
        @
        @ IRQs on, then call the main handler
        @
-       enable_irq r2
+       enable_irq
        mov     r2, sp
        adr     lr, ret_from_exception
        b       do_DataAbort
@@ -418,7 +424,7 @@
        movcss  r7, r5, lsr #(TIF_USING_IWMMXT + 1)
        bcs     iwmmxt_task_enable
 #endif
-       enable_irq r7
+       enable_irq
        add     pc, pc, r8, lsr #6
        mov     r0, r0
 
@@ -472,7 +478,7 @@
 __pabt_usr:
        usr_entry abt
 
-       enable_irq r0                           @ Enable interrupts
+       enable_irq                              @ Enable interrupts
        mov     r0, r2                          @ address (pc)
        mov     r1, sp                          @ regs
        bl      do_PrefetchAbort                @ call abort handler
@@ -499,8 +505,12 @@
        mra     r4, r5, acc0
        stmia   ip, {r4, r5}
 #endif
+#if defined(CONFIG_HAS_TLS_REG)
+       mcr     p15, 0, r3, c13, c0, 3          @ set TLS register
+#elif !defined(CONFIG_TLS_REG_EMUL)
        mov     r4, #0xffff0fff
-       str     r3, [r4, #-3]                   @ Set TLS ptr
+       str     r3, [r4, #-15]                  @ TLS val at 0xffff0ff0
+#endif
        mcr     p15, 0, r6, c3, c0, 0           @ Set domain register
 #ifdef CONFIG_VFP
        @ Always disable VFP so we can lazily save/restore the old
@@ -519,11 +529,209 @@
        ldmib   r2, {r4 - sl, fp, sp, pc}       @ Load all regs saved previously
 
        __INIT
+
+/*
+ * User helpers.
+ *
+ * These are segment of kernel provided user code reachable from user space
+ * at a fixed address in kernel memory.  This is used to provide user space
+ * with some operations which require kernel help because of unimplemented
+ * native feature and/or instructions in many ARM CPUs. The idea is for
+ * this code to be executed directly in user mode for best efficiency but
+ * which is too intimate with the kernel counter part to be left to user
+ * libraries.  In fact this code might even differ from one CPU to another
+ * depending on the available  instruction set and restrictions like on
+ * SMP systems.  In other words, the kernel reserves the right to change
+ * this code as needed without warning. Only the entry points and their
+ * results are guaranteed to be stable.
+ *
+ * Each segment is 32-byte aligned and will be moved to the top of the high
+ * vector page.  New segments (if ever needed) must be added in front of
+ * existing ones.  This mechanism should be used only for things that are
+ * really small and justified, and not be abused freely.
+ *
+ * User space is expected to implement those things inline when optimizing
+ * for a processor that has the necessary native support, but only if such
+ * resulting binaries are already to be incompatible with earlier ARM
+ * processors due to the use of unsupported instructions other than what
+ * is provided here.  In other words don't make binaries unable to run on
+ * earlier processors just for the sake of not using these kernel helpers
+ * if your compiled code is not going to use the new instructions for other
+ * purpose.
+ */
+
+       .align  5
+       .globl  __kuser_helper_start
+__kuser_helper_start:
+
+/*
+ * Reference prototype:
+ *
+ *     int __kernel_cmpxchg(int oldval, int newval, int *ptr)
+ *
+ * Input:
+ *
+ *     r0 = oldval
+ *     r1 = newval
+ *     r2 = ptr
+ *     lr = return address
+ *
+ * Output:
+ *
+ *     r0 = returned value (zero or non-zero)
+ *     C flag = set if r0 == 0, clear if r0 != 0
+ *
+ * Clobbered:
+ *
+ *     r3, ip, flags
+ *
+ * Definition and user space usage example:
+ *
+ *     typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
+ *     #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
+ *
+ * Atomically store newval in *ptr if *ptr is equal to oldval for user space.
+ * Return zero if *ptr was changed or non-zero if no exchange happened.
+ * The C flag is also set if *ptr was changed to allow for assembly
+ * optimization in the calling code.
+ *
+ * For example, a user space atomic_add implementation could look like this:
+ *
+ * #define atomic_add(ptr, val) \
+ *     ({ register unsigned int *__ptr asm("r2") = (ptr); \
+ *        register unsigned int __result asm("r1"); \
+ *        asm volatile ( \
+ *            "1: @ atomic_add\n\t" \
+ *            "ldr     r0, [r2]\n\t" \
+ *            "mov     r3, #0xffff0fff\n\t" \
+ *            "add     lr, pc, #4\n\t" \
+ *            "add     r1, r0, %2\n\t" \
+ *            "add     pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \
+ *            "bcc     1b" \
+ *            : "=&r" (__result) \
+ *            : "r" (__ptr), "rIL" (val) \
+ *            : "r0","r3","ip","lr","cc","memory" ); \
+ *        __result; })
+ */
+
+__kuser_cmpxchg:                               @ 0xffff0fc0
+
+#if __LINUX_ARM_ARCH__ < 6
+
+#ifdef CONFIG_SMP  /* sanity check */
+#error "CONFIG_SMP on a machine supporting pre-ARMv6 processors?"
+#endif
+
+       /*
+        * Theory of operation:
+        *
+        * We set the Z flag before loading oldval. If ever an exception
+        * occurs we can not be sure the loaded value will still be the same
+        * when the exception returns, therefore the user exception handler
+        * will clear the Z flag whenever the interrupted user code was
+        * actually from the kernel address space (see the usr_entry macro).
+        *
+        * The post-increment on the str is used to prevent a race with an
+        * exception happening just after the str instruction which would
+        * clear the Z flag although the exchange was done.
+        */
+       teq     ip, ip                  @ set Z flag
+       ldr     ip, [r2]                @ load current val
+       add     r3, r2, #1              @ prepare store ptr
+       teqeq   ip, r0                  @ compare with oldval if still allowed
+       streq   r1, [r3, #-1]!          @ store newval if still allowed
+       subs    r0, r2, r3              @ if r2 == r3 the str occured
+       mov     pc, lr
+
+#else
+
+       ldrex   r3, [r2]
+       subs    r3, r3, r0
+       strexeq r3, r1, [r2]
+       rsbs    r0, r3, #0
+       mov     pc, lr
+
+#endif
+
+       .align  5
+
+/*
+ * Reference prototype:
+ *
+ *     int __kernel_get_tls(void)
+ *
+ * Input:
+ *
+ *     lr = return address
+ *
+ * Output:
+ *
+ *     r0 = TLS value
+ *
+ * Clobbered:
+ *
+ *     the Z flag might be lost
+ *
+ * Definition and user space usage example:
+ *
+ *     typedef int (__kernel_get_tls_t)(void);
+ *     #define __kernel_get_tls (*(__kernel_get_tls_t *)0xffff0fe0)
+ *
+ * Get the TLS value as previously set via the __ARM_NR_set_tls syscall.
+ *
+ * This could be used as follows:
+ *
+ * #define __kernel_get_tls() \
+ *     ({ register unsigned int __val asm("r0"); \
+ *         asm( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #31" \
+ *             : "=r" (__val) : : "lr","cc" ); \
+ *        __val; })
+ */
+
+__kuser_get_tls:                               @ 0xffff0fe0
+
+#if !defined(CONFIG_HAS_TLS_REG) && !defined(CONFIG_TLS_REG_EMUL)
+
+       ldr     r0, [pc, #(16 - 8)]             @ TLS stored at 0xffff0ff0
+       mov     pc, lr
+
+#else
+
+       mrc     p15, 0, r0, c13, c0, 3          @ read TLS register
+       mov     pc, lr
+
+#endif
+
+       .rep    5
+       .word   0                       @ pad up to __kuser_helper_version
+       .endr
+
+/*
+ * Reference declaration:
+ *
+ *     extern unsigned int __kernel_helper_version;
+ *
+ * Definition and user space usage example:
+ *
+ *     #define __kernel_helper_version (*(unsigned int *)0xffff0ffc)
+ *
+ * User space may read this to determine the curent number of helpers
+ * available.
+ */
+
+__kuser_helper_version:                                @ 0xffff0ffc
+       .word   ((__kuser_helper_end - __kuser_helper_start) >> 5)
+
+       .globl  __kuser_helper_end
+__kuser_helper_end:
+
+
 /*
  * Vector stubs.
  *
- * This code is copied to 0x200 or 0xffff0200 so we can use branches in the
- * vectors, rather than ldr's.
+ * This code is copied to 0xffff0200 so we can use branches in the
+ * vectors, rather than ldr's.  Note that this code must not
+ * exceed 0x300 bytes.
  *
  * Common stub entry macro:
  *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
@@ -544,7 +752,7 @@
        @
        mrs     r13, cpsr
        bic     r13, r13, #MODE_MASK
-       orr     r13, r13, #MODE_SVC
+       orr     r13, r13, #SVC_MODE
        msr     spsr_cxsf, r13                  @ switch to SVC_32 mode
 
        and     lr, lr, #15
@@ -552,6 +760,7 @@
        movs    pc, lr                          @ Changes mode and branches
        .endm
 
+       .globl  __stubs_start
 __stubs_start:
 /*
  * Interrupt dispatcher
@@ -686,37 +895,24 @@
 .LCsabt:
        .word   __temp_abt
 
+       .globl  __stubs_end
 __stubs_end:
 
-       .equ    __real_stubs_start, .LCvectors + 0x200
+       .equ    stubs_offset, __vectors_start + 0x200 - __stubs_start
 
-.LCvectors:
+       .globl  __vectors_start
+__vectors_start:
        swi     SYS_ERROR0
-       b       __real_stubs_start + (vector_und - __stubs_start)
-       ldr     pc, __real_stubs_start + (.LCvswi - __stubs_start)
-       b       __real_stubs_start + (vector_pabt - __stubs_start)
-       b       __real_stubs_start + (vector_dabt - __stubs_start)
-       b       __real_stubs_start + (vector_addrexcptn - __stubs_start)
-       b       __real_stubs_start + (vector_irq - __stubs_start)
-       b       __real_stubs_start + (vector_fiq - __stubs_start)
-
-ENTRY(__trap_init)
-       stmfd   sp!, {r4 - r6, lr}
-
-       mov     r0, #0xff000000
-       orr     r0, r0, #0x00ff0000             @ high vectors position
-       adr     r1, .LCvectors                  @ set up the vectors
-       ldmia   r1, {r1, r2, r3, r4, r5, r6, ip, lr}
-       stmia   r0, {r1, r2, r3, r4, r5, r6, ip, lr}
-
-       add     r2, r0, #0x200
-       adr     r0, __stubs_start               @ copy stubs to 0x200
-       adr     r1, __stubs_end
-1:     ldr     r3, [r0], #4
-       str     r3, [r2], #4
-       cmp     r0, r1
-       blt     1b
-       LOADREGS(fd, sp!, {r4 - r6, pc})
+       b       vector_und + stubs_offset
+       ldr     pc, .LCvswi + stubs_offset
+       b       vector_pabt + stubs_offset
+       b       vector_dabt + stubs_offset
+       b       vector_addrexcptn + stubs_offset
+       b       vector_irq + stubs_offset
+       b       vector_fiq + stubs_offset
+
+       .globl  __vectors_end
+__vectors_end:
 
        .data
 
diff -urN linux/arch/arm/kernel/entry-common.S 
linux/arch/arm/kernel/entry-common.S
--- linux/arch/arm/kernel/entry-common.S        2005/02/13 20:16:14     1.34
+++ linux/arch/arm/kernel/entry-common.S        2005/05/19 12:08:06     1.35
@@ -9,19 +9,10 @@
  */
 #include <linux/config.h>
 
-#include <asm/thread_info.h>
-#include <asm/ptrace.h>
 #include <asm/unistd.h>
 
 #include "entry-header.S"
 
-/* 
- * We rely on the fact that R0 is at the bottom of the stack (due to
- * slow/fast restore user regs).
- */
-#if S_R0 != 0
-#error "Please fix"
-#endif
 
        .align  5
 /*
@@ -30,11 +21,19 @@
  * stack.
  */
 ret_fast_syscall:
-       disable_irq r1                          @ disable interrupts
+       disable_irq                             @ disable interrupts
        ldr     r1, [tsk, #TI_FLAGS]
        tst     r1, #_TIF_WORK_MASK
        bne     fast_work_pending
-       fast_restore_user_regs
+
+       @ fast_restore_user_regs
+       ldr     r1, [sp, #S_OFF + S_PSR]        @ get calling cpsr
+       ldr     lr, [sp, #S_OFF + S_PC]!        @ get pc
+       msr     spsr_cxsf, r1                   @ save in spsr_svc
+       ldmdb   sp, {r1 - lr}^                  @ get calling r1 - lr
+       mov     r0, r0
+       add     sp, sp, #S_FRAME_SIZE - S_PC
+       movs    pc, lr                          @ return & move spsr_svc into 
cpsr
 
 /*
  * Ok, we need to do extra processing, enter the slow path.
@@ -49,7 +48,7 @@
        mov     r0, sp                          @ 'regs'
        mov     r2, why                         @ 'syscall'
        bl      do_notify_resume
-       disable_irq r1                          @ disable interrupts
+       disable_irq                             @ disable interrupts
        b       no_work_pending
 
 work_resched:
@@ -59,12 +58,19 @@
  */
 ENTRY(ret_to_user)
 ret_slow_syscall:
-       disable_irq r1                          @ disable interrupts
+       disable_irq                             @ disable interrupts
        ldr     r1, [tsk, #TI_FLAGS]
        tst     r1, #_TIF_WORK_MASK
        bne     work_pending
 no_work_pending:
-       slow_restore_user_regs
+       @ slow_restore_user_regs
+       ldr     r1, [sp, #S_PSR]                @ get calling cpsr
+       ldr     lr, [sp, #S_PC]!                @ get pc
+       msr     spsr_cxsf, r1                   @ save in spsr_svc
+       ldmdb   sp, {r0 - lr}^                  @ get calling r1 - lr
+       mov     r0, r0
+       add     sp, sp, #S_FRAME_SIZE - S_PC
+       movs    pc, lr                          @ return & move spsr_svc into 
cpsr
 
 /*
  * This is how we return from a fork.
@@ -116,9 +122,26 @@
 
        .align  5
 ENTRY(vector_swi)
-       save_user_regs
+       sub     sp, sp, #S_FRAME_SIZE
+       stmia   sp, {r0 - r12}                  @ Calling r0 - r12
+       add     r8, sp, #S_PC
+       stmdb   r8, {sp, lr}^                   @ Calling sp, lr
+       mrs     r8, spsr                        @ called from non-FIQ mode, so 
ok.
+       str     lr, [sp, #S_PC]                 @ Save calling PC
+       str     r8, [sp, #S_PSR]                @ Save CPSR
+       str     r0, [sp, #S_OLD_R0]             @ Save OLD_R0
        zero_fp
-       get_scno
+
+       /*
+        * Get the system call number.
+        */
+#ifdef CONFIG_ARM_THUMB
+       tst     r8, #PSR_T_BIT                  @ this is SPSR from 
save_user_regs
+       addne   scno, r7, #__NR_SYSCALL_BASE    @ put OS number in
+       ldreq   scno, [lr, #-4]
+#else
+       ldr     scno, [lr, #-4]                 @ get SWI instruction
+#endif
        arm710_bug_check scno, ip
 
 #ifdef CONFIG_ALIGNMENT_TRAP
@@ -126,14 +149,14 @@
        ldr     ip, [ip]
        mcr     p15, 0, ip, c1, c0              @ update control register
 #endif
-       enable_irq ip
+       enable_irq
 
        str     r4, [sp, #-S_OFF]!              @ push fifth arg
 
        get_thread_info tsk
        ldr     ip, [tsk, #TI_FLAGS]            @ check for syscall tracing
        bic     scno, scno, #0xff000000         @ mask off SWI op-code
-       eor     scno, scno, #OS_NUMBER << 20    @ check OS number
+       eor     scno, scno, #__NR_SYSCALL_BASE  @ check OS number
        adr     tbl, sys_call_table             @ load syscall table pointer
        tst     ip, #_TIF_SYSCALL_TRACE         @ are we tracing syscalls?
        bne     __sys_trace
@@ -144,8 +167,8 @@
 
        add     r1, sp, #S_OFF
 2:     mov     why, #0                         @ no longer a real syscall
-       cmp     scno, #ARMSWI_OFFSET
-       eor     r0, scno, #OS_NUMBER << 20      @ put OS number back
+       cmp     scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
+       eor     r0, scno, #__NR_SYSCALL_BASE    @ put OS number back
        bcs     arm_syscall     
        b       sys_ni_syscall                  @ not private func
 
@@ -190,7 +213,7 @@
 @ r5 = syscall table
                .type   sys_syscall, #function
 sys_syscall:
-               eor     scno, r0, #OS_NUMBER << 20
+               eor     scno, r0, #__NR_SYSCALL_BASE
                cmp     scno, #__NR_syscall - __NR_SYSCALL_BASE
                cmpne   scno, #NR_syscalls      @ check range
                stmloia sp, {r5, r6}            @ shuffle args
diff -urN linux/arch/arm/kernel/entry-header.S 
linux/arch/arm/kernel/entry-header.S
--- linux/arch/arm/kernel/entry-header.S        2005/02/07 02:54:30     1.13
+++ linux/arch/arm/kernel/entry-header.S        2005/05/19 12:08:06     1.14
@@ -1,24 +1,11 @@
-#include <linux/config.h> /* for CONFIG_ARCH_xxxx */
+#include <linux/config.h>
+#include <linux/init.h>
 #include <linux/linkage.h>
 
 #include <asm/assembler.h>
 #include <asm/constants.h>
 #include <asm/errno.h>
-#include <asm/hardware.h>
-#include <asm/arch/irqs.h>
-#include <asm/arch/entry-macro.S>
-
-#ifndef MODE_SVC
-#define MODE_SVC 0x13
-#endif
-
-       .macro  zero_fp
-#ifdef CONFIG_FRAME_POINTER
-       mov     fp, #0
-#endif
-       .endm
-
-       .text
+#include <asm/thread_info.h>
 
 @ Bad Abort numbers
 @ -----------------
@@ -29,113 +16,44 @@
 #define BAD_IRQ                3
 #define BAD_UNDEFINSTR 4
 
-#define PT_TRACESYS    0x00000002
-
-@ OS version number used in SWIs
-@  RISC OS is 0
-@  RISC iX is 8
 @
-#define OS_NUMBER      9
-#define ARMSWI_OFFSET  0x000f0000
-
-@
-@ Stack format (ensured by USER_* and SVC_*)
+@ Most of the stack format comes from struct pt_regs, but with
+@ the addition of 8 bytes for storing syscall args 5 and 6.
 @
-#define S_FRAME_SIZE   72
-#define S_OLD_R0       68
-#define S_PSR          64
-
-#define S_PC           60
-#define S_LR           56
-#define S_SP           52
-#define S_IP           48
-#define S_FP           44
-#define S_R10          40
-#define S_R9           36
-#define S_R8           32
-#define S_R7           28
-#define S_R6           24
-#define S_R5           20
-#define S_R4           16
-#define S_R3           12
-#define S_R2           8
-#define S_R1           4
-#define S_R0           0
 #define S_OFF          8
 
-       .macro  set_cpsr_c, reg, mode
-       msr     cpsr_c, \mode
+/* 
+ * The SWI code relies on the fact that R0 is at the bottom of the stack
+ * (due to slow/fast restore user regs).
+ */
+#if S_R0 != 0
+#error "Please fix"
+#endif
+
+       .macro  zero_fp
+#ifdef CONFIG_FRAME_POINTER
+       mov     fp, #0
+#endif
        .endm
 
 #if __LINUX_ARM_ARCH__ >= 6
-       .macro  disable_irq, temp
+       .macro  disable_irq
        cpsid   i
        .endm
 
-       .macro  enable_irq, temp
+       .macro  enable_irq
        cpsie   i
        .endm
 #else
-       .macro  disable_irq, temp
-       set_cpsr_c \temp, #PSR_I_BIT | MODE_SVC
+       .macro  disable_irq
+       msr     cpsr_c, #PSR_I_BIT | SVC_MODE
        .endm
 
-       .macro  enable_irq, temp
-       set_cpsr_c \temp, #MODE_SVC
+       .macro  enable_irq
+       msr     cpsr_c, #SVC_MODE
        .endm
 #endif
 
-       .macro  save_user_regs
-       sub     sp, sp, #S_FRAME_SIZE
-       stmia   sp, {r0 - r12}                  @ Calling r0 - r12
-       add     r8, sp, #S_PC
-       stmdb   r8, {sp, lr}^                   @ Calling sp, lr
-       mrs     r8, spsr                        @ called from non-FIQ mode, so 
ok.
-       str     lr, [sp, #S_PC]                 @ Save calling PC
-       str     r8, [sp, #S_PSR]                @ Save CPSR
-       str     r0, [sp, #S_OLD_R0]             @ Save OLD_R0
-       .endm
-
-       .macro  restore_user_regs
-       ldr     r1, [sp, #S_PSR]                @ Get calling cpsr
-       disable_irq ip                          @ disable IRQs
-       ldr     lr, [sp, #S_PC]!                @ Get PC
-       msr     spsr_cxsf, r1                   @ save in spsr_svc
-       ldmdb   sp, {r0 - lr}^                  @ Get calling r0 - lr
-       mov     r0, r0
-       add     sp, sp, #S_FRAME_SIZE - S_PC
-       movs    pc, lr                          @ return & move spsr_svc into 
cpsr
-       .endm
-
-/*
- * Must be called with IRQs already disabled.
- */
-       .macro  fast_restore_user_regs
-       ldr     r1, [sp, #S_OFF + S_PSR]        @ get calling cpsr
-       ldr     lr, [sp, #S_OFF + S_PC]!        @ get pc
-       msr     spsr_cxsf, r1                   @ save in spsr_svc
-       ldmdb   sp, {r1 - lr}^                  @ get calling r1 - lr
-       mov     r0, r0
-       add     sp, sp, #S_FRAME_SIZE - S_PC
-       movs    pc, lr                          @ return & move spsr_svc into 
cpsr
-       .endm
-
-/*
- * Must be called with IRQs already disabled.
- */
-       .macro  slow_restore_user_regs
-       ldr     r1, [sp, #S_PSR]                @ get calling cpsr
-       ldr     lr, [sp, #S_PC]!                @ get pc
-       msr     spsr_cxsf, r1                   @ save in spsr_svc
-       ldmdb   sp, {r0 - lr}^                  @ get calling r1 - lr
-       mov     r0, r0
-       add     sp, sp, #S_FRAME_SIZE - S_PC
-       movs    pc, lr                          @ return & move spsr_svc into 
cpsr
-       .endm
-
-       .macro  mask_pc, rd, rm
-       .endm
-
        .macro  get_thread_info, rd
        mov     \rd, sp, lsr #13
        mov     \rd, \rd, lsl #13
@@ -165,18 +83,3 @@
 tbl    .req    r8              @ syscall table pointer
 why    .req    r8              @ Linux syscall (!= 0)
 tsk    .req    r9              @ current thread_info
-
-/*
- * Get the system call number.
- */
-       .macro  get_scno
-#ifdef CONFIG_ARM_THUMB
-       tst     r8, #PSR_T_BIT          @ this is SPSR from save_user_regs
-       addne   scno, r7, #OS_NUMBER << 20 @ put OS number in
-       ldreq   scno, [lr, #-4]
-
-#else
-       mask_pc lr, lr
-       ldr     scno, [lr, #-4]         @ get SWI instruction
-#endif
-       .endm
diff -urN linux/arch/arm/kernel/head.S linux/arch/arm/kernel/head.S
--- linux/arch/arm/kernel/head.S        2005/04/08 18:57:50     1.16
+++ linux/arch/arm/kernel/head.S        2005/05/19 12:08:06     1.17
@@ -19,6 +19,7 @@
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
 #include <asm/constants.h>
+#include <asm/thread_info.h>
 #include <asm/system.h>
 
 #define PROCINFO_MMUFLAGS      8
@@ -131,7 +132,7 @@
        .long   processor_id                    @ r4
        .long   __machine_arch_type             @ r5
        .long   cr_alignment                    @ r6
-       .long   init_thread_union+8192          @ sp
+       .long   init_thread_union + THREAD_START_SP @ sp
 
 /*
  * The following fragment of code is executed with the MMU on, and uses
diff -urN linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c
--- linux/arch/arm/kernel/process.c     2005/04/29 11:15:00     1.50
+++ linux/arch/arm/kernel/process.c     2005/05/19 12:08:06     1.51
@@ -256,8 +256,6 @@
 static unsigned int nr_thread_info;
 
 #define EXTRA_TASK_STRUCT      4
-#define ll_alloc_task_struct() ((struct thread_info *) 
__get_free_pages(GFP_KERNEL,1))
-#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
 
 struct thread_info *alloc_thread_info(struct task_struct *task)
 {
@@ -274,17 +272,16 @@
        }
 
        if (!thread)
-               thread = ll_alloc_task_struct();
+               thread = (struct thread_info *)
+                          __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
 
-#ifdef CONFIG_MAGIC_SYSRQ
+#ifdef CONFIG_DEBUG_STACK_USAGE
        /*
         * The stack must be cleared if you want SYSRQ-T to
         * give sensible stack usage information
         */
-       if (thread) {
-               char *p = (char *)thread;
-               memzero(p+KERNEL_STACK_SIZE, KERNEL_STACK_SIZE);
-       }
+       if (thread)
+               memzero(thread, THREAD_SIZE);
 #endif
        return thread;
 }
@@ -297,7 +294,7 @@
                thread_info_head = p;
                nr_thread_info += 1;
        } else
-               ll_free_task_struct(thread);
+               free_pages((unsigned long)thread, THREAD_SIZE_ORDER);
 }
 
 /*
@@ -350,7 +347,7 @@
        struct thread_info *thread = p->thread_info;
        struct pt_regs *childregs;
 
-       childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_SIZE - 
8)) - 1;
+       childregs = ((struct pt_regs *)((unsigned long)thread + 
THREAD_START_SP)) - 1;
        *childregs = *regs;
        childregs->ARM_r0 = 0;
        childregs->ARM_sp = stack_start;
@@ -447,15 +444,17 @@
 unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long fp, lr;
-       unsigned long stack_page;
+       unsigned long stack_start, stack_end;
        int count = 0;
        if (!p || p == current || p->state == TASK_RUNNING)
                return 0;
 
-       stack_page = 4096 + (unsigned long)p->thread_info;
+       stack_start = (unsigned long)(p->thread_info + 1);
+       stack_end = ((unsigned long)p->thread_info) + THREAD_SIZE;
+
        fp = thread_saved_fp(p);
        do {
-               if (fp < stack_page || fp > 4092+stack_page)
+               if (fp < stack_start || fp > stack_end)
                        return 0;
                lr = pc_pointer (((unsigned long *)fp)[-1]);
                if (!in_sched_functions(lr))
diff -urN linux/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c
--- linux/arch/arm/kernel/ptrace.c      2005/04/08 18:57:50     1.37
+++ linux/arch/arm/kernel/ptrace.c      2005/05/19 12:08:06     1.38
@@ -19,6 +19,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/init.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -693,7 +694,7 @@
                case PTRACE_SYSCALL:
                case PTRACE_CONT:
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        if (request == PTRACE_SYSCALL)
                                set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -728,7 +729,7 @@
                 */
                case PTRACE_SINGLESTEP:
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        child->ptrace |= PT_SINGLESTEP;
                        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
diff -urN linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c
--- linux/arch/arm/kernel/sys_arm.c     2005/04/29 11:15:00     1.39
+++ linux/arch/arm/kernel/sys_arm.c     2005/05/19 12:08:06     1.40
@@ -227,18 +227,6 @@
        }
 }
 
-asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg,
-                         unsigned long __user *addr)
-{
-       unsigned long ret;
-       long err;
-
-       err = do_shmat(shmid, shmaddr, shmflg, &ret);
-       if (err == 0)
-               err = put_user(ret, addr);
-       return err;
-}
-
 /* Fork a new task - this creates a new program thread.
  * This is called indirectly via a small wrapper
  */
@@ -314,7 +302,7 @@
                "b      ret_to_user"
                :
                : "r" (current_thread_info()),
-                 "Ir" (THREAD_SIZE - 8 - sizeof(regs)),
+                 "Ir" (THREAD_START_SP - sizeof(regs)),
                  "r" (&regs),
                  "Ir" (sizeof(regs))
                : "r0", "r1", "r2", "r3", "ip", "memory");
diff -urN linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- linux/arch/arm/kernel/traps.c       2005/04/29 11:15:00     1.50
+++ linux/arch/arm/kernel/traps.c       2005/05/19 12:08:06     1.51
@@ -218,7 +218,8 @@
                tsk->comm, tsk->pid, tsk->thread_info + 1);
 
        if (!user_mode(regs) || in_interrupt()) {
-               dump_mem("Stack: ", regs->ARM_sp, 8192+(unsigned 
long)tsk->thread_info);
+               dump_mem("Stack: ", regs->ARM_sp,
+                        THREAD_SIZE + (unsigned long)tsk->thread_info);
                dump_backtrace(regs, tsk);
                dump_instr(regs);
        }
@@ -450,13 +451,17 @@
 
        case NR(set_tls):
                thread->tp_value = regs->ARM_r0;
+#if defined(CONFIG_HAS_TLS_REG)
+               asm ("mcr p15, 0, %0, c13, c0, 3" : : "r" (regs->ARM_r0) );
+#elif !defined(CONFIG_TLS_REG_EMUL)
                /*
-                * Our user accessible TLS ptr is located at 0xffff0ffc.
-                * On SMP read access to this address must raise a fault
-                * and be emulated from the data abort handler.
-                * m
+                * User space must never try to access this directly.
+                * Expect your app to break eventually if you do so.
+                * The user helper at 0xffff0fe0 must be used instead.
+                * (see entry-armv.S for details)
                 */
-               *((unsigned long *)0xffff0ffc) = thread->tp_value;
+               *((unsigned int *)0xffff0ff0) = regs->ARM_r0;
+#endif
                return 0;
 
        default:
@@ -493,6 +498,44 @@
        return 0;
 }
 
+#ifdef CONFIG_TLS_REG_EMUL
+
+/*
+ * We might be running on an ARMv6+ processor which should have the TLS
+ * register but for some reason we can't use it, or maybe an SMP system
+ * using a pre-ARMv6 processor (there are apparently a few prototypes like
+ * that in existence) and therefore access to that register must be
+ * emulated.
+ */
+
+static int get_tp_trap(struct pt_regs *regs, unsigned int instr)
+{
+       int reg = (instr >> 12) & 15;
+       if (reg == 15)
+               return 1;
+       regs->uregs[reg] = current_thread_info()->tp_value;
+       regs->ARM_pc += 4;
+       return 0;
+}
+
+static struct undef_hook arm_mrc_hook = {
+       .instr_mask     = 0x0fff0fff,
+       .instr_val      = 0x0e1d0f70,
+       .cpsr_mask      = PSR_T_BIT,
+       .cpsr_val       = 0,
+       .fn             = get_tp_trap,
+};
+
+static int __init arm_mrc_hook_init(void)
+{
+       register_undef_hook(&arm_mrc_hook);
+       return 0;
+}
+
+late_initcall(arm_mrc_hook_init);
+
+#endif
+
 void __bad_xchg(volatile void *ptr, int size)
 {
        printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n",
@@ -578,9 +621,19 @@
 
 void __init trap_init(void)
 {
-       extern void __trap_init(void);
+       extern char __stubs_start[], __stubs_end[];
+       extern char __vectors_start[], __vectors_end[];
+       extern char __kuser_helper_start[], __kuser_helper_end[];
+       int kuser_sz = __kuser_helper_end - __kuser_helper_start;
 
-       __trap_init();
+       /*
+        * Copy the vectors, stubs and kuser helpers (in entry-armv.S)
+        * into the vector page, mapped at 0xffff0000, and ensure these
+        * are visible to the instruction stream.
+        */
+       memcpy((void *)0xffff0000, __vectors_start, __vectors_end - 
__vectors_start);
+       memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start);
+       memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz);
        flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE);
        modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
 }
diff -urN linux/arch/arm/kernel/vmlinux.lds.S 
linux/arch/arm/kernel/vmlinux.lds.S
--- linux/arch/arm/kernel/vmlinux.lds.S 2005/04/08 18:57:50     1.8
+++ linux/arch/arm/kernel/vmlinux.lds.S 2005/05/19 12:08:06     1.9
@@ -5,6 +5,7 @@
 
 #include <asm-generic/vmlinux.lds.h>
 #include <linux/config.h>
+#include <asm/thread_info.h>
        
 OUTPUT_ARCH(arm)
 ENTRY(stext)
@@ -103,7 +104,7 @@
        __data_loc = ALIGN(4);          /* location in binary */
        . = DATAADDR;
 #else
-       . = ALIGN(8192);
+       . = ALIGN(THREAD_SIZE);
        __data_loc = .;
 #endif
 
diff -urN linux/arch/arm/mach-clps711x/Kconfig 
linux/arch/arm/mach-clps711x/Kconfig
--- linux/arch/arm/mach-clps711x/Kconfig        2004/06/16 12:09:34     1.2
+++ linux/arch/arm/mach-clps711x/Kconfig        2005/05/19 12:08:06     1.3
@@ -10,6 +10,7 @@
 
 config ARCH_CDB89712
        bool "CDB89712"
+       select ISA
        help
          This is an evaluation board from Cirrus for the CS89712 processor.
          The board includes 2 serial ports, Ethernet, IRDA, and expansion
@@ -26,6 +27,8 @@
 
 config ARCH_EDB7211
        bool "EDB7211"
+       select ISA
+       select DISCONTIGMEM
        help
          Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211
          evaluation board.
diff -urN linux/arch/arm/mach-footbridge/Kconfig 
linux/arch/arm/mach-footbridge/Kconfig
--- linux/arch/arm/mach-footbridge/Kconfig      2005/01/25 04:27:52     1.5
+++ linux/arch/arm/mach-footbridge/Kconfig      2005/05/19 12:08:07     1.6
@@ -5,6 +5,9 @@
 config ARCH_CATS
        bool "CATS"
        select FOOTBRIDGE_HOST
+       select ISA
+       select ISA_DMA
+       select PCI
        help
          Say Y here if you intend to run this kernel on the CATS.
 
@@ -13,6 +16,9 @@
 config ARCH_PERSONAL_SERVER
        bool "Compaq Personal Server"
        select FOOTBRIDGE_HOST
+       select ISA
+       select ISA_DMA
+       select PCI
        ---help---
          Say Y here if you intend to run this kernel on the Compaq
          Personal Server.
@@ -42,6 +48,9 @@
        bool "EBSA285 (host mode)"
        select ARCH_EBSA285
        select FOOTBRIDGE_HOST
+       select ISA
+       select ISA_DMA
+       select PCI
        help
          Say Y here if you intend to run this kernel on the EBSA285 card
          in host ("central function") mode.
@@ -51,6 +60,9 @@
 config ARCH_NETWINDER
        bool "NetWinder"
        select FOOTBRIDGE_HOST
+       select ISA
+       select ISA_DMA
+       select PCI
        help
          Say Y here if you intend to run this kernel on the Rebel.COM
          NetWinder.  Information about this machine can be found at:
diff -urN linux/arch/arm/mach-imx/Kconfig linux/arch/arm/mach-imx/Kconfig
--- linux/arch/arm/mach-imx/Kconfig     2004/08/24 15:10:03     1.1
+++ linux/arch/arm/mach-imx/Kconfig     2005/05/19 12:08:07     1.2
@@ -4,6 +4,7 @@
 config ARCH_MX1ADS
        bool "mx1ads"
        depends on ARCH_IMX
+       select ISA
        help
          Say Y here if you are using the Motorola MX1ADS board
 
diff -urN linux/arch/arm/mach-imx/generic.c linux/arch/arm/mach-imx/generic.c
--- linux/arch/arm/mach-imx/generic.c   2005/03/02 19:58:00     1.2
+++ linux/arch/arm/mach-imx/generic.c   2005/05/19 12:08:07     1.3
@@ -26,6 +26,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <asm/arch/imxfb.h>
 #include <asm/hardware.h>
 
 #include <asm/mach/map.h>
@@ -228,6 +229,14 @@
        .resource       = imx_uart2_resources,
 };
 
+static struct imxfb_mach_info imx_fb_info;
+
+void __init set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info)
+{
+       memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imxfb_mach_info));
+}
+EXPORT_SYMBOL(set_imx_fb_info);
+
 static struct resource imxfb_resources[] = {
        [0] = {
                .start  = 0x00205000,
@@ -241,9 +250,16 @@
        },
 };
 
+static u64 fb_dma_mask = ~(u64)0;
+
 static struct platform_device imxfb_device = {
        .name           = "imx-fb",
        .id             = 0,
+       .dev            = {
+               .platform_data  = &imx_fb_info,
+               .dma_mask       = &fb_dma_mask,
+               .coherent_dma_mask = 0xffffffff,
+       },
        .num_resources  = ARRAY_SIZE(imxfb_resources),
        .resource       = imxfb_resources,
 };
diff -urN linux/arch/arm/mach-integrator/core.c 
linux/arch/arm/mach-integrator/core.c
--- linux/arch/arm/mach-integrator/core.c       2005/01/25 04:27:53     1.9
+++ linux/arch/arm/mach-integrator/core.c       2005/05/19 12:08:07     1.10
@@ -216,7 +216,9 @@
 
        write_seqlock(&xtime_lock);
 
-       // ...clear the interrupt
+       /*
+        * clear the interrupt
+        */
        timer1->TimerClear = 1;
 
        timer_tick(regs);
@@ -264,7 +266,7 @@
        timer1->TimerValue   = timer_reload;
        timer1->TimerControl = timer_ctrl;
 
-       /* 
+       /*
         * Make irqs happen for the system timer
         */
        setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
diff -urN linux/arch/arm/mach-integrator/integrator_cp.c 
linux/arch/arm/mach-integrator/integrator_cp.c
--- linux/arch/arm/mach-integrator/integrator_cp.c      2005/01/13 14:05:18     
1.6
+++ linux/arch/arm/mach-integrator/integrator_cp.c      2005/05/19 12:08:07     
1.7
@@ -420,7 +420,22 @@
  */
 static void cp_clcd_enable(struct clcd_fb *fb)
 {
-       cm_control(CM_CTRL_LCDMUXSEL_MASK, CM_CTRL_LCDMUXSEL_VGA);
+       u32 val;
+
+       if (fb->fb.var.bits_per_pixel <= 8)
+               val = CM_CTRL_LCDMUXSEL_VGA_8421BPP;
+       else if (fb->fb.var.bits_per_pixel <= 16)
+               val = CM_CTRL_LCDMUXSEL_VGA_16BPP;
+       else
+               val = 0; /* no idea for this, don't trust the docs */
+
+       cm_control(CM_CTRL_LCDMUXSEL_MASK|
+                  CM_CTRL_LCDEN0|
+                  CM_CTRL_LCDEN1|
+                  CM_CTRL_STATIC1|
+                  CM_CTRL_STATIC2|
+                  CM_CTRL_STATIC|
+                  CM_CTRL_n24BITEN, val);
 }
 
 static unsigned long framesize = SZ_1M;
diff -urN linux/arch/arm/mach-integrator/leds.c 
linux/arch/arm/mach-integrator/leds.c
--- linux/arch/arm/mach-integrator/leds.c       2004/02/19 03:06:21     1.2
+++ linux/arch/arm/mach-integrator/leds.c       2005/05/19 12:08:07     1.3
@@ -37,7 +37,7 @@
        unsigned long flags;
        const unsigned int dbg_base = IO_ADDRESS(INTEGRATOR_DBG_BASE);
        unsigned int update_alpha_leds;
-       
+
        // yup, change the LEDs
        local_irq_save(flags);
        update_alpha_leds = 0;
diff -urN linux/arch/arm/mach-integrator/time.c 
linux/arch/arm/mach-integrator/time.c
--- linux/arch/arm/mach-integrator/time.c       2005/04/08 18:57:51     1.6
+++ linux/arch/arm/mach-integrator/time.c       2005/05/19 12:08:07     1.7
@@ -40,25 +40,32 @@
        return 1;
 }
 
-static void rtc_read_alarm(struct rtc_wkalrm *alrm)
+static int rtc_read_alarm(struct rtc_wkalrm *alrm)
 {
        rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time);
+       return 0;
 }
 
-static int rtc_set_alarm(struct rtc_wkalrm *alrm)
+static inline int rtc_set_alarm(struct rtc_wkalrm *alrm)
 {
        unsigned long time;
        int ret;
 
-       ret = rtc_tm_to_time(&alrm->time, &time);
+       /*
+        * At the moment, we can only deal with non-wildcarded alarm times.
+        */
+       ret = rtc_valid_tm(&alrm->time);
+       if (ret == 0)
+               ret = rtc_tm_to_time(&alrm->time, &time);
        if (ret == 0)
                writel(time, rtc_base + RTC_MR);
        return ret;
 }
 
-static void rtc_read_time(struct rtc_time *tm)
+static int rtc_read_time(struct rtc_time *tm)
 {
        rtc_time_to_tm(readl(rtc_base + RTC_DR), tm);
+       return 0;
 }
 
 /*
@@ -69,7 +76,7 @@
  * edge of the 1Hz clock, we must write the time one second
  * in advance.
  */
-static int rtc_set_time(struct rtc_time *tm)
+static inline int rtc_set_time(struct rtc_time *tm)
 {
        unsigned long time;
        int ret;
diff -urN linux/arch/arm/mach-ixp2000/ixdp2800.c 
linux/arch/arm/mach-ixp2000/ixdp2800.c
--- linux/arch/arm/mach-ixp2000/ixdp2800.c      2005/01/13 14:05:18     1.4
+++ linux/arch/arm/mach-ixp2000/ixdp2800.c      2005/05/19 12:08:07     1.5
@@ -65,19 +65,102 @@
 /*************************************************************************
  * IXDP2800 PCI
  *************************************************************************/
+static void __init ixdp2800_slave_disable_pci_master(void)
+{
+       *IXP2000_PCI_CMDSTAT &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+}
+
+static void __init ixdp2800_master_wait_for_slave(void)
+{
+       volatile u32 *addr;
+
+       printk(KERN_INFO "IXDP2800: waiting for slave NPU to configure "
+                        "its BAR sizes\n");
+
+       addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN,
+                                       PCI_BASE_ADDRESS_1);
+       do {
+               *addr = 0xffffffff;
+               cpu_relax();
+       } while (*addr != 0xfe000008);
+
+       addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN,
+                                       PCI_BASE_ADDRESS_2);
+       do {
+               *addr = 0xffffffff;
+               cpu_relax();
+       } while (*addr != 0xc0000008);
+
+       /*
+        * Configure the slave's SDRAM BAR by hand.
+        */
+       *addr = 0x40000008;
+}
+
+static void __init ixdp2800_slave_wait_for_master_enable(void)
+{
+       printk(KERN_INFO "IXDP2800: waiting for master NPU to enable us\n");
+
+       while ((*IXP2000_PCI_CMDSTAT & PCI_COMMAND_MASTER) == 0)
+               cpu_relax();
+}
+
 void __init ixdp2800_pci_preinit(void)
 {
        printk("ixdp2x00_pci_preinit called\n");
 
-       *IXP2000_PCI_ADDR_EXT =  0x0000e000;
+       *IXP2000_PCI_ADDR_EXT = 0x0001e000;
+
+       if (!ixdp2x00_master_npu())
+               ixdp2800_slave_disable_pci_master();
 
-       *IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;
        *IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff;
+       *IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff;
 
        ixp2000_pci_preinit();
+
+       if (ixdp2x00_master_npu()) {
+               /*
+                * Wait until the slave set its SRAM/SDRAM BAR sizes
+                * correctly before we proceed to scan and enumerate
+                * the bus.
+                */
+               ixdp2800_master_wait_for_slave();
+
+               /*
+                * We configure the SDRAM BARs by hand because they
+                * are 1G and fall outside of the regular allocated
+                * PCI address space.
+                */
+               *IXP2000_PCI_SDRAM_BAR = 0x00000008;
+       } else {
+               /*
+                * Wait for the master to complete scanning the bus
+                * and assigning resources before we proceed to scan
+                * the bus ourselves.  Set pci=firmware to honor the
+                * master's resource assignment.
+                */
+               ixdp2800_slave_wait_for_master_enable();
+               pcibios_setup("firmware");
+       }
+}
+
+/*
+ * We assign the SDRAM BARs for the two IXP2800 CPUs by hand, outside
+ * of the regular PCI window, because there's only 512M of outbound PCI
+ * memory window on each IXP, while we need 1G for each of the BARs.
+ */
+static void __devinit ixp2800_pci_fixup(struct pci_dev *dev)
+{
+       if (machine_is_ixdp2800()) {
+               dev->resource[2].start = 0;
+               dev->resource[2].end   = 0;
+               dev->resource[2].flags = 0;
+       }
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP2800, 
ixp2800_pci_fixup);
 
-int ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
+static int __init ixdp2800_pci_setup(int nr, struct pci_sys_data *sys)
 {
        sys->mem_offset = 0x00000000;
 
@@ -129,22 +212,47 @@
        } else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */
 }
 
-static void ixdp2800_pci_postinit(void)
+static void __init ixdp2800_master_enable_slave(void)
 {
-       struct pci_dev *dev;
+       volatile u32 *addr;
 
-       if (ixdp2x00_master_npu()) {
-               dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
-               pci_remove_bus_device(dev);
-       } else {
-               dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN);
-               pci_remove_bus_device(dev);
+       printk(KERN_INFO "IXDP2800: enabling slave NPU\n");
+
+       addr = (volatile u32 *)ixp2000_pci_config_addr(0,
+                                       IXDP2X00_SLAVE_NPU_DEVFN,
+                                       PCI_COMMAND);
+
+       *addr |= PCI_COMMAND_MASTER;
+}
 
+static void __init ixdp2800_master_wait_for_slave_bus_scan(void)
+{
+       volatile u32 *addr;
+
+       printk(KERN_INFO "IXDP2800: waiting for slave to finish bus scan\n");
+
+       addr = (volatile u32 *)ixp2000_pci_config_addr(0,
+                                       IXDP2X00_SLAVE_NPU_DEVFN,
+                                       PCI_COMMAND);
+       while ((*addr & PCI_COMMAND_MEMORY) == 0)
+               cpu_relax();
+}
+
+static void __init ixdp2800_slave_signal_bus_scan_completion(void)
+{
+       printk(KERN_INFO "IXDP2800: bus scan done, signaling master\n");
+       *IXP2000_PCI_CMDSTAT |= PCI_COMMAND_MEMORY;
+}
+
+static void __init ixdp2800_pci_postinit(void)
+{
+       if (!ixdp2x00_master_npu()) {
                ixdp2x00_slave_pci_postinit();
+               ixdp2800_slave_signal_bus_scan_completion();
        }
 }
 
-struct hw_pci ixdp2800_pci __initdata = {
+struct __initdata hw_pci ixdp2800_pci __initdata = {
        .nr_controllers = 1,
        .setup          = ixdp2800_pci_setup,
        .preinit        = ixdp2800_pci_preinit,
@@ -155,8 +263,21 @@
 
 int __init ixdp2800_pci_init(void)
 {
-       if (machine_is_ixdp2800())
+       if (machine_is_ixdp2800()) {
+               struct pci_dev *dev;
+
                pci_common_init(&ixdp2800_pci);
+               if (ixdp2x00_master_npu()) {
+                       dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN);
+                       pci_remove_bus_device(dev);
+
+                       ixdp2800_master_enable_slave();
+                       ixdp2800_master_wait_for_slave_bus_scan();
+               } else {
+                       dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN);
+                       pci_remove_bus_device(dev);
+               }
+       }
 
        return 0;
 }
diff -urN linux/arch/arm/mach-ixp2000/pci.c linux/arch/arm/mach-ixp2000/pci.c
--- linux/arch/arm/mach-ixp2000/pci.c   2005/02/28 15:45:09     1.3
+++ linux/arch/arm/mach-ixp2000/pci.c   2005/05/19 12:08:07     1.4
@@ -37,7 +37,7 @@
 
 static int clear_master_aborts(void);
 
-static u32 *
+u32 *
 ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
 {
        u32 *paddress;
@@ -208,15 +208,15 @@
  * use our own resource space.
  */
 static struct resource ixp2000_pci_mem_space = {
-       .start  = 0x00000000,
+       .start  = 0xe0000000,
        .end    = 0xffffffff,
        .flags  = IORESOURCE_MEM,
        .name   = "PCI Mem Space"
 };
 
 static struct resource ixp2000_pci_io_space = {
-       .start  = 0x00000000,
-       .end    = 0xffffffff,
+       .start  = 0x00010000,
+       .end    = 0x0001ffff,
        .flags  = IORESOURCE_IO,
        .name   = "PCI I/O Space"
 };
diff -urN linux/arch/arm/mach-ixp4xx/common-pci.c 
linux/arch/arm/mach-ixp4xx/common-pci.c
--- linux/arch/arm/mach-ixp4xx/common-pci.c     2005/01/25 04:27:53     1.7
+++ linux/arch/arm/mach-ixp4xx/common-pci.c     2005/05/19 12:08:07     1.8
@@ -502,15 +502,6 @@
 }
     
 int
-pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       if (mask >= SZ_64M - 1 )
-               return 0;
-
-       return -EIO;
-}
-
-int
 pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
 {
        if (mask >= SZ_64M - 1 )
@@ -520,7 +511,6 @@
 }
 
 EXPORT_SYMBOL(pci_set_dma_mask);
-EXPORT_SYMBOL(pci_dac_set_dma_mask);
 EXPORT_SYMBOL(pci_set_consistent_dma_mask);
 EXPORT_SYMBOL(ixp4xx_pci_read);
 EXPORT_SYMBOL(ixp4xx_pci_write);
diff -urN linux/arch/arm/mach-pxa/generic.c linux/arch/arm/mach-pxa/generic.c
--- linux/arch/arm/mach-pxa/generic.c   2005/01/13 14:05:19     1.16
+++ linux/arch/arm/mach-pxa/generic.c   2005/05/19 12:08:07     1.17
@@ -220,6 +220,30 @@
        .id             = 2,
 };
 
+static struct resource i2c_resources[] = {
+       {
+               .start  = 0x40301680,
+               .end    = 0x403016a3,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_I2C,
+               .end    = IRQ_I2C,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c_device = {
+       .name           = "pxa2xx-i2c",
+       .id             = 0,
+       .resource       = i2c_resources,
+       .num_resources  = ARRAY_SIZE(i2c_resources),
+};
+
+void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
+{
+       i2c_device.dev.platform_data = info;
+}
+
 static struct platform_device *devices[] __initdata = {
        &pxamci_device,
        &udc_device,
@@ -227,6 +251,7 @@
        &ffuart_device,
        &btuart_device,
        &stuart_device,
+       &i2c_device,
 };
 
 static int __init pxa_init(void)
diff -urN linux/arch/arm/mach-pxa/sleep.S linux/arch/arm/mach-pxa/sleep.S
--- linux/arch/arm/mach-pxa/sleep.S     2005/04/08 18:57:52     1.5
+++ linux/arch/arm/mach-pxa/sleep.S     2005/05/19 12:08:07     1.6
@@ -18,6 +18,11 @@
 
 #include <asm/arch/pxa-regs.h>
 
+#ifdef CONFIG_PXA27x                   // workaround for Errata 50
+#define MDREFR_KDIV    0x200a4000      // all banks
+#define CCCR_SLEEP     0x00000107      // L=7 2N=2 A=0 PPDIS=0 CPDIS=0
+#endif
+
                .text
 
 /*
@@ -28,7 +33,9 @@
 
 ENTRY(pxa_cpu_suspend)
 
+#ifndef CONFIG_IWMMXT
        mra     r2, r3, acc0
+#endif
        stmfd   sp!, {r2 - r12, lr}             @ save registers on stack
 
        @ get coprocessor registers
@@ -61,14 +68,23 @@
        @ prepare value for sleep mode
        mov     r1, #3                          @ sleep mode
 
-       @ prepare to put SDRAM into self-refresh manually
+       @ prepare pointer to physical address 0 (virtual mapping in generic.c)
+       mov     r2, #UNCACHED_PHYS_0
+
+       @ prepare SDRAM refresh settings
        ldr     r4, =MDREFR
        ldr     r5, [r4]
+
+       @ enable SDRAM self-refresh mode
        orr     r5, r5, #MDREFR_SLFRSH
 
-       @ prepare pointer to physical address 0 (virtual mapping in generic.c)
-       mov     r2, #UNCACHED_PHYS_0
+#ifdef CONFIG_PXA27x
+       @ set SDCLKx divide-by-2 bits (this is part of a workaround for Errata 
50)
+       ldr     r6, =MDREFR_KDIV
+       orr     r5, r5, r6
+#endif
 
+#ifdef CONFIG_PXA25x
        @ Intel PXA255 Specification Update notes problems
        @ about suspending with PXBus operating above 133MHz
        @ (see Errata 31, GPIO output signals, ... unpredictable in sleep
@@ -100,6 +116,18 @@
        mov     r0, #0
        mcr     p14, 0, r0, c6, c0, 0
        orr     r0, r0, #2                      @ initiate change bit
+#endif
+#ifdef CONFIG_PXA27x
+       @ Intel PXA270 Specification Update notes problems sleeping
+       @ with core operating above 91 MHz
+       @ (see Errata 50, ...processor does not exit from sleep...)
+
+       ldr     r6, =CCCR
+       ldr     r8, [r6]                @ keep original value for resume
+
+       ldr     r7, =CCCR_SLEEP         @ prepare CCCR sleep value
+       mov     r0, #0x2                @ prepare value for CLKCFG
+#endif
 
        @ align execution to a cache line
        b       1f
@@ -111,6 +139,7 @@
        @ All needed values are now in registers.
        @ These last instructions should be in cache
 
+#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
        @ initiate the frequency change...
        str     r7, [r6]
        mcr     p14, 0, r0, c6, c0, 0
@@ -118,14 +147,27 @@
        @ restore the original cpu speed value for resume
        str     r8, [r6]
 
-       @ put SDRAM into self-refresh
-       str     r5, [r4]
+       @ need 6 13-MHz cycles before changing PWRMODE
+       @ just set frequency to 91-MHz... 6*91/13 = 42
+
+       mov     r0, #42
+10:    subs    r0, r0, #1
+       bne     10b
+#endif
+
+       @ Do not reorder...
+       @ Intel PXA270 Specification Update notes problems performing
+       @ external accesses after SDRAM is put in self-refresh mode
+       @ (see Errata 39 ...hangs when entering self-refresh mode)
 
        @ force address lines low by reading at physical address 0
        ldr     r3, [r2]
 
+       @ put SDRAM into self-refresh
+       str     r5, [r4]
+
        @ enter sleep mode
-       mcr     p14, 0, r1, c7, c0, 0
+       mcr     p14, 0, r1, c7, c0, 0           @ PWRMODE
 
 20:    b       20b                             @ loop waiting for sleep
 
@@ -188,7 +230,9 @@
        bl      cpu_xscale_proc_init
 #endif
        ldmfd   sp!, {r2, r3}
+#ifndef CONFIG_IWMMXT
        mar     acc0, r2, r3
+#endif
        ldmfd   sp!, {r4 - r12, pc}             @ return to caller
 
 
diff -urN linux/arch/arm/mm/Kconfig linux/arch/arm/mm/Kconfig
--- linux/arch/arm/mm/Kconfig   2005/01/25 04:27:54     1.16
+++ linux/arch/arm/mm/Kconfig   2005/05/19 12:08:07     1.17
@@ -409,3 +409,24 @@
        depends on CPU_ARM1020
        help
          Say Y here to disable branch prediction.  If unsure, say N.
+
+config TLS_REG_EMUL
+       bool
+       default y if (SMP || CPU_32v6) && (CPU_32v5 || CPU_32v4 || CPU_32v3)
+       help
+         We might be running on an ARMv6+ processor which should have the TLS
+         register but for some reason we can't use it, or maybe an SMP system
+         using a pre-ARMv6 processor (there are apparently a few prototypes
+         like that in existence) and therefore access to that register must
+         be emulated.
+
+config HAS_TLS_REG
+       bool
+       depends on CPU_32v6
+       default y if !TLS_REG_EMUL
+       help
+         This selects support for the CP15 thread register.
+         It is defined to be available on ARMv6 or later.  If a particular
+         ARMv6 or later CPU doesn't support it then it must omc;ide "select
+         TLS_REG_EMUL" along with its other caracteristics.
+
diff -urN linux/arch/arm/mm/abort-ev6.S linux/arch/arm/mm/abort-ev6.S
--- linux/arch/arm/mm/abort-ev6.S       2004/03/11 16:46:40     1.1
+++ linux/arch/arm/mm/abort-ev6.S       2005/05/19 12:08:07     1.2
@@ -1,5 +1,6 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include "abort-macro.S"
 /*
  * Function: v6_early_abort
  *
@@ -13,11 +14,26 @@
  *        : sp = pointer to registers
  *
  * Purpose : obtain information about current aborted instruction.
+ * Note: we read user space.  This means we might cause a data
+ * abort here if the I-TLB and D-TLB aren't seeing the same
+ * picture.  Unfortunately, this does happen.  We live with it.
  */
        .align  5
 ENTRY(v6_early_abort)
        mrc     p15, 0, r1, c5, c0, 0           @ get FSR
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
+/*
+ * Faulty SWP instruction on 1136 doesn't set bit 11 in DFSR.
+ * The test below covers all the write situations, including Java bytecodes
+ */
+       bic     r1, r1, #1 << 11 | 1 << 10      @ clear bits 11 and 10 of FSR
+       tst     r3, #PSR_J_BIT                  @ Java?
+       movne   pc, lr
+       do_thumb_abort
+       ldreq   r3, [r2]                        @ read aborted ARM instruction
+       do_ldrd_abort
+       tst     r3, #1 << 20                    @ L = 0 -> write
+       orreq   r1, r1, #1 << 11                @ yes.
        mov     pc, lr
 
 
diff -urN linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c
--- linux/arch/arm/mm/mm-armv.c 2005/04/08 18:57:52     1.46
+++ linux/arch/arm/mm/mm-armv.c 2005/05/19 12:08:07     1.47
@@ -411,9 +411,10 @@
                mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4;
                mem_types[MT_ROM].prot_sect &= ~PMD_BIT4;
                /*
-                * Mark cache clean areas read only from SVC mode
-                * and no access from userspace.
+                * Mark cache clean areas and XIP ROM read only
+                * from SVC mode and no access from userspace.
                 */
+               mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
                mem_types[MT_MINICLEAN].prot_sect |= 
PMD_SECT_APX|PMD_SECT_AP_WRITE;
                mem_types[MT_CACHECLEAN].prot_sect |= 
PMD_SECT_APX|PMD_SECT_AP_WRITE;
        }
diff -urN linux/arch/arm26/Kconfig linux/arch/arm26/Kconfig
--- linux/arch/arm26/Kconfig    2005/01/25 04:27:54     1.13
+++ linux/arch/arm26/Kconfig    2005/05/19 12:08:07     1.14
@@ -89,6 +89,10 @@
           machine with 4MB of memory.
 endmenu
 
+config ISA_DMA_API
+       bool
+       default y
+
 menu "General setup"
 
 # Compressed boot loader in ROM.  Yes, we really want to ask about
diff -urN linux/arch/arm26/kernel/ptrace.c linux/arch/arm26/kernel/ptrace.c
--- linux/arch/arm26/kernel/ptrace.c    2005/02/07 02:54:31     1.4
+++ linux/arch/arm26/kernel/ptrace.c    2005/05/19 12:08:07     1.5
@@ -18,6 +18,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -591,7 +592,7 @@
                case PTRACE_SYSCALL:
                case PTRACE_CONT:
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        if (request == PTRACE_SYSCALL)
                                set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -626,7 +627,7 @@
                 */
                case PTRACE_SINGLESTEP:
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        child->ptrace |= PT_SINGLESTEP;
                        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
diff -urN linux/arch/arm26/mm/small_page.c linux/arch/arm26/mm/small_page.c
--- linux/arch/arm26/mm/small_page.c    2005/01/25 04:27:54     1.2
+++ linux/arch/arm26/mm/small_page.c    2005/05/19 12:08:07     1.3
@@ -92,8 +92,7 @@
                page = list_entry(order->queue.next, struct page, lru);
 again:
 #ifdef PEDANTIC
-               if (USED_MAP(page) & ~order->all_used)
-                       PAGE_BUG(page);
+               BUG_ON(USED_MAP(page) & ~order->all_used);
 #endif
                offset = ffz(USED_MAP(page));
                SET_USED(page, offset);
@@ -141,8 +140,7 @@
                        goto non_small;
 
 #ifdef PEDANTIC
-               if (USED_MAP(page) & ~order->all_used)
-                       PAGE_BUG(page);
+               BUG_ON(USED_MAP(page) & ~order->all_used);
 #endif
 
                spage = spage >> order->shift;
diff -urN linux/arch/cris/arch-v10/kernel/ptrace.c 
linux/arch/cris/arch-v10/kernel/ptrace.c
--- linux/arch/cris/arch-v10/kernel/ptrace.c    2004/11/15 11:49:15     1.5
+++ linux/arch/cris/arch-v10/kernel/ptrace.c    2005/05/19 12:08:07     1.6
@@ -10,6 +10,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -184,7 +185,7 @@
                case PTRACE_CONT:
                        ret = -EIO;
                        
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                         
                        if (request == PTRACE_SYSCALL) {
@@ -219,7 +220,7 @@
                case PTRACE_SINGLESTEP:
                        ret = -EIO;
                        
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        
                        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
diff -urN linux/arch/frv/kernel/ptrace.c linux/arch/frv/kernel/ptrace.c
--- linux/arch/frv/kernel/ptrace.c      2005/01/13 14:05:22     1.1
+++ linux/arch/frv/kernel/ptrace.c      2005/05/19 12:08:07     1.2
@@ -20,6 +20,7 @@
 #include <linux/user.h>
 #include <linux/config.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -239,7 +240,7 @@
        case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall 
*/
        case PTRACE_CONT: /* restart after signal. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                if (request == PTRACE_SYSCALL)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -267,7 +268,7 @@
 
        case PTRACE_SINGLESTEP:  /* set the trap flag. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                ptrace_enable(child);
diff -urN linux/arch/h8300/kernel/ptrace.c linux/arch/h8300/kernel/ptrace.c
--- linux/arch/h8300/kernel/ptrace.c    2004/10/25 20:44:13     1.8
+++ linux/arch/h8300/kernel/ptrace.c    2005/05/19 12:08:07     1.9
@@ -24,6 +24,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/config.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -171,7 +172,7 @@
                case PTRACE_SYSCALL: /* continue and stop at next (return from) 
syscall */
                case PTRACE_CONT: { /* restart after signal. */
                        ret = -EIO;
-                       if ((unsigned long) data >= _NSIG)
+                       if (!valid_signal(data))
                                break ;
                        if (request == PTRACE_SYSCALL)
                                set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -202,7 +203,7 @@
 
                case PTRACE_SINGLESTEP: {  /* set the trap flag. */
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                        child->exit_code = data;
diff -urN linux/arch/i386/Kconfig linux/arch/i386/Kconfig
--- linux/arch/i386/Kconfig     2005/03/18 17:36:48     1.53
+++ linux/arch/i386/Kconfig     2005/05/19 12:08:08     1.54
@@ -183,7 +183,7 @@
          - "Winchip-C6" for original IDT Winchip.
          - "Winchip-2" for IDT Winchip 2.
          - "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
-         - "MediaGX/Geode" for Cyrix MediaGX aka Geode.
+         - "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
          - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
          - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
 
@@ -311,12 +311,10 @@
          stores for this CPU, which can increase performance of some
          operations.
 
-config MGEODE
-       bool "MediaGX/Geode"
+config MGEODEGX1
+       bool "GeodeGX1"
        help
-         Select this for a Cyrix MediaGX aka Geode chip. Linux and GCC
-          treat this chip as a 586TSC with some extended instructions
-          and alignment reqirements.
+         Select this for a Geode GX1 (Cyrix MediaGX) chip.
 
 config MCYRIXIII
        bool "CyrixIII/VIA-C3"
@@ -368,7 +366,7 @@
        int
        default "7" if MPENTIUM4 || X86_GENERIC
        default "4" if X86_ELAN || M486 || M386
-       default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || 
MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX 
|| M586TSC || M586 || MVIAC3_2 || MGEODE
+       default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || 
MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX 
|| M586TSC || M586 || MVIAC3_2 || MGEODEGX1
        default "6" if MK7 || MK8 || MPENTIUMM
 
 config RWSEM_GENERIC_SPINLOCK
@@ -387,7 +385,7 @@
 
 config X86_PPRO_FENCE
        bool
-       depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODE
+       depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || 
MGEODEGX1
        default y
 
 config X86_F00F_BUG
@@ -417,7 +415,7 @@
 
 config X86_ALIGNMENT_16
        bool
-       depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || 
X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODE
+       depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || 
X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
        default y
 
 config X86_GOOD_APIC
@@ -442,7 +440,7 @@
 
 config X86_OOSTORE
        bool
-       depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MGEODE) && MTRR
+       depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
        default y
 
 config HPET_TIMER
@@ -578,7 +576,7 @@
 
 config X86_TSC
        bool
-       depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || 
MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII 
|| M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODE) && !X86_NUMAQ
+       depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || 
MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII 
|| M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1) && !X86_NUMAQ
        default y
 
 config X86_MCE
@@ -653,6 +651,24 @@
          Say Y if you intend to run this kernel on a Dell Inspiron 8000.
          Say N otherwise.
 
+config X86_REBOOTFIXUPS
+       bool "Enable X86 board specific fixups for reboot"
+       depends on X86
+       default n
+       ---help---
+         This enables chipset and/or board specific fixups to be done
+         in order to get reboot to work correctly. This is only needed on
+         some combinations of hardware and BIOS. The symptom, for which
+         this config is intended, is when reboot ends with a stalled/hung
+         system.
+
+         Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1.
+         combination.
+
+         Say Y if you want to enable the fixup. Currently, it's safe to
+         enable this option even if you don't need it.
+         Say N otherwise.
+
 config MICROCODE
        tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
        ---help---
@@ -1155,6 +1171,10 @@
 
 source "drivers/pci/Kconfig"
 
+config ISA_DMA_API
+       bool
+       default y
+
 config ISA
        bool "ISA support"
        depends on !(X86_VOYAGER || X86_VISWS)
diff -urN linux/arch/i386/Makefile linux/arch/i386/Makefile
--- linux/arch/i386/Makefile    2005/03/18 17:36:48     1.69
+++ linux/arch/i386/Makefile    2005/05/19 12:08:08     1.70
@@ -14,7 +14,7 @@
 # 19990713  Artur Skawina <skawina@geocities.com>
 #           Added '-march' and '-mpreferred-stack-boundary' support
 #
-#           Kianusch Sayah Karadji <kianusch@sk-tech.net>
+# 20050320  Kianusch Sayah Karadji <kianusch@sk-tech.net>
 #           Added support for GEODE CPU
 
 LDFLAGS                := -m elf_i386
@@ -54,8 +54,8 @@
 # AMD Elan support
 cflags-$(CONFIG_X86_ELAN)      += -march=i486
 
-# MediaGX aka Geode support
-cflags-$(CONFIG_MGEODE)                += $(call 
cc-option,-march=pentium-mmx,-march=i586)
+# Geode GX1 support
+cflags-$(CONFIG_MGEODEGX1)             += $(call 
cc-option,-march=pentium-mmx,-march=i486)
 
 # -mregparm=3 works ok on gcc-3.0 and later
 #
@@ -123,7 +123,7 @@
 boot := arch/i386/boot
 
 .PHONY: zImage bzImage compressed zlilo bzlilo \
-       zdisk bzdisk fdimage fdimage144 fdimage288 install
+       zdisk bzdisk fdimage fdimage144 fdimage288 install kernel_install
 
 all: bzImage
 
@@ -145,8 +145,9 @@
 fdimage fdimage144 fdimage288: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
 
-install:
-       $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
+install: vmlinux
+install kernel_install:
+       $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
 
 prepare: include/asm-$(ARCH)/asm_offsets.h
 CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
diff -urN linux/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S
--- linux/arch/i386/boot/bootsect.S     2003/06/05 00:04:30     1.18
+++ linux/arch/i386/boot/bootsect.S     2005/05/19 12:08:08     1.19
@@ -83,7 +83,7 @@
        .ascii  "\n"
        .ascii  "Remove disk and press any key to reboot . . .\r\n"
        .byte   0
-       
+
 
        # Kernel attributes; used by setup
 
diff -urN linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S
--- linux/arch/i386/boot/setup.S        2005/01/13 14:05:23     1.44
+++ linux/arch/i386/boot/setup.S        2005/05/19 12:08:08     1.45
@@ -164,7 +164,7 @@
 trampoline:    call    start_of_setup
                .align 16
                                        # The offset at this point is 0x240
-               .space  (0x7ff-0x240+1) # E820 & EDD space (ending at 0x7ff)
+               .space  (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff)
 # End of setup header #####################################################
 
 start_of_setup:
@@ -333,9 +333,9 @@
        # sizeof(e820rec).
        #
 good820:
-       movb    (E820NR), %al                   # up to 32 entries
+       movb    (E820NR), %al                   # up to 128 entries
        cmpb    $E820MAX, %al
-       jnl     bail820
+       jae     bail820
 
        incb    (E820NR)
        movw    %di, %ax
diff -urN linux/arch/i386/boot/video.S linux/arch/i386/boot/video.S
--- linux/arch/i386/boot/video.S        2004/10/25 20:44:13     1.14
+++ linux/arch/i386/boot/video.S        2005/05/19 12:08:08     1.15
@@ -1924,36 +1924,36 @@
        ret
 
 store_edid:
-       pushw   %es                             # just save all registers 
-       pushw   %ax                             
+       pushw   %es                             # just save all registers
+       pushw   %ax
        pushw   %bx
        pushw   %cx
        pushw   %dx
        pushw   %di
 
-       pushw   %fs                             
+       pushw   %fs
        popw    %es
 
        movl    $0x13131313, %eax               # memset block with 0x13
        movw    $32, %cx
        movw    $0x140, %di
        cld
-       rep 
-       stosl  
+       rep
+       stosl
 
-       movw    $0x4f15, %ax                    # do VBE/DDC 
+       movw    $0x4f15, %ax                    # do VBE/DDC
        movw    $0x01, %bx
        movw    $0x00, %cx
        movw    $0x01, %dx
        movw    $0x140, %di
-       int     $0x10   
+       int     $0x10
 
-       popw    %di                             # restore all registers        
+       popw    %di                             # restore all registers
        popw    %dx
        popw    %cx
        popw    %bx
        popw    %ax
-       popw    %es     
+       popw    %es
        ret
 
 # VIDEO_SELECT-only variables
diff -urN linux/arch/i386/boot/compressed/misc.c 
linux/arch/i386/boot/compressed/misc.c
--- linux/arch/i386/boot/compressed/misc.c      2004/06/26 15:15:08     1.24
+++ linux/arch/i386/boot/compressed/misc.c      2005/05/19 12:08:08     1.25
@@ -12,7 +12,6 @@
 #include <linux/linkage.h>
 #include <linux/vmalloc.h>
 #include <linux/tty.h>
-#include <video/edid.h>
 #include <asm/io.h>
 
 /*
diff -urN linux/arch/i386/kernel/reboot_fixups.c 
linux/arch/i386/kernel/reboot_fixups.c
--- linux/arch/i386/kernel/reboot_fixups.c      1970/01/01 00:00:00
+++ linux/arch/i386/kernel/reboot_fixups.c      2005-05-19 13:08:08.484921000 
+0100     1.1
@@ -0,0 +1,56 @@
+/*
+ * linux/arch/i386/kernel/reboot_fixups.c
+ *
+ * This is a good place to put board specific reboot fixups.
+ *
+ * List of supported fixups:
+ * geode-gx1/cs5530a - Jaya Kumar <jayalk@intworks.biz>
+ *
+ */
+
+#include <asm/delay.h>
+#include <linux/pci.h>
+
+static void cs5530a_warm_reset(struct pci_dev *dev)
+{
+       /* writing 1 to the reset control register, 0x44 causes the
+       cs5530a to perform a system warm reset */
+       pci_write_config_byte(dev, 0x44, 0x1);
+       udelay(50); /* shouldn't get here but be safe and spin-a-while */
+       return;
+}
+
+struct device_fixup {
+       unsigned int vendor;
+       unsigned int device;
+       void (*reboot_fixup)(struct pci_dev *);
+};
+
+static struct device_fixup fixups_table[] = {
+{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset },
+};
+
+/*
+ * we see if any fixup is available for our current hardware. if there
+ * is a fixup, we call it and we expect to never return from it. if we
+ * do return, we keep looking and then eventually fall back to the
+ * standard mach_reboot on return.
+ */
+void mach_reboot_fixups(void)
+{
+       struct device_fixup *cur;
+       struct pci_dev *dev;
+       int i;
+
+       for (i=0; i < (sizeof(fixups_table)/sizeof(fixups_table[0])); i++) {
+               cur = &(fixups_table[i]);
+               dev = pci_get_device(cur->vendor, cur->device, 0);
+               if (!dev)
+                       continue;
+
+               cur->reboot_fixup(dev);
+       }
+
+       printk(KERN_WARNING "No reboot fixup found for your hardware\n");
+}
+
diff -urN linux/arch/i386/kernel/syscall_table.S 
linux/arch/i386/kernel/syscall_table.S
--- linux/arch/i386/kernel/syscall_table.S      1970/01/01 00:00:00
+++ linux/arch/i386/kernel/syscall_table.S      2005-05-19 13:08:08.495831000 
+0100     1.1
@@ -0,0 +1,291 @@
+.data
+ENTRY(sys_call_table)
+       .long sys_restart_syscall       /* 0 - old "setup()" system call, used 
for restarting */
+       .long sys_exit
+       .long sys_fork
+       .long sys_read
+       .long sys_write
+       .long sys_open          /* 5 */
+       .long sys_close
+       .long sys_waitpid
+       .long sys_creat
+       .long sys_link
+       .long sys_unlink        /* 10 */
+       .long sys_execve
+       .long sys_chdir
+       .long sys_time
+       .long sys_mknod
+       .long sys_chmod         /* 15 */
+       .long sys_lchown16
+       .long sys_ni_syscall    /* old break syscall holder */
+       .long sys_stat
+       .long sys_lseek
+       .long sys_getpid        /* 20 */
+       .long sys_mount
+       .long sys_oldumount
+       .long sys_setuid16
+       .long sys_getuid16
+       .long sys_stime         /* 25 */
+       .long sys_ptrace
+       .long sys_alarm
+       .long sys_fstat
+       .long sys_pause
+       .long sys_utime         /* 30 */
+       .long sys_ni_syscall    /* old stty syscall holder */
+       .long sys_ni_syscall    /* old gtty syscall holder */
+       .long sys_access
+       .long sys_nice
+       .long sys_ni_syscall    /* 35 - old ftime syscall holder */
+       .long sys_sync
+       .long sys_kill
+       .long sys_rename
+       .long sys_mkdir
+       .long sys_rmdir         /* 40 */
+       .long sys_dup
+       .long sys_pipe
+       .long sys_times
+       .long sys_ni_syscall    /* old prof syscall holder */
+       .long sys_brk           /* 45 */
+       .long sys_setgid16
+       .long sys_getgid16
+       .long sys_signal
+       .long sys_geteuid16
+       .long sys_getegid16     /* 50 */
+       .long sys_acct
+       .long sys_umount        /* recycled never used phys() */
+       .long sys_ni_syscall    /* old lock syscall holder */
+       .long sys_ioctl
+       .long sys_fcntl         /* 55 */
+       .long sys_ni_syscall    /* old mpx syscall holder */
+       .long sys_setpgid
+       .long sys_ni_syscall    /* old ulimit syscall holder */
+       .long sys_olduname
+       .long sys_umask         /* 60 */
+       .long sys_chroot
+       .long sys_ustat
+       .long sys_dup2
+       .long sys_getppid
+       .long sys_getpgrp       /* 65 */
+       .long sys_setsid
+       .long sys_sigaction
+       .long sys_sgetmask
+       .long sys_ssetmask
+       .long sys_setreuid16    /* 70 */
+       .long sys_setregid16
+       .long sys_sigsuspend
+       .long sys_sigpending
+       .long sys_sethostname
+       .long sys_setrlimit     /* 75 */
+       .long sys_old_getrlimit
+       .long sys_getrusage
+       .long sys_gettimeofday
+       .long sys_settimeofday
+       .long sys_getgroups16   /* 80 */
+       .long sys_setgroups16
+       .long old_select
+       .long sys_symlink
+       .long sys_lstat
+       .long sys_readlink      /* 85 */
+       .long sys_uselib
+       .long sys_swapon
+       .long sys_reboot
+       .long old_readdir
+       .long old_mmap          /* 90 */
+       .long sys_munmap
+       .long sys_truncate
+       .long sys_ftruncate
+       .long sys_fchmod
+       .long sys_fchown16      /* 95 */
+       .long sys_getpriority
+       .long sys_setpriority
+       .long sys_ni_syscall    /* old profil syscall holder */
+       .long sys_statfs
+       .long sys_fstatfs       /* 100 */
+       .long sys_ioperm
+       .long sys_socketcall
+       .long sys_syslog
+       .long sys_setitimer
+       .long sys_getitimer     /* 105 */
+       .long sys_newstat
+       .long sys_newlstat
+       .long sys_newfstat
+       .long sys_uname
+       .long sys_iopl          /* 110 */
+       .long sys_vhangup
+       .long sys_ni_syscall    /* old "idle" system call */
+       .long sys_vm86old
+       .long sys_wait4
+       .long sys_swapoff       /* 115 */
+       .long sys_sysinfo
+       .long sys_ipc
+       .long sys_fsync
+       .long sys_sigreturn
+       .long sys_clone         /* 120 */
+       .long sys_setdomainname
+       .long sys_newuname
+       .long sys_modify_ldt
+       .long sys_adjtimex
+       .long sys_mprotect      /* 125 */
+       .long sys_sigprocmask
+       .long sys_ni_syscall    /* old "create_module" */
+       .long sys_init_module
+       .long sys_delete_module
+       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
+       .long sys_quotactl
+       .long sys_getpgid
+       .long sys_fchdir
+       .long sys_bdflush
+       .long sys_sysfs         /* 135 */
+       .long sys_personality
+       .long sys_ni_syscall    /* reserved for afs_syscall */
+       .long sys_setfsuid16
+       .long sys_setfsgid16
+       .long sys_llseek        /* 140 */
+       .long sys_getdents
+       .long sys_select
+       .long sys_flock
+       .long sys_msync
+       .long sys_readv         /* 145 */
+       .long sys_writev
+       .long sys_getsid
+       .long sys_fdatasync
+       .long sys_sysctl
+       .long sys_mlock         /* 150 */
+       .long sys_munlock
+       .long sys_mlockall
+       .long sys_munlockall
+       .long sys_sched_setparam
+       .long sys_sched_getparam   /* 155 */
+       .long sys_sched_setscheduler
+       .long sys_sched_getscheduler
+       .long sys_sched_yield
+       .long sys_sched_get_priority_max
+       .long sys_sched_get_priority_min  /* 160 */
+       .long sys_sched_rr_get_interval
+       .long sys_nanosleep
+       .long sys_mremap
+       .long sys_setresuid16
+       .long sys_getresuid16   /* 165 */
+       .long sys_vm86
+       .long sys_ni_syscall    /* Old sys_query_module */
+       .long sys_poll
+       .long sys_nfsservctl
+       .long sys_setresgid16   /* 170 */
+       .long sys_getresgid16
+       .long sys_prctl
+       .long sys_rt_sigreturn
+       .long sys_rt_sigaction
+       .long sys_rt_sigprocmask        /* 175 */
+       .long sys_rt_sigpending
+       .long sys_rt_sigtimedwait
+       .long sys_rt_sigqueueinfo
+       .long sys_rt_sigsuspend
+       .long sys_pread64       /* 180 */
+       .long sys_pwrite64
+       .long sys_chown16
+       .long sys_getcwd
+       .long sys_capget
+       .long sys_capset        /* 185 */
+       .long sys_sigaltstack
+       .long sys_sendfile
+       .long sys_ni_syscall    /* reserved for streams1 */
+       .long sys_ni_syscall    /* reserved for streams2 */
+       .long sys_vfork         /* 190 */
+       .long sys_getrlimit
+       .long sys_mmap2
+       .long sys_truncate64
+       .long sys_ftruncate64
+       .long sys_stat64        /* 195 */
+       .long sys_lstat64
+       .long sys_fstat64
+       .long sys_lchown
+       .long sys_getuid
+       .long sys_getgid        /* 200 */
+       .long sys_geteuid
+       .long sys_getegid
+       .long sys_setreuid
+       .long sys_setregid
+       .long sys_getgroups     /* 205 */
+       .long sys_setgroups
+       .long sys_fchown
+       .long sys_setresuid
+       .long sys_getresuid
+       .long sys_setresgid     /* 210 */
+       .long sys_getresgid
+       .long sys_chown
+       .long sys_setuid
+       .long sys_setgid
+       .long sys_setfsuid      /* 215 */
+       .long sys_setfsgid
+       .long sys_pivot_root
+       .long sys_mincore
+       .long sys_madvise
+       .long sys_getdents64    /* 220 */
+       .long sys_fcntl64
+       .long sys_ni_syscall    /* reserved for TUX */
+       .long sys_ni_syscall
+       .long sys_gettid
+       .long sys_readahead     /* 225 */
+       .long sys_setxattr
+       .long sys_lsetxattr
+       .long sys_fsetxattr
+       .long sys_getxattr
+       .long sys_lgetxattr     /* 230 */
+       .long sys_fgetxattr
+       .long sys_listxattr
+       .long sys_llistxattr
+       .long sys_flistxattr
+       .long sys_removexattr   /* 235 */
+       .long sys_lremovexattr
+       .long sys_fremovexattr
+       .long sys_tkill
+       .long sys_sendfile64
+       .long sys_futex         /* 240 */
+       .long sys_sched_setaffinity
+       .long sys_sched_getaffinity
+       .long sys_set_thread_area
+       .long sys_get_thread_area
+       .long sys_io_setup      /* 245 */
+       .long sys_io_destroy
+       .long sys_io_getevents
+       .long sys_io_submit
+       .long sys_io_cancel
+       .long sys_fadvise64     /* 250 */
+       .long sys_ni_syscall
+       .long sys_exit_group
+       .long sys_lookup_dcookie
+       .long sys_epoll_create
+       .long sys_epoll_ctl     /* 255 */
+       .long sys_epoll_wait
+       .long sys_remap_file_pages
+       .long sys_set_tid_address
+       .long sys_timer_create
+       .long sys_timer_settime         /* 260 */
+       .long sys_timer_gettime
+       .long sys_timer_getoverrun
+       .long sys_timer_delete
+       .long sys_clock_settime
+       .long sys_clock_gettime         /* 265 */
+       .long sys_clock_getres
+       .long sys_clock_nanosleep
+       .long sys_statfs64
+       .long sys_fstatfs64
+       .long sys_tgkill        /* 270 */
+       .long sys_utimes
+       .long sys_fadvise64_64
+       .long sys_ni_syscall    /* sys_vserver */
+       .long sys_mbind
+       .long sys_get_mempolicy
+       .long sys_set_mempolicy
+       .long sys_mq_open
+       .long sys_mq_unlink
+       .long sys_mq_timedsend
+       .long sys_mq_timedreceive       /* 280 */
+       .long sys_mq_notify
+       .long sys_mq_getsetattr
+       .long sys_ni_syscall            /* reserved for kexec */
+       .long sys_waitid
+       .long sys_ni_syscall            /* 285 */ /* available */
+       .long sys_add_key
+       .long sys_request_key
+       .long sys_keyctl
diff -urN linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- linux/arch/i386/kernel/Makefile     2005/04/29 11:15:00     1.71
+++ linux/arch/i386/kernel/Makefile     2005/05/19 12:08:08     1.72
@@ -23,6 +23,7 @@
 obj-$(CONFIG_X86_MPPARSE)      += mpparse.o
 obj-$(CONFIG_X86_LOCAL_APIC)   += apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)      += io_apic.o
+obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o
 obj-$(CONFIG_X86_NUMAQ)                += numaq.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)  += summit.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
diff -urN linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c
--- linux/arch/i386/kernel/apic.c       2005/04/29 11:15:00     1.64
+++ linux/arch/i386/kernel/apic.c       2005/05/19 12:08:08     1.65
@@ -1265,8 +1265,6 @@
 
        setup_local_APIC();
 
-       if (nmi_watchdog == NMI_LOCAL_APIC)
-               check_nmi_watchdog();
 #ifdef CONFIG_X86_IO_APIC
        if (smp_found_config)
                if (!skip_ioapic_setup && nr_ioapics)
diff -urN linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux/arch/i386/kernel/entry.S      2005/04/29 11:15:00     1.100
+++ linux/arch/i386/kernel/entry.S      2005/05/19 12:08:08     1.101
@@ -260,11 +260,9 @@
 .section .fixup,"ax"
 iret_exc:
        sti
-       movl $__USER_DS, %edx
-       movl %edx, %ds
-       movl %edx, %es
-       movl $11,%eax
-       call do_exit
+       pushl $0                        # no error code
+       pushl $do_iret_error
+       jmp error_code
 .previous
 .section __ex_table,"a"
        .align 4
@@ -516,8 +514,6 @@
        xorl %edx,%edx                  # error code 0
        movl %esp,%eax                  # pt_regs pointer
        call do_debug
-       testl %eax,%eax
-       jnz restore_all
        jmp ret_from_exception
 
 /*
@@ -598,8 +594,6 @@
        xorl %edx,%edx          # zero error code
        movl %esp,%eax          # pt_regs pointer
        call do_int3
-       testl %eax,%eax
-       jnz restore_all
        jmp ret_from_exception
 
 ENTRY(overflow)
@@ -658,296 +652,6 @@
        pushl $do_spurious_interrupt_bug
        jmp error_code
 
-.data
-ENTRY(sys_call_table)
-       .long sys_restart_syscall       /* 0 - old "setup()" system call, used 
for restarting */
-       .long sys_exit
-       .long sys_fork
-       .long sys_read
-       .long sys_write
-       .long sys_open          /* 5 */
-       .long sys_close
-       .long sys_waitpid
-       .long sys_creat
-       .long sys_link
-       .long sys_unlink        /* 10 */
-       .long sys_execve
-       .long sys_chdir
-       .long sys_time
-       .long sys_mknod
-       .long sys_chmod         /* 15 */
-       .long sys_lchown16
-       .long sys_ni_syscall    /* old break syscall holder */
-       .long sys_stat
-       .long sys_lseek
-       .long sys_getpid        /* 20 */
-       .long sys_mount
-       .long sys_oldumount
-       .long sys_setuid16
-       .long sys_getuid16
-       .long sys_stime         /* 25 */
-       .long sys_ptrace
-       .long sys_alarm
-       .long sys_fstat
-       .long sys_pause
-       .long sys_utime         /* 30 */
-       .long sys_ni_syscall    /* old stty syscall holder */
-       .long sys_ni_syscall    /* old gtty syscall holder */
-       .long sys_access
-       .long sys_nice
-       .long sys_ni_syscall    /* 35 - old ftime syscall holder */
-       .long sys_sync
-       .long sys_kill
-       .long sys_rename
-       .long sys_mkdir
-       .long sys_rmdir         /* 40 */
-       .long sys_dup
-       .long sys_pipe
-       .long sys_times
-       .long sys_ni_syscall    /* old prof syscall holder */
-       .long sys_brk           /* 45 */
-       .long sys_setgid16
-       .long sys_getgid16
-       .long sys_signal
-       .long sys_geteuid16
-       .long sys_getegid16     /* 50 */
-       .long sys_acct
-       .long sys_umount        /* recycled never used phys() */
-       .long sys_ni_syscall    /* old lock syscall holder */
-       .long sys_ioctl
-       .long sys_fcntl         /* 55 */
-       .long sys_ni_syscall    /* old mpx syscall holder */
-       .long sys_setpgid
-       .long sys_ni_syscall    /* old ulimit syscall holder */
-       .long sys_olduname
-       .long sys_umask         /* 60 */
-       .long sys_chroot
-       .long sys_ustat
-       .long sys_dup2
-       .long sys_getppid
-       .long sys_getpgrp       /* 65 */
-       .long sys_setsid
-       .long sys_sigaction
-       .long sys_sgetmask
-       .long sys_ssetmask
-       .long sys_setreuid16    /* 70 */
-       .long sys_setregid16
-       .long sys_sigsuspend
-       .long sys_sigpending
-       .long sys_sethostname
-       .long sys_setrlimit     /* 75 */
-       .long sys_old_getrlimit
-       .long sys_getrusage
-       .long sys_gettimeofday
-       .long sys_settimeofday
-       .long sys_getgroups16   /* 80 */
-       .long sys_setgroups16
-       .long old_select
-       .long sys_symlink
-       .long sys_lstat
-       .long sys_readlink      /* 85 */
-       .long sys_uselib
-       .long sys_swapon
-       .long sys_reboot
-       .long old_readdir
-       .long old_mmap          /* 90 */
-       .long sys_munmap
-       .long sys_truncate
-       .long sys_ftruncate
-       .long sys_fchmod
-       .long sys_fchown16      /* 95 */
-       .long sys_getpriority
-       .long sys_setpriority
-       .long sys_ni_syscall    /* old profil syscall holder */
-       .long sys_statfs
-       .long sys_fstatfs       /* 100 */
-       .long sys_ioperm
-       .long sys_socketcall
-       .long sys_syslog
-       .long sys_setitimer
-       .long sys_getitimer     /* 105 */
-       .long sys_newstat
-       .long sys_newlstat
-       .long sys_newfstat
-       .long sys_uname
-       .long sys_iopl          /* 110 */
-       .long sys_vhangup
-       .long sys_ni_syscall    /* old "idle" system call */
-       .long sys_vm86old
-       .long sys_wait4
-       .long sys_swapoff       /* 115 */
-       .long sys_sysinfo
-       .long sys_ipc
-       .long sys_fsync
-       .long sys_sigreturn
-       .long sys_clone         /* 120 */
-       .long sys_setdomainname
-       .long sys_newuname
-       .long sys_modify_ldt
-       .long sys_adjtimex
-       .long sys_mprotect      /* 125 */
-       .long sys_sigprocmask
-       .long sys_ni_syscall    /* old "create_module" */ 
-       .long sys_init_module
-       .long sys_delete_module
-       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
-       .long sys_quotactl
-       .long sys_getpgid
-       .long sys_fchdir
-       .long sys_bdflush
-       .long sys_sysfs         /* 135 */
-       .long sys_personality
-       .long sys_ni_syscall    /* reserved for afs_syscall */
-       .long sys_setfsuid16
-       .long sys_setfsgid16
-       .long sys_llseek        /* 140 */
-       .long sys_getdents
-       .long sys_select
-       .long sys_flock
-       .long sys_msync
-       .long sys_readv         /* 145 */
-       .long sys_writev
-       .long sys_getsid
-       .long sys_fdatasync
-       .long sys_sysctl
-       .long sys_mlock         /* 150 */
-       .long sys_munlock
-       .long sys_mlockall
-       .long sys_munlockall
-       .long sys_sched_setparam
-       .long sys_sched_getparam   /* 155 */
-       .long sys_sched_setscheduler
-       .long sys_sched_getscheduler
-       .long sys_sched_yield
-       .long sys_sched_get_priority_max
-       .long sys_sched_get_priority_min  /* 160 */
-       .long sys_sched_rr_get_interval
-       .long sys_nanosleep
-       .long sys_mremap
-       .long sys_setresuid16
-       .long sys_getresuid16   /* 165 */
-       .long sys_vm86
-       .long sys_ni_syscall    /* Old sys_query_module */
-       .long sys_poll
-       .long sys_nfsservctl
-       .long sys_setresgid16   /* 170 */
-       .long sys_getresgid16
-       .long sys_prctl
-       .long sys_rt_sigreturn
-       .long sys_rt_sigaction
-       .long sys_rt_sigprocmask        /* 175 */
-       .long sys_rt_sigpending
-       .long sys_rt_sigtimedwait
-       .long sys_rt_sigqueueinfo
-       .long sys_rt_sigsuspend
-       .long sys_pread64       /* 180 */
-       .long sys_pwrite64
-       .long sys_chown16
-       .long sys_getcwd
-       .long sys_capget
-       .long sys_capset        /* 185 */
-       .long sys_sigaltstack
-       .long sys_sendfile
-       .long sys_ni_syscall    /* reserved for streams1 */
-       .long sys_ni_syscall    /* reserved for streams2 */
-       .long sys_vfork         /* 190 */
-       .long sys_getrlimit
-       .long sys_mmap2
-       .long sys_truncate64
-       .long sys_ftruncate64
-       .long sys_stat64        /* 195 */
-       .long sys_lstat64
-       .long sys_fstat64
-       .long sys_lchown
-       .long sys_getuid
-       .long sys_getgid        /* 200 */
-       .long sys_geteuid
-       .long sys_getegid
-       .long sys_setreuid
-       .long sys_setregid
-       .long sys_getgroups     /* 205 */
-       .long sys_setgroups
-       .long sys_fchown
-       .long sys_setresuid
-       .long sys_getresuid
-       .long sys_setresgid     /* 210 */
-       .long sys_getresgid
-       .long sys_chown
-       .long sys_setuid
-       .long sys_setgid
-       .long sys_setfsuid      /* 215 */
-       .long sys_setfsgid
-       .long sys_pivot_root
-       .long sys_mincore
-       .long sys_madvise
-       .long sys_getdents64    /* 220 */
-       .long sys_fcntl64
-       .long sys_ni_syscall    /* reserved for TUX */
-       .long sys_ni_syscall
-       .long sys_gettid
-       .long sys_readahead     /* 225 */
-       .long sys_setxattr
-       .long sys_lsetxattr
-       .long sys_fsetxattr
-       .long sys_getxattr
-       .long sys_lgetxattr     /* 230 */
-       .long sys_fgetxattr
-       .long sys_listxattr
-       .long sys_llistxattr
-       .long sys_flistxattr
-       .long sys_removexattr   /* 235 */
-       .long sys_lremovexattr
-       .long sys_fremovexattr
-       .long sys_tkill
-       .long sys_sendfile64
-       .long sys_futex         /* 240 */
-       .long sys_sched_setaffinity
-       .long sys_sched_getaffinity
-       .long sys_set_thread_area
-       .long sys_get_thread_area
-       .long sys_io_setup      /* 245 */
-       .long sys_io_destroy
-       .long sys_io_getevents
-       .long sys_io_submit
-       .long sys_io_cancel
-       .long sys_fadvise64     /* 250 */
-       .long sys_ni_syscall
-       .long sys_exit_group
-       .long sys_lookup_dcookie
-       .long sys_epoll_create
-       .long sys_epoll_ctl     /* 255 */
-       .long sys_epoll_wait
-       .long sys_remap_file_pages
-       .long sys_set_tid_address
-       .long sys_timer_create
-       .long sys_timer_settime         /* 260 */
-       .long sys_timer_gettime
-       .long sys_timer_getoverrun
-       .long sys_timer_delete
-       .long sys_clock_settime
-       .long sys_clock_gettime         /* 265 */
-       .long sys_clock_getres
-       .long sys_clock_nanosleep
-       .long sys_statfs64
-       .long sys_fstatfs64     
-       .long sys_tgkill        /* 270 */
-       .long sys_utimes
-       .long sys_fadvise64_64
-       .long sys_ni_syscall    /* sys_vserver */
-       .long sys_mbind
-       .long sys_get_mempolicy
-       .long sys_set_mempolicy
-       .long sys_mq_open
-       .long sys_mq_unlink
-       .long sys_mq_timedsend
-       .long sys_mq_timedreceive       /* 280 */
-       .long sys_mq_notify
-       .long sys_mq_getsetattr
-       .long sys_ni_syscall            /* reserved for kexec */
-       .long sys_waitid
-       .long sys_ni_syscall            /* 285 */ /* available */
-       .long sys_add_key
-       .long sys_request_key
-       .long sys_keyctl
+#include "syscall_table.S"
 
 syscall_table_size=(.-sys_call_table)
diff -urN linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- linux/arch/i386/kernel/head.S       2005/04/08 18:57:53     1.51
+++ linux/arch/i386/kernel/head.S       2005/05/19 12:08:08     1.52
@@ -380,6 +380,7 @@
        ALIGN
 ignore_int:
        cld
+#ifdef CONFIG_PRINTK
        pushl %eax
        pushl %ecx
        pushl %edx
@@ -400,6 +401,7 @@
        popl %edx
        popl %ecx
        popl %eax
+#endif
        iret
 
 /*
diff -urN linux/arch/i386/kernel/i386_ksyms.c 
linux/arch/i386/kernel/i386_ksyms.c
--- linux/arch/i386/kernel/i386_ksyms.c 2005/03/18 17:36:48     1.81
+++ linux/arch/i386/kernel/i386_ksyms.c 2005/05/19 12:08:08     1.82
@@ -169,10 +169,6 @@
 EXPORT_SYMBOL_GPL(set_nmi_callback);
 EXPORT_SYMBOL_GPL(unset_nmi_callback);
 
-#undef memcmp
-extern int memcmp(const void *,const void *,__kernel_size_t);
-EXPORT_SYMBOL(memcmp);
-
 EXPORT_SYMBOL(register_die_notifier);
 #ifdef CONFIG_HAVE_DEC_LOCK
 EXPORT_SYMBOL(_atomic_dec_and_lock);
diff -urN linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- linux/arch/i386/kernel/io_apic.c    2005/04/29 11:15:00     1.89
+++ linux/arch/i386/kernel/io_apic.c    2005/05/19 12:08:08     1.90
@@ -2175,7 +2175,6 @@
                                disable_8259A_irq(0);
                                setup_nmi();
                                enable_8259A_irq(0);
-                               check_nmi_watchdog();
                        }
                        return;
                }
@@ -2198,7 +2197,6 @@
                                add_pin_to_irq(0, 0, pin2);
                        if (nmi_watchdog == NMI_IO_APIC) {
                                setup_nmi();
-                               check_nmi_watchdog();
                        }
                        return;
                }
diff -urN linux/arch/i386/kernel/kprobes.c linux/arch/i386/kernel/kprobes.c
--- linux/arch/i386/kernel/kprobes.c    2005/04/08 18:57:53     1.7
+++ linux/arch/i386/kernel/kprobes.c    2005/05/19 12:08:08     1.8
@@ -217,6 +217,13 @@
                *tos &= ~(TF_MASK | IF_MASK);
                *tos |= kprobe_old_eflags;
                break;
+       case 0xc3:              /* ret/lret */
+       case 0xcb:
+       case 0xc2:
+       case 0xca:
+               regs->eflags &= ~TF_MASK;
+               /* eip is already adjusted, no more changes required*/
+               return;
        case 0xe8:              /* call relative - Fix return addr */
                *tos = orig_eip + (*tos - copy_eip);
                break;
diff -urN linux/arch/i386/kernel/nmi.c linux/arch/i386/kernel/nmi.c
--- linux/arch/i386/kernel/nmi.c        2005/04/29 11:15:00     1.28
+++ linux/arch/i386/kernel/nmi.c        2005/05/19 12:08:08     1.29
@@ -102,20 +102,21 @@
        (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|     \
         P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
 
-int __init check_nmi_watchdog (void)
+static int __init check_nmi_watchdog(void)
 {
        unsigned int prev_nmi_count[NR_CPUS];
        int cpu;
 
-       printk(KERN_INFO "testing NMI watchdog ... ");
+       if (nmi_watchdog == NMI_NONE)
+               return 0;
+
+       printk(KERN_INFO "Testing NMI watchdog ... ");
 
        for (cpu = 0; cpu < NR_CPUS; cpu++)
                prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count;
        local_irq_enable();
        mdelay((10*1000)/nmi_hz); // wait 10 ticks
 
-       /* FIXME: Only boot CPU is online at this stage.  Check CPUs
-           as they come up. */
        for (cpu = 0; cpu < NR_CPUS; cpu++) {
 #ifdef CONFIG_SMP
                /* Check cpu_callin_map here because that is set
@@ -139,6 +140,8 @@
 
        return 0;
 }
+/* This needs to happen later in boot so counters are working */
+late_initcall(check_nmi_watchdog);
 
 static int __init setup_nmi_watchdog(char *str)
 {
diff -urN linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- linux/arch/i386/kernel/process.c    2005/04/29 11:15:00     1.98
+++ linux/arch/i386/kernel/process.c    2005/05/19 12:08:08     1.99
@@ -400,11 +400,6 @@
        int err;
 
        childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) 
p->thread_info)) - 1;
-       *childregs = *regs;
-       childregs->eax = 0;
-       childregs->esp = esp;
-
-       p->thread.esp = (unsigned long) childregs;
        /*
         * The below -8 is to reserve 8 bytes on top of the ring0 stack.
         * This is necessary to guarantee that the entire "struct pt_regs"
@@ -415,7 +410,13 @@
         * "struct pt_regs" is possible, but they may contain the
         * completely wrong values.
         */
-       p->thread.esp0 = (unsigned long) (childregs+1) - 8;
+       childregs = (struct pt_regs *) ((unsigned long) childregs - 8);
+       *childregs = *regs;
+       childregs->eax = 0;
+       childregs->esp = esp;
+
+       p->thread.esp = (unsigned long) childregs;
+       p->thread.esp0 = (unsigned long) (childregs+1);
 
        p->thread.eip = (unsigned long) ret_from_fork;
 
@@ -611,8 +612,8 @@
         * Save away %fs and %gs. No need to save %es and %ds, as
         * those are always kernel segments while inside the kernel.
         */
-       asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->fs));
-       asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
+       asm volatile("mov %%fs,%0":"=m" (prev->fs));
+       asm volatile("mov %%gs,%0":"=m" (prev->gs));
 
        /*
         * Restore %fs and %gs if needed.
diff -urN linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- linux/arch/i386/kernel/ptrace.c     2005/03/18 17:36:48     1.49
+++ linux/arch/i386/kernel/ptrace.c     2005/05/19 12:08:08     1.50
@@ -16,6 +16,7 @@
 #include <linux/security.h>
 #include <linux/audit.h>
 #include <linux/seccomp.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -511,7 +512,7 @@
        case PTRACE_SYSCALL:    /* continue and stop at next (return from) 
syscall */
        case PTRACE_CONT:       /* restart after signal. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                if (request == PTRACE_SYSCALL) {
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -543,7 +544,7 @@
 
        case PTRACE_SINGLESTEP: /* set the trap flag. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                set_singlestep(child);
@@ -682,24 +683,18 @@
        /* do the secure computing check first */
        secure_computing(regs->orig_eax);
 
-       if (unlikely(current->audit_context)) {
-               if (!entryexit)
-                       audit_syscall_entry(current, regs->orig_eax,
-                                           regs->ebx, regs->ecx,
-                                           regs->edx, regs->esi);
-               else
-                       audit_syscall_exit(current, regs->eax);
-       }
+       if (unlikely(current->audit_context) && entryexit)
+               audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), 
regs->eax);
 
        if (!(current->ptrace & PT_PTRACED))
-               return;
+               goto out;
 
        /* Fake a debug trap */
        if (test_thread_flag(TIF_SINGLESTEP))
                send_sigtrap(current, regs, 0);
 
        if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
+               goto out;
 
        /* the 0x80 provides a way for the tracing parent to distinguish
           between a syscall stop and SIGTRAP delivery */
@@ -714,4 +709,9 @@
                send_sig(current->exit_code, current, 1);
                current->exit_code = 0;
        }
+ out:
+       if (unlikely(current->audit_context) && !entryexit)
+               audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
+                                   regs->ebx, regs->ecx, regs->edx, regs->esi);
+
 }
diff -urN linux/arch/i386/kernel/reboot.c linux/arch/i386/kernel/reboot.c
--- linux/arch/i386/kernel/reboot.c     2005/02/07 02:54:31     1.12
+++ linux/arch/i386/kernel/reboot.c     2005/05/19 12:08:08     1.13
@@ -13,6 +13,7 @@
 #include <asm/uaccess.h>
 #include <asm/apic.h>
 #include "mach_reboot.h"
+#include <linux/reboot_fixups.h>
 
 /*
  * Power off function, if any
@@ -348,6 +349,7 @@
                /* rebooting needs to touch the page at absolute addr 0 */
                *((unsigned short *)__va(0x472)) = reboot_mode;
                for (;;) {
+                       mach_reboot_fixups(); /* for board specific fixups */
                        mach_reboot();
                        /* That didn't work - force a triple fault.. */
                        __asm__ __volatile__("lidt %0": :"m" (no_idt));
diff -urN linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- linux/arch/i386/kernel/smpboot.c    2005/04/29 11:15:00     1.68
+++ linux/arch/i386/kernel/smpboot.c    2005/05/19 12:08:08     1.69
@@ -1089,9 +1089,6 @@
                }
        }
 
-       if (nmi_watchdog == NMI_LOCAL_APIC)
-               check_nmi_watchdog();
-
        smpboot_setup_io_apic();
 
        setup_boot_APIC_clock();
diff -urN linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- linux/arch/i386/kernel/time.c       2005/04/29 11:15:00     1.62
+++ linux/arch/i386/kernel/time.c       2005/05/19 12:08:08     1.63
@@ -441,7 +441,7 @@
        set_normalized_timespec(&wall_to_monotonic,
                -xtime.tv_sec, -xtime.tv_nsec);
 
-       if (hpet_enable() >= 0) {
+       if ((hpet_enable() >= 0) && hpet_use_timer) {
                printk("Using HPET for base-timer\n");
        }
 
diff -urN linux/arch/i386/kernel/time_hpet.c linux/arch/i386/kernel/time_hpet.c
--- linux/arch/i386/kernel/time_hpet.c  2005/03/18 17:36:48     1.9
+++ linux/arch/i386/kernel/time_hpet.c  2005/05/19 12:08:08     1.10
@@ -26,6 +26,7 @@
 static unsigned long hpet_period;      /* fsecs / HPET clock */
 unsigned long hpet_tick;               /* hpet clks count per tick */
 unsigned long hpet_address;            /* hpet memory map physical address */
+int hpet_use_timer;
 
 static int use_hpet;           /* can be used for runtime check of hpet */
 static int boot_hpet_disable;  /* boottime override for HPET timer */
@@ -73,27 +74,30 @@
        hpet_writel(0, HPET_COUNTER);
        hpet_writel(0, HPET_COUNTER + 4);
 
-       /*
-        * Set up timer 0, as periodic with first interrupt to happen at
-        * hpet_tick, and period also hpet_tick.
-        */
-       cfg = hpet_readl(HPET_T0_CFG);
-       cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
-              HPET_TN_SETVAL | HPET_TN_32BIT;
-       hpet_writel(cfg, HPET_T0_CFG);
-
-       /*
-        * The first write after writing TN_SETVAL to the config register sets
-        * the counter value, the second write sets the threshold.
-        */
-       hpet_writel(tick, HPET_T0_CMP);
-       hpet_writel(tick, HPET_T0_CMP);
+       if (hpet_use_timer) {
+               /*
+                * Set up timer 0, as periodic with first interrupt to happen at
+                * hpet_tick, and period also hpet_tick.
+                */
+               cfg = hpet_readl(HPET_T0_CFG);
+               cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
+                      HPET_TN_SETVAL | HPET_TN_32BIT;
+               hpet_writel(cfg, HPET_T0_CFG);
 
+               /*
+                * The first write after writing TN_SETVAL to the config 
register sets
+                * the counter value, the second write sets the threshold.
+                */
+               hpet_writel(tick, HPET_T0_CMP);
+               hpet_writel(tick, HPET_T0_CMP);
+       }
        /*
         * Go!
         */
        cfg = hpet_readl(HPET_CFG);
-       cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY;
+       if (hpet_use_timer)
+               cfg |= HPET_CFG_LEGACY;
+       cfg |= HPET_CFG_ENABLE;
        hpet_writel(cfg, HPET_CFG);
 
        return 0;
@@ -128,12 +132,11 @@
         * However, we can do with one timer otherwise using the
         * the single HPET timer for system time.
         */
-       if (
 #ifdef CONFIG_HPET_EMULATE_RTC
-               !(id & HPET_ID_NUMBER) ||
-#endif
-           !(id & HPET_ID_LEGSUP))
+       if (!(id & HPET_ID_NUMBER))
                return -1;
+#endif
+
 
        hpet_period = hpet_readl(HPET_PERIOD);
        if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD))
@@ -152,6 +155,8 @@
        if (hpet_tick_rem > (hpet_period >> 1))
                hpet_tick++; /* rounding the result */
 
+       hpet_use_timer = id & HPET_ID_LEGSUP;
+
        if (hpet_timer_stop_set_go(hpet_tick))
                return -1;
 
@@ -202,7 +207,8 @@
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
-       wait_timer_tick = wait_hpet_tick;
+       if (hpet_use_timer)
+               wait_timer_tick = wait_hpet_tick;
 #endif
        return 0;
 }
diff -urN linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- linux/arch/i386/kernel/traps.c      2005/04/08 18:57:53     1.102
+++ linux/arch/i386/kernel/traps.c      2005/05/19 12:08:08     1.103
@@ -451,6 +451,7 @@
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
 
 fastcall void do_general_protection(struct pt_regs * regs, long error_code)
 {
@@ -642,16 +643,15 @@
 }
 
 #ifdef CONFIG_KPROBES
-fastcall int do_int3(struct pt_regs *regs, long error_code)
+fastcall void do_int3(struct pt_regs *regs, long error_code)
 {
        if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
                        == NOTIFY_STOP)
-               return 1;
+               return;
        /* This is an interrupt gate, because kprobes wants interrupts
        disabled.  Normal trap handlers don't. */
        restore_interrupts(regs);
        do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
-       return 0;
 }
 #endif
 
diff -urN linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c
--- linux/arch/i386/kernel/vm86.c       2005/03/18 17:36:48     1.48
+++ linux/arch/i386/kernel/vm86.c       2005/05/19 12:08:08     1.49
@@ -222,7 +222,7 @@
                        goto out;
                case VM86_PLUS_INSTALL_CHECK:
                        /* NOTE: on old vm86 stuff this will return the error
-                          from verify_area(), because the subfunction is
+                          from access_ok(), because the subfunction is
                           interpreted as (invalid) address to vm86_struct.
                           So the installation check works.
                         */
@@ -294,8 +294,8 @@
  */
        info->regs32->eax = 0;
        tsk->thread.saved_esp0 = tsk->thread.esp0;
-       asm volatile("movl %%fs,%0":"=m" (tsk->thread.saved_fs));
-       asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs));
+       asm volatile("mov %%fs,%0":"=m" (tsk->thread.saved_fs));
+       asm volatile("mov %%gs,%0":"=m" (tsk->thread.saved_gs));
 
        tss = &per_cpu(init_tss, get_cpu());
        tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
@@ -717,12 +717,12 @@
        irqbits |= irq_bit;
        if (vm86_irqs[intno].sig)
                send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1);
-       spin_unlock_irqrestore(&irqbits_lock, flags);
        /*
         * IRQ will be re-enabled when user asks for the irq (whether
         * polling or as a result of the signal)
         */
-       disable_irq(intno);
+       disable_irq_nosync(intno);
+       spin_unlock_irqrestore(&irqbits_lock, flags);
        return IRQ_HANDLED;
 
 out:
@@ -754,17 +754,20 @@
 {
        int bit;
        unsigned long flags;
+       int ret = 0;
        
        if (invalid_vm86_irq(irqnumber)) return 0;
        if (vm86_irqs[irqnumber].tsk != current) return 0;
        spin_lock_irqsave(&irqbits_lock, flags);        
        bit = irqbits & (1 << irqnumber);
        irqbits &= ~bit;
+       if (bit) {
+               enable_irq(irqnumber);
+               ret = 1;
+       }
+
        spin_unlock_irqrestore(&irqbits_lock, flags);   
-       if (!bit)
-               return 0;
-       enable_irq(irqnumber);
-       return 1;
+       return ret;
 }
 
 
diff -urN linux/arch/i386/kernel/acpi/boot.c linux/arch/i386/kernel/acpi/boot.c
--- linux/arch/i386/kernel/acpi/boot.c  2005/04/29 11:15:01     1.24
+++ linux/arch/i386/kernel/acpi/boot.c  2005/05/19 12:08:08     1.25
@@ -650,7 +650,7 @@
         */
        rsdp_phys = acpi_scan_rsdp (0, 0x400);
        if (!rsdp_phys)
-               rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF);
+               rsdp_phys = acpi_scan_rsdp (0xE0000, 0x20000);
 
        return rsdp_phys;
 }
diff -urN linux/arch/i386/kernel/cpu/amd.c linux/arch/i386/kernel/cpu/amd.c
--- linux/arch/i386/kernel/cpu/amd.c    2005/04/29 11:15:01     1.14
+++ linux/arch/i386/kernel/cpu/amd.c    2005/05/19 12:08:08     1.15
@@ -24,7 +24,7 @@
 
 static void __init init_amd(struct cpuinfo_x86 *c)
 {
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_SMP
        int cpu = c == &boot_cpu_data ? 0 : c - cpu_data;
 #endif
        u32 l, h;
@@ -198,7 +198,7 @@
                        c->x86_num_cores = 1;
        }
 
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_SMP
        /*
         * On a AMD dual core setup the lower bits of the APIC id
         * distingush the cores.  Assumes number of cores is a power
diff -urN linux/arch/i386/kernel/cpu/proc.c linux/arch/i386/kernel/cpu/proc.c
--- linux/arch/i386/kernel/cpu/proc.c   2005/04/29 11:15:01     1.17
+++ linux/arch/i386/kernel/cpu/proc.c   2005/05/19 12:08:08     1.18
@@ -25,7 +25,7 @@
                "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
 
                /* AMD-defined */
-               "pni", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
                NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
diff -urN linux/arch/i386/kernel/cpu/mtrr/cyrix.c 
linux/arch/i386/kernel/cpu/mtrr/cyrix.c
--- linux/arch/i386/kernel/cpu/mtrr/cyrix.c     2005/03/18 17:36:49     1.5
+++ linux/arch/i386/kernel/cpu/mtrr/cyrix.c     2005/05/19 12:08:09     1.6
@@ -218,12 +218,12 @@
        mtrr_type type;
 } arr_state_t;
 
-static arr_state_t arr_state[8] __initdata = {
+static arr_state_t arr_state[8] __devinitdata = {
        {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
        {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
 };
 
-static unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char ccr_state[7] __devinitdata = { 0, 0, 0, 0, 0, 0, 0 };
 
 static void cyrix_set_all(void)
 {
diff -urN linux/arch/i386/kernel/cpu/mtrr/generic.c 
linux/arch/i386/kernel/cpu/mtrr/generic.c
--- linux/arch/i386/kernel/cpu/mtrr/generic.c   2005/04/29 11:15:01     1.13
+++ linux/arch/i386/kernel/cpu/mtrr/generic.c   2005/05/19 12:08:09     1.14
@@ -124,8 +124,8 @@
        return -ENOSPC;
 }
 
-void generic_get_mtrr(unsigned int reg, unsigned long *base,
-                     unsigned int *size, mtrr_type * type)
+static void generic_get_mtrr(unsigned int reg, unsigned long *base,
+                            unsigned int *size, mtrr_type * type)
 {
        unsigned int mask_lo, mask_hi, base_lo, base_hi;
 
diff -urN linux/arch/i386/kernel/cpu/mtrr/main.c 
linux/arch/i386/kernel/cpu/mtrr/main.c
--- linux/arch/i386/kernel/cpu/mtrr/main.c      2005/04/29 11:15:01     1.14
+++ linux/arch/i386/kernel/cpu/mtrr/main.c      2005/05/19 12:08:09     1.15
@@ -72,17 +72,21 @@
 static int have_wrcomb(void)
 {
        struct pci_dev *dev;
+       u8 rev;
        
        if ((dev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) != NULL) {
-               /* ServerWorks LE chipsets have problems with write-combining 
+               /* ServerWorks LE chipsets < rev 6 have problems with 
write-combining
                   Don't allow it and leave room for other chipsets to be 
tagged */
                if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
                    dev->device == PCI_DEVICE_ID_SERVERWORKS_LE) {
-                       printk(KERN_INFO "mtrr: Serverworks LE detected. 
Write-combining disabled.\n");
-                       pci_dev_put(dev);
-                       return 0;
+                       pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
+                       if (rev <= 5) {
+                               printk(KERN_INFO "mtrr: Serverworks LE rev < 6 
detected. Write-combining disabled.\n");
+                               pci_dev_put(dev);
+                               return 0;
+                       }
                }
-               /* Intel 450NX errata # 23. Non ascending cachline evictions to
+               /* Intel 450NX errata # 23. Non ascending cacheline evictions to
                   write combining memory may resulting in data corruption */
                if (dev->vendor == PCI_VENDOR_ID_INTEL &&
                    dev->device == PCI_DEVICE_ID_INTEL_82451NX) {
diff -urN linux/arch/i386/kernel/timers/timer_hpet.c 
linux/arch/i386/kernel/timers/timer_hpet.c
--- linux/arch/i386/kernel/timers/timer_hpet.c  2005/03/18 17:36:49     1.6
+++ linux/arch/i386/kernel/timers/timer_hpet.c  2005/05/19 12:08:09     1.7
@@ -79,7 +79,7 @@
 
        eax = hpet_readl(HPET_COUNTER);
        eax -= hpet_last;       /* hpet delta */
-
+       eax = min(hpet_tick, eax);
        /*
          * Time offset = (hpet delta) * ( usecs per HPET clock )
         *             = (hpet delta) * ( usecs per tick / HPET clocks per tick)
@@ -105,9 +105,12 @@
        last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
        rdtsc(last_tsc_low, last_tsc_high);
 
-       offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
-       if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) {
-               int lost_ticks = (offset - hpet_last) / hpet_tick;
+       if (hpet_use_timer)
+               offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
+       else
+               offset = hpet_readl(HPET_COUNTER);
+       if (unlikely(((offset - hpet_last) >= (2*hpet_tick)) && (hpet_last != 
0))) {
+               int lost_ticks = ((offset - hpet_last) / hpet_tick) - 1;
                jiffies_64 += lost_ticks;
        }
        hpet_last = offset;
diff -urN linux/arch/i386/kernel/timers/timer_tsc.c 
linux/arch/i386/kernel/timers/timer_tsc.c
--- linux/arch/i386/kernel/timers/timer_tsc.c   2004/11/15 11:49:16     1.27
+++ linux/arch/i386/kernel/timers/timer_tsc.c   2005/05/19 12:08:09     1.28
@@ -477,7 +477,7 @@
        if (cpu_has_tsc) {
                unsigned long tsc_quotient;
 #ifdef CONFIG_HPET_TIMER
-               if (is_hpet_enabled()){
+               if (is_hpet_enabled() && hpet_use_timer) {
                        unsigned long result, remain;
                        printk("Using TSC for gettimeofday\n");
                        tsc_quotient = calibrate_tsc_hpet(NULL);
diff -urN linux/arch/i386/oprofile/nmi_timer_int.c 
linux/arch/i386/oprofile/nmi_timer_int.c
--- linux/arch/i386/oprofile/nmi_timer_int.c    2005/01/13 14:05:25     1.3
+++ linux/arch/i386/oprofile/nmi_timer_int.c    2005/05/19 12:08:09     1.4
@@ -36,7 +36,7 @@
 {
        enable_timer_nmi_watchdog();
        unset_nmi_callback();
-       synchronize_kernel();
+       synchronize_sched();  /* Allow already-started NMIs to complete. */
 }
 
 
diff -urN linux/arch/i386/pci/irq.c linux/arch/i386/pci/irq.c
--- linux/arch/i386/pci/irq.c   2005/04/29 11:15:01     1.24
+++ linux/arch/i386/pci/irq.c   2005/05/19 12:08:09     1.25
@@ -495,6 +495,8 @@
                case PCI_DEVICE_ID_INTEL_ICH6_1:
                case PCI_DEVICE_ID_INTEL_ICH7_0:
                case PCI_DEVICE_ID_INTEL_ICH7_1:
+               case PCI_DEVICE_ID_INTEL_ICH7_30:
+               case PCI_DEVICE_ID_INTEL_ICH7_31:
                case PCI_DEVICE_ID_INTEL_ESB2_0:
                        r->name = "PIIX/ICH";
                        r->get = pirq_piix_get;
diff -urN linux/arch/ia64/Kconfig linux/arch/ia64/Kconfig
--- linux/arch/ia64/Kconfig     2005/04/08 18:57:54     1.40
+++ linux/arch/ia64/Kconfig     2005/05/19 12:08:09     1.41
@@ -46,6 +46,10 @@
        bool
        default y
 
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+       bool
+       default y
+
 choice
        prompt "System type"
        default IA64_GENERIC
@@ -217,6 +221,16 @@
          If you are compiling a kernel that will run under SGI's IA-64
          simulator (Medusa) then say Y, otherwise say N.
 
+config IA64_SGI_SN_XP
+       tristate "Support communication between SGI SSIs"
+       depends on MSPEC
+       help
+         An SGI machine can be divided into multiple Single System
+         Images which act independently of each other and have
+         hardware based memory protection from the others.  Enabling
+         this feature will allow for direct communication between SSIs
+         based on a network adapter and DMA messaging.
+
 config FORCE_MAX_ZONEORDER
        int
        default "18"
@@ -261,6 +275,15 @@
          can be controlled through /sys/devices/system/cpu/cpu#.
          Say N if you want to disable CPU hotplug.
 
+config SCHED_SMT
+       bool "SMT scheduler support"
+       depends on SMP
+       default off
+       help
+         Improves the CPU scheduler's decision making when dealing with
+         Intel IA64 chips with MultiThreading at a cost of slightly increased
+         overhead in some places. If unsure say N here.
+
 config PREEMPT
        bool "Preemptible Kernel"
         help
@@ -329,7 +352,7 @@
 
 config PM
        bool "Power Management support"
-       depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 || 
IA64_HP_ZX1_SWIOTLB
+       depends on !IA64_HP_SIM
        default y
        help
          "Power Management" means that parts of your computer are shut
diff -urN linux/arch/ia64/configs/sn2_defconfig 
linux/arch/ia64/configs/sn2_defconfig
--- linux/arch/ia64/configs/sn2_defconfig       2005/03/18 17:36:51     1.14
+++ linux/arch/ia64/configs/sn2_defconfig       2005/05/19 12:08:09     1.15
@@ -574,6 +574,8 @@
 # CONFIG_N_HDLC is not set
 # CONFIG_STALDRV is not set
 CONFIG_SGI_SNSC=y
+CONFIG_SGI_TIOCX=y
+CONFIG_SGI_MBCS=m
 
 #
 # Serial drivers
diff -urN linux/arch/ia64/configs/tiger_defconfig 
linux/arch/ia64/configs/tiger_defconfig
--- linux/arch/ia64/configs/tiger_defconfig     2005/02/07 02:54:32     1.3
+++ linux/arch/ia64/configs/tiger_defconfig     2005/05/19 12:08:09     1.4
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Sat Jan 22 11:17:02 2005
+# Linux kernel version: 2.6.12-rc3
+# Tue May  3 15:55:04 2005
 #
 
 #
@@ -10,6 +10,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -21,24 +22,27 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=20
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -85,6 +89,7 @@
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_HOTPLUG_CPU=y
+# CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
@@ -135,6 +140,7 @@
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCI Hotplug Support
@@ -152,10 +158,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # Device Drivers
 #
 
@@ -195,9 +197,10 @@
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -313,7 +316,6 @@
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
@@ -325,7 +327,6 @@
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 CONFIG_SCSI_QLOGIC_FC=y
 # CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
 CONFIG_SCSI_QLOGIC_1280=y
@@ -336,6 +337,7 @@
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -358,6 +360,7 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
 
 #
 # Fusion MPT device support
@@ -386,7 +389,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -446,7 +448,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -484,7 +485,6 @@
 # CONFIG_DGRS is not set
 CONFIG_EEPRO100=m
 CONFIG_E100=m
-# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -566,25 +566,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-CONFIG_GAMEPORT=m
-CONFIG_SOUND_GAMEPORT=m
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
-# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461X is not set
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -602,6 +583,24 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+CONFIG_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_VORTEX is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# CONFIG_GAMEPORT_CS461X is not set
+CONFIG_SOUND_GAMEPORT=m
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -615,6 +614,8 @@
 # CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
 # CONFIG_STALDRV is not set
 
 #
@@ -635,6 +636,7 @@
 #
 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
@@ -670,6 +672,12 @@
 # CONFIG_HPET_RTC_IRQ is not set
 CONFIG_HPET_MMAP=y
 CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -705,7 +713,6 @@
 #
 CONFIG_VGA_CONSOLE=y
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -715,6 +722,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -726,8 +735,6 @@
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -736,6 +743,8 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
 
@@ -751,12 +760,11 @@
 #
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
 # CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e 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
@@ -800,6 +808,7 @@
 # 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
@@ -824,6 +833,7 @@
 # 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_TEST is not set
 
 #
@@ -867,7 +877,12 @@
 CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
 CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
@@ -945,7 +960,7 @@
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
+CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -1042,8 +1057,10 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=20
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1077,6 +1094,7 @@
 # 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=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
diff -urN linux/arch/ia64/hp/common/sba_iommu.c 
linux/arch/ia64/hp/common/sba_iommu.c
--- linux/arch/ia64/hp/common/sba_iommu.c       2005/04/08 18:57:54     1.28
+++ linux/arch/ia64/hp/common/sba_iommu.c       2005/05/19 12:08:09     1.29
@@ -1,9 +1,9 @@
 /*
 **  IA64 System Bus Adapter (SBA) I/O MMU manager
 **
-**     (c) Copyright 2002-2004 Alex Williamson
+**     (c) Copyright 2002-2005 Alex Williamson
 **     (c) Copyright 2002-2003 Grant Grundler
-**     (c) Copyright 2002-2004 Hewlett-Packard Company
+**     (c) Copyright 2002-2005 Hewlett-Packard Company
 **
 **     Portions (c) 2000 Grant Grundler (from parisc I/O MMU code)
 **     Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code)
@@ -459,21 +459,32 @@
  * sba_search_bitmap - find free space in IO PDIR resource bitmap
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @bits_wanted: number of entries we need.
+ * @use_hint: use res_hint to indicate where to start looking
  *
  * Find consecutive free bits in resource bitmap.
  * Each bit represents one entry in the IO Pdir.
  * Cool perf optimization: search for log2(size) bits at a time.
  */
 static SBA_INLINE unsigned long
-sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
+sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted, int use_hint)
 {
-       unsigned long *res_ptr = ioc->res_hint;
+       unsigned long *res_ptr;
        unsigned long *res_end = (unsigned long *) 
&(ioc->res_map[ioc->res_size]);
-       unsigned long pide = ~0UL;
+       unsigned long flags, pide = ~0UL;
 
        ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) 
== 0);
        ASSERT(res_ptr < res_end);
 
+       spin_lock_irqsave(&ioc->res_lock, flags);
+
+       /* Allow caller to force a search through the entire resource space */
+       if (likely(use_hint)) {
+               res_ptr = ioc->res_hint;
+       } else {
+               res_ptr = (ulong *)ioc->res_map;
+               ioc->res_bitshift = 0;
+       }
+
        /*
         * N.B.  REO/Grande defect AR2305 can cause TLB fetch timeouts
         * if a TLB entry is purged while in use.  sba_mark_invalid()
@@ -570,10 +581,12 @@
        prefetch(ioc->res_map);
        ioc->res_hint = (unsigned long *) ioc->res_map;
        ioc->res_bitshift = 0;
+       spin_unlock_irqrestore(&ioc->res_lock, flags);
        return (pide);
 
 found_it:
        ioc->res_hint = res_ptr;
+       spin_unlock_irqrestore(&ioc->res_lock, flags);
        return (pide);
 }
 
@@ -594,36 +607,36 @@
        unsigned long itc_start;
 #endif
        unsigned long pide;
-       unsigned long flags;
 
        ASSERT(pages_needed);
        ASSERT(0 == (size & ~iovp_mask));
 
-       spin_lock_irqsave(&ioc->res_lock, flags);
-
 #ifdef PDIR_SEARCH_TIMING
        itc_start = ia64_get_itc();
 #endif
        /*
        ** "seek and ye shall find"...praying never hurts either...
        */
-       pide = sba_search_bitmap(ioc, pages_needed);
+       pide = sba_search_bitmap(ioc, pages_needed, 1);
        if (unlikely(pide >= (ioc->res_size << 3))) {
-               pide = sba_search_bitmap(ioc, pages_needed);
+               pide = sba_search_bitmap(ioc, pages_needed, 0);
                if (unlikely(pide >= (ioc->res_size << 3))) {
 #if DELAYED_RESOURCE_CNT > 0
+                       unsigned long flags;
+
                        /*
                        ** With delayed resource freeing, we can give this one 
more shot.  We're
                        ** getting close to being in trouble here, so do what 
we can to make this
                        ** one count.
                        */
-                       spin_lock(&ioc->saved_lock);
+                       spin_lock_irqsave(&ioc->saved_lock, flags);
                        if (ioc->saved_cnt > 0) {
                                struct sba_dma_pair *d;
                                int cnt = ioc->saved_cnt;
 
-                               d = &(ioc->saved[ioc->saved_cnt]);
+                               d = &(ioc->saved[ioc->saved_cnt - 1]);
 
+                               spin_lock(&ioc->res_lock);
                                while (cnt--) {
                                        sba_mark_invalid(ioc, d->iova, d->size);
                                        sba_free_range(ioc, d->iova, d->size);
@@ -631,10 +644,11 @@
                                }
                                ioc->saved_cnt = 0;
                                READ_REG(ioc->ioc_hpa+IOC_PCOM);        /* 
flush purges */
+                               spin_unlock(&ioc->res_lock);
                        }
-                       spin_unlock(&ioc->saved_lock);
+                       spin_unlock_irqrestore(&ioc->saved_lock, flags);
 
-                       pide = sba_search_bitmap(ioc, pages_needed);
+                       pide = sba_search_bitmap(ioc, pages_needed, 0);
                        if (unlikely(pide >= (ioc->res_size << 3)))
                                panic(__FILE__ ": I/O MMU @ %p is out of 
mapping resources\n",
                                      ioc->ioc_hpa);
@@ -664,8 +678,6 @@
                (uint) ((unsigned long) ioc->res_hint - (unsigned long) 
ioc->res_map),
                ioc->res_bitshift );
 
-       spin_unlock_irqrestore(&ioc->res_lock, flags);
-
        return (pide);
 }
 
@@ -950,6 +962,30 @@
        return SBA_IOVA(ioc, iovp, offset);
 }
 
+#ifdef ENABLE_MARK_CLEAN
+static SBA_INLINE void
+sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size)
+{
+       u32     iovp = (u32) SBA_IOVP(ioc,iova);
+       int     off = PDIR_INDEX(iovp);
+       void    *addr;
+
+       if (size <= iovp_size) {
+               addr = phys_to_virt(ioc->pdir_base[off] &
+                                   ~0xE000000000000FFFULL);
+               mark_clean(addr, size);
+       } else {
+               do {
+                       addr = phys_to_virt(ioc->pdir_base[off] &
+                                           ~0xE000000000000FFFULL);
+                       mark_clean(addr, min(size, iovp_size));
+                       off++;
+                       size -= iovp_size;
+               } while (size > 0);
+       }
+}
+#endif
+
 /**
  * sba_unmap_single - unmap one IOVA and free resources
  * @dev: instance of PCI owned by the driver that's asking.
@@ -995,6 +1031,10 @@
        size += offset;
        size = ROUNDUP(size, iovp_size);
 
+#ifdef ENABLE_MARK_CLEAN
+       if (dir == DMA_FROM_DEVICE)
+               sba_mark_clean(ioc, iova, size);
+#endif
 
 #if DELAYED_RESOURCE_CNT > 0
        spin_lock_irqsave(&ioc->saved_lock, flags);
@@ -1021,30 +1061,6 @@
        READ_REG(ioc->ioc_hpa+IOC_PCOM);        /* flush purges */
        spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif /* DELAYED_RESOURCE_CNT == 0 */
-#ifdef ENABLE_MARK_CLEAN
-       if (dir == DMA_FROM_DEVICE) {
-               u32 iovp = (u32) SBA_IOVP(ioc,iova);
-               int off = PDIR_INDEX(iovp);
-               void *addr;
-
-               if (size <= iovp_size) {
-                       addr = phys_to_virt(ioc->pdir_base[off] &
-                                           ~0xE000000000000FFFULL);
-                       mark_clean(addr, size);
-               } else {
-                       size_t byte_cnt = size;
-
-                       do {
-                               addr = phys_to_virt(ioc->pdir_base[off] &
-                                                   ~0xE000000000000FFFULL);
-                               mark_clean(addr, min(byte_cnt, iovp_size));
-                               off++;
-                               byte_cnt -= iovp_size;
-
-                          } while (byte_cnt > 0);
-               }
-       }
-#endif
 }
 
 
@@ -1928,43 +1944,17 @@
 static void __init
 sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
 {
-       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
-       union acpi_object *obj;
-       acpi_handle phandle;
        unsigned int node;
+       int pxm;
 
        ioc->node = MAX_NUMNODES;
 
-       /*
-        * Check for a _PXM on this node first.  We don't typically see
-        * one here, so we'll end up getting it from the parent.
-        */
-       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer))) {
-               if (ACPI_FAILURE(acpi_get_parent(handle, &phandle)))
-                       return;
-
-               /* Reset the acpi buffer */
-               buffer.length = ACPI_ALLOCATE_BUFFER;
-               buffer.pointer = NULL;
+       pxm = acpi_get_pxm(handle);
 
-               if (ACPI_FAILURE(acpi_evaluate_object(phandle, "_PXM", NULL,
-                                                     &buffer)))
-                       return;
-       }
-
-       if (!buffer.length || !buffer.pointer)
+       if (pxm < 0)
                return;
 
-       obj = buffer.pointer;
-
-       if (obj->type != ACPI_TYPE_INTEGER ||
-           obj->integer.value >= MAX_PXM_DOMAINS) {
-               acpi_os_free(buffer.pointer);
-               return;
-       }
-
-       node = pxm_to_nid_map[obj->integer.value];
-       acpi_os_free(buffer.pointer);
+       node = pxm_to_nid_map[pxm];
 
        if (node >= MAX_NUMNODES || !node_online(node))
                return;
diff -urN linux/arch/ia64/ia32/ia32_signal.c linux/arch/ia64/ia32/ia32_signal.c
--- linux/arch/ia64/ia32/ia32_signal.c  2005/03/18 17:36:51     1.28
+++ linux/arch/ia64/ia32/ia32_signal.c  2005/05/19 12:08:09     1.29
@@ -460,10 +460,9 @@
        sigset_t oldset, set;
 
        scr->scratch_unat = 0;  /* avoid leaking kernel bits to user level */
-       memset(&set, 0, sizeof(&set));
+       memset(&set, 0, sizeof(set));
 
-       if (memcpy(&set.sig, &sset->sig, sigsetsize))
-               return -EFAULT;
+       memcpy(&set.sig, &sset->sig, sigsetsize);
 
        sigdelsetmask(&set, ~_BLOCKABLE);
 
diff -urN linux/arch/ia64/kernel/acpi.c linux/arch/ia64/kernel/acpi.c
--- linux/arch/ia64/kernel/acpi.c       2005/04/08 18:57:54     1.48
+++ linux/arch/ia64/kernel/acpi.c       2005/05/19 12:08:09     1.49
@@ -779,7 +779,7 @@
        union acpi_object *obj;
        struct acpi_table_iosapic *iosapic;
        unsigned int gsi_base;
-       int node;
+       int pxm, node;
 
        /* Only care about objects w/ a method that returns the MADT */
        if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
@@ -805,29 +805,16 @@
        gsi_base = iosapic->global_irq_base;
 
        acpi_os_free(buffer.pointer);
-       buffer.length = ACPI_ALLOCATE_BUFFER;
-       buffer.pointer = NULL;
 
        /*
-        * OK, it's an IOSAPIC MADT entry, look for a _PXM method to tell
+        * OK, it's an IOSAPIC MADT entry, look for a _PXM value to tell
         * us which node to associate this with.
         */
-       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer)))
+       pxm = acpi_get_pxm(handle);
+       if (pxm < 0)
                return AE_OK;
 
-       if (!buffer.length || !buffer.pointer)
-               return AE_OK;
-
-       obj = buffer.pointer;
-
-       if (obj->type != ACPI_TYPE_INTEGER ||
-           obj->integer.value >= MAX_PXM_DOMAINS) {
-               acpi_os_free(buffer.pointer);
-               return AE_OK;
-       }
-
-       node = pxm_to_nid_map[obj->integer.value];
-       acpi_os_free(buffer.pointer);
+       node = pxm_to_nid_map[pxm];
 
        if (node >= MAX_NUMNODES || !node_online(node) ||
            cpus_empty(node_to_cpumask(node)))
diff -urN linux/arch/ia64/kernel/entry.S linux/arch/ia64/kernel/entry.S
--- linux/arch/ia64/kernel/entry.S      2005/02/13 20:16:16     1.55
+++ linux/arch/ia64/kernel/entry.S      2005/05/19 12:08:09     1.56
@@ -728,12 +728,8 @@
        mov f8=f0               // clear f8
        ;;
        ld8 r30=[r2],16         // M0|1 load cr.ifs
-       mov.m ar.ssd=r0         // M2 clear ar.ssd
-       cmp.eq p9,p0=r0,r0      // set p9 to indicate that we should restore 
cr.ifs
-       ;;
        ld8 r25=[r3],16         // M0|1 load ar.unat
-       mov.m ar.csd=r0         // M2 clear ar.csd
-       mov r22=r0              // clear r22
+       cmp.eq p9,p0=r0,r0      // set p9 to indicate that we should restore 
cr.ifs
        ;;
        ld8 r26=[r2],PT(B0)-PT(AR_PFS)  // M0|1 load ar.pfs
 (pKStk)        mov r22=psr             // M2 read PSR now that interrupts are 
disabled
@@ -756,11 +752,15 @@
        mov f7=f0               // clear f7
        ;;
        ld8.fill r12=[r2]       // restore r12 (sp)
+       mov.m ar.ssd=r0         // M2 clear ar.ssd
+       mov r22=r0              // clear r22
+
        ld8.fill r15=[r3]       // restore r15
+(pUStk) st1 [r14]=r17
        addl r3=THIS_CPU(ia64_phys_stacked_size_p8),r0
        ;;
-(pUStk)        ld4 r3=[r3]             // r3 = cpu_data->phys_stacked_size_p8
-(pUStk) st1 [r14]=r17
+(pUStk)        ld4 r17=[r3]            // r17 = cpu_data->phys_stacked_size_p8
+       mov.m ar.csd=r0         // M2 clear ar.csd
        mov b6=r18              // I0  restore b6
        ;;
        mov r14=r0              // clear r14
@@ -782,7 +782,7 @@
        st8.spill [r2]=r8       // store return value in slot for r8 and set 
unat bit
        .mem.offset 8,0
        st8.spill [r3]=r0       // clear error indication in slot for r10 and 
set unat bit
-END(ia64_ret_from_ia32_execve_syscall)
+END(ia64_ret_from_ia32_execve)
        // fall through
 #endif /* CONFIG_IA32_SUPPORT */
 GLOBAL_ENTRY(ia64_leave_kernel)
@@ -1417,7 +1417,7 @@
        data8 sys_msgrcv
        data8 sys_msgctl
        data8 sys_shmget
-       data8 ia64_shmat
+       data8 sys_shmat
        data8 sys_shmdt                         // 1115
        data8 sys_shmctl
        data8 sys_syslog
diff -urN linux/arch/ia64/kernel/fsys.S linux/arch/ia64/kernel/fsys.S
--- linux/arch/ia64/kernel/fsys.S       2005/02/07 02:54:32     1.18
+++ linux/arch/ia64/kernel/fsys.S       2005/05/19 12:08:09     1.19
@@ -611,8 +611,10 @@
        movl r2=ia64_ret_from_syscall
        ;;
        mov rp=r2                               // set the real return addr
-       tbit.z p8,p0=r3,TIF_SYSCALL_TRACE
+       and r3=_TIF_SYSCALL_TRACEAUDIT,r3
        ;;
+       cmp.eq p8,p0=r3,r0
+
 (p10)  br.cond.spnt.many ia64_ret_from_syscall // p10==true means out 
registers are more than 8
 (p8)   br.call.sptk.many b6=b6         // ignore this return addr
        br.cond.sptk ia64_trace_syscall
diff -urN linux/arch/ia64/kernel/head.S linux/arch/ia64/kernel/head.S
--- linux/arch/ia64/kernel/head.S       2005/02/13 20:16:16     1.31
+++ linux/arch/ia64/kernel/head.S       2005/05/19 12:08:09     1.32
@@ -15,6 +15,8 @@
  * Copyright (C) 1999 Don Dugger <Don.Dugger@intel.com>
  * Copyright (C) 2002 Fenghua Yu <fenghua.yu@intel.com>
  *   -Optimize __ia64_save_fpu() and __ia64_load_fpu() for Itanium 2.
+ * Copyright (C) 2004 Ashok Raj <ashok.raj@intel.com>
+ *   Support for CPU Hotplug
  */
 
 #include <linux/config.h>
@@ -29,6 +31,139 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
+#include <asm/mca_asm.h>
+
+#ifdef CONFIG_HOTPLUG_CPU
+#define SAL_PSR_BITS_TO_SET                            \
+       (IA64_PSR_AC | IA64_PSR_BN | IA64_PSR_MFH | IA64_PSR_MFL)
+
+#define SAVE_FROM_REG(src, ptr, dest)  \
+       mov dest=src;;                                          \
+       st8 [ptr]=dest,0x08
+
+#define RESTORE_REG(reg, ptr, _tmp)            \
+       ld8 _tmp=[ptr],0x08;;                           \
+       mov reg=_tmp
+
+#define SAVE_BREAK_REGS(ptr, _idx, _breg, _dest)\
+       mov ar.lc=IA64_NUM_DBG_REGS-1;;                         \
+       mov _idx=0;;                                                            
\
+1:                                                                             
                \
+       SAVE_FROM_REG(_breg[_idx], ptr, _dest);;        \
+       add _idx=1,_idx;;                                                       
\
+       br.cloop.sptk.many 1b
+
+#define RESTORE_BREAK_REGS(ptr, _idx, _breg, _tmp, _lbl)\
+       mov ar.lc=IA64_NUM_DBG_REGS-1;;                 \
+       mov _idx=0;;                                                    \
+_lbl:  RESTORE_REG(_breg[_idx], ptr, _tmp);;   \
+       add _idx=1, _idx;;                                              \
+       br.cloop.sptk.many _lbl
+
+#define SAVE_ONE_RR(num, _reg, _tmp) \
+       movl _tmp=(num<<61);;   \
+       mov _reg=rr[_tmp]
+
+#define SAVE_REGION_REGS(_tmp, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) \
+       SAVE_ONE_RR(0,_r0, _tmp);; \
+       SAVE_ONE_RR(1,_r1, _tmp);; \
+       SAVE_ONE_RR(2,_r2, _tmp);; \
+       SAVE_ONE_RR(3,_r3, _tmp);; \
+       SAVE_ONE_RR(4,_r4, _tmp);; \
+       SAVE_ONE_RR(5,_r5, _tmp);; \
+       SAVE_ONE_RR(6,_r6, _tmp);; \
+       SAVE_ONE_RR(7,_r7, _tmp);;
+
+#define STORE_REGION_REGS(ptr, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) \
+       st8 [ptr]=_r0, 8;; \
+       st8 [ptr]=_r1, 8;; \
+       st8 [ptr]=_r2, 8;; \
+       st8 [ptr]=_r3, 8;; \
+       st8 [ptr]=_r4, 8;; \
+       st8 [ptr]=_r5, 8;; \
+       st8 [ptr]=_r6, 8;; \
+       st8 [ptr]=_r7, 8;;
+
+#define RESTORE_REGION_REGS(ptr, _idx1, _idx2, _tmp) \
+       mov             ar.lc=0x08-1;;                                          
\
+       movl    _idx1=0x00;;                                            \
+RestRR:                                                                        
                \
+       dep.z   _idx2=_idx1,61,3;;                                      \
+       ld8             _tmp=[ptr],8;;                                          
\
+       mov             rr[_idx2]=_tmp;;                                        
\
+       srlz.d;;                                                                
        \
+       add             _idx1=1,_idx1;;                                         
\
+       br.cloop.sptk.few       RestRR
+
+#define SET_AREA_FOR_BOOTING_CPU(reg1, reg2) \
+       movl reg1=sal_state_for_booting_cpu;;   \
+       ld8 reg2=[reg1];;
+
+/*
+ * Adjust region registers saved before starting to save
+ * break regs and rest of the states that need to be preserved.
+ */
+#define SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(_reg1,_reg2,_pred)  \
+       SAVE_FROM_REG(b0,_reg1,_reg2);;                                         
\
+       SAVE_FROM_REG(b1,_reg1,_reg2);;                                         
\
+       SAVE_FROM_REG(b2,_reg1,_reg2);;                                         
\
+       SAVE_FROM_REG(b3,_reg1,_reg2);;                                         
\
+       SAVE_FROM_REG(b4,_reg1,_reg2);;                                         
\
+       SAVE_FROM_REG(b5,_reg1,_reg2);;                                         
\
+       st8 [_reg1]=r1,0x08;;                                                   
        \
+       st8 [_reg1]=r12,0x08;;                                                  
        \
+       st8 [_reg1]=r13,0x08;;                                                  
        \
+       SAVE_FROM_REG(ar.fpsr,_reg1,_reg2);;                            \
+       SAVE_FROM_REG(ar.pfs,_reg1,_reg2);;                                     
\
+       SAVE_FROM_REG(ar.rnat,_reg1,_reg2);;                            \
+       SAVE_FROM_REG(ar.unat,_reg1,_reg2);;                            \
+       SAVE_FROM_REG(ar.bspstore,_reg1,_reg2);;                        \
+       SAVE_FROM_REG(cr.dcr,_reg1,_reg2);;                                     
\
+       SAVE_FROM_REG(cr.iva,_reg1,_reg2);;                                     
\
+       SAVE_FROM_REG(cr.pta,_reg1,_reg2);;                                     
\
+       SAVE_FROM_REG(cr.itv,_reg1,_reg2);;                                     
\
+       SAVE_FROM_REG(cr.pmv,_reg1,_reg2);;                                     
\
+       SAVE_FROM_REG(cr.cmcv,_reg1,_reg2);;                            \
+       SAVE_FROM_REG(cr.lrr0,_reg1,_reg2);;                            \
+       SAVE_FROM_REG(cr.lrr1,_reg1,_reg2);;                            \
+       st8 [_reg1]=r4,0x08;;                                                   
        \
+       st8 [_reg1]=r5,0x08;;                                                   
        \
+       st8 [_reg1]=r6,0x08;;                                                   
        \
+       st8 [_reg1]=r7,0x08;;                                                   
        \
+       st8 [_reg1]=_pred,0x08;;                                                
        \
+       SAVE_FROM_REG(ar.lc, _reg1, _reg2);;                            \
+       stf.spill.nta [_reg1]=f2,16;;                                           
\
+       stf.spill.nta [_reg1]=f3,16;;                                           
\
+       stf.spill.nta [_reg1]=f4,16;;                                           
\
+       stf.spill.nta [_reg1]=f5,16;;                                           
\
+       stf.spill.nta [_reg1]=f16,16;;                                          
\
+       stf.spill.nta [_reg1]=f17,16;;                                          
\
+       stf.spill.nta [_reg1]=f18,16;;                                          
\
+       stf.spill.nta [_reg1]=f19,16;;                                          
\
+       stf.spill.nta [_reg1]=f20,16;;                                          
\
+       stf.spill.nta [_reg1]=f21,16;;                                          
\
+       stf.spill.nta [_reg1]=f22,16;;                                          
\
+       stf.spill.nta [_reg1]=f23,16;;                                          
\
+       stf.spill.nta [_reg1]=f24,16;;                                          
\
+       stf.spill.nta [_reg1]=f25,16;;                                          
\
+       stf.spill.nta [_reg1]=f26,16;;                                          
\
+       stf.spill.nta [_reg1]=f27,16;;                                          
\
+       stf.spill.nta [_reg1]=f28,16;;                                          
\
+       stf.spill.nta [_reg1]=f29,16;;                                          
\
+       stf.spill.nta [_reg1]=f30,16;;                                          
\
+       stf.spill.nta [_reg1]=f31,16;;
+
+#else
+#define SET_AREA_FOR_BOOTING_CPU(a1, a2)
+#define SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(a1,a2, a3)
+#define SAVE_REGION_REGS(_tmp, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7)
+#define STORE_REGION_REGS(ptr, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7)
+#endif
+
+#define SET_ONE_RR(num, pgsize, _tmp1, _tmp2, vhpt) \
+       movl _tmp1=(num << 61);;        \
+       mov _tmp2=((ia64_rid(IA64_REGION_ID_KERNEL, (num<<61)) << 8) | (pgsize 
<< 2) | vhpt);; \
+       mov rr[_tmp1]=_tmp2
 
        .section __special_page_section,"ax"
 
@@ -64,6 +199,12 @@
        srlz.i
        ;;
        /*
+        * Save the region registers, predicate before they get clobbered
+        */
+       SAVE_REGION_REGS(r2, r8,r9,r10,r11,r12,r13,r14,r15);
+       mov r25=pr;;
+
+       /*
         * Initialize kernel region registers:
         *      rr[0]: VHPT enabled, page size = PAGE_SHIFT
         *      rr[1]: VHPT enabled, page size = PAGE_SHIFT
@@ -76,32 +217,14 @@
         * We initialize all of them to prevent inadvertently assuming
         * something about the state of address translation early in boot.
         */
-       mov r6=((ia64_rid(IA64_REGION_ID_KERNEL, (0<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
-       movl r7=(0<<61)
-       mov r8=((ia64_rid(IA64_REGION_ID_KERNEL, (1<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
-       movl r9=(1<<61)
-       mov r10=((ia64_rid(IA64_REGION_ID_KERNEL, (2<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
-       movl r11=(2<<61)
-       mov r12=((ia64_rid(IA64_REGION_ID_KERNEL, (3<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
-       movl r13=(3<<61)
-       mov r14=((ia64_rid(IA64_REGION_ID_KERNEL, (4<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
-       movl r15=(4<<61)
-       mov r16=((ia64_rid(IA64_REGION_ID_KERNEL, (5<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
-       movl r17=(5<<61)
-       mov r18=((ia64_rid(IA64_REGION_ID_KERNEL, (6<<61)) << 8) | 
(IA64_GRANULE_SHIFT << 2))
-       movl r19=(6<<61)
-       mov r20=((ia64_rid(IA64_REGION_ID_KERNEL, (7<<61)) << 8) | 
(IA64_GRANULE_SHIFT << 2))
-       movl r21=(7<<61)
-       ;;
-       mov rr[r7]=r6
-       mov rr[r9]=r8
-       mov rr[r11]=r10
-       mov rr[r13]=r12
-       mov rr[r15]=r14
-       mov rr[r17]=r16
-       mov rr[r19]=r18
-       mov rr[r21]=r20
-       ;;
+       SET_ONE_RR(0, PAGE_SHIFT, r2, r16, 1);;
+       SET_ONE_RR(1, PAGE_SHIFT, r2, r16, 1);;
+       SET_ONE_RR(2, PAGE_SHIFT, r2, r16, 1);;
+       SET_ONE_RR(3, PAGE_SHIFT, r2, r16, 1);;
+       SET_ONE_RR(4, PAGE_SHIFT, r2, r16, 1);;
+       SET_ONE_RR(5, PAGE_SHIFT, r2, r16, 1);;
+       SET_ONE_RR(6, IA64_GRANULE_SHIFT, r2, r16, 0);;
+       SET_ONE_RR(7, IA64_GRANULE_SHIFT, r2, r16, 0);;
        /*
         * Now pin mappings into the TLB for kernel text and data
         */
@@ -142,6 +265,12 @@
        ;;
 1:     // now we are in virtual mode
 
+       SET_AREA_FOR_BOOTING_CPU(r2, r16);
+
+       STORE_REGION_REGS(r16, r8,r9,r10,r11,r12,r13,r14,r15);
+       SAL_TO_OS_BOOT_HANDOFF_STATE_SAVE(r16,r17,r25)
+       ;;
+
        // set IVT entry point---can't access I/O ports without it
        movl r3=ia64_ivt
        ;;
@@ -211,12 +340,13 @@
        mov IA64_KR(CURRENT_STACK)=r16
        mov r13=r2
        /*
-        * Reserve space at the top of the stack for "struct pt_regs".  Kernel 
threads
-        * don't store interesting values in that structure, but the space 
still needs
-        * to be there because time-critical stuff such as the context 
switching can
-        * be implemented more efficiently (for example, __switch_to()
+        * Reserve space at the top of the stack for "struct pt_regs".  Kernel
+        * threads don't store interesting values in that structure, but the 
space
+        * still needs to be there because time-critical stuff such as the 
context
+        * switching can be implemented more efficiently (for example, 
__switch_to()
         * always sets the psr.dfh bit of the task it is switching to).
         */
+
        addl r12=IA64_STK_OFFSET-IA64_PT_REGS_SIZE-16,r2
        addl r2=IA64_RBS_OFFSET,r2      // initialize the RSE
        mov ar.rsc=0            // place RSE in enforced lazy mode
@@ -993,4 +1123,98 @@
 
 #endif
 
+#ifdef CONFIG_HOTPLUG_CPU
+GLOBAL_ENTRY(ia64_jump_to_sal)
+       alloc r16=ar.pfs,1,0,0,0;;
+       rsm psr.i  | psr.ic
+{
+       flushrs
+       srlz.i
+}
+       tpa r25=in0
+       movl r18=tlb_purge_done;;
+       DATA_VA_TO_PA(r18);;
+       mov b1=r18      // Return location
+       movl r18=ia64_do_tlb_purge;;
+       DATA_VA_TO_PA(r18);;
+       mov b2=r18      // doing tlb_flush work
+       mov ar.rsc=0  // Put RSE  in enforced lazy, LE mode
+       movl r17=1f;;
+       DATA_VA_TO_PA(r17);;
+       mov cr.iip=r17
+       movl r16=SAL_PSR_BITS_TO_SET;;
+       mov cr.ipsr=r16
+       mov cr.ifs=r0;;
+       rfi;;
+1:
+       /*
+        * Invalidate all TLB data/inst
+        */
+       br.sptk.many b2;; // jump to tlb purge code
+
+tlb_purge_done:
+       RESTORE_REGION_REGS(r25, r17,r18,r19);;
+       RESTORE_REG(b0, r25, r17);;
+       RESTORE_REG(b1, r25, r17);;
+       RESTORE_REG(b2, r25, r17);;
+       RESTORE_REG(b3, r25, r17);;
+       RESTORE_REG(b4, r25, r17);;
+       RESTORE_REG(b5, r25, r17);;
+       ld8 r1=[r25],0x08;;
+       ld8 r12=[r25],0x08;;
+       ld8 r13=[r25],0x08;;
+       RESTORE_REG(ar.fpsr, r25, r17);;
+       RESTORE_REG(ar.pfs, r25, r17);;
+       RESTORE_REG(ar.rnat, r25, r17);;
+       RESTORE_REG(ar.unat, r25, r17);;
+       RESTORE_REG(ar.bspstore, r25, r17);;
+       RESTORE_REG(cr.dcr, r25, r17);;
+       RESTORE_REG(cr.iva, r25, r17);;
+       RESTORE_REG(cr.pta, r25, r17);;
+       RESTORE_REG(cr.itv, r25, r17);;
+       RESTORE_REG(cr.pmv, r25, r17);;
+       RESTORE_REG(cr.cmcv, r25, r17);;
+       RESTORE_REG(cr.lrr0, r25, r17);;
+       RESTORE_REG(cr.lrr1, r25, r17);;
+       ld8 r4=[r25],0x08;;
+       ld8 r5=[r25],0x08;;
+       ld8 r6=[r25],0x08;;
+       ld8 r7=[r25],0x08;;
+       ld8 r17=[r25],0x08;;
+       mov pr=r17,-1;;
+       RESTORE_REG(ar.lc, r25, r17);;
+       /*
+        * Now Restore floating point regs
+        */
+       ldf.fill.nta f2=[r25],16;;
+       ldf.fill.nta f3=[r25],16;;
+       ldf.fill.nta f4=[r25],16;;
+       ldf.fill.nta f5=[r25],16;;
+       ldf.fill.nta f16=[r25],16;;
+       ldf.fill.nta f17=[r25],16;;
+       ldf.fill.nta f18=[r25],16;;
+       ldf.fill.nta f19=[r25],16;;
+       ldf.fill.nta f20=[r25],16;;
+       ldf.fill.nta f21=[r25],16;;
+       ldf.fill.nta f22=[r25],16;;
+       ldf.fill.nta f23=[r25],16;;
+       ldf.fill.nta f24=[r25],16;;
+       ldf.fill.nta f25=[r25],16;;
+       ldf.fill.nta f26=[r25],16;;
+       ldf.fill.nta f27=[r25],16;;
+       ldf.fill.nta f28=[r25],16;;
+       ldf.fill.nta f29=[r25],16;;
+       ldf.fill.nta f30=[r25],16;;
+       ldf.fill.nta f31=[r25],16;;
+
+       /*
+        * Now that we have done all the register restores
+        * we are now ready for the big DIVE to SAL Land
+        */
+       ssm psr.ic;;
+       srlz.d;;
+       br.ret.sptk.many b0;;
+END(ia64_jump_to_sal)
+#endif /* CONFIG_HOTPLUG_CPU */
+
 #endif /* CONFIG_SMP */
diff -urN linux/arch/ia64/kernel/iosapic.c linux/arch/ia64/kernel/iosapic.c
--- linux/arch/ia64/kernel/iosapic.c    2005/04/08 18:57:54     1.36
+++ linux/arch/ia64/kernel/iosapic.c    2005/05/19 12:08:09     1.37
@@ -79,6 +79,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/string.h>
+#include <linux/bootmem.h>
 
 #include <asm/delay.h>
 #include <asm/hw_irq.h>
@@ -98,19 +99,30 @@
 #define DBG(fmt...)
 #endif
 
+#define NR_PREALLOCATE_RTE_ENTRIES     (PAGE_SIZE / sizeof(struct 
iosapic_rte_info))
+#define RTE_PREALLOCATED       (1)
+
 static DEFINE_SPINLOCK(iosapic_lock);
 
 /* These tables map IA-64 vectors to the IOSAPIC pin that generates this 
vector. */
 
-static struct iosapic_intr_info {
+struct iosapic_rte_info {
+       struct list_head rte_list;      /* node in list of RTEs sharing the 
same vector */
        char __iomem    *addr;          /* base address of IOSAPIC */
-       u32             low32;          /* current value of low word of 
Redirection table entry */
        unsigned int    gsi_base;       /* first GSI assigned to this IOSAPIC */
-       char            rte_index;      /* IOSAPIC RTE index (-1 => not an 
IOSAPIC interrupt) */
+       char            rte_index;      /* IOSAPIC RTE index */
+       int             refcnt;         /* reference counter */
+       unsigned int    flags;          /* flags */
+} ____cacheline_aligned;
+
+static struct iosapic_intr_info {
+       struct list_head rtes;          /* RTEs using this vector (empty => not 
an IOSAPIC interrupt) */
+       int             count;          /* # of RTEs that shares this vector */
+       u32             low32;          /* current value of low word of 
Redirection table entry */
+       unsigned int    dest;           /* destination CPU physical ID */
        unsigned char   dmode   : 3;    /* delivery mode (see iosapic.h) */
        unsigned char   polarity: 1;    /* interrupt polarity (see iosapic.h) */
        unsigned char   trigger : 1;    /* trigger mode (see iosapic.h) */
-       int             refcnt;         /* reference counter */
 } iosapic_intr_info[IA64_NUM_VECTORS];
 
 static struct iosapic {
@@ -126,6 +138,8 @@
 
 static unsigned char pcat_compat __initdata;   /* 8259 compatibility flag */
 
+static int iosapic_kmalloc_ok;
+static LIST_HEAD(free_rte_list);
 
 /*
  * Find an IOSAPIC associated with a GSI
@@ -147,10 +161,12 @@
 _gsi_to_vector (unsigned int gsi)
 {
        struct iosapic_intr_info *info;
+       struct iosapic_rte_info *rte;
 
        for (info = iosapic_intr_info; info < iosapic_intr_info + 
IA64_NUM_VECTORS; ++info)
-               if (info->gsi_base + info->rte_index == gsi)
-                       return info - iosapic_intr_info;
+               list_for_each_entry(rte, &info->rtes, rte_list)
+                       if (rte->gsi_base + rte->rte_index == gsi)
+                               return info - iosapic_intr_info;
        return -1;
 }
 
@@ -167,33 +183,52 @@
 int
 gsi_to_irq (unsigned int gsi)
 {
+       unsigned long flags;
+       int irq;
        /*
         * XXX fix me: this assumes an identity mapping vetween IA-64 vector 
and Linux irq
         * numbers...
         */
-       return _gsi_to_vector(gsi);
+       spin_lock_irqsave(&iosapic_lock, flags);
+       {
+               irq = _gsi_to_vector(gsi);
+       }
+       spin_unlock_irqrestore(&iosapic_lock, flags);
+
+       return irq;
+}
+
+static struct iosapic_rte_info *gsi_vector_to_rte(unsigned int gsi, unsigned 
int vec)
+{
+       struct iosapic_rte_info *rte;
+
+       list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list)
+               if (rte->gsi_base + rte->rte_index == gsi)
+                       return rte;
+       return NULL;
 }
 
 static void
-set_rte (unsigned int vector, unsigned int dest, int mask)
+set_rte (unsigned int gsi, unsigned int vector, unsigned int dest, int mask)
 {
        unsigned long pol, trigger, dmode;
        u32 low32, high32;
        char __iomem *addr;
        int rte_index;
        char redir;
+       struct iosapic_rte_info *rte;
 
        DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
 
-       rte_index = iosapic_intr_info[vector].rte_index;
-       if (rte_index < 0)
+       rte = gsi_vector_to_rte(gsi, vector);
+       if (!rte)
                return;         /* not an IOSAPIC interrupt */
 
-       addr    = iosapic_intr_info[vector].addr;
+       rte_index = rte->rte_index;
+       addr    = rte->addr;
        pol     = iosapic_intr_info[vector].polarity;
        trigger = iosapic_intr_info[vector].trigger;
        dmode   = iosapic_intr_info[vector].dmode;
-       vector &= (~IA64_IRQ_REDIRECTED);
 
        redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
 
@@ -221,6 +256,7 @@
        iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
        iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
        iosapic_intr_info[vector].low32 = low32;
+       iosapic_intr_info[vector].dest = dest;
 }
 
 static void
@@ -237,18 +273,20 @@
        u32 low32;
        int rte_index;
        ia64_vector vec = irq_to_vector(irq);
+       struct iosapic_rte_info *rte;
 
-       addr = iosapic_intr_info[vec].addr;
-       rte_index = iosapic_intr_info[vec].rte_index;
-
-       if (rte_index < 0)
+       if (list_empty(&iosapic_intr_info[vec].rtes))
                return;                 /* not an IOSAPIC interrupt! */
 
        spin_lock_irqsave(&iosapic_lock, flags);
        {
                /* set only the mask bit */
                low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK;
-               iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+               list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, 
rte_list) {
+                       addr = rte->addr;
+                       rte_index = rte->rte_index;
+                       iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+               }
        }
        spin_unlock_irqrestore(&iosapic_lock, flags);
 }
@@ -261,16 +299,19 @@
        u32 low32;
        int rte_index;
        ia64_vector vec = irq_to_vector(irq);
+       struct iosapic_rte_info *rte;
 
-       addr = iosapic_intr_info[vec].addr;
-       rte_index = iosapic_intr_info[vec].rte_index;
-       if (rte_index < 0)
+       if (list_empty(&iosapic_intr_info[vec].rtes))
                return;                 /* not an IOSAPIC interrupt! */
 
        spin_lock_irqsave(&iosapic_lock, flags);
        {
                low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK;
-               iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+               list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, 
rte_list) {
+                       addr = rte->addr;
+                       rte_index = rte->rte_index;
+                       iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+               }
        }
        spin_unlock_irqrestore(&iosapic_lock, flags);
 }
@@ -286,6 +327,7 @@
        char __iomem *addr;
        int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
        ia64_vector vec;
+       struct iosapic_rte_info *rte;
 
        irq &= (~IA64_IRQ_REDIRECTED);
        vec = irq_to_vector(irq);
@@ -295,10 +337,7 @@
 
        dest = cpu_physical_id(first_cpu(mask));
 
-       rte_index = iosapic_intr_info[vec].rte_index;
-       addr = iosapic_intr_info[vec].addr;
-
-       if (rte_index < 0)
+       if (list_empty(&iosapic_intr_info[vec].rtes))
                return;                 /* not an IOSAPIC interrupt */
 
        set_irq_affinity_info(irq, dest, redir);
@@ -318,8 +357,13 @@
                        low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
 
                iosapic_intr_info[vec].low32 = low32;
-               iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), high32);
-               iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+               iosapic_intr_info[vec].dest = dest;
+               list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, 
rte_list) {
+                       addr = rte->addr;
+                       rte_index = rte->rte_index;
+                       iosapic_write(addr, IOSAPIC_RTE_HIGH(rte_index), 
high32);
+                       iosapic_write(addr, IOSAPIC_RTE_LOW(rte_index), low32);
+               }
        }
        spin_unlock_irqrestore(&iosapic_lock, flags);
 #endif
@@ -340,9 +384,11 @@
 iosapic_end_level_irq (unsigned int irq)
 {
        ia64_vector vec = irq_to_vector(irq);
+       struct iosapic_rte_info *rte;
 
        move_irq(irq);
-       iosapic_eoi(iosapic_intr_info[vec].addr, vec);
+       list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list)
+               iosapic_eoi(rte->addr, vec);
 }
 
 #define iosapic_shutdown_level_irq     mask_irq
@@ -422,6 +468,34 @@
        return iosapic_read(addr, IOSAPIC_VERSION);
 }
 
+static int iosapic_find_sharable_vector (unsigned long trigger, unsigned long 
pol)
+{
+       int i, vector = -1, min_count = -1;
+       struct iosapic_intr_info *info;
+
+       /*
+        * shared vectors for edge-triggered interrupts are not
+        * supported yet
+        */
+       if (trigger == IOSAPIC_EDGE)
+               return -1;
+
+       for (i = IA64_FIRST_DEVICE_VECTOR; i <= IA64_LAST_DEVICE_VECTOR; i++) {
+               info = &iosapic_intr_info[i];
+               if (info->trigger == trigger && info->polarity == pol &&
+                   (info->dmode == IOSAPIC_FIXED || info->dmode == 
IOSAPIC_LOWEST_PRIORITY)) {
+                       if (min_count == -1 || info->count < min_count) {
+                               vector = i;
+                               min_count = info->count;
+                       }
+               }
+       }
+       if (vector < 0)
+               panic("%s: out of interrupt vectors!\n", __FUNCTION__);
+
+       return vector;
+}
+
 /*
  * if the given vector is already owned by other,
  *  assign a new vector for the other and make the vector available
@@ -431,19 +505,63 @@
 {
        int new_vector;
 
-       if (iosapic_intr_info[vector].rte_index >= 0 || 
iosapic_intr_info[vector].addr
-           || iosapic_intr_info[vector].gsi_base || 
iosapic_intr_info[vector].dmode
-           || iosapic_intr_info[vector].polarity || 
iosapic_intr_info[vector].trigger)
-       {
+       if (!list_empty(&iosapic_intr_info[vector].rtes)) {
                new_vector = assign_irq_vector(AUTO_ASSIGN);
                printk(KERN_INFO "Reassigning vector %d to %d\n", vector, 
new_vector);
                memcpy(&iosapic_intr_info[new_vector], 
&iosapic_intr_info[vector],
                       sizeof(struct iosapic_intr_info));
+               INIT_LIST_HEAD(&iosapic_intr_info[new_vector].rtes);
+               list_move(iosapic_intr_info[vector].rtes.next, 
&iosapic_intr_info[new_vector].rtes);
                memset(&iosapic_intr_info[vector], 0, sizeof(struct 
iosapic_intr_info));
-               iosapic_intr_info[vector].rte_index = -1;
+               iosapic_intr_info[vector].low32 = IOSAPIC_MASK;
+               INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
        }
 }
 
+static struct iosapic_rte_info *iosapic_alloc_rte (void)
+{
+       int i;
+       struct iosapic_rte_info *rte;
+       int preallocated = 0;
+
+       if (!iosapic_kmalloc_ok && list_empty(&free_rte_list)) {
+               rte = alloc_bootmem(sizeof(struct iosapic_rte_info) * 
NR_PREALLOCATE_RTE_ENTRIES);
+               if (!rte)
+                       return NULL;
+               for (i = 0; i < NR_PREALLOCATE_RTE_ENTRIES; i++, rte++)
+                       list_add(&rte->rte_list, &free_rte_list);
+       }
+
+       if (!list_empty(&free_rte_list)) {
+               rte = list_entry(free_rte_list.next, struct iosapic_rte_info, 
rte_list);
+               list_del(&rte->rte_list);
+               preallocated++;
+       } else {
+               rte = kmalloc(sizeof(struct iosapic_rte_info), GFP_ATOMIC);
+               if (!rte)
+                       return NULL;
+       }
+
+       memset(rte, 0, sizeof(struct iosapic_rte_info));
+       if (preallocated)
+               rte->flags |= RTE_PREALLOCATED;
+
+       return rte;
+}
+
+static void iosapic_free_rte (struct iosapic_rte_info *rte)
+{
+       if (rte->flags & RTE_PREALLOCATED)
+               list_add_tail(&rte->rte_list, &free_rte_list);
+       else
+               kfree(rte);
+}
+
+static inline int vector_is_shared (int vector)
+{
+       return (iosapic_intr_info[vector].count > 1);
+}
+
 static void
 register_intr (unsigned int gsi, int vector, unsigned char delivery,
               unsigned long polarity, unsigned long trigger)
@@ -454,6 +572,7 @@
        int index;
        unsigned long gsi_base;
        void __iomem *iosapic_address;
+       struct iosapic_rte_info *rte;
 
        index = find_iosapic(gsi);
        if (index < 0) {
@@ -464,14 +583,33 @@
        iosapic_address = iosapic_lists[index].addr;
        gsi_base = iosapic_lists[index].gsi_base;
 
-       rte_index = gsi - gsi_base;
-       iosapic_intr_info[vector].rte_index = rte_index;
+       rte = gsi_vector_to_rte(gsi, vector);
+       if (!rte) {
+               rte = iosapic_alloc_rte();
+               if (!rte) {
+                       printk(KERN_WARNING "%s: cannot allocate memory\n", 
__FUNCTION__);
+                       return;
+               }
+
+               rte_index = gsi - gsi_base;
+               rte->rte_index  = rte_index;
+               rte->addr       = iosapic_address;
+               rte->gsi_base   = gsi_base;
+               rte->refcnt++;
+               list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes);
+               iosapic_intr_info[vector].count++;
+       }
+       else if (vector_is_shared(vector)) {
+               struct iosapic_intr_info *info = &iosapic_intr_info[vector];
+               if (info->trigger != trigger || info->polarity != polarity) {
+                       printk (KERN_WARNING "%s: cannot override the 
interrupt\n", __FUNCTION__);
+                       return;
+               }
+       }
+
        iosapic_intr_info[vector].polarity = polarity;
        iosapic_intr_info[vector].dmode    = delivery;
-       iosapic_intr_info[vector].addr     = iosapic_address;
-       iosapic_intr_info[vector].gsi_base = gsi_base;
        iosapic_intr_info[vector].trigger  = trigger;
-       iosapic_intr_info[vector].refcnt++;
 
        if (trigger == IOSAPIC_EDGE)
                irq_type = &irq_type_iosapic_edge;
@@ -494,6 +632,13 @@
        static int cpu = -1;
 
        /*
+        * In case of vector shared by multiple RTEs, all RTEs that
+        * share the vector need to use the same destination CPU.
+        */
+       if (!list_empty(&iosapic_intr_info[vector].rtes))
+               return iosapic_intr_info[vector].dest;
+
+       /*
         * If the platform supports redirection via XTP, let it
         * distribute interrupts.
         */
@@ -565,10 +710,12 @@
 iosapic_register_intr (unsigned int gsi,
                       unsigned long polarity, unsigned long trigger)
 {
-       int vector;
+       int vector, mask = 1;
        unsigned int dest;
        unsigned long flags;
-
+       struct iosapic_rte_info *rte;
+       u32 low32;
+again:
        /*
         * If this GSI has already been registered (i.e., it's a
         * shared interrupt, or we lost a race to register it),
@@ -578,19 +725,45 @@
        {
                vector = gsi_to_vector(gsi);
                if (vector > 0) {
-                       iosapic_intr_info[vector].refcnt++;
+                       rte = gsi_vector_to_rte(gsi, vector);
+                       rte->refcnt++;
                        spin_unlock_irqrestore(&iosapic_lock, flags);
                        return vector;
                }
+       }
+       spin_unlock_irqrestore(&iosapic_lock, flags);
+
+       /* If vector is running out, we try to find a sharable vector */
+       vector = assign_irq_vector_nopanic(AUTO_ASSIGN);
+       if (vector < 0)
+               vector = iosapic_find_sharable_vector(trigger, polarity);
+
+       spin_lock_irqsave(&irq_descp(vector)->lock, flags);
+       spin_lock(&iosapic_lock);
+       {
+               if (gsi_to_vector(gsi) > 0) {
+                       if (list_empty(&iosapic_intr_info[vector].rtes))
+                               free_irq_vector(vector);
+                       spin_unlock(&iosapic_lock);
+                       spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
+                       goto again;
+               }
 
-               vector = assign_irq_vector(AUTO_ASSIGN);
                dest = get_target_cpu(gsi, vector);
                register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
-                       polarity, trigger);
+                             polarity, trigger);
 
-               set_rte(vector, dest, 1);
+               /*
+                * If the vector is shared and already unmasked for
+                * other interrupt sources, don't mask it.
+                */
+               low32 = iosapic_intr_info[vector].low32;
+               if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK))
+                       mask = 0;
+               set_rte(gsi, vector, dest, mask);
        }
-       spin_unlock_irqrestore(&iosapic_lock, flags);
+       spin_unlock(&iosapic_lock);
+       spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);
 
        printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
               gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
@@ -607,8 +780,10 @@
        unsigned long flags;
        int irq, vector;
        irq_desc_t *idesc;
-       int rte_index;
+       u32 low32;
        unsigned long trigger, polarity;
+       unsigned int dest;
+       struct iosapic_rte_info *rte;
 
        /*
         * If the irq associated with the gsi is not found,
@@ -627,54 +802,56 @@
        spin_lock_irqsave(&idesc->lock, flags);
        spin_lock(&iosapic_lock);
        {
-               rte_index = iosapic_intr_info[vector].rte_index;
-               if (rte_index < 0) {
-                       spin_unlock(&iosapic_lock);
-                       spin_unlock_irqrestore(&idesc->lock, flags);
+               if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) {
                        printk(KERN_ERR "iosapic_unregister_intr(%u) 
unbalanced\n", gsi);
                        WARN_ON(1);
-                       return;
+                       goto out;
                }
 
-               if (--iosapic_intr_info[vector].refcnt > 0) {
-                       spin_unlock(&iosapic_lock);
-                       spin_unlock_irqrestore(&idesc->lock, flags);
-                       return;
-               }
+               if (--rte->refcnt > 0)
+                       goto out;
 
-               /*
-                * If interrupt handlers still exist on the irq
-                * associated with the gsi, don't unregister the
-                * interrupt.
-                */
-               if (idesc->action) {
-                       iosapic_intr_info[vector].refcnt++;
-                       spin_unlock(&iosapic_lock);
-                       spin_unlock_irqrestore(&idesc->lock, flags);
-                       printk(KERN_WARNING "Cannot unregister GSI. IRQ %u is 
still in use.\n", irq);
-                       return;
-               }
+               /* Mask the interrupt */
+               low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK;
+               iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), 
low32);
+
+               /* Remove the rte entry from the list */
+               list_del(&rte->rte_list);
+               iosapic_intr_info[vector].count--;
+               iosapic_free_rte(rte);
 
-               /* Clear the interrupt controller descriptor. */
-               idesc->handler = &no_irq_type;
-
-               trigger  = iosapic_intr_info[vector].trigger;
+               trigger  = iosapic_intr_info[vector].trigger;
                polarity = iosapic_intr_info[vector].polarity;
+               dest     = iosapic_intr_info[vector].dest;
+               printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d 
unregistered\n",
+                      gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
+                      (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+                      cpu_logical_id(dest), dest, vector);
+
+               if (list_empty(&iosapic_intr_info[vector].rtes)) {
+                       /* Sanity check */
+                       BUG_ON(iosapic_intr_info[vector].count);
+
+                       /* Clear the interrupt controller descriptor */
+                       idesc->handler = &no_irq_type;
+
+                       /* Clear the interrupt information */
+                       memset(&iosapic_intr_info[vector], 0, sizeof(struct 
iosapic_intr_info));
+                       iosapic_intr_info[vector].low32 |= IOSAPIC_MASK;
+                       INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);
+
+                       if (idesc->action) {
+                               printk(KERN_ERR "interrupt handlers still exist 
on IRQ %u\n", irq);
+                               WARN_ON(1);
+                       }
 
-               /* Clear the interrupt information. */
-               memset(&iosapic_intr_info[vector], 0, sizeof(struct 
iosapic_intr_info));
-               iosapic_intr_info[vector].rte_index = -1;       /* mark as 
unused */
+                       /* Free the interrupt vector */
+                       free_irq_vector(vector);
+               }
        }
+ out:
        spin_unlock(&iosapic_lock);
        spin_unlock_irqrestore(&idesc->lock, flags);
-
-       /* Free the interrupt vector */
-       free_irq_vector(vector);
-
-       printk(KERN_INFO "GSI %u (%s, %s) -> vector %d unregisterd.\n",
-              gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
-              (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
-              vector);
 }
 #endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
 
@@ -724,7 +901,7 @@
               (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
               cpu_logical_id(dest), dest, vector);
 
-       set_rte(vector, dest, mask);
+       set_rte(gsi, vector, dest, mask);
        return vector;
 }
 
@@ -750,7 +927,7 @@
            polarity == IOSAPIC_POL_HIGH ? "high" : "low",
            cpu_logical_id(dest), dest, vector);
 
-       set_rte(vector, dest, 1);
+       set_rte(gsi, vector, dest, 1);
 }
 
 void __init
@@ -758,8 +935,10 @@
 {
        int vector;
 
-       for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
-               iosapic_intr_info[vector].rte_index = -1;       /* mark as 
unused */
+       for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) {
+               iosapic_intr_info[vector].low32 = IOSAPIC_MASK;
+               INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);        /* mark 
as unused */
+       }
 
        pcat_compat = system_pcat_compat;
        if (pcat_compat) {
@@ -825,3 +1004,10 @@
        return;
 }
 #endif
+
+static int __init iosapic_enable_kmalloc (void)
+{
+       iosapic_kmalloc_ok = 1;
+       return 0;
+}
+core_initcall (iosapic_enable_kmalloc);
diff -urN linux/arch/ia64/kernel/irq_ia64.c linux/arch/ia64/kernel/irq_ia64.c
--- linux/arch/ia64/kernel/irq_ia64.c   2005/02/07 02:54:32     1.26
+++ linux/arch/ia64/kernel/irq_ia64.c   2005/05/19 12:08:09     1.27
@@ -63,20 +63,30 @@
 static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
 
 int
-assign_irq_vector (int irq)
+assign_irq_vector_nopanic (int irq)
 {
        int pos, vector;
  again:
        pos = find_first_zero_bit(ia64_vector_mask, IA64_NUM_DEVICE_VECTORS);
        vector = IA64_FIRST_DEVICE_VECTOR + pos;
        if (vector > IA64_LAST_DEVICE_VECTOR)
-               /* XXX could look for sharable vectors instead of panic'ing... 
*/
-               panic("assign_irq_vector: out of interrupt vectors!");
+               return -1;
        if (test_and_set_bit(pos, ia64_vector_mask))
                goto again;
        return vector;
 }
 
+int
+assign_irq_vector (int irq)
+{
+       int vector = assign_irq_vector_nopanic(irq);
+
+       if (vector < 0)
+               panic("assign_irq_vector: out of interrupt vectors!");
+
+       return vector;
+}
+
 void
 free_irq_vector (int vector)
 {
diff -urN linux/arch/ia64/kernel/mca_asm.S linux/arch/ia64/kernel/mca_asm.S
--- linux/arch/ia64/kernel/mca_asm.S    2005/02/13 20:16:16     1.18
+++ linux/arch/ia64/kernel/mca_asm.S    2005/05/19 12:08:09     1.19
@@ -110,46 +110,19 @@
        .global ia64_os_mca_dispatch_end
        .global ia64_sal_to_os_handoff_state
        .global ia64_os_to_sal_handoff_state
+       .global ia64_do_tlb_purge
 
        .text
        .align 16
 
-ia64_os_mca_dispatch:
-
-       // Serialize all MCA processing
-       mov     r3=1;;
-       LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;
-ia64_os_mca_spin:
-       xchg8   r4=[r2],r3;;
-       cmp.ne  p6,p0=r4,r0
-(p6)   br ia64_os_mca_spin
-
-       // Save the SAL to OS MCA handoff state as defined
-       // by SAL SPEC 3.0
-       // NOTE : The order in which the state gets saved
-       //        is dependent on the way the C-structure
-       //        for ia64_mca_sal_to_os_state_t has been
-       //        defined in include/asm/mca.h
-       SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
-       ;;
-
-       // LOG PROCESSOR STATE INFO FROM HERE ON..
-begin_os_mca_dump:
-       br      ia64_os_mca_proc_state_dump;;
-
-ia64_os_mca_done_dump:
-
-       LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56)
-       ;;
-       ld8 r18=[r16]           // Get processor state parameter on existing 
PALE_CHECK.
-       ;;
-       tbit.nz p6,p7=r18,60
-(p7)   br.spnt done_tlb_purge_and_reload
-
-       // The following code purges TC and TR entries. Then reload all TC 
entries.
-       // Purge percpu data TC entries.
-begin_tlb_purge_and_reload:
+/*
+ * Just the TLB purge part is moved to a separate function
+ * so we can re-use the code for cpu hotplug code as well
+ * Caller should now setup b1, so we can branch once the
+ * tlb flush is complete.
+ */
 
+ia64_do_tlb_purge:
 #define O(member)      IA64_CPUINFO_##member##_OFFSET
 
        GET_THIS_PADDR(r2, cpu_info)    // load phys addr of cpu_info into r2
@@ -230,6 +203,51 @@
        ;;
        srlz.i
        ;;
+       // Now branch away to caller.
+       br.sptk.many b1
+       ;;
+
+ia64_os_mca_dispatch:
+
+       // Serialize all MCA processing
+       mov     r3=1;;
+       LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;
+ia64_os_mca_spin:
+       xchg8   r4=[r2],r3;;
+       cmp.ne  p6,p0=r4,r0
+(p6)   br ia64_os_mca_spin
+
+       // Save the SAL to OS MCA handoff state as defined
+       // by SAL SPEC 3.0
+       // NOTE : The order in which the state gets saved
+       //        is dependent on the way the C-structure
+       //        for ia64_mca_sal_to_os_state_t has been
+       //        defined in include/asm/mca.h
+       SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
+       ;;
+
+       // LOG PROCESSOR STATE INFO FROM HERE ON..
+begin_os_mca_dump:
+       br      ia64_os_mca_proc_state_dump;;
+
+ia64_os_mca_done_dump:
+
+       LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56)
+       ;;
+       ld8 r18=[r16]           // Get processor state parameter on existing 
PALE_CHECK.
+       ;;
+       tbit.nz p6,p7=r18,60
+(p7)   br.spnt done_tlb_purge_and_reload
+
+       // The following code purges TC and TR entries. Then reload all TC 
entries.
+       // Purge percpu data TC entries.
+begin_tlb_purge_and_reload:
+       movl r18=ia64_reload_tr;;
+       LOAD_PHYSICAL(p0,r18,ia64_reload_tr);;
+       mov b1=r18;;
+       br.sptk.many ia64_do_tlb_purge;;
+
+ia64_reload_tr:
        // Finally reload the TR registers.
        // 1. Reload DTR/ITR registers for kernel.
        mov r18=KERNEL_TR_PAGE_SHIFT<<2
diff -urN linux/arch/ia64/kernel/mca_drv.c linux/arch/ia64/kernel/mca_drv.c
--- linux/arch/ia64/kernel/mca_drv.c    2005/02/07 02:54:32     1.3
+++ linux/arch/ia64/kernel/mca_drv.c    2005/05/19 12:08:09     1.4
@@ -132,8 +132,7 @@
        spin_unlock(&mca_bh_lock);
 
        /* This process is about to be killed itself */
-       force_sig(SIGKILL, current);
-       schedule();
+       do_exit(SIGKILL);
 }
 
 /**
@@ -439,6 +438,7 @@
                        psr2 = (struct ia64_psr *)&pmsa->pmsa_ipsr;
                        psr2->cpl = 0;
                        psr2->ri  = 0;
+                       psr2->i  = 0;
 
                        return 1;
                }
diff -urN linux/arch/ia64/kernel/mca_drv_asm.S 
linux/arch/ia64/kernel/mca_drv_asm.S
--- linux/arch/ia64/kernel/mca_drv_asm.S        2004/10/12 14:36:32     1.1
+++ linux/arch/ia64/kernel/mca_drv_asm.S        2005/05/19 12:08:09     1.2
@@ -10,6 +10,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/processor.h>
+#include <asm/ptrace.h>
 
 GLOBAL_ENTRY(mca_handler_bhhook)
        invala                                          // clear RSE ?
@@ -20,12 +21,21 @@
        ;;                                              
        alloc           r16=ar.pfs,0,2,1,0              // make a new frame
        ;;
+       mov             ar.rsc=0
+       ;;
        mov             r13=IA64_KR(CURRENT)            // current task pointer
        ;;
-       adds            r12=IA64_TASK_THREAD_KSP_OFFSET,r13
+       mov             r2=r13
+       ;;
+       addl            r22=IA64_RBS_OFFSET,r2
+       ;;
+       mov             ar.bspstore=r22
        ;;
-       ld8             r12=[r12]                       // stack pointer
+       addl            sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2
        ;;
+       adds            r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
+       ;;
+       st1             [r2]=r0                         // clear 
current->thread.on_ustack flag
        mov             loc0=r16
        movl            loc1=mca_handler_bh             // recovery C function
        ;;
@@ -34,7 +44,9 @@
        ;;
        mov             loc1=rp
        ;;
-       br.call.sptk.many    rp=b6                      // not return ...
+       ssm             psr.i
+       ;;
+       br.call.sptk.many    rp=b6                      // does not return ...
        ;;
        mov             ar.pfs=loc0
        mov             rp=loc1
diff -urN linux/arch/ia64/kernel/perfmon.c linux/arch/ia64/kernel/perfmon.c
--- linux/arch/ia64/kernel/perfmon.c    2005/02/13 20:16:16     1.50
+++ linux/arch/ia64/kernel/perfmon.c    2005/05/19 12:08:09     1.51
@@ -480,14 +480,6 @@
 #define PFM_CMD_ARG_MANY       -1 /* cannot be zero */
 
 typedef struct {
-       int     debug;          /* turn on/off debugging via syslog */
-       int     debug_ovfl;     /* turn on/off debug printk in overflow handler 
*/
-       int     fastctxsw;      /* turn on/off fast (unsecure) ctxsw */
-       int     expert_mode;    /* turn on/off value checking */
-       int     debug_pfm_read;
-} pfm_sysctl_t;
-
-typedef struct {
        unsigned long pfm_spurious_ovfl_intr_count;     /* keep track of 
spurious ovfl interrupts */
        unsigned long pfm_replay_ovfl_intr_count;       /* keep track of 
replayed ovfl interrupts */
        unsigned long pfm_ovfl_intr_count;              /* keep track of ovfl 
interrupts */
@@ -514,8 +506,8 @@
 static pmu_config_t            *pmu_conf;
 
 /* sysctl() controls */
-static pfm_sysctl_t pfm_sysctl;
-int pfm_debug_var;
+pfm_sysctl_t pfm_sysctl;
+EXPORT_SYMBOL(pfm_sysctl);
 
 static ctl_table pfm_ctl_table[]={
        {1, "debug", &pfm_sysctl.debug, sizeof(int), 0666, NULL, 
&proc_dointvec, NULL,},
@@ -1273,6 +1265,8 @@
 }
 EXPORT_SYMBOL(pfm_unregister_buffer_fmt);
 
+extern void update_pal_halt_status(int);
+
 static int
 pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu)
 {
@@ -1319,6 +1313,11 @@
                is_syswide,
                cpu));
 
+       /*
+        * disable default_idle() to go to PAL_HALT
+        */
+       update_pal_halt_status(0);
+
        UNLOCK_PFS(flags);
 
        return 0;
@@ -1374,6 +1373,12 @@
                is_syswide,
                cpu));
 
+       /*
+        * if possible, enable default_idle() to go into PAL_HALT
+        */
+       if (pfm_sessions.pfs_task_sessions == 0 && 
pfm_sessions.pfs_sys_sessions == 0)
+               update_pal_halt_status(1);
+
        UNLOCK_PFS(flags);
 
        return 0;
@@ -1576,7 +1581,7 @@
                goto abort_locked;
        }
 
-       DPRINT(("[%d] fd=%d type=%d\n", current->pid, 
msg->pfm_gen_msg.msg_ctx_fd, msg->pfm_gen_msg.msg_type));
+       DPRINT(("fd=%d type=%d\n", msg->pfm_gen_msg.msg_ctx_fd, 
msg->pfm_gen_msg.msg_type));
 
        ret = -EFAULT;
        if(copy_to_user(buf, msg, sizeof(pfm_msg_t)) == 0) ret = 
sizeof(pfm_msg_t);
@@ -3695,8 +3700,6 @@
 
        pfm_sysctl.debug = m == 0 ? 0 : 1;
 
-       pfm_debug_var = pfm_sysctl.debug;
-
        printk(KERN_INFO "perfmon debugging %s (timing reset)\n", 
pfm_sysctl.debug ? "on" : "off");
 
        if (m == 0) {
@@ -4212,7 +4215,7 @@
                DPRINT(("cannot load to [%d], invalid ctx_state=%d\n",
                        req->load_pid,
                        ctx->ctx_state));
-               return -EINVAL;
+               return -EBUSY;
        }
 
        DPRINT(("load_pid [%d] using_dbreg=%d\n", req->load_pid, 
ctx->ctx_fl_using_dbreg));
@@ -4714,16 +4717,26 @@
        if (task == current || ctx->ctx_fl_system) return 0;
 
        /*
-        * if context is UNLOADED we are safe to go
+        * we are monitoring another thread
         */
-       if (state == PFM_CTX_UNLOADED) return 0;
-
-       /*
-        * no command can operate on a zombie context
-        */
-       if (state == PFM_CTX_ZOMBIE) {
-               DPRINT(("cmd %d state zombie cannot operate on context\n", 
cmd));
-               return -EINVAL;
+       switch(state) {
+               case PFM_CTX_UNLOADED:
+                       /*
+                        * if context is UNLOADED we are safe to go
+                        */
+                       return 0;
+               case PFM_CTX_ZOMBIE:
+                       /*
+                        * no command can operate on a zombie context
+                        */
+                       DPRINT(("cmd %d state zombie cannot operate on 
context\n", cmd));
+                       return -EINVAL;
+               case PFM_CTX_MASKED:
+                       /*
+                        * PMU state has been saved to software even though
+                        * the thread may still be running.
+                        */
+                       if (cmd != PFM_UNLOAD_CONTEXT) return 0;
        }
 
        /*
@@ -4996,13 +5009,21 @@
 }
 
 static int pfm_ovfl_notify_user(pfm_context_t *ctx, unsigned long ovfl_pmds);
-
+ /*
+  * pfm_handle_work() can be called with interrupts enabled
+  * (TIF_NEED_RESCHED) or disabled. The down_interruptible
+  * call may sleep, therefore we must re-enable interrupts
+  * to avoid deadlocks. It is safe to do so because this function
+  * is called ONLY when returning to user level (PUStk=1), in which case
+  * there is no risk of kernel stack overflow due to deep
+  * interrupt nesting.
+  */
 void
 pfm_handle_work(void)
 {
        pfm_context_t *ctx;
        struct pt_regs *regs;
-       unsigned long flags;
+       unsigned long flags, dummy_flags;
        unsigned long ovfl_regs;
        unsigned int reason;
        int ret;
@@ -5039,18 +5060,15 @@
        //if (CTX_OVFL_NOBLOCK(ctx)) goto skip_blocking;
        if (reason == PFM_TRAP_REASON_RESET) goto skip_blocking;
 
+       /*
+        * restore interrupt mask to what it was on entry.
+        * Could be enabled/diasbled.
+        */
        UNPROTECT_CTX(ctx, flags);
 
-        /*
-         * pfm_handle_work() is currently called with interrupts disabled.
-         * The down_interruptible call may sleep, therefore we
-         * must re-enable interrupts to avoid deadlocks. It is
-         * safe to do so because this function is called ONLY
-         * when returning to user level (PUStk=1), in which case
-         * there is no risk of kernel stack overflow due to deep
-         * interrupt nesting.
-         */
-       BUG_ON(flags & IA64_PSR_I);
+       /*
+        * force interrupt enable because of down_interruptible()
+        */
        local_irq_enable();
 
        DPRINT(("before block sleeping\n"));
@@ -5064,12 +5082,12 @@
        DPRINT(("after block sleeping ret=%d\n", ret));
 
        /*
-        * disable interrupts to restore state we had upon entering
-        * this function
+        * lock context and mask interrupts again
+        * We save flags into a dummy because we may have
+        * altered interrupts mask compared to entry in this
+        * function.
         */
-       local_irq_disable();
-
-       PROTECT_CTX(ctx, flags);
+       PROTECT_CTX(ctx, dummy_flags);
 
        /*
         * we need to read the ovfl_regs only after wake-up
@@ -5095,7 +5113,9 @@
        ctx->ctx_ovfl_regs[0] = 0UL;
 
 nothing_to_do:
-
+       /*
+        * restore flags as they were upon entry
+        */
        UNPROTECT_CTX(ctx, flags);
 }
 
diff -urN linux/arch/ia64/kernel/perfmon_default_smpl.c 
linux/arch/ia64/kernel/perfmon_default_smpl.c
--- linux/arch/ia64/kernel/perfmon_default_smpl.c       2004/03/11 16:46:42     
1.5
+++ linux/arch/ia64/kernel/perfmon_default_smpl.c       2005/05/19 12:08:09     
1.6
@@ -20,24 +20,17 @@
 MODULE_DESCRIPTION("perfmon default sampling format");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "debug");
-
-MODULE_PARM(debug_ovfl, "i");
-MODULE_PARM_DESC(debug_ovfl, "debug ovfl");
-
-
 #define DEFAULT_DEBUG 1
 
 #ifdef DEFAULT_DEBUG
 #define DPRINT(a) \
        do { \
-               if (unlikely(debug >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, 
__LINE__, smp_processor_id()); printk a; } \
+               if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d ", 
__FUNCTION__, __LINE__, smp_processor_id()); printk a; } \
        } while (0)
 
 #define DPRINT_ovfl(a) \
        do { \
-               if (unlikely(debug_ovfl >0)) { printk("%s.%d: CPU%d ", 
__FUNCTION__, __LINE__, smp_processor_id()); printk a; } \
+               if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) 
{ printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk 
a; } \
        } while (0)
 
 #else
@@ -45,8 +38,6 @@
 #define DPRINT_ovfl(a)
 #endif
 
-static int debug, debug_ovfl;
-
 static int
 default_validate(struct task_struct *task, unsigned int flags, int cpu, void 
*data)
 {
diff -urN linux/arch/ia64/kernel/process.c linux/arch/ia64/kernel/process.c
--- linux/arch/ia64/kernel/process.c    2005/02/07 02:54:32     1.46
+++ linux/arch/ia64/kernel/process.c    2005/05/19 12:08:09     1.47
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 1998-2003 Hewlett-Packard Co
  *     David Mosberger-Tang <davidm@hpl.hp.com>
+ * 04/11/17 Ashok Raj  <ashok.raj@intel.com> Added CPU Hotplug Support
  */
 #define __KERNEL_SYSCALLS__    /* see <asm/unistd.h> */
 #include <linux/config.h>
@@ -49,7 +50,7 @@
 #include "sigframe.h"
 
 void (*ia64_mark_idle)(int);
-static cpumask_t cpu_idle_map;
+static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
 
 unsigned long boot_option_idle_override = 0;
 EXPORT_SYMBOL(boot_option_idle_override);
@@ -172,7 +173,9 @@
                ia64_do_signal(oldset, scr, in_syscall);
 }
 
-static int pal_halt = 1;
+static int pal_halt        = 1;
+static int can_do_pal_halt = 1;
+
 static int __init nohalt_setup(char * str)
 {
        pal_halt = 0;
@@ -180,16 +183,20 @@
 }
 __setup("nohalt", nohalt_setup);
 
+void
+update_pal_halt_status(int status)
+{
+       can_do_pal_halt = pal_halt && status;
+}
+
 /*
  * We use this if we don't have any better idle routine..
  */
 void
 default_idle (void)
 {
-       unsigned long pmu_active = ia64_getreg(_IA64_REG_PSR) & (IA64_PSR_PP | 
IA64_PSR_UP);
-
        while (!need_resched())
-               if (pal_halt && !pmu_active)
+               if (can_do_pal_halt)
                        safe_halt();
                else
                        cpu_relax();
@@ -200,27 +207,20 @@
 static inline void play_dead(void)
 {
        extern void ia64_cpu_local_tick (void);
+       unsigned int this_cpu = smp_processor_id();
+
        /* Ack it */
        __get_cpu_var(cpu_state) = CPU_DEAD;
 
-       /* We shouldn't have to disable interrupts while dead, but
-        * some interrupts just don't seem to go away, and this makes
-        * it "work" for testing purposes. */
        max_xtp();
        local_irq_disable();
-       /* Death loop */
-       while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
-               cpu_relax();
-
+       idle_task_exit();
+       ia64_jump_to_sal(&sal_boot_rendez_state[this_cpu]);
        /*
-        * Enable timer interrupts from now on
-        * Not required if we put processor in SAL_BOOT_RENDEZ mode.
+        * The above is a point of no-return, the processor is
+        * expected to be in SAL loop now.
         */
-       local_flush_tlb_all();
-       cpu_set(smp_processor_id(), cpu_online_map);
-       wmb();
-       ia64_cpu_local_tick ();
-       local_irq_enable();
+       BUG();
 }
 #else
 static inline void play_dead(void)
@@ -229,20 +229,31 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-
 void cpu_idle_wait(void)
 {
-        int cpu;
-        cpumask_t map;
+       unsigned int cpu, this_cpu = get_cpu();
+       cpumask_t map;
+
+       set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+       put_cpu();
 
-        for_each_online_cpu(cpu)
-                cpu_set(cpu, cpu_idle_map);
+       cpus_clear(map);
+       for_each_online_cpu(cpu) {
+               per_cpu(cpu_idle_state, cpu) = 1;
+               cpu_set(cpu, map);
+       }
 
-        wmb();
-        do {
-                ssleep(1);
-                cpus_and(map, cpu_idle_map, cpu_online_map);
-        } while (!cpus_empty(map));
+       __get_cpu_var(cpu_idle_state) = 0;
+
+       wmb();
+       do {
+               ssleep(1);
+               for_each_online_cpu(cpu) {
+                       if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, 
cpu))
+                               cpu_clear(cpu, map);
+               }
+               cpus_and(map, map, cpu_online_map);
+       } while (!cpus_empty(map));
 }
 EXPORT_SYMBOL_GPL(cpu_idle_wait);
 
@@ -250,7 +261,6 @@
 cpu_idle (void)
 {
        void (*mark_idle)(int) = ia64_mark_idle;
-       int cpu = smp_processor_id();
 
        /* endless idle loop with no priority at all */
        while (1) {
@@ -261,12 +271,13 @@
                while (!need_resched()) {
                        void (*idle)(void);
 
+                       if (__get_cpu_var(cpu_idle_state))
+                               __get_cpu_var(cpu_idle_state) = 0;
+
+                       rmb();
                        if (mark_idle)
                                (*mark_idle)(1);
 
-                       if (cpu_isset(cpu, cpu_idle_map))
-                               cpu_clear(cpu, cpu_idle_map);
-                       rmb();
                        idle = pm_idle;
                        if (!idle)
                                idle = default_idle;
diff -urN linux/arch/ia64/kernel/ptrace.c linux/arch/ia64/kernel/ptrace.c
--- linux/arch/ia64/kernel/ptrace.c     2005/03/18 17:36:51     1.36
+++ linux/arch/ia64/kernel/ptrace.c     2005/05/19 12:08:09     1.37
@@ -17,6 +17,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
+#include <linux/signal.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -1481,7 +1482,7 @@
              case PTRACE_CONT:
                /* restart after signal. */
                ret = -EIO;
-               if (data > _NSIG)
+               if (!valid_signal(data))
                        goto out_tsk;
                if (request == PTRACE_SYSCALL)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -1520,7 +1521,7 @@
                /* let child execute for one instruction */
              case PTRACE_SINGLEBLOCK:
                ret = -EIO;
-               if (data > _NSIG)
+               if (!valid_signal(data))
                        goto out_tsk;
 
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -1595,20 +1596,25 @@
                     long arg4, long arg5, long arg6, long arg7,
                     struct pt_regs regs)
 {
-       long syscall;
+       if (test_thread_flag(TIF_SYSCALL_TRACE) 
+           && (current->ptrace & PT_PTRACED))
+               syscall_trace();
 
        if (unlikely(current->audit_context)) {
-               if (IS_IA32_PROCESS(&regs))
+               long syscall;
+               int arch;
+
+               if (IS_IA32_PROCESS(&regs)) {
                        syscall = regs.r1;
-               else
+                       arch = AUDIT_ARCH_I386;
+               } else {
                        syscall = regs.r15;
+                       arch = AUDIT_ARCH_IA64;
+               }
 
-               audit_syscall_entry(current, syscall, arg0, arg1, arg2, arg3);
+               audit_syscall_entry(current, arch, syscall, arg0, arg1, arg2, 
arg3);
        }
 
-       if (test_thread_flag(TIF_SYSCALL_TRACE)
-           && (current->ptrace & PT_PTRACED))
-               syscall_trace();
 }
 
 /* "asmlinkage" so the input arguments are preserved... */
@@ -1619,7 +1625,7 @@
                     struct pt_regs regs)
 {
        if (unlikely(current->audit_context))
-               audit_syscall_exit(current, regs.r8);
+               audit_syscall_exit(current, AUDITSC_RESULT(regs.r10), regs.r8);
 
        if (test_thread_flag(TIF_SYSCALL_TRACE)
            && (current->ptrace & PT_PTRACED))
diff -urN linux/arch/ia64/kernel/setup.c linux/arch/ia64/kernel/setup.c
--- linux/arch/ia64/kernel/setup.c      2005/04/08 18:57:54     1.48
+++ linux/arch/ia64/kernel/setup.c      2005/05/19 12:08:09     1.49
@@ -4,10 +4,15 @@
  * Copyright (C) 1998-2001, 2003-2004 Hewlett-Packard Co
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  *     Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 2000, Rohit Seth <rohit.seth@intel.com>
+ * Copyright (C) 2000, 2004 Intel Corp
+ *     Rohit Seth <rohit.seth@intel.com>
+ *     Suresh Siddha <suresh.b.siddha@intel.com>
+ *     Gordon Jin <gordon.jin@intel.com>
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
  *
+ * 12/26/04 S.Siddha, G.Jin, R.Seth
+ *                     Add multi-threading and multi-core detection
  * 11/12/01 D.Mosberger Convert get_cpuinfo() to seq_file based show_cpuinfo().
  * 04/04/00 D.Mosberger renamed cpu_initialized to cpu_online_map
  * 03/31/00 R.Seth     cpu_initialized and current->processor fixes
@@ -296,6 +301,34 @@
 #endif
 }
 
+#ifdef CONFIG_SMP
+static void
+check_for_logical_procs (void)
+{
+       pal_logical_to_physical_t info;
+       s64 status;
+
+       status = ia64_pal_logical_to_phys(0, &info);
+       if (status == -1) {
+               printk(KERN_INFO "No logical to physical processor mapping "
+                      "available\n");
+               return;
+       }
+       if (status) {
+               printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
+                      status);
+               return;
+       }
+       /*
+        * Total number of siblings that BSP has.  Though not all of them 
+        * may have booted successfully. The correct number of siblings 
+        * booted is in info.overview_num_log.
+        */
+       smp_num_siblings = info.overview_tpc;
+       smp_num_cpucores = info.overview_cpp;
+}
+#endif
+
 void __init
 setup_arch (char **cmdline_p)
 {
@@ -356,6 +389,19 @@
 
 #ifdef CONFIG_SMP
        cpu_physical_id(0) = hard_smp_processor_id();
+
+       cpu_set(0, cpu_sibling_map[0]);
+       cpu_set(0, cpu_core_map[0]);
+
+       check_for_logical_procs();
+       if (smp_num_cpucores > 1)
+               printk(KERN_INFO
+                      "cpu package is Multi-Core capable: number of 
cores=%d\n",
+                      smp_num_cpucores);
+       if (smp_num_siblings > 1)
+               printk(KERN_INFO
+                      "cpu package is Multi-Threading capable: number of 
siblings=%d\n",
+                      smp_num_siblings);
 #endif
 
        cpu_init();     /* initialize the bootstrap CPU */
@@ -459,12 +505,23 @@
                   "cpu regs   : %u\n"
                   "cpu MHz    : %lu.%06lu\n"
                   "itc MHz    : %lu.%06lu\n"
-                  "BogoMIPS   : %lu.%02lu\n\n",
+                  "BogoMIPS   : %lu.%02lu\n",
                   cpunum, c->vendor, family, c->model, c->revision, c->archrev,
                   features, c->ppn, c->number,
                   c->proc_freq / 1000000, c->proc_freq % 1000000,
                   c->itc_freq / 1000000, c->itc_freq % 1000000,
                   lpj*HZ/500000, (lpj*HZ/5000) % 100);
+#ifdef CONFIG_SMP
+       seq_printf(m, "siblings   : %u\n", c->num_log);
+       if (c->threads_per_core > 1 || c->cores_per_socket > 1)
+               seq_printf(m,
+                          "physical id: %u\n"
+                          "core id    : %u\n"
+                          "thread id  : %u\n",
+                          c->socket_id, c->core_id, c->thread_id);
+#endif
+       seq_printf(m,"\n");
+
        return 0;
 }
 
@@ -533,6 +590,14 @@
        memcpy(c->vendor, cpuid.field.vendor, 16);
 #ifdef CONFIG_SMP
        c->cpu = smp_processor_id();
+
+       /* below default values will be overwritten  by identify_siblings() 
+        * for Multi-Threading/Multi-Core capable cpu's
+        */
+       c->threads_per_core = c->cores_per_socket = c->num_log = 1;
+       c->socket_id = -1;
+
+       identify_siblings(c);
 #endif
        c->ppn = cpuid.field.ppn;
        c->number = cpuid.field.number;
diff -urN linux/arch/ia64/kernel/signal.c linux/arch/ia64/kernel/signal.c
--- linux/arch/ia64/kernel/signal.c     2005/02/13 20:16:16     1.38
+++ linux/arch/ia64/kernel/signal.c     2005/05/19 12:08:09     1.39
@@ -224,7 +224,8 @@
         * could be corrupted.
         */
        retval = (long) &ia64_leave_kernel;
-       if (test_thread_flag(TIF_SYSCALL_TRACE))
+       if (test_thread_flag(TIF_SYSCALL_TRACE)
+           || test_thread_flag(TIF_SYSCALL_AUDIT))
                /*
                 * strace expects to be notified after sigreturn returns even 
though the
                 * context to which we return may not be in the middle of a 
syscall.
diff -urN linux/arch/ia64/kernel/smpboot.c linux/arch/ia64/kernel/smpboot.c
--- linux/arch/ia64/kernel/smpboot.c    2005/03/18 17:36:51     1.39
+++ linux/arch/ia64/kernel/smpboot.c    2005/05/19 12:08:09     1.40
@@ -1,14 +1,25 @@
 /*
  * SMP boot-related support
  *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
+ * Copyright (C) 1998-2003, 2005 Hewlett-Packard Co
  *     David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2001, 2004-2005 Intel Corp
+ *     Rohit Seth <rohit.seth@intel.com>
+ *     Suresh Siddha <suresh.b.siddha@intel.com>
+ *     Gordon Jin <gordon.jin@intel.com>
+ *     Ashok Raj  <ashok.raj@intel.com>
  *
  * 01/05/16 Rohit Seth <rohit.seth@intel.com>  Moved SMP booting functions 
from smp.c to here.
  * 01/04/27 David Mosberger <davidm@hpl.hp.com>        Added ITC synching code.
  * 02/07/31 David Mosberger <davidm@hpl.hp.com>        Switch over to 
hotplug-CPU boot-sequence.
  *                                             smp_boot_cpus()/smp_commence() 
is replaced by
  *                                             
smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
+ * 04/06/21 Ashok Raj          <ashok.raj@intel.com> Added CPU Hotplug Support
+ * 04/12/26 Jin Gordon <gordon.jin@intel.com>
+ * 04/12/26 Rohit Seth <rohit.seth@intel.com>
+ *                                             Add multi-threading and 
multi-core detection
+ * 05/01/30 Suresh Siddha <suresh.b.siddha@intel.com>
+ *                                             Setup cpu_sibling_map and 
cpu_core_map
  */
 #include <linux/config.h>
 
@@ -58,6 +69,37 @@
 #define Dprintk(x...)
 #endif
 
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * Store all idle threads, this can be reused instead of creating
+ * a new thread. Also avoids complicated thread destroy functionality
+ * for idle threads.
+ */
+struct task_struct *idle_thread_array[NR_CPUS];
+
+/*
+ * Global array allocated for NR_CPUS at boot time
+ */
+struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
+
+/*
+ * start_ap in head.S uses this to store current booting cpu
+ * info.
+ */
+struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
+
+#define set_brendez_area(x) (sal_state_for_booting_cpu = 
&sal_boot_rendez_state[(x)]);
+
+#define get_idle_for_cpu(x)            (idle_thread_array[(x)])
+#define set_idle_for_cpu(x,p)  (idle_thread_array[(x)] = (p))
+
+#else
+
+#define get_idle_for_cpu(x)            (NULL)
+#define set_idle_for_cpu(x,p)
+#define set_brendez_area(x)
+#endif
+
 
 /*
  * ITC synchronization related stuff:
@@ -90,6 +132,11 @@
 cpumask_t cpu_possible_map;
 EXPORT_SYMBOL(cpu_possible_map);
 
+cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+int smp_num_siblings = 1;
+int smp_num_cpucores = 1;
+
 /* which logical CPU number maps to which CPU (physical APIC ID) */
 volatile int ia64_cpu_to_sapicid[NR_CPUS];
 EXPORT_SYMBOL(ia64_cpu_to_sapicid);
@@ -124,7 +171,8 @@
        local_irq_save(flags);
        {
                for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
-                       while (!go[MASTER]);
+                       while (!go[MASTER])
+                               cpu_relax();
                        go[MASTER] = 0;
                        go[SLAVE] = ia64_get_itc();
                }
@@ -147,7 +195,8 @@
        for (i = 0; i < NUM_ITERS; ++i) {
                t0 = ia64_get_itc();
                go[MASTER] = 1;
-               while (!(tm = go[SLAVE]));
+               while (!(tm = go[SLAVE]))
+                       cpu_relax();
                go[SLAVE] = 0;
                t1 = ia64_get_itc();
 
@@ -226,7 +275,8 @@
                return;
        }
 
-       while (go[MASTER]);     /* wait for master to be ready */
+       while (go[MASTER])
+               cpu_relax();    /* wait for master to be ready */
 
        spin_lock_irqsave(&itc_sync_lock, flags);
        {
@@ -345,7 +395,6 @@
 {
        /* Early console may use I/O ports */
        ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
-
        Dprintk("start_secondary: starting CPU 0x%x\n", 
hard_smp_processor_id());
        efi_map_pal_code();
        cpu_init();
@@ -384,6 +433,13 @@
                .done   = COMPLETION_INITIALIZER(c_idle.done),
        };
        DECLARE_WORK(work, do_fork_idle, &c_idle);
+
+       c_idle.idle = get_idle_for_cpu(cpu);
+       if (c_idle.idle) {
+               init_idle(c_idle.idle, cpu);
+               goto do_rest;
+       }
+
        /*
         * We can't use kernel_thread since we must avoid to reschedule the 
child.
         */
@@ -396,10 +452,15 @@
 
        if (IS_ERR(c_idle.idle))
                panic("failed fork for CPU %d", cpu);
+
+       set_idle_for_cpu(cpu, c_idle.idle);
+
+do_rest:
        task_for_booting_cpu = c_idle.idle;
 
        Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", 
ap_wakeup_vector, cpu, sapicid);
 
+       set_brendez_area(cpu);
        platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
 
        /*
@@ -552,19 +613,70 @@
        cpu_set(smp_processor_id(), cpu_callin_map);
 }
 
+/*
+ * mt_info[] is a temporary store for all info returned by
+ * PAL_LOGICAL_TO_PHYSICAL, to be copied into cpuinfo_ia64 when the
+ * specific cpu comes.
+ */
+static struct {
+       __u32   socket_id;
+       __u16   core_id;
+       __u16   thread_id;
+       __u16   proc_fixed_addr;
+       __u8    valid;
+}mt_info[NR_CPUS] __devinit;
+
 #ifdef CONFIG_HOTPLUG_CPU
-extern void fixup_irqs(void);
-/* must be called with cpucontrol mutex held */
-static int __devinit cpu_enable(unsigned int cpu)
+static inline void
+remove_from_mtinfo(int cpu)
 {
-       per_cpu(cpu_state,cpu) = CPU_UP_PREPARE;
-       wmb();
+       int i;
 
-       while (!cpu_online(cpu))
-               cpu_relax();
-       return 0;
+       for_each_cpu(i)
+               if (mt_info[i].valid &&  mt_info[i].socket_id ==
+                                               cpu_data(cpu)->socket_id)
+                       mt_info[i].valid = 0;
+}
+
+static inline void
+clear_cpu_sibling_map(int cpu)
+{
+       int i;
+
+       for_each_cpu_mask(i, cpu_sibling_map[cpu])
+               cpu_clear(cpu, cpu_sibling_map[i]);
+       for_each_cpu_mask(i, cpu_core_map[cpu])
+               cpu_clear(cpu, cpu_core_map[i]);
+
+       cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE;
+}
+
+static void
+remove_siblinginfo(int cpu)
+{
+       int last = 0;
+
+       if (cpu_data(cpu)->threads_per_core == 1 &&
+           cpu_data(cpu)->cores_per_socket == 1) {
+               cpu_clear(cpu, cpu_core_map[cpu]);
+               cpu_clear(cpu, cpu_sibling_map[cpu]);
+               return;
+       }
+
+       last = (cpus_weight(cpu_core_map[cpu]) == 1 ? 1 : 0);
+
+       /* remove it from all sibling map's */
+       clear_cpu_sibling_map(cpu);
+
+       /* if this cpu is the last in the core group, remove all its info 
+        * from mt_info structure
+        */
+       if (last)
+               remove_from_mtinfo(cpu);
 }
 
+extern void fixup_irqs(void);
+/* must be called with cpucontrol mutex held */
 int __cpu_disable(void)
 {
        int cpu = smp_processor_id();
@@ -575,9 +687,10 @@
        if (cpu == 0)
                return -EBUSY;
 
+       remove_siblinginfo(cpu);
        fixup_irqs();
        local_flush_tlb_all();
-       printk ("Disabled cpu %u\n", smp_processor_id());
+       cpu_clear(cpu, cpu_callin_map);
        return 0;
 }
 
@@ -589,12 +702,7 @@
                /* They ack this in play_dead by setting CPU_DEAD */
                if (per_cpu(cpu_state, cpu) == CPU_DEAD)
                {
-                       /*
-                        * TBD: Enable this when physical removal
-                        * or when we put the processor is put in
-                        * SAL_BOOT_RENDEZ mode
-                        * cpu_clear(cpu, cpu_callin_map);
-                        */
+                       printk ("CPU %d is now offline\n", cpu);
                        return;
                }
                msleep(100);
@@ -602,11 +710,6 @@
        printk(KERN_ERR "CPU %u didn't die...\n", cpu);
 }
 #else /* !CONFIG_HOTPLUG_CPU */
-static int __devinit cpu_enable(unsigned int cpu)
-{
-       return 0;
-}
-
 int __cpu_disable(void)
 {
        return -ENOSYS;
@@ -637,6 +740,23 @@
               (int)num_online_cpus(), bogosum/(500000/HZ), 
(bogosum/(5000/HZ))%100);
 }
 
+static inline void __devinit
+set_cpu_sibling_map(int cpu)
+{
+       int i;
+
+       for_each_online_cpu(i) {
+               if ((cpu_data(cpu)->socket_id == cpu_data(i)->socket_id)) {
+                       cpu_set(i, cpu_core_map[cpu]);
+                       cpu_set(cpu, cpu_core_map[i]);
+                       if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) {
+                               cpu_set(i, cpu_sibling_map[cpu]);
+                               cpu_set(cpu, cpu_sibling_map[i]);
+                       }
+               }
+       }
+}
+
 int __devinit
 __cpu_up (unsigned int cpu)
 {
@@ -648,21 +768,26 @@
                return -EINVAL;
 
        /*
-        * Already booted.. just enable and get outa idle lool
+        * Already booted cpu? not valid anymore since we dont
+        * do idle loop tightspin anymore.
         */
        if (cpu_isset(cpu, cpu_callin_map))
-       {
-               cpu_enable(cpu);
-               local_irq_enable();
-               while (!cpu_isset(cpu, cpu_online_map))
-                       mb();
-               return 0;
-       }
+               return -EINVAL;
+
        /* Processor goes to start_secondary(), sets online flag */
        ret = do_boot_cpu(sapicid, cpu);
        if (ret < 0)
                return ret;
 
+       if (cpu_data(cpu)->threads_per_core == 1 &&
+           cpu_data(cpu)->cores_per_socket == 1) {
+               cpu_set(cpu, cpu_sibling_map[cpu]);
+               cpu_set(cpu, cpu_core_map[cpu]);
+               return 0;
+       }
+
+       set_cpu_sibling_map(cpu);
+
        return 0;
 }
 
@@ -690,3 +815,106 @@
                       ia64_sal_strerror(sal_ret));
 }
 
+static inline int __devinit
+check_for_mtinfo_index(void)
+{
+       int i;
+       
+       for_each_cpu(i)
+               if (!mt_info[i].valid)
+                       return i;
+
+       return -1;
+}
+
+/*
+ * Search the mt_info to find out if this socket's cid/tid information is
+ * cached or not. If the socket exists, fill in the core_id and thread_id 
+ * in cpuinfo
+ */
+static int __devinit
+check_for_new_socket(__u16 logical_address, struct cpuinfo_ia64 *c)
+{
+       int i;
+       __u32 sid = c->socket_id;
+
+       for_each_cpu(i) {
+               if (mt_info[i].valid && mt_info[i].proc_fixed_addr == 
logical_address
+                   && mt_info[i].socket_id == sid) {
+                       c->core_id = mt_info[i].core_id;
+                       c->thread_id = mt_info[i].thread_id;
+                       return 1; /* not a new socket */
+               }
+       }
+       return 0;
+}
+
+/*
+ * identify_siblings(cpu) gets called from identify_cpu. This populates the 
+ * information related to logical execution units in per_cpu_data structure.
+ */
+void __devinit
+identify_siblings(struct cpuinfo_ia64 *c)
+{
+       s64 status;
+       u16 pltid;
+       u64 proc_fixed_addr;
+       int count, i;
+       pal_logical_to_physical_t info;
+
+       if (smp_num_cpucores == 1 && smp_num_siblings == 1)
+               return;
+
+       if ((status = ia64_pal_logical_to_phys(0, &info)) != 
PAL_STATUS_SUCCESS) {
+               printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
+                      status);
+               return;
+       }
+       if ((status = ia64_sal_physical_id_info(&pltid)) != PAL_STATUS_SUCCESS) 
{
+               printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status);
+               return;
+       }
+       if ((status = ia64_pal_fixed_addr(&proc_fixed_addr)) != 
PAL_STATUS_SUCCESS) {
+               printk(KERN_ERR "ia64_pal_fixed_addr failed with %ld\n", 
status);
+               return;
+       }
+
+       c->socket_id =  (pltid << 8) | info.overview_ppid;
+       c->cores_per_socket = info.overview_cpp;
+       c->threads_per_core = info.overview_tpc;
+       count = c->num_log = info.overview_num_log;
+
+       /* If the thread and core id information is already cached, then
+        * we will simply update cpu_info and return. Otherwise, we will
+        * do the PAL calls and cache core and thread id's of all the siblings.
+        */
+       if (check_for_new_socket(proc_fixed_addr, c))
+               return;
+
+       for (i = 0; i < count; i++) {
+               int index;
+
+               if (i && (status = ia64_pal_logical_to_phys(i, &info))
+                         != PAL_STATUS_SUCCESS) {
+                       printk(KERN_ERR "ia64_pal_logical_to_phys failed"
+                                       " with %ld\n", status);
+                       return;
+               }
+               if (info.log2_la == proc_fixed_addr) {
+                       c->core_id = info.log1_cid;
+                       c->thread_id = info.log1_tid;
+               }
+
+               index = check_for_mtinfo_index();
+               /* We will not do the mt_info caching optimization in this case.
+                */
+               if (index < 0)
+                       continue;
+
+               mt_info[index].valid = 1;
+               mt_info[index].socket_id = c->socket_id;
+               mt_info[index].core_id = info.log1_cid;
+               mt_info[index].thread_id = info.log1_tid;
+               mt_info[index].proc_fixed_addr = info.log2_la;
+       }
+}
diff -urN linux/arch/ia64/kernel/sys_ia64.c linux/arch/ia64/kernel/sys_ia64.c
--- linux/arch/ia64/kernel/sys_ia64.c   2005/02/13 20:16:16     1.31
+++ linux/arch/ia64/kernel/sys_ia64.c   2005/05/19 12:08:09     1.32
@@ -93,20 +93,6 @@
 }
 
 asmlinkage unsigned long
-ia64_shmat (int shmid, void __user *shmaddr, int shmflg)
-{
-       unsigned long raddr;
-       int retval;
-
-       retval = do_shmat(shmid, shmaddr, shmflg, &raddr);
-       if (retval < 0)
-               return retval;
-
-       force_successful_syscall_return();
-       return raddr;
-}
-
-asmlinkage unsigned long
 ia64_brk (unsigned long brk)
 {
        unsigned long rlim, retval, newbrk, oldbrk;
diff -urN linux/arch/ia64/kernel/unwind.c linux/arch/ia64/kernel/unwind.c
--- linux/arch/ia64/kernel/unwind.c     2005/02/07 02:54:32     1.32
+++ linux/arch/ia64/kernel/unwind.c     2005/05/19 12:08:09     1.33
@@ -1943,23 +1943,30 @@
 int
 unw_unwind_to_user (struct unw_frame_info *info)
 {
-       unsigned long ip, sp;
+       unsigned long ip, sp, pr = 0;
 
        while (unw_unwind(info) >= 0) {
-               if (unw_get_rp(info, &ip) < 0) {
-                       unw_get_ip(info, &ip);
-                       UNW_DPRINT(0, "unwind.%s: failed to read return pointer 
(ip=0x%lx)\n",
-                                  __FUNCTION__, ip);
-                       return -1;
-               }
                unw_get_sp(info, &sp);
-               if (sp >= (unsigned long)info->task + IA64_STK_OFFSET)
+               if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
+                   < IA64_PT_REGS_SIZE) {
+                       UNW_DPRINT(0, "unwind.%s: ran off the top of the kernel 
stack\n",
+                                  __FUNCTION__);
                        break;
-               if (ip < FIXADDR_USER_END)
+               }
+               if (unw_is_intr_frame(info) &&
+                   (pr & (1UL << PRED_USER_STACK)))
                        return 0;
+               if (unw_get_pr (info, &pr) < 0) {
+                       unw_get_rp(info, &ip);
+                       UNW_DPRINT(0, "unwind.%s: failed to read "
+                                  "predicate register (ip=0x%lx)\n",
+                               __FUNCTION__, ip);
+                       return -1;
+               }
        }
        unw_get_ip(info, &ip);
-       UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", 
__FUNCTION__, ip);
+       UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
+                  __FUNCTION__, ip);
        return -1;
 }
 EXPORT_SYMBOL(unw_unwind_to_user);
diff -urN linux/arch/ia64/lib/flush.S linux/arch/ia64/lib/flush.S
--- linux/arch/ia64/lib/flush.S 2001/06/13 17:27:41     1.4
+++ linux/arch/ia64/lib/flush.S 2005/05/19 12:08:10     1.5
@@ -1,8 +1,8 @@
 /*
  * Cache flushing routines.
  *
- * Copyright (C) 1999-2001 Hewlett-Packard Co
- * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001, 2005 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #include <asm/asmmacro.h>
 #include <asm/page.h>
@@ -26,7 +26,7 @@
 
        mov ar.lc=r8
        ;;
-.Loop: fc in0                          // issuable on M0 only
+.Loop: fc.i in0                        // issuable on M2 only
        add in0=32,in0
        br.cloop.sptk.few .Loop
        ;;
diff -urN linux/arch/ia64/lib/memcpy_mck.S linux/arch/ia64/lib/memcpy_mck.S
--- linux/arch/ia64/lib/memcpy_mck.S    2005/02/07 02:54:32     1.5
+++ linux/arch/ia64/lib/memcpy_mck.S    2005/05/19 12:08:10     1.6
@@ -75,6 +75,7 @@
        mov     f6=f0
        br.cond.sptk .common_code
        ;;
+END(memcpy)
 GLOBAL_ENTRY(__copy_user)
        .prologue
 // check dest alignment
@@ -300,7 +301,7 @@
        add     src_pre_mem=0,src0      // prefetch src pointer
        add     dst_pre_mem=0,dst0      // prefetch dest pointer
        and     src0=-8,src0            // 1st src pointer
-(p7)   mov     ar.lc = r21
+(p7)   mov     ar.lc = cnt
 (p8)   mov     ar.lc = r0
        ;;
        TEXT_ALIGN(32)
@@ -524,7 +525,6 @@
 #undef B
 #undef C
 #undef D
-END(memcpy)
 
 /*
  * Due to lack of local tag support in gcc 2.x assembler, it is not clear which
diff -urN linux/arch/ia64/lib/memset.S linux/arch/ia64/lib/memset.S
--- linux/arch/ia64/lib/memset.S        2004/02/05 02:39:53     1.8
+++ linux/arch/ia64/lib/memset.S        2005/05/19 12:08:10     1.9
@@ -57,10 +57,10 @@
 { .mmi
        .prologue
        alloc   tmp = ar.pfs, 3, 0, 0, 0
-       .body
        lfetch.nt1 [dest]                       //
        .save   ar.lc, save_lc
        mov.i   save_lc = ar.lc
+       .body
 } { .mmi
        mov     ret0 = dest                     // return value
        cmp.ne  p_nz, p_zr = value, r0          // use stf.spill if value is 
zero
diff -urN linux/arch/ia64/mm/contig.c linux/arch/ia64/mm/contig.c
--- linux/arch/ia64/mm/contig.c 2005/03/18 17:36:51     1.12
+++ linux/arch/ia64/mm/contig.c 2005/05/19 12:08:10     1.13
@@ -61,7 +61,8 @@
        printk("%d reserved pages\n", reserved);
        printk("%d pages shared\n", shared);
        printk("%d pages swap cached\n", cached);
-       printk("%ld pages in page table cache\n", pgtable_cache_size);
+       printk("%ld pages in page table cache\n",
+               pgtable_quicklist_total_size());
 }
 
 /* physical address where the bootmem map is located */
diff -urN linux/arch/ia64/mm/discontig.c linux/arch/ia64/mm/discontig.c
--- linux/arch/ia64/mm/discontig.c      2005/02/13 20:16:16     1.21
+++ linux/arch/ia64/mm/discontig.c      2005/05/19 12:08:10     1.22
@@ -582,7 +582,8 @@
        printk("%d reserved pages\n", total_reserved);
        printk("%d pages shared\n", total_shared);
        printk("%d pages swap cached\n", total_cached);
-       printk("Total of %ld pages in page table cache\n", pgtable_cache_size);
+       printk("Total of %ld pages in page table cache\n",
+               pgtable_quicklist_total_size());
        printk("%d free buffer pages\n", nr_free_buffer_pages());
 }
 
diff -urN linux/arch/ia64/mm/fault.c linux/arch/ia64/mm/fault.c
--- linux/arch/ia64/mm/fault.c  2005/01/13 14:05:26     1.22
+++ linux/arch/ia64/mm/fault.c  2005/05/19 12:08:10     1.23
@@ -209,10 +209,13 @@
        }
 
   no_context:
-       if (isr & IA64_ISR_SP) {
+       if ((isr & IA64_ISR_SP)
+           || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == 
IA64_ISR_CODE_LFETCH))
+       {
                /*
-                * This fault was due to a speculative load set the "ed" bit in 
the psr to
-                * ensure forward progress (target register will get a NaT).
+                * This fault was due to a speculative load or lfetch.fault, 
set the "ed"
+                * bit in the psr to ensure forward progress.  (Target register 
will get a
+                * NaT for ld.s, lfetch will be canceled.)
                 */
                ia64_psr(regs)->ed = 1;
                return;
diff -urN linux/arch/ia64/mm/init.c linux/arch/ia64/mm/init.c
--- linux/arch/ia64/mm/init.c   2005/04/08 18:57:54     1.54
+++ linux/arch/ia64/mm/init.c   2005/05/19 12:08:10     1.55
@@ -39,6 +39,9 @@
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
+DEFINE_PER_CPU(unsigned long *, __pgtable_quicklist);
+DEFINE_PER_CPU(long, __pgtable_quicklist_size);
+
 extern void ia64_tlb_init (void);
 
 unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
@@ -50,27 +53,53 @@
 EXPORT_SYMBOL(vmem_map);
 #endif
 
-static int pgt_cache_water[2] = { 25, 50 };
-
-struct page *zero_page_memmap_ptr;             /* map entry for zero page */
+struct page *zero_page_memmap_ptr;     /* map entry for zero page */
 EXPORT_SYMBOL(zero_page_memmap_ptr);
 
+#define MIN_PGT_PAGES                  25UL
+#define MAX_PGT_FREES_PER_PASS         16L
+#define PGT_FRACTION_OF_NODE_MEM       16
+
+static inline long
+max_pgt_pages(void)
+{
+       u64 node_free_pages, max_pgt_pages;
+
+#ifndef        CONFIG_NUMA
+       node_free_pages = nr_free_pages();
+#else
+       node_free_pages = nr_free_pages_pgdat(NODE_DATA(numa_node_id()));
+#endif
+       max_pgt_pages = node_free_pages / PGT_FRACTION_OF_NODE_MEM;
+       max_pgt_pages = max(max_pgt_pages, MIN_PGT_PAGES);
+       return max_pgt_pages;
+}
+
+static inline long
+min_pages_to_free(void)
+{
+       long pages_to_free;
+
+       pages_to_free = pgtable_quicklist_size - max_pgt_pages();
+       pages_to_free = min(pages_to_free, MAX_PGT_FREES_PER_PASS);
+       return pages_to_free;
+}
+
 void
-check_pgt_cache (void)
+check_pgt_cache(void)
 {
-       int low, high;
+       long pages_to_free;
 
-       low = pgt_cache_water[0];
-       high = pgt_cache_water[1];
+       if (unlikely(pgtable_quicklist_size <= MIN_PGT_PAGES))
+               return;
 
        preempt_disable();
-       if (pgtable_cache_size > (u64) high) {
-               do {
-                       if (pgd_quicklist)
-                               free_page((unsigned 
long)pgd_alloc_one_fast(NULL));
-                       if (pmd_quicklist)
-                               free_page((unsigned 
long)pmd_alloc_one_fast(NULL, 0));
-               } while (pgtable_cache_size > (u64) low);
+       while (unlikely((pages_to_free = min_pages_to_free()) > 0)) {
+               while (pages_to_free--) {
+                       free_page((unsigned long)pgtable_quicklist_alloc());
+               }
+               preempt_enable();
+               preempt_disable();
        }
        preempt_enable();
 }
@@ -523,11 +552,14 @@
 mem_init (void)
 {
        long reserved_pages, codesize, datasize, initsize;
-       unsigned long num_pgt_pages;
        pg_data_t *pgdat;
        int i;
        static struct kcore_list kcore_mem, kcore_vmem, kcore_kernel;
 
+       BUG_ON(PTRS_PER_PGD * sizeof(pgd_t) != PAGE_SIZE);
+       BUG_ON(PTRS_PER_PMD * sizeof(pmd_t) != PAGE_SIZE);
+       BUG_ON(PTRS_PER_PTE * sizeof(pte_t) != PAGE_SIZE);
+
 #ifdef CONFIG_PCI
        /*
         * This needs to be called _after_ the command line has been parsed but 
_before_
@@ -564,18 +596,6 @@
               num_physpages << (PAGE_SHIFT - 10), codesize >> 10,
               reserved_pages << (PAGE_SHIFT - 10), datasize >> 10, initsize >> 
10);
 
-       /*
-        * Allow for enough (cached) page table pages so that we can map the 
entire memory
-        * at least once.  Each task also needs a couple of page tables pages, 
so add in a
-        * fudge factor for that (don't use "threads-max" here; that would be 
wrong!).
-        * Don't allow the cache to be more than 10% of total memory, though.
-        */
-#      define NUM_TASKS        500     /* typical number of tasks */
-       num_pgt_pages = nr_free_pages() / PTRS_PER_PGD + NUM_TASKS;
-       if (num_pgt_pages > nr_free_pages() / 10)
-               num_pgt_pages = nr_free_pages() / 10;
-       if (num_pgt_pages > (u64) pgt_cache_water[1])
-               pgt_cache_water[1] = num_pgt_pages;
 
        /*
         * For fsyscall entrpoints with no light-weight handler, use the 
ordinary
diff -urN linux/arch/ia64/sn/include/pci/pcibr_provider.h 
linux/arch/ia64/sn/include/pci/pcibr_provider.h
--- linux/arch/ia64/sn/include/pci/pcibr_provider.h     2004/10/25 20:44:14     
1.1
+++ linux/arch/ia64/sn/include/pci/pcibr_provider.h     2005/05/19 12:08:10     
1.2
@@ -123,9 +123,11 @@
 }
 #define pcibr_unlock(pcibus_info, flag)  
spin_unlock_irqrestore(&pcibus_info->pbi_lock, flag)
 
+extern int  pcibr_init_provider(void);
 extern void *pcibr_bus_fixup(struct pcibus_bussoft *);
-extern uint64_t pcibr_dma_map(struct pcidev_info *, unsigned long, size_t, 
unsigned int);
-extern void pcibr_dma_unmap(struct pcidev_info *, dma_addr_t, int);
+extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t);
+extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, 
size_t);
+extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int);
 
 /*
  * prototypes for the bridge asic register access routines in pcibr_reg.c
diff -urN linux/arch/ia64/sn/include/pci/pcibus_provider_defs.h 
linux/arch/ia64/sn/include/pci/pcibus_provider_defs.h
--- linux/arch/ia64/sn/include/pci/Attic/pcibus_provider_defs.h 2005-05-19 
13:08:10.593849000 +0100     1.1
+++ linux/arch/ia64/sn/include/pci/Attic/pcibus_provider_defs.h 1970/01/01 
00:00:00+0100
@@ -1,43 +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) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights 
reserved.
- */
-#ifndef _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H
-#define _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H
-
-/*
- * SN pci asic types.  Do not ever renumber these or reuse values.  The
- * values must agree with what prom thinks they are.
- */
-
-#define PCIIO_ASIC_TYPE_UNKNOWN        0
-#define PCIIO_ASIC_TYPE_PPB    1
-#define PCIIO_ASIC_TYPE_PIC    2
-#define PCIIO_ASIC_TYPE_TIOCP  3
-
-/*
- * Common pciio bus provider data.  There should be one of these as the
- * first field in any pciio based provider soft structure (e.g. pcibr_soft
- * tioca_soft, etc).
- */
-
-struct pcibus_bussoft {
-       uint32_t                bs_asic_type;   /* chipset type */
-       uint32_t                bs_xid;         /* xwidget id */
-       uint64_t                bs_persist_busnum; /* Persistent Bus Number */
-       uint64_t                bs_legacy_io;   /* legacy io pio addr */
-       uint64_t                bs_legacy_mem;  /* legacy mem pio addr */
-       uint64_t                bs_base;        /* widget base */
-       struct xwidget_info     *bs_xwidget_info;
-};
-
-/*
- * DMA mapping flags
- */
-
-#define SN_PCIDMA_CONSISTENT    0x0001
-
-#endif                         /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */
diff -urN linux/arch/ia64/sn/include/pci/pcidev.h 
linux/arch/ia64/sn/include/pci/pcidev.h
--- linux/arch/ia64/sn/include/pci/Attic/pcidev.h       2005-05-19 
13:08:10.604607000 +0100     1.1
+++ linux/arch/ia64/sn/include/pci/Attic/pcidev.h       1970/01/01 00:00:00+0100
@@ -1,54 +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) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights 
reserved.
- */
-#ifndef _ASM_IA64_SN_PCI_PCIDEV_H
-#define _ASM_IA64_SN_PCI_PCIDEV_H
-
-#include <linux/pci.h>
-
-extern struct sn_irq_info **sn_irq;
-
-#define SN_PCIDEV_INFO(pci_dev) \
-        ((struct pcidev_info *)(pci_dev)->sysdata)
-
-/*
- * Given a pci_bus, return the sn pcibus_bussoft struct.  Note that
- * this only works for root busses, not for busses represented by PPB's.
- */
-
-#define SN_PCIBUS_BUSSOFT(pci_bus) \
-        ((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
-
-/*
- * Given a struct pci_dev, return the sn pcibus_bussoft struct.  Note
- * that this is not equivalent to SN_PCIBUS_BUSSOFT(pci_dev->bus) due
- * due to possible PPB's in the path.
- */
-
-#define SN_PCIDEV_BUSSOFT(pci_dev) \
-       (SN_PCIDEV_INFO(pci_dev)->pdi_host_pcidev_info->pdi_pcibus_info)
-
-#define PCIIO_BUS_NONE 255      /* bus 255 reserved */
-#define PCIIO_SLOT_NONE 255
-#define PCIIO_FUNC_NONE 255
-#define PCIIO_VENDOR_ID_NONE   (-1)
-
-struct pcidev_info {
-       uint64_t                pdi_pio_mapped_addr[7]; /* 6 BARs PLUS 1 ROM */
-       uint64_t                pdi_slot_host_handle;   /* Bus and devfn Host 
pci_dev */
-
-       struct pcibus_bussoft   *pdi_pcibus_info;       /* Kernel common bus 
soft */
-       struct pcidev_info      *pdi_host_pcidev_info;  /* Kernel Host pci_dev 
*/
-       struct pci_dev          *pdi_linux_pcidev;      /* Kernel pci_dev */
-
-       struct sn_irq_info      *pdi_sn_irq_info;
-};
-
-extern void sn_irq_fixup(struct pci_dev *pci_dev,
-                        struct sn_irq_info *sn_irq_info);
-
-#endif                         /* _ASM_IA64_SN_PCI_PCIDEV_H */
diff -urN linux/arch/ia64/sn/kernel/tiocx.c linux/arch/ia64/sn/kernel/tiocx.c
--- linux/arch/ia64/sn/kernel/tiocx.c   1970/01/01 00:00:00
+++ linux/arch/ia64/sn/kernel/tiocx.c   2005-05-19 13:08:10.703675000 +0100     
1.1
@@ -0,0 +1,552 @@
+/*
+ * 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 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/proc_fs.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/io.h>
+#include <asm/sn/types.h>
+#include <asm/sn/shubio.h>
+#include <asm/sn/tiocx.h>
+#include <asm/sn/l1.h>
+#include <asm/sn/module.h>
+#include "tio.h"
+#include "xtalk/xwidgetdev.h"
+#include "xtalk/hubdev.h"
+
+#define CX_DEV_NONE 0
+#define DEVICE_NAME "tiocx"
+#define WIDGET_ID 0
+#define TIOCX_DEBUG 0
+
+#if TIOCX_DEBUG
+#define DBG(fmt...)    printk(KERN_ALERT fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+struct device_attribute dev_attr_cxdev_control;
+
+/**
+ * tiocx_match - Try to match driver id list with device.
+ * @dev: device pointer
+ * @drv: driver pointer
+ *
+ * Returns 1 if match, 0 otherwise.
+ */
+static int tiocx_match(struct device *dev, struct device_driver *drv)
+{
+       struct cx_dev *cx_dev = to_cx_dev(dev);
+       struct cx_drv *cx_drv = to_cx_driver(drv);
+       const struct cx_device_id *ids = cx_drv->id_table;
+
+       if (!ids)
+               return 0;
+
+       while (ids->part_num) {
+               if (ids->part_num == cx_dev->cx_id.part_num)
+                       return 1;
+               ids++;
+       }
+       return 0;
+
+}
+
+static int tiocx_hotplug(struct device *dev, char **envp, int num_envp,
+                        char *buffer, int buffer_size)
+{
+       return -ENODEV;
+}
+
+static void tiocx_bus_release(struct device *dev)
+{
+       kfree(to_cx_dev(dev));
+}
+
+struct bus_type tiocx_bus_type = {
+       .name = "tiocx",
+       .match = tiocx_match,
+       .hotplug = tiocx_hotplug,
+};
+
+/**
+ * cx_device_match - Find cx_device in the id table.
+ * @ids: id table from driver
+ * @cx_device: part/mfg id for the device
+ *
+ */
+static const struct cx_device_id *cx_device_match(const struct cx_device_id
+                                                 *ids,
+                                                 struct cx_dev *cx_device)
+{
+       /*
+        * NOTES: We may want to check for CX_ANY_ID too.
+        *        Do we want to match against nasid too?
+        *        CX_DEV_NONE == 0, if the driver tries to register for
+        *        part/mfg == 0 we should return no-match (NULL) here.
+        */
+       while (ids->part_num && ids->mfg_num) {
+               if (ids->part_num == cx_device->cx_id.part_num &&
+                   ids->mfg_num == cx_device->cx_id.mfg_num)
+                       return ids;
+               ids++;
+       }
+
+       return NULL;
+}
+
+/**
+ * cx_device_probe - Look for matching device.
+ *                     Call driver probe routine if found.
+ * @cx_driver: driver table (cx_drv struct) from driver
+ * @cx_device: part/mfg id for the device
+ */
+static int cx_device_probe(struct device *dev)
+{
+       const struct cx_device_id *id;
+       struct cx_drv *cx_drv = to_cx_driver(dev->driver);
+       struct cx_dev *cx_dev = to_cx_dev(dev);
+       int error = 0;
+
+       if (!cx_dev->driver && cx_drv->probe) {
+               id = cx_device_match(cx_drv->id_table, cx_dev);
+               if (id) {
+                       if ((error = cx_drv->probe(cx_dev, id)) < 0)
+                               return error;
+                       else
+                               cx_dev->driver = cx_drv;
+               }
+       }
+
+       return error;
+}
+
+/**
+ * cx_driver_remove - Remove driver from device struct.
+ * @dev: device
+ */
+static int cx_driver_remove(struct device *dev)
+{
+       struct cx_dev *cx_dev = to_cx_dev(dev);
+       struct cx_drv *cx_drv = cx_dev->driver;
+       if (cx_drv->remove)
+               cx_drv->remove(cx_dev);
+       cx_dev->driver = NULL;
+       return 0;
+}
+
+/**
+ * cx_driver_register - Register the driver.
+ * @cx_driver: driver table (cx_drv struct) from driver
+ * 
+ * Called from the driver init routine to register a driver.
+ * The cx_drv struct contains the driver name, a pointer to
+ * a table of part/mfg numbers and a pointer to the driver's
+ * probe/attach routine.
+ */
+int cx_driver_register(struct cx_drv *cx_driver)
+{
+       cx_driver->driver.name = cx_driver->name;
+       cx_driver->driver.bus = &tiocx_bus_type;
+       cx_driver->driver.probe = cx_device_probe;
+       cx_driver->driver.remove = cx_driver_remove;
+
+       return driver_register(&cx_driver->driver);
+}
+
+/**
+ * cx_driver_unregister - Unregister the driver.
+ * @cx_driver: driver table (cx_drv struct) from driver
+ */
+int cx_driver_unregister(struct cx_drv *cx_driver)
+{
+       driver_unregister(&cx_driver->driver);
+       return 0;
+}
+
+/**
+ * cx_device_register - Register a device.
+ * @nasid: device's nasid
+ * @part_num: device's part number
+ * @mfg_num: device's manufacturer number
+ * @hubdev: hub info associated with this device
+ *
+ */
+int
+cx_device_register(nasid_t nasid, int part_num, int mfg_num,
+                  struct hubdev_info *hubdev)
+{
+       struct cx_dev *cx_dev;
+
+       cx_dev = kcalloc(1, sizeof(struct cx_dev), GFP_KERNEL);
+       DBG("cx_dev= 0x%p\n", cx_dev);
+       if (cx_dev == NULL)
+               return -ENOMEM;
+
+       cx_dev->cx_id.part_num = part_num;
+       cx_dev->cx_id.mfg_num = mfg_num;
+       cx_dev->cx_id.nasid = nasid;
+       cx_dev->hubdev = hubdev;
+
+       cx_dev->dev.parent = NULL;
+       cx_dev->dev.bus = &tiocx_bus_type;
+       cx_dev->dev.release = tiocx_bus_release;
+       snprintf(cx_dev->dev.bus_id, BUS_ID_SIZE, "%d.0x%x",
+                cx_dev->cx_id.nasid, cx_dev->cx_id.part_num);
+       device_register(&cx_dev->dev);
+       get_device(&cx_dev->dev);
+
+       device_create_file(&cx_dev->dev, &dev_attr_cxdev_control);
+
+       return 0;
+}
+
+/**
+ * cx_device_unregister - Unregister a device.
+ * @cx_dev: part/mfg id for the device
+ */
+int cx_device_unregister(struct cx_dev *cx_dev)
+{
+       put_device(&cx_dev->dev);
+       device_unregister(&cx_dev->dev);
+       return 0;
+}
+
+/**
+ * cx_device_reload - Reload the device.
+ * @nasid: device's nasid
+ * @part_num: device's part number
+ * @mfg_num: device's manufacturer number
+ *
+ * Remove the device associated with 'nasid' from device list and then
+ * call device-register with the given part/mfg numbers.
+ */
+static int cx_device_reload(struct cx_dev *cx_dev)
+{
+       device_remove_file(&cx_dev->dev, &dev_attr_cxdev_control);
+       cx_device_unregister(cx_dev);
+       return cx_device_register(cx_dev->cx_id.nasid, cx_dev->cx_id.part_num,
+                                 cx_dev->cx_id.mfg_num, cx_dev->hubdev);
+}
+
+static inline uint64_t tiocx_intr_alloc(nasid_t nasid, int widget,
+                                       u64 sn_irq_info,
+                                       int req_irq, nasid_t req_nasid,
+                                       int req_slice)
+{
+       struct ia64_sal_retval rv;
+       rv.status = 0;
+       rv.v0 = 0;
+
+       ia64_sal_oemcall_nolock(&rv, SN_SAL_IOIF_INTERRUPT,
+                               SAL_INTR_ALLOC, nasid,
+                               widget, sn_irq_info, req_irq,
+                               req_nasid, req_slice);
+       return rv.status;
+}
+
+static inline void tiocx_intr_free(nasid_t nasid, int widget,
+                                  struct sn_irq_info *sn_irq_info)
+{
+       struct ia64_sal_retval rv;
+       rv.status = 0;
+       rv.v0 = 0;
+
+       ia64_sal_oemcall_nolock(&rv, SN_SAL_IOIF_INTERRUPT,
+                               SAL_INTR_FREE, nasid,
+                               widget, sn_irq_info->irq_irq,
+                               sn_irq_info->irq_cookie, 0, 0);
+}
+
+struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq,
+                                   nasid_t req_nasid, int slice)
+{
+       struct sn_irq_info *sn_irq_info;
+       int status;
+       int sn_irq_size = sizeof(struct sn_irq_info);
+
+       if ((nasid & 1) == 0)
+               return NULL;
+
+       sn_irq_info = kmalloc(sn_irq_size, GFP_KERNEL);
+       if (sn_irq_info == NULL)
+               return NULL;
+
+       memset(sn_irq_info, 0x0, sn_irq_size);
+
+       status = tiocx_intr_alloc(nasid, widget, __pa(sn_irq_info), irq,
+                                 req_nasid, slice);
+       if (status) {
+               kfree(sn_irq_info);
+               return NULL;
+       } else {
+               return sn_irq_info;
+       }
+}
+
+void tiocx_irq_free(struct sn_irq_info *sn_irq_info)
+{
+       uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge;
+       nasid_t nasid = NASID_GET(bridge);
+       int widget;
+
+       if (nasid & 1) {
+               widget = TIO_SWIN_WIDGETNUM(bridge);
+               tiocx_intr_free(nasid, widget, sn_irq_info);
+               kfree(sn_irq_info);
+       }
+}
+
+uint64_t tiocx_dma_addr(uint64_t addr)
+{
+       return PHYS_TO_TIODMA(addr);
+}
+
+uint64_t tiocx_swin_base(int nasid)
+{
+       return TIO_SWIN_BASE(nasid, TIOCX_CORELET);
+}
+
+EXPORT_SYMBOL(cx_driver_register);
+EXPORT_SYMBOL(cx_driver_unregister);
+EXPORT_SYMBOL(cx_device_register);
+EXPORT_SYMBOL(cx_device_unregister);
+EXPORT_SYMBOL(tiocx_irq_alloc);
+EXPORT_SYMBOL(tiocx_irq_free);
+EXPORT_SYMBOL(tiocx_bus_type);
+EXPORT_SYMBOL(tiocx_dma_addr);
+EXPORT_SYMBOL(tiocx_swin_base);
+
+static void tio_conveyor_set(nasid_t nasid, int enable_flag)
+{
+       uint64_t ice_frz;
+       uint64_t disable_cb = (1ull << 61);
+
+       if (!(nasid & 1))
+               return;
+
+       ice_frz = REMOTE_HUB_L(nasid, TIO_ICE_FRZ_CFG);
+       if (enable_flag) {
+               if (!(ice_frz & disable_cb))    /* already enabled */
+                       return;
+               ice_frz &= ~disable_cb;
+       } else {
+               if (ice_frz & disable_cb)       /* already disabled */
+                       return;
+               ice_frz |= disable_cb;
+       }
+       DBG(KERN_ALERT "TIO_ICE_FRZ_CFG= 0x%lx\n", ice_frz);
+       REMOTE_HUB_S(nasid, TIO_ICE_FRZ_CFG, ice_frz);
+}
+
+#define tio_conveyor_enable(nasid) tio_conveyor_set(nasid, 1)
+#define tio_conveyor_disable(nasid) tio_conveyor_set(nasid, 0)
+
+static void tio_corelet_reset(nasid_t nasid, int corelet)
+{
+       if (!(nasid & 1))
+               return;
+
+       REMOTE_HUB_S(nasid, TIO_ICE_PMI_TX_CFG, 1 << corelet);
+       udelay(2000);
+       REMOTE_HUB_S(nasid, TIO_ICE_PMI_TX_CFG, 0);
+       udelay(2000);
+}
+
+static int tiocx_btchar_get(int nasid)
+{
+       moduleid_t module_id;
+       geoid_t geoid;
+       int cnodeid;
+
+       cnodeid = nasid_to_cnodeid(nasid);
+       geoid = cnodeid_get_geoid(cnodeid);
+       module_id = geo_module(geoid);
+       return MODULE_GET_BTCHAR(module_id);
+}
+
+static int is_fpga_brick(int nasid)
+{
+       switch (tiocx_btchar_get(nasid)) {
+       case L1_BRICKTYPE_SA:
+       case L1_BRICKTYPE_ATHENA:
+               return 1;
+       }
+       return 0;
+}
+
+static int bitstream_loaded(nasid_t nasid)
+{
+       uint64_t cx_credits;
+
+       cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3);
+       cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK;
+       DBG("cx_credits= 0x%lx\n", cx_credits);
+
+       return (cx_credits == 0xf) ? 1 : 0;
+}
+
+static int tiocx_reload(struct cx_dev *cx_dev)
+{
+       int part_num = CX_DEV_NONE;
+       int mfg_num = CX_DEV_NONE;
+       nasid_t nasid = cx_dev->cx_id.nasid;
+
+       if (bitstream_loaded(nasid)) {
+               uint64_t cx_id;
+
+               cx_id =
+                   *(volatile int32_t *)(TIO_SWIN_BASE(nasid, TIOCX_CORELET) +
+                                         WIDGET_ID);
+               part_num = XWIDGET_PART_NUM(cx_id);
+               mfg_num = XWIDGET_MFG_NUM(cx_id);
+               DBG("part= 0x%x, mfg= 0x%x\n", part_num, mfg_num);
+               /* just ignore it if it's a CE */
+               if (part_num == TIO_CE_ASIC_PARTNUM)
+                       return 0;
+       }
+
+       cx_dev->cx_id.part_num = part_num;
+       cx_dev->cx_id.mfg_num = mfg_num;
+
+       /*
+        * Delete old device and register the new one.  It's ok if
+        * part_num/mfg_num == CX_DEV_NONE.  We want to register
+        * devices in the table even if a bitstream isn't loaded.
+        * That allows use to see that a bitstream isn't loaded via
+        * TIOCX_IOCTL_DEV_LIST.
+        */
+       return cx_device_reload(cx_dev);
+}
+
+static ssize_t show_cxdev_control(struct device *dev, char *buf)
+{
+       struct cx_dev *cx_dev = to_cx_dev(dev);
+
+       return sprintf(buf, "0x%x 0x%x 0x%x %d\n",
+                      cx_dev->cx_id.nasid,
+                      cx_dev->cx_id.part_num, cx_dev->cx_id.mfg_num,
+                      tiocx_btchar_get(cx_dev->cx_id.nasid));
+}
+
+static ssize_t store_cxdev_control(struct device *dev, const char *buf,
+                                  size_t count)
+{
+       int n;
+       struct cx_dev *cx_dev = to_cx_dev(dev);
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (count <= 0)
+               return 0;
+
+       n = simple_strtoul(buf, NULL, 0);
+
+       switch (n) {
+       case 1:
+               tiocx_reload(cx_dev);
+               break;
+       case 3:
+               tio_corelet_reset(cx_dev->cx_id.nasid, TIOCX_CORELET);
+               break;
+       default:
+               break;
+       }
+
+       return count;
+}
+
+DEVICE_ATTR(cxdev_control, 0644, show_cxdev_control, store_cxdev_control);
+
+static int __init tiocx_init(void)
+{
+       cnodeid_t cnodeid;
+       int found_tiocx_device = 0;
+
+       bus_register(&tiocx_bus_type);
+
+       for (cnodeid = 0; cnodeid < MAX_COMPACT_NODES; cnodeid++) {
+               nasid_t nasid;
+
+               if ((nasid = cnodeid_to_nasid(cnodeid)) < 0)
+                       break;  /* No more nasids .. bail out of loop */
+
+               if ((nasid & 0x1) && is_fpga_brick(nasid)) {
+                       struct hubdev_info *hubdev;
+                       struct xwidget_info *widgetp;
+
+                       DBG("Found TIO at nasid 0x%x\n", nasid);
+
+                       hubdev =
+                           (struct hubdev_info *)(NODEPDA(cnodeid)->pdinfo);
+
+                       widgetp = &hubdev->hdi_xwidget_info[TIOCX_CORELET];
+
+                       /* The CE hangs off of the CX port but is not an FPGA */
+                       if (widgetp->xwi_hwid.part_num == TIO_CE_ASIC_PARTNUM)
+                               continue;
+
+                       tio_corelet_reset(nasid, TIOCX_CORELET);
+                       tio_conveyor_enable(nasid);
+
+                       if (cx_device_register
+                           (nasid, widgetp->xwi_hwid.part_num,
+                            widgetp->xwi_hwid.mfg_num, hubdev) < 0)
+                               return -ENXIO;
+                       else
+                               found_tiocx_device++;
+               }
+       }
+
+       /* It's ok if we find zero devices. */
+       DBG("found_tiocx_device= %d\n", found_tiocx_device);
+
+       return 0;
+}
+
+static void __exit tiocx_exit(void)
+{
+       struct device *dev;
+       struct device *tdev;
+
+       DBG("tiocx_exit\n");
+
+       /*
+        * Unregister devices.
+        */
+       list_for_each_entry_safe(dev, tdev, &tiocx_bus_type.devices.list,
+                                bus_list) {
+               if (dev) {
+                       struct cx_dev *cx_dev = to_cx_dev(dev);
+                       device_remove_file(dev, &dev_attr_cxdev_control);
+                       cx_device_unregister(cx_dev);
+               }
+       }
+
+       bus_unregister(&tiocx_bus_type);
+}
+
+module_init(tiocx_init);
+module_exit(tiocx_exit);
+
+/************************************************************************
+ * Module licensing and description
+ ************************************************************************/
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bruce Losure <blosure@sgi.com>");
+MODULE_DESCRIPTION("TIOCX module");
+MODULE_SUPPORTED_DEVICE(DEVICE_NAME);
diff -urN linux/arch/ia64/sn/kernel/xp_main.c 
linux/arch/ia64/sn/kernel/xp_main.c
--- linux/arch/ia64/sn/kernel/xp_main.c 1970/01/01 00:00:00
+++ linux/arch/ia64/sn/kernel/xp_main.c 2005-05-19 13:08:10.718703000 +0100     
1.1
@@ -0,0 +1,289 @@
+/*
+ * 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-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition (XP) base.
+ *
+ *     XP provides a base from which its users can interact
+ *     with XPC, yet not be dependent on XPC.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/xp.h>
+
+
+/*
+ * Target of nofault PIO read.
+ */
+u64 xp_nofault_PIOR_target;
+
+
+/*
+ * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
+ * users of XPC.
+ */
+struct xpc_registration xpc_registrations[XPC_NCHANNELS];
+
+
+/*
+ * Initialize the XPC interface to indicate that XPC isn't loaded.
+ */
+static enum xpc_retval xpc_notloaded(void) { return xpcNotLoaded; }
+
+struct xpc_interface xpc_interface = {
+       (void (*)(int)) xpc_notloaded,
+       (void (*)(int)) xpc_notloaded,
+       (enum xpc_retval (*)(partid_t, int, u32, void **)) xpc_notloaded,
+       (enum xpc_retval (*)(partid_t, int, void *)) xpc_notloaded,
+       (enum xpc_retval (*)(partid_t, int, void *, xpc_notify_func, void *))
+                                                       xpc_notloaded,
+       (void (*)(partid_t, int, void *)) xpc_notloaded,
+       (enum xpc_retval (*)(partid_t, void *)) xpc_notloaded
+};
+
+
+/*
+ * XPC calls this when it (the XPC module) has been loaded.
+ */
+void
+xpc_set_interface(void (*connect)(int),
+               void (*disconnect)(int),
+               enum xpc_retval (*allocate)(partid_t, int, u32, void **),
+               enum xpc_retval (*send)(partid_t, int, void *),
+               enum xpc_retval (*send_notify)(partid_t, int, void *,
+                                               xpc_notify_func, void *),
+               void (*received)(partid_t, int, void *),
+               enum xpc_retval (*partid_to_nasids)(partid_t, void *))
+{
+       xpc_interface.connect = connect;
+       xpc_interface.disconnect = disconnect;
+       xpc_interface.allocate = allocate;
+       xpc_interface.send = send;
+       xpc_interface.send_notify = send_notify;
+       xpc_interface.received = received;
+       xpc_interface.partid_to_nasids = partid_to_nasids;
+}
+
+
+/*
+ * XPC calls this when it (the XPC module) is being unloaded.
+ */
+void
+xpc_clear_interface(void)
+{
+       xpc_interface.connect = (void (*)(int)) xpc_notloaded;
+       xpc_interface.disconnect = (void (*)(int)) xpc_notloaded;
+       xpc_interface.allocate = (enum xpc_retval (*)(partid_t, int, u32,
+                                       void **)) xpc_notloaded;
+       xpc_interface.send = (enum xpc_retval (*)(partid_t, int, void *))
+                                       xpc_notloaded;
+       xpc_interface.send_notify = (enum xpc_retval (*)(partid_t, int, void *,
+                                   xpc_notify_func, void *)) xpc_notloaded;
+       xpc_interface.received = (void (*)(partid_t, int, void *))
+                                       xpc_notloaded;
+       xpc_interface.partid_to_nasids = (enum xpc_retval (*)(partid_t, void *))
+                                       xpc_notloaded;
+}
+
+
+/*
+ * Register for automatic establishment of a channel connection whenever
+ * a partition comes up.
+ *
+ * Arguments:
+ *
+ *     ch_number - channel # to register for connection.
+ *     func - function to call for asynchronous notification of channel
+ *            state changes (i.e., connection, disconnection, error) and
+ *            the arrival of incoming messages.
+ *      key - pointer to optional user-defined value that gets passed back
+ *           to the user on any callouts made to func.
+ *     payload_size - size in bytes of the XPC message's payload area which
+ *                    contains a user-defined message. The user should make
+ *                    this large enough to hold their largest message.
+ *     nentries - max #of XPC message entries a message queue can contain.
+ *                The actual number, which is determined when a connection
+ *                is established and may be less then requested, will be
+ *                passed to the user via the xpcConnected callout.
+ *     assigned_limit - max number of kthreads allowed to be processing
+ *                      messages (per connection) at any given instant.
+ *     idle_limit - max number of kthreads allowed to be idle at any given
+ *                  instant.
+ */
+enum xpc_retval
+xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
+               u16 nentries, u32 assigned_limit, u32 idle_limit)
+{
+       struct xpc_registration *registration;
+
+
+       DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+       DBUG_ON(payload_size == 0 || nentries == 0);
+       DBUG_ON(func == NULL);
+       DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
+
+       registration = &xpc_registrations[ch_number];
+
+       if (down_interruptible(&registration->sema) != 0) {
+               return xpcInterrupted;
+       }
+
+       /* if XPC_CHANNEL_REGISTERED(ch_number) */
+       if (registration->func != NULL) {
+               up(&registration->sema);
+               return xpcAlreadyRegistered;
+       }
+
+       /* register the channel for connection */
+       registration->msg_size = XPC_MSG_SIZE(payload_size);
+       registration->nentries = nentries;
+       registration->assigned_limit = assigned_limit;
+       registration->idle_limit = idle_limit;
+       registration->key = key;
+       registration->func = func;
+
+       up(&registration->sema);
+
+       xpc_interface.connect(ch_number);
+
+       return xpcSuccess;
+}
+
+
+/*
+ * Remove the registration for automatic connection of the specified channel
+ * when a partition comes up.
+ *
+ * Before returning this xpc_disconnect() will wait for all connections on the
+ * specified channel have been closed/torndown. So the caller can be assured
+ * that they will not be receiving any more callouts from XPC to their
+ * function registered via xpc_connect().
+ *
+ * Arguments:
+ *
+ *     ch_number - channel # to unregister.
+ */
+void
+xpc_disconnect(int ch_number)
+{
+       struct xpc_registration *registration;
+
+
+       DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+
+       registration = &xpc_registrations[ch_number];
+
+       /*
+        * We've decided not to make this a down_interruptible(), since we
+        * figured XPC's users will just turn around and call xpc_disconnect()
+        * again anyways, so we might as well wait, if need be.
+        */
+       down(&registration->sema);
+
+       /* if !XPC_CHANNEL_REGISTERED(ch_number) */
+       if (registration->func == NULL) {
+               up(&registration->sema);
+               return;
+       }
+
+       /* remove the connection registration for the specified channel */
+       registration->func = NULL;
+       registration->key = NULL;
+       registration->nentries = 0;
+       registration->msg_size = 0;
+       registration->assigned_limit = 0;
+       registration->idle_limit = 0;
+
+       xpc_interface.disconnect(ch_number);
+
+       up(&registration->sema);
+
+       return;
+}
+
+
+int __init
+xp_init(void)
+{
+       int ret, ch_number;
+       u64 func_addr = *(u64 *) xp_nofault_PIOR;
+       u64 err_func_addr = *(u64 *) xp_error_PIOR;
+
+
+       if (!ia64_platform_is("sn2")) {
+               return -ENODEV;
+       }
+
+       /*
+        * Register a nofault code region which performs a cross-partition
+        * PIO read. If the PIO read times out, the MCA handler will consume
+        * the error and return to a kernel-provided instruction to indicate
+        * an error. This PIO read exists because it is guaranteed to timeout
+        * if the destination is down (AMO operations do not timeout on at
+        * least some CPUs on Shubs <= v1.2, which unfortunately we have to
+        * work around).
+        */
+       if ((ret = sn_register_nofault_code(func_addr, err_func_addr,
+                                               err_func_addr, 1, 1)) != 0) {
+               printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
+                       ret);
+       }
+       /*
+        * Setup the nofault PIO read target. (There is no special reason why
+        * SH_IPI_ACCESS was selected.)
+        */
+       if (is_shub2()) {
+               xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
+       } else {
+               xp_nofault_PIOR_target = SH1_IPI_ACCESS;
+       }
+
+       /* initialize the connection registration semaphores */
+       for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) {
+               sema_init(&xpc_registrations[ch_number].sema, 1);  /* mutex */
+       }
+
+       return 0;
+}
+module_init(xp_init);
+
+
+void __exit
+xp_exit(void)
+{
+       u64 func_addr = *(u64 *) xp_nofault_PIOR;
+       u64 err_func_addr = *(u64 *) xp_error_PIOR;
+
+
+       /* unregister the PIO read nofault code region */
+       (void) sn_register_nofault_code(func_addr, err_func_addr,
+                                       err_func_addr, 1, 0);
+}
+module_exit(xp_exit);
+
+
+MODULE_AUTHOR("Silicon Graphics, Inc.");
+MODULE_DESCRIPTION("Cross Partition (XP) base");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(xp_nofault_PIOR);
+EXPORT_SYMBOL(xp_nofault_PIOR_target);
+EXPORT_SYMBOL(xpc_registrations);
+EXPORT_SYMBOL(xpc_interface);
+EXPORT_SYMBOL(xpc_clear_interface);
+EXPORT_SYMBOL(xpc_set_interface);
+EXPORT_SYMBOL(xpc_connect);
+EXPORT_SYMBOL(xpc_disconnect);
+
diff -urN linux/arch/ia64/sn/kernel/xp_nofault.S 
linux/arch/ia64/sn/kernel/xp_nofault.S
--- linux/arch/ia64/sn/kernel/xp_nofault.S      1970/01/01 00:00:00
+++ linux/arch/ia64/sn/kernel/xp_nofault.S      2005-05-19 13:08:10.731691000 
+0100     1.1
@@ -0,0 +1,31 @@
+/*
+ * 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-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * The xp_nofault_PIOR function takes a pointer to a remote PIO register
+ * and attempts to load and consume a value from it.  This function
+ * will be registered as a nofault code block.  In the event that the
+ * PIO read fails, the MCA handler will force the error to look
+ * corrected and vector to the xp_error_PIOR which will return an error.
+ *
+ *     extern int xp_nofault_PIOR(void *remote_register);
+ */
+
+       .global xp_nofault_PIOR
+xp_nofault_PIOR:
+       mov     r8=r0                   // Stage a success return value
+       ld8.acq r9=[r32];;              // PIO Read the specified register
+       adds    r9=1,r9                 // Add to force a consume
+       br.ret.sptk.many b0;;           // Return success
+
+       .global xp_error_PIOR
+xp_error_PIOR:
+       mov     r8=1                    // Return value of 1
+       br.ret.sptk.many b0;;           // Return failure
+
diff -urN linux/arch/ia64/sn/kernel/xpc.h linux/arch/ia64/sn/kernel/xpc.h
--- linux/arch/ia64/sn/kernel/xpc.h     1970/01/01 00:00:00
+++ linux/arch/ia64/sn/kernel/xpc.h     2005-05-19 13:08:10.742387000 +0100     
1.1
@@ -0,0 +1,991 @@
+/*
+ * 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-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition Communication (XPC) structures and macros.
+ */
+
+#ifndef _IA64_SN_KERNEL_XPC_H
+#define _IA64_SN_KERNEL_XPC_H
+
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/sysctl.h>
+#include <linux/device.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/sn/bte.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/mspec.h>
+#include <asm/sn/shub_mmr.h>
+#include <asm/sn/xp.h>
+
+
+/*
+ * XPC Version numbers consist of a major and minor number. XPC can always
+ * talk to versions with same major #, and never talk to versions with a
+ * different major #.
+ */
+#define _XPC_VERSION(_maj, _min)       (((_maj) << 4) | ((_min) & 0xf))
+#define XPC_VERSION_MAJOR(_v)          ((_v) >> 4)
+#define XPC_VERSION_MINOR(_v)          ((_v) & 0xf)
+
+
+/*
+ * The next macros define word or bit representations for given
+ * C-brick nasid in either the SAL provided bit array representing
+ * nasids in the partition/machine or the AMO_t array used for
+ * inter-partition initiation communications.
+ *
+ * For SN2 machines, C-Bricks are alway even numbered NASIDs.  As
+ * such, some space will be saved by insisting that nasid information
+ * passed from SAL always be packed for C-Bricks and the
+ * cross-partition interrupts use the same packing scheme.
+ */
+#define XPC_NASID_W_INDEX(_n)  (((_n) / 64) / 2)
+#define XPC_NASID_B_INDEX(_n)  (((_n) / 2) & (64 - 1))
+#define XPC_NASID_IN_ARRAY(_n, _p) ((_p)[XPC_NASID_W_INDEX(_n)] & \
+                                   (1UL << XPC_NASID_B_INDEX(_n)))
+#define XPC_NASID_FROM_W_B(_w, _b) (((_w) * 64 + (_b)) * 2)
+
+#define XPC_HB_DEFAULT_INTERVAL                5       /* incr HB every x secs 
*/
+#define XPC_HB_CHECK_DEFAULT_TIMEOUT   20      /* check HB every x secs */
+
+/* define the process name of HB checker and the CPU it is pinned to */
+#define XPC_HB_CHECK_THREAD_NAME       "xpc_hb"
+#define XPC_HB_CHECK_CPU               0
+
+/* define the process name of the discovery thread */
+#define XPC_DISCOVERY_THREAD_NAME      "xpc_discovery"
+
+
+#define XPC_HB_ALLOWED(_p, _v) ((_v)->heartbeating_to_mask & (1UL << (_p)))
+#define XPC_ALLOW_HB(_p, _v)   (_v)->heartbeating_to_mask |= (1UL << (_p))
+#define XPC_DISALLOW_HB(_p, _v)        (_v)->heartbeating_to_mask &= (~(1UL << 
(_p)))
+
+
+/*
+ * Reserved Page provided by SAL.
+ *
+ * SAL provides one page per partition of reserved memory.  When SAL
+ * initialization is complete, SAL_signature, SAL_version, partid,
+ * part_nasids, and mach_nasids are set.
+ *
+ * Note: Until vars_pa is set, the partition XPC code has not been initialized.
+ */
+struct xpc_rsvd_page {
+       u64 SAL_signature;      /* SAL unique signature */
+       u64 SAL_version;        /* SAL specified version */
+       u8 partid;              /* partition ID from SAL */
+       u8 version;
+       u8 pad[6];              /* pad to u64 align */
+       u64 vars_pa;
+       u64 part_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
+       u64 mach_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
+};
+#define XPC_RP_VERSION _XPC_VERSION(1,0) /* version 1.0 of the reserved page */
+
+#define XPC_RSVD_PAGE_ALIGNED_SIZE \
+                       (L1_CACHE_ALIGN(sizeof(struct xpc_rsvd_page)))
+
+
+/*
+ * Define the structures by which XPC variables can be exported to other
+ * partitions. (There are two: struct xpc_vars and struct xpc_vars_part)
+ */
+
+/*
+ * The following structure describes the partition generic variables
+ * needed by other partitions in order to properly initialize.
+ *
+ * struct xpc_vars version number also applies to struct xpc_vars_part.
+ * Changes to either structure and/or related functionality should be
+ * reflected by incrementing either the major or minor version numbers
+ * of struct xpc_vars.
+ */
+struct xpc_vars {
+       u8 version;
+       u64 heartbeat;
+       u64 heartbeating_to_mask;
+       u64 kdb_status;         /* 0 = machine running */
+       int act_nasid;
+       int act_phys_cpuid;
+       u64 vars_part_pa;
+       u64 amos_page_pa;       /* paddr of page of AMOs from MSPEC driver */
+       AMO_t *amos_page;       /* vaddr of page of AMOs from MSPEC driver */
+       AMO_t *act_amos;        /* pointer to the first activation AMO */
+};
+#define XPC_V_VERSION _XPC_VERSION(3,0) /* version 3.0 of the cross vars */
+
+#define XPC_VARS_ALIGNED_SIZE  (L1_CACHE_ALIGN(sizeof(struct xpc_vars)))
+
+/*
+ * The following structure describes the per partition specific variables.
+ *
+ * An array of these structures, one per partition, will be defined. As a
+ * partition becomes active XPC will copy the array entry corresponding to
+ * itself from that partition. It is desirable that the size of this
+ * structure evenly divide into a cacheline, such that none of the entries
+ * in this array crosses a cacheline boundary. As it is now, each entry
+ * occupies half a cacheline.
+ */
+struct xpc_vars_part {
+       u64 magic;
+
+       u64 openclose_args_pa;  /* physical address of open and close args */
+       u64 GPs_pa;             /* physical address of Get/Put values */
+
+       u64 IPI_amo_pa;         /* physical address of IPI AMO_t structure */
+       int IPI_nasid;          /* nasid of where to send IPIs */
+       int IPI_phys_cpuid;     /* physical CPU ID of where to send IPIs */
+
+       u8 nchannels;           /* #of defined channels supported */
+
+       u8 reserved[23];        /* pad to a full 64 bytes */
+};
+
+/*
+ * The vars_part MAGIC numbers play a part in the first contact protocol.
+ *
+ * MAGIC1 indicates that the per partition specific variables for a remote
+ * partition have been initialized by this partition.
+ *
+ * MAGIC2 indicates that this partition has pulled the remote partititions
+ * per partition variables that pertain to this partition.
+ */
+#define XPC_VP_MAGIC1  0x0053524156435058L  /* 'XPCVARS\0'L (little endian) */
+#define XPC_VP_MAGIC2  0x0073726176435058L  /* 'XPCvars\0'L (little endian) */
+
+
+
+/*
+ * Functions registered by add_timer() or called by kernel_thread() only
+ * allow for a single 64-bit argument. The following macros can be used to
+ * pack and unpack two (32-bit, 16-bit or 8-bit) arguments into or out from
+ * the passed argument.
+ */
+#define XPC_PACK_ARGS(_arg1, _arg2) \
+                       ((((u64) _arg1) & 0xffffffff) | \
+                       ((((u64) _arg2) & 0xffffffff) << 32))
+
+#define XPC_UNPACK_ARG1(_args) (((u64) _args) & 0xffffffff)
+#define XPC_UNPACK_ARG2(_args) ((((u64) _args) >> 32) & 0xffffffff)
+
+
+
+/*
+ * Define a Get/Put value pair (pointers) used with a message queue.
+ */
+struct xpc_gp {
+       s64 get;        /* Get value */
+       s64 put;        /* Put value */
+};
+
+#define XPC_GP_SIZE \
+               L1_CACHE_ALIGN(sizeof(struct xpc_gp) * XPC_NCHANNELS)
+
+
+
+/*
+ * Define a structure that contains arguments associated with opening and
+ * closing a channel.
+ */
+struct xpc_openclose_args {
+       u16 reason;             /* reason why channel is closing */
+       u16 msg_size;           /* sizeof each message entry */
+       u16 remote_nentries;    /* #of message entries in remote msg queue */
+       u16 local_nentries;     /* #of message entries in local msg queue */
+       u64 local_msgqueue_pa;  /* physical address of local message queue */
+};
+
+#define XPC_OPENCLOSE_ARGS_SIZE \
+             L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * XPC_NCHANNELS)
+
+
+
+/* struct xpc_msg flags */
+
+#define        XPC_M_DONE              0x01    /* msg has been 
received/consumed */
+#define        XPC_M_READY             0x02    /* msg is ready to be sent */
+#define        XPC_M_INTERRUPT         0x04    /* send interrupt when msg 
consumed */
+
+
+#define XPC_MSG_ADDRESS(_payload) \
+               ((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET))
+
+
+
+/*
+ * Defines notify entry.
+ *
+ * This is used to notify a message's sender that their message was received
+ * and consumed by the intended recipient.
+ */
+struct xpc_notify {
+       struct semaphore sema;          /* notify semaphore */
+       u8 type;                        /* type of notification */
+
+       /* the following two fields are only used if type == XPC_N_CALL */
+       xpc_notify_func func;           /* user's notify function */
+       void *key;                      /* pointer to user's key */
+};
+
+/* struct xpc_notify type of notification */
+
+#define        XPC_N_CALL              0x01    /* notify function provided by 
user */
+
+
+
+/*
+ * Define the structure that manages all the stuff required by a channel. In
+ * particular, they are used to manage the messages sent across the channel.
+ *
+ * This structure is private to a partition, and is NOT shared across the
+ * partition boundary.
+ *
+ * There is an array of these structures for each remote partition. It is
+ * allocated at the time a partition becomes active. The array contains one
+ * of these structures for each potential channel connection to that partition.
+ *
+ * Each of these structures manages two message queues (circular buffers).
+ * They are allocated at the time a channel connection is made. One of
+ * these message queues (local_msgqueue) holds the locally created messages
+ * that are destined for the remote partition. The other of these message
+ * queues (remote_msgqueue) is a locally cached copy of the remote partition's
+ * own local_msgqueue.
+ *
+ * The following is a description of the Get/Put pointers used to manage these
+ * two message queues. Consider the local_msgqueue to be on one partition
+ * and the remote_msgqueue to be its cached copy on another partition. A
+ * description of what each of the lettered areas contains is included.
+ *
+ *
+ *                     local_msgqueue      remote_msgqueue
+ *
+ *                        |/////////|      |/////////|
+ *    w_remote_GP.get --> +---------+      |/////////|
+ *                        |    F    |      |/////////|
+ *     remote_GP.get  --> +---------+      +---------+ <-- local_GP->get
+ *                        |         |      |         |
+ *                        |         |      |    E    |
+ *                        |         |      |         |
+ *                        |         |      +---------+ <-- w_local_GP.get
+ *                        |    B    |      |/////////|
+ *                        |         |      |////D////|
+ *                        |         |      |/////////|
+ *                        |         |      +---------+ <-- w_remote_GP.put
+ *                        |         |      |////C////|
+ *      local_GP->put --> +---------+      +---------+ <-- remote_GP.put
+ *                        |         |      |/////////|
+ *                        |    A    |      |/////////|
+ *                        |         |      |/////////|
+ *     w_local_GP.put --> +---------+      |/////////|
+ *                        |/////////|      |/////////|
+ *
+ *
+ *         ( remote_GP.[get|put] are cached copies of the remote
+ *           partition's local_GP->[get|put], and thus their values can
+ *           lag behind their counterparts on the remote partition. )
+ *
+ *
+ *  A - Messages that have been allocated, but have not yet been sent to the
+ *     remote partition.
+ *
+ *  B - Messages that have been sent, but have not yet been acknowledged by the
+ *      remote partition as having been received.
+ *
+ *  C - Area that needs to be prepared for the copying of sent messages, by
+ *     the clearing of the message flags of any previously received messages.
+ *
+ *  D - Area into which sent messages are to be copied from the remote
+ *     partition's local_msgqueue and then delivered to their intended
+ *     recipients. [ To allow for a multi-message copy, another pointer
+ *     (next_msg_to_pull) has been added to keep track of the next message
+ *     number needing to be copied (pulled). It chases after w_remote_GP.put.
+ *     Any messages lying between w_local_GP.get and next_msg_to_pull have
+ *     been copied and are ready to be delivered. ]
+ *
+ *  E - Messages that have been copied and delivered, but have not yet been
+ *     acknowledged by the recipient as having been received.
+ *
+ *  F - Messages that have been acknowledged, but XPC has not yet notified the
+ *     sender that the message was received by its intended recipient.
+ *     This is also an area that needs to be prepared for the allocating of
+ *     new messages, by the clearing of the message flags of the acknowledged
+ *     messages.
+ */
+struct xpc_channel {
+       partid_t partid;                /* ID of remote partition connected */
+       spinlock_t lock;                /* lock for updating this structure */
+       u32 flags;                      /* general flags */
+
+       enum xpc_retval reason;         /* reason why channel is disconnect'g */
+       int reason_line;                /* line# disconnect initiated from */
+
+       u16 number;                     /* channel # */
+
+       u16 msg_size;                   /* sizeof each msg entry */
+       u16 local_nentries;             /* #of msg entries in local msg queue */
+       u16 remote_nentries;            /* #of msg entries in remote msg queue*/
+
+       void *local_msgqueue_base;      /* base address of kmalloc'd space */
+       struct xpc_msg *local_msgqueue; /* local message queue */
+       void *remote_msgqueue_base;     /* base address of kmalloc'd space */
+       struct xpc_msg *remote_msgqueue;/* cached copy of remote partition's */
+                                       /* local message queue */
+       u64 remote_msgqueue_pa;         /* phys addr of remote partition's */
+                                       /* local message queue */
+
+       atomic_t references;            /* #of external references to queues */
+
+       atomic_t n_on_msg_allocate_wq;   /* #on msg allocation wait queue */
+       wait_queue_head_t msg_allocate_wq; /* msg allocation wait queue */
+
+       /* queue of msg senders who want to be notified when msg received */
+
+       atomic_t n_to_notify;           /* #of msg senders to notify */
+       struct xpc_notify *notify_queue;/* notify queue for messages sent */
+
+       xpc_channel_func func;          /* user's channel function */
+       void *key;                      /* pointer to user's key */
+
+       struct semaphore msg_to_pull_sema; /* next msg to pull serialization */
+       struct semaphore teardown_sema;    /* wait for teardown completion */
+
+       struct xpc_openclose_args *local_openclose_args; /* args passed on */
+                                       /* opening or closing of channel */
+
+       /* various flavors of local and remote Get/Put values */
+
+       struct xpc_gp *local_GP;        /* local Get/Put values */
+       struct xpc_gp remote_GP;        /* remote Get/Put values */
+       struct xpc_gp w_local_GP;       /* working local Get/Put values */
+       struct xpc_gp w_remote_GP;      /* working remote Get/Put values */
+       s64 next_msg_to_pull;           /* Put value of next msg to pull */
+
+       /* kthread management related fields */
+
+// >>> rethink having kthreads_assigned_limit and kthreads_idle_limit; perhaps
+// >>> allow the assigned limit be unbounded and let the idle limit be dynamic
+// >>> dependent on activity over the last interval of time
+       atomic_t kthreads_assigned;     /* #of kthreads assigned to channel */
+       u32 kthreads_assigned_limit;    /* limit on #of kthreads assigned */
+       atomic_t kthreads_idle;         /* #of kthreads idle waiting for work */
+       u32 kthreads_idle_limit;        /* limit on #of kthreads idle */
+       atomic_t kthreads_active;       /* #of kthreads actively working */
+       // >>> following field is temporary
+       u32 kthreads_created;           /* total #of kthreads created */
+
+       wait_queue_head_t idle_wq;      /* idle kthread wait queue */
+
+} ____cacheline_aligned;
+
+
+/* struct xpc_channel flags */
+
+#define        XPC_C_WASCONNECTED      0x00000001 /* channel was connected */
+
+#define        XPC_C_ROPENREPLY        0x00000002 /* remote open channel reply 
*/
+#define        XPC_C_OPENREPLY         0x00000004 /* local open channel reply 
*/
+#define        XPC_C_ROPENREQUEST      0x00000008 /* remote open channel 
request */
+#define        XPC_C_OPENREQUEST       0x00000010 /* local open channel 
request */
+
+#define        XPC_C_SETUP             0x00000020 /* channel's msgqueues are 
alloc'd */
+#define        XPC_C_CONNECTCALLOUT    0x00000040 /* channel connected callout 
made */
+#define        XPC_C_CONNECTED         0x00000080 /* local channel is 
connected */
+#define        XPC_C_CONNECTING        0x00000100 /* channel is being 
connected */
+
+#define        XPC_C_RCLOSEREPLY       0x00000200 /* remote close channel 
reply */
+#define        XPC_C_CLOSEREPLY        0x00000400 /* local close channel reply 
*/
+#define        XPC_C_RCLOSEREQUEST     0x00000800 /* remote close channel 
request */
+#define        XPC_C_CLOSEREQUEST      0x00001000 /* local close channel 
request */
+
+#define        XPC_C_DISCONNECTED      0x00002000 /* channel is disconnected */
+#define        XPC_C_DISCONNECTING     0x00004000 /* channel is being 
disconnected */
+
+
+
+/*
+ * Manages channels on a partition basis. There is one of these structures
+ * for each partition (a partition will never utilize the structure that
+ * represents itself).
+ */
+struct xpc_partition {
+
+       /* XPC HB infrastructure */
+
+       u64 remote_rp_pa;               /* phys addr of partition's rsvd pg */
+       u64 remote_vars_pa;             /* phys addr of partition's vars */
+       u64 remote_vars_part_pa;        /* phys addr of partition's vars part */
+       u64 last_heartbeat;             /* HB at last read */
+       u64 remote_amos_page_pa;        /* phys addr of partition's amos page */
+       int remote_act_nasid;           /* active part's act/deact nasid */
+       int remote_act_phys_cpuid;      /* active part's act/deact phys cpuid */
+       u32 act_IRQ_rcvd;               /* IRQs since activation */
+       spinlock_t act_lock;            /* protect updating of act_state */
+       u8 act_state;                   /* from XPC HB viewpoint */
+       enum xpc_retval reason;         /* reason partition is deactivating */
+       int reason_line;                /* line# deactivation initiated from */
+       int reactivate_nasid;           /* nasid in partition to reactivate */
+
+
+       /* XPC infrastructure referencing and teardown control */
+
+       u8 setup_state;                 /* infrastructure setup state */
+       wait_queue_head_t teardown_wq;  /* kthread waiting to teardown infra */
+       atomic_t references;            /* #of references to infrastructure */
+
+
+       /*
+        * NONE OF THE PRECEDING FIELDS OF THIS STRUCTURE WILL BE CLEARED WHEN
+        * XPC SETS UP THE NECESSARY INFRASTRUCTURE TO SUPPORT CROSS PARTITION
+        * COMMUNICATION. ALL OF THE FOLLOWING FIELDS WILL BE CLEARED. (THE
+        * 'nchannels' FIELD MUST BE THE FIRST OF THE FIELDS TO BE CLEARED.)
+        */
+
+
+       u8 nchannels;              /* #of defined channels supported */
+       atomic_t nchannels_active; /* #of channels that are not DISCONNECTED */
+       struct xpc_channel *channels;/* array of channel structures */
+
+       void *local_GPs_base;     /* base address of kmalloc'd space */
+       struct xpc_gp *local_GPs; /* local Get/Put values */
+       void *remote_GPs_base;    /* base address of kmalloc'd space */
+       struct xpc_gp *remote_GPs;/* copy of remote partition's local Get/Put */
+                                 /* values */
+       u64 remote_GPs_pa;        /* phys address of remote partition's local */
+                                 /* Get/Put values */
+
+
+       /* fields used to pass args when opening or closing a channel */
+
+       void *local_openclose_args_base;  /* base address of kmalloc'd space */
+       struct xpc_openclose_args *local_openclose_args;  /* local's args */
+       void *remote_openclose_args_base; /* base address of kmalloc'd space */
+       struct xpc_openclose_args *remote_openclose_args; /* copy of remote's */
+                                         /* args */
+       u64 remote_openclose_args_pa;     /* phys addr of remote's args */
+
+
+       /* IPI sending, receiving and handling related fields */
+
+       int remote_IPI_nasid;       /* nasid of where to send IPIs */
+       int remote_IPI_phys_cpuid;  /* phys CPU ID of where to send IPIs */
+       AMO_t *remote_IPI_amo_va;   /* address of remote IPI AMO_t structure */
+
+       AMO_t *local_IPI_amo_va;    /* address of IPI AMO_t structure */
+       u64 local_IPI_amo;          /* IPI amo flags yet to be handled */
+       char IPI_owner[8];          /* IPI owner's name */
+       struct timer_list dropped_IPI_timer; /* dropped IPI timer */
+
+       spinlock_t IPI_lock;        /* IPI handler lock */
+
+
+       /* channel manager related fields */
+
+       atomic_t channel_mgr_requests;  /* #of requests to activate chan mgr */
+       wait_queue_head_t channel_mgr_wq; /* channel mgr's wait queue */
+
+} ____cacheline_aligned;
+
+
+/* struct xpc_partition act_state values (for XPC HB) */
+
+#define        XPC_P_INACTIVE          0x00    /* partition is not active */
+#define XPC_P_ACTIVATION_REQ   0x01    /* created thread to activate */
+#define XPC_P_ACTIVATING       0x02    /* activation thread started */
+#define XPC_P_ACTIVE           0x03    /* xpc_partition_up() was called */
+#define XPC_P_DEACTIVATING     0x04    /* partition deactivation initiated */
+
+
+#define XPC_DEACTIVATE_PARTITION(_p, _reason) \
+                       xpc_deactivate_partition(__LINE__, (_p), (_reason))
+
+
+/* struct xpc_partition setup_state values */
+
+#define XPC_P_UNSET            0x00    /* infrastructure was never setup */
+#define XPC_P_SETUP            0x01    /* infrastructure is setup */
+#define XPC_P_WTEARDOWN                0x02    /* waiting to teardown 
infrastructure */
+#define XPC_P_TORNDOWN         0x03    /* infrastructure is torndown */
+
+
+/*
+ * struct xpc_partition IPI_timer #of seconds to wait before checking for
+ * dropped IPIs. These occur whenever an IPI amo write doesn't complete until
+ * after the IPI was received.
+ */
+#define XPC_P_DROPPED_IPI_WAIT (0.25 * HZ)
+
+
+#define XPC_PARTID(_p) ((partid_t) ((_p) - &xpc_partitions[0]))
+
+
+
+/* found in xp_main.c */
+extern struct xpc_registration xpc_registrations[];
+
+
+/* >>> found in xpc_main.c only */
+extern struct device *xpc_part;
+extern struct device *xpc_chan;
+extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *);
+extern void xpc_dropped_IPI_check(struct xpc_partition *);
+extern void xpc_activate_kthreads(struct xpc_channel *, int);
+extern void xpc_create_kthreads(struct xpc_channel *, int);
+extern void xpc_disconnect_wait(int);
+
+
+/* found in xpc_main.c and efi-xpc.c */
+extern void xpc_activate_partition(struct xpc_partition *);
+
+
+/* found in xpc_partition.c */
+extern int xpc_exiting;
+extern int xpc_hb_interval;
+extern int xpc_hb_check_interval;
+extern struct xpc_vars *xpc_vars;
+extern struct xpc_rsvd_page *xpc_rsvd_page;
+extern struct xpc_vars_part *xpc_vars_part;
+extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
+extern char xpc_remote_copy_buffer[];
+extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
+extern void xpc_allow_IPI_ops(void);
+extern void xpc_restrict_IPI_ops(void);
+extern int xpc_identify_act_IRQ_sender(void);
+extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *);
+extern void xpc_mark_partition_inactive(struct xpc_partition *);
+extern void xpc_discovery(void);
+extern void xpc_check_remote_hb(void);
+extern void xpc_deactivate_partition(const int, struct xpc_partition *,
+                                               enum xpc_retval);
+extern enum xpc_retval xpc_initiate_partid_to_nasids(partid_t, void *);
+
+
+/* found in xpc_channel.c */
+extern void xpc_initiate_connect(int);
+extern void xpc_initiate_disconnect(int);
+extern enum xpc_retval xpc_initiate_allocate(partid_t, int, u32, void **);
+extern enum xpc_retval xpc_initiate_send(partid_t, int, void *);
+extern enum xpc_retval xpc_initiate_send_notify(partid_t, int, void *,
+                                               xpc_notify_func, void *);
+extern void xpc_initiate_received(partid_t, int, void *);
+extern enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *);
+extern enum xpc_retval xpc_pull_remote_vars_part(struct xpc_partition *);
+extern void xpc_process_channel_activity(struct xpc_partition *);
+extern void xpc_connected_callout(struct xpc_channel *);
+extern void xpc_deliver_msg(struct xpc_channel *);
+extern void xpc_disconnect_channel(const int, struct xpc_channel *,
+                                       enum xpc_retval, unsigned long *);
+extern void xpc_disconnected_callout(struct xpc_channel *);
+extern void xpc_partition_down(struct xpc_partition *, enum xpc_retval);
+extern void xpc_teardown_infrastructure(struct xpc_partition *);
+
+
+
+static inline void
+xpc_wakeup_channel_mgr(struct xpc_partition *part)
+{
+       if (atomic_inc_return(&part->channel_mgr_requests) == 1) {
+               wake_up(&part->channel_mgr_wq);
+       }
+}
+
+
+
+/*
+ * These next two inlines are used to keep us from tearing down a channel's
+ * msg queues while a thread may be referencing them.
+ */
+static inline void
+xpc_msgqueue_ref(struct xpc_channel *ch)
+{
+       atomic_inc(&ch->references);
+}
+
+static inline void
+xpc_msgqueue_deref(struct xpc_channel *ch)
+{
+       s32 refs = atomic_dec_return(&ch->references);
+
+       DBUG_ON(refs < 0);
+       if (refs == 0) {
+               xpc_wakeup_channel_mgr(&xpc_partitions[ch->partid]);
+       }
+}
+
+
+
+#define XPC_DISCONNECT_CHANNEL(_ch, _reason, _irqflgs) \
+               xpc_disconnect_channel(__LINE__, _ch, _reason, _irqflgs)
+
+
+/*
+ * These two inlines are used to keep us from tearing down a partition's
+ * setup infrastructure while a thread may be referencing it.
+ */
+static inline void
+xpc_part_deref(struct xpc_partition *part)
+{
+       s32 refs = atomic_dec_return(&part->references);
+
+
+       DBUG_ON(refs < 0);
+       if (refs == 0 && part->setup_state == XPC_P_WTEARDOWN) {
+               wake_up(&part->teardown_wq);
+       }
+}
+
+static inline int
+xpc_part_ref(struct xpc_partition *part)
+{
+       int setup;
+
+
+       atomic_inc(&part->references);
+       setup = (part->setup_state == XPC_P_SETUP);
+       if (!setup) {
+               xpc_part_deref(part);
+       }
+       return setup;
+}
+
+
+
+/*
+ * The following macro is to be used for the setting of the reason and
+ * reason_line fields in both the struct xpc_channel and struct xpc_partition
+ * structures.
+ */
+#define XPC_SET_REASON(_p, _reason, _line) \
+       { \
+               (_p)->reason = _reason; \
+               (_p)->reason_line = _line; \
+       }
+
+
+
+/*
+ * The following set of macros and inlines are used for the sending and
+ * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
+ * one that is associated with partition activity (SGI_XPC_ACTIVATE) and
+ * the other that is associated with channel activity (SGI_XPC_NOTIFY).
+ */
+
+static inline u64
+xpc_IPI_receive(AMO_t *amo)
+{
+       return FETCHOP_LOAD_OP(TO_AMO((u64) &amo->variable), FETCHOP_CLEAR);
+}
+
+
+static inline enum xpc_retval
+xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)
+{
+       int ret = 0;
+       unsigned long irq_flags;
+
+
+       local_irq_save(irq_flags);
+
+       FETCHOP_STORE_OP(TO_AMO((u64) &amo->variable), FETCHOP_OR, flag);
+       sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
+
+       /*
+        * We must always use the nofault function regardless of whether we
+        * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
+        * didn't, we'd never know that the other partition is down and would
+        * keep sending IPIs and AMOs to it until the heartbeat times out.
+        */
+       ret = xp_nofault_PIOR((u64 *) GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
+                               xp_nofault_PIOR_target));
+
+       local_irq_restore(irq_flags);
+
+       return ((ret == 0) ? xpcSuccess : xpcPioReadError);
+}
+
+
+/*
+ * IPIs associated with SGI_XPC_ACTIVATE IRQ.
+ */
+
+/*
+ * Flag the appropriate AMO variable and send an IPI to the specified node.
+ */
+static inline void
+xpc_activate_IRQ_send(u64 amos_page, int from_nasid, int to_nasid,
+                       int to_phys_cpuid)
+{
+       int w_index = XPC_NASID_W_INDEX(from_nasid);
+       int b_index = XPC_NASID_B_INDEX(from_nasid);
+       AMO_t *amos = (AMO_t *) __va(amos_page +
+                                       (XP_MAX_PARTITIONS * sizeof(AMO_t)));
+
+
+       (void) xpc_IPI_send(&amos[w_index], (1UL << b_index), to_nasid,
+                               to_phys_cpuid, SGI_XPC_ACTIVATE);
+}
+
+static inline void
+xpc_IPI_send_activate(struct xpc_vars *vars)
+{
+       xpc_activate_IRQ_send(vars->amos_page_pa, cnodeid_to_nasid(0),
+                               vars->act_nasid, vars->act_phys_cpuid);
+}
+
+static inline void
+xpc_IPI_send_activated(struct xpc_partition *part)
+{
+       xpc_activate_IRQ_send(part->remote_amos_page_pa, cnodeid_to_nasid(0),
+                       part->remote_act_nasid, part->remote_act_phys_cpuid);
+}
+
+static inline void
+xpc_IPI_send_reactivate(struct xpc_partition *part)
+{
+       xpc_activate_IRQ_send(xpc_vars->amos_page_pa, part->reactivate_nasid,
+                               xpc_vars->act_nasid, xpc_vars->act_phys_cpuid);
+}
+
+
+/*
+ * IPIs associated with SGI_XPC_NOTIFY IRQ.
+ */
+
+/*
+ * Send an IPI to the remote partition that is associated with the
+ * specified channel.
+ */
+#define XPC_NOTIFY_IRQ_SEND(_ch, _ipi_f, _irq_f) \
+               xpc_notify_IRQ_send(_ch, _ipi_f, #_ipi_f, _irq_f)
+
+static inline void
+xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string,
+                       unsigned long *irq_flags)
+{
+       struct xpc_partition *part = &xpc_partitions[ch->partid];
+       enum xpc_retval ret;
+
+
+       if (likely(part->act_state != XPC_P_DEACTIVATING)) {
+               ret = xpc_IPI_send(part->remote_IPI_amo_va,
+                                       (u64) ipi_flag << (ch->number * 8),
+                                       part->remote_IPI_nasid,
+                                       part->remote_IPI_phys_cpuid,
+                                       SGI_XPC_NOTIFY);
+               dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
+                       ipi_flag_string, ch->partid, ch->number, ret);
+               if (unlikely(ret != xpcSuccess)) {
+                       if (irq_flags != NULL) {
+                               spin_unlock_irqrestore(&ch->lock, *irq_flags);
+                       }
+                       XPC_DEACTIVATE_PARTITION(part, ret);
+                       if (irq_flags != NULL) {
+                               spin_lock_irqsave(&ch->lock, *irq_flags);
+                       }
+               }
+       }
+}
+
+
+/*
+ * Make it look like the remote partition, which is associated with the
+ * specified channel, sent us an IPI. This faked IPI will be handled
+ * by xpc_dropped_IPI_check().
+ */
+#define XPC_NOTIFY_IRQ_SEND_LOCAL(_ch, _ipi_f) \
+               xpc_notify_IRQ_send_local(_ch, _ipi_f, #_ipi_f)
+
+static inline void
+xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag,
+                               char *ipi_flag_string)
+{
+       struct xpc_partition *part = &xpc_partitions[ch->partid];
+
+
+       FETCHOP_STORE_OP(TO_AMO((u64) &part->local_IPI_amo_va->variable),
+                       FETCHOP_OR, ((u64) ipi_flag << (ch->number * 8)));
+       dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
+               ipi_flag_string, ch->partid, ch->number);
+}
+
+
+/*
+ * The sending and receiving of IPIs includes the setting of an AMO variable
+ * to indicate the reason the IPI was sent. The 64-bit variable is divided
+ * up into eight bytes, ordered from right to left. Byte zero pertains to
+ * channel 0, byte one to channel 1, and so on. Each byte is described by
+ * the following IPI flags.
+ */
+
+#define        XPC_IPI_CLOSEREQUEST    0x01
+#define        XPC_IPI_CLOSEREPLY      0x02
+#define        XPC_IPI_OPENREQUEST     0x04
+#define        XPC_IPI_OPENREPLY       0x08
+#define        XPC_IPI_MSGREQUEST      0x10
+
+
+/* given an AMO variable and a channel#, get its associated IPI flags */
+#define XPC_GET_IPI_FLAGS(_amo, _c)    ((u8) (((_amo) >> ((_c) * 8)) & 0xff))
+
+#define        XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 
0x0f0f0f0f0f0f0f0f)
+#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & 0x1010101010101010)
+
+
+static inline void
+xpc_IPI_send_closerequest(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+       struct xpc_openclose_args *args = ch->local_openclose_args;
+
+
+       args->reason = ch->reason;
+
+       XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREQUEST, irq_flags);
+}
+
+static inline void
+xpc_IPI_send_closereply(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+       XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_CLOSEREPLY, irq_flags);
+}
+
+static inline void
+xpc_IPI_send_openrequest(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+       struct xpc_openclose_args *args = ch->local_openclose_args;
+
+
+       args->msg_size = ch->msg_size;
+       args->local_nentries = ch->local_nentries;
+
+       XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREQUEST, irq_flags);
+}
+
+static inline void
+xpc_IPI_send_openreply(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+       struct xpc_openclose_args *args = ch->local_openclose_args;
+
+
+       args->remote_nentries = ch->remote_nentries;
+       args->local_nentries = ch->local_nentries;
+       args->local_msgqueue_pa = __pa(ch->local_msgqueue);
+
+       XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_OPENREPLY, irq_flags);
+}
+
+static inline void
+xpc_IPI_send_msgrequest(struct xpc_channel *ch)
+{
+       XPC_NOTIFY_IRQ_SEND(ch, XPC_IPI_MSGREQUEST, NULL);
+}
+
+static inline void
+xpc_IPI_send_local_msgrequest(struct xpc_channel *ch)
+{
+       XPC_NOTIFY_IRQ_SEND_LOCAL(ch, XPC_IPI_MSGREQUEST);
+}
+
+
+/*
+ * Memory for XPC's AMO variables is allocated by the MSPEC driver. These
+ * pages are located in the lowest granule. The lowest granule uses 4k pages
+ * for cached references and an alternate TLB handler to never provide a
+ * cacheable mapping for the entire region. This will prevent speculative
+ * reading of cached copies of our lines from being issued which will cause
+ * a PI FSB Protocol error to be generated by the SHUB. For XPC, we need 64
+ * (XP_MAX_PARTITIONS) AMO variables for message notification (xpc_main.c)
+ * and an additional 16 AMO variables for partition activation (xpc_hb.c).
+ */
+static inline AMO_t *
+xpc_IPI_init(partid_t partid)
+{
+       AMO_t *part_amo = xpc_vars->amos_page + partid;
+
+
+       xpc_IPI_receive(part_amo);
+       return part_amo;
+}
+
+
+
+static inline enum xpc_retval
+xpc_map_bte_errors(bte_result_t error)
+{
+       switch (error) {
+       case BTE_SUCCESS:       return xpcSuccess;
+       case BTEFAIL_DIR:       return xpcBteDirectoryError;
+       case BTEFAIL_POISON:    return xpcBtePoisonError;
+       case BTEFAIL_WERR:      return xpcBteWriteError;
+       case BTEFAIL_ACCESS:    return xpcBteAccessError;
+       case BTEFAIL_PWERR:     return xpcBtePWriteError;
+       case BTEFAIL_PRERR:     return xpcBtePReadError;
+       case BTEFAIL_TOUT:      return xpcBteTimeOutError;
+       case BTEFAIL_XTERR:     return xpcBteXtalkError;
+       case BTEFAIL_NOTAVAIL:  return xpcBteNotAvailable;
+       default:                return xpcBteUnmappedError;
+       }
+}
+
+
+
+static inline void *
+xpc_kmalloc_cacheline_aligned(size_t size, int flags, void **base)
+{
+       /* see if kmalloc will give us cachline aligned memory by default */
+       *base = kmalloc(size, flags);
+       if (*base == NULL) {
+               return NULL;
+       }
+       if ((u64) *base == L1_CACHE_ALIGN((u64) *base)) {
+               return *base;
+       }
+       kfree(*base);
+
+       /* nope, we'll have to do it ourselves */
+       *base = kmalloc(size + L1_CACHE_BYTES, flags);
+       if (*base == NULL) {
+               return NULL;
+       }
+       return (void *) L1_CACHE_ALIGN((u64) *base);
+}
+
+
+/*
+ * Check to see if there is any channel activity to/from the specified
+ * partition.
+ */
+static inline void
+xpc_check_for_channel_activity(struct xpc_partition *part)
+{
+       u64 IPI_amo;
+       unsigned long irq_flags;
+
+
+       IPI_amo = xpc_IPI_receive(part->local_IPI_amo_va);
+       if (IPI_amo == 0) {
+               return;
+       }
+
+       spin_lock_irqsave(&part->IPI_lock, irq_flags);
+       part->local_IPI_amo |= IPI_amo;
+       spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
+
+       dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n",
+               XPC_PARTID(part), IPI_amo);
+
+       xpc_wakeup_channel_mgr(part);
+}
+
+
+#endif /* _IA64_SN_KERNEL_XPC_H */
+
diff -urN linux/arch/ia64/sn/kernel/xpc_channel.c 
linux/arch/ia64/sn/kernel/xpc_channel.c
--- linux/arch/ia64/sn/kernel/xpc_channel.c     1970/01/01 00:00:00
+++ linux/arch/ia64/sn/kernel/xpc_channel.c     2005-05-19 13:08:10.762761000 
+0100     1.1
@@ -0,0 +1,2297 @@
+/*
+ * 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-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition Communication (XPC) channel support.
+ *
+ *     This is the part of XPC that manages the channels and
+ *     sends/receives messages across them to/from other partitions.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/cache.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <asm/sn/bte.h>
+#include <asm/sn/sn_sal.h>
+#include "xpc.h"
+
+
+/*
+ * Set up the initial values for the XPartition Communication channels.
+ */
+static void
+xpc_initialize_channels(struct xpc_partition *part, partid_t partid)
+{
+       int ch_number;
+       struct xpc_channel *ch;
+
+
+       for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+               ch = &part->channels[ch_number];
+
+               ch->partid = partid;
+               ch->number = ch_number;
+               ch->flags = XPC_C_DISCONNECTED;
+
+               ch->local_GP = &part->local_GPs[ch_number];
+               ch->local_openclose_args =
+                                       &part->local_openclose_args[ch_number];
+
+               atomic_set(&ch->kthreads_assigned, 0);
+               atomic_set(&ch->kthreads_idle, 0);
+               atomic_set(&ch->kthreads_active, 0);
+
+               atomic_set(&ch->references, 0);
+               atomic_set(&ch->n_to_notify, 0);
+
+               spin_lock_init(&ch->lock);
+               sema_init(&ch->msg_to_pull_sema, 1);    /* mutex */
+
+               atomic_set(&ch->n_on_msg_allocate_wq, 0);
+               init_waitqueue_head(&ch->msg_allocate_wq);
+               init_waitqueue_head(&ch->idle_wq);
+       }
+}
+
+
+/*
+ * Setup the infrastructure necessary to support XPartition Communication
+ * between the specified remote partition and the local one.
+ */
+enum xpc_retval
+xpc_setup_infrastructure(struct xpc_partition *part)
+{
+       int ret;
+       struct timer_list *timer;
+       partid_t partid = XPC_PARTID(part);
+
+
+       /*
+        * Zero out MOST of the entry for this partition. Only the fields
+        * starting with `nchannels' will be zeroed. The preceding fields must
+        * remain `viable' across partition ups and downs, since they may be
+        * referenced during this memset() operation.
+        */
+       memset(&part->nchannels, 0, sizeof(struct xpc_partition) -
+                               offsetof(struct xpc_partition, nchannels));
+
+       /*
+        * Allocate all of the channel structures as a contiguous chunk of
+        * memory.
+        */
+       part->channels = kmalloc(sizeof(struct xpc_channel) * XPC_NCHANNELS,
+                                                               GFP_KERNEL);
+       if (part->channels == NULL) {
+               dev_err(xpc_chan, "can't get memory for channels\n");
+               return xpcNoMemory;
+       }
+       memset(part->channels, 0, sizeof(struct xpc_channel) * XPC_NCHANNELS);
+
+       part->nchannels = XPC_NCHANNELS;
+
+
+       /* allocate all the required GET/PUT values */
+
+       part->local_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE,
+                                       GFP_KERNEL, &part->local_GPs_base);
+       if (part->local_GPs == NULL) {
+               kfree(part->channels);
+               part->channels = NULL;
+               dev_err(xpc_chan, "can't get memory for local get/put "
+                       "values\n");
+               return xpcNoMemory;
+       }
+       memset(part->local_GPs, 0, XPC_GP_SIZE);
+
+       part->remote_GPs = xpc_kmalloc_cacheline_aligned(XPC_GP_SIZE,
+                                       GFP_KERNEL, &part->remote_GPs_base);
+       if (part->remote_GPs == NULL) {
+               kfree(part->channels);
+               part->channels = NULL;
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               dev_err(xpc_chan, "can't get memory for remote get/put "
+                       "values\n");
+               return xpcNoMemory;
+       }
+       memset(part->remote_GPs, 0, XPC_GP_SIZE);
+
+
+       /* allocate all the required open and close args */
+
+       part->local_openclose_args = xpc_kmalloc_cacheline_aligned(
+                                       XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
+                                       &part->local_openclose_args_base);
+       if (part->local_openclose_args == NULL) {
+               kfree(part->channels);
+               part->channels = NULL;
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->remote_GPs_base);
+               part->remote_GPs = NULL;
+               dev_err(xpc_chan, "can't get memory for local connect args\n");
+               return xpcNoMemory;
+       }
+       memset(part->local_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);
+
+       part->remote_openclose_args = xpc_kmalloc_cacheline_aligned(
+                                       XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
+                                       &part->remote_openclose_args_base);
+       if (part->remote_openclose_args == NULL) {
+               kfree(part->channels);
+               part->channels = NULL;
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->remote_GPs_base);
+               part->remote_GPs = NULL;
+               kfree(part->local_openclose_args_base);
+               part->local_openclose_args = NULL;
+               dev_err(xpc_chan, "can't get memory for remote connect args\n");
+               return xpcNoMemory;
+       }
+       memset(part->remote_openclose_args, 0, XPC_OPENCLOSE_ARGS_SIZE);
+
+
+       xpc_initialize_channels(part, partid);
+
+       atomic_set(&part->nchannels_active, 0);
+
+
+       /* local_IPI_amo were set to 0 by an earlier memset() */
+
+       /* Initialize this partitions AMO_t structure */
+       part->local_IPI_amo_va = xpc_IPI_init(partid);
+
+       spin_lock_init(&part->IPI_lock);
+
+       atomic_set(&part->channel_mgr_requests, 1);
+       init_waitqueue_head(&part->channel_mgr_wq);
+
+       sprintf(part->IPI_owner, "xpc%02d", partid);
+       ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, SA_SHIRQ,
+                               part->IPI_owner, (void *) (u64) partid);
+       if (ret != 0) {
+               kfree(part->channels);
+               part->channels = NULL;
+               kfree(part->local_GPs_base);
+               part->local_GPs = NULL;
+               kfree(part->remote_GPs_base);
+               part->remote_GPs = NULL;
+               kfree(part->local_openclose_args_base);
+               part->local_openclose_args = NULL;
+               kfree(part->remote_openclose_args_base);
+               part->remote_openclose_args = NULL;
+               dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
+                       "errno=%d\n", -ret);
+               return xpcLackOfResources;
+       }
+
+       /* Setup a timer to check for dropped IPIs */
+       timer = &part->dropped_IPI_timer;
+       init_timer(timer);
+       timer->function = (void (*)(unsigned long)) xpc_dropped_IPI_check;
+       timer->data = (unsigned long) part;
+       timer->expires = jiffies + XPC_P_DROPPED_IPI_WAIT;
+       add_timer(timer);
+
+       /*
+        * With the setting of the partition setup_state to XPC_P_SETUP, we're
+        * declaring that this partition is ready to go.
+        */
+       (volatile u8) part->setup_state = XPC_P_SETUP;
+
+
+       /*
+        * Setup the per partition specific variables required by the
+        * remote partition to establish channel connections with us.
+        *
+        * The setting of the magic # indicates that these per partition
+        * specific variables are ready to be used.
+        */
+       xpc_vars_part[partid].GPs_pa = __pa(part->local_GPs);
+       xpc_vars_part[partid].openclose_args_pa =
+                                       __pa(part->local_openclose_args);
+       xpc_vars_part[partid].IPI_amo_pa = __pa(part->local_IPI_amo_va);
+       xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(smp_processor_id());
+       xpc_vars_part[partid].IPI_phys_cpuid =
+                                       cpu_physical_id(smp_processor_id());
+       xpc_vars_part[partid].nchannels = part->nchannels;
+       (volatile u64) xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
+
+       return xpcSuccess;
+}
+
+
+/*
+ * Create a wrapper that hides the underlying mechanism for pulling a cacheline
+ * (or multiple cachelines) from a remote partition.
+ *
+ * src must be a cacheline aligned physical address on the remote partition.
+ * dst must be a cacheline aligned virtual address on this partition.
+ * cnt must be an cacheline sized
+ */
+static enum xpc_retval
+xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst,
+                               const void *src, size_t cnt)
+{
+       bte_result_t bte_ret;
+
+
+       DBUG_ON((u64) src != L1_CACHE_ALIGN((u64) src));
+       DBUG_ON((u64) dst != L1_CACHE_ALIGN((u64) dst));
+       DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));
+
+       if (part->act_state == XPC_P_DEACTIVATING) {
+               return part->reason;
+       }
+
+       bte_ret = xp_bte_copy((u64) src, (u64) ia64_tpa((u64) dst),
+                               (u64) cnt, (BTE_NORMAL | BTE_WACQUIRE), NULL);
+       if (bte_ret == BTE_SUCCESS) {
+               return xpcSuccess;
+       }
+
+       dev_dbg(xpc_chan, "xp_bte_copy() from partition %d failed, ret=%d\n",
+               XPC_PARTID(part), bte_ret);
+
+       return xpc_map_bte_errors(bte_ret);
+}
+
+
+/*
+ * Pull the remote per partititon specific variables from the specified
+ * partition.
+ */
+enum xpc_retval
+xpc_pull_remote_vars_part(struct xpc_partition *part)
+{
+       u8 buffer[L1_CACHE_BYTES * 2];
+       struct xpc_vars_part *pulled_entry_cacheline =
+                       (struct xpc_vars_part *) L1_CACHE_ALIGN((u64) buffer);
+       struct xpc_vars_part *pulled_entry;
+       u64 remote_entry_cacheline_pa, remote_entry_pa;
+       partid_t partid = XPC_PARTID(part);
+       enum xpc_retval ret;
+
+
+       /* pull the cacheline that contains the variables we're interested in */
+
+       DBUG_ON(part->remote_vars_part_pa !=
+                               L1_CACHE_ALIGN(part->remote_vars_part_pa));
+       DBUG_ON(sizeof(struct xpc_vars_part) != L1_CACHE_BYTES / 2);
+
+       remote_entry_pa = part->remote_vars_part_pa +
+                       sn_partition_id * sizeof(struct xpc_vars_part);
+
+       remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
+
+       pulled_entry = (struct xpc_vars_part *) ((u64) pulled_entry_cacheline +
+                               (remote_entry_pa & (L1_CACHE_BYTES - 1)));
+
+       ret = xpc_pull_remote_cachelines(part, pulled_entry_cacheline,
+                                       (void *) remote_entry_cacheline_pa,
+                                       L1_CACHE_BYTES);
+       if (ret != xpcSuccess) {
+               dev_dbg(xpc_chan, "failed to pull XPC vars_part from "
+                       "partition %d, ret=%d\n", partid, ret);
+               return ret;
+       }
+
+
+       /* see if they've been set up yet */
+
+       if (pulled_entry->magic != XPC_VP_MAGIC1 &&
+                               pulled_entry->magic != XPC_VP_MAGIC2) {
+
+               if (pulled_entry->magic != 0) {
+                       dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
+                               "partition %d has bad magic value (=0x%lx)\n",
+                               partid, sn_partition_id, pulled_entry->magic);
+                       return xpcBadMagic;
+               }
+
+               /* they've not been initialized yet */
+               return xpcRetry;
+       }
+
+       if (xpc_vars_part[partid].magic == XPC_VP_MAGIC1) {
+
+               /* validate the variables */
+
+               if (pulled_entry->GPs_pa == 0 ||
+                               pulled_entry->openclose_args_pa == 0 ||
+                                       pulled_entry->IPI_amo_pa == 0) {
+
+                       dev_err(xpc_chan, "partition %d's XPC vars_part for "
+                               "partition %d are not valid\n", partid,
+                               sn_partition_id);
+                       return xpcInvalidAddress;
+               }
+
+               /* the variables we imported look to be valid */
+
+               part->remote_GPs_pa = pulled_entry->GPs_pa;
+               part->remote_openclose_args_pa =
+                                       pulled_entry->openclose_args_pa;
+               part->remote_IPI_amo_va =
+                                     (AMO_t *) __va(pulled_entry->IPI_amo_pa);
+               part->remote_IPI_nasid = pulled_entry->IPI_nasid;
+               part->remote_IPI_phys_cpuid = pulled_entry->IPI_phys_cpuid;
+
+               if (part->nchannels > pulled_entry->nchannels) {
+                       part->nchannels = pulled_entry->nchannels;
+               }
+
+               /* let the other side know that we've pulled their variables */
+
+               (volatile u64) xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
+       }
+
+       if (pulled_entry->magic == XPC_VP_MAGIC1) {
+               return xpcRetry;
+       }
+
+       return xpcSuccess;
+}
+
+
+/*
+ * Get the IPI flags and pull the openclose args and/or remote GPs as needed.
+ */
+static u64
+xpc_get_IPI_flags(struct xpc_partition *part)
+{
+       unsigned long irq_flags;
+       u64 IPI_amo;
+       enum xpc_retval ret;
+
+
+       /*
+        * See if there are any IPI flags to be handled.
+        */
+
+       spin_lock_irqsave(&part->IPI_lock, irq_flags);
+       if ((IPI_amo = part->local_IPI_amo) != 0) {
+               part->local_IPI_amo = 0;
+       }
+       spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
+
+
+       if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_amo)) {
+               ret = xpc_pull_remote_cachelines(part,
+                                       part->remote_openclose_args,
+                                       (void *) part->remote_openclose_args_pa,
+                                       XPC_OPENCLOSE_ARGS_SIZE);
+               if (ret != xpcSuccess) {
+                       XPC_DEACTIVATE_PARTITION(part, ret);
+
+                       dev_dbg(xpc_chan, "failed to pull openclose args from "
+                               "partition %d, ret=%d\n", XPC_PARTID(part),
+                               ret);
+
+                       /* don't bother processing IPIs anymore */
+                       IPI_amo = 0;
+               }
+       }
+
+       if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_amo)) {
+               ret = xpc_pull_remote_cachelines(part, part->remote_GPs,
+                                               (void *) part->remote_GPs_pa,
+                                               XPC_GP_SIZE);
+               if (ret != xpcSuccess) {
+                       XPC_DEACTIVATE_PARTITION(part, ret);
+
+                       dev_dbg(xpc_chan, "failed to pull GPs from partition "
+                               "%d, ret=%d\n", XPC_PARTID(part), ret);
+
+                       /* don't bother processing IPIs anymore */
+                       IPI_amo = 0;
+               }
+       }
+
+       return IPI_amo;
+}
+
+
+/*
+ * Allocate the local message queue and the notify queue.
+ */
+static enum xpc_retval
+xpc_allocate_local_msgqueue(struct xpc_channel *ch)
+{
+       unsigned long irq_flags;
+       int nentries;
+       size_t nbytes;
+
+
+       // >>> may want to check for ch->flags & XPC_C_DISCONNECTING between
+       // >>> iterations of the for-loop, bail if set?
+
+       // >>> should we impose a minumum #of entries? like 4 or 8?
+       for (nentries = ch->local_nentries; nentries > 0; nentries--) {
+
+               nbytes = nentries * ch->msg_size;
+               ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
+                                               (GFP_KERNEL | GFP_DMA),
+                                               &ch->local_msgqueue_base);
+               if (ch->local_msgqueue == NULL) {
+                       continue;
+               }
+               memset(ch->local_msgqueue, 0, nbytes);
+
+               nbytes = nentries * sizeof(struct xpc_notify);
+               ch->notify_queue = kmalloc(nbytes, (GFP_KERNEL | GFP_DMA));
+               if (ch->notify_queue == NULL) {
+                       kfree(ch->local_msgqueue_base);
+                       ch->local_msgqueue = NULL;
+                       continue;
+               }
+               memset(ch->notify_queue, 0, nbytes);
+
+               spin_lock_irqsave(&ch->lock, irq_flags);
+               if (nentries < ch->local_nentries) {
+                       dev_dbg(xpc_chan, "nentries=%d local_nentries=%d, "
+                               "partid=%d, channel=%d\n", nentries,
+                               ch->local_nentries, ch->partid, ch->number);
+
+                       ch->local_nentries = nentries;
+               }
+               spin_unlock_irqrestore(&ch->lock, irq_flags);
+               return xpcSuccess;
+       }
+
+       dev_dbg(xpc_chan, "can't get memory for local message queue and notify "
+               "queue, partid=%d, channel=%d\n", ch->partid, ch->number);
+       return xpcNoMemory;
+}
+
+
+/*
+ * Allocate the cached remote message queue.
+ */
+static enum xpc_retval
+xpc_allocate_remote_msgqueue(struct xpc_channel *ch)
+{
+       unsigned long irq_flags;
+       int nentries;
+       size_t nbytes;
+
+
+       DBUG_ON(ch->remote_nentries <= 0);
+
+       // >>> may want to check for ch->flags & XPC_C_DISCONNECTING between
+       // >>> iterations of the for-loop, bail if set?
+
+       // >>> should we impose a minumum #of entries? like 4 or 8?
+       for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
+
+               nbytes = nentries * ch->msg_size;
+               ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes,
+                                               (GFP_KERNEL | GFP_DMA),
+                                               &ch->remote_msgqueue_base);
+               if (ch->remote_msgqueue == NULL) {
+                       continue;
+               }
+               memset(ch->remote_msgqueue, 0, nbytes);
+
+               spin_lock_irqsave(&ch->lock, irq_flags);
+               if (nentries < ch->remote_nentries) {
+                       dev_dbg(xpc_chan, "nentries=%d remote_nentries=%d, "
+                               "partid=%d, channel=%d\n", nentries,
+                               ch->remote_nentries, ch->partid, ch->number);
+
+                       ch->remote_nentries = nentries;
+               }
+               spin_unlock_irqrestore(&ch->lock, irq_flags);
+               return xpcSuccess;
+       }
+
+       dev_dbg(xpc_chan, "can't get memory for cached remote message queue, "
+               "partid=%d, channel=%d\n", ch->partid, ch->number);
+       return xpcNoMemory;
+}
+
+
+/*
+ * Allocate message queues and other stuff associated with a channel.
+ *
+ * Note: Assumes all of the channel sizes are filled in.
+ */
+static enum xpc_retval
+xpc_allocate_msgqueues(struct xpc_channel *ch)
+{
+       unsigned long irq_flags;
+       int i;
+       enum xpc_retval ret;
+
+
+       DBUG_ON(ch->flags & XPC_C_SETUP);
+
+       if ((ret = xpc_allocate_local_msgqueue(ch)) != xpcSuccess) {
+               return ret;
+       }
+
+       if ((ret = xpc_allocate_remote_msgqueue(ch)) != xpcSuccess) {
+               kfree(ch->local_msgqueue_base);
+               ch->local_msgqueue = NULL;
+               kfree(ch->notify_queue);
+               ch->notify_queue = NULL;
+               return ret;
+       }
+
+       for (i = 0; i < ch->local_nentries; i++) {
+               /* use a semaphore as an event wait queue */
+               sema_init(&ch->notify_queue[i].sema, 0);
+       }
+
+       sema_init(&ch->teardown_sema, 0);       /* event wait */
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+       ch->flags |= XPC_C_SETUP;
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+       return xpcSuccess;
+}
+
+
+/*
+ * Process a connect message from a remote partition.
+ *
+ * Note: xpc_process_connect() is expecting to be called with the
+ * spin_lock_irqsave held and will leave it locked upon return.
+ */
+static void
+xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+       enum xpc_retval ret;
+
+
+       DBUG_ON(!spin_is_locked(&ch->lock));
+
+       if (!(ch->flags & XPC_C_OPENREQUEST) ||
+                               !(ch->flags & XPC_C_ROPENREQUEST)) {
+               /* nothing more to do for now */
+               return;
+       }
+       DBUG_ON(!(ch->flags & XPC_C_CONNECTING));
+
+       if (!(ch->flags & XPC_C_SETUP)) {
+               spin_unlock_irqrestore(&ch->lock, *irq_flags);
+               ret = xpc_allocate_msgqueues(ch);
+               spin_lock_irqsave(&ch->lock, *irq_flags);
+
+               if (ret != xpcSuccess) {
+                       XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags);
+               }
+               if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING)) {
+                       return;
+               }
+
+               DBUG_ON(!(ch->flags & XPC_C_SETUP));
+               DBUG_ON(ch->local_msgqueue == NULL);
+               DBUG_ON(ch->remote_msgqueue == NULL);
+       }
+
+       if (!(ch->flags & XPC_C_OPENREPLY)) {
+               ch->flags |= XPC_C_OPENREPLY;
+               xpc_IPI_send_openreply(ch, irq_flags);
+       }
+
+       if (!(ch->flags & XPC_C_ROPENREPLY)) {
+               return;
+       }
+
+       DBUG_ON(ch->remote_msgqueue_pa == 0);
+
+       ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP);    /* clear all else */
+
+       dev_info(xpc_chan, "channel %d to partition %d connected\n",
+               ch->number, ch->partid);
+
+       spin_unlock_irqrestore(&ch->lock, *irq_flags);
+       xpc_create_kthreads(ch, 1);
+       spin_lock_irqsave(&ch->lock, *irq_flags);
+}
+
+
+/*
+ * Free up message queues and other stuff that were allocated for the specified
+ * channel.
+ *
+ * Note: ch->reason and ch->reason_line are left set for debugging purposes,
+ * they're cleared when XPC_C_DISCONNECTED is cleared.
+ */
+static void
+xpc_free_msgqueues(struct xpc_channel *ch)
+{
+       DBUG_ON(!spin_is_locked(&ch->lock));
+       DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
+
+       ch->remote_msgqueue_pa = 0;
+       ch->func = NULL;
+       ch->key = NULL;
+       ch->msg_size = 0;
+       ch->local_nentries = 0;
+       ch->remote_nentries = 0;
+       ch->kthreads_assigned_limit = 0;
+       ch->kthreads_idle_limit = 0;
+
+       ch->local_GP->get = 0;
+       ch->local_GP->put = 0;
+       ch->remote_GP.get = 0;
+       ch->remote_GP.put = 0;
+       ch->w_local_GP.get = 0;
+       ch->w_local_GP.put = 0;
+       ch->w_remote_GP.get = 0;
+       ch->w_remote_GP.put = 0;
+       ch->next_msg_to_pull = 0;
+
+       if (ch->flags & XPC_C_SETUP) {
+               ch->flags &= ~XPC_C_SETUP;
+
+               dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
+                       ch->flags, ch->partid, ch->number);
+
+               kfree(ch->local_msgqueue_base);
+               ch->local_msgqueue = NULL;
+               kfree(ch->remote_msgqueue_base);
+               ch->remote_msgqueue = NULL;
+               kfree(ch->notify_queue);
+               ch->notify_queue = NULL;
+
+               /* in case someone is waiting for the teardown to complete */
+               up(&ch->teardown_sema);
+       }
+}
+
+
+/*
+ * spin_lock_irqsave() is expected to be held on entry.
+ */
+static void
+xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
+{
+       struct xpc_partition *part = &xpc_partitions[ch->partid];
+       u32 ch_flags = ch->flags;
+
+
+       DBUG_ON(!spin_is_locked(&ch->lock));
+
+       if (!(ch->flags & XPC_C_DISCONNECTING)) {
+               return;
+       }
+
+       DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+
+       /* make sure all activity has settled down first */
+
+       if (atomic_read(&ch->references) > 0) {
+               return;
+       }
+       DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
+
+       /* it's now safe to free the channel's message queues */
+
+       xpc_free_msgqueues(ch);
+       DBUG_ON(ch->flags & XPC_C_SETUP);
+
+       if (part->act_state != XPC_P_DEACTIVATING) {
+
+               /* as long as the other side is up do the full protocol */
+
+               if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
+                       return;
+               }
+
+               if (!(ch->flags & XPC_C_CLOSEREPLY)) {
+                       ch->flags |= XPC_C_CLOSEREPLY;
+                       xpc_IPI_send_closereply(ch, irq_flags);
+               }
+
+               if (!(ch->flags & XPC_C_RCLOSEREPLY)) {
+                       return;
+               }
+       }
+
+       /* both sides are disconnected now */
+
+       ch->flags = XPC_C_DISCONNECTED; /* clear all flags, but this one */
+
+       atomic_dec(&part->nchannels_active);
+
+       if (ch_flags & XPC_C_WASCONNECTED) {
+               dev_info(xpc_chan, "channel %d to partition %d disconnected, "
+                       "reason=%d\n", ch->number, ch->partid, ch->reason);
+       }
+}
+
+
+/*
+ * Process a change in the channel's remote connection state.
+ */
+static void
+xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
+                               u8 IPI_flags)
+{
+       unsigned long irq_flags;
+       struct xpc_openclose_args *args =
+                               &part->remote_openclose_args[ch_number];
+       struct xpc_channel *ch = &part->channels[ch_number];
+       enum xpc_retval reason;
+
+
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+
+
+       if (IPI_flags & XPC_IPI_CLOSEREQUEST) {
+
+               dev_dbg(xpc_chan, "XPC_IPI_CLOSEREQUEST (reason=%d) received "
+                       "from partid=%d, channel=%d\n", args->reason,
+                       ch->partid, ch->number);
+
+               /*
+                * If RCLOSEREQUEST is set, we're probably waiting for
+                * RCLOSEREPLY. We should find it and a ROPENREQUEST packed
+                * with this RCLOSEQREUQEST in the IPI_flags.
+                */
+
+               if (ch->flags & XPC_C_RCLOSEREQUEST) {
+                       DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
+                       DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+                       DBUG_ON(!(ch->flags & XPC_C_CLOSEREPLY));
+                       DBUG_ON(ch->flags & XPC_C_RCLOSEREPLY);
+
+                       DBUG_ON(!(IPI_flags & XPC_IPI_CLOSEREPLY));
+                       IPI_flags &= ~XPC_IPI_CLOSEREPLY;
+                       ch->flags |= XPC_C_RCLOSEREPLY;
+
+                       /* both sides have finished disconnecting */
+                       xpc_process_disconnect(ch, &irq_flags);
+               }
+
+               if (ch->flags & XPC_C_DISCONNECTED) {
+                       // >>> explain this section
+
+                       if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {
+                               DBUG_ON(part->act_state !=
+                                                       XPC_P_DEACTIVATING);
+                               spin_unlock_irqrestore(&ch->lock, irq_flags);
+                               return;
+                       }
+
+                       XPC_SET_REASON(ch, 0, 0);
+                       ch->flags &= ~XPC_C_DISCONNECTED;
+
+                       atomic_inc(&part->nchannels_active);
+                       ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
+               }
+
+               IPI_flags &= ~(XPC_IPI_OPENREQUEST | XPC_IPI_OPENREPLY);
+
+               /*
+                * The meaningful CLOSEREQUEST connection state fields are:
+                *      reason = reason connection is to be closed
+                */
+
+               ch->flags |= XPC_C_RCLOSEREQUEST;
+
+               if (!(ch->flags & XPC_C_DISCONNECTING)) {
+                       reason = args->reason;
+                       if (reason <= xpcSuccess || reason > xpcUnknownReason) {
+                               reason = xpcUnknownReason;
+                       } else if (reason == xpcUnregistering) {
+                               reason = xpcOtherUnregistering;
+                       }
+
+                       XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
+               } else {
+                       xpc_process_disconnect(ch, &irq_flags);
+               }
+       }
+
+
+       if (IPI_flags & XPC_IPI_CLOSEREPLY) {
+
+               dev_dbg(xpc_chan, "XPC_IPI_CLOSEREPLY received from partid=%d,"
+                       " channel=%d\n", ch->partid, ch->number);
+
+               if (ch->flags & XPC_C_DISCONNECTED) {
+                       DBUG_ON(part->act_state != XPC_P_DEACTIVATING);
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return;
+               }
+
+               DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
+               DBUG_ON(!(ch->flags & XPC_C_RCLOSEREQUEST));
+
+               ch->flags |= XPC_C_RCLOSEREPLY;
+
+               if (ch->flags & XPC_C_CLOSEREPLY) {
+                       /* both sides have finished disconnecting */
+                       xpc_process_disconnect(ch, &irq_flags);
+               }
+       }
+
+
+       if (IPI_flags & XPC_IPI_OPENREQUEST) {
+
+               dev_dbg(xpc_chan, "XPC_IPI_OPENREQUEST (msg_size=%d, "
+                       "local_nentries=%d) received from partid=%d, "
+                       "channel=%d\n", args->msg_size, args->local_nentries,
+                       ch->partid, ch->number);
+
+               if ((ch->flags & XPC_C_DISCONNECTING) ||
+                                       part->act_state == XPC_P_DEACTIVATING) {
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return;
+               }
+               DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED |
+                                                       XPC_C_OPENREQUEST)));
+               DBUG_ON(ch->flags & (XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
+                                       XPC_C_OPENREPLY | XPC_C_CONNECTED));
+
+               /*
+                * The meaningful OPENREQUEST connection state fields are:
+                *      msg_size = size of channel's messages in bytes
+                *      local_nentries = remote partition's local_nentries
+                */
+               DBUG_ON(args->msg_size == 0);
+               DBUG_ON(args->local_nentries == 0);
+
+               ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
+               ch->remote_nentries = args->local_nentries;
+
+
+               if (ch->flags & XPC_C_OPENREQUEST) {
+                       if (args->msg_size != ch->msg_size) {
+                               XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
+                                                               &irq_flags);
+                               spin_unlock_irqrestore(&ch->lock, irq_flags);
+                               return;
+                       }
+               } else {
+                       ch->msg_size = args->msg_size;
+
+                       XPC_SET_REASON(ch, 0, 0);
+                       ch->flags &= ~XPC_C_DISCONNECTED;
+
+                       atomic_inc(&part->nchannels_active);
+               }
+
+               xpc_process_connect(ch, &irq_flags);
+       }
+
+
+       if (IPI_flags & XPC_IPI_OPENREPLY) {
+
+               dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY (local_msgqueue_pa=0x%lx, "
+                       "local_nentries=%d, remote_nentries=%d) received from "
+                       "partid=%d, channel=%d\n", args->local_msgqueue_pa,
+                       args->local_nentries, args->remote_nentries,
+                       ch->partid, ch->number);
+
+               if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return;
+               }
+               DBUG_ON(!(ch->flags & XPC_C_OPENREQUEST));
+               DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
+               DBUG_ON(ch->flags & XPC_C_CONNECTED);
+
+               /*
+                * The meaningful OPENREPLY connection state fields are:
+                *      local_msgqueue_pa = physical address of remote
+                *                          partition's local_msgqueue
+                *      local_nentries = remote partition's local_nentries
+                *      remote_nentries = remote partition's remote_nentries
+                */
+               DBUG_ON(args->local_msgqueue_pa == 0);
+               DBUG_ON(args->local_nentries == 0);
+               DBUG_ON(args->remote_nentries == 0);
+
+               ch->flags |= XPC_C_ROPENREPLY;
+               ch->remote_msgqueue_pa = args->local_msgqueue_pa;
+
+               if (args->local_nentries < ch->remote_nentries) {
+                       dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
+                               "remote_nentries=%d, old remote_nentries=%d, "
+                               "partid=%d, channel=%d\n",
+                               args->local_nentries, ch->remote_nentries,
+                               ch->partid, ch->number);
+
+                       ch->remote_nentries = args->local_nentries;
+               }
+               if (args->remote_nentries < ch->local_nentries) {
+                       dev_dbg(xpc_chan, "XPC_IPI_OPENREPLY: new "
+                               "local_nentries=%d, old local_nentries=%d, "
+                               "partid=%d, channel=%d\n",
+                               args->remote_nentries, ch->local_nentries,
+                               ch->partid, ch->number);
+
+                       ch->local_nentries = args->remote_nentries;
+               }
+
+               xpc_process_connect(ch, &irq_flags);
+       }
+
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+}
+
+
+/*
+ * Attempt to establish a channel connection to a remote partition.
+ */
+static enum xpc_retval
+xpc_connect_channel(struct xpc_channel *ch)
+{
+       unsigned long irq_flags;
+       struct xpc_registration *registration = &xpc_registrations[ch->number];
+
+
+       if (down_interruptible(&registration->sema) != 0) {
+               return xpcInterrupted;
+       }
+
+       if (!XPC_CHANNEL_REGISTERED(ch->number)) {
+               up(&registration->sema);
+               return xpcUnregistered;
+       }
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+
+       DBUG_ON(ch->flags & XPC_C_CONNECTED);
+       DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
+
+       if (ch->flags & XPC_C_DISCONNECTING) {
+               spin_unlock_irqrestore(&ch->lock, irq_flags);
+               up(&registration->sema);
+               return ch->reason;
+       }
+
+
+       /* add info from the channel connect registration to the channel */
+
+       ch->kthreads_assigned_limit = registration->assigned_limit;
+       ch->kthreads_idle_limit = registration->idle_limit;
+       DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
+       DBUG_ON(atomic_read(&ch->kthreads_idle) != 0);
+       DBUG_ON(atomic_read(&ch->kthreads_active) != 0);
+
+       ch->func = registration->func;
+       DBUG_ON(registration->func == NULL);
+       ch->key = registration->key;
+
+       ch->local_nentries = registration->nentries;
+
+       if (ch->flags & XPC_C_ROPENREQUEST) {
+               if (registration->msg_size != ch->msg_size) {
+                       /* the local and remote sides aren't the same */
+
+                       /*
+                        * Because XPC_DISCONNECT_CHANNEL() can block we're
+                        * forced to up the registration sema before we unlock
+                        * the channel lock. But that's okay here because we're
+                        * done with the part that required the registration
+                        * sema. XPC_DISCONNECT_CHANNEL() requires that the
+                        * channel lock be locked and will unlock and relock
+                        * the channel lock as needed.
+                        */
+                       up(&registration->sema);
+                       XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes,
+                                                               &irq_flags);
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return xpcUnequalMsgSizes;
+               }
+       } else {
+               ch->msg_size = registration->msg_size;
+
+               XPC_SET_REASON(ch, 0, 0);
+               ch->flags &= ~XPC_C_DISCONNECTED;
+
+               atomic_inc(&xpc_partitions[ch->partid].nchannels_active);
+       }
+
+       up(&registration->sema);
+
+
+       /* initiate the connection */
+
+       ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
+       xpc_IPI_send_openrequest(ch, &irq_flags);
+
+       xpc_process_connect(ch, &irq_flags);
+
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+       return xpcSuccess;
+}
+
+
+/*
+ * Notify those who wanted to be notified upon delivery of their message.
+ */
+static void
+xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put)
+{
+       struct xpc_notify *notify;
+       u8 notify_type;
+       s64 get = ch->w_remote_GP.get - 1;
+
+
+       while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
+
+               notify = &ch->notify_queue[get % ch->local_nentries];
+
+               /*
+                * See if the notify entry indicates it was associated with
+                * a message who's sender wants to be notified. It is possible
+                * that it is, but someone else is doing or has done the
+                * notification.
+                */
+               notify_type = notify->type;
+               if (notify_type == 0 ||
+                               cmpxchg(&notify->type, notify_type, 0) !=
+                                                               notify_type) {
+                       continue;
+               }
+
+               DBUG_ON(notify_type != XPC_N_CALL);
+
+               atomic_dec(&ch->n_to_notify);
+
+               if (notify->func != NULL) {
+                       dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
+                               "msg_number=%ld, partid=%d, channel=%d\n",
+                               (void *) notify, get, ch->partid, ch->number);
+
+                       notify->func(reason, ch->partid, ch->number,
+                                                               notify->key);
+
+                       dev_dbg(xpc_chan, "notify->func() returned, "
+                               "notify=0x%p, msg_number=%ld, partid=%d, "
+                               "channel=%d\n", (void *) notify, get,
+                               ch->partid, ch->number);
+               }
+       }
+}
+
+
+/*
+ * Clear some of the msg flags in the local message queue.
+ */
+static inline void
+xpc_clear_local_msgqueue_flags(struct xpc_channel *ch)
+{
+       struct xpc_msg *msg;
+       s64 get;
+
+
+       get = ch->w_remote_GP.get;
+       do {
+               msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+                               (get % ch->local_nentries) * ch->msg_size);
+               msg->flags = 0;
+       } while (++get < (volatile s64) ch->remote_GP.get);
+}
+
+
+/*
+ * Clear some of the msg flags in the remote message queue.
+ */
+static inline void
+xpc_clear_remote_msgqueue_flags(struct xpc_channel *ch)
+{
+       struct xpc_msg *msg;
+       s64 put;
+
+
+       put = ch->w_remote_GP.put;
+       do {
+               msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+                               (put % ch->remote_nentries) * ch->msg_size);
+               msg->flags = 0;
+       } while (++put < (volatile s64) ch->remote_GP.put);
+}
+
+
+static void
+xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
+{
+       struct xpc_channel *ch = &part->channels[ch_number];
+       int nmsgs_sent;
+
+
+       ch->remote_GP = part->remote_GPs[ch_number];
+
+
+       /* See what, if anything, has changed for each connected channel */
+
+       xpc_msgqueue_ref(ch);
+
+       if (ch->w_remote_GP.get == ch->remote_GP.get &&
+                               ch->w_remote_GP.put == ch->remote_GP.put) {
+               /* nothing changed since GPs were last pulled */
+               xpc_msgqueue_deref(ch);
+               return;
+       }
+
+       if (!(ch->flags & XPC_C_CONNECTED)){
+               xpc_msgqueue_deref(ch);
+               return;
+       }
+
+
+       /*
+        * First check to see if messages recently sent by us have been
+        * received by the other side. (The remote GET value will have
+        * changed since we last looked at it.)
+        */
+
+       if (ch->w_remote_GP.get != ch->remote_GP.get) {
+
+               /*
+                * We need to notify any senders that want to be notified
+                * that their sent messages have been received by their
+                * intended recipients. We need to do this before updating
+                * w_remote_GP.get so that we don't allocate the same message
+                * queue entries prematurely (see xpc_allocate_msg()).
+                */
+               if (atomic_read(&ch->n_to_notify) > 0) {
+                       /*
+                        * Notify senders that messages sent have been
+                        * received and delivered by the other side.
+                        */
+                       xpc_notify_senders(ch, xpcMsgDelivered,
+                                                       ch->remote_GP.get);
+               }
+
+               /*
+                * Clear msg->flags in previously sent messages, so that
+                * they're ready for xpc_allocate_msg().
+                */
+               xpc_clear_local_msgqueue_flags(ch);
+
+               (volatile s64) ch->w_remote_GP.get = ch->remote_GP.get;
+
+               dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
+                       "channel=%d\n", ch->w_remote_GP.get, ch->partid,
+                       ch->number);
+
+               /*
+                * If anyone was waiting for message queue entries to become
+                * available, wake them up.
+                */
+               if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
+                       wake_up(&ch->msg_allocate_wq);
+               }
+       }
+
+
+       /*
+        * Now check for newly sent messages by the other side. (The remote
+        * PUT value will have changed since we last looked at it.)
+        */
+
+       if (ch->w_remote_GP.put != ch->remote_GP.put) {
+               /*
+                * Clear msg->flags in previously received messages, so that
+                * they're ready for xpc_get_deliverable_msg().
+                */
+               xpc_clear_remote_msgqueue_flags(ch);
+
+               (volatile s64) ch->w_remote_GP.put = ch->remote_GP.put;
+
+               dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
+                       "channel=%d\n", ch->w_remote_GP.put, ch->partid,
+                       ch->number);
+
+               nmsgs_sent = ch->w_remote_GP.put - ch->w_local_GP.get;
+               if (nmsgs_sent > 0) {
+                       dev_dbg(xpc_chan, "msgs waiting to be copied and "
+                               "delivered=%d, partid=%d, channel=%d\n",
+                               nmsgs_sent, ch->partid, ch->number);
+
+                       if (ch->flags & XPC_C_CONNECTCALLOUT) {
+                               xpc_activate_kthreads(ch, nmsgs_sent);
+                       }
+               }
+       }
+
+       xpc_msgqueue_deref(ch);
+}
+
+
+void
+xpc_process_channel_activity(struct xpc_partition *part)
+{
+       unsigned long irq_flags;
+       u64 IPI_amo, IPI_flags;
+       struct xpc_channel *ch;
+       int ch_number;
+
+
+       IPI_amo = xpc_get_IPI_flags(part);
+
+       /*
+        * Initiate channel connections for registered channels.
+        *
+        * For each connected channel that has pending messages activate idle
+        * kthreads and/or create new kthreads as needed.
+        */
+
+       for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+               ch = &part->channels[ch_number];
+
+
+               /*
+                * Process any open or close related IPI flags, and then deal
+                * with connecting or disconnecting the channel as required.
+                */
+
+               IPI_flags = XPC_GET_IPI_FLAGS(IPI_amo, ch_number);
+
+               if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_flags)) {
+                       xpc_process_openclose_IPI(part, ch_number, IPI_flags);
+               }
+
+
+               if (ch->flags & XPC_C_DISCONNECTING) {
+                       spin_lock_irqsave(&ch->lock, irq_flags);
+                       xpc_process_disconnect(ch, &irq_flags);
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       continue;
+               }
+
+               if (part->act_state == XPC_P_DEACTIVATING) {
+                       continue;
+               }
+
+               if (!(ch->flags & XPC_C_CONNECTED)) {
+                       if (!(ch->flags & XPC_C_OPENREQUEST)) {
+                               DBUG_ON(ch->flags & XPC_C_SETUP);
+                               (void) xpc_connect_channel(ch);
+                       } else {
+                               spin_lock_irqsave(&ch->lock, irq_flags);
+                               xpc_process_connect(ch, &irq_flags);
+                               spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       }
+                       continue;
+               }
+
+
+               /*
+                * Process any message related IPI flags, this may involve the
+                * activation of kthreads to deliver any pending messages sent
+                * from the other partition.
+                */
+
+               if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_flags)) {
+                       xpc_process_msg_IPI(part, ch_number);
+               }
+       }
+}
+
+
+/*
+ * XPC's heartbeat code calls this function to inform XPC that a partition has
+ * gone down.  XPC responds by tearing down the XPartition Communication
+ * infrastructure used for the just downed partition.
+ *
+ * XPC's heartbeat code will never call this function and xpc_partition_up()
+ * at the same time. Nor will it ever make multiple calls to either function
+ * at the same time.
+ */
+void
+xpc_partition_down(struct xpc_partition *part, enum xpc_retval reason)
+{
+       unsigned long irq_flags;
+       int ch_number;
+       struct xpc_channel *ch;
+
+
+       dev_dbg(xpc_chan, "deactivating partition %d, reason=%d\n",
+               XPC_PARTID(part), reason);
+
+       if (!xpc_part_ref(part)) {
+               /* infrastructure for this partition isn't currently set up */
+               return;
+       }
+
+
+       /* disconnect all channels associated with the downed partition */
+
+       for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
+               ch = &part->channels[ch_number];
+
+
+               xpc_msgqueue_ref(ch);
+               spin_lock_irqsave(&ch->lock, irq_flags);
+
+               XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
+
+               spin_unlock_irqrestore(&ch->lock, irq_flags);
+               xpc_msgqueue_deref(ch);
+       }
+
+       xpc_wakeup_channel_mgr(part);
+
+       xpc_part_deref(part);
+}
+
+
+/*
+ * Teardown the infrastructure necessary to support XPartition Communication
+ * between the specified remote partition and the local one.
+ */
+void
+xpc_teardown_infrastructure(struct xpc_partition *part)
+{
+       partid_t partid = XPC_PARTID(part);
+
+
+       /*
+        * We start off by making this partition inaccessible to local
+        * processes by marking it as no longer setup. Then we make it
+        * inaccessible to remote processes by clearing the XPC per partition
+        * specific variable's magic # (which indicates that these variables
+        * are no longer valid) and by ignoring all XPC notify IPIs sent to
+        * this partition.
+        */
+
+       DBUG_ON(atomic_read(&part->nchannels_active) != 0);
+       DBUG_ON(part->setup_state != XPC_P_SETUP);
+       part->setup_state = XPC_P_WTEARDOWN;
+
+       xpc_vars_part[partid].magic = 0;
+
+
+       free_irq(SGI_XPC_NOTIFY, (void *) (u64) partid);
+
+
+       /*
+        * Before proceding with the teardown we have to wait until all
+        * existing references cease.
+        */
+       wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));
+
+
+       /* now we can begin tearing down the infrastructure */
+
+       part->setup_state = XPC_P_TORNDOWN;
+
+       /* in case we've still got outstanding timers registered... */
+       del_timer_sync(&part->dropped_IPI_timer);
+
+       kfree(part->remote_openclose_args_base);
+       part->remote_openclose_args = NULL;
+       kfree(part->local_openclose_args_base);
+       part->local_openclose_args = NULL;
+       kfree(part->remote_GPs_base);
+       part->remote_GPs = NULL;
+       kfree(part->local_GPs_base);
+       part->local_GPs = NULL;
+       kfree(part->channels);
+       part->channels = NULL;
+       part->local_IPI_amo_va = NULL;
+}
+
+
+/*
+ * Called by XP at the time of channel connection registration to cause
+ * XPC to establish connections to all currently active partitions.
+ */
+void
+xpc_initiate_connect(int ch_number)
+{
+       partid_t partid;
+       struct xpc_partition *part;
+       struct xpc_channel *ch;
+
+
+       DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+
+       for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+               part = &xpc_partitions[partid];
+
+               if (xpc_part_ref(part)) {
+                       ch = &part->channels[ch_number];
+
+                       if (!(ch->flags & XPC_C_DISCONNECTING)) {
+                               DBUG_ON(ch->flags & XPC_C_OPENREQUEST);
+                               DBUG_ON(ch->flags & XPC_C_CONNECTED);
+                               DBUG_ON(ch->flags & XPC_C_SETUP);
+
+                               /*
+                                * Initiate the establishment of a connection
+                                * on the newly registered channel to the
+                                * remote partition.
+                                */
+                               xpc_wakeup_channel_mgr(part);
+                       }
+
+                       xpc_part_deref(part);
+               }
+       }
+}
+
+
+void
+xpc_connected_callout(struct xpc_channel *ch)
+{
+       unsigned long irq_flags;
+
+
+       /* let the registerer know that a connection has been established */
+
+       if (ch->func != NULL) {
+               dev_dbg(xpc_chan, "ch->func() called, reason=xpcConnected, "
+                       "partid=%d, channel=%d\n", ch->partid, ch->number);
+
+               ch->func(xpcConnected, ch->partid, ch->number,
+                               (void *) (u64) ch->local_nentries, ch->key);
+
+               dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, "
+                       "partid=%d, channel=%d\n", ch->partid, ch->number);
+       }
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+       ch->flags |= XPC_C_CONNECTCALLOUT;
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+}
+
+
+/*
+ * Called by XP at the time of channel connection unregistration to cause
+ * XPC to teardown all current connections for the specified channel.
+ *
+ * Before returning xpc_initiate_disconnect() will wait until all connections
+ * on the specified channel have been closed/torndown. So the caller can be
+ * assured that they will not be receiving any more callouts from XPC to the
+ * function they registered via xpc_connect().
+ *
+ * Arguments:
+ *
+ *     ch_number - channel # to unregister.
+ */
+void
+xpc_initiate_disconnect(int ch_number)
+{
+       unsigned long irq_flags;
+       partid_t partid;
+       struct xpc_partition *part;
+       struct xpc_channel *ch;
+
+
+       DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
+
+       /* initiate the channel disconnect for every active partition */
+       for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+               part = &xpc_partitions[partid];
+
+               if (xpc_part_ref(part)) {
+                       ch = &part->channels[ch_number];
+                       xpc_msgqueue_ref(ch);
+
+                       spin_lock_irqsave(&ch->lock, irq_flags);
+
+                       XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering,
+                                                               &irq_flags);
+
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+                       xpc_msgqueue_deref(ch);
+                       xpc_part_deref(part);
+               }
+       }
+
+       xpc_disconnect_wait(ch_number);
+}
+
+
+/*
+ * To disconnect a channel, and reflect it back to all who may be waiting.
+ *
+ * >>> An OPEN is not allowed until XPC_C_DISCONNECTING is cleared by
+ * >>> xpc_free_msgqueues().
+ *
+ * THE CHANNEL IS TO BE LOCKED BY THE CALLER AND WILL REMAIN LOCKED UPON 
RETURN.
+ */
+void
+xpc_disconnect_channel(const int line, struct xpc_channel *ch,
+                       enum xpc_retval reason, unsigned long *irq_flags)
+{
+       u32 flags;
+
+
+       DBUG_ON(!spin_is_locked(&ch->lock));
+
+       if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) {
+               return;
+       }
+       DBUG_ON(!(ch->flags & (XPC_C_CONNECTING | XPC_C_CONNECTED)));
+
+       dev_dbg(xpc_chan, "reason=%d, line=%d, partid=%d, channel=%d\n",
+               reason, line, ch->partid, ch->number);
+
+       XPC_SET_REASON(ch, reason, line);
+
+       flags = ch->flags;
+       /* some of these may not have been set */
+       ch->flags &= ~(XPC_C_OPENREQUEST | XPC_C_OPENREPLY |
+                       XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
+                       XPC_C_CONNECTING | XPC_C_CONNECTED);
+
+       ch->flags |= (XPC_C_CLOSEREQUEST | XPC_C_DISCONNECTING);
+       xpc_IPI_send_closerequest(ch, irq_flags);
+
+       if (flags & XPC_C_CONNECTED) {
+               ch->flags |= XPC_C_WASCONNECTED;
+       }
+
+       if (atomic_read(&ch->kthreads_idle) > 0) {
+               /* wake all idle kthreads so they can exit */
+               wake_up_all(&ch->idle_wq);
+       }
+
+       spin_unlock_irqrestore(&ch->lock, *irq_flags);
+
+
+       /* wake those waiting to allocate an entry from the local msg queue */
+
+       if (atomic_read(&ch->n_on_msg_allocate_wq) > 0) {
+               wake_up(&ch->msg_allocate_wq);
+       }
+
+       /* wake those waiting for notify completion */
+
+       if (atomic_read(&ch->n_to_notify) > 0) {
+               xpc_notify_senders(ch, reason, ch->w_local_GP.put);
+       }
+
+       spin_lock_irqsave(&ch->lock, *irq_flags);
+}
+
+
+void
+xpc_disconnected_callout(struct xpc_channel *ch)
+{
+       /*
+        * Let the channel's registerer know that the channel is now
+        * disconnected. We don't want to do this if the registerer was never
+        * informed of a connection being made, unless the disconnect was for
+        * abnormal reasons.
+        */
+
+       if (ch->func != NULL) {
+               dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
+                       "channel=%d\n", ch->reason, ch->partid, ch->number);
+
+               ch->func(ch->reason, ch->partid, ch->number, NULL, ch->key);
+
+               dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
+                       "channel=%d\n", ch->reason, ch->partid, ch->number);
+       }
+}
+
+
+/*
+ * Wait for a message entry to become available for the specified channel,
+ * but don't wait any longer than 1 jiffy.
+ */
+static enum xpc_retval
+xpc_allocate_msg_wait(struct xpc_channel *ch)
+{
+       enum xpc_retval ret;
+
+
+       if (ch->flags & XPC_C_DISCONNECTING) {
+               DBUG_ON(ch->reason == xpcInterrupted);  // >>> Is this true?
+               return ch->reason;
+       }
+
+       atomic_inc(&ch->n_on_msg_allocate_wq);
+       ret = interruptible_sleep_on_timeout(&ch->msg_allocate_wq, 1);
+       atomic_dec(&ch->n_on_msg_allocate_wq);
+
+       if (ch->flags & XPC_C_DISCONNECTING) {
+               ret = ch->reason;
+               DBUG_ON(ch->reason == xpcInterrupted);  // >>> Is this true?
+       } else if (ret == 0) {
+               ret = xpcTimeout;
+       } else {
+               ret = xpcInterrupted;
+       }
+
+       return ret;
+}
+
+
+/*
+ * Allocate an entry for a message from the message queue associated with the
+ * specified channel.
+ */
+static enum xpc_retval
+xpc_allocate_msg(struct xpc_channel *ch, u32 flags,
+                       struct xpc_msg **address_of_msg)
+{
+       struct xpc_msg *msg;
+       enum xpc_retval ret;
+       s64 put;
+
+
+       /* this reference will be dropped in xpc_send_msg() */
+       xpc_msgqueue_ref(ch);
+
+       if (ch->flags & XPC_C_DISCONNECTING) {
+               xpc_msgqueue_deref(ch);
+               return ch->reason;
+       }
+       if (!(ch->flags & XPC_C_CONNECTED)) {
+               xpc_msgqueue_deref(ch);
+               return xpcNotConnected;
+       }
+
+
+       /*
+        * Get the next available message entry from the local message queue.
+        * If none are available, we'll make sure that we grab the latest
+        * GP values.
+        */
+       ret = xpcTimeout;
+
+       while (1) {
+
+               put = (volatile s64) ch->w_local_GP.put;
+               if (put - (volatile s64) ch->w_remote_GP.get <
+                                                       ch->local_nentries) {
+
+                       /* There are available message entries. We need to try
+                        * to secure one for ourselves. We'll do this by trying
+                        * to increment w_local_GP.put as long as someone else
+                        * doesn't beat us to it. If they do, we'll have to
+                        * try again.
+                        */
+                       if (cmpxchg(&ch->w_local_GP.put, put, put + 1) ==
+                                                                       put) {
+                               /* we got the entry referenced by put */
+                               break;
+                       }
+                       continue;       /* try again */
+               }
+
+
+               /*
+                * There aren't any available msg entries at this time.
+                *
+                * In waiting for a message entry to become available,
+                * we set a timeout in case the other side is not
+                * sending completion IPIs. This lets us fake an IPI
+                * that will cause the IPI handler to fetch the latest
+                * GP values as if an IPI was sent by the other side.
+                */
+               if (ret == xpcTimeout) {
+                       xpc_IPI_send_local_msgrequest(ch);
+               }
+
+               if (flags & XPC_NOWAIT) {
+                       xpc_msgqueue_deref(ch);
+                       return xpcNoWait;
+               }
+
+               ret = xpc_allocate_msg_wait(ch);
+               if (ret != xpcInterrupted && ret != xpcTimeout) {
+                       xpc_msgqueue_deref(ch);
+                       return ret;
+               }
+       }
+
+
+       /* get the message's address and initialize it */
+       msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+                               (put % ch->local_nentries) * ch->msg_size);
+
+
+       DBUG_ON(msg->flags != 0);
+       msg->number = put;
+
+       dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, "
+               "msg_number=%ld, partid=%d, channel=%d\n", put + 1,
+               (void *) msg, msg->number, ch->partid, ch->number);
+
+       *address_of_msg = msg;
+
+       return xpcSuccess;
+}
+
+
+/*
+ * Allocate an entry for a message from the message queue associated with the
+ * specified channel. NOTE that this routine can sleep waiting for a message
+ * entry to become available. To not sleep, pass in the XPC_NOWAIT flag.
+ *
+ * Arguments:
+ *
+ *     partid - ID of partition to which the channel is connected.
+ *     ch_number - channel #.
+ *     flags - see xpc.h for valid flags.
+ *     payload - address of the allocated payload area pointer (filled in on
+ *               return) in which the user-defined message is constructed.
+ */
+enum xpc_retval
+xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void 
**payload)
+{
+       struct xpc_partition *part = &xpc_partitions[partid];
+       enum xpc_retval ret = xpcUnknownReason;
+       struct xpc_msg *msg;
+
+
+       DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+       DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+
+       *payload = NULL;
+
+       if (xpc_part_ref(part)) {
+               ret = xpc_allocate_msg(&part->channels[ch_number], flags, &msg);
+               xpc_part_deref(part);
+
+               if (msg != NULL) {
+                       *payload = &msg->payload;
+               }
+       }
+
+       return ret;
+}
+
+
+/*
+ * Now we actually send the messages that are ready to be sent by advancing
+ * the local message queue's Put value and then send an IPI to the recipient
+ * partition.
+ */
+static void
+xpc_send_msgs(struct xpc_channel *ch, s64 initial_put)
+{
+       struct xpc_msg *msg;
+       s64 put = initial_put + 1;
+       int send_IPI = 0;
+
+
+       while (1) {
+
+               while (1) {
+                       if (put == (volatile s64) ch->w_local_GP.put) {
+                               break;
+                       }
+
+                       msg = (struct xpc_msg *) ((u64) ch->local_msgqueue +
+                              (put % ch->local_nentries) * ch->msg_size);
+
+                       if (!(msg->flags & XPC_M_READY)) {
+                               break;
+                       }
+
+                       put++;
+               }
+
+               if (put == initial_put) {
+                       /* nothing's changed */
+                       break;
+               }
+
+               if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) !=
+                                                               initial_put) {
+                       /* someone else beat us to it */
+                       DBUG_ON((volatile s64) ch->local_GP->put < initial_put);
+                       break;
+               }
+
+               /* we just set the new value of local_GP->put */
+
+               dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, "
+                       "channel=%d\n", put, ch->partid, ch->number);
+
+               send_IPI = 1;
+
+               /*
+                * We need to ensure that the message referenced by
+                * local_GP->put is not XPC_M_READY or that local_GP->put
+                * equals w_local_GP.put, so we'll go have a look.
+                */
+               initial_put = put;
+       }
+
+       if (send_IPI) {
+               xpc_IPI_send_msgrequest(ch);
+       }
+}
+
+
+/*
+ * Common code that does the actual sending of the message by advancing the
+ * local message queue's Put value and sends an IPI to the partition the
+ * message is being sent to.
+ */
+static enum xpc_retval
+xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type,
+                       xpc_notify_func func, void *key)
+{
+       enum xpc_retval ret = xpcSuccess;
+       struct xpc_notify *notify = NULL;   // >>> to keep the compiler happy!!
+       s64 put, msg_number = msg->number;
+
+
+       DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
+       DBUG_ON((((u64) msg - (u64) ch->local_msgqueue) / ch->msg_size) !=
+                                       msg_number % ch->local_nentries);
+       DBUG_ON(msg->flags & XPC_M_READY);
+
+       if (ch->flags & XPC_C_DISCONNECTING) {
+               /* drop the reference grabbed in xpc_allocate_msg() */
+               xpc_msgqueue_deref(ch);
+               return ch->reason;
+       }
+
+       if (notify_type != 0) {
+               /*
+                * Tell the remote side to send an ACK interrupt when the
+                * message has been delivered.
+                */
+               msg->flags |= XPC_M_INTERRUPT;
+
+               atomic_inc(&ch->n_to_notify);
+
+               notify = &ch->notify_queue[msg_number % ch->local_nentries];
+               notify->func = func;
+               notify->key = key;
+               (volatile u8) notify->type = notify_type;
+
+               // >>> is a mb() needed here?
+
+               if (ch->flags & XPC_C_DISCONNECTING) {
+                       /*
+                        * An error occurred between our last error check and
+                        * this one. We will try to clear the type field from
+                        * the notify entry. If we succeed then
+                        * xpc_disconnect_channel() didn't already process
+                        * the notify entry.
+                        */
+                       if (cmpxchg(&notify->type, notify_type, 0) ==
+                                                               notify_type) {
+                               atomic_dec(&ch->n_to_notify);
+                               ret = ch->reason;
+                       }
+
+                       /* drop the reference grabbed in xpc_allocate_msg() */
+                       xpc_msgqueue_deref(ch);
+                       return ret;
+               }
+       }
+
+       msg->flags |= XPC_M_READY;
+
+       /*
+        * The preceding store of msg->flags must occur before the following
+        * load of ch->local_GP->put.
+        */
+       mb();
+
+       /* see if the message is next in line to be sent, if so send it */
+
+       put = ch->local_GP->put;
+       if (put == msg_number) {
+               xpc_send_msgs(ch, put);
+       }
+
+       /* drop the reference grabbed in xpc_allocate_msg() */
+       xpc_msgqueue_deref(ch);
+       return ret;
+}
+
+
+/*
+ * Send a message previously allocated using xpc_initiate_allocate() on the
+ * specified channel connected to the specified partition.
+ *
+ * This routine will not wait for the message to be received, nor will
+ * notification be given when it does happen. Once this routine has returned
+ * the message entry allocated via xpc_initiate_allocate() is no longer
+ * accessable to the caller.
+ *
+ * This routine, although called by users, does not call xpc_part_ref() to
+ * ensure that the partition infrastructure is in place. It relies on the
+ * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
+ *
+ * Arguments:
+ *
+ *     partid - ID of partition to which the channel is connected.
+ *     ch_number - channel # to send message on.
+ *     payload - pointer to the payload area allocated via
+ *                     xpc_initiate_allocate().
+ */
+enum xpc_retval
+xpc_initiate_send(partid_t partid, int ch_number, void *payload)
+{
+       struct xpc_partition *part = &xpc_partitions[partid];
+       struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+       enum xpc_retval ret;
+
+
+       dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *) msg,
+               partid, ch_number);
+
+       DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+       DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+       DBUG_ON(msg == NULL);
+
+       ret = xpc_send_msg(&part->channels[ch_number], msg, 0, NULL, NULL);
+
+       return ret;
+}
+
+
+/*
+ * Send a message previously allocated using xpc_initiate_allocate on the
+ * specified channel connected to the specified partition.
+ *
+ * This routine will not wait for the message to be sent. Once this routine
+ * has returned the message entry allocated via xpc_initiate_allocate() is no
+ * longer accessable to the caller.
+ *
+ * Once the remote end of the channel has received the message, the function
+ * passed as an argument to xpc_initiate_send_notify() will be called. This
+ * allows the sender to free up or re-use any buffers referenced by the
+ * message, but does NOT mean the message has been processed at the remote
+ * end by a receiver.
+ *
+ * If this routine returns an error, the caller's function will NOT be called.
+ *
+ * This routine, although called by users, does not call xpc_part_ref() to
+ * ensure that the partition infrastructure is in place. It relies on the
+ * fact that we called xpc_msgqueue_ref() in xpc_allocate_msg().
+ *
+ * Arguments:
+ *
+ *     partid - ID of partition to which the channel is connected.
+ *     ch_number - channel # to send message on.
+ *     payload - pointer to the payload area allocated via
+ *                     xpc_initiate_allocate().
+ *     func - function to call with asynchronous notification of message
+ *               receipt. THIS FUNCTION MUST BE NON-BLOCKING.
+ *     key - user-defined key to be passed to the function when it's called.
+ */
+enum xpc_retval
+xpc_initiate_send_notify(partid_t partid, int ch_number, void *payload,
+                               xpc_notify_func func, void *key)
+{
+       struct xpc_partition *part = &xpc_partitions[partid];
+       struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+       enum xpc_retval ret;
+
+
+       dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *) msg,
+               partid, ch_number);
+
+       DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+       DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+       DBUG_ON(msg == NULL);
+       DBUG_ON(func == NULL);
+
+       ret = xpc_send_msg(&part->channels[ch_number], msg, XPC_N_CALL,
+                                                               func, key);
+       return ret;
+}
+
+
+static struct xpc_msg *
+xpc_pull_remote_msg(struct xpc_channel *ch, s64 get)
+{
+       struct xpc_partition *part = &xpc_partitions[ch->partid];
+       struct xpc_msg *remote_msg, *msg;
+       u32 msg_index, nmsgs;
+       u64 msg_offset;
+       enum xpc_retval ret;
+
+
+       if (down_interruptible(&ch->msg_to_pull_sema) != 0) {
+               /* we were interrupted by a signal */
+               return NULL;
+       }
+
+       while (get >= ch->next_msg_to_pull) {
+
+               /* pull as many messages as are ready and able to be pulled */
+
+               msg_index = ch->next_msg_to_pull % ch->remote_nentries;
+
+               DBUG_ON(ch->next_msg_to_pull >=
+                                       (volatile s64) ch->w_remote_GP.put);
+               nmsgs =  (volatile s64) ch->w_remote_GP.put -
+                                               ch->next_msg_to_pull;
+               if (msg_index + nmsgs > ch->remote_nentries) {
+                       /* ignore the ones that wrap the msg queue for now */
+                       nmsgs = ch->remote_nentries - msg_index;
+               }
+
+               msg_offset = msg_index * ch->msg_size;
+               msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+                                                               msg_offset);
+               remote_msg = (struct xpc_msg *) (ch->remote_msgqueue_pa +
+                                                               msg_offset);
+
+               if ((ret = xpc_pull_remote_cachelines(part, msg, remote_msg,
+                               nmsgs * ch->msg_size)) != xpcSuccess) {
+
+                       dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
+                               " msg %ld from partition %d, channel=%d, "
+                               "ret=%d\n", nmsgs, ch->next_msg_to_pull,
+                               ch->partid, ch->number, ret);
+
+                       XPC_DEACTIVATE_PARTITION(part, ret);
+
+                       up(&ch->msg_to_pull_sema);
+                       return NULL;
+               }
+
+               mb();   /* >>> this may not be needed, we're not sure */
+
+               ch->next_msg_to_pull += nmsgs;
+       }
+
+       up(&ch->msg_to_pull_sema);
+
+       /* return the message we were looking for */
+       msg_offset = (get % ch->remote_nentries) * ch->msg_size;
+       msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue + msg_offset);
+
+       return msg;
+}
+
+
+/*
+ * Get a message to be delivered.
+ */
+static struct xpc_msg *
+xpc_get_deliverable_msg(struct xpc_channel *ch)
+{
+       struct xpc_msg *msg = NULL;
+       s64 get;
+
+
+       do {
+               if ((volatile u32) ch->flags & XPC_C_DISCONNECTING) {
+                       break;
+               }
+
+               get = (volatile s64) ch->w_local_GP.get;
+               if (get == (volatile s64) ch->w_remote_GP.put) {
+                       break;
+               }
+
+               /* There are messages waiting to be pulled and delivered.
+                * We need to try to secure one for ourselves. We'll do this
+                * by trying to increment w_local_GP.get and hope that no one
+                * else beats us to it. If they do, we'll we'll simply have
+                * to try again for the next one.
+                */
+
+               if (cmpxchg(&ch->w_local_GP.get, get, get + 1) == get) {
+                       /* we got the entry referenced by get */
+
+                       dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, "
+                               "partid=%d, channel=%d\n", get + 1,
+                               ch->partid, ch->number);
+
+                       /* pull the message from the remote partition */
+
+                       msg = xpc_pull_remote_msg(ch, get);
+
+                       DBUG_ON(msg != NULL && msg->number != get);
+                       DBUG_ON(msg != NULL && (msg->flags & XPC_M_DONE));
+                       DBUG_ON(msg != NULL && !(msg->flags & XPC_M_READY));
+
+                       break;
+               }
+
+       } while (1);
+
+       return msg;
+}
+
+
+/*
+ * Deliver a message to its intended recipient.
+ */
+void
+xpc_deliver_msg(struct xpc_channel *ch)
+{
+       struct xpc_msg *msg;
+
+
+       if ((msg = xpc_get_deliverable_msg(ch)) != NULL) {
+
+               /*
+                * This ref is taken to protect the payload itself from being
+                * freed before the user is finished with it, which the user
+                * indicates by calling xpc_initiate_received().
+                */
+               xpc_msgqueue_ref(ch);
+
+               atomic_inc(&ch->kthreads_active);
+
+               if (ch->func != NULL) {
+                       dev_dbg(xpc_chan, "ch->func() called, msg=0x%p, "
+                               "msg_number=%ld, partid=%d, channel=%d\n",
+                               (void *) msg, msg->number, ch->partid,
+                               ch->number);
+
+                       /* deliver the message to its intended recipient */
+                       ch->func(xpcMsgReceived, ch->partid, ch->number,
+                                       &msg->payload, ch->key);
+
+                       dev_dbg(xpc_chan, "ch->func() returned, msg=0x%p, "
+                               "msg_number=%ld, partid=%d, channel=%d\n",
+                               (void *) msg, msg->number, ch->partid,
+                               ch->number);
+               }
+
+               atomic_dec(&ch->kthreads_active);
+       }
+}
+
+
+/*
+ * Now we actually acknowledge the messages that have been delivered and ack'd
+ * by advancing the cached remote message queue's Get value and if requested
+ * send an IPI to the message sender's partition.
+ */
+static void
+xpc_acknowledge_msgs(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
+{
+       struct xpc_msg *msg;
+       s64 get = initial_get + 1;
+       int send_IPI = 0;
+
+
+       while (1) {
+
+               while (1) {
+                       if (get == (volatile s64) ch->w_local_GP.get) {
+                               break;
+                       }
+
+                       msg = (struct xpc_msg *) ((u64) ch->remote_msgqueue +
+                              (get % ch->remote_nentries) * ch->msg_size);
+
+                       if (!(msg->flags & XPC_M_DONE)) {
+                               break;
+                       }
+
+                       msg_flags |= msg->flags;
+                       get++;
+               }
+
+               if (get == initial_get) {
+                       /* nothing's changed */
+                       break;
+               }
+
+               if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) !=
+                                                               initial_get) {
+                       /* someone else beat us to it */
+                       DBUG_ON((volatile s64) ch->local_GP->get <=
+                                                               initial_get);
+                       break;
+               }
+
+               /* we just set the new value of local_GP->get */
+
+               dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "
+                       "channel=%d\n", get, ch->partid, ch->number);
+
+               send_IPI = (msg_flags & XPC_M_INTERRUPT);
+
+               /*
+                * We need to ensure that the message referenced by
+                * local_GP->get is not XPC_M_DONE or that local_GP->get
+                * equals w_local_GP.get, so we'll go have a look.
+                */
+               initial_get = get;
+       }
+
+       if (send_IPI) {
+               xpc_IPI_send_msgrequest(ch);
+       }
+}
+
+
+/*
+ * Acknowledge receipt of a delivered message.
+ *
+ * If a message has XPC_M_INTERRUPT set, send an interrupt to the partition
+ * that sent the message.
+ *
+ * This function, although called by users, does not call xpc_part_ref() to
+ * ensure that the partition infrastructure is in place. It relies on the
+ * fact that we called xpc_msgqueue_ref() in xpc_deliver_msg().
+ *
+ * Arguments:
+ *
+ *     partid - ID of partition to which the channel is connected.
+ *     ch_number - channel # message received on.
+ *     payload - pointer to the payload area allocated via
+ *                     xpc_initiate_allocate().
+ */
+void
+xpc_initiate_received(partid_t partid, int ch_number, void *payload)
+{
+       struct xpc_partition *part = &xpc_partitions[partid];
+       struct xpc_channel *ch;
+       struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
+       s64 get, msg_number = msg->number;
+
+
+       DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+       DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
+
+       ch = &part->channels[ch_number];
+
+       dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
+               (void *) msg, msg_number, ch->partid, ch->number);
+
+       DBUG_ON((((u64) msg - (u64) ch->remote_msgqueue) / ch->msg_size) !=
+                                       msg_number % ch->remote_nentries);
+       DBUG_ON(msg->flags & XPC_M_DONE);
+
+       msg->flags |= XPC_M_DONE;
+
+       /*
+        * The preceding store of msg->flags must occur before the following
+        * load of ch->local_GP->get.
+        */
+       mb();
+
+       /*
+        * See if this message is next in line to be acknowledged as having
+        * been delivered.
+        */
+       get = ch->local_GP->get;
+       if (get == msg_number) {
+               xpc_acknowledge_msgs(ch, get, msg->flags);
+       }
+
+       /* the call to xpc_msgqueue_ref() was done by xpc_deliver_msg()  */
+       xpc_msgqueue_deref(ch);
+}
+
diff -urN linux/arch/ia64/sn/kernel/xpc_main.c 
linux/arch/ia64/sn/kernel/xpc_main.c
--- linux/arch/ia64/sn/kernel/xpc_main.c        1970/01/01 00:00:00
+++ linux/arch/ia64/sn/kernel/xpc_main.c        2005-05-19 13:08:10.795783000 
+0100     1.1
@@ -0,0 +1,1064 @@
+/*
+ * 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-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition Communication (XPC) support - standard version.
+ *
+ *     XPC provides a message passing capability that crosses partition
+ *     boundaries. This module is made up of two parts:
+ *
+ *         partition   This part detects the presence/absence of other
+ *                     partitions. It provides a heartbeat and monitors
+ *                     the heartbeats of other partitions.
+ *
+ *         channel     This part manages the channels and sends/receives
+ *                     messages across them to/from other partitions.
+ *
+ *     There are a couple of additional functions residing in XP, which
+ *     provide an interface to XPC for its users.
+ *
+ *
+ *     Caveats:
+ *
+ *       . We currently have no way to determine which nasid an IPI came
+ *         from. Thus, xpc_IPI_send() does a remote AMO write followed by
+ *         an IPI. The AMO indicates where data is to be pulled from, so
+ *         after the IPI arrives, the remote partition checks the AMO word.
+ *         The IPI can actually arrive before the AMO however, so other code
+ *         must periodically check for this case. Also, remote AMO operations
+ *         do not reliably time out. Thus we do a remote PIO read solely to
+ *         know whether the remote partition is down and whether we should
+ *         stop sending IPIs to it. This remote PIO read operation is set up
+ *         in a special nofault region so SAL knows to ignore (and cleanup)
+ *         any errors due to the remote AMO write, PIO read, and/or PIO
+ *         write operations.
+ *
+ *         If/when new hardware solves this IPI problem, we should abandon
+ *         the current approach.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/cache.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/uaccess.h>
+#include "xpc.h"
+
+
+/* define two XPC debug device structures to be used with dev_dbg() et al */
+
+struct device_driver xpc_dbg_name = {
+       .name = "xpc"
+};
+
+struct device xpc_part_dbg_subname = {
+       .bus_id = {0},          /* set to "part" at xpc_init() time */
+       .driver = &xpc_dbg_name
+};
+
+struct device xpc_chan_dbg_subname = {
+       .bus_id = {0},          /* set to "chan" at xpc_init() time */
+       .driver = &xpc_dbg_name
+};
+
+struct device *xpc_part = &xpc_part_dbg_subname;
+struct device *xpc_chan = &xpc_chan_dbg_subname;
+
+
+/* systune related variables for /proc/sys directories */
+
+static int xpc_hb_min = 1;
+static int xpc_hb_max = 10;
+
+static int xpc_hb_check_min = 10;
+static int xpc_hb_check_max = 120;
+
+static ctl_table xpc_sys_xpc_hb_dir[] = {
+       {
+               1,
+               "hb_interval",
+               &xpc_hb_interval,
+               sizeof(int),
+               0644,
+               NULL,
+               &proc_dointvec_minmax,
+               &sysctl_intvec,
+               NULL,
+               &xpc_hb_min, &xpc_hb_max
+       },
+       {
+               2,
+               "hb_check_interval",
+               &xpc_hb_check_interval,
+               sizeof(int),
+               0644,
+               NULL,
+               &proc_dointvec_minmax,
+               &sysctl_intvec,
+               NULL,
+               &xpc_hb_check_min, &xpc_hb_check_max
+       },
+       {0}
+};
+static ctl_table xpc_sys_xpc_dir[] = {
+       {
+               1,
+               "hb",
+               NULL,
+               0,
+               0555,
+               xpc_sys_xpc_hb_dir
+       },
+       {0}
+};
+static ctl_table xpc_sys_dir[] = {
+       {
+               1,
+               "xpc",
+               NULL,
+               0,
+               0555,
+               xpc_sys_xpc_dir
+       },
+       {0}
+};
+static struct ctl_table_header *xpc_sysctl;
+
+
+/* #of IRQs received */
+static atomic_t xpc_act_IRQ_rcvd;
+
+/* IRQ handler notifies this wait queue on receipt of an IRQ */
+static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq);
+
+static unsigned long xpc_hb_check_timeout;
+
+/* xpc_hb_checker thread exited notification */
+static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited);
+
+/* xpc_discovery thread exited notification */
+static DECLARE_MUTEX_LOCKED(xpc_discovery_exited);
+
+
+static struct timer_list xpc_hb_timer;
+
+
+static void xpc_kthread_waitmsgs(struct xpc_partition *, struct xpc_channel *);
+
+
+/*
+ * Notify the heartbeat check thread that an IRQ has been received.
+ */
+static irqreturn_t
+xpc_act_IRQ_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       atomic_inc(&xpc_act_IRQ_rcvd);
+       wake_up_interruptible(&xpc_act_IRQ_wq);
+       return IRQ_HANDLED;
+}
+
+
+/*
+ * Timer to produce the heartbeat.  The timer structures function is
+ * already set when this is initially called.  A tunable is used to
+ * specify when the next timeout should occur.
+ */
+static void
+xpc_hb_beater(unsigned long dummy)
+{
+       xpc_vars->heartbeat++;
+
+       if (jiffies >= xpc_hb_check_timeout) {
+               wake_up_interruptible(&xpc_act_IRQ_wq);
+       }
+
+       xpc_hb_timer.expires = jiffies + (xpc_hb_interval * HZ);
+       add_timer(&xpc_hb_timer);
+}
+
+
+/*
+ * This thread is responsible for nearly all of the partition
+ * activation/deactivation.
+ */
+static int
+xpc_hb_checker(void *ignore)
+{
+       int last_IRQ_count = 0;
+       int new_IRQ_count;
+       int force_IRQ=0;
+
+
+       /* this thread was marked active by xpc_hb_init() */
+
+       daemonize(XPC_HB_CHECK_THREAD_NAME);
+
+       set_cpus_allowed(current, cpumask_of_cpu(XPC_HB_CHECK_CPU));
+
+       xpc_hb_check_timeout = jiffies + (xpc_hb_check_interval * HZ);
+
+       while (!(volatile int) xpc_exiting) {
+
+               /* wait for IRQ or timeout */
+               (void) wait_event_interruptible(xpc_act_IRQ_wq,
+                           (last_IRQ_count < atomic_read(&xpc_act_IRQ_rcvd) ||
+                                       jiffies >= xpc_hb_check_timeout ||
+                                               (volatile int) xpc_exiting));
+
+               dev_dbg(xpc_part, "woke up with %d ticks rem; %d IRQs have "
+                       "been received\n",
+                       (int) (xpc_hb_check_timeout - jiffies),
+                       atomic_read(&xpc_act_IRQ_rcvd) - last_IRQ_count);
+
+
+               /* checking of remote heartbeats is skewed by IRQ handling */
+               if (jiffies >= xpc_hb_check_timeout) {
+                       dev_dbg(xpc_part, "checking remote heartbeats\n");
+                       xpc_check_remote_hb();
+
+                       /*
+                        * We need to periodically recheck to ensure no
+                        * IPI/AMO pairs have been missed.  That check
+                        * must always reset xpc_hb_check_timeout.
+                        */
+                       force_IRQ = 1;
+               }
+
+
+               new_IRQ_count = atomic_read(&xpc_act_IRQ_rcvd);
+               if (last_IRQ_count < new_IRQ_count || force_IRQ != 0) {
+                       force_IRQ = 0;
+
+                       dev_dbg(xpc_part, "found an IRQ to process; will be "
+                               "resetting xpc_hb_check_timeout\n");
+
+                       last_IRQ_count += xpc_identify_act_IRQ_sender();
+                       if (last_IRQ_count < new_IRQ_count) {
+                               /* retry once to help avoid missing AMO */
+                               (void) xpc_identify_act_IRQ_sender();
+                       }
+                       last_IRQ_count = new_IRQ_count;
+
+                       xpc_hb_check_timeout = jiffies +
+                                          (xpc_hb_check_interval * HZ);
+               }
+       }
+
+       dev_dbg(xpc_part, "heartbeat checker is exiting\n");
+
+
+       /* mark this thread as inactive */
+       up(&xpc_hb_checker_exited);
+       return 0;
+}
+
+
+/*
+ * This thread will attempt to discover other partitions to activate
+ * based on info provided by SAL. This new thread is short lived and
+ * will exit once discovery is complete.
+ */
+static int
+xpc_initiate_discovery(void *ignore)
+{
+       daemonize(XPC_DISCOVERY_THREAD_NAME);
+
+       xpc_discovery();
+
+       dev_dbg(xpc_part, "discovery thread is exiting\n");
+
+       /* mark this thread as inactive */
+       up(&xpc_discovery_exited);
+       return 0;
+}
+
+
+/*
+ * Establish first contact with the remote partititon. This involves pulling
+ * the XPC per partition variables from the remote partition and waiting for
+ * the remote partition to pull ours.
+ */
+static enum xpc_retval
+xpc_make_first_contact(struct xpc_partition *part)
+{
+       enum xpc_retval ret;
+
+
+       while ((ret = xpc_pull_remote_vars_part(part)) != xpcSuccess) {
+               if (ret != xpcRetry) {
+                       XPC_DEACTIVATE_PARTITION(part, ret);
+                       return ret;
+               }
+
+               dev_dbg(xpc_chan, "waiting to make first contact with "
+                       "partition %d\n", XPC_PARTID(part));
+
+               /* wait a 1/4 of a second or so */
+               set_current_state(TASK_INTERRUPTIBLE);
+               (void) schedule_timeout(0.25 * HZ);
+
+               if (part->act_state == XPC_P_DEACTIVATING) {
+                       return part->reason;
+               }
+       }
+
+       return xpc_mark_partition_active(part);
+}
+
+
+/*
+ * The first kthread assigned to a newly activated partition is the one
+ * created by XPC HB with which it calls xpc_partition_up(). XPC hangs on to
+ * that kthread until the partition is brought down, at which time that kthread
+ * returns back to XPC HB. (The return of that kthread will signify to XPC HB
+ * that XPC has dismantled all communication infrastructure for the associated
+ * partition.) This kthread becomes the channel manager for that partition.
+ *
+ * Each active partition has a channel manager, who, besides connecting and
+ * disconnecting channels, will ensure that each of the partition's connected
+ * channels has the required number of assigned kthreads to get the work done.
+ */
+static void
+xpc_channel_mgr(struct xpc_partition *part)
+{
+       while (part->act_state != XPC_P_DEACTIVATING ||
+                               atomic_read(&part->nchannels_active) > 0) {
+
+               xpc_process_channel_activity(part);
+
+
+               /*
+                * Wait until we've been requested to activate kthreads or
+                * all of the channel's message queues have been torn down or
+                * a signal is pending.
+                *
+                * The channel_mgr_requests is set to 1 after being awakened,
+                * This is done to prevent the channel mgr from making one pass
+                * through the loop for each request, since he will
+                * be servicing all the requests in one pass. The reason it's
+                * set to 1 instead of 0 is so that other kthreads will know
+                * that the channel mgr is running and won't bother trying to
+                * wake him up.
+                */
+               atomic_dec(&part->channel_mgr_requests);
+               (void) wait_event_interruptible(part->channel_mgr_wq,
+                               (atomic_read(&part->channel_mgr_requests) > 0 ||
+                               (volatile u64) part->local_IPI_amo != 0 ||
+                               ((volatile u8) part->act_state ==
+                                                       XPC_P_DEACTIVATING &&
+                               atomic_read(&part->nchannels_active) == 0)));
+               atomic_set(&part->channel_mgr_requests, 1);
+
+               // >>> Does it need to wakeup periodically as well? In case we
+               // >>> miscalculated the #of kthreads to wakeup or create?
+       }
+}
+
+
+/*
+ * When XPC HB determines that a partition has come up, it will create a new
+ * kthread and that kthread will call this function to attempt to set up the
+ * basic infrastructure used for Cross Partition Communication with the newly
+ * upped partition.
+ *
+ * The kthread that was created by XPC HB and which setup the XPC
+ * infrastructure will remain assigned to the partition until the partition
+ * goes down. At which time the kthread will teardown the XPC infrastructure
+ * and then exit.
+ *
+ * XPC HB will put the remote partition's XPC per partition specific variables
+ * physical address into xpc_partitions[partid].remote_vars_part_pa prior to
+ * calling xpc_partition_up().
+ */
+static void
+xpc_partition_up(struct xpc_partition *part)
+{
+       DBUG_ON(part->channels != NULL);
+
+       dev_dbg(xpc_chan, "activating partition %d\n", XPC_PARTID(part));
+
+       if (xpc_setup_infrastructure(part) != xpcSuccess) {
+               return;
+       }
+
+       /*
+        * The kthread that XPC HB called us with will become the
+        * channel manager for this partition. It will not return
+        * back to XPC HB until the partition's XPC infrastructure
+        * has been dismantled.
+        */
+
+       (void) xpc_part_ref(part);      /* this will always succeed */
+
+       if (xpc_make_first_contact(part) == xpcSuccess) {
+               xpc_channel_mgr(part);
+       }
+
+       xpc_part_deref(part);
+
+       xpc_teardown_infrastructure(part);
+}
+
+
+static int
+xpc_activating(void *__partid)
+{
+       partid_t partid = (u64) __partid;
+       struct xpc_partition *part = &xpc_partitions[partid];
+       unsigned long irq_flags;
+       struct sched_param param = { sched_priority: MAX_USER_RT_PRIO - 1 };
+       int ret;
+
+
+       DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+
+       spin_lock_irqsave(&part->act_lock, irq_flags);
+
+       if (part->act_state == XPC_P_DEACTIVATING) {
+               part->act_state = XPC_P_INACTIVE;
+               spin_unlock_irqrestore(&part->act_lock, irq_flags);
+               part->remote_rp_pa = 0;
+               return 0;
+       }
+
+       /* indicate the thread is activating */
+       DBUG_ON(part->act_state != XPC_P_ACTIVATION_REQ);
+       part->act_state = XPC_P_ACTIVATING;
+
+       XPC_SET_REASON(part, 0, 0);
+       spin_unlock_irqrestore(&part->act_lock, irq_flags);
+
+       dev_dbg(xpc_part, "bringing partition %d up\n", partid);
+
+       daemonize("xpc%02d", partid);
+
+       /*
+        * This thread needs to run at a realtime priority to prevent a
+        * significant performance degradation.
+        */
+       ret = sched_setscheduler(current, SCHED_FIFO, &param);
+       if (ret != 0) {
+               dev_warn(xpc_part, "unable to set pid %d to a realtime "
+                       "priority, ret=%d\n", current->pid, ret);
+       }
+
+       /* allow this thread and its children to run on any CPU */
+       set_cpus_allowed(current, CPU_MASK_ALL);
+
+       /*
+        * Register the remote partition's AMOs with SAL so it can handle
+        * and cleanup errors within that address range should the remote
+        * partition go down. We don't unregister this range because it is
+        * difficult to tell when outstanding writes to the remote partition
+        * are finished and thus when it is safe to unregister. This should
+        * not result in wasted space in the SAL xp_addr_region table because
+        * we should get the same page for remote_amos_page_pa after module
+        * reloads and system reboots.
+        */
+       if (sn_register_xp_addr_region(part->remote_amos_page_pa,
+                                                       PAGE_SIZE, 1) < 0) {
+               dev_warn(xpc_part, "xpc_partition_up(%d) failed to register "
+                       "xp_addr region\n", partid);
+
+               spin_lock_irqsave(&part->act_lock, irq_flags);
+               part->act_state = XPC_P_INACTIVE;
+               XPC_SET_REASON(part, xpcPhysAddrRegFailed, __LINE__);
+               spin_unlock_irqrestore(&part->act_lock, irq_flags);
+               part->remote_rp_pa = 0;
+               return 0;
+       }
+
+       XPC_ALLOW_HB(partid, xpc_vars);
+       xpc_IPI_send_activated(part);
+
+
+       /*
+        * xpc_partition_up() holds this thread and marks this partition as
+        * XPC_P_ACTIVE by calling xpc_hb_mark_active().
+        */
+       (void) xpc_partition_up(part);
+
+       xpc_mark_partition_inactive(part);
+
+       if (part->reason == xpcReactivating) {
+               /* interrupting ourselves results in activating partition */
+               xpc_IPI_send_reactivate(part);
+       }
+
+       return 0;
+}
+
+
+void
+xpc_activate_partition(struct xpc_partition *part)
+{
+       partid_t partid = XPC_PARTID(part);
+       unsigned long irq_flags;
+       pid_t pid;
+
+
+       spin_lock_irqsave(&part->act_lock, irq_flags);
+
+       pid = kernel_thread(xpc_activating, (void *) ((u64) partid), 0);
+
+       DBUG_ON(part->act_state != XPC_P_INACTIVE);
+
+       if (pid > 0) {
+               part->act_state = XPC_P_ACTIVATION_REQ;
+               XPC_SET_REASON(part, xpcCloneKThread, __LINE__);
+       } else {
+               XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__);
+       }
+
+       spin_unlock_irqrestore(&part->act_lock, irq_flags);
+}
+
+
+/*
+ * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified
+ * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more
+ * than one partition, we use an AMO_t structure per partition to indicate
+ * whether a partition has sent an IPI or not.  >>> If it has, then wake up the
+ * associated kthread to handle it.
+ *
+ * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IPIs sent by XPC
+ * running on other partitions.
+ *
+ * Noteworthy Arguments:
+ *
+ *     irq - Interrupt ReQuest number. NOT USED.
+ *
+ *     dev_id - partid of IPI's potential sender.
+ *
+ *     regs - processor's context before the processor entered
+ *            interrupt code. NOT USED.
+ */
+irqreturn_t
+xpc_notify_IRQ_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       partid_t partid = (partid_t) (u64) dev_id;
+       struct xpc_partition *part = &xpc_partitions[partid];
+
+
+       DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+
+       if (xpc_part_ref(part)) {
+               xpc_check_for_channel_activity(part);
+
+               xpc_part_deref(part);
+       }
+       return IRQ_HANDLED;
+}
+
+
+/*
+ * Check to see if xpc_notify_IRQ_handler() dropped any IPIs on the floor
+ * because the write to their associated IPI amo completed after the IRQ/IPI
+ * was received.
+ */
+void
+xpc_dropped_IPI_check(struct xpc_partition *part)
+{
+       if (xpc_part_ref(part)) {
+               xpc_check_for_channel_activity(part);
+
+               part->dropped_IPI_timer.expires = jiffies +
+                                                       XPC_P_DROPPED_IPI_WAIT;
+               add_timer(&part->dropped_IPI_timer);
+               xpc_part_deref(part);
+       }
+}
+
+
+void
+xpc_activate_kthreads(struct xpc_channel *ch, int needed)
+{
+       int idle = atomic_read(&ch->kthreads_idle);
+       int assigned = atomic_read(&ch->kthreads_assigned);
+       int wakeup;
+
+
+       DBUG_ON(needed <= 0);
+
+       if (idle > 0) {
+               wakeup = (needed > idle) ? idle : needed;
+               needed -= wakeup;
+
+               dev_dbg(xpc_chan, "wakeup %d idle kthreads, partid=%d, "
+                       "channel=%d\n", wakeup, ch->partid, ch->number);
+
+               /* only wakeup the requested number of kthreads */
+               wake_up_nr(&ch->idle_wq, wakeup);
+       }
+
+       if (needed <= 0) {
+               return;
+       }
+
+       if (needed + assigned > ch->kthreads_assigned_limit) {
+               needed = ch->kthreads_assigned_limit - assigned;
+               // >>>should never be less than 0
+               if (needed <= 0) {
+                       return;
+               }
+       }
+
+       dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n",
+               needed, ch->partid, ch->number);
+
+       xpc_create_kthreads(ch, needed);
+}
+
+
+/*
+ * This function is where XPC's kthreads wait for messages to deliver.
+ */
+static void
+xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
+{
+       do {
+               /* deliver messages to their intended recipients */
+
+               while ((volatile s64) ch->w_local_GP.get <
+                               (volatile s64) ch->w_remote_GP.put &&
+                                       !((volatile u32) ch->flags &
+                                               XPC_C_DISCONNECTING)) {
+                       xpc_deliver_msg(ch);
+               }
+
+               if (atomic_inc_return(&ch->kthreads_idle) >
+                                               ch->kthreads_idle_limit) {
+                       /* too many idle kthreads on this channel */
+                       atomic_dec(&ch->kthreads_idle);
+                       break;
+               }
+
+               dev_dbg(xpc_chan, "idle kthread calling "
+                       "wait_event_interruptible_exclusive()\n");
+
+               (void) wait_event_interruptible_exclusive(ch->idle_wq,
+                               ((volatile s64) ch->w_local_GP.get <
+                                       (volatile s64) ch->w_remote_GP.put ||
+                               ((volatile u32) ch->flags &
+                                               XPC_C_DISCONNECTING)));
+
+               atomic_dec(&ch->kthreads_idle);
+
+       } while (!((volatile u32) ch->flags & XPC_C_DISCONNECTING));
+}
+
+
+static int
+xpc_daemonize_kthread(void *args)
+{
+       partid_t partid = XPC_UNPACK_ARG1(args);
+       u16 ch_number = XPC_UNPACK_ARG2(args);
+       struct xpc_partition *part = &xpc_partitions[partid];
+       struct xpc_channel *ch;
+       int n_needed;
+
+
+       daemonize("xpc%02dc%d", partid, ch_number);
+
+       dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n",
+               partid, ch_number);
+
+       ch = &part->channels[ch_number];
+
+       if (!(ch->flags & XPC_C_DISCONNECTING)) {
+               DBUG_ON(!(ch->flags & XPC_C_CONNECTED));
+
+               /* let registerer know that connection has been established */
+
+               if (atomic_read(&ch->kthreads_assigned) == 1) {
+                       xpc_connected_callout(ch);
+
+                       /*
+                        * It is possible that while the callout was being
+                        * made that the remote partition sent some messages.
+                        * If that is the case, we may need to activate
+                        * additional kthreads to help deliver them. We only
+                        * need one less than total #of messages to deliver.
+                        */
+                       n_needed = ch->w_remote_GP.put - ch->w_local_GP.get - 1;
+                       if (n_needed > 0 &&
+                                       !(ch->flags & XPC_C_DISCONNECTING)) {
+                               xpc_activate_kthreads(ch, n_needed);
+                       }
+               }
+
+               xpc_kthread_waitmsgs(part, ch);
+       }
+
+       if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
+                       ((ch->flags & XPC_C_CONNECTCALLOUT) ||
+                               (ch->reason != xpcUnregistering &&
+                                       ch->reason != xpcOtherUnregistering))) {
+               xpc_disconnected_callout(ch);
+       }
+
+
+       xpc_msgqueue_deref(ch);
+
+       dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n",
+               partid, ch_number);
+
+       xpc_part_deref(part);
+       return 0;
+}
+
+
+/*
+ * For each partition that XPC has established communications with, there is
+ * a minimum of one kernel thread assigned to perform any operation that
+ * may potentially sleep or block (basically the callouts to the asynchronous
+ * functions registered via xpc_connect()).
+ *
+ * Additional kthreads are created and destroyed by XPC as the workload
+ * demands.
+ *
+ * A kthread is assigned to one of the active channels that exists for a given
+ * partition.
+ */
+void
+xpc_create_kthreads(struct xpc_channel *ch, int needed)
+{
+       unsigned long irq_flags;
+       pid_t pid;
+       u64 args = XPC_PACK_ARGS(ch->partid, ch->number);
+
+
+       while (needed-- > 0) {
+               pid = kernel_thread(xpc_daemonize_kthread, (void *) args, 0);
+               if (pid < 0) {
+                       /* the fork failed */
+
+                       if (atomic_read(&ch->kthreads_assigned) <
+                                               ch->kthreads_idle_limit) {
+                               /*
+                                * Flag this as an error only if we have an
+                                * insufficient #of kthreads for the channel
+                                * to function.
+                                *
+                                * No xpc_msgqueue_ref() is needed here since
+                                * the channel mgr is doing this.
+                                */
+                               spin_lock_irqsave(&ch->lock, irq_flags);
+                               XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources,
+                                                               &irq_flags);
+                               spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       }
+                       break;
+               }
+
+               /*
+                * The following is done on behalf of the newly created
+                * kthread. That kthread is responsible for doing the
+                * counterpart to the following before it exits.
+                */
+               (void) xpc_part_ref(&xpc_partitions[ch->partid]);
+               xpc_msgqueue_ref(ch);
+               atomic_inc(&ch->kthreads_assigned);
+               ch->kthreads_created++; // >>> temporary debug only!!!
+       }
+}
+
+
+void
+xpc_disconnect_wait(int ch_number)
+{
+       partid_t partid;
+       struct xpc_partition *part;
+       struct xpc_channel *ch;
+
+
+       /* now wait for all callouts to the caller's function to cease */
+       for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+               part = &xpc_partitions[partid];
+
+               if (xpc_part_ref(part)) {
+                       ch = &part->channels[ch_number];
+
+// >>> how do we keep from falling into the window between our check and going
+// >>> down and coming back up where sema is re-inited?
+                       if (ch->flags & XPC_C_SETUP) {
+                               (void) down(&ch->teardown_sema);
+                       }
+
+                       xpc_part_deref(part);
+               }
+       }
+}
+
+
+static void
+xpc_do_exit(void)
+{
+       partid_t partid;
+       int active_part_count;
+       struct xpc_partition *part;
+
+
+       /* now it's time to eliminate our heartbeat */
+       del_timer_sync(&xpc_hb_timer);
+       xpc_vars->heartbeating_to_mask = 0;
+
+       /* indicate to others that our reserved page is uninitialized */
+       xpc_rsvd_page->vars_pa = 0;
+
+       /*
+        * Ignore all incoming interrupts. Without interupts the heartbeat
+        * checker won't activate any new partitions that may come up.
+        */
+       free_irq(SGI_XPC_ACTIVATE, NULL);
+
+       /*
+        * Cause the heartbeat checker and the discovery threads to exit.
+        * We don't want them attempting to activate new partitions as we
+        * try to deactivate the existing ones.
+        */
+       xpc_exiting = 1;
+       wake_up_interruptible(&xpc_act_IRQ_wq);
+
+       /* wait for the heartbeat checker thread to mark itself inactive */
+       down(&xpc_hb_checker_exited);
+
+       /* wait for the discovery thread to mark itself inactive */
+       down(&xpc_discovery_exited);
+
+
+       set_current_state(TASK_INTERRUPTIBLE);
+       schedule_timeout(0.3 * HZ);
+       set_current_state(TASK_RUNNING);
+
+
+       /* wait for all partitions to become inactive */
+
+       do {
+               active_part_count = 0;
+
+               for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+                       part = &xpc_partitions[partid];
+                       if (part->act_state != XPC_P_INACTIVE) {
+                               active_part_count++;
+
+                               XPC_DEACTIVATE_PARTITION(part, xpcUnloading);
+                       }
+               }
+
+               if (active_part_count) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       schedule_timeout(0.3 * HZ);
+                       set_current_state(TASK_RUNNING);
+               }
+
+       } while (active_part_count > 0);
+
+
+       /* close down protections for IPI operations */
+       xpc_restrict_IPI_ops();
+
+
+       /* clear the interface to XPC's functions */
+       xpc_clear_interface();
+
+       if (xpc_sysctl) {
+               unregister_sysctl_table(xpc_sysctl);
+       }
+}
+
+
+int __init
+xpc_init(void)
+{
+       int ret;
+       partid_t partid;
+       struct xpc_partition *part;
+       pid_t pid;
+
+
+       /*
+        * xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng
+        * both a partition's reserved page and its XPC variables. Its size was
+        * based on the size of a reserved page. So we need to ensure that the
+        * XPC variables will fit as well.
+        */
+       if (XPC_VARS_ALIGNED_SIZE > XPC_RSVD_PAGE_ALIGNED_SIZE) {
+               dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n");
+               return -EPERM;
+       }
+       DBUG_ON((u64) xpc_remote_copy_buffer !=
+                               L1_CACHE_ALIGN((u64) xpc_remote_copy_buffer));
+
+       snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
+       snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
+
+       xpc_sysctl = register_sysctl_table(xpc_sys_dir, 1);
+
+       /*
+        * The first few fields of each entry of xpc_partitions[] need to
+        * be initialized now so that calls to xpc_connect() and
+        * xpc_disconnect() can be made prior to the activation of any remote
+        * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE
+        * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING
+        * PARTITION HAS BEEN ACTIVATED.
+        */
+       for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+               part = &xpc_partitions[partid];
+
+               DBUG_ON((u64) part != L1_CACHE_ALIGN((u64) part));
+
+               part->act_IRQ_rcvd = 0;
+               spin_lock_init(&part->act_lock);
+               part->act_state = XPC_P_INACTIVE;
+               XPC_SET_REASON(part, 0, 0);
+               part->setup_state = XPC_P_UNSET;
+               init_waitqueue_head(&part->teardown_wq);
+               atomic_set(&part->references, 0);
+       }
+
+       /*
+        * Open up protections for IPI operations (and AMO operations on
+        * Shub 1.1 systems).
+        */
+       xpc_allow_IPI_ops();
+
+       /*
+        * Interrupts being processed will increment this atomic variable and
+        * awaken the heartbeat thread which will process the interrupts.
+        */
+       atomic_set(&xpc_act_IRQ_rcvd, 0);
+
+       /*
+        * This is safe to do before the xpc_hb_checker thread has started
+        * because the handler releases a wait queue.  If an interrupt is
+        * received before the thread is waiting, it will not go to sleep,
+        * but rather immediately process the interrupt.
+        */
+       ret = request_irq(SGI_XPC_ACTIVATE, xpc_act_IRQ_handler, 0,
+                                                       "xpc hb", NULL);
+       if (ret != 0) {
+               dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "
+                       "errno=%d\n", -ret);
+
+               xpc_restrict_IPI_ops();
+
+               if (xpc_sysctl) {
+                       unregister_sysctl_table(xpc_sysctl);
+               }
+               return -EBUSY;
+       }
+
+       /*
+        * Fill the partition reserved page with the information needed by
+        * other partitions to discover we are alive and establish initial
+        * communications.
+        */
+       xpc_rsvd_page = xpc_rsvd_page_init();
+       if (xpc_rsvd_page == NULL) {
+               dev_err(xpc_part, "could not setup our reserved page\n");
+
+               free_irq(SGI_XPC_ACTIVATE, NULL);
+               xpc_restrict_IPI_ops();
+
+               if (xpc_sysctl) {
+                       unregister_sysctl_table(xpc_sysctl);
+               }
+               return -EBUSY;
+       }
+
+
+       /*
+        * Set the beating to other partitions into motion.  This is
+        * the last requirement for other partitions' discovery to
+        * initiate communications with us.
+        */
+       init_timer(&xpc_hb_timer);
+       xpc_hb_timer.function = xpc_hb_beater;
+       xpc_hb_beater(0);
+
+
+       /*
+        * The real work-horse behind xpc.  This processes incoming
+        * interrupts and monitors remote heartbeats.
+        */
+       pid = kernel_thread(xpc_hb_checker, NULL, 0);
+       if (pid < 0) {
+               dev_err(xpc_part, "failed while forking hb check thread\n");
+
+               /* indicate to others that our reserved page is uninitialized */
+               xpc_rsvd_page->vars_pa = 0;
+
+               del_timer_sync(&xpc_hb_timer);
+               free_irq(SGI_XPC_ACTIVATE, NULL);
+               xpc_restrict_IPI_ops();
+
+               if (xpc_sysctl) {
+                       unregister_sysctl_table(xpc_sysctl);
+               }
+               return -EBUSY;
+       }
+
+
+       /*
+        * Startup a thread that will attempt to discover other partitions to
+        * activate based on info provided by SAL. This new thread is short
+        * lived and will exit once discovery is complete.
+        */
+       pid = kernel_thread(xpc_initiate_discovery, NULL, 0);
+       if (pid < 0) {
+               dev_err(xpc_part, "failed while forking discovery thread\n");
+
+               /* mark this new thread as a non-starter */
+               up(&xpc_discovery_exited);
+
+               xpc_do_exit();
+               return -EBUSY;
+       }
+
+
+       /* set the interface to point at XPC's functions */
+       xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect,
+                         xpc_initiate_allocate, xpc_initiate_send,
+                         xpc_initiate_send_notify, xpc_initiate_received,
+                         xpc_initiate_partid_to_nasids);
+
+       return 0;
+}
+module_init(xpc_init);
+
+
+void __exit
+xpc_exit(void)
+{
+       xpc_do_exit();
+}
+module_exit(xpc_exit);
+
+
+MODULE_AUTHOR("Silicon Graphics, Inc.");
+MODULE_DESCRIPTION("Cross Partition Communication (XPC) support");
+MODULE_LICENSE("GPL");
+
+module_param(xpc_hb_interval, int, 0);
+MODULE_PARM_DESC(xpc_hb_interval, "Number of seconds between "
+               "heartbeat increments.");
+
+module_param(xpc_hb_check_interval, int, 0);
+MODULE_PARM_DESC(xpc_hb_check_interval, "Number of seconds between "
+               "heartbeat checks.");
+
diff -urN linux/arch/ia64/sn/kernel/xpc_partition.c 
linux/arch/ia64/sn/kernel/xpc_partition.c
--- linux/arch/ia64/sn/kernel/xpc_partition.c   1970/01/01 00:00:00
+++ linux/arch/ia64/sn/kernel/xpc_partition.c   2005-05-19 13:08:10.816582000 
+0100     1.1
@@ -0,0 +1,984 @@
+/*
+ * 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-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * Cross Partition Communication (XPC) partition support.
+ *
+ *     This is the part of XPC that detects the presence/absence of
+ *     other partitions. It provides a heartbeat and monitors the
+ *     heartbeats of other partitions.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/sysctl.h>
+#include <linux/cache.h>
+#include <linux/mmzone.h>
+#include <linux/nodemask.h>
+#include <asm/sn/bte.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/addrs.h>
+#include "xpc.h"
+
+
+/* XPC is exiting flag */
+int xpc_exiting;
+
+
+/* SH_IPI_ACCESS shub register value on startup */
+static u64 xpc_sh1_IPI_access;
+static u64 xpc_sh2_IPI_access0;
+static u64 xpc_sh2_IPI_access1;
+static u64 xpc_sh2_IPI_access2;
+static u64 xpc_sh2_IPI_access3;
+
+
+/* original protection values for each node */
+u64 xpc_prot_vec[MAX_COMPACT_NODES];
+
+
+/* this partition's reserved page */
+struct xpc_rsvd_page *xpc_rsvd_page;
+
+/* this partition's XPC variables (within the reserved page) */
+struct xpc_vars *xpc_vars;
+struct xpc_vars_part *xpc_vars_part;
+
+
+/*
+ * For performance reasons, each entry of xpc_partitions[] is cacheline
+ * aligned. And xpc_partitions[] is padded with an additional entry at the
+ * end so that the last legitimate entry doesn't share its cacheline with
+ * another variable.
+ */
+struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
+
+
+/*
+ * Generic buffer used to store a local copy of the remote partitions
+ * reserved page or XPC variables.
+ *
+ * xpc_discovery runs only once and is a seperate thread that is
+ * very likely going to be processing in parallel with receiving
+ * interrupts.
+ */
+char ____cacheline_aligned
+               xpc_remote_copy_buffer[XPC_RSVD_PAGE_ALIGNED_SIZE];
+
+
+/* systune related variables */
+int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
+int xpc_hb_check_interval = XPC_HB_CHECK_DEFAULT_TIMEOUT;
+
+
+/*
+ * Given a nasid, get the physical address of the  partition's reserved page
+ * for that nasid. This function returns 0 on any error.
+ */
+static u64
+xpc_get_rsvd_page_pa(int nasid, u64 buf, u64 buf_size)
+{
+       bte_result_t bte_res;
+       s64 status;
+       u64 cookie = 0;
+       u64 rp_pa = nasid;      /* seed with nasid */
+       u64 len = 0;
+
+
+       while (1) {
+
+               status = sn_partition_reserved_page_pa(buf, &cookie, &rp_pa,
+                                                               &len);
+
+               dev_dbg(xpc_part, "SAL returned with status=%li, cookie="
+                       "0x%016lx, address=0x%016lx, len=0x%016lx\n",
+                       status, cookie, rp_pa, len);
+
+               if (status != SALRET_MORE_PASSES) {
+                       break;
+               }
+
+               if (len > buf_size) {
+                       dev_err(xpc_part, "len (=0x%016lx) > buf_size\n", len);
+                       status = SALRET_ERROR;
+                       break;
+               }
+
+               bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_size,
+                                       (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+               if (bte_res != BTE_SUCCESS) {
+                       dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
+                       status = SALRET_ERROR;
+                       break;
+               }
+       }
+
+       if (status != SALRET_OK) {
+               rp_pa = 0;
+       }
+       dev_dbg(xpc_part, "reserved page at phys address 0x%016lx\n", rp_pa);
+       return rp_pa;
+}
+
+
+/*
+ * Fill the partition reserved page with the information needed by
+ * other partitions to discover we are alive and establish initial
+ * communications.
+ */
+struct xpc_rsvd_page *
+xpc_rsvd_page_init(void)
+{
+       struct xpc_rsvd_page *rp;
+       AMO_t *amos_page;
+       u64 rp_pa, next_cl, nasid_array = 0;
+       int i, ret;
+
+
+       /* get the local reserved page's address */
+
+       rp_pa = xpc_get_rsvd_page_pa(cnodeid_to_nasid(0),
+                                       (u64) xpc_remote_copy_buffer,
+                                               XPC_RSVD_PAGE_ALIGNED_SIZE);
+       if (rp_pa == 0) {
+               dev_err(xpc_part, "SAL failed to locate the reserved page\n");
+               return NULL;
+       }
+       rp = (struct xpc_rsvd_page *) __va(rp_pa);
+
+       if (rp->partid != sn_partition_id) {
+               dev_err(xpc_part, "the reserved page's partid of %d should be "
+                       "%d\n", rp->partid, sn_partition_id);
+               return NULL;
+       }
+
+       rp->version = XPC_RP_VERSION;
+
+       /*
+        * Place the XPC variables on the cache line following the
+        * reserved page structure.
+        */
+       next_cl = (u64) rp + XPC_RSVD_PAGE_ALIGNED_SIZE;
+       xpc_vars = (struct xpc_vars *) next_cl;
+
+       /*
+        * Before clearing xpc_vars, see if a page of AMOs had been previously
+        * allocated. If not we'll need to allocate one and set permissions
+        * so that cross-partition AMOs are allowed.
+        *
+        * The allocated AMO page needs MCA reporting to remain disabled after
+        * XPC has unloaded.  To make this work, we keep a copy of the pointer
+        * to this page (i.e., amos_page) in the struct xpc_vars structure,
+        * which is pointed to by the reserved page, and re-use that saved copy
+        * on subsequent loads of XPC. This AMO page is never freed, and its
+        * memory protections are never restricted.
+        */
+       if ((amos_page = xpc_vars->amos_page) == NULL) {
+               amos_page = (AMO_t *) mspec_kalloc_page(0);
+               if (amos_page == NULL) {
+                       dev_err(xpc_part, "can't allocate page of AMOs\n");
+                       return NULL;
+               }
+
+               /*
+                * Open up AMO-R/W to cpu.  This is done for Shub 1.1 systems
+                * when xpc_allow_IPI_ops() is called via xpc_hb_init().
+                */
+               if (!enable_shub_wars_1_1()) {
+                       ret = sn_change_memprotect(ia64_tpa((u64) amos_page),
+                                       PAGE_SIZE, SN_MEMPROT_ACCESS_CLASS_1,
+                                       &nasid_array);
+                       if (ret != 0) {
+                               dev_err(xpc_part, "can't change memory "
+                                       "protections\n");
+                               mspec_kfree_page((unsigned long) amos_page);
+                               return NULL;
+                       }
+               }
+       } else if (!IS_AMO_ADDRESS((u64) amos_page)) {
+               /*
+                * EFI's XPBOOT can also set amos_page in the reserved page,
+                * but it happens to leave it as an uncached physical address
+                * and we need it to be an uncached virtual, so we'll have to
+                * convert it.
+                */
+               if (!IS_AMO_PHYS_ADDRESS((u64) amos_page)) {
+                       dev_err(xpc_part, "previously used amos_page address "
+                               "is bad = 0x%p\n", (void *) amos_page);
+                       return NULL;
+               }
+               amos_page = (AMO_t *) TO_AMO((u64) amos_page);
+       }
+
+       memset(xpc_vars, 0, sizeof(struct xpc_vars));
+
+       /*
+        * Place the XPC per partition specific variables on the cache line
+        * following the XPC variables structure.
+        */
+       next_cl += XPC_VARS_ALIGNED_SIZE;
+       memset((u64 *) next_cl, 0, sizeof(struct xpc_vars_part) *
+                                                       XP_MAX_PARTITIONS);
+       xpc_vars_part = (struct xpc_vars_part *) next_cl;
+       xpc_vars->vars_part_pa = __pa(next_cl);
+
+       xpc_vars->version = XPC_V_VERSION;
+       xpc_vars->act_nasid = cpuid_to_nasid(0);
+       xpc_vars->act_phys_cpuid = cpu_physical_id(0);
+       xpc_vars->amos_page = amos_page;  /* save for next load of XPC */
+
+
+       /*
+        * Initialize the activation related AMO variables.
+        */
+       xpc_vars->act_amos = xpc_IPI_init(XP_MAX_PARTITIONS);
+       for (i = 1; i < XP_NASID_MASK_WORDS; i++) {
+               xpc_IPI_init(i + XP_MAX_PARTITIONS);
+       }
+       /* export AMO page's physical address to other partitions */
+       xpc_vars->amos_page_pa = ia64_tpa((u64) xpc_vars->amos_page);
+
+       /*
+        * This signifies to the remote partition that our reserved
+        * page is initialized.
+        */
+       (volatile u64) rp->vars_pa = __pa(xpc_vars);
+
+       return rp;
+}
+
+
+/*
+ * Change protections to allow IPI operations (and AMO operations on
+ * Shub 1.1 systems).
+ */
+void
+xpc_allow_IPI_ops(void)
+{
+       int node;
+       int nasid;
+
+
+       // >>> Change SH_IPI_ACCESS code to use SAL call once it is available.
+
+       if (is_shub2()) {
+               xpc_sh2_IPI_access0 =
+                       (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
+               xpc_sh2_IPI_access1 =
+                       (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
+               xpc_sh2_IPI_access2 =
+                       (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
+               xpc_sh2_IPI_access3 =
+                       (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));
+
+               for_each_online_node(node) {
+                       nasid = cnodeid_to_nasid(node);
+                       HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
+                                                               -1UL);
+                       HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
+                                                               -1UL);
+                       HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
+                                                               -1UL);
+                       HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
+                                                               -1UL);
+               }
+
+       } else {
+               xpc_sh1_IPI_access =
+                       (u64) HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_IPI_ACCESS));
+
+               for_each_online_node(node) {
+                       nasid = cnodeid_to_nasid(node);
+                       HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
+                                                               -1UL);
+
+                       /*
+                        * Since the BIST collides with memory operations on
+                        * SHUB 1.1 sn_change_memprotect() cannot be used.
+                        */
+                       if (enable_shub_wars_1_1()) {
+                               /* open up everything */
+                               xpc_prot_vec[node] = (u64) HUB_L((u64 *)
+                                               GLOBAL_MMR_ADDR(nasid,
+                                               SH1_MD_DQLP_MMR_DIR_PRIVEC0));
+                               HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+                                               SH1_MD_DQLP_MMR_DIR_PRIVEC0),
+                                                               -1UL);
+                               HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+                                               SH1_MD_DQRP_MMR_DIR_PRIVEC0),
+                                                               -1UL);
+                       }
+               }
+       }
+}
+
+
+/*
+ * Restrict protections to disallow IPI operations (and AMO operations on
+ * Shub 1.1 systems).
+ */
+void
+xpc_restrict_IPI_ops(void)
+{
+       int node;
+       int nasid;
+
+
+       // >>> Change SH_IPI_ACCESS code to use SAL call once it is available.
+
+       if (is_shub2()) {
+
+               for_each_online_node(node) {
+                       nasid = cnodeid_to_nasid(node);
+                       HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
+                                                       xpc_sh2_IPI_access0);
+                       HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
+                                                       xpc_sh2_IPI_access1);
+                       HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
+                                                       xpc_sh2_IPI_access2);
+                       HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
+                                                       xpc_sh2_IPI_access3);
+               }
+
+       } else {
+
+               for_each_online_node(node) {
+                       nasid = cnodeid_to_nasid(node);
+                       HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
+                                                       xpc_sh1_IPI_access);
+
+                       if (enable_shub_wars_1_1()) {
+                               HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+                                               SH1_MD_DQLP_MMR_DIR_PRIVEC0),
+                                                       xpc_prot_vec[node]);
+                               HUB_S((u64 *) GLOBAL_MMR_ADDR(nasid,
+                                               SH1_MD_DQRP_MMR_DIR_PRIVEC0),
+                                                       xpc_prot_vec[node]);
+                       }
+               }
+       }
+}
+
+
+/*
+ * At periodic intervals, scan through all active partitions and ensure
+ * their heartbeat is still active.  If not, the partition is deactivated.
+ */
+void
+xpc_check_remote_hb(void)
+{
+       struct xpc_vars *remote_vars;
+       struct xpc_partition *part;
+       partid_t partid;
+       bte_result_t bres;
+
+
+       remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;
+
+       for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+               if (partid == sn_partition_id) {
+                       continue;
+               }
+
+               part = &xpc_partitions[partid];
+
+               if (part->act_state == XPC_P_INACTIVE ||
+                               part->act_state == XPC_P_DEACTIVATING) {
+                       continue;
+               }
+
+               /* pull the remote_hb cache line */
+               bres = xp_bte_copy(part->remote_vars_pa,
+                                       ia64_tpa((u64) remote_vars),
+                                       XPC_VARS_ALIGNED_SIZE,
+                                       (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+               if (bres != BTE_SUCCESS) {
+                       XPC_DEACTIVATE_PARTITION(part,
+                                               xpc_map_bte_errors(bres));
+                       continue;
+               }
+
+               dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"
+                       " = %ld, kdb_status = %ld, HB_mask = 0x%lx\n", partid,
+                       remote_vars->heartbeat, part->last_heartbeat,
+                       remote_vars->kdb_status,
+                       remote_vars->heartbeating_to_mask);
+
+               if (((remote_vars->heartbeat == part->last_heartbeat) &&
+                       (remote_vars->kdb_status == 0)) ||
+                            !XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {
+
+                       XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat);
+                       continue;
+               }
+
+               part->last_heartbeat = remote_vars->heartbeat;
+       }
+}
+
+
+/*
+ * Get a copy of the remote partition's rsvd page.
+ *
+ * remote_rp points to a buffer that is cacheline aligned for BTE copies and
+ * assumed to be of size XPC_RSVD_PAGE_ALIGNED_SIZE.
+ */
+static enum xpc_retval
+xpc_get_remote_rp(int nasid, u64 *discovered_nasids,
+               struct xpc_rsvd_page *remote_rp, u64 *remote_rsvd_page_pa)
+{
+       int bres, i;
+
+
+       /* get the reserved page's physical address */
+
+       *remote_rsvd_page_pa = xpc_get_rsvd_page_pa(nasid, (u64) remote_rp,
+                                               XPC_RSVD_PAGE_ALIGNED_SIZE);
+       if (*remote_rsvd_page_pa == 0) {
+               return xpcNoRsvdPageAddr;
+       }
+
+
+       /* pull over the reserved page structure */
+
+       bres = xp_bte_copy(*remote_rsvd_page_pa, ia64_tpa((u64) remote_rp),
+                               XPC_RSVD_PAGE_ALIGNED_SIZE,
+                               (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+       if (bres != BTE_SUCCESS) {
+               return xpc_map_bte_errors(bres);
+       }
+
+
+       if (discovered_nasids != NULL) {
+               for (i = 0; i < XP_NASID_MASK_WORDS; i++) {
+                       discovered_nasids[i] |= remote_rp->part_nasids[i];
+               }
+       }
+
+
+       /* check that the partid is for another partition */
+
+       if (remote_rp->partid < 1 ||
+                               remote_rp->partid > (XP_MAX_PARTITIONS - 1)) {
+               return xpcInvalidPartid;
+       }
+
+       if (remote_rp->partid == sn_partition_id) {
+               return xpcLocalPartid;
+       }
+
+
+       if (XPC_VERSION_MAJOR(remote_rp->version) !=
+                                       XPC_VERSION_MAJOR(XPC_RP_VERSION)) {
+               return xpcBadVersion;
+       }
+
+       return xpcSuccess;
+}
+
+
+/*
+ * Get a copy of the remote partition's XPC variables.
+ *
+ * remote_vars points to a buffer that is cacheline aligned for BTE copies and
+ * assumed to be of size XPC_VARS_ALIGNED_SIZE.
+ */
+static enum xpc_retval
+xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars)
+{
+       int bres;
+
+
+       if (remote_vars_pa == 0) {
+               return xpcVarsNotSet;
+       }
+
+
+       /* pull over the cross partition variables */
+
+       bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars),
+                               XPC_VARS_ALIGNED_SIZE,
+                               (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+       if (bres != BTE_SUCCESS) {
+               return xpc_map_bte_errors(bres);
+       }
+
+       if (XPC_VERSION_MAJOR(remote_vars->version) !=
+                                       XPC_VERSION_MAJOR(XPC_V_VERSION)) {
+               return xpcBadVersion;
+       }
+
+       return xpcSuccess;
+}
+
+
+/*
+ * Prior code has determine the nasid which generated an IPI.  Inspect
+ * that nasid to determine if its partition needs to be activated or
+ * deactivated.
+ *
+ * A partition is consider "awaiting activation" if our partition
+ * flags indicate it is not active and it has a heartbeat.  A
+ * partition is considered "awaiting deactivation" if our partition
+ * flags indicate it is active but it has no heartbeat or it is not
+ * sending its heartbeat to us.
+ *
+ * To determine the heartbeat, the remote nasid must have a properly
+ * initialized reserved page.
+ */
+static void
+xpc_identify_act_IRQ_req(int nasid)
+{
+       struct xpc_rsvd_page *remote_rp;
+       struct xpc_vars *remote_vars;
+       u64 remote_rsvd_page_pa;
+       u64 remote_vars_pa;
+       partid_t partid;
+       struct xpc_partition *part;
+       enum xpc_retval ret;
+
+
+       /* pull over the reserved page structure */
+
+       remote_rp = (struct xpc_rsvd_page *) xpc_remote_copy_buffer;
+
+       ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rsvd_page_pa);
+       if (ret != xpcSuccess) {
+               dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
+                       "which sent interrupt, reason=%d\n", nasid, ret);
+               return;
+       }
+
+       remote_vars_pa = remote_rp->vars_pa;
+       partid = remote_rp->partid;
+       part = &xpc_partitions[partid];
+
+
+       /* pull over the cross partition variables */
+
+       remote_vars = (struct xpc_vars *) xpc_remote_copy_buffer;
+
+       ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
+       if (ret != xpcSuccess) {
+
+               dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
+                       "which sent interrupt, reason=%d\n", nasid, ret);
+
+               XPC_DEACTIVATE_PARTITION(part, ret);
+               return;
+       }
+
+
+       part->act_IRQ_rcvd++;
+
+       dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
+               "%ld:0x%lx\n", (int) nasid, (int) partid, part->act_IRQ_rcvd,
+               remote_vars->heartbeat, remote_vars->heartbeating_to_mask);
+
+
+       if (part->act_state == XPC_P_INACTIVE) {
+
+               part->remote_rp_pa = remote_rsvd_page_pa;
+               dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n",
+                       part->remote_rp_pa);
+
+               part->remote_vars_pa = remote_vars_pa;
+               dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
+                       part->remote_vars_pa);
+
+               part->last_heartbeat = remote_vars->heartbeat;
+               dev_dbg(xpc_part, "  last_heartbeat = 0x%016lx\n",
+                       part->last_heartbeat);
+
+               part->remote_vars_part_pa = remote_vars->vars_part_pa;
+               dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
+                       part->remote_vars_part_pa);
+
+               part->remote_act_nasid = remote_vars->act_nasid;
+               dev_dbg(xpc_part, "  remote_act_nasid = 0x%x\n",
+                       part->remote_act_nasid);
+
+               part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
+               dev_dbg(xpc_part, "  remote_act_phys_cpuid = 0x%x\n",
+                       part->remote_act_phys_cpuid);
+
+               part->remote_amos_page_pa = remote_vars->amos_page_pa;
+               dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
+                       part->remote_amos_page_pa);
+
+               xpc_activate_partition(part);
+
+       } else if (part->remote_amos_page_pa != remote_vars->amos_page_pa ||
+                       !XPC_HB_ALLOWED(sn_partition_id, remote_vars)) {
+
+               part->reactivate_nasid = nasid;
+               XPC_DEACTIVATE_PARTITION(part, xpcReactivating);
+       }
+}
+
+
+/*
+ * Loop through the activation AMO variables and process any bits
+ * which are set.  Each bit indicates a nasid sending a partition
+ * activation or deactivation request.
+ *
+ * Return #of IRQs detected.
+ */
+int
+xpc_identify_act_IRQ_sender(void)
+{
+       int word, bit;
+       u64 nasid_mask;
+       u64 nasid;                      /* remote nasid */
+       int n_IRQs_detected = 0;
+       AMO_t *act_amos;
+       struct xpc_rsvd_page *rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
+
+
+       act_amos = xpc_vars->act_amos;
+
+
+       /* scan through act AMO variable looking for non-zero entries */
+       for (word = 0; word < XP_NASID_MASK_WORDS; word++) {
+
+               nasid_mask = xpc_IPI_receive(&act_amos[word]);
+               if (nasid_mask == 0) {
+                       /* no IRQs from nasids in this variable */
+                       continue;
+               }
+
+               dev_dbg(xpc_part, "AMO[%d] gave back 0x%lx\n", word,
+                       nasid_mask);
+
+
+               /*
+                * If this nasid has been added to the machine since
+                * our partition was reset, this will retain the
+                * remote nasid in our reserved pages machine mask.
+                * This is used in the event of module reload.
+                */
+               rp->mach_nasids[word] |= nasid_mask;
+
+
+               /* locate the nasid(s) which sent interrupts */
+
+               for (bit = 0; bit < (8 * sizeof(u64)); bit++) {
+                       if (nasid_mask & (1UL << bit)) {
+                               n_IRQs_detected++;
+                               nasid = XPC_NASID_FROM_W_B(word, bit);
+                               dev_dbg(xpc_part, "interrupt from nasid %ld\n",
+                                       nasid);
+                               xpc_identify_act_IRQ_req(nasid);
+                       }
+               }
+       }
+       return n_IRQs_detected;
+}
+
+
+/*
+ * Mark specified partition as active.
+ */
+enum xpc_retval
+xpc_mark_partition_active(struct xpc_partition *part)
+{
+       unsigned long irq_flags;
+       enum xpc_retval ret;
+
+
+       dev_dbg(xpc_part, "setting partition %d to ACTIVE\n", XPC_PARTID(part));
+
+       spin_lock_irqsave(&part->act_lock, irq_flags);
+       if (part->act_state == XPC_P_ACTIVATING) {
+               part->act_state = XPC_P_ACTIVE;
+               ret = xpcSuccess;
+       } else {
+               DBUG_ON(part->reason == xpcSuccess);
+               ret = part->reason;
+       }
+       spin_unlock_irqrestore(&part->act_lock, irq_flags);
+
+       return ret;
+}
+
+
+/*
+ * Notify XPC that the partition is down.
+ */
+void
+xpc_deactivate_partition(const int line, struct xpc_partition *part,
+                               enum xpc_retval reason)
+{
+       unsigned long irq_flags;
+       partid_t partid = XPC_PARTID(part);
+
+
+       spin_lock_irqsave(&part->act_lock, irq_flags);
+
+       if (part->act_state == XPC_P_INACTIVE) {
+               XPC_SET_REASON(part, reason, line);
+               spin_unlock_irqrestore(&part->act_lock, irq_flags);
+               if (reason == xpcReactivating) {
+                       /* we interrupt ourselves to reactivate partition */
+                       xpc_IPI_send_reactivate(part);
+               }
+               return;
+       }
+       if (part->act_state == XPC_P_DEACTIVATING) {
+               if ((part->reason == xpcUnloading && reason != xpcUnloading) ||
+                                       reason == xpcReactivating) {
+                       XPC_SET_REASON(part, reason, line);
+               }
+               spin_unlock_irqrestore(&part->act_lock, irq_flags);
+               return;
+       }
+
+       part->act_state = XPC_P_DEACTIVATING;
+       XPC_SET_REASON(part, reason, line);
+
+       spin_unlock_irqrestore(&part->act_lock, irq_flags);
+
+       XPC_DISALLOW_HB(partid, xpc_vars);
+
+       dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n", partid,
+               reason);
+
+       xpc_partition_down(part, reason);
+}
+
+
+/*
+ * Mark specified partition as active.
+ */
+void
+xpc_mark_partition_inactive(struct xpc_partition *part)
+{
+       unsigned long irq_flags;
+
+
+       dev_dbg(xpc_part, "setting partition %d to INACTIVE\n",
+               XPC_PARTID(part));
+
+       spin_lock_irqsave(&part->act_lock, irq_flags);
+       part->act_state = XPC_P_INACTIVE;
+       spin_unlock_irqrestore(&part->act_lock, irq_flags);
+       part->remote_rp_pa = 0;
+}
+
+
+/*
+ * SAL has provided a partition and machine mask.  The partition mask
+ * contains a bit for each even nasid in our partition.  The machine
+ * mask contains a bit for each even nasid in the entire machine.
+ *
+ * Using those two bit arrays, we can determine which nasids are
+ * known in the machine.  Each should also have a reserved page
+ * initialized if they are available for partitioning.
+ */
+void
+xpc_discovery(void)
+{
+       void *remote_rp_base;
+       struct xpc_rsvd_page *remote_rp;
+       struct xpc_vars *remote_vars;
+       u64 remote_rsvd_page_pa;
+       u64 remote_vars_pa;
+       int region;
+       int max_regions;
+       int nasid;
+       struct xpc_rsvd_page *rp;
+       partid_t partid;
+       struct xpc_partition *part;
+       u64 *discovered_nasids;
+       enum xpc_retval ret;
+
+
+       remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RSVD_PAGE_ALIGNED_SIZE,
+                                               GFP_KERNEL, &remote_rp_base);
+       if (remote_rp == NULL) {
+               return;
+       }
+       remote_vars = (struct xpc_vars *) remote_rp;
+
+
+       discovered_nasids = kmalloc(sizeof(u64) * XP_NASID_MASK_WORDS,
+                                                       GFP_KERNEL);
+       if (discovered_nasids == NULL) {
+               kfree(remote_rp_base);
+               return;
+       }
+       memset(discovered_nasids, 0, sizeof(u64) * XP_NASID_MASK_WORDS);
+
+       rp = (struct xpc_rsvd_page *) xpc_rsvd_page;
+
+       /*
+        * The term 'region' in this context refers to the minimum number of
+        * nodes that can comprise an access protection grouping. The access
+        * protection is in regards to memory, IOI and IPI.
+        */
+//>>> move the next two #defines into either include/asm-ia64/sn/arch.h or
+//>>> include/asm-ia64/sn/addrs.h
+#define SH1_MAX_REGIONS                64
+#define SH2_MAX_REGIONS                256
+       max_regions = is_shub2() ? SH2_MAX_REGIONS : SH1_MAX_REGIONS;
+
+       for (region = 0; region < max_regions; region++) {
+
+               if ((volatile int) xpc_exiting) {
+                       break;
+               }
+
+               dev_dbg(xpc_part, "searching region %d\n", region);
+
+               for (nasid = (region * sn_region_size * 2);
+                    nasid < ((region + 1) * sn_region_size * 2);
+                    nasid += 2) {
+
+                       if ((volatile int) xpc_exiting) {
+                               break;
+                       }
+
+                       dev_dbg(xpc_part, "checking nasid %d\n", nasid);
+
+
+                       if (XPC_NASID_IN_ARRAY(nasid, rp->part_nasids)) {
+                               dev_dbg(xpc_part, "PROM indicates Nasid %d is "
+                                       "part of the local partition; skipping "
+                                       "region\n", nasid);
+                               break;
+                       }
+
+                       if (!(XPC_NASID_IN_ARRAY(nasid, rp->mach_nasids))) {
+                               dev_dbg(xpc_part, "PROM indicates Nasid %d was "
+                                       "not on Numa-Link network at reset\n",
+                                       nasid);
+                               continue;
+                       }
+
+                       if (XPC_NASID_IN_ARRAY(nasid, discovered_nasids)) {
+                               dev_dbg(xpc_part, "Nasid %d is part of a "
+                                       "partition which was previously "
+                                       "discovered\n", nasid);
+                               continue;
+                       }
+
+
+                       /* pull over the reserved page structure */
+
+                       ret = xpc_get_remote_rp(nasid, discovered_nasids,
+                                             remote_rp, &remote_rsvd_page_pa);
+                       if (ret != xpcSuccess) {
+                               dev_dbg(xpc_part, "unable to get reserved page "
+                                       "from nasid %d, reason=%d\n", nasid,
+                                       ret);
+
+                               if (ret == xpcLocalPartid) {
+                                       break;
+                               }
+                               continue;
+                       }
+
+                       remote_vars_pa = remote_rp->vars_pa;
+
+                       partid = remote_rp->partid;
+                       part = &xpc_partitions[partid];
+
+
+                       /* pull over the cross partition variables */
+
+                       ret = xpc_get_remote_vars(remote_vars_pa, remote_vars);
+                       if (ret != xpcSuccess) {
+                               dev_dbg(xpc_part, "unable to get XPC variables "
+                                       "from nasid %d, reason=%d\n", nasid,
+                                       ret);
+
+                               XPC_DEACTIVATE_PARTITION(part, ret);
+                               continue;
+                       }
+
+                       if (part->act_state != XPC_P_INACTIVE) {
+                               dev_dbg(xpc_part, "partition %d on nasid %d is "
+                                       "already activating\n", partid, nasid);
+                               break;
+                       }
+
+                       /*
+                        * Register the remote partition's AMOs with SAL so it
+                        * can handle and cleanup errors within that address
+                        * range should the remote partition go down. We don't
+                        * unregister this range because it is difficult to
+                        * tell when outstanding writes to the remote partition
+                        * are finished and thus when it is thus safe to
+                        * unregister. This should not result in wasted space
+                        * in the SAL xp_addr_region table because we should
+                        * get the same page for remote_act_amos_pa after
+                        * module reloads and system reboots.
+                        */
+                       if (sn_register_xp_addr_region(
+                                           remote_vars->amos_page_pa,
+                                                       PAGE_SIZE, 1) < 0) {
+                               dev_dbg(xpc_part, "partition %d failed to "
+                                       "register xp_addr region 0x%016lx\n",
+                                       partid, remote_vars->amos_page_pa);
+
+                               XPC_SET_REASON(part, xpcPhysAddrRegFailed,
+                                               __LINE__);
+                               break;
+                       }
+
+                       /*
+                        * The remote nasid is valid and available.
+                        * Send an interrupt to that nasid to notify
+                        * it that we are ready to begin activation.
+                        */
+                       dev_dbg(xpc_part, "sending an interrupt to AMO 0x%lx, "
+                               "nasid %d, phys_cpuid 0x%x\n",
+                               remote_vars->amos_page_pa,
+                               remote_vars->act_nasid,
+                               remote_vars->act_phys_cpuid);
+
+                       xpc_IPI_send_activate(remote_vars);
+               }
+       }
+
+       kfree(discovered_nasids);
+       kfree(remote_rp_base);
+}
+
+
+/*
+ * Given a partid, get the nasids owned by that partition from the
+ * remote partition's reserved page.
+ */
+enum xpc_retval
+xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask)
+{
+       struct xpc_partition *part;
+       u64 part_nasid_pa;
+       int bte_res;
+
+
+       part = &xpc_partitions[partid];
+       if (part->remote_rp_pa == 0) {
+               return xpcPartitionDown;
+       }
+
+       part_nasid_pa = part->remote_rp_pa +
+               (u64) &((struct xpc_rsvd_page *) 0)->part_nasids;
+
+       bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask),
+                               L1_CACHE_ALIGN(XP_NASID_MASK_BYTES),
+                               (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+
+       return xpc_map_bte_errors(bte_res);
+}
+
diff -urN linux/arch/ia64/sn/kernel/xpnet.c linux/arch/ia64/sn/kernel/xpnet.c
--- linux/arch/ia64/sn/kernel/xpnet.c   1970/01/01 00:00:00
+++ linux/arch/ia64/sn/kernel/xpnet.c   2005-05-19 13:08:10.836601000 +0100     
1.1
@@ -0,0 +1,715 @@
+/*
+ * 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,2001-2005 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+/*
+ * Cross Partition Network Interface (XPNET) support
+ *
+ *     XPNET provides a virtual network layered on top of the Cross
+ *     Partition communication layer.
+ *
+ *     XPNET provides direct point-to-point and broadcast-like support
+ *     for an ethernet-like device.  The ethernet broadcast medium is
+ *     replaced with a point-to-point message structure which passes
+ *     pointers to a DMA-capable block that a remote partition should
+ *     retrieve and pass to the upper level networking layer.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/smp.h>
+#include <linux/string.h>
+#include <asm/sn/bte.h>
+#include <asm/sn/io.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/types.h>
+#include <asm/atomic.h>
+#include <asm/sn/xp.h>
+
+
+/*
+ * The message payload transferred by XPC.
+ *
+ * buf_pa is the physical address where the DMA should pull from.
+ *
+ * NOTE: for performance reasons, buf_pa should _ALWAYS_ begin on a
+ * cacheline boundary.  To accomplish this, we record the number of
+ * bytes from the beginning of the first cacheline to the first useful
+ * byte of the skb (leadin_ignore) and the number of bytes from the
+ * last useful byte of the skb to the end of the last cacheline
+ * (tailout_ignore).
+ *
+ * size is the number of bytes to transfer which includes the skb->len
+ * (useful bytes of the senders skb) plus the leadin and tailout
+ */
+struct xpnet_message {
+       u16 version;            /* Version for this message */
+       u16 embedded_bytes;     /* #of bytes embedded in XPC message */
+       u32 magic;              /* Special number indicating this is xpnet */
+       u64 buf_pa;             /* phys address of buffer to retrieve */
+       u32 size;               /* #of bytes in buffer */
+       u8 leadin_ignore;       /* #of bytes to ignore at the beginning */
+       u8 tailout_ignore;      /* #of bytes to ignore at the end */
+       unsigned char data;     /* body of small packets */
+};
+
+/*
+ * Determine the size of our message, the cacheline aligned size,
+ * and then the number of message will request from XPC.
+ *
+ * XPC expects each message to exist in an individual cacheline.
+ */
+#define XPNET_MSG_SIZE         (L1_CACHE_BYTES - XPC_MSG_PAYLOAD_OFFSET)
+#define XPNET_MSG_DATA_MAX     \
+               (XPNET_MSG_SIZE - (u64)(&((struct xpnet_message *)0)->data))
+#define XPNET_MSG_ALIGNED_SIZE (L1_CACHE_ALIGN(XPNET_MSG_SIZE))
+#define XPNET_MSG_NENTRIES     (PAGE_SIZE / XPNET_MSG_ALIGNED_SIZE)
+
+
+#define XPNET_MAX_KTHREADS     (XPNET_MSG_NENTRIES + 1)
+#define XPNET_MAX_IDLE_KTHREADS        (XPNET_MSG_NENTRIES + 1)
+
+/*
+ * Version number of XPNET implementation. XPNET can always talk to versions
+ * with same major #, and never talk to versions with a different version.
+ */
+#define _XPNET_VERSION(_major, _minor) (((_major) << 4) | (_minor))
+#define XPNET_VERSION_MAJOR(_v)                ((_v) >> 4)
+#define XPNET_VERSION_MINOR(_v)                ((_v) & 0xf)
+
+#define        XPNET_VERSION _XPNET_VERSION(1,0)               /* version 1.0 
*/
+#define        XPNET_VERSION_EMBED _XPNET_VERSION(1,1)         /* version 1.1 
*/
+#define XPNET_MAGIC    0x88786984 /* "XNET" */
+
+#define XPNET_VALID_MSG(_m)                                                 \
+   ((XPNET_VERSION_MAJOR(_m->version) == XPNET_VERSION_MAJOR(XPNET_VERSION)) \
+    && (msg->magic == XPNET_MAGIC))
+
+#define XPNET_DEVICE_NAME              "xp0"
+
+
+/*
+ * When messages are queued with xpc_send_notify, a kmalloc'd buffer
+ * of the following type is passed as a notification cookie.  When the
+ * notification function is called, we use the cookie to decide
+ * whether all outstanding message sends have completed.  The skb can
+ * then be released.
+ */
+struct xpnet_pending_msg {
+       struct list_head free_list;
+       struct sk_buff *skb;
+       atomic_t use_count;
+};
+
+/* driver specific structure pointed to by the device structure */
+struct xpnet_dev_private {
+       struct net_device_stats stats;
+};
+
+struct net_device *xpnet_device;
+
+/*
+ * When we are notified of other partitions activating, we add them to
+ * our bitmask of partitions to which we broadcast.
+ */
+static u64 xpnet_broadcast_partitions;
+/* protect above */
+static spinlock_t xpnet_broadcast_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Since the Block Transfer Engine (BTE) is being used for the transfer
+ * and it relies upon cache-line size transfers, we need to reserve at
+ * least one cache-line for head and tail alignment.  The BTE is
+ * limited to 8MB transfers.
+ *
+ * Testing has shown that changing MTU to greater than 64KB has no effect
+ * on TCP as the two sides negotiate a Max Segment Size that is limited
+ * to 64K.  Other protocols May use packets greater than this, but for
+ * now, the default is 64KB.
+ */
+#define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)
+/* 32KB has been determined to be the ideal */
+#define XPNET_DEF_MTU (0x8000UL)
+
+
+/*
+ * The partition id is encapsulated in the MAC address.  The following
+ * define locates the octet the partid is in.
+ */
+#define XPNET_PARTID_OCTET     1
+#define XPNET_LICENSE_OCTET    2
+
+
+/*
+ * Define the XPNET debug device structure that is to be used with dev_dbg(),
+ * dev_err(), dev_warn(), and dev_info().
+ */
+struct device_driver xpnet_dbg_name = {
+       .name = "xpnet"
+};
+
+struct device xpnet_dbg_subname = {
+       .bus_id = {0},                  /* set to "" */
+       .driver = &xpnet_dbg_name
+};
+
+struct device *xpnet = &xpnet_dbg_subname;
+
+/*
+ * Packet was recevied by XPC and forwarded to us.
+ */
+static void
+xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg)
+{
+       struct sk_buff *skb;
+       bte_result_t bret;
+       struct xpnet_dev_private *priv =
+               (struct xpnet_dev_private *) xpnet_device->priv;
+
+
+       if (!XPNET_VALID_MSG(msg)) {
+               /*
+                * Packet with a different XPC version.  Ignore.
+                */
+               xpc_received(partid, channel, (void *) msg);
+
+               priv->stats.rx_errors++;
+
+               return;
+       }
+       dev_dbg(xpnet, "received 0x%lx, %d, %d, %d\n", msg->buf_pa, msg->size,
+               msg->leadin_ignore, msg->tailout_ignore);
+
+
+       /* reserve an extra cache line */
+       skb = dev_alloc_skb(msg->size + L1_CACHE_BYTES);
+       if (!skb) {
+               dev_err(xpnet, "failed on dev_alloc_skb(%d)\n",
+                       msg->size + L1_CACHE_BYTES);
+
+               xpc_received(partid, channel, (void *) msg);
+
+               priv->stats.rx_errors++;
+
+               return;
+       }
+
+       /*
+        * The allocated skb has some reserved space.
+        * In order to use bte_copy, we need to get the
+        * skb->data pointer moved forward.
+        */
+       skb_reserve(skb, (L1_CACHE_BYTES - ((u64)skb->data &
+                                           (L1_CACHE_BYTES - 1)) +
+                         msg->leadin_ignore));
+
+       /*
+        * Update the tail pointer to indicate data actually
+        * transferred.
+        */
+       skb_put(skb, (msg->size - msg->leadin_ignore - msg->tailout_ignore));
+
+       /*
+        * Move the data over from the the other side.
+        */
+       if ((XPNET_VERSION_MINOR(msg->version) == 1) &&
+                                               (msg->embedded_bytes != 0)) {
+               dev_dbg(xpnet, "copying embedded message. memcpy(0x%p, 0x%p, "
+                       "%lu)\n", skb->data, &msg->data,
+                       (size_t) msg->embedded_bytes);
+
+               memcpy(skb->data, &msg->data, (size_t) msg->embedded_bytes);
+       } else {
+               dev_dbg(xpnet, "transferring buffer to the skb->data area;\n\t"
+                       "bte_copy(0x%p, 0x%p, %hu)\n", (void *)msg->buf_pa,
+                       (void *)__pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
+                       msg->size);
+
+               bret = bte_copy(msg->buf_pa,
+                               __pa((u64)skb->data & ~(L1_CACHE_BYTES - 1)),
+                               msg->size, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
+
+               if (bret != BTE_SUCCESS) {
+                       // >>> Need better way of cleaning skb.  Currently skb
+                       // >>> appears in_use and we can't just call
+                       // >>> dev_kfree_skb.
+                       dev_err(xpnet, "bte_copy(0x%p, 0x%p, 0x%hx) returned "
+                               "error=0x%x\n", (void *)msg->buf_pa,
+                               (void *)__pa((u64)skb->data &
+                                                       ~(L1_CACHE_BYTES - 1)),
+                               msg->size, bret);
+
+                       xpc_received(partid, channel, (void *) msg);
+
+                       priv->stats.rx_errors++;
+
+                       return;
+               }
+       }
+
+       dev_dbg(xpnet, "<skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+               "skb->end=0x%p skb->len=%d\n", (void *) skb->head,
+               (void *) skb->data, (void *) skb->tail, (void *) skb->end,
+               skb->len);
+
+       skb->dev = xpnet_device;
+       skb->protocol = eth_type_trans(skb, xpnet_device);
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+       dev_dbg(xpnet, "passing skb to network layer; \n\tskb->head=0x%p "
+               "skb->data=0x%p skb->tail=0x%p skb->end=0x%p skb->len=%d\n",
+               (void *) skb->head, (void *) skb->data, (void *) skb->tail,
+               (void *) skb->end, skb->len);
+
+
+       xpnet_device->last_rx = jiffies;
+       priv->stats.rx_packets++;
+       priv->stats.rx_bytes += skb->len + ETH_HLEN;
+
+       netif_rx_ni(skb);
+       xpc_received(partid, channel, (void *) msg);
+}
+
+
+/*
+ * This is the handler which XPC calls during any sort of change in
+ * state or message reception on a connection.
+ */
+static void
+xpnet_connection_activity(enum xpc_retval reason, partid_t partid, int channel,
+                         void *data, void *key)
+{
+       long bp;
+
+
+       DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS);
+       DBUG_ON(channel != XPC_NET_CHANNEL);
+
+       switch(reason) {
+       case xpcMsgReceived:    /* message received */
+               DBUG_ON(data == NULL);
+
+               xpnet_receive(partid, channel, (struct xpnet_message *) data);
+               break;
+
+       case xpcConnected:      /* connection completed to a partition */
+               spin_lock_bh(&xpnet_broadcast_lock);
+               xpnet_broadcast_partitions |= 1UL << (partid -1 );
+               bp = xpnet_broadcast_partitions;
+               spin_unlock_bh(&xpnet_broadcast_lock);
+
+               netif_carrier_on(xpnet_device);
+
+               dev_dbg(xpnet, "%s connection created to partition %d; "
+                       "xpnet_broadcast_partitions=0x%lx\n",
+                       xpnet_device->name, partid, bp);
+               break;
+
+       default:
+               spin_lock_bh(&xpnet_broadcast_lock);
+               xpnet_broadcast_partitions &= ~(1UL << (partid -1 ));
+               bp = xpnet_broadcast_partitions;
+               spin_unlock_bh(&xpnet_broadcast_lock);
+
+               if (bp == 0) {
+                       netif_carrier_off(xpnet_device);
+               }
+
+               dev_dbg(xpnet, "%s disconnected from partition %d; "
+                       "xpnet_broadcast_partitions=0x%lx\n",
+                       xpnet_device->name, partid, bp);
+               break;
+
+       }
+}
+
+
+static int
+xpnet_dev_open(struct net_device *dev)
+{
+       enum xpc_retval ret;
+
+
+       dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %d, "
+               "%d)\n", XPC_NET_CHANNEL, xpnet_connection_activity,
+               XPNET_MSG_SIZE, XPNET_MSG_NENTRIES, XPNET_MAX_KTHREADS,
+               XPNET_MAX_IDLE_KTHREADS);
+
+       ret = xpc_connect(XPC_NET_CHANNEL, xpnet_connection_activity, NULL,
+                         XPNET_MSG_SIZE, XPNET_MSG_NENTRIES,
+                         XPNET_MAX_KTHREADS, XPNET_MAX_IDLE_KTHREADS);
+       if (ret != xpcSuccess) {
+               dev_err(xpnet, "ifconfig up of %s failed on XPC connect, "
+                       "ret=%d\n", dev->name, ret);
+
+               return -ENOMEM;
+       }
+
+       dev_dbg(xpnet, "ifconfig up of %s; XPC connected\n", dev->name);
+
+       return 0;
+}
+
+
+static int
+xpnet_dev_stop(struct net_device *dev)
+{
+       xpc_disconnect(XPC_NET_CHANNEL);
+
+       dev_dbg(xpnet, "ifconfig down of %s; XPC disconnected\n", dev->name);
+
+       return 0;
+}
+
+
+static int
+xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)
+{
+       /* 68 comes from min TCP+IP+MAC header */
+       if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) {
+               dev_err(xpnet, "ifconfig %s mtu %d failed; value must be "
+                       "between 68 and %ld\n", dev->name, new_mtu,
+                       XPNET_MAX_MTU);
+               return -EINVAL;
+       }
+
+       dev->mtu = new_mtu;
+       dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu);
+       return 0;
+}
+
+
+/*
+ * Required for the net_device structure.
+ */
+static int
+xpnet_dev_set_config(struct net_device *dev, struct ifmap *new_map)
+{
+       return 0;
+}
+
+
+/*
+ * Return statistics to the caller.
+ */
+static struct net_device_stats *
+xpnet_dev_get_stats(struct net_device *dev)
+{
+       struct xpnet_dev_private *priv;
+
+
+       priv = (struct xpnet_dev_private *) dev->priv;
+
+       return &priv->stats;
+}
+
+
+/*
+ * Notification that the other end has received the message and
+ * DMA'd the skb information.  At this point, they are done with
+ * our side.  When all recipients are done processing, we
+ * release the skb and then release our pending message structure.
+ */
+static void
+xpnet_send_completed(enum xpc_retval reason, partid_t partid, int channel,
+                       void *__qm)
+{
+       struct xpnet_pending_msg *queued_msg =
+               (struct xpnet_pending_msg *) __qm;
+
+
+       DBUG_ON(queued_msg == NULL);
+
+       dev_dbg(xpnet, "message to %d notified with reason %d\n",
+               partid, reason);
+
+       if (atomic_dec_return(&queued_msg->use_count) == 0) {
+               dev_dbg(xpnet, "all acks for skb->head=-x%p\n",
+                       (void *) queued_msg->skb->head);
+
+               dev_kfree_skb_any(queued_msg->skb);
+               kfree(queued_msg);
+       }
+}
+
+
+/*
+ * Network layer has formatted a packet (skb) and is ready to place it
+ * "on the wire".  Prepare and send an xpnet_message to all partitions
+ * which have connected with us and are targets of this packet.
+ *
+ * MAC-NOTE:  For the XPNET driver, the MAC address contains the
+ * destination partition_id.  If the destination partition id word
+ * is 0xff, this packet is to broadcast to all partitions.
+ */
+static int
+xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct xpnet_pending_msg *queued_msg;
+       enum xpc_retval ret;
+       struct xpnet_message *msg;
+       u64 start_addr, end_addr;
+       long dp;
+       u8 second_mac_octet;
+       partid_t dest_partid;
+       struct xpnet_dev_private *priv;
+       u16 embedded_bytes;
+
+
+       priv = (struct xpnet_dev_private *) dev->priv;
+
+
+       dev_dbg(xpnet, ">skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+               "skb->end=0x%p skb->len=%d\n", (void *) skb->head,
+               (void *) skb->data, (void *) skb->tail, (void *) skb->end,
+               skb->len);
+
+
+       /*
+        * The xpnet_pending_msg tracks how many outstanding
+        * xpc_send_notifies are relying on this skb.  When none
+        * remain, release the skb.
+        */
+       queued_msg = kmalloc(sizeof(struct xpnet_pending_msg), GFP_ATOMIC);
+       if (queued_msg == NULL) {
+               dev_warn(xpnet, "failed to kmalloc %ld bytes; dropping "
+                       "packet\n", sizeof(struct xpnet_pending_msg));
+
+               priv->stats.tx_errors++;
+
+               return -ENOMEM;
+       }
+
+
+       /* get the beginning of the first cacheline and end of last */
+       start_addr = ((u64) skb->data & ~(L1_CACHE_BYTES - 1));
+       end_addr = L1_CACHE_ALIGN((u64) skb->tail);
+
+       /* calculate how many bytes to embed in the XPC message */
+       embedded_bytes = 0;
+       if (unlikely(skb->len <= XPNET_MSG_DATA_MAX)) {
+               /* skb->data does fit so embed */
+               embedded_bytes = skb->len;
+       }
+
+
+       /*
+        * Since the send occurs asynchronously, we set the count to one
+        * and begin sending.  Any sends that happen to complete before
+        * we are done sending will not free the skb.  We will be left
+        * with that task during exit.  This also handles the case of
+        * a packet destined for a partition which is no longer up.
+        */
+       atomic_set(&queued_msg->use_count, 1);
+       queued_msg->skb = skb;
+
+
+       second_mac_octet = skb->data[XPNET_PARTID_OCTET];
+       if (second_mac_octet == 0xff) {
+               /* we are being asked to broadcast to all partitions */
+               dp = xpnet_broadcast_partitions;
+       } else if (second_mac_octet != 0) {
+               dp = xpnet_broadcast_partitions &
+                                       (1UL << (second_mac_octet - 1));
+       } else {
+               /* 0 is an invalid partid.  Ignore */
+               dp = 0;
+       }
+       dev_dbg(xpnet, "destination Partitions mask (dp) = 0x%lx\n", dp);
+
+       /*
+        * If we wanted to allow promiscous mode to work like an
+        * unswitched network, this would be a good point to OR in a
+        * mask of partitions which should be receiving all packets.
+        */
+
+       /*
+        * Main send loop.
+        */
+       for (dest_partid = 1; dp && dest_partid < XP_MAX_PARTITIONS;
+            dest_partid++) {
+
+
+               if (!(dp & (1UL << (dest_partid - 1)))) {
+                       /* not destined for this partition */
+                       continue;
+               }
+
+               /* remove this partition from the destinations mask */
+               dp &= ~(1UL << (dest_partid - 1));
+
+
+               /* found a partition to send to */
+
+               ret = xpc_allocate(dest_partid, XPC_NET_CHANNEL,
+                                  XPC_NOWAIT, (void **)&msg);
+               if (unlikely(ret != xpcSuccess)) {
+                       continue;
+               }
+
+               msg->embedded_bytes = embedded_bytes;
+               if (unlikely(embedded_bytes != 0)) {
+                       msg->version = XPNET_VERSION_EMBED;
+                       dev_dbg(xpnet, "calling memcpy(0x%p, 0x%p, 0x%lx)\n",
+                               &msg->data, skb->data, (size_t) embedded_bytes);
+                       memcpy(&msg->data, skb->data, (size_t) embedded_bytes);
+               } else {
+                       msg->version = XPNET_VERSION;
+               }
+               msg->magic = XPNET_MAGIC;
+               msg->size = end_addr - start_addr;
+               msg->leadin_ignore = (u64) skb->data - start_addr;
+               msg->tailout_ignore = end_addr - (u64) skb->tail;
+               msg->buf_pa = __pa(start_addr);
+
+               dev_dbg(xpnet, "sending XPC message to %d:%d\nmsg->buf_pa="
+                       "0x%lx, msg->size=%u, msg->leadin_ignore=%u, "
+                       "msg->tailout_ignore=%u\n", dest_partid,
+                       XPC_NET_CHANNEL, msg->buf_pa, msg->size,
+                       msg->leadin_ignore, msg->tailout_ignore);
+
+
+               atomic_inc(&queued_msg->use_count);
+
+               ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, msg,
+                                     xpnet_send_completed, queued_msg);
+               if (unlikely(ret != xpcSuccess)) {
+                       atomic_dec(&queued_msg->use_count);
+                       continue;
+               }
+
+       }
+
+       if (atomic_dec_return(&queued_msg->use_count) == 0) {
+               dev_dbg(xpnet, "no partitions to receive packet destined for "
+                       "%d\n", dest_partid);
+
+
+               dev_kfree_skb(skb);
+               kfree(queued_msg);
+       }
+
+       priv->stats.tx_packets++;
+       priv->stats.tx_bytes += skb->len;
+
+       return 0;
+}
+
+
+/*
+ * Deal with transmit timeouts coming from the network layer.
+ */
+static void
+xpnet_dev_tx_timeout (struct net_device *dev)
+{
+       struct xpnet_dev_private *priv;
+
+
+       priv = (struct xpnet_dev_private *) dev->priv;
+
+       priv->stats.tx_errors++;
+       return;
+}
+
+
+static int __init
+xpnet_init(void)
+{
+       int i;
+       u32 license_num;
+       int result = -ENOMEM;
+
+
+       dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);
+
+       /*
+        * use ether_setup() to init the majority of our device
+        * structure and then override the necessary pieces.
+        */
+       xpnet_device = alloc_netdev(sizeof(struct xpnet_dev_private),
+                                   XPNET_DEVICE_NAME, ether_setup);
+       if (xpnet_device == NULL) {
+               return -ENOMEM;
+       }
+
+       netif_carrier_off(xpnet_device);
+
+       xpnet_device->mtu = XPNET_DEF_MTU;
+       xpnet_device->change_mtu = xpnet_dev_change_mtu;
+       xpnet_device->open = xpnet_dev_open;
+       xpnet_device->get_stats = xpnet_dev_get_stats;
+       xpnet_device->stop = xpnet_dev_stop;
+       xpnet_device->hard_start_xmit = xpnet_dev_hard_start_xmit;
+       xpnet_device->tx_timeout = xpnet_dev_tx_timeout;
+       xpnet_device->set_config = xpnet_dev_set_config;
+
+       /*
+        * Multicast assumes the LSB of the first octet is set for multicast
+        * MAC addresses.  We chose the first octet of the MAC to be unlikely
+        * to collide with any vendor's officially issued MAC.
+        */
+       xpnet_device->dev_addr[0] = 0xfe;
+       xpnet_device->dev_addr[XPNET_PARTID_OCTET] = sn_partition_id;
+       license_num = sn_partition_serial_number_val();
+       for (i = 3; i >= 0; i--) {
+               xpnet_device->dev_addr[XPNET_LICENSE_OCTET + i] =
+                                                       license_num & 0xff;
+               license_num = license_num >> 8;
+       }
+
+       /*
+        * ether_setup() sets this to a multicast device.  We are
+        * really not supporting multicast at this time.
+        */
+       xpnet_device->flags &= ~IFF_MULTICAST;
+
+       /*
+        * No need to checksum as it is a DMA transfer.  The BTE will
+        * report an error if the data is not retrievable and the
+        * packet will be dropped.
+        */
+       xpnet_device->features = NETIF_F_NO_CSUM;
+
+       result = register_netdev(xpnet_device);
+       if (result != 0) {
+               free_netdev(xpnet_device);
+       }
+
+       return result;
+}
+module_init(xpnet_init);
+
+
+static void __exit
+xpnet_exit(void)
+{
+       dev_info(xpnet, "unregistering network device %s\n",
+               xpnet_device[0].name);
+
+       unregister_netdev(xpnet_device);
+
+       free_netdev(xpnet_device);
+}
+module_exit(xpnet_exit);
+
+
+MODULE_AUTHOR("Silicon Graphics, Inc.");
+MODULE_DESCRIPTION("Cross Partition Network adapter (XPNET)");
+MODULE_LICENSE("GPL");
+
diff -urN linux/arch/ia64/sn/kernel/Makefile linux/arch/ia64/sn/kernel/Makefile
--- linux/arch/ia64/sn/kernel/Makefile  2004/10/25 20:44:15     1.15
+++ linux/arch/ia64/sn/kernel/Makefile  2005/05/19 12:08:10     1.16
@@ -4,9 +4,15 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1999,2001-2003 Silicon Graphics, Inc.  All Rights Reserved.
+# Copyright (C) 1999,2001-2005 Silicon Graphics, Inc.  All Rights Reserved.
 #
 
 obj-y                          += setup.o bte.o bte_error.o irq.o mca.o idle.o 
\
                                   huberror.o io_init.o iomv.o klconflib.o sn2/
 obj-$(CONFIG_IA64_GENERIC)      += machvec.o
+obj-$(CONFIG_SGI_TIOCX)                += tiocx.o
+obj-$(CONFIG_IA64_SGI_SN_XP)   += xp.o
+xp-y                           := xp_main.o xp_nofault.o
+obj-$(CONFIG_IA64_SGI_SN_XP)   += xpc.o
+xpc-y                          := xpc_main.o xpc_channel.o xpc_partition.o
+obj-$(CONFIG_IA64_SGI_SN_XP)   += xpnet.o
diff -urN linux/arch/ia64/sn/kernel/bte.c linux/arch/ia64/sn/kernel/bte.c
--- linux/arch/ia64/sn/kernel/bte.c     2005/02/13 20:16:17     1.11
+++ linux/arch/ia64/sn/kernel/bte.c     2005/05/19 12:08:10     1.12
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 #include <linux/config.h>
@@ -170,10 +170,6 @@
        /* Initialize the notification to a known value. */
        *bte->most_rcnt_na = BTE_WORD_BUSY;
 
-       /* Set the status reg busy bit and transfer length */
-       BTE_PRINTKV(("IBLS = 0x%lx\n", IBLS_BUSY | transfer_size));
-       BTE_LNSTAT_STORE(bte, IBLS_BUSY | transfer_size);
-
        /* Set the source and destination registers */
        BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src))));
        BTE_SRC_STORE(bte, TO_PHYS(src));
@@ -188,7 +184,7 @@
 
        /* Initiate the transfer */
        BTE_PRINTK(("IBCT = 0x%lx)\n", BTE_VALID_MODE(mode)));
-       BTE_CTRL_STORE(bte, BTE_VALID_MODE(mode));
+       BTE_START_TRANSFER(bte, transfer_size, BTE_VALID_MODE(mode));
 
        itc_end = ia64_get_itc() + (40000000 * local_cpu_data->cyc_per_usec);
 
@@ -429,10 +425,16 @@
        mynodepda->bte_recovery_timer.data = (unsigned long)mynodepda;
 
        for (i = 0; i < BTES_PER_NODE; i++) {
+               u64 *base_addr;
+
                /* Which link status register should we use? */
-               unsigned long link_status = (i == 0 ? IIO_IBLS0 : IIO_IBLS1);
-               mynodepda->bte_if[i].bte_base_addr = (u64 *)
-                   REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), link_status);
+               base_addr = (u64 *)
+                   REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), BTE_BASE_ADDR(i));
+               mynodepda->bte_if[i].bte_base_addr = base_addr;
+               mynodepda->bte_if[i].bte_source_addr = 
BTE_SOURCE_ADDR(base_addr);
+               mynodepda->bte_if[i].bte_destination_addr = 
BTE_DEST_ADDR(base_addr);
+               mynodepda->bte_if[i].bte_control_addr = 
BTE_CTRL_ADDR(base_addr);
+               mynodepda->bte_if[i].bte_notify_addr = 
BTE_NOTIF_ADDR(base_addr);
 
                /*
                 * Initialize the notification and spinlock
diff -urN linux/arch/ia64/sn/kernel/bte_error.c 
linux/arch/ia64/sn/kernel/bte_error.c
--- linux/arch/ia64/sn/kernel/bte_error.c       2005/02/13 20:16:17     1.4
+++ linux/arch/ia64/sn/kernel/bte_error.c       2005/05/19 12:08:10     1.5
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 #include <linux/types.h>
@@ -33,48 +33,28 @@
  * Wait until all BTE related CRBs are completed
  * and then reset the interfaces.
  */
-void bte_error_handler(unsigned long _nodepda)
+void shub1_bte_error_handler(unsigned long _nodepda)
 {
        struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
-       spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
        struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
        nasid_t nasid;
        int i;
        int valid_crbs;
-       unsigned long irq_flags;
-       volatile u64 *notify;
-       bte_result_t bh_error;
        ii_imem_u_t imem;       /* II IMEM Register */
        ii_icrb0_d_u_t icrbd;   /* II CRB Register D */
        ii_ibcr_u_t ibcr;
        ii_icmr_u_t icmr;
        ii_ieclr_u_t ieclr;
 
-       BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
+       BTE_PRINTK(("shub1_bte_error_handler(%p) - %d\n", err_nodepda,
                    smp_processor_id()));
 
-       spin_lock_irqsave(recovery_lock, irq_flags);
-
        if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) &&
            (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
                BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
                            smp_processor_id()));
-               spin_unlock_irqrestore(recovery_lock, irq_flags);
                return;
        }
-       /*
-        * Lock all interfaces on this node to prevent new transfers
-        * from being queued.
-        */
-       for (i = 0; i < BTES_PER_NODE; i++) {
-               if (err_nodepda->bte_if[i].cleanup_active) {
-                       continue;
-               }
-               spin_lock(&err_nodepda->bte_if[i].spinlock);
-               BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
-                           smp_processor_id(), i));
-               err_nodepda->bte_if[i].cleanup_active = 1;
-       }
 
        /* Determine information about our hub */
        nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
@@ -101,7 +81,6 @@
                mod_timer(recovery_timer, HZ * 5);
                BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
                            smp_processor_id()));
-               spin_unlock_irqrestore(recovery_lock, irq_flags);
                return;
        }
        if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
@@ -120,8 +99,6 @@
                                BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
                                            err_nodepda, smp_processor_id(),
                                            i));
-                               spin_unlock_irqrestore(recovery_lock,
-                                                      irq_flags);
                                return;
                        }
                }
@@ -146,6 +123,51 @@
        ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
        REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
 
+       del_timer(recovery_timer);
+}
+
+/*
+ * Wait until all BTE related CRBs are completed
+ * and then reset the interfaces.
+ */
+void bte_error_handler(unsigned long _nodepda)
+{
+       struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
+       spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
+       int i;
+       nasid_t nasid;
+       unsigned long irq_flags;
+       volatile u64 *notify;
+       bte_result_t bh_error;
+
+       BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
+                   smp_processor_id()));
+
+       spin_lock_irqsave(recovery_lock, irq_flags);
+
+       /*
+        * Lock all interfaces on this node to prevent new transfers
+        * from being queued.
+        */
+       for (i = 0; i < BTES_PER_NODE; i++) {
+               if (err_nodepda->bte_if[i].cleanup_active) {
+                       continue;
+               }
+               spin_lock(&err_nodepda->bte_if[i].spinlock);
+               BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
+                           smp_processor_id(), i));
+               err_nodepda->bte_if[i].cleanup_active = 1;
+       }
+
+       if (is_shub1()) {
+               shub1_bte_error_handler(_nodepda);
+       } else {
+               nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
+
+               if (ia64_sn_bte_recovery(nasid))
+                       panic("bte_error_handler(): Fatal BTE Error");
+       }
+
        for (i = 0; i < BTES_PER_NODE; i++) {
                bh_error = err_nodepda->bte_if[i].bh_error;
                if (bh_error != BTE_SUCCESS) {
@@ -165,8 +187,6 @@
                spin_unlock(&err_nodepda->bte_if[i].spinlock);
        }
 
-       del_timer(recovery_timer);
-
        spin_unlock_irqrestore(recovery_lock, irq_flags);
 }
 
diff -urN linux/arch/ia64/sn/kernel/huberror.c 
linux/arch/ia64/sn/kernel/huberror.c
--- linux/arch/ia64/sn/kernel/huberror.c        2005/02/13 20:16:17     1.2
+++ linux/arch/ia64/sn/kernel/huberror.c        2005/05/19 12:08:10     1.3
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000,2002-2004 Silicon Graphics, Inc. All rights 
reserved.
+ * Copyright (C) 1992 - 1997, 2000,2002-2005 Silicon Graphics, Inc. All rights 
reserved.
  */
 
 #include <linux/types.h>
@@ -38,8 +38,11 @@
        if ((int)ret_stuff.v0)
                panic("hubii_eint_handler(): Fatal TIO Error");
 
-       if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
-               (void)hubiio_crb_error_handler(hubdev_info);
+       if (is_shub1()) {
+               if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
+                       (void)hubiio_crb_error_handler(hubdev_info);
+       } else 
+               bte_error_handler((unsigned 
long)NODEPDA(nasid_to_cnodeid(nasid)));
 
        return IRQ_HANDLED;
 }
diff -urN linux/arch/ia64/sn/kernel/io_init.c 
linux/arch/ia64/sn/kernel/io_init.c
--- linux/arch/ia64/sn/kernel/io_init.c 2005/01/25 04:27:58     1.4
+++ linux/arch/ia64/sn/kernel/io_init.c 2005/05/19 12:08:10     1.5
@@ -11,14 +11,15 @@
 #include <asm/sn/types.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/pcibr_provider.h"
 #include "xtalk/xwidgetdev.h"
 #include <asm/sn/geo.h>
 #include "xtalk/hubdev.h"
 #include <asm/sn/io.h>
 #include <asm/sn/simulator.h>
+#include <asm/sn/tioca_provider.h>
 
 char master_baseio_wid;
 nasid_t master_nasid = INVALID_NASID;  /* Partition Master */
@@ -34,6 +35,37 @@
 
 int sn_ioif_inited = 0;                /* SN I/O infrastructure initialized? */
 
+struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES];      /* 
indexed by asic type */
+
+/*
+ * Hooks and struct for unsupported pci providers
+ */
+
+static dma_addr_t
+sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size)
+{
+       return 0;
+}
+
+static void
+sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction)
+{
+       return;
+}
+
+static void *
+sn_default_pci_bus_fixup(struct pcibus_bussoft *soft)
+{
+       return NULL;
+}
+
+static struct sn_pcibus_provider sn_pci_default_provider = {
+       .dma_map = sn_default_pci_map,
+       .dma_map_consistent = sn_default_pci_map,
+       .dma_unmap = sn_default_pci_unmap,
+       .bus_fixup = sn_default_pci_bus_fixup,
+};
+
 /*
  * Retrieve the DMA Flush List given nasid.  This list is needed 
  * to implement the WAR - Flush DMA data on PIO Reads.
@@ -142,6 +174,12 @@
                if (status)
                        continue;
 
+               /* Attach the error interrupt handlers */
+               if (nasid & 1)
+                       ice_error_init(hubdev);
+               else
+                       hub_error_init(hubdev);
+
                for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++)
                        hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev;
 
@@ -179,10 +217,6 @@
                            sn_flush_device_list;
                }
 
-               if (!(i & 1))
-                       hub_error_init(hubdev);
-               else
-                       ice_error_init(hubdev);
        }
 
 }
@@ -201,6 +235,7 @@
        struct sn_irq_info *sn_irq_info;
        struct pci_dev *host_pci_dev;
        int status = 0;
+       struct pcibus_bussoft *bs;
 
        dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL);
        if (SN_PCIDEV_INFO(dev) <= 0)
@@ -241,6 +276,7 @@
        }
 
        /* set up host bus linkages */
+       bs = SN_PCIBUS_BUSSOFT(dev->bus);
        host_pci_dev =
            pci_find_slot(SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32,
                          SN_PCIDEV_INFO(dev)->
@@ -248,10 +284,16 @@
        SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info =
            SN_PCIDEV_INFO(host_pci_dev);
        SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev;
-       SN_PCIDEV_INFO(dev)->pdi_pcibus_info = SN_PCIBUS_BUSSOFT(dev->bus);
+       SN_PCIDEV_INFO(dev)->pdi_pcibus_info = bs;
+
+       if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) {
+               SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type];
+       } else {
+               SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider;
+       }
 
        /* Only set up IRQ stuff if this device has a host bus context */
-       if (SN_PCIDEV_BUSSOFT(dev) && sn_irq_info->irq_irq) {
+       if (bs && sn_irq_info->irq_irq) {
                SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info;
                dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq;
                sn_irq_fixup(dev, sn_irq_info);
@@ -271,6 +313,7 @@
        struct pcibus_bussoft *prom_bussoft_ptr;
        struct hubdev_info *hubdev_info;
        void *provider_soft;
+       struct sn_pcibus_provider *provider;
 
        status =
            sal_get_pcibus_info((u64) segment, (u64) busnum,
@@ -291,16 +334,22 @@
        /*
         * Per-provider fixup.  Copies the contents from prom to local
         * area and links SN_PCIBUS_BUSSOFT().
-        *
-        * Note:  Provider is responsible for ensuring that prom_bussoft_ptr
-        * represents an asic-type that it can handle.
         */
 
-       if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB) {
-               return;         /* no further fixup necessary */
+       if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) {
+               return;         /* unsupported asic type */
+       }
+
+       provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
+       if (provider == NULL) {
+               return;         /* no provider registerd for this asic */
+       }
+
+       provider_soft = NULL;
+       if (provider->bus_fixup) {
+               provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr);
        }
 
-       provider_soft = pcibr_bus_fixup(prom_bussoft_ptr);
        if (provider_soft == NULL) {
                return;         /* fixup failed or not applicable */
        }
@@ -339,6 +388,17 @@
                return 0;
 
        /*
+        * prime sn_pci_provider[].  Individial provider init routines will
+        * override their respective default entries.
+        */
+
+       for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++)
+               sn_pci_provider[i] = &sn_pci_default_provider;
+
+       pcibr_init_provider();
+       tioca_init_provider();
+
+       /*
         * This is needed to avoid bounce limit checks in the blk layer
         */
        ia64_max_iommu_merge_mask = ~PAGE_MASK;
diff -urN linux/arch/ia64/sn/kernel/irq.c linux/arch/ia64/sn/kernel/irq.c
--- linux/arch/ia64/sn/kernel/irq.c     2005/02/07 02:54:33     1.20
+++ linux/arch/ia64/sn/kernel/irq.c     2005/05/19 12:08:10     1.21
@@ -13,8 +13,8 @@
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
 #include "xtalk/xwidgetdev.h"
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/pcibr_provider.h"
 #include <asm/sn/shub_mmr.h>
 #include <asm/sn/sn_sal.h>
@@ -82,20 +82,9 @@
        nasid = get_nasid();
        event_occurred =
            HUB_L((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED));
-       if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
-               mask |= (1 << SH_EVENT_OCCURRED_UART_INT_SHFT);
-       }
-       if (event_occurred & SH_EVENT_OCCURRED_IPI_INT_MASK) {
-               mask |= (1 << SH_EVENT_OCCURRED_IPI_INT_SHFT);
-       }
-       if (event_occurred & SH_EVENT_OCCURRED_II_INT0_MASK) {
-               mask |= (1 << SH_EVENT_OCCURRED_II_INT0_SHFT);
-       }
-       if (event_occurred & SH_EVENT_OCCURRED_II_INT1_MASK) {
-               mask |= (1 << SH_EVENT_OCCURRED_II_INT1_SHFT);
-       }
+       mask = event_occurred & SH_ALL_INT_MASK;
        HUB_S((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS),
-             mask);
+                mask);
        __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
 
        move_irq(irq);
diff -urN linux/arch/ia64/sn/kernel/mca.c linux/arch/ia64/sn/kernel/mca.c
--- linux/arch/ia64/sn/kernel/mca.c     2004/11/15 11:49:17     1.13
+++ linux/arch/ia64/sn/kernel/mca.c     2005/05/19 12:08:10     1.14
@@ -37,6 +37,11 @@
  * This function is the callback routine that SAL calls to log error
  * info for platform errors.  buf is appended to sn_oemdata, resizing as
  * required.
+ * Note: this is a SAL to OS callback, running under the same rules as the SAL
+ * code.  SAL calls are run with preempt disabled so this routine must not
+ * sleep.  vmalloc can sleep so print_hook cannot resize the output buffer
+ * itself, instead it must set the required size and return to let the caller
+ * resize the buffer then redrive the SAL call.
  */
 static int print_hook(const char *fmt, ...)
 {
@@ -47,18 +52,8 @@
        vsnprintf(buf, sizeof(buf), fmt, args);
        va_end(args);
        len = strlen(buf);
-       while (*sn_oemdata_size + len + 1 > sn_oemdata_bufsize) {
-               u8 *newbuf = vmalloc(sn_oemdata_bufsize += 1000);
-               if (!newbuf) {
-                       printk(KERN_ERR "%s: unable to extend sn_oemdata\n",
-                              __FUNCTION__);
-                       return 0;
-               }
-               memcpy(newbuf, *sn_oemdata, *sn_oemdata_size);
-               vfree(*sn_oemdata);
-               *sn_oemdata = newbuf;
-       }
-       memcpy(*sn_oemdata + *sn_oemdata_size, buf, len + 1);
+       if (*sn_oemdata_size + len <= sn_oemdata_bufsize)
+               memcpy(*sn_oemdata + *sn_oemdata_size, buf, len);
        *sn_oemdata_size += len;
        return 0;
 }
@@ -98,7 +93,20 @@
        sn_oemdata = oemdata;
        sn_oemdata_size = oemdata_size;
        sn_oemdata_bufsize = 0;
-       ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
+       *sn_oemdata_size = PAGE_SIZE;   /* first guess at how much data will be 
generated */
+       while (*sn_oemdata_size > sn_oemdata_bufsize) {
+               u8 *newbuf = vmalloc(*sn_oemdata_size);
+               if (!newbuf) {
+                       printk(KERN_ERR "%s: unable to extend sn_oemdata\n",
+                              __FUNCTION__);
+                       return 1;
+               }
+               vfree(*sn_oemdata);
+               *sn_oemdata = newbuf;
+               sn_oemdata_bufsize = *sn_oemdata_size;
+               *sn_oemdata_size = 0;
+               ia64_sn_plat_specific_err_print(print_hook, (char 
*)sect_header);
+       }
        up(&sn_oemdata_mutex);
        return 0;
 }
diff -urN linux/arch/ia64/sn/kernel/setup.c linux/arch/ia64/sn/kernel/setup.c
--- linux/arch/ia64/sn/kernel/setup.c   2005/04/08 18:57:54     1.31
+++ linux/arch/ia64/sn/kernel/setup.c   2005/05/19 12:08:10     1.32
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999,2001-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1999,2001-2005 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/config.h>
@@ -29,6 +29,7 @@
 #include <linux/sched.h>
 #include <linux/root_dev.h>
 #include <linux/nodemask.h>
+#include <linux/pm.h>
 
 #include <asm/io.h>
 #include <asm/sal.h>
@@ -72,6 +73,12 @@
 DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);
 EXPORT_PER_CPU_SYMBOL(__sn_hub_info);
 
+DEFINE_PER_CPU(short, __sn_cnodeid_to_nasid[MAX_NUMNODES]);
+EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid);
+
+DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda);
+EXPORT_PER_CPU_SYMBOL(__sn_nodepda);
+
 partid_t sn_partid = -1;
 EXPORT_SYMBOL(sn_partid);
 char sn_system_serial_number_string[128];
@@ -353,6 +360,14 @@
        screen_info = sn_screen_info;
 
        sn_timer_init();
+
+       /*
+        * set pm_power_off to a SAL call to allow
+        * sn machines to power off. The SAL call can be replaced
+        * by an ACPI interface call when ACPI is fully implemented
+        * for sn.
+        */
+       pm_power_off = ia64_sn_power_down;
 }
 
 /**
@@ -364,11 +379,11 @@
 {
        cnodeid_t cnode;
 
-       memset(pda->cnodeid_to_nasid_table, -1,
-              sizeof(pda->cnodeid_to_nasid_table));
+       memset(sn_cnodeid_to_nasid, -1,
+                       sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
        for_each_online_node(cnode)
-               pda->cnodeid_to_nasid_table[cnode] =
-                   pxm_to_nasid(nid_to_pxm_map[cnode]);
+               sn_cnodeid_to_nasid[cnode] =
+                               pxm_to_nasid(nid_to_pxm_map[cnode]);
 
        numionodes = num_online_nodes();
        scan_for_ionodes();
@@ -468,7 +483,8 @@
 
        cnode = nasid_to_cnodeid(nasid);
 
-       pda->p_nodepda = nodepdaindr[cnode];
+       sn_nodepda = nodepdaindr[cnode];
+
        pda->led_address =
            (typeof(pda->led_address)) (LED0 + (slice << LED_CPU_SHIFT));
        pda->led_state = LED_ALWAYS_SET;
@@ -477,15 +493,18 @@
        pda->idle_flag = 0;
 
        if (cpuid != 0) {
-               memcpy(pda->cnodeid_to_nasid_table,
-                      pdacpu(0)->cnodeid_to_nasid_table,
-                      sizeof(pda->cnodeid_to_nasid_table));
+               /* copy cpu 0's sn_cnodeid_to_nasid table to this cpu's */
+               memcpy(sn_cnodeid_to_nasid,
+                      (&per_cpu(__sn_cnodeid_to_nasid, 0)),
+                      sizeof(__ia64_per_cpu_var(__sn_cnodeid_to_nasid)));
        }
 
        /*
         * Check for WARs.
         * Only needs to be done once, on BSP.
-        * Has to be done after loop above, because it uses 
pda.cnodeid_to_nasid_table[i].
+        * Has to be done after loop above, because it uses this cpu's
+        * sn_cnodeid_to_nasid table which was just initialized if this
+        * isn't cpu 0.
         * Has to be done before assignment below.
         */
        if (!wars_have_been_checked) {
@@ -571,8 +590,7 @@
                brd = find_lboard_any(brd, KLTYPE_SNIA);
 
                while (brd) {
-                       pda->cnodeid_to_nasid_table[numionodes] =
-                           brd->brd_nasid;
+                       sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;
                        physical_node_map[brd->brd_nasid] = numionodes;
                        root_lboard[numionodes] = brd;
                        numionodes++;
@@ -593,8 +611,7 @@
                                      root_lboard[nasid_to_cnodeid(nasid)],
                                      KLTYPE_TIO);
                while (brd) {
-                       pda->cnodeid_to_nasid_table[numionodes] =
-                           brd->brd_nasid;
+                       sn_cnodeid_to_nasid[numionodes] = brd->brd_nasid;
                        physical_node_map[brd->brd_nasid] = numionodes;
                        root_lboard[numionodes] = brd;
                        numionodes++;
@@ -605,7 +622,6 @@
                        brd = find_lboard_any(brd, KLTYPE_TIO);
                }
        }
-
 }
 
 int
@@ -614,7 +630,8 @@
        long cpu;
        
        for (cpu=0; cpu < NR_CPUS; cpu++) 
-               if (nodepda->phys_cpuid[cpu].nasid == nasid && 
nodepda->phys_cpuid[cpu].slice == slice)
+               if (cpuid_to_nasid(cpu) == nasid &&
+                                       cpuid_to_slice(cpu) == slice)
                        return cpu;
 
        return -1;
diff -urN linux/arch/ia64/sn/kernel/sn2/sn_hwperf.c 
linux/arch/ia64/sn/kernel/sn2/sn_hwperf.c
--- linux/arch/ia64/sn/kernel/sn2/sn_hwperf.c   2005/02/07 02:54:33     1.6
+++ linux/arch/ia64/sn/kernel/sn2/sn_hwperf.c   2005/05/19 12:08:11     1.7
@@ -28,6 +28,7 @@
 #include <linux/vmalloc.h>
 #include <linux/seq_file.h>
 #include <linux/miscdevice.h>
+#include <linux/utsname.h>
 #include <linux/cpumask.h>
 #include <linux/smp_lock.h>
 #include <linux/nodemask.h>
@@ -43,6 +44,7 @@
 #include <asm/sn/module.h>
 #include <asm/sn/geo.h>
 #include <asm/sn/sn2/sn_hwperf.h>
+#include <asm/sn/addrs.h>
 
 static void *sn_hwperf_salheap = NULL;
 static int sn_hwperf_obj_cnt = 0;
@@ -81,26 +83,45 @@
        return e;
 }
 
+static int sn_hwperf_location_to_bpos(char *location,
+       int *rack, int *bay, int *slot, int *slab)
+{
+       char type;
+
+       /* first scan for an old style geoid string */
+       if (sscanf(location, "%03d%c%02d#%d",
+               rack, &type, bay, slab) == 4)
+               *slot = 0; 
+       else /* scan for a new bladed geoid string */
+       if (sscanf(location, "%03d%c%02d^%02d#%d",
+               rack, &type, bay, slot, slab) != 5)
+               return -1; 
+       /* success */
+       return 0;
+}
+
 static int sn_hwperf_geoid_to_cnode(char *location)
 {
        int cnode;
        geoid_t geoid;
        moduleid_t module_id;
-       char type;
-       int rack, slot, slab;
-       int this_rack, this_slot, this_slab;
+       int rack, bay, slot, slab;
+       int this_rack, this_bay, this_slot, this_slab;
 
-       if (sscanf(location, "%03d%c%02d#%d", &rack, &type, &slot, &slab) != 4)
+       if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab))
                return -1;
 
        for (cnode = 0; cnode < numionodes; cnode++) {
                geoid = cnodeid_get_geoid(cnode);
                module_id = geo_module(geoid);
                this_rack = MODULE_GET_RACK(module_id);
-               this_slot = MODULE_GET_BPOS(module_id);
+               this_bay = MODULE_GET_BPOS(module_id);
+               this_slot = geo_slot(geoid);
                this_slab = geo_slab(geoid);
-               if (rack == this_rack && slot == this_slot && slab == this_slab)
+               if (rack == this_rack && bay == this_bay &&
+                       slot == this_slot && slab == this_slab) {
                        break;
+               }
        }
 
        return cnode < numionodes ? cnode : -1;
@@ -153,11 +174,36 @@
        return slabname;
 }
 
+static void print_pci_topology(struct seq_file *s,
+       struct sn_hwperf_object_info *obj, int *ordinal,
+       u64 rack, u64 bay, u64 slot, u64 slab)
+{
+       char *p1;
+       char *p2;
+       char *pg;
+
+       if (!(pg = (char *)get_zeroed_page(GFP_KERNEL)))
+               return; /* ignore */
+       if (ia64_sn_ioif_get_pci_topology(rack, bay, slot, slab,
+               __pa(pg), PAGE_SIZE) == SN_HWPERF_OP_OK) {
+               for (p1=pg; *p1 && p1 < pg + PAGE_SIZE;) {
+                       if (!(p2 = strchr(p1, '\n')))
+                               break;
+                       *p2 = '\0';
+                       seq_printf(s, "pcibus %d %s-%s\n",
+                               *ordinal, obj->location, p1);
+                       (*ordinal)++;
+                       p1 = p2 + 1;
+               }
+       }
+       free_page((unsigned long)pg);
+}
+
 static int sn_topology_show(struct seq_file *s, void *d)
 {
        int sz;
        int pt;
-       int e;
+       int e = 0;
        int i;
        int j;
        const char *slabname;
@@ -169,11 +215,44 @@
        struct sn_hwperf_object_info *p;
        struct sn_hwperf_object_info *obj = d;  /* this object */
        struct sn_hwperf_object_info *objs = s->private; /* all objects */
+       int rack, bay, slot, slab;
+       u8 shubtype;
+       u8 system_size;
+       u8 sharing_size;
+       u8 partid;
+       u8 coher;
+       u8 nasid_shift;
+       u8 region_size;
+       u16 nasid_mask;
+       int nasid_msb;
+       int pci_bus_ordinal = 0;
 
        if (obj == objs) {
-               seq_printf(s, "# sn_topology version 1\n");
+               seq_printf(s, "# sn_topology version 2\n");
                seq_printf(s, "# objtype ordinal location partition"
                        " [attribute value [, ...]]\n");
+
+               if (ia64_sn_get_sn_info(0,
+                       &shubtype, &nasid_mask, &nasid_shift, &system_size,
+                       &sharing_size, &partid, &coher, &region_size))
+                       BUG();
+               for (nasid_msb=63; nasid_msb > 0; nasid_msb--) {
+                       if (((u64)nasid_mask << nasid_shift) & (1ULL << 
nasid_msb))
+                               break;
+               }
+               seq_printf(s, "partition %u %s local "
+                       "shubtype %s, "
+                       "nasid_mask 0x%016lx, "
+                       "nasid_bits %d:%d, "
+                       "system_size %d, "
+                       "sharing_size %d, "
+                       "coherency_domain %d, "
+                       "region_size %d\n",
+
+                       partid, system_utsname.nodename,
+                       shubtype ? "shub2" : "shub1", 
+                       (u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift,
+                       system_size, sharing_size, coher, region_size);
        }
 
        if (SN_HWPERF_FOREIGN(obj)) {
@@ -181,7 +260,7 @@
                return 0;
        }
 
-       for (i = 0; obj->name[i]; i++) {
+       for (i = 0; i < SN_HWPERF_MAXSTRING && obj->name[i]; i++) {
                if (obj->name[i] == ' ')
                        obj->name[i] = '_';
        }
@@ -221,6 +300,17 @@
                                seq_putc(s, '\n');
                        }
                }
+
+               /*
+                * PCI busses attached to this node, if any
+                */
+               if (sn_hwperf_location_to_bpos(obj->location,
+                       &rack, &bay, &slot, &slab)) {
+                       /* export pci bus info */
+                       print_pci_topology(s, obj, &pci_bus_ordinal,
+                               rack, bay, slot, slab);
+
+               }
        }
 
        if (obj->ports) {
@@ -397,6 +487,9 @@
                break;
 
        case SN_HWPERF_OP_BUSY:
+               e = -EBUSY;
+               break;
+
        case SN_HWPERF_OP_RECONFIGURE:
                e = -EAGAIN;
                break;
@@ -549,6 +642,7 @@
                r = sn_hwperf_op_cpu(&op_info);
                if (r) {
                        r = sn_hwperf_map_err(r);
+                       a.v0 = v0;
                        goto error;
                }
                break;
diff -urN linux/arch/ia64/sn/pci/tioca_provider.c 
linux/arch/ia64/sn/pci/tioca_provider.c
--- linux/arch/ia64/sn/pci/tioca_provider.c     1970/01/01 00:00:00
+++ linux/arch/ia64/sn/pci/tioca_provider.c     2005-05-19 13:08:11.146409000 
+0100     1.1
@@ -0,0 +1,668 @@
+/*
+ * 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-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/tioca_provider.h>
+
+uint32_t tioca_gart_found;
+EXPORT_SYMBOL(tioca_gart_found);       /* used by agp-sgi */
+
+LIST_HEAD(tioca_list);
+EXPORT_SYMBOL(tioca_list);     /* used by agp-sgi */
+
+static int tioca_gart_init(struct tioca_kernel *);
+
+/**
+ * tioca_gart_init - Initialize SGI TIOCA GART
+ * @tioca_common: ptr to common prom/kernel struct identifying the 
+ *
+ * If the indicated tioca has devices present, initialize its associated
+ * GART MMR's and kernel memory.
+ */
+static int
+tioca_gart_init(struct tioca_kernel *tioca_kern)
+{
+       uint64_t ap_reg;
+       uint64_t offset;
+       struct page *tmp;
+       struct tioca_common *tioca_common;
+       volatile struct tioca *ca_base;
+
+       tioca_common = tioca_kern->ca_common;
+       ca_base = (struct tioca *)tioca_common->ca_common.bs_base;
+
+       if (list_empty(tioca_kern->ca_devices))
+               return 0;
+
+       ap_reg = 0;
+
+       /*
+        * Validate aperature size
+        */
+
+       switch (CA_APERATURE_SIZE >> 20) {
+       case 4:
+               ap_reg |= (0x3ff << CA_GART_AP_SIZE_SHFT);      /* 4MB */
+               break;
+       case 8:
+               ap_reg |= (0x3fe << CA_GART_AP_SIZE_SHFT);      /* 8MB */
+               break;
+       case 16:
+               ap_reg |= (0x3fc << CA_GART_AP_SIZE_SHFT);      /* 16MB */
+               break;
+       case 32:
+               ap_reg |= (0x3f8 << CA_GART_AP_SIZE_SHFT);      /* 32 MB */
+               break;
+       case 64:
+               ap_reg |= (0x3f0 << CA_GART_AP_SIZE_SHFT);      /* 64 MB */
+               break;
+       case 128:
+               ap_reg |= (0x3e0 << CA_GART_AP_SIZE_SHFT);      /* 128 MB */
+               break;
+       case 256:
+               ap_reg |= (0x3c0 << CA_GART_AP_SIZE_SHFT);      /* 256 MB */
+               break;
+       case 512:
+               ap_reg |= (0x380 << CA_GART_AP_SIZE_SHFT);      /* 512 MB */
+               break;
+       case 1024:
+               ap_reg |= (0x300 << CA_GART_AP_SIZE_SHFT);      /* 1GB */
+               break;
+       case 2048:
+               ap_reg |= (0x200 << CA_GART_AP_SIZE_SHFT);      /* 2GB */
+               break;
+       case 4096:
+               ap_reg |= (0x000 << CA_GART_AP_SIZE_SHFT);      /* 4 GB */
+               break;
+       default:
+               printk(KERN_ERR "%s:  Invalid CA_APERATURE_SIZE "
+                      "0x%lx\n", __FUNCTION__, (ulong) CA_APERATURE_SIZE);
+               return -1;
+       }
+
+       /*
+        * Set up other aperature parameters
+        */
+
+       if (PAGE_SIZE >= 16384) {
+               tioca_kern->ca_ap_pagesize = 16384;
+               ap_reg |= CA_GART_PAGE_SIZE;
+       } else {
+               tioca_kern->ca_ap_pagesize = 4096;
+       }
+
+       tioca_kern->ca_ap_size = CA_APERATURE_SIZE;
+       tioca_kern->ca_ap_bus_base = CA_APERATURE_BASE;
+       tioca_kern->ca_gart_entries =
+           tioca_kern->ca_ap_size / tioca_kern->ca_ap_pagesize;
+
+       ap_reg |= (CA_GART_AP_ENB_AGP | CA_GART_AP_ENB_PCI);
+       ap_reg |= tioca_kern->ca_ap_bus_base;
+
+       /*
+        * Allocate and set up the GART
+        */
+
+       tioca_kern->ca_gart_size = tioca_kern->ca_gart_entries * sizeof(u64);
+       tmp =
+           alloc_pages_node(tioca_kern->ca_closest_node,
+                            GFP_KERNEL | __GFP_ZERO,
+                            get_order(tioca_kern->ca_gart_size));
+
+       if (!tmp) {
+               printk(KERN_ERR "%s:  Could not allocate "
+                      "%lu bytes (order %d) for GART\n",
+                      __FUNCTION__,
+                      tioca_kern->ca_gart_size,
+                      get_order(tioca_kern->ca_gart_size));
+               return -ENOMEM;
+       }
+
+       tioca_kern->ca_gart = page_address(tmp);
+       tioca_kern->ca_gart_coretalk_addr =
+           PHYS_TO_TIODMA(virt_to_phys(tioca_kern->ca_gart));
+
+       /*
+        * Compute PCI/AGP convenience fields 
+        */
+
+       offset = CA_PCI32_MAPPED_BASE - CA_APERATURE_BASE;
+       tioca_kern->ca_pciap_base = CA_PCI32_MAPPED_BASE;
+       tioca_kern->ca_pciap_size = CA_PCI32_MAPPED_SIZE;
+       tioca_kern->ca_pcigart_start = offset / tioca_kern->ca_ap_pagesize;
+       tioca_kern->ca_pcigart_base =
+           tioca_kern->ca_gart_coretalk_addr + offset;
+       tioca_kern->ca_pcigart =
+           &tioca_kern->ca_gart[tioca_kern->ca_pcigart_start];
+       tioca_kern->ca_pcigart_entries =
+           tioca_kern->ca_pciap_size / tioca_kern->ca_ap_pagesize;
+       tioca_kern->ca_pcigart_pagemap =
+           kcalloc(1, tioca_kern->ca_pcigart_entries / 8, GFP_KERNEL);
+       if (!tioca_kern->ca_pcigart_pagemap) {
+               free_pages((unsigned long)tioca_kern->ca_gart,
+                          get_order(tioca_kern->ca_gart_size));
+               return -1;
+       }
+
+       offset = CA_AGP_MAPPED_BASE - CA_APERATURE_BASE;
+       tioca_kern->ca_gfxap_base = CA_AGP_MAPPED_BASE;
+       tioca_kern->ca_gfxap_size = CA_AGP_MAPPED_SIZE;
+       tioca_kern->ca_gfxgart_start = offset / tioca_kern->ca_ap_pagesize;
+       tioca_kern->ca_gfxgart_base =
+           tioca_kern->ca_gart_coretalk_addr + offset;
+       tioca_kern->ca_gfxgart =
+           &tioca_kern->ca_gart[tioca_kern->ca_gfxgart_start];
+       tioca_kern->ca_gfxgart_entries =
+           tioca_kern->ca_gfxap_size / tioca_kern->ca_ap_pagesize;
+
+       /*
+        * various control settings:
+        *      use agp op-combining
+        *      use GET semantics to fetch memory
+        *      participate in coherency domain
+        *      DISABLE GART PREFETCHING due to hw bug tracked in SGI PV930029
+        */
+
+       ca_base->ca_control1 |= CA_AGPDMA_OP_ENB_COMBDELAY;     /* PV895469 ? */
+       ca_base->ca_control2 &= ~(CA_GART_MEM_PARAM);
+       ca_base->ca_control2 |= (0x2ull << CA_GART_MEM_PARAM_SHFT);
+       tioca_kern->ca_gart_iscoherent = 1;
+       ca_base->ca_control2 &=
+           ~(CA_GART_WR_PREFETCH_ENB | CA_GART_RD_PREFETCH_ENB);
+
+       /*
+        * Unmask GART fetch error interrupts.  Clear residual errors first.
+        */
+
+       ca_base->ca_int_status_alias = CA_GART_FETCH_ERR;
+       ca_base->ca_mult_error_alias = CA_GART_FETCH_ERR;
+       ca_base->ca_int_mask &= ~CA_GART_FETCH_ERR;
+
+       /*
+        * Program the aperature and gart registers in TIOCA
+        */
+
+       ca_base->ca_gart_aperature = ap_reg;
+       ca_base->ca_gart_ptr_table = tioca_kern->ca_gart_coretalk_addr | 1;
+
+       return 0;
+}
+
+/**
+ * tioca_fastwrite_enable - enable AGP FW for a tioca and its functions
+ * @tioca_kernel: structure representing the CA
+ *
+ * Given a CA, scan all attached functions making sure they all support
+ * FastWrite.  If so, enable FastWrite for all functions and the CA itself.
+ */
+
+void
+tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
+{
+       int cap_ptr;
+       uint64_t ca_control1;
+       uint32_t reg;
+       struct tioca *tioca_base;
+       struct pci_dev *pdev;
+       struct tioca_common *common;
+
+       common = tioca_kern->ca_common;
+
+       /*
+        * Scan all vga controllers on this bus making sure they all
+        * suport FW.  If not, return.
+        */
+
+       list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {
+               if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
+                       continue;
+
+               cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+               if (!cap_ptr)
+                       return; /* no AGP CAP means no FW */
+
+               pci_read_config_dword(pdev, cap_ptr + PCI_AGP_STATUS, &reg);
+               if (!(reg & PCI_AGP_STATUS_FW))
+                       return; /* function doesn't support FW */
+       }
+
+       /*
+        * Set fw for all vga fn's
+        */
+
+       list_for_each_entry(pdev, tioca_kern->ca_devices, bus_list) {
+               if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
+                       continue;
+
+               cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+               pci_read_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, &reg);
+               reg |= PCI_AGP_COMMAND_FW;
+               pci_write_config_dword(pdev, cap_ptr + PCI_AGP_COMMAND, reg);
+       }
+
+       /*
+        * Set ca's fw to match
+        */
+
+       tioca_base = (struct tioca *)common->ca_common.bs_base;
+       ca_control1 = tioca_base->ca_control1;
+       ca_control1 |= CA_AGP_FW_ENABLE;
+       tioca_base->ca_control1 = ca_control1;
+}
+
+EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */
+
+/**
+ * tioca_dma_d64 - create a DMA mapping using 64-bit direct mode
+ * @paddr: system physical address
+ *
+ * Map @paddr into 64-bit CA bus space.  No device context is necessary.
+ * Bits 53:0 come from the coretalk address.  We just need to mask in the
+ * following optional bits of the 64-bit pci address:
+ *
+ * 63:60 - Coretalk Packet Type -  0x1 for Mem Get/Put (coherent)
+ *                                 0x2 for PIO (non-coherent)
+ *                                 We will always use 0x1
+ * 55:55 - Swap bytes             Currently unused
+ */
+static uint64_t
+tioca_dma_d64(unsigned long paddr)
+{
+       dma_addr_t bus_addr;
+
+       bus_addr = PHYS_TO_TIODMA(paddr);
+
+       BUG_ON(!bus_addr);
+       BUG_ON(bus_addr >> 54);
+
+       /* Set upper nibble to Cache Coherent Memory op */
+       bus_addr |= (1UL << 60);
+
+       return bus_addr;
+}
+
+/**
+ * tioca_dma_d48 - create a DMA mapping using 48-bit direct mode
+ * @pdev: linux pci_dev representing the function
+ * @paddr: system physical address
+ *
+ * Map @paddr into 64-bit bus space of the CA associated with @pcidev_info.
+ *
+ * The CA agp 48 bit direct address falls out as follows:
+ *
+ * When direct mapping AGP addresses, the 48 bit AGP address is
+ * constructed as follows:
+ *
+ * [47:40] - Low 8 bits of the page Node ID extracted from coretalk
+ *              address [47:40].  The upper 8 node bits are fixed
+ *              and come from the xxx register bits [5:0]
+ * [39:38] - Chiplet ID extracted from coretalk address [39:38]
+ * [37:00] - node offset extracted from coretalk address [37:00]
+ * 
+ * Since the node id in general will be non-zero, and the chiplet id
+ * will always be non-zero, it follows that the device must support
+ * a dma mask of at least 0xffffffffff (40 bits) to target node 0
+ * and in general should be 0xffffffffffff (48 bits) to target nodes
+ * up to 255.  Nodes above 255 need the support of the xxx register,
+ * and so a given CA can only directly target nodes in the range
+ * xxx - xxx+255.
+ */
+static uint64_t
+tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
+{
+       struct tioca_common *tioca_common;
+       struct tioca *ca_base;
+       uint64_t ct_addr;
+       dma_addr_t bus_addr;
+       uint32_t node_upper;
+       uint64_t agp_dma_extn;
+       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
+
+       tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
+       ca_base = (struct tioca *)tioca_common->ca_common.bs_base;
+
+       ct_addr = PHYS_TO_TIODMA(paddr);
+       if (!ct_addr)
+               return 0;
+
+       bus_addr = (dma_addr_t) (ct_addr & 0xffffffffffff);
+       node_upper = ct_addr >> 48;
+
+       if (node_upper > 64) {
+               printk(KERN_ERR "%s:  coretalk addr 0x%p node id out "
+                      "of range\n", __FUNCTION__, (void *)ct_addr);
+               return 0;
+       }
+
+       agp_dma_extn = ca_base->ca_agp_dma_addr_extn;
+       if (node_upper != (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT)) {
+               printk(KERN_ERR "%s:  coretalk upper node (%u) "
+                      "mismatch with ca_agp_dma_addr_extn (%lu)\n",
+                      __FUNCTION__,
+                      node_upper, (agp_dma_extn >> CA_AGP_DMA_NODE_ID_SHFT));
+               return 0;
+       }
+
+       return bus_addr;
+}
+
+/**
+ * tioca_dma_mapped - create a DMA mapping using a CA GART 
+ * @pdev: linux pci_dev representing the function
+ * @paddr: host physical address to map
+ * @req_size: len (bytes) to map
+ *
+ * Map @paddr into CA address space using the GART mechanism.  The mapped
+ * dma_addr_t is guarenteed to be contiguous in CA bus space.
+ */
+static dma_addr_t
+tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size)
+{
+       int i, ps, ps_shift, entry, entries, mapsize, last_entry;
+       uint64_t xio_addr, end_xio_addr;
+       struct tioca_common *tioca_common;
+       struct tioca_kernel *tioca_kern;
+       dma_addr_t bus_addr = 0;
+       struct tioca_dmamap *ca_dmamap;
+       void *map;
+       unsigned long flags;
+       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);;
+
+       tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
+       tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private;
+
+       xio_addr = PHYS_TO_TIODMA(paddr);
+       if (!xio_addr)
+               return 0;
+
+       spin_lock_irqsave(&tioca_kern->ca_lock, flags);
+
+       /*
+        * allocate a map struct
+        */
+
+       ca_dmamap = kcalloc(1, sizeof(struct tioca_dmamap), GFP_ATOMIC);
+       if (!ca_dmamap)
+               goto map_return;
+
+       /*
+        * Locate free entries that can hold req_size.  Account for
+        * unaligned start/length when allocating.
+        */
+
+       ps = tioca_kern->ca_ap_pagesize;        /* will be power of 2 */
+       ps_shift = ffs(ps) - 1;
+       end_xio_addr = xio_addr + req_size - 1;
+
+       entries = (end_xio_addr >> ps_shift) - (xio_addr >> ps_shift) + 1;
+
+       map = tioca_kern->ca_pcigart_pagemap;
+       mapsize = tioca_kern->ca_pcigart_entries;
+
+       entry = find_first_zero_bit(map, mapsize);
+       while (entry < mapsize) {
+               last_entry = find_next_bit(map, mapsize, entry);
+
+               if (last_entry - entry >= entries)
+                       break;
+
+               entry = find_next_zero_bit(map, mapsize, last_entry);
+       }
+
+       if (entry > mapsize)
+               goto map_return;
+
+       for (i = 0; i < entries; i++)
+               set_bit(entry + i, map);
+
+       bus_addr = tioca_kern->ca_pciap_base + (entry * ps);
+
+       ca_dmamap->cad_dma_addr = bus_addr;
+       ca_dmamap->cad_gart_size = entries;
+       ca_dmamap->cad_gart_entry = entry;
+       list_add(&ca_dmamap->cad_list, &tioca_kern->ca_dmamaps);
+
+       if (xio_addr % ps) {
+               tioca_kern->ca_pcigart[entry] = tioca_paddr_to_gart(xio_addr);
+               bus_addr += xio_addr & (ps - 1);
+               xio_addr &= ~(ps - 1);
+               xio_addr += ps;
+               entry++;
+       }
+
+       while (xio_addr < end_xio_addr) {
+               tioca_kern->ca_pcigart[entry] = tioca_paddr_to_gart(xio_addr);
+               xio_addr += ps;
+               entry++;
+       }
+
+       tioca_tlbflush(tioca_kern);
+
+map_return:
+       spin_unlock_irqrestore(&tioca_kern->ca_lock, flags);
+       return bus_addr;
+}
+
+/**
+ * tioca_dma_unmap - release CA mapping resources
+ * @pdev: linux pci_dev representing the function
+ * @bus_addr: bus address returned by an earlier tioca_dma_map
+ * @dir: mapping direction (unused)
+ *
+ * Locate mapping resources associated with @bus_addr and release them.
+ * For mappings created using the direct modes (64 or 48) there are no
+ * resources to release.
+ */
+void
+tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
+{
+       int i, entry;
+       struct tioca_common *tioca_common;
+       struct tioca_kernel *tioca_kern;
+       struct tioca_dmamap *map;
+       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
+       unsigned long flags;
+
+       tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
+       tioca_kern = (struct tioca_kernel *)tioca_common->ca_kernel_private;
+
+       /* return straight away if this isn't be a mapped address */
+
+       if (bus_addr < tioca_kern->ca_pciap_base ||
+           bus_addr >= (tioca_kern->ca_pciap_base + tioca_kern->ca_pciap_size))
+               return;
+
+       spin_lock_irqsave(&tioca_kern->ca_lock, flags);
+
+       list_for_each_entry(map, &tioca_kern->ca_dmamaps, cad_list)
+           if (map->cad_dma_addr == bus_addr)
+               break;
+
+       BUG_ON(map == NULL);
+
+       entry = map->cad_gart_entry;
+
+       for (i = 0; i < map->cad_gart_size; i++, entry++) {
+               clear_bit(entry, tioca_kern->ca_pcigart_pagemap);
+               tioca_kern->ca_pcigart[entry] = 0;
+       }
+       tioca_tlbflush(tioca_kern);
+
+       list_del(&map->cad_list);
+       spin_unlock_irqrestore(&tioca_kern->ca_lock, flags);
+       kfree(map);
+}
+
+/**
+ * tioca_dma_map - map pages for PCI DMA
+ * @pdev: linux pci_dev representing the function
+ * @paddr: host physical address to map
+ * @byte_count: bytes to map
+ *
+ * This is the main wrapper for mapping host physical pages to CA PCI space.
+ * The mapping mode used is based on the devices dma_mask.  As a last resort
+ * use the GART mapped mode.
+ */
+uint64_t
+tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
+{
+       uint64_t mapaddr;
+
+       /*
+        * If card is 64 or 48 bit addresable, use a direct mapping.  32
+        * bit direct is so restrictive w.r.t. where the memory resides that
+        * we don't use it even though CA has some support.
+        */
+
+       if (pdev->dma_mask == ~0UL)
+               mapaddr = tioca_dma_d64(paddr);
+       else if (pdev->dma_mask == 0xffffffffffffUL)
+               mapaddr = tioca_dma_d48(pdev, paddr);
+       else
+               mapaddr = 0;
+
+       /* Last resort ... use PCI portion of CA GART */
+
+       if (mapaddr == 0)
+               mapaddr = tioca_dma_mapped(pdev, paddr, byte_count);
+
+       return mapaddr;
+}
+
+/**
+ * tioca_error_intr_handler - SGI TIO CA error interrupt handler
+ * @irq: unused
+ * @arg: pointer to tioca_common struct for the given CA
+ * @pt: unused
+ *
+ * Handle a CA error interrupt.  Simply a wrapper around a SAL call which
+ * defers processing to the SGI prom.
+ */
+static irqreturn_t
+tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
+{
+       struct tioca_common *soft = arg;
+       struct ia64_sal_retval ret_stuff;
+       uint64_t segment;
+       uint64_t busnum;
+       ret_stuff.status = 0;
+       ret_stuff.v0 = 0;
+
+       segment = 0;
+       busnum = soft->ca_common.bs_persist_busnum;
+
+       SAL_CALL_NOLOCK(ret_stuff,
+                       (u64) SN_SAL_IOIF_ERROR_INTERRUPT,
+                       segment, busnum, 0, 0, 0, 0, 0);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * tioca_bus_fixup - perform final PCI fixup for a TIO CA bus
+ * @prom_bussoft: Common prom/kernel struct representing the bus
+ *
+ * Replicates the tioca_common pointed to by @prom_bussoft in kernel
+ * space.  Allocates and initializes a kernel-only area for a given CA,
+ * and sets up an irq for handling CA error interrupts.
+ *
+ * On successful setup, returns the kernel version of tioca_common back to
+ * the caller.
+ */
+void *
+tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft)
+{
+       struct tioca_common *tioca_common;
+       struct tioca_kernel *tioca_kern;
+       struct pci_bus *bus;
+
+       /* sanity check prom rev */
+
+       if (sn_sal_rev_major() < 4 ||
+           (sn_sal_rev_major() == 4 && sn_sal_rev_minor() < 6)) {
+               printk
+                   (KERN_ERR "%s:  SGI prom rev 4.06 or greater required "
+                    "for tioca support\n", __FUNCTION__);
+               return NULL;
+       }
+
+       /*
+        * Allocate kernel bus soft and copy from prom.
+        */
+
+       tioca_common = kcalloc(1, sizeof(struct tioca_common), GFP_KERNEL);
+       if (!tioca_common)
+               return NULL;
+
+       memcpy(tioca_common, prom_bussoft, sizeof(struct tioca_common));
+       tioca_common->ca_common.bs_base |= __IA64_UNCACHED_OFFSET;
+
+       /* init kernel-private area */
+
+       tioca_kern = kcalloc(1, sizeof(struct tioca_kernel), GFP_KERNEL);
+       if (!tioca_kern) {
+               kfree(tioca_common);
+               return NULL;
+       }
+
+       tioca_kern->ca_common = tioca_common;
+       spin_lock_init(&tioca_kern->ca_lock);
+       INIT_LIST_HEAD(&tioca_kern->ca_dmamaps);
+       tioca_kern->ca_closest_node =
+           nasid_to_cnodeid(tioca_common->ca_closest_nasid);
+       tioca_common->ca_kernel_private = (uint64_t) tioca_kern;
+
+       bus = pci_find_bus(0, tioca_common->ca_common.bs_persist_busnum);
+       BUG_ON(!bus);
+       tioca_kern->ca_devices = &bus->devices;
+
+       /* init GART */
+
+       if (tioca_gart_init(tioca_kern) < 0) {
+               kfree(tioca_kern);
+               kfree(tioca_common);
+               return NULL;
+       }
+
+       tioca_gart_found++;
+       list_add(&tioca_kern->ca_list, &tioca_list);
+
+       if (request_irq(SGI_TIOCA_ERROR,
+                       tioca_error_intr_handler,
+                       SA_SHIRQ, "TIOCA error", (void *)tioca_common))
+               printk(KERN_WARNING
+                      "%s:  Unable to get irq %d.  "
+                      "Error interrupts won't be routed for TIOCA bus %d\n",
+                      __FUNCTION__, SGI_TIOCA_ERROR,
+                      (int)tioca_common->ca_common.bs_persist_busnum);
+
+       return tioca_common;
+}
+
+static struct sn_pcibus_provider tioca_pci_interfaces = {
+       .dma_map = tioca_dma_map,
+       .dma_map_consistent = tioca_dma_map,
+       .dma_unmap = tioca_dma_unmap,
+       .bus_fixup = tioca_bus_fixup,
+};
+
+/**
+ * tioca_init_provider - init SN PCI provider ops for TIO CA
+ */
+int
+tioca_init_provider(void)
+{
+       sn_pci_provider[PCIIO_ASIC_TYPE_TIOCA] = &tioca_pci_interfaces;
+       return 0;
+}
diff -urN linux/arch/ia64/sn/pci/Makefile linux/arch/ia64/sn/pci/Makefile
--- linux/arch/ia64/sn/pci/Makefile     2004/10/25 20:44:15     1.1
+++ linux/arch/ia64/sn/pci/Makefile     2005/05/19 12:08:11     1.2
@@ -7,4 +7,4 @@
 #
 # Makefile for the sn pci general routines.
 
-obj-y := pci_dma.o pcibr/ 
+obj-y := pci_dma.o tioca_provider.o pcibr/ 
diff -urN linux/arch/ia64/sn/pci/pci_dma.c linux/arch/ia64/sn/pci/pci_dma.c
--- linux/arch/ia64/sn/pci/pci_dma.c    2005/02/07 02:54:33     1.3
+++ linux/arch/ia64/sn/pci/pci_dma.c    2005/05/19 12:08:11     1.4
@@ -12,9 +12,8 @@
 #include <linux/module.h>
 #include <asm/dma.h>
 #include <asm/sn/sn_sal.h>
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
-#include "pci/pcibr_provider.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 
 #define SG_ENT_VIRT_ADDRESS(sg)        (page_address((sg)->page) + 
(sg)->offset)
 #define SG_ENT_PHYS_ADDRESS(SG)        virt_to_phys(SG_ENT_VIRT_ADDRESS(SG))
@@ -79,7 +78,8 @@
 {
        void *cpuaddr;
        unsigned long phys_addr;
-       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
        BUG_ON(dev->bus != &pci_bus_type);
 
@@ -102,8 +102,7 @@
         * resources.
         */
 
-       *dma_handle = pcibr_dma_map(pcidev_info, phys_addr, size,
-                                   SN_PCIDMA_CONSISTENT);
+       *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size);
        if (!*dma_handle) {
                printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
                free_pages((unsigned long)cpuaddr, get_order(size));
@@ -127,11 +126,12 @@
 void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
                          dma_addr_t dma_handle)
 {
-       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
        BUG_ON(dev->bus != &pci_bus_type);
 
-       pcibr_dma_unmap(pcidev_info, dma_handle, 0);
+       provider->dma_unmap(pdev, dma_handle, 0);
        free_pages((unsigned long)cpu_addr, get_order(size));
 }
 EXPORT_SYMBOL(sn_dma_free_coherent);
@@ -159,12 +159,13 @@
 {
        dma_addr_t dma_addr;
        unsigned long phys_addr;
-       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
        BUG_ON(dev->bus != &pci_bus_type);
 
        phys_addr = __pa(cpu_addr);
-       dma_addr = pcibr_dma_map(pcidev_info, phys_addr, size, 0);
+       dma_addr = provider->dma_map(pdev, phys_addr, size);
        if (!dma_addr) {
                printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
                return 0;
@@ -187,10 +188,12 @@
 void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                         int direction)
 {
-       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
        BUG_ON(dev->bus != &pci_bus_type);
-       pcibr_dma_unmap(pcidev_info, dma_addr, direction);
+
+       provider->dma_unmap(pdev, dma_addr, direction);
 }
 EXPORT_SYMBOL(sn_dma_unmap_single);
 
@@ -207,12 +210,13 @@
                     int nhwentries, int direction)
 {
        int i;
-       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
 
        BUG_ON(dev->bus != &pci_bus_type);
 
        for (i = 0; i < nhwentries; i++, sg++) {
-               pcibr_dma_unmap(pcidev_info, sg->dma_address, direction);
+               provider->dma_unmap(pdev, sg->dma_address, direction);
                sg->dma_address = (dma_addr_t) NULL;
                sg->dma_length = 0;
        }
@@ -233,7 +237,8 @@
 {
        unsigned long phys_addr;
        struct scatterlist *saved_sg = sg;
-       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(to_pci_dev(dev));
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
        int i;
 
        BUG_ON(dev->bus != &pci_bus_type);
@@ -243,8 +248,8 @@
         */
        for (i = 0; i < nhwentries; i++, sg++) {
                phys_addr = SG_ENT_PHYS_ADDRESS(sg);
-               sg->dma_address = pcibr_dma_map(pcidev_info, phys_addr,
-                                               sg->length, 0);
+               sg->dma_address = provider->dma_map(pdev,
+                                                   phys_addr, sg->length);
 
                if (!sg->dma_address) {
                        printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
diff -urN linux/arch/ia64/sn/pci/pcibr/pcibr_ate.c 
linux/arch/ia64/sn/pci/pcibr/pcibr_ate.c
--- linux/arch/ia64/sn/pci/pcibr/pcibr_ate.c    2004/10/25 20:44:15     1.1
+++ linux/arch/ia64/sn/pci/pcibr/pcibr_ate.c    2005/05/19 12:08:11     1.2
@@ -8,8 +8,8 @@
 
 #include <linux/types.h>
 #include <asm/sn/sn_sal.h>
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/pcibr_provider.h"
 
 int pcibr_invalidate_ate = 0;  /* by default don't invalidate ATE on free */
diff -urN linux/arch/ia64/sn/pci/pcibr/pcibr_dma.c 
linux/arch/ia64/sn/pci/pcibr/pcibr_dma.c
--- linux/arch/ia64/sn/pci/pcibr/pcibr_dma.c    2004/11/15 11:49:17     1.2
+++ linux/arch/ia64/sn/pci/pcibr/pcibr_dma.c    2005/05/19 12:08:11     1.3
@@ -12,8 +12,8 @@
 #include <asm/sn/geo.h>
 #include "xtalk/xwidgetdev.h"
 #include "xtalk/hubdev.h"
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/tiocp.h"
 #include "pci/pic.h"
 #include "pci/pcibr_provider.h"
@@ -40,7 +40,7 @@
  *      we do not have to allocate entries in the PMU.
  */
 
-static uint64_t
+static dma_addr_t
 pcibr_dmamap_ate32(struct pcidev_info *info,
                   uint64_t paddr, size_t req_size, uint64_t flags)
 {
@@ -109,7 +109,7 @@
        return pci_addr;
 }
 
-static uint64_t
+static dma_addr_t
 pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr,
                        uint64_t dma_attributes)
 {
@@ -141,7 +141,7 @@
 
 }
 
-static uint64_t
+static dma_addr_t
 pcibr_dmatrans_direct32(struct pcidev_info * info,
                        uint64_t paddr, size_t req_size, uint64_t flags)
 {
@@ -180,11 +180,11 @@
  * DMA mappings for Direct 64 and 32 do not have any DMA maps.
  */
 void
-pcibr_dma_unmap(struct pcidev_info *pcidev_info, dma_addr_t dma_handle,
-               int direction)
+pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction)
 {
-       struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
-           pdi_pcibus_info;
+       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
+       struct pcibus_info *pcibus_info =
+           (struct pcibus_info *)pcidev_info->pdi_pcibus_info;
 
        if (IS_PCI32_MAPPED(dma_handle)) {
                int ate_index;
@@ -301,7 +301,7 @@
                spin_lock_irqsave(&((struct sn_flush_device_list *)p)->
                                  sfdl_flush_lock, flags);
 
-               p->sfdl_flush_value = 0;
+               *p->sfdl_flush_addr = 0;
 
                /* force an interrupt. */
                *(volatile uint32_t *)(p->sfdl_force_int_addr) = 1;
@@ -316,64 +316,63 @@
 }
 
 /*
- * Wrapper DMA interface.  Called from pci_dma.c routines.
+ * DMA interfaces.  Called from pci_dma.c routines.
  */
 
-uint64_t
-pcibr_dma_map(struct pcidev_info * pcidev_info, unsigned long phys_addr,
-             size_t size, unsigned int flags)
+dma_addr_t
+pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size)
 {
        dma_addr_t dma_handle;
-       struct pci_dev *pcidev = pcidev_info->pdi_linux_pcidev;
+       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
 
-       if (flags & SN_PCIDMA_CONSISTENT) {
-               /* sn_pci_alloc_consistent interfaces */
-               if (pcidev->dev.coherent_dma_mask == ~0UL) {
-                       dma_handle =
-                           pcibr_dmatrans_direct64(pcidev_info, phys_addr,
-                                                   PCI64_ATTR_BAR);
-               } else {
-                       dma_handle =
-                           (dma_addr_t) pcibr_dmamap_ate32(pcidev_info,
-                                                           phys_addr, size,
-                                                           PCI32_ATE_BAR);
-               }
-       } else {
-               /* map_sg/map_single interfaces */
+       /* SN cannot support DMA addresses smaller than 32 bits. */
+       if (hwdev->dma_mask < 0x7fffffff) {
+               return 0;
+       }
 
-               /* SN cannot support DMA addresses smaller than 32 bits. */
-               if (pcidev->dma_mask < 0x7fffffff) {
-                       return 0;
-               }
+       if (hwdev->dma_mask == ~0UL) {
+               /*
+                * Handle the most common case: 64 bit cards.  This
+                * call should always succeed.
+                */
 
-               if (pcidev->dma_mask == ~0UL) {
+               dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
+                                                    PCI64_ATTR_PREF);
+       } else {
+               /* Handle 32-63 bit cards via direct mapping */
+               dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr,
+                                                    size, 0);
+               if (!dma_handle) {
                        /*
-                        * Handle the most common case: 64 bit cards.  This
-                        * call should always succeed.
+                        * It is a 32 bit card and we cannot do direct mapping,
+                        * so we use an ATE.
                         */
 
-                       dma_handle =
-                           pcibr_dmatrans_direct64(pcidev_info, phys_addr,
-                                                   PCI64_ATTR_PREF);
-               } else {
-                       /* Handle 32-63 bit cards via direct mapping */
-                       dma_handle =
-                           pcibr_dmatrans_direct32(pcidev_info, phys_addr,
-                                                   size, 0);
-                       if (!dma_handle) {
-                               /*
-                                * It is a 32 bit card and we cannot do direct 
mapping,
-                                * so we use an ATE.
-                                */
-
-                               dma_handle =
-                                   pcibr_dmamap_ate32(pcidev_info, phys_addr,
-                                                      size, PCI32_ATE_PREF);
-                       }
+                       dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr,
+                                                       size, PCI32_ATE_PREF);
                }
        }
 
        return dma_handle;
 }
 
+dma_addr_t
+pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr,
+                        size_t size)
+{
+       dma_addr_t dma_handle;
+       struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
+
+       if (hwdev->dev.coherent_dma_mask == ~0UL) {
+               dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
+                                           PCI64_ATTR_BAR);
+       } else {
+               dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info,
+                                                   phys_addr, size,
+                                                   PCI32_ATE_BAR);
+       }
+
+       return dma_handle;
+}
+
 EXPORT_SYMBOL(sn_dma_flush);
diff -urN linux/arch/ia64/sn/pci/pcibr/pcibr_provider.c 
linux/arch/ia64/sn/pci/pcibr/pcibr_provider.c
--- linux/arch/ia64/sn/pci/pcibr/pcibr_provider.c       2004/11/15 11:49:17     
1.2
+++ linux/arch/ia64/sn/pci/pcibr/pcibr_provider.c       2005/05/19 12:08:11     
1.3
@@ -13,8 +13,8 @@
 #include "xtalk/xwidgetdev.h"
 #include <asm/sn/geo.h>
 #include "xtalk/hubdev.h"
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/pcibr_provider.h"
 #include <asm/sn/addrs.h>
 
@@ -168,3 +168,23 @@
                pcibr_force_interrupt(sn_irq_info);
        }
 }
+
+/*
+ * Provider entries for PIC/CP
+ */
+
+struct sn_pcibus_provider pcibr_provider = {
+       .dma_map = pcibr_dma_map,
+       .dma_map_consistent = pcibr_dma_map_consistent,
+       .dma_unmap = pcibr_dma_unmap,
+       .bus_fixup = pcibr_bus_fixup,
+};
+
+int
+pcibr_init_provider(void)
+{
+       sn_pci_provider[PCIIO_ASIC_TYPE_PIC] = &pcibr_provider;
+       sn_pci_provider[PCIIO_ASIC_TYPE_TIOCP] = &pcibr_provider;
+
+       return 0;
+}
diff -urN linux/arch/ia64/sn/pci/pcibr/pcibr_reg.c 
linux/arch/ia64/sn/pci/pcibr/pcibr_reg.c
--- linux/arch/ia64/sn/pci/pcibr/pcibr_reg.c    2004/10/25 20:44:16     1.1
+++ linux/arch/ia64/sn/pci/pcibr/pcibr_reg.c    2005/05/19 12:08:11     1.2
@@ -8,8 +8,8 @@
 
 #include <linux/types.h>
 #include <linux/interrupt.h>
-#include "pci/pcibus_provider_defs.h"
-#include "pci/pcidev.h"
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include "pci/tiocp.h"
 #include "pci/pic.h"
 #include "pci/pcibr_provider.h"
diff -urN linux/arch/m32r/kernel/ptrace.c linux/arch/m32r/kernel/ptrace.c
--- linux/arch/m32r/kernel/ptrace.c     2005/02/07 02:54:33     1.4
+++ linux/arch/m32r/kernel/ptrace.c     2005/05/19 12:08:11     1.5
@@ -24,6 +24,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/string.h>
+#include <linux/signal.h>
 
 #include <asm/cacheflush.h>
 #include <asm/io.h>
@@ -665,7 +666,7 @@
        case PTRACE_SYSCALL:
        case PTRACE_CONT:
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                if (request == PTRACE_SYSCALL)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -700,7 +701,7 @@
                unsigned long pc, insn;
 
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                if ((child->ptrace & PT_DTRACE) == 0) {
diff -urN linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c
--- linux/arch/m68k/kernel/ptrace.c     2004/10/25 20:44:16     1.24
+++ linux/arch/m68k/kernel/ptrace.c     2005/05/19 12:08:11     1.25
@@ -19,6 +19,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/config.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -251,7 +252,7 @@
                        long tmp;
 
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        if (request == PTRACE_SYSCALL) {
                                        child->thread.work.syscall_trace = ~0;
@@ -292,7 +293,7 @@
                        long tmp;
 
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        child->thread.work.syscall_trace = 0;
                        tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
diff -urN linux/arch/m68knommu/Kconfig linux/arch/m68knommu/Kconfig
--- linux/arch/m68knommu/Kconfig        2005/01/13 14:05:28     1.22
+++ linux/arch/m68knommu/Kconfig        2005/05/19 12:08:11     1.23
@@ -534,6 +534,11 @@
 
 endmenu
 
+config ISA_DMA_API
+       bool
+       depends on !M5272
+       default y
+
 menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
 
 config PCI
diff -urN linux/arch/m68knommu/kernel/ptrace.c 
linux/arch/m68knommu/kernel/ptrace.c
--- linux/arch/m68knommu/kernel/ptrace.c        2004/10/25 20:44:16     1.3
+++ linux/arch/m68knommu/kernel/ptrace.c        2005/05/19 12:08:11     1.4
@@ -19,6 +19,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/config.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -240,7 +241,7 @@
                        long tmp;
 
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        if (request == PTRACE_SYSCALL)
                                set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -278,7 +279,7 @@
                        long tmp;
 
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                        tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
diff -urN linux/arch/mips/defconfig linux/arch/mips/defconfig
--- linux/arch/mips/defconfig   2005/04/29 11:15:02     1.288
+++ linux/arch/mips/defconfig   2005/05/19 12:08:11     1.289
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:00:41 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:27 2005
 #
 CONFIG_MIPS=y
 
@@ -30,6 +30,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/atlas_defconfig 
linux/arch/mips/configs/atlas_defconfig
--- linux/arch/mips/configs/atlas_defconfig     2005/04/29 11:15:02     1.52
+++ linux/arch/mips/configs/atlas_defconfig     2005/05/19 12:08:11     1.53
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:13:22 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:28 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -319,11 +321,8 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
diff -urN linux/arch/mips/configs/capcella_defconfig 
linux/arch/mips/configs/capcella_defconfig
--- linux/arch/mips/configs/capcella_defconfig  2005/04/29 11:15:02     1.52
+++ linux/arch/mips/configs/capcella_defconfig  2005/05/19 12:08:11     1.53
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:13:25 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:28 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/cobalt_defconfig 
linux/arch/mips/configs/cobalt_defconfig
--- linux/arch/mips/configs/cobalt_defconfig    2005/04/29 11:15:02     1.49
+++ linux/arch/mips/configs/cobalt_defconfig    2005/05/19 12:08:11     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:13:29 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:29 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/db1000_defconfig 
linux/arch/mips/configs/db1000_defconfig
--- linux/arch/mips/configs/db1000_defconfig    2005/04/29 11:15:02     1.55
+++ linux/arch/mips/configs/db1000_defconfig    2005/05/19 12:08:11     1.56
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:13:31 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:30 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/db1100_defconfig 
linux/arch/mips/configs/db1100_defconfig
--- linux/arch/mips/configs/db1100_defconfig    2005/04/29 11:15:02     1.54
+++ linux/arch/mips/configs/db1100_defconfig    2005/05/19 12:08:11     1.55
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:13:34 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:31 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/db1500_defconfig 
linux/arch/mips/configs/db1500_defconfig
--- linux/arch/mips/configs/db1500_defconfig    2005/04/29 11:15:02     1.57
+++ linux/arch/mips/configs/db1500_defconfig    2005/05/19 12:08:11     1.58
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:13:37 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:31 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/db1550_defconfig 
linux/arch/mips/configs/db1550_defconfig
--- linux/arch/mips/configs/db1550_defconfig    2005/04/29 11:15:02     1.32
+++ linux/arch/mips/configs/db1550_defconfig    2005/05/19 12:08:11     1.33
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:13:39 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:32 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/ddb5476_defconfig 
linux/arch/mips/configs/ddb5476_defconfig
--- linux/arch/mips/configs/ddb5476_defconfig   2005/04/29 11:15:02     1.49
+++ linux/arch/mips/configs/ddb5476_defconfig   2005/05/19 12:08:11     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:14:39 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:33 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -210,7 +212,6 @@
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -378,7 +379,6 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 
diff -urN linux/arch/mips/configs/ddb5477_defconfig 
linux/arch/mips/configs/ddb5477_defconfig
--- linux/arch/mips/configs/ddb5477_defconfig   2005/04/29 11:15:02     1.49
+++ linux/arch/mips/configs/ddb5477_defconfig   2005/05/19 12:08:11     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:14:42 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:34 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/decstation_defconfig 
linux/arch/mips/configs/decstation_defconfig
--- linux/arch/mips/configs/decstation_defconfig        2005/04/29 11:15:02     
1.50
+++ linux/arch/mips/configs/decstation_defconfig        2005/05/19 12:08:11     
1.51
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:14:45 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:34 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/e55_defconfig 
linux/arch/mips/configs/e55_defconfig
--- linux/arch/mips/configs/e55_defconfig       2005/04/29 11:15:02     1.51
+++ linux/arch/mips/configs/e55_defconfig       2005/05/19 12:08:11     1.52
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:14:48 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:35 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -215,7 +217,6 @@
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -371,7 +372,6 @@
 CONFIG_NET_ETHERNET=y
 # CONFIG_MII is not set
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
diff -urN linux/arch/mips/configs/ev64120_defconfig 
linux/arch/mips/configs/ev64120_defconfig
--- linux/arch/mips/configs/ev64120_defconfig   2005/04/29 11:15:02     1.48
+++ linux/arch/mips/configs/ev64120_defconfig   2005/05/19 12:08:11     1.49
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:14:51 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:36 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/ev96100_defconfig 
linux/arch/mips/configs/ev96100_defconfig
--- linux/arch/mips/configs/ev96100_defconfig   2005/04/29 11:15:02     1.49
+++ linux/arch/mips/configs/ev96100_defconfig   2005/05/19 12:08:11     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:14:53 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:37 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/ip22_defconfig 
linux/arch/mips/configs/ip22_defconfig
--- linux/arch/mips/configs/ip22_defconfig      2005/04/29 11:15:02     1.58
+++ linux/arch/mips/configs/ip22_defconfig      2005/05/19 12:08:11     1.59
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:14:55 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:37 2005
 #
 CONFIG_MIPS=y
 
@@ -30,6 +30,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/ip27_defconfig 
linux/arch/mips/configs/ip27_defconfig
--- linux/arch/mips/configs/ip27_defconfig      2005/04/29 11:15:02     1.62
+++ linux/arch/mips/configs/ip27_defconfig      2005/05/19 12:08:11     1.63
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:16:37 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:38 2005
 #
 CONFIG_MIPS=y
 
@@ -31,6 +31,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -303,11 +305,8 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
diff -urN linux/arch/mips/configs/ip32_defconfig 
linux/arch/mips/configs/ip32_defconfig
--- linux/arch/mips/configs/ip32_defconfig      2005/04/29 11:15:02     1.52
+++ linux/arch/mips/configs/ip32_defconfig      2005/05/19 12:08:11     1.53
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:16:41 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:39 2005
 #
 CONFIG_MIPS=y
 
@@ -30,6 +30,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -296,11 +298,8 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
diff -urN linux/arch/mips/configs/it8172_defconfig 
linux/arch/mips/configs/it8172_defconfig
--- linux/arch/mips/configs/it8172_defconfig    2005/04/29 11:15:02     1.48
+++ linux/arch/mips/configs/it8172_defconfig    2005/05/19 12:08:11     1.49
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:16:44 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:40 2005
 #
 CONFIG_MIPS=y
 
@@ -30,6 +30,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/ivr_defconfig 
linux/arch/mips/configs/ivr_defconfig
--- linux/arch/mips/configs/ivr_defconfig       2005/04/29 11:15:02     1.48
+++ linux/arch/mips/configs/ivr_defconfig       2005/05/19 12:08:11     1.49
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:16:46 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:40 2005
 #
 CONFIG_MIPS=y
 
@@ -30,6 +30,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/jaguar-atx_defconfig 
linux/arch/mips/configs/jaguar-atx_defconfig
--- linux/arch/mips/configs/jaguar-atx_defconfig        2005/04/29 11:15:02     
1.53
+++ linux/arch/mips/configs/jaguar-atx_defconfig        2005/05/19 12:08:11     
1.54
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:16:48 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:41 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/jmr3927_defconfig 
linux/arch/mips/configs/jmr3927_defconfig
--- linux/arch/mips/configs/jmr3927_defconfig   2005/04/29 11:15:02     1.49
+++ linux/arch/mips/configs/jmr3927_defconfig   2005/05/19 12:08:11     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:20:26 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:42 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -453,7 +455,6 @@
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_RISCOM8 is not set
diff -urN linux/arch/mips/configs/lasat200_defconfig 
linux/arch/mips/configs/lasat200_defconfig
--- linux/arch/mips/configs/lasat200_defconfig  2005/04/29 11:15:02     1.49
+++ linux/arch/mips/configs/lasat200_defconfig  2005/05/19 12:08:11     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:20:31 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:43 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/malta_defconfig 
linux/arch/mips/configs/malta_defconfig
--- linux/arch/mips/configs/malta_defconfig     2005/04/29 11:15:02     1.51
+++ linux/arch/mips/configs/malta_defconfig     2005/05/19 12:08:11     1.52
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:20:37 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:44 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -354,11 +356,8 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
diff -urN linux/arch/mips/configs/mpc30x_defconfig 
linux/arch/mips/configs/mpc30x_defconfig
--- linux/arch/mips/configs/mpc30x_defconfig    2005/04/29 11:15:02     1.53
+++ linux/arch/mips/configs/mpc30x_defconfig    2005/05/19 12:08:11     1.54
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:20:40 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:44 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/ocelot_3_defconfig 
linux/arch/mips/configs/ocelot_3_defconfig
--- linux/arch/mips/configs/ocelot_3_defconfig  2005/04/29 11:15:02     1.21
+++ linux/arch/mips/configs/ocelot_3_defconfig  2005/05/19 12:08:11     1.22
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:20:45 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:45 2005
 #
 CONFIG_MIPS=y
 
@@ -30,6 +30,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -295,11 +297,8 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
diff -urN linux/arch/mips/configs/ocelot_c_defconfig 
linux/arch/mips/configs/ocelot_c_defconfig
--- linux/arch/mips/configs/ocelot_c_defconfig  2005/04/29 11:15:02     1.47
+++ linux/arch/mips/configs/ocelot_c_defconfig  2005/05/19 12:08:11     1.48
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:20:48 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:46 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/ocelot_defconfig 
linux/arch/mips/configs/ocelot_defconfig
--- linux/arch/mips/configs/ocelot_defconfig    2005/04/29 11:15:02     1.49
+++ linux/arch/mips/configs/ocelot_defconfig    2005/05/19 12:08:11     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:20:51 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:46 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/ocelot_g_defconfig 
linux/arch/mips/configs/ocelot_g_defconfig
--- linux/arch/mips/configs/ocelot_g_defconfig  2005/04/29 11:15:02     1.42
+++ linux/arch/mips/configs/ocelot_g_defconfig  2005/05/19 12:08:11     1.43
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:20:54 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:47 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/osprey_defconfig 
linux/arch/mips/configs/osprey_defconfig
--- linux/arch/mips/configs/osprey_defconfig    2005/04/29 11:15:02     1.48
+++ linux/arch/mips/configs/osprey_defconfig    2005/05/19 12:08:11     1.49
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:20:57 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:47 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/pb1100_defconfig 
linux/arch/mips/configs/pb1100_defconfig
--- linux/arch/mips/configs/pb1100_defconfig    2005/04/29 11:15:02     1.51
+++ linux/arch/mips/configs/pb1100_defconfig    2005/05/19 12:08:11     1.52
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:20:59 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:48 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/pb1500_defconfig 
linux/arch/mips/configs/pb1500_defconfig
--- linux/arch/mips/configs/pb1500_defconfig    2005/04/29 11:15:02     1.57
+++ linux/arch/mips/configs/pb1500_defconfig    2005/05/19 12:08:11     1.58
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:21:02 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:49 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/pb1550_defconfig 
linux/arch/mips/configs/pb1550_defconfig
--- linux/arch/mips/configs/pb1550_defconfig    2005/04/29 11:15:02     1.47
+++ linux/arch/mips/configs/pb1550_defconfig    2005/05/19 12:08:11     1.48
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:21:05 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:49 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/rm200_defconfig 
linux/arch/mips/configs/rm200_defconfig
--- linux/arch/mips/configs/rm200_defconfig     2005/04/29 11:15:02     1.58
+++ linux/arch/mips/configs/rm200_defconfig     2005/05/19 12:08:11     1.59
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:21:09 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:50 2005
 #
 CONFIG_MIPS=y
 
@@ -31,6 +31,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -234,7 +236,6 @@
 # Block devices
 #
 CONFIG_BLK_DEV_FD=m
-# CONFIG_BLK_DEV_XD is not set
 CONFIG_PARIDE=m
 CONFIG_PARIDE_PARPORT=m
 
@@ -334,10 +335,8 @@
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
@@ -348,12 +347,9 @@
 CONFIG_MEGARAID_MM=m
 CONFIG_MEGARAID_MAILBOX=m
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
 # CONFIG_SCSI_IPS is not set
@@ -386,7 +382,6 @@
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
@@ -678,8 +673,6 @@
 CONFIG_MKISS=m
 CONFIG_6PACK=m
 CONFIG_BPQETHER=m
-# CONFIG_DMASCC is not set
-# CONFIG_SCC is not set
 # CONFIG_BAYCOM_SER_FDX is not set
 # CONFIG_BAYCOM_SER_HDX is not set
 # CONFIG_BAYCOM_PAR is not set
@@ -706,7 +699,6 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 
@@ -727,7 +719,6 @@
 # CONFIG_LP486E is not set
 # CONFIG_ETH16I is not set
 CONFIG_NE2000=m
-# CONFIG_ZNET is not set
 # CONFIG_SEEQ8005 is not set
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
@@ -1094,6 +1085,7 @@
 #
 CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRPRIME=m
 CONFIG_USB_SERIAL_BELKIN=m
 CONFIG_USB_SERIAL_WHITEHEAT=m
 CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
@@ -1126,6 +1118,7 @@
 CONFIG_USB_SERIAL_KOBIL_SCT=m
 CONFIG_USB_SERIAL_MCT_U232=m
 CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_HP4X=m
 CONFIG_USB_SERIAL_SAFE=m
 CONFIG_USB_SERIAL_SAFE_PADDED=y
 # CONFIG_USB_SERIAL_TI is not set
diff -urN linux/arch/mips/configs/sb1250-swarm_defconfig 
linux/arch/mips/configs/sb1250-swarm_defconfig
--- linux/arch/mips/configs/sb1250-swarm_defconfig      2005/04/29 11:15:02     
1.55
+++ linux/arch/mips/configs/sb1250-swarm_defconfig      2005/05/19 12:08:11     
1.56
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:21:12 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:50 2005
 #
 CONFIG_MIPS=y
 
@@ -30,6 +30,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -487,7 +489,6 @@
 # CONFIG_CYCLADES is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_SPECIALIX is not set
diff -urN linux/arch/mips/configs/sead_defconfig 
linux/arch/mips/configs/sead_defconfig
--- linux/arch/mips/configs/sead_defconfig      2005/04/29 11:15:02     1.47
+++ linux/arch/mips/configs/sead_defconfig      2005/05/19 12:08:11     1.48
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:21:14 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:51 2005
 #
 CONFIG_MIPS=y
 
@@ -27,6 +27,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/tb0226_defconfig 
linux/arch/mips/configs/tb0226_defconfig
--- linux/arch/mips/configs/tb0226_defconfig    2005/04/29 11:15:02     1.51
+++ linux/arch/mips/configs/tb0226_defconfig    2005/05/19 12:08:11     1.52
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:21:16 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:51 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/tb0229_defconfig 
linux/arch/mips/configs/tb0229_defconfig
--- linux/arch/mips/configs/tb0229_defconfig    2005/04/29 11:15:02     1.54
+++ linux/arch/mips/configs/tb0229_defconfig    2005/05/19 12:08:11     1.55
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:21:19 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:52 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/configs/workpad_defconfig 
linux/arch/mips/configs/workpad_defconfig
--- linux/arch/mips/configs/workpad_defconfig   2005/04/29 11:15:02     1.51
+++ linux/arch/mips/configs/workpad_defconfig   2005/05/19 12:08:11     1.52
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:21:21 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:52 2005
 #
 CONFIG_MIPS=y
 
@@ -29,6 +29,8 @@
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -215,7 +217,6 @@
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -371,7 +372,6 @@
 CONFIG_NET_ETHERNET=y
 # CONFIG_MII is not set
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
diff -urN linux/arch/mips/configs/yosemite_defconfig 
linux/arch/mips/configs/yosemite_defconfig
--- linux/arch/mips/configs/yosemite_defconfig  2005/04/29 11:15:02     1.53
+++ linux/arch/mips/configs/yosemite_defconfig  2005/05/19 12:08:11     1.54
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Thu Apr 28 18:21:24 2005
+# Linux kernel version: 2.6.12-rc4
+# Wed May 11 17:20:53 2005
 #
 CONFIG_MIPS=y
 
@@ -31,6 +31,8 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
diff -urN linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- linux/arch/mips/kernel/ptrace.c     2005/04/13 17:43:59     1.61
+++ linux/arch/mips/kernel/ptrace.c     2005/05/19 12:08:12     1.62
@@ -28,6 +28,7 @@
 #include <linux/audit.h>
 #include <linux/seccomp.h>
 
+#include <asm/byteorder.h>
 #include <asm/cpu.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
@@ -306,31 +307,36 @@
        return ret;
 }
 
+static inline int audit_arch(void)
+{
+       int arch = EM_MIPS;
+#ifdef CONFIG_MIPS64
+       arch |=  __AUDIT_ARCH_64BIT;
+#endif
+#if defined(__LITTLE_ENDIAN)
+       arch |=  __AUDIT_ARCH_LE;
+#endif
+       return arch;
+}
+
 /*
  * Notification of system call entry/exit
  * - triggered by current->work.syscall_trace
  */
 asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
-       /* There is no ->orig_eax and that's quite intensional for now making
-          this work will require some work in various other place before it's
-          more than a placebo.  */
        /* do the secure computing check first */
        secure_computing(regs->orig_eax);
 
-       if (unlikely(current->audit_context)) {
-               if (!entryexit)
-                       audit_syscall_entry(current, regs->orig_eax,
-                                           regs->regs[4], regs->regs[5],
-                                           regs->regs[6], regs->regs[7]);
-               else
-                       audit_syscall_exit(current, regs->regs[2]);
-       }
+       if (unlikely(current->audit_context) && entryexit)
+               audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]),
+                                  regs->regs[2]);
 
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
        if (!(current->ptrace & PT_PTRACED))
-               return;
+               goto out;
+
+       if (!test_thread_flag(TIF_SYSCALL_TRACE))
+               goto out;
 
        /* The 0x80 provides a way for the tracing parent to distinguish
           between a syscall stop and SIGTRAP delivery */
@@ -346,4 +352,14 @@
                send_sig(current->exit_code, current, 1);
                current->exit_code = 0;
        }
+
+out:
+       /* There is no ->orig_eax and that's quite intensional for now making
+          this work will require some work in various other place before it's
+          more than a placebo.  */
+
+       if (unlikely(current->audit_context) && !entryexit)
+               audit_syscall_entry(current, audit_arch(), regs->orig_eax,
+                                   regs->regs[4], regs->regs[5],
+                                   regs->regs[6], regs->regs[7]);
 }
diff -urN linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c
--- linux/arch/mips/kernel/syscall.c    2005/04/14 11:31:25     1.53
+++ linux/arch/mips/kernel/syscall.c    2005/05/19 12:08:12     1.54
@@ -402,20 +402,6 @@
 }
 
 /*
- * Native N64 ABI only.
- */
-asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg)
-{
-       unsigned long raddr, err;
-
-       err = do_shmat(shmid, shmaddr, shmflg, &raddr);
-       if (err)
-               return err;
-
-       return raddr;
-}
-
-/*
  * No implemented yet ...
  */
 asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
diff -urN linux/arch/parisc/Kconfig linux/arch/parisc/Kconfig
--- linux/arch/parisc/Kconfig   2005/03/18 17:36:54     1.27
+++ linux/arch/parisc/Kconfig   2005/05/19 12:08:12     1.28
@@ -45,6 +45,10 @@
 config PM
        bool
 
+config ISA_DMA_API
+       bool
+       default y
+
 source "init/Kconfig"
 
 
diff -urN linux/arch/parisc/kernel/ptrace.c linux/arch/parisc/kernel/ptrace.c
--- linux/arch/parisc/kernel/ptrace.c   2005/01/25 04:28:00     1.13
+++ linux/arch/parisc/kernel/ptrace.c   2005/05/19 12:08:12     1.14
@@ -17,6 +17,7 @@
 #include <linux/personality.h>
 #include <linux/security.h>
 #include <linux/compat.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -285,7 +286,7 @@
                ret = -EIO;
                DBG("sys_ptrace(%s)\n",
                        request == PTRACE_SYSCALL ? "SYSCALL" : "CONT");
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        goto out_tsk;
                child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
                if (request == PTRACE_SYSCALL) {
@@ -311,7 +312,7 @@
        case PTRACE_SINGLEBLOCK:
                DBG("sys_ptrace(SINGLEBLOCK)\n");
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        goto out_tsk;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                child->ptrace &= ~PT_SINGLESTEP;
@@ -328,7 +329,7 @@
        case PTRACE_SINGLESTEP:
                DBG("sys_ptrace(SINGLESTEP)\n");
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        goto out_tsk;
 
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
diff -urN linux/arch/parisc/kernel/sys_parisc.c 
linux/arch/parisc/kernel/sys_parisc.c
--- linux/arch/parisc/kernel/sys_parisc.c       2005/03/18 17:36:54     1.18
+++ linux/arch/parisc/kernel/sys_parisc.c       2005/05/19 12:08:12     1.19
@@ -161,17 +161,6 @@
        }
 }
 
-long sys_shmat_wrapper(int shmid, char __user *shmaddr, int shmflag)
-{
-       unsigned long raddr;
-       int r;
-
-       r = do_shmat(shmid, shmaddr, shmflag, &raddr);
-       if (r < 0)
-               return r;
-       return raddr;
-}
-
 /* Fucking broken ABI */
 
 #ifdef CONFIG_64BIT
diff -urN linux/arch/parisc/kernel/syscall_table.S 
linux/arch/parisc/kernel/syscall_table.S
--- linux/arch/parisc/kernel/syscall_table.S    2005/01/25 04:28:00     1.8
+++ linux/arch/parisc/kernel/syscall_table.S    2005/05/19 12:08:12     1.9
@@ -297,7 +297,7 @@
        ENTRY_DIFF(msgrcv)
        ENTRY_SAME(msgget)              /* 190 */
        ENTRY_SAME(msgctl)
-       ENTRY_SAME(shmat_wrapper)
+       ENTRY_SAME(shmat)
        ENTRY_SAME(shmdt)
        ENTRY_SAME(shmget)
        ENTRY_SAME(shmctl)              /* 195 */
diff -urN linux/arch/ppc/Kconfig linux/arch/ppc/Kconfig
--- linux/arch/ppc/Kconfig      2005/04/29 11:15:03     1.47
+++ linux/arch/ppc/Kconfig      2005/05/19 12:08:12     1.48
@@ -43,6 +43,10 @@
        bool
        default y
 
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+       bool
+       default y
+
 source "init/Kconfig"
 
 menu "Processor"
@@ -53,6 +57,7 @@
 
 config 6xx
        bool "6xx/7xx/74xx/52xx/82xx/83xx"
+       select PPC_FPU
        help
          There are four types of PowerPC chips supported.  The more common
          types (601, 603, 604, 740, 750, 7400), the Motorola embedded
@@ -72,9 +77,11 @@
        bool "44x"
 
 config POWER3
+       select PPC_FPU
        bool "POWER3"
 
 config POWER4
+       select PPC_FPU
        bool "POWER4 and 970 (G5)"
 
 config 8xx
@@ -86,6 +93,9 @@
 
 endchoice
 
+config PPC_FPU
+       bool
+
 config BOOKE
        bool
        depends on E500
@@ -1075,6 +1085,10 @@
 
 endmenu
 
+config ISA_DMA_API
+       bool
+       default y
+
 menu "Bus options"
 
 config ISA
diff -urN linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- linux/arch/ppc/Makefile     2005/04/08 18:57:59     1.64
+++ linux/arch/ppc/Makefile     2005/05/19 12:08:12     1.65
@@ -53,6 +53,7 @@
 
 head-$(CONFIG_6xx)             += arch/ppc/kernel/idle_6xx.o
 head-$(CONFIG_POWER4)          += arch/ppc/kernel/idle_power4.o
+head-$(CONFIG_PPC_FPU)         += arch/ppc/kernel/fpu.o
 
 core-y                         += arch/ppc/kernel/ arch/ppc/platforms/ \
                                   arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/
diff -urN linux/arch/ppc/boot/images/Makefile 
linux/arch/ppc/boot/images/Makefile
--- linux/arch/ppc/boot/images/Makefile 2004/04/28 13:54:53     1.10
+++ linux/arch/ppc/boot/images/Makefile 2005/05/19 12:08:13     1.11
@@ -20,8 +20,9 @@
 
 targets += uImage
 $(obj)/uImage: $(obj)/vmlinux.gz
+       $(Q)rm -f $@
        $(call if_changed,uimage)
-       @echo '  Image $@ is ready'
+       @echo '  Image: $@' $(if $(wildcard $@),'is ready','not made')
 
 # Files generated that shall be removed upon make clean
 clean-files    := sImage vmapus vmlinux* miboot* zImage* uImage
diff -urN linux/arch/ppc/kernel/fpu.S linux/arch/ppc/kernel/fpu.S
--- linux/arch/ppc/kernel/fpu.S 1970/01/01 00:00:00
+++ linux/arch/ppc/kernel/fpu.S 2005-05-19 13:08:13.217251000 +0100     1.1
@@ -0,0 +1,133 @@
+/*
+ *  FPU support code, moved here from head.S so that it can be used
+ *  by chips which use other head-whatever.S files.
+ *
+ *  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 <asm/processor.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/cputable.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+/*
+ * This task wants to use the FPU now.
+ * On UP, disable FP for the task which had the FPU previously,
+ * and save its floating-point registers in its thread_struct.
+ * Load up this task's FP registers from its thread_struct,
+ * enable the FPU for the current task and return to the task.
+ */
+       .globl  load_up_fpu
+load_up_fpu:
+       mfmsr   r5
+       ori     r5,r5,MSR_FP
+#ifdef CONFIG_PPC64BRIDGE
+       clrldi  r5,r5,1                 /* turn off 64-bit mode */
+#endif /* CONFIG_PPC64BRIDGE */
+       SYNC
+       MTMSRD(r5)                      /* enable use of fpu now */
+       isync
+/*
+ * For SMP, we don't do lazy FPU switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another.  Instead we call giveup_fpu in switch_to.
+ */
+#ifndef CONFIG_SMP
+       tophys(r6,0)                    /* get __pa constant */
+       addis   r3,r6,last_task_used_math@ha
+       lwz     r4,last_task_used_math@l(r3)
+       cmpwi   0,r4,0
+       beq     1f
+       add     r4,r4,r6
+       addi    r4,r4,THREAD            /* want last_task_used_math->thread */
+       SAVE_32FPRS(0, r4)
+       mffs    fr0
+       stfd    fr0,THREAD_FPSCR-4(r4)
+       lwz     r5,PT_REGS(r4)
+       add     r5,r5,r6
+       lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+       li      r10,MSR_FP|MSR_FE0|MSR_FE1
+       andc    r4,r4,r10               /* disable FP for previous task */
+       stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* CONFIG_SMP */
+       /* enable use of FP after return */
+       mfspr   r5,SPRN_SPRG3           /* current task's THREAD (phys) */
+       lwz     r4,THREAD_FPEXC_MODE(r5)
+       ori     r9,r9,MSR_FP            /* enable FP for current */
+       or      r9,r9,r4
+       lfd     fr0,THREAD_FPSCR-4(r5)
+       mtfsf   0xff,fr0
+       REST_32FPRS(0, r5)
+#ifndef CONFIG_SMP
+       subi    r4,r5,THREAD
+       sub     r4,r4,r6
+       stw     r4,last_task_used_math@l(r3)
+#endif /* CONFIG_SMP */
+       /* restore registers and return */
+       /* we haven't used ctr or xer or lr */
+       b       fast_exception_return
+
+/*
+ * FP unavailable trap from kernel - print a message, but let
+ * the task use FP in the kernel until it returns to user mode.
+ */
+       .globl  KernelFP
+KernelFP:
+       lwz     r3,_MSR(r1)
+       ori     r3,r3,MSR_FP
+       stw     r3,_MSR(r1)             /* enable use of FP after return */
+       lis     r3,86f@h
+       ori     r3,r3,86f@l
+       mr      r4,r2                   /* current */
+       lwz     r5,_NIP(r1)
+       bl      printk
+       b       ret_from_except
+86:    .string "floating point used in kernel (task=%p, pc=%x)\n"
+       .align  4,0
+
+/*
+ * giveup_fpu(tsk)
+ * Disable FP for the task given as the argument,
+ * and save the floating-point registers in its thread_struct.
+ * Enables the FPU for use in the kernel on return.
+ */
+       .globl  giveup_fpu
+giveup_fpu:
+       mfmsr   r5
+       ori     r5,r5,MSR_FP
+       SYNC_601
+       ISYNC_601
+       MTMSRD(r5)                      /* enable use of fpu now */
+       SYNC_601
+       isync
+       cmpwi   0,r3,0
+       beqlr-                          /* if no previous owner, done */
+       addi    r3,r3,THREAD            /* want THREAD of task */
+       lwz     r5,PT_REGS(r3)
+       cmpwi   0,r5,0
+       SAVE_32FPRS(0, r3)
+       mffs    fr0
+       stfd    fr0,THREAD_FPSCR-4(r3)
+       beq     1f
+       lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+       li      r3,MSR_FP|MSR_FE0|MSR_FE1
+       andc    r4,r4,r3                /* disable FP for previous task */
+       stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef CONFIG_SMP
+       li      r5,0
+       lis     r4,last_task_used_math@ha
+       stw     r5,last_task_used_math@l(r4)
+#endif /* CONFIG_SMP */
+       blr
diff -urN linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- linux/arch/ppc/kernel/Makefile      2005/04/08 18:58:00     1.63
+++ linux/arch/ppc/kernel/Makefile      2005/05/19 12:08:13     1.64
@@ -9,6 +9,7 @@
 extra-$(CONFIG_8xx)            := head_8xx.o
 extra-$(CONFIG_6xx)            += idle_6xx.o
 extra-$(CONFIG_POWER4)         += idle_power4.o
+extra-$(CONFIG_PPC_FPU)                += fpu.o
 extra-y                                += vmlinux.lds
 
 obj-y                          := entry.o traps.o irq.o idle.o time.o misc.o \
diff -urN linux/arch/ppc/kernel/align.c linux/arch/ppc/kernel/align.c
--- linux/arch/ppc/kernel/align.c       2005/03/18 17:36:56     1.19
+++ linux/arch/ppc/kernel/align.c       2005/05/19 12:08:13     1.20
@@ -290,6 +290,10 @@
                        /* lwm, stmw */
                        nb = (32 - reg) * 4;
                }
+
+               if (!access_ok((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, 
nb+nb0))
+                       return -EFAULT; /* bad address */
+
                rptr = (unsigned char *) &regs->gpr[reg];
                if (flags & LD) {
                        for (i = 0; i < nb; ++i)
@@ -368,16 +372,24 @@
 
        /* Single-precision FP load and store require conversions... */
        case LD+F+S:
+#ifdef CONFIG_PPC_FPU
                preempt_disable();
                enable_kernel_fp();
                cvt_fd(&data.f, &data.d, &current->thread.fpscr);
                preempt_enable();
+#else
+               return 0;
+#endif
                break;
        case ST+F+S:
+#ifdef CONFIG_PPC_FPU
                preempt_disable();
                enable_kernel_fp();
                cvt_df(&data.d, &data.f, &current->thread.fpscr);
                preempt_enable();
+#else
+               return 0;
+#endif
                break;
        }
 
diff -urN linux/arch/ppc/kernel/cpu_setup_6xx.S 
linux/arch/ppc/kernel/cpu_setup_6xx.S
--- linux/arch/ppc/kernel/cpu_setup_6xx.S       2005/03/18 17:36:56     1.9
+++ linux/arch/ppc/kernel/cpu_setup_6xx.S       2005/05/19 12:08:13     1.10
@@ -30,12 +30,14 @@
        blr
 _GLOBAL(__setup_cpu_750)
        mflr    r4
+       bl      __init_fpu_registers
        bl      setup_common_caches
        bl      setup_750_7400_hid0
        mtlr    r4
        blr
 _GLOBAL(__setup_cpu_750cx)
        mflr    r4
+       bl      __init_fpu_registers
        bl      setup_common_caches
        bl      setup_750_7400_hid0
        bl      setup_750cx
@@ -43,6 +45,7 @@
        blr
 _GLOBAL(__setup_cpu_750fx)
        mflr    r4
+       bl      __init_fpu_registers
        bl      setup_common_caches
        bl      setup_750_7400_hid0
        bl      setup_750fx
@@ -50,6 +53,7 @@
        blr
 _GLOBAL(__setup_cpu_7400)
        mflr    r4
+       bl      __init_fpu_registers
        bl      setup_7400_workarounds
        bl      setup_common_caches
        bl      setup_750_7400_hid0
@@ -57,6 +61,7 @@
        blr
 _GLOBAL(__setup_cpu_7410)
        mflr    r4
+       bl      __init_fpu_registers
        bl      setup_7410_workarounds
        bl      setup_common_caches
        bl      setup_750_7400_hid0
@@ -80,7 +85,7 @@
        bne     1f                      /* don't invalidate the D-cache */
        ori     r8,r8,HID0_DCI          /* unless it wasn't enabled */
 1:     sync
-       mtspr   SPRN_HID0,r8                    /* enable and invalidate caches 
*/
+       mtspr   SPRN_HID0,r8            /* enable and invalidate caches */
        sync
        mtspr   SPRN_HID0,r11           /* enable caches */
        sync
@@ -152,9 +157,13 @@
 setup_750_7400_hid0:
        mfspr   r11,SPRN_HID0
        ori     r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC
+       oris    r11,r11,HID0_DPM@h
 BEGIN_FTR_SECTION
-       oris    r11,r11,HID0_DPM@h      /* enable dynamic power mgmt */
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
+       xori    r11,r11,HID0_BTIC
+END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC)
+BEGIN_FTR_SECTION
+       xoris   r11,r11,HID0_DPM@h      /* disable dynamic power mgmt */
+END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM)
        li      r3,HID0_SPD
        andc    r11,r11,r3              /* clear SPD: enable speculative */
        li      r3,0
@@ -218,13 +227,15 @@
 
        /* All of the bits we have to set.....
         */
-       ori     r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK | 
HID0_BTIC
+       ori     r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE
+       ori     r11,r11,HID0_LRSTK | HID0_BTIC
+       oris    r11,r11,HID0_DPM@h
 BEGIN_FTR_SECTION
        xori    r11,r11,HID0_BTIC
 END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC)
 BEGIN_FTR_SECTION
-       oris    r11,r11,HID0_DPM@h      /* enable dynamic power mgmt */
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
+       xoris   r11,r11,HID0_DPM@h      /* disable dynamic power mgmt */
+END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM)
 
        /* All of the bits we have to clear....
         */
@@ -248,6 +259,25 @@
        isync
        blr
 
+/*
+ * Initialize the FPU registers. This is needed to work around an errata
+ * in some 750 cpus where using a not yet initialized FPU register after
+ * power on reset may hang the CPU
+ */
+_GLOBAL(__init_fpu_registers)
+       mfmsr   r10
+       ori     r11,r10,MSR_FP
+       mtmsr   r11
+       isync
+       addis   r9,r3,empty_zero_page@ha
+       addi    r9,r9,empty_zero_page@l
+       REST_32FPRS(0,r9)
+       sync
+       mtmsr   r10
+       isync
+       blr
+
+
 /* Definitions for the table use to save CPU states */
 #define CS_HID0                0
 #define CS_HID1                4
diff -urN linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- linux/arch/ppc/kernel/entry.S       2005/04/08 18:58:00     1.45
+++ linux/arch/ppc/kernel/entry.S       2005/05/19 12:08:13     1.46
@@ -563,6 +563,65 @@
        addi    r1,r1,INT_FRAME_SIZE
        blr
 
+       .globl  fast_exception_return
+fast_exception_return:
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
+       andi.   r10,r9,MSR_RI           /* check for recoverable interrupt */
+       beq     1f                      /* if not, we've got problems */
+#endif
+
+2:     REST_4GPRS(3, r11)
+       lwz     r10,_CCR(r11)
+       REST_GPR(1, r11)
+       mtcr    r10
+       lwz     r10,_LINK(r11)
+       mtlr    r10
+       REST_GPR(10, r11)
+       mtspr   SPRN_SRR1,r9
+       mtspr   SPRN_SRR0,r12
+       REST_GPR(9, r11)
+       REST_GPR(12, r11)
+       lwz     r11,GPR11(r11)
+       SYNC
+       RFI
+
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
+/* check if the exception happened in a restartable section */
+1:     lis     r3,exc_exit_restart_end@ha
+       addi    r3,r3,exc_exit_restart_end@l
+       cmplw   r12,r3
+       bge     3f
+       lis     r4,exc_exit_restart@ha
+       addi    r4,r4,exc_exit_restart@l
+       cmplw   r12,r4
+       blt     3f
+       lis     r3,fee_restarts@ha
+       tophys(r3,r3)
+       lwz     r5,fee_restarts@l(r3)
+       addi    r5,r5,1
+       stw     r5,fee_restarts@l(r3)
+       mr      r12,r4          /* restart at exc_exit_restart */
+       b       2b
+
+       .comm   fee_restarts,4
+
+/* aargh, a nonrecoverable interrupt, panic */
+/* aargh, we don't know which trap this is */
+/* but the 601 doesn't implement the RI bit, so assume it's OK */
+3:
+BEGIN_FTR_SECTION
+       b       2b
+END_FTR_SECTION_IFSET(CPU_FTR_601)
+       li      r10,-1
+       stw     r10,TRAP(r11)
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       lis     r10,MSR_KERNEL@h
+       ori     r10,r10,MSR_KERNEL@l
+       bl      transfer_to_handler_full
+       .long   nonrecoverable_exception
+       .long   ret_from_except
+#endif
+
        .globl  sigreturn_exit
 sigreturn_exit:
        subi    r1,r3,STACK_FRAME_OVERHEAD
diff -urN linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- linux/arch/ppc/kernel/head.S        2005/03/18 17:36:56     1.61
+++ linux/arch/ppc/kernel/head.S        2005/05/19 12:08:13     1.62
@@ -775,133 +775,6 @@
        EXC_XFER_STD(0x480, UnknownException)
 #endif /* CONFIG_PPC64BRIDGE */
 
-/*
- * This task wants to use the FPU now.
- * On UP, disable FP for the task which had the FPU previously,
- * and save its floating-point registers in its thread_struct.
- * Load up this task's FP registers from its thread_struct,
- * enable the FPU for the current task and return to the task.
- */
-load_up_fpu:
-       mfmsr   r5
-       ori     r5,r5,MSR_FP
-#ifdef CONFIG_PPC64BRIDGE
-       clrldi  r5,r5,1                 /* turn off 64-bit mode */
-#endif /* CONFIG_PPC64BRIDGE */
-       SYNC
-       MTMSRD(r5)                      /* enable use of fpu now */
-       isync
-/*
- * For SMP, we don't do lazy FPU switching because it just gets too
- * horrendously complex, especially when a task switches from one CPU
- * to another.  Instead we call giveup_fpu in switch_to.
- */
-#ifndef CONFIG_SMP
-       tophys(r6,0)                    /* get __pa constant */
-       addis   r3,r6,last_task_used_math@ha
-       lwz     r4,last_task_used_math@l(r3)
-       cmpwi   0,r4,0
-       beq     1f
-       add     r4,r4,r6
-       addi    r4,r4,THREAD            /* want last_task_used_math->thread */
-       SAVE_32FPRS(0, r4)
-       mffs    fr0
-       stfd    fr0,THREAD_FPSCR-4(r4)
-       lwz     r5,PT_REGS(r4)
-       add     r5,r5,r6
-       lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-       li      r10,MSR_FP|MSR_FE0|MSR_FE1
-       andc    r4,r4,r10               /* disable FP for previous task */
-       stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#endif /* CONFIG_SMP */
-       /* enable use of FP after return */
-       mfspr   r5,SPRN_SPRG3           /* current task's THREAD (phys) */
-       lwz     r4,THREAD_FPEXC_MODE(r5)
-       ori     r9,r9,MSR_FP            /* enable FP for current */
-       or      r9,r9,r4
-       lfd     fr0,THREAD_FPSCR-4(r5)
-       mtfsf   0xff,fr0
-       REST_32FPRS(0, r5)
-#ifndef CONFIG_SMP
-       subi    r4,r5,THREAD
-       sub     r4,r4,r6
-       stw     r4,last_task_used_math@l(r3)
-#endif /* CONFIG_SMP */
-       /* restore registers and return */
-       /* we haven't used ctr or xer or lr */
-       /* fall through to fast_exception_return */
-
-       .globl  fast_exception_return
-fast_exception_return:
-       andi.   r10,r9,MSR_RI           /* check for recoverable interrupt */
-       beq     1f                      /* if not, we've got problems */
-2:     REST_4GPRS(3, r11)
-       lwz     r10,_CCR(r11)
-       REST_GPR(1, r11)
-       mtcr    r10
-       lwz     r10,_LINK(r11)
-       mtlr    r10
-       REST_GPR(10, r11)
-       mtspr   SPRN_SRR1,r9
-       mtspr   SPRN_SRR0,r12
-       REST_GPR(9, r11)
-       REST_GPR(12, r11)
-       lwz     r11,GPR11(r11)
-       SYNC
-       RFI
-
-/* check if the exception happened in a restartable section */
-1:     lis     r3,exc_exit_restart_end@ha
-       addi    r3,r3,exc_exit_restart_end@l
-       cmplw   r12,r3
-       bge     3f
-       lis     r4,exc_exit_restart@ha
-       addi    r4,r4,exc_exit_restart@l
-       cmplw   r12,r4
-       blt     3f
-       lis     r3,fee_restarts@ha
-       tophys(r3,r3)
-       lwz     r5,fee_restarts@l(r3)
-       addi    r5,r5,1
-       stw     r5,fee_restarts@l(r3)
-       mr      r12,r4          /* restart at exc_exit_restart */
-       b       2b
-
-       .comm   fee_restarts,4
-
-/* aargh, a nonrecoverable interrupt, panic */
-/* aargh, we don't know which trap this is */
-/* but the 601 doesn't implement the RI bit, so assume it's OK */
-3:
-BEGIN_FTR_SECTION
-       b       2b
-END_FTR_SECTION_IFSET(CPU_FTR_601)
-       li      r10,-1
-       stw     r10,TRAP(r11)
-       addi    r3,r1,STACK_FRAME_OVERHEAD
-       li      r10,MSR_KERNEL
-       bl      transfer_to_handler_full
-       .long   nonrecoverable_exception
-       .long   ret_from_except
-
-/*
- * FP unavailable trap from kernel - print a message, but let
- * the task use FP in the kernel until it returns to user mode.
- */
-KernelFP:
-       lwz     r3,_MSR(r1)
-       ori     r3,r3,MSR_FP
-       stw     r3,_MSR(r1)             /* enable use of FP after return */
-       lis     r3,86f@h
-       ori     r3,r3,86f@l
-       mr      r4,r2                   /* current */
-       lwz     r5,_NIP(r1)
-       bl      printk
-       b       ret_from_except
-86:    .string "floating point used in kernel (task=%p, pc=%x)\n"
-       .align  4,0
-
 #ifdef CONFIG_ALTIVEC
 /* Note that the AltiVec support is closely modeled after the FP
  * support.  Changes to one are likely to be applicable to the
@@ -1016,42 +889,6 @@
 #endif /* CONFIG_ALTIVEC */
 
 /*
- * giveup_fpu(tsk)
- * Disable FP for the task given as the argument,
- * and save the floating-point registers in its thread_struct.
- * Enables the FPU for use in the kernel on return.
- */
-       .globl  giveup_fpu
-giveup_fpu:
-       mfmsr   r5
-       ori     r5,r5,MSR_FP
-       SYNC_601
-       ISYNC_601
-       MTMSRD(r5)                      /* enable use of fpu now */
-       SYNC_601
-       isync
-       cmpwi   0,r3,0
-       beqlr-                          /* if no previous owner, done */
-       addi    r3,r3,THREAD            /* want THREAD of task */
-       lwz     r5,PT_REGS(r3)
-       cmpwi   0,r5,0
-       SAVE_32FPRS(0, r3)
-       mffs    fr0
-       stfd    fr0,THREAD_FPSCR-4(r3)
-       beq     1f
-       lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-       li      r3,MSR_FP|MSR_FE0|MSR_FE1
-       andc    r4,r4,r3                /* disable FP for previous task */
-       stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-1:
-#ifndef CONFIG_SMP
-       li      r5,0
-       lis     r4,last_task_used_math@ha
-       stw     r5,last_task_used_math@l(r4)
-#endif /* CONFIG_SMP */
-       blr
-
-/*
  * This code is jumped to from the startup code to copy
  * the kernel image to physical address 0.
  */
diff -urN linux/arch/ppc/kernel/head_44x.S linux/arch/ppc/kernel/head_44x.S
--- linux/arch/ppc/kernel/head_44x.S    2005/04/08 18:58:00     1.14
+++ linux/arch/ppc/kernel/head_44x.S    2005/05/19 12:08:13     1.15
@@ -426,7 +426,11 @@
        PROGRAM_EXCEPTION
 
        /* Floating Point Unavailable Interrupt */
+#ifdef CONFIG_PPC_FPU
+       FP_UNAVAILABLE_EXCEPTION
+#else
        EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, 
EXC_XFER_EE)
+#endif
 
        /* System Call Interrupt */
        START_EXCEPTION(SystemCall)
@@ -686,8 +690,10 @@
  *
  * The 44x core does not have an FPU.
  */
+#ifndef CONFIG_PPC_FPU
 _GLOBAL(giveup_fpu)
        blr
+#endif
 
 /*
  * extern void abort(void)
diff -urN linux/arch/ppc/kernel/head_booke.h linux/arch/ppc/kernel/head_booke.h
--- linux/arch/ppc/kernel/head_booke.h  2005/04/08 18:58:00     1.5
+++ linux/arch/ppc/kernel/head_booke.h  2005/05/19 12:08:13     1.6
@@ -337,4 +337,11 @@
        addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
        EXC_XFER_LITE(0x0900, timer_interrupt)
 
+#define FP_UNAVAILABLE_EXCEPTION                                             \
+       START_EXCEPTION(FloatingPointUnavailable)                             \
+       NORMAL_EXCEPTION_PROLOG;                                              \
+       bne     load_up_fpu;            /* if from user, just load it up */   \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
+       EXC_XFER_EE_LITE(0x800, KernelFP)
+
 #endif /* __HEAD_BOOKE_H__ */
diff -urN linux/arch/ppc/kernel/head_fsl_booke.S 
linux/arch/ppc/kernel/head_fsl_booke.S
--- linux/arch/ppc/kernel/head_fsl_booke.S      2005/04/29 11:15:03     1.2
+++ linux/arch/ppc/kernel/head_fsl_booke.S      2005/05/19 12:08:13     1.3
@@ -504,7 +504,11 @@
        PROGRAM_EXCEPTION
 
        /* Floating Point Unavailable Interrupt */
+#ifdef CONFIG_PPC_FPU
+       FP_UNAVAILABLE_EXCEPTION
+#else
        EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, 
EXC_XFER_EE)
+#endif
 
        /* System Call Interrupt */
        START_EXCEPTION(SystemCall)
@@ -916,10 +920,12 @@
 /*
  * extern void giveup_fpu(struct task_struct *prev)
  *
- * The e500 core does not have an FPU.
+ * Not all FSL Book-E cores have an FPU
  */
+#ifndef CONFIG_PPC_FPU
 _GLOBAL(giveup_fpu)
        blr
+#endif
 
 /*
  * extern void abort(void)
diff -urN linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- linux/arch/ppc/kernel/misc.S        2005/03/18 17:36:56     1.77
+++ linux/arch/ppc/kernel/misc.S        2005/05/19 12:08:13     1.78
@@ -1096,17 +1096,7 @@
  * and exceptions as if the cpu had performed the load or store.
  */
 
-#if defined(CONFIG_4xx) || defined(CONFIG_E500)
-_GLOBAL(cvt_fd)
-       lfs     0,0(r3)
-       stfd    0,0(r4)
-       blr
-
-_GLOBAL(cvt_df)
-       lfd     0,0(r3)
-       stfs    0,0(r4)
-       blr
-#else
+#ifdef CONFIG_PPC_FPU
 _GLOBAL(cvt_fd)
        lfd     0,-4(r5)        /* load up fpscr value */
        mtfsf   0xff,0
diff -urN linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- linux/arch/ppc/kernel/pci.c 2005/04/08 18:58:00     1.57
+++ linux/arch/ppc/kernel/pci.c 2005/05/19 12:08:13     1.58
@@ -1432,7 +1432,7 @@
        return NULL;
 }
 
-void*
+void __iomem *
 pci_bus_io_base(unsigned int bus)
 {
        struct pci_controller *hose;
diff -urN linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- linux/arch/ppc/kernel/ptrace.c      2004/11/15 11:49:19     1.32
+++ linux/arch/ppc/kernel/ptrace.c      2005/05/19 12:08:13     1.33
@@ -26,6 +26,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -356,7 +357,7 @@
        case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall 
*/
        case PTRACE_CONT: { /* restart after signal. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                if (request == PTRACE_SYSCALL) {
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -389,7 +390,7 @@
 
        case PTRACE_SINGLESTEP: {  /* set the trap flag. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                set_single_step(child);
diff -urN linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- linux/arch/ppc/kernel/setup.c       2005/04/08 18:58:00     1.81
+++ linux/arch/ppc/kernel/setup.c       2005/05/19 12:08:13     1.82
@@ -221,27 +221,26 @@
                        return err;
        }
 
-       switch (PVR_VER(pvr)) {
-       case 0x0020:    /* 403 family */
-               maj = PVR_MAJ(pvr) + 1;
-               min = PVR_MIN(pvr);
-               break;
-       case 0x1008:    /* 740P/750P ?? */
-               maj = ((pvr >> 8) & 0xFF) - 1;
-               min = pvr & 0xFF;
-               break;
-       case 0x8083:    /* e300 */
-               maj = PVR_MAJ(pvr);
-               min = PVR_MIN(pvr);
-               break;
-       case 0x8020:    /* e500 */
+       /* If we are a Freescale core do a simple check so
+        * we dont have to keep adding cases in the future */
+       if ((PVR_VER(pvr) & 0x8000) == 0x8000) {
                maj = PVR_MAJ(pvr);
                min = PVR_MIN(pvr);
-               break;
-       default:
-               maj = (pvr >> 8) & 0xFF;
-               min = pvr & 0xFF;
-               break;
+       } else {
+               switch (PVR_VER(pvr)) {
+                       case 0x0020:    /* 403 family */
+                               maj = PVR_MAJ(pvr) + 1;
+                               min = PVR_MIN(pvr);
+                               break;
+                       case 0x1008:    /* 740P/750P ?? */
+                               maj = ((pvr >> 8) & 0xFF) - 1;
+                               min = pvr & 0xFF;
+                               break;
+                       default:
+                               maj = (pvr >> 8) & 0xFF;
+                               min = pvr & 0xFF;
+                               break;
+               }
        }
 
        seq_printf(m, "revision\t: %hd.%hd (pvr %04x %04x)\n",
diff -urN linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c
--- linux/arch/ppc/kernel/signal.c      2005/04/29 11:15:03     1.45
+++ linux/arch/ppc/kernel/signal.c      2005/05/19 12:08:13     1.46
@@ -511,7 +511,7 @@
 }
 
 int sys_debug_setcontext(struct ucontext __user *ctx,
-                        int ndbg, struct sig_dbg_op *dbg,
+                        int ndbg, struct sig_dbg_op __user *dbg,
                         int r6, int r7, int r8,
                         struct pt_regs *regs)
 {
@@ -632,7 +632,7 @@
        if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
            || __put_user(oldset->sig[0], &sc->oldmask)
            || __put_user(oldset->sig[1], &sc->_unused[3])
-           || __put_user((struct pt_regs *)frame, &sc->regs)
+           || __put_user((struct pt_regs __user *)frame, &sc->regs)
            || __put_user(sig, &sc->signal))
                goto badframe;
 
diff -urN linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- linux/arch/ppc/kernel/traps.c       2005/04/29 11:15:03     1.52
+++ linux/arch/ppc/kernel/traps.c       2005/05/19 12:08:13     1.53
@@ -176,7 +176,7 @@
 #else
 #define get_mc_reason(regs)    (mfspr(SPRN_MCSR))
 #endif
-#define REASON_FP              0
+#define REASON_FP              ESR_FP
 #define REASON_ILLEGAL         ESR_PIL
 #define REASON_PRIVILEGED      ESR_PPR
 #define REASON_TRAP            ESR_PTR
@@ -403,7 +403,7 @@
        u8 rA = (instword >> 16) & 0x1f;
        u8 NB_RB = (instword >> 11) & 0x1f;
        u32 num_bytes;
-       u32 EA;
+       unsigned long EA;
        int pos = 0;
 
        /* Early out if we are an invalid form of lswx */
diff -urN linux/arch/ppc/kernel/vmlinux.lds.S 
linux/arch/ppc/kernel/vmlinux.lds.S
--- linux/arch/ppc/kernel/vmlinux.lds.S 2005/03/18 17:36:56     1.7
+++ linux/arch/ppc/kernel/vmlinux.lds.S 2005/05/19 12:08:13     1.8
@@ -145,6 +145,7 @@
   __init_end = .;
 
   . = ALIGN(4096);
+  _sextratext = .;
   __pmac_begin = .;
   .pmac.text : { *(.pmac.text) }
   .pmac.data : { *(.pmac.data) }
@@ -171,6 +172,7 @@
   .openfirmware.data : { *(.openfirmware.data) }
   . = ALIGN(4096);
   __openfirmware_end = .;
+  _eextratext = .;
 
   __bss_start = .;
   .bss       :
diff -urN linux/arch/ppc/platforms/chrp_pci.c 
linux/arch/ppc/platforms/chrp_pci.c
--- linux/arch/ppc/platforms/chrp_pci.c 2005/02/07 02:54:35     1.7
+++ linux/arch/ppc/platforms/chrp_pci.c 2005/05/19 12:08:13     1.8
@@ -129,7 +129,7 @@
        rtas_write_config
 };
 
-volatile struct Hydra *Hydra = NULL;
+volatile struct Hydra __iomem *Hydra = NULL;
 
 int __init
 hydra_init(void)
@@ -175,13 +175,14 @@
 static void __init
 setup_python(struct pci_controller *hose, struct device_node *dev)
 {
-       u32 *reg, val;
+       u32 __iomem *reg;
+       u32 val;
        unsigned long addr = dev->addrs[0].address;
 
        setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
 
        /* Clear the magic go-slow bit */
-       reg = (u32 *) ioremap(dev->addrs[0].address + 0xf6000, 0x40);
+       reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40);
        val = in_be32(&reg[12]);
        if (val & PRG_CL_RESET_VALID) {
                out_be32(&reg[12], val & ~PRG_CL_RESET_VALID);
diff -urN linux/arch/ppc/platforms/chrp_setup.c 
linux/arch/ppc/platforms/chrp_setup.c
--- linux/arch/ppc/platforms/chrp_setup.c       2005/04/08 18:58:00     1.19
+++ linux/arch/ppc/platforms/chrp_setup.c       2005/05/19 12:08:13     1.20
@@ -356,7 +356,7 @@
        struct device_node *np;
        int len, i;
        unsigned int *iranges;
-       void *isu;
+       void __iomem *isu;
 
        np = find_type_devices("open-pic");
        if (np == NULL || np->n_addrs == 0)
diff -urN linux/arch/ppc/platforms/pmac_cache.S 
linux/arch/ppc/platforms/pmac_cache.S
--- linux/arch/ppc/platforms/pmac_cache.S       2005/04/29 11:15:03     1.3
+++ linux/arch/ppc/platforms/pmac_cache.S       2005/05/19 12:08:13     1.4
@@ -64,27 +64,39 @@
        mtspr   SPRN_HID0,r4            /* Disable DPM */
        sync
 
-       /* disp-flush L1 */
-       li      r4,0x4000
-       mtctr   r4
+       /* Disp-flush L1. We have a weird problem here that I never
+        * totally figured out. On 750FX, using the ROM for the flush
+        * results in a non-working flush. We use that workaround for
+        * now until I finally understand what's going on. --BenH
+        */
+
+       /* ROM base by default */
        lis     r4,0xfff0
-1:     lwzx    r0,r0,r4
+       mfpvr   r3
+       srwi    r3,r3,16
+       cmplwi  cr0,r3,0x7000
+       bne+    1f
+       /* RAM base on 750FX */
+       li      r4,0
+1:     li      r4,0x4000
+       mtctr   r4
+1:     lwz     r0,0(r4)
        addi    r4,r4,32
        bdnz    1b
        sync
        isync
 
-       /* disable / invalidate / enable L1 data */
+       /* Disable / invalidate / enable L1 data */
        mfspr   r3,SPRN_HID0
-       rlwinm  r0,r0,0,~HID0_DCE
+       rlwinm  r3,r3,0,~(HID0_DCE | HID0_ICE)
        mtspr   SPRN_HID0,r3
        sync
        isync
-       ori     r3,r3,HID0_DCE|HID0_DCI
+       ori     r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI)
        sync
        isync
        mtspr   SPRN_HID0,r3
-       xori    r3,r3,HID0_DCI
+       xori    r3,r3,(HID0_DCI|HID0_ICFI)
        mtspr   SPRN_HID0,r3
        sync
 
@@ -110,11 +122,20 @@
        lis     r4,2
        mtctr   r4
        lis     r4,0xfff0
-1:     lwzx    r0,r0,r4
+1:     lwz     r0,0(r4)
+       addi    r4,r4,32
+       bdnz    1b
+       sync
+       isync
+       lis     r4,2
+       mtctr   r4
+       lis     r4,0xfff0
+1:     dcbf    0,r4
        addi    r4,r4,32
        bdnz    1b
        sync
        isync
+
        /* now disable L2 */
        rlwinm  r5,r5,0,~L2CR_L2E
        b       2f
@@ -135,6 +156,13 @@
        mtspr   SPRN_L2CR,r4
        sync
        isync
+
+       /* Wait for the invalidation to complete */
+1:     mfspr   r3,SPRN_L2CR
+       rlwinm. r0,r3,0,31,31
+       bne     1b
+
+       /* Clear L2I */
        xoris   r4,r4,L2CR_L2I@h
        sync
        mtspr   SPRN_L2CR,r4
@@ -142,14 +170,16 @@
 
        /* now disable the L1 data cache */
        mfspr   r0,SPRN_HID0
-       rlwinm  r0,r0,0,~HID0_DCE
+       rlwinm  r0,r0,0,~(HID0_DCE|HID0_ICE)
        mtspr   SPRN_HID0,r0
        sync
        isync
 
        /* Restore HID0[DPM] to whatever it was before */
        sync
-       mtspr   SPRN_HID0,r8
+       mfspr   r0,SPRN_HID0
+       rlwimi  r0,r8,0,11,11           /* Turn back HID0[DPM] */
+       mtspr   SPRN_HID0,r0
        sync
 
        /* restore DR and EE */
@@ -201,7 +231,7 @@
         mtctr   r4
        li      r4,0
 1:
-        lwzx    r0,r0,r4
+        lwz     r0,0(r4)
         addi    r4,r4,32                /* Go to start of next cache line */
         bdnz    1b
         isync
diff -urN linux/arch/ppc/platforms/pmac_feature.c 
linux/arch/ppc/platforms/pmac_feature.c
--- linux/arch/ppc/platforms/pmac_feature.c     2005/04/29 11:15:03     1.21
+++ linux/arch/ppc/platforms/pmac_feature.c     2005/05/19 12:08:13     1.22
@@ -1590,6 +1590,114 @@
        mdelay(10);
 }
 
+
+void __pmac pmac_tweak_clock_spreading(int enable)
+{
+       struct macio_chip* macio = &macio_chips[0];
+
+       /* Hack for doing clock spreading on some machines PowerBooks and
+        * iBooks. This implements the "platform-do-clockspreading" OF
+        * property as decoded manually on various models. For safety, we also
+        * check the product ID in the device-tree in cases we'll whack the i2c
+        * chip to make reasonably sure we won't set wrong values in there
+        *
+        * Of course, ultimately, we have to implement a real parser for
+        * the platform-do-* stuff...
+        */
+
+       if (macio->type == macio_intrepid) {
+               if (enable)
+                       UN_OUT(UNI_N_CLOCK_SPREADING, 2);
+               else
+                       UN_OUT(UNI_N_CLOCK_SPREADING, 0);
+               mdelay(40);
+       }
+
+       while (machine_is_compatible("PowerBook5,2") ||
+              machine_is_compatible("PowerBook5,3") ||
+              machine_is_compatible("PowerBook6,2") ||
+              machine_is_compatible("PowerBook6,3")) {
+               struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
+               struct device_node *dt = of_find_node_by_name(NULL, 
"device-tree");
+               u8 buffer[9];
+               u32 *productID;
+               int i, rc, changed = 0;
+
+               if (dt == NULL)
+                       break;
+               productID = (u32 *)get_property(dt, "pid#", NULL);
+               if (productID == NULL)
+                       break;
+               while(ui2c) {
+                       struct device_node *p = of_get_parent(ui2c);
+                       if (p && !strcmp(p->name, "uni-n"))
+                               break;
+                       ui2c = of_find_node_by_type(ui2c, "i2c");
+               }
+               if (ui2c == NULL)
+                       break;
+               DBG("Trying to bump clock speed for PID: %08x...\n", 
*productID);
+               rc = pmac_low_i2c_open(ui2c, 1);
+               if (rc != 0)
+                       break;
+               pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
+               rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, 
buffer, 9);
+               DBG("read result: %d,", rc);
+               if (rc != 0) {
+                       pmac_low_i2c_close(ui2c);
+                       break;
+               }
+               for (i=0; i<9; i++)
+                       DBG(" %02x", buffer[i]);
+               DBG("\n");
+
+               switch(*productID) {
+               case 0x1182:    /* AlBook 12" rev 2 */
+               case 0x1183:    /* iBook G4 12" */
+                       buffer[0] = (buffer[0] & 0x8f) | 0x70;
+                       buffer[2] = (buffer[2] & 0x7f) | 0x00;
+                       buffer[5] = (buffer[5] & 0x80) | 0x31;
+                       buffer[6] = (buffer[6] & 0x40) | 0xb0;
+                       buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba);
+                       buffer[8] = (buffer[8] & 0x00) | 0x30;
+                       changed = 1;
+                       break;
+               case 0x3142:    /* AlBook 15" (ATI M10) */
+               case 0x3143:    /* AlBook 17" (ATI M10) */
+                       buffer[0] = (buffer[0] & 0xaf) | 0x50;
+                       buffer[2] = (buffer[2] & 0x7f) | 0x00;
+                       buffer[5] = (buffer[5] & 0x80) | 0x31;
+                       buffer[6] = (buffer[6] & 0x40) | 0xb0;
+                       buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0);
+                       buffer[8] = (buffer[8] & 0x00) | 0x30;
+                       changed = 1;
+                       break;
+               default:
+                       DBG("i2c-hwclock: Machine model not handled\n");
+                       break;
+               }
+               if (!changed) {
+                       pmac_low_i2c_close(ui2c);
+                       break;
+               }
+               pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
+               rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, 
buffer, 9);
+               DBG("write result: %d,", rc);
+               pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
+               rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, 
buffer, 9);
+               DBG("read result: %d,", rc);
+               if (rc != 0) {
+                       pmac_low_i2c_close(ui2c);
+                       break;
+               }
+               for (i=0; i<9; i++)
+                       DBG(" %02x", buffer[i]);
+               pmac_low_i2c_close(ui2c);
+               break;
+       }
+}
+
+
 static int __pmac
 core99_sleep(void)
 {
@@ -1601,12 +1709,6 @@
            macio->type != macio_intrepid)
                return -ENODEV;
 
-       /* The device-tree contains that in the hwclock node */
-       if (macio->type == macio_intrepid) {
-               UN_OUT(UNI_N_CLOCK_SPREADING, 0);
-               mdelay(40);
-       }
-
        /* We power off the wireless slot in case it was not done
         * by the driver. We don't power it on automatically however
         */
@@ -1749,12 +1851,6 @@
        UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
        udelay(100);
 
-       /* Restore clock spreading */
-       if (macio->type == macio_intrepid) {
-               UN_OUT(UNI_N_CLOCK_SPREADING, 2);
-               mdelay(40);
-       }
-
        return 0;
 }
 
@@ -2149,7 +2245,7 @@
        },
        {       "PowerBook1,1",                 "PowerBook 101 (Lombard)",
                PMAC_TYPE_101_PBOOK,            paddington_features,
-               PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE
+               PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
        },
        {       "PowerBook2,1",                 "iBook (first generation)",
                PMAC_TYPE_ORIG_IBOOK,           core99_features,
@@ -2718,97 +2814,11 @@
                MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
        }
 
-       /* Hack for bumping clock speed on the new PowerBooks and the
-        * iBook G4. This implements the "platform-do-clockspreading" OF
-        * property. For safety, we also check the product ID in the
-        * device-tree to make reasonably sure we won't set wrong values
-        * in the clock chip.
-        *
-        * Of course, ultimately, we have to implement a real parser for
-        * the platform-do-* stuff...
+       /* Some machine models need the clock chip to be properly setup for
+        * clock spreading now. This should be a platform function but we
+        * don't do these at the moment
         */
-       while (machine_is_compatible("PowerBook5,2") ||
-              machine_is_compatible("PowerBook5,3") ||
-              machine_is_compatible("PowerBook6,2") ||
-              machine_is_compatible("PowerBook6,3")) {
-               struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
-               struct device_node *dt = of_find_node_by_name(NULL, 
"device-tree");
-               u8 buffer[9];
-               u32 *productID;
-               int i, rc, changed = 0;
-               
-               if (dt == NULL)
-                       break;
-               productID = (u32 *)get_property(dt, "pid#", NULL);
-               if (productID == NULL)
-                       break;
-               while(ui2c) {
-                       struct device_node *p = of_get_parent(ui2c);
-                       if (p && !strcmp(p->name, "uni-n"))
-                               break;
-                       ui2c = of_find_node_by_type(ui2c, "i2c");
-               }
-               if (ui2c == NULL)
-                       break;
-               DBG("Trying to bump clock speed for PID: %08x...\n", 
*productID);
-               rc = pmac_low_i2c_open(ui2c, 1);
-               if (rc != 0)
-                       break;
-               pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
-               rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, 
buffer, 9);
-               DBG("read result: %d,", rc);
-               if (rc != 0) {
-                       pmac_low_i2c_close(ui2c);
-                       break;
-               }
-               for (i=0; i<9; i++)
-                       DBG(" %02x", buffer[i]);
-               DBG("\n");
-               
-               switch(*productID) {
-               case 0x1182:    /* AlBook 12" rev 2 */
-               case 0x1183:    /* iBook G4 12" */
-                       buffer[0] = (buffer[0] & 0x8f) | 0x70;
-                       buffer[2] = (buffer[2] & 0x7f) | 0x00;
-                       buffer[5] = (buffer[5] & 0x80) | 0x31;
-                       buffer[6] = (buffer[6] & 0x40) | 0xb0;
-                       buffer[7] = (buffer[7] & 0x00) | 0xc0;
-                       buffer[8] = (buffer[8] & 0x00) | 0x30;
-                       changed = 1;
-                       break;
-               case 0x3142:    /* AlBook 15" (ATI M10) */
-               case 0x3143:    /* AlBook 17" (ATI M10) */
-                       buffer[0] = (buffer[0] & 0xaf) | 0x50;
-                       buffer[2] = (buffer[2] & 0x7f) | 0x00;
-                       buffer[5] = (buffer[5] & 0x80) | 0x31;
-                       buffer[6] = (buffer[6] & 0x40) | 0xb0;
-                       buffer[7] = (buffer[7] & 0x00) | 0xd0;
-                       buffer[8] = (buffer[8] & 0x00) | 0x30;
-                       changed = 1;
-                       break;
-               default:
-                       DBG("i2c-hwclock: Machine model not handled\n");
-                       break;
-               }
-               if (!changed) {
-                       pmac_low_i2c_close(ui2c);
-                       break;
-               }
-               pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
-               rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, 
buffer, 9);
-               DBG("write result: %d,", rc);
-               pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
-               rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, 
buffer, 9);
-               DBG("read result: %d,", rc);
-               if (rc != 0) {
-                       pmac_low_i2c_close(ui2c);
-                       break;
-               }
-               for (i=0; i<9; i++)
-                       DBG(" %02x", buffer[i]);
-               pmac_low_i2c_close(ui2c);
-               break;
-       }
+       pmac_tweak_clock_spreading(1);
 
 #endif /* CONFIG_POWER4 */
 
diff -urN linux/arch/ppc/platforms/pmac_low_i2c.c 
linux/arch/ppc/platforms/pmac_low_i2c.c
--- linux/arch/ppc/platforms/pmac_low_i2c.c     2004/02/19 03:06:24     1.1
+++ linux/arch/ppc/platforms/pmac_low_i2c.c     2005/05/19 12:08:13     1.2
@@ -54,7 +54,7 @@
        int                     mode;           /* Current mode */
        int                     channel;        /* Current channel */
        int                     num_channels;   /* Number of channels */
-       unsigned long           base;           /* For keywest-i2c, base 
address */
+       void __iomem *          base;           /* For keywest-i2c, base 
address */
        int                     bsteps;         /* And register stepping */
        int                     speed;          /* And speed */
 };
@@ -154,14 +154,12 @@
 
 static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)
 {
-       return in_8(((volatile u8 *)host->base)
-               + (((unsigned)reg) << host->bsteps));
+       return in_8(host->base + (((unsigned)reg) << host->bsteps));
 }
 
 static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
 {
-       out_8(((volatile u8 *)host->base)
-               + (((unsigned)reg) << host->bsteps), val);
+       out_8(host->base + (((unsigned)reg) << host->bsteps), val);
        (void)__kw_read_reg(host, reg_subaddr);
 }
 
@@ -370,7 +368,7 @@
                break;
        }       
        host->mode = pmac_low_i2c_mode_std;
-       host->base = (unsigned long)ioremap(np->addrs[0].address + aoffset,
+       host->base = ioremap(np->addrs[0].address + aoffset,
                                                np->addrs[0].size);
        host->func = keywest_low_i2c_func;
 }
diff -urN linux/arch/ppc/platforms/pmac_sleep.S 
linux/arch/ppc/platforms/pmac_sleep.S
--- linux/arch/ppc/platforms/pmac_sleep.S       2005/03/18 17:36:57     1.6
+++ linux/arch/ppc/platforms/pmac_sleep.S       2005/05/19 12:08:13     1.7
@@ -267,6 +267,10 @@
        /* Restore various CPU config stuffs */
        bl      __restore_cpu_setup
 
+       /* Make sure all FPRs have been initialized */
+       bl      reloc_offset
+       bl      __init_fpu_registers
+
        /* Invalidate & enable L1 cache, we don't care about
         * whatever the ROM may have tried to write to memory
         */
diff -urN linux/arch/ppc/platforms/pmac_smp.c 
linux/arch/ppc/platforms/pmac_smp.c
--- linux/arch/ppc/platforms/pmac_smp.c 2005/04/29 11:15:03     1.17
+++ linux/arch/ppc/platforms/pmac_smp.c 2005/05/19 12:08:13     1.18
@@ -91,11 +91,11 @@
 #define PSURGE_QUAD_BIC(r, v)  (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
 
 /* virtual addresses for the above */
-static volatile u8 *hhead_base;
-static volatile u8 *quad_base;
-static volatile u32 *psurge_pri_intr;
-static volatile u8 *psurge_sec_intr;
-static volatile u32 *psurge_start;
+static volatile u8 __iomem *hhead_base;
+static volatile u8 __iomem *quad_base;
+static volatile u32 __iomem *psurge_pri_intr;
+static volatile u8 __iomem *psurge_sec_intr;
+static volatile u32 __iomem *psurge_start;
 
 /* values for psurge_type */
 #define PSURGE_NONE            -1
@@ -322,10 +322,10 @@
                /* All released cards using this HW design have 4 CPUs */
                ncpus = 4;
        } else {
-               iounmap((void *) quad_base);
+               iounmap(quad_base);
                if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
                        /* not a dual-cpu card */
-                       iounmap((void *) hhead_base);
+                       iounmap(hhead_base);
                        psurge_type = PSURGE_NONE;
                        return 1;
                }
diff -urN linux/arch/ppc/platforms/pmac_time.c 
linux/arch/ppc/platforms/pmac_time.c
--- linux/arch/ppc/platforms/pmac_time.c        2004/09/19 12:30:05     1.8
+++ linux/arch/ppc/platforms/pmac_time.c        2005/05/19 12:08:13     1.9
@@ -165,7 +165,7 @@
 via_calibrate_decr(void)
 {
        struct device_node *vias;
-       volatile unsigned char *via;
+       volatile unsigned char __iomem *via;
        int count = VIA_TIMER_FREQ_6 / 100;
        unsigned int dstart, dend;
 
@@ -176,8 +176,7 @@
                vias = find_devices("via");
        if (vias == 0 || vias->n_addrs == 0)
                return 0;
-       via = (volatile unsigned char *)
-               ioremap(vias->addrs[0].address, vias->addrs[0].size);
+       via = ioremap(vias->addrs[0].address, vias->addrs[0].size);
 
        /* set timer 1 for continuous interrupts */
        out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
@@ -202,7 +201,7 @@
        printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u 
ticks)\n",
               tb_ticks_per_jiffy, dstart - dend);
 
-       iounmap((void*)via);
+       iounmap(via);
        
        return 1;
 }
diff -urN linux/arch/ppc/platforms/radstone_ppc7d.c 
linux/arch/ppc/platforms/radstone_ppc7d.c
--- linux/arch/ppc/platforms/radstone_ppc7d.c   2005/04/08 18:58:00     1.2
+++ linux/arch/ppc/platforms/radstone_ppc7d.c   2005/05/19 12:08:13     1.3
@@ -68,6 +68,7 @@
 #define PPC7D_RST_PIN                  17      /* GPP17 */
 
 extern u32 mv64360_irq_base;
+extern spinlock_t rtc_lock;
 
 static struct mv64x60_handle bh;
 static int ppc7d_has_alma;
@@ -75,6 +76,11 @@
 extern void gen550_progress(char *, unsigned short);
 extern void gen550_init(int, struct uart_port *);
 
+/* FIXME - move to h file */
+extern int ds1337_do_command(int id, int cmd, void *arg);
+#define DS1337_GET_DATE         0
+#define DS1337_SET_DATE         1
+
 /* residual data */
 unsigned char __res[sizeof(bd_t)];
 
@@ -253,6 +259,8 @@
        u8 val1, val2;
        static int flash_sizes[4] = { 64, 32, 0, 16 };
        static int flash_banks[4] = { 4, 3, 2, 1 };
+       static int sdram_bank_sizes[4] = { 128, 256, 512, 1 };
+       int sdram_num_banks = 2;
        static char *pci_modes[] = { "PCI33", "PCI66",
                "Unknown", "Unknown",
                "PCIX33", "PCIX66",
@@ -279,13 +287,17 @@
                   (val1 == PPC7D_CPLD_MB_TYPE_PLL_100) ? 100 :
                   (val1 == PPC7D_CPLD_MB_TYPE_PLL_64) ? 64 : 0);
 
+       val = inb(PPC7D_CPLD_MEM_CONFIG);
+       if (val & PPC7D_CPLD_SDRAM_BANK_NUM_MASK) sdram_num_banks--;
+
        val = inb(PPC7D_CPLD_MEM_CONFIG_EXTEND);
-       val1 = val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK;
-       seq_printf(m, "SDRAM\t\t: %d%c",
-                  (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_128M) ? 128 :
-                  (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_256M) ? 256 :
-                  (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_512M) ? 512 : 1,
-                  (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_1G) ? 'G' : 'M');
+       val1 = (val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK) >> 6;
+       seq_printf(m, "SDRAM\t\t: %d banks of %d%c, total %d%c",
+                  sdram_num_banks,
+                  sdram_bank_sizes[val1],
+                  (sdram_bank_sizes[val1] < 128) ? 'G' : 'M',
+                  sdram_num_banks * sdram_bank_sizes[val1],
+                  (sdram_bank_sizes[val1] < 128) ? 'G' : 'M');
        if (val2 & PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK) {
                seq_printf(m, " [ECC %sabled]",
                           (val2 & PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK) ? "en" :
@@ -1236,6 +1248,38 @@
        printk(KERN_INFO "Radstone Technology PPC7D\n");
        if (ppc_md.progress)
                ppc_md.progress("ppc7d_setup_arch: exit", 0);
+
+}
+
+/* Real Time Clock support.
+ * PPC7D has a DS1337 accessed by I2C.
+ */
+static ulong ppc7d_get_rtc_time(void)
+{
+        struct rtc_time tm;
+        int result;
+
+        spin_lock(&rtc_lock);
+        result = ds1337_do_command(0, DS1337_GET_DATE, &tm);
+        spin_unlock(&rtc_lock);
+
+        if (result == 0)
+                result = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, 
tm.tm_min, tm.tm_sec);
+
+        return result;
+}
+
+static int ppc7d_set_rtc_time(unsigned long nowtime)
+{
+        struct rtc_time tm;
+        int result;
+
+        spin_lock(&rtc_lock);
+        to_tm(nowtime, &tm);
+        result = ds1337_do_command(0, DS1337_SET_DATE, &tm);
+        spin_unlock(&rtc_lock);
+
+        return result;
 }
 
 /* This kernel command line parameter can be used to have the target
@@ -1293,6 +1337,10 @@
        data8 |= 0x07;
        outb(data8, PPC7D_CPLD_LEDS);
 
+        /* Hook up RTC. We couldn't do this earlier because we need the I2C 
subsystem */
+        ppc_md.set_rtc_time = ppc7d_set_rtc_time;
+        ppc_md.get_rtc_time = ppc7d_get_rtc_time;
+
        pr_debug("%s: exit\n", __FUNCTION__);
 }
 
diff -urN linux/arch/ppc/platforms/radstone_ppc7d.h 
linux/arch/ppc/platforms/radstone_ppc7d.h
--- linux/arch/ppc/platforms/radstone_ppc7d.h   2005/03/18 17:36:57     1.1
+++ linux/arch/ppc/platforms/radstone_ppc7d.h   2005/05/19 12:08:13     1.2
@@ -240,6 +240,7 @@
 #define PPC7D_CPLD_FLASH_CNTL                  0x086E
 
 /* MEMORY_CONFIG_EXTEND */
+#define PPC7D_CPLD_SDRAM_BANK_NUM_MASK         0x02
 #define PPC7D_CPLD_SDRAM_BANK_SIZE_MASK                0xc0
 #define PPC7D_CPLD_SDRAM_BANK_SIZE_128M                0
 #define PPC7D_CPLD_SDRAM_BANK_SIZE_256M                0x40
diff -urN linux/arch/ppc/platforms/4xx/ebony.c 
linux/arch/ppc/platforms/4xx/ebony.c
--- linux/arch/ppc/platforms/4xx/ebony.c        2005/03/18 17:36:57     1.10
+++ linux/arch/ppc/platforms/4xx/ebony.c        2005/05/19 12:08:13     1.11
@@ -149,7 +149,7 @@
 static void __init
 ebony_setup_pcix(void)
 {
-       void *pcix_reg_base;
+       void __iomem *pcix_reg_base;
 
        pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX_REG_SIZE);
 
@@ -210,9 +210,8 @@
        hose->io_space.end = EBONY_PCI_UPPER_IO;
        hose->mem_space.start = EBONY_PCI_LOWER_MEM;
        hose->mem_space.end = EBONY_PCI_UPPER_MEM;
-       isa_io_base =
-               (unsigned long)ioremap64(EBONY_PCI_IO_BASE, EBONY_PCI_IO_SIZE);
-       hose->io_base_virt = (void *)isa_io_base;
+       hose->io_base_virt = ioremap64(EBONY_PCI_IO_BASE, EBONY_PCI_IO_SIZE);
+       isa_io_base = (unsigned long)hose->io_base_virt;
 
        setup_indirect_pci(hose,
                        EBONY_PCI_CFGA_PLB32,
diff -urN linux/arch/ppc/platforms/4xx/luan.c 
linux/arch/ppc/platforms/4xx/luan.c
--- linux/arch/ppc/platforms/4xx/luan.c 2005/02/13 20:16:18     1.1
+++ linux/arch/ppc/platforms/4xx/luan.c 2005/05/19 12:08:13     1.2
@@ -223,9 +223,8 @@
        hose->io_space.end = LUAN_PCIX_UPPER_IO;
        hose->mem_space.start = lower_mem;
        hose->mem_space.end = upper_mem;
-       isa_io_base =
-               (unsigned long)ioremap64(pcix_io_base, PCIX_IO_SIZE);
-       hose->io_base_virt = (void *)isa_io_base;
+       hose->io_base_virt = ioremap64(pcix_io_base, PCIX_IO_SIZE);
+       isa_io_base = (unsigned long) hose->io_base_virt;
 
        setup_indirect_pci(hose, cfga, cfgd);
        hose->set_cfg_type = 1;
diff -urN linux/arch/ppc/platforms/4xx/ocotea.c 
linux/arch/ppc/platforms/4xx/ocotea.c
--- linux/arch/ppc/platforms/4xx/ocotea.c       2005/02/13 20:16:18     1.9
+++ linux/arch/ppc/platforms/4xx/ocotea.c       2005/05/19 12:08:13     1.10
@@ -227,9 +227,8 @@
        hose->io_space.end = OCOTEA_PCI_UPPER_IO;
        hose->mem_space.start = OCOTEA_PCI_LOWER_MEM;
        hose->mem_space.end = OCOTEA_PCI_UPPER_MEM;
-       isa_io_base =
-               (unsigned long)ioremap64(OCOTEA_PCI_IO_BASE, 
OCOTEA_PCI_IO_SIZE);
-       hose->io_base_virt = (void *)isa_io_base;
+       hose->io_base_virt = ioremap64(OCOTEA_PCI_IO_BASE, OCOTEA_PCI_IO_SIZE);
+       isa_io_base = (unsigned long) hose->io_base_virt;
 
        setup_indirect_pci(hose,
                        OCOTEA_PCI_CFGA_PLB32,
diff -urN linux/arch/ppc/syslib/cpm2_pic.c linux/arch/ppc/syslib/cpm2_pic.c
--- linux/arch/ppc/syslib/cpm2_pic.c    2005/04/08 18:58:01     1.3
+++ linux/arch/ppc/syslib/cpm2_pic.c    2005/05/19 12:08:13     1.4
@@ -107,6 +107,11 @@
                simr = &(cpm2_immr->im_intctl.ic_simrh);
                ppc_cached_irq_mask[word] |= 1 << bit;
                simr[word] = ppc_cached_irq_mask[word];
+               /*
+                * Work around large numbers of spurious IRQs on PowerPC 82xx
+                * systems.
+                */
+               mb();
        }
 }
 
diff -urN linux/arch/ppc/syslib/m8260_pci.c linux/arch/ppc/syslib/m8260_pci.c
--- linux/arch/ppc/syslib/m8260_pci.c   2004/06/28 01:09:05     1.1
+++ linux/arch/ppc/syslib/m8260_pci.c   2005/05/19 12:08:13     1.2
@@ -171,10 +171,9 @@
        m8260_setup_pci(hose);
         hose->pci_mem_offset = MPC826x_PCI_MEM_OFFSET;
 
-        isa_io_base =
-                (unsigned long) ioremap(MPC826x_PCI_IO_BASE,
+        hose->io_base_virt = ioremap(MPC826x_PCI_IO_BASE,
                                         MPC826x_PCI_IO_SIZE);
-        hose->io_base_virt = (void *) isa_io_base;
+        isa_io_base = (unsigned long) hose->io_base_virt;
  
         /* setup resources */
         pci_init_resource(&hose->mem_resources[0],
diff -urN linux/arch/ppc/syslib/mpc52xx_pci.c 
linux/arch/ppc/syslib/mpc52xx_pci.c
--- linux/arch/ppc/syslib/mpc52xx_pci.c 2005/04/08 18:58:01     1.1
+++ linux/arch/ppc/syslib/mpc52xx_pci.c 2005/05/19 12:08:13     1.2
@@ -205,13 +205,11 @@
 
        hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET;
 
-       isa_io_base =
-               (unsigned long) ioremap(MPC52xx_PCI_IO_BASE,
-                                       MPC52xx_PCI_IO_SIZE);
-       hose->io_base_virt = (void *) isa_io_base;
+       hose->io_base_virt = ioremap(MPC52xx_PCI_IO_BASE, MPC52xx_PCI_IO_SIZE);
+       isa_io_base = (unsigned long) hose->io_base_virt;
 
        hose->cfg_addr = &pci_regs->car;
-       hose->cfg_data = (void __iomem *) isa_io_base;
+       hose->cfg_data = hose->io_base_virt;
 
        /* Setup resources */
        pci_init_resource(&hose->mem_resources[0],
diff -urN linux/arch/ppc/syslib/ppc85xx_setup.c 
linux/arch/ppc/syslib/ppc85xx_setup.c
--- linux/arch/ppc/syslib/ppc85xx_setup.c       2005/02/13 20:16:18     1.7
+++ linux/arch/ppc/syslib/ppc85xx_setup.c       2005/05/19 12:08:13     1.8
@@ -280,16 +280,14 @@
        hose_a->io_space.end = MPC85XX_PCI1_UPPER_IO;
        hose_a->io_base_phys = MPC85XX_PCI1_IO_BASE;
 #ifdef CONFIG_85xx_PCI2
-       isa_io_base =
-               (unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
+       hose_a->io_base_virt =  ioremap(MPC85XX_PCI1_IO_BASE,
                                        MPC85XX_PCI1_IO_SIZE +
                                        MPC85XX_PCI2_IO_SIZE);
 #else
-       isa_io_base =
-               (unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
+       hose_a->io_base_virt =  ioremap(MPC85XX_PCI1_IO_BASE,
                                        MPC85XX_PCI1_IO_SIZE);
 #endif
-       hose_a->io_base_virt = (void *) isa_io_base;
+       isa_io_base = (unsigned long)hose_a->io_base_virt;
 
        /* setup resources */
        pci_init_resource(&hose_a->mem_resources[0],
@@ -329,8 +327,8 @@
        hose_b->io_space.start = MPC85XX_PCI2_LOWER_IO;
        hose_b->io_space.end = MPC85XX_PCI2_UPPER_IO;
        hose_b->io_base_phys = MPC85XX_PCI2_IO_BASE;
-       hose_b->io_base_virt = (void *) isa_io_base + MPC85XX_PCI1_IO_SIZE;
-
+       hose_b->io_base_virt = hose_a->io_base_virt + MPC85XX_PCI1_IO_SIZE;
+       
        /* setup resources */
        pci_init_resource(&hose_b->mem_resources[0],
                        MPC85XX_PCI2_LOWER_MEM,
diff -urN linux/arch/ppc64/Kconfig linux/arch/ppc64/Kconfig
--- linux/arch/ppc64/Kconfig    2005/04/29 11:15:03     1.38
+++ linux/arch/ppc64/Kconfig    2005/05/19 12:08:14     1.39
@@ -40,6 +40,10 @@
        bool
        default y
 
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+       bool
+       default y
+
 # We optimistically allocate largepages from the VM, so make the limit
 # large enough (16MB). This badly named config option is actually
 # max order + 1
@@ -258,6 +262,7 @@
 config RTAS_PROC
        bool "Proc interface to RTAS"
        depends on PPC_RTAS
+       default y
 
 config RTAS_FLASH
        tristate "Firmware flash interface"
@@ -293,6 +298,9 @@
 
 endmenu
 
+config ISA_DMA_API
+       bool
+       default y
 
 menu "General setup"
 
diff -urN linux/arch/ppc64/Kconfig.debug linux/arch/ppc64/Kconfig.debug
--- linux/arch/ppc64/Kconfig.debug      2005/02/07 02:54:36     1.6
+++ linux/arch/ppc64/Kconfig.debug      2005/05/19 12:08:14     1.7
@@ -5,6 +5,9 @@
 config DEBUG_STACKOVERFLOW
        bool "Check for stack overflows"
        depends on DEBUG_KERNEL
+       help
+         This option will cause messages to be printed if free stack space
+         drops below a certain limit.
 
 config KPROBES
        bool "Kprobes"
diff -urN linux/arch/ppc64/Makefile linux/arch/ppc64/Makefile
--- linux/arch/ppc64/Makefile   2005/03/18 17:36:58     1.33
+++ linux/arch/ppc64/Makefile   2005/05/19 12:08:14     1.34
@@ -56,13 +56,20 @@
 CFLAGS         += -msoft-float -pipe -mminimal-toc -mtraceback=none \
                   -mcall-aixdesc
 
+GCC_VERSION     := $(call cc-version)
+GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi ;)
+
 ifeq ($(CONFIG_POWER4_ONLY),y)
 ifeq ($(CONFIG_ALTIVEC),y)
+ifeq ($(GCC_BROKEN_VEC),y)
        CFLAGS += $(call cc-option,-mcpu=970)
 else
        CFLAGS += $(call cc-option,-mcpu=power4)
 endif
 else
+       CFLAGS += $(call cc-option,-mcpu=power4)
+endif
+else
        CFLAGS += $(call cc-option,-mtune=power4)
 endif
 
diff -urN linux/arch/ppc64/boot/addnote.c linux/arch/ppc64/boot/addnote.c
--- linux/arch/ppc64/boot/addnote.c     2003/06/05 18:24:00     1.3
+++ linux/arch/ppc64/boot/addnote.c     2005/05/19 12:08:14     1.4
@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <string.h>
 
+/* CHRP note section */
 char arch[] = "PowerPC";
 
 #define N_DESCR        6
@@ -31,6 +32,29 @@
        0x4000,                 /* load-base */
 };
 
+/* RPA note section */
+char rpaname[] = "IBM,RPA-Client-Config";
+
+/*
+ * Note: setting ignore_my_client_config *should* mean that OF ignores
+ * all the other fields, but there is a firmware bug which means that
+ * it looks at the splpar field at least.  So these values need to be
+ * reasonable.
+ */
+#define N_RPA_DESCR    8
+unsigned int rpanote[N_RPA_DESCR] = {
+       0,                      /* lparaffinity */
+       64,                     /* min_rmo_size */
+       0,                      /* min_rmo_percent */
+       40,                     /* max_pft_size */
+       1,                      /* splpar */
+       -1,                     /* min_load */
+       0,                      /* new_mem_def */
+       1,                      /* ignore_my_client_config */
+};
+
+#define ROUNDUP(len)   (((len) + 3) & ~3)
+
 unsigned char buf[512];
 
 #define GET_16BE(off)  ((buf[off] << 8) + (buf[(off)+1]))
@@ -69,7 +93,7 @@
 {
        int fd, n, i;
        int ph, ps, np;
-       int nnote, ns;
+       int nnote, nnote2, ns;
 
        if (ac != 2) {
                fprintf(stderr, "Usage: %s elf-file\n", av[0]);
@@ -81,7 +105,8 @@
                exit(1);
        }
 
-       nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
+       nnote = 12 + ROUNDUP(strlen(arch) + 1) + sizeof(descr);
+       nnote2 = 12 + ROUNDUP(strlen(rpaname) + 1) + sizeof(rpanote);
 
        n = read(fd, buf, sizeof(buf));
        if (n < 0) {
@@ -104,7 +129,7 @@
        np = GET_16BE(E_PHNUM);
        if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
                goto notelf;
-       if (ph + (np + 1) * ps + nnote > n)
+       if (ph + (np + 2) * ps + nnote + nnote2 > n)
                goto nospace;
 
        for (i = 0; i < np; ++i) {
@@ -117,12 +142,12 @@
        }
 
        /* XXX check that the area we want to use is all zeroes */
-       for (i = 0; i < ps + nnote; ++i)
+       for (i = 0; i < 2 * ps + nnote + nnote2; ++i)
                if (buf[ph + i] != 0)
                        goto nospace;
 
        /* fill in the program header entry */
-       ns = ph + ps;
+       ns = ph + 2 * ps;
        PUT_32BE(ph + PH_TYPE, PT_NOTE);
        PUT_32BE(ph + PH_OFFSET, ns);
        PUT_32BE(ph + PH_FILESZ, nnote);
@@ -134,11 +159,26 @@
        PUT_32BE(ns + 8, 0x1275);
        strcpy(&buf[ns + 12], arch);
        ns += 12 + strlen(arch) + 1;
-       for (i = 0; i < N_DESCR; ++i)
-               PUT_32BE(ns + i * 4, descr[i]);
+       for (i = 0; i < N_DESCR; ++i, ns += 4)
+               PUT_32BE(ns, descr[i]);
+
+       /* fill in the second program header entry and the RPA note area */
+       ph += ps;
+       PUT_32BE(ph + PH_TYPE, PT_NOTE);
+       PUT_32BE(ph + PH_OFFSET, ns);
+       PUT_32BE(ph + PH_FILESZ, nnote2);
+
+       /* fill in the note area we point to */
+       PUT_32BE(ns, strlen(rpaname) + 1);
+       PUT_32BE(ns + 4, sizeof(rpanote));
+       PUT_32BE(ns + 8, 0x12759999);
+       strcpy(&buf[ns + 12], rpaname);
+       ns += 12 + ROUNDUP(strlen(rpaname) + 1);
+       for (i = 0; i < N_RPA_DESCR; ++i, ns += 4)
+               PUT_32BE(ns, rpanote[i]);
 
        /* Update the number of program headers */
-       PUT_16BE(E_PHNUM, np + 1);
+       PUT_16BE(E_PHNUM, np + 2);
 
        /* write back */
        lseek(fd, (long) 0, SEEK_SET);
@@ -155,11 +195,11 @@
        exit(0);
 
  notelf:
-       fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
+       fprintf(stderr, "%s does not appear to be an ELF file\n", av[1]);
        exit(1);
 
  nospace:
        fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
-               av[0]);
+               av[1]);
        exit(1);
 }
diff -urN linux/arch/ppc64/boot/main.c linux/arch/ppc64/boot/main.c
--- linux/arch/ppc64/boot/main.c        2005/04/08 18:58:02     1.12
+++ linux/arch/ppc64/boot/main.c        2005/05/19 12:08:14     1.13
@@ -14,7 +14,6 @@
 #include <linux/string.h>
 #include <asm/processor.h>
 #include <asm/page.h>
-#include <asm/bootinfo.h>
 
 extern void *finddevice(const char *);
 extern int getprop(void *, const char *, void *, int);
diff -urN linux/arch/ppc64/boot/start.c linux/arch/ppc64/boot/start.c
--- linux/arch/ppc64/boot/Attic/start.c 2005-05-19 13:08:14.269084000 +0100     
1.1
+++ linux/arch/ppc64/boot/Attic/start.c 1970/01/01 00:00:00+0100
@@ -1,654 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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 <stdarg.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-
-#include <asm/div64.h>
-
-int (*prom)(void *);
-
-void *chosen_handle;
-void *stdin;
-void *stdout;
-void *stderr;
-
-void exit(void);
-void *finddevice(const char *name);
-int getprop(void *phandle, const char *name, void *buf, int buflen);
-void chrpboot(int a1, int a2, void *prom);     /* in main.c */
-
-void printk(char *fmt, ...);
-
-void
-start(int a1, int a2, void *promptr)
-{
-       prom = (int (*)(void *)) promptr;
-       chosen_handle = finddevice("/chosen");
-       if (chosen_handle == (void *) -1)
-               exit();
-       if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
-               exit();
-       stderr = stdout;
-       if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
-       exit();
-
-       chrpboot(a1, a2, promptr);
-       for (;;)
-               exit();
-}
-
-int
-write(void *handle, void *ptr, int nb)
-{
-       struct prom_args {
-               char *service;
-               int nargs;
-               int nret;
-               void *ihandle;
-               void *addr;
-               int len;
-               int actual;
-       } args;
-
-       args.service = "write";
-       args.nargs = 3;
-       args.nret = 1;
-       args.ihandle = handle;
-       args.addr = ptr;
-       args.len = nb;
-       args.actual = -1;
-       (*prom)(&args);
-       return args.actual;
-}
-
-int
-read(void *handle, void *ptr, int nb)
-{
-       struct prom_args {
-               char *service;
-               int nargs;
-               int nret;
-               void *ihandle;
-               void *addr;
-               int len;
-               int actual;
-       } args;
-
-       args.service = "read";
-       args.nargs = 3;
-       args.nret = 1;
-       args.ihandle = handle;
-       args.addr = ptr;
-       args.len = nb;
-       args.actual = -1;
-       (*prom)(&args);
-       return args.actual;
-}
-
-void
-exit()
-{
-       struct prom_args {
-               char *service;
-       } args;
-
-       for (;;) {
-               args.service = "exit";
-               (*prom)(&args);
-       }
-}
-
-void
-pause(void)
-{
-       struct prom_args {
-               char *service;
-       } args;
-
-       args.service = "enter";
-       (*prom)(&args);
-}
-
-void *
-finddevice(const char *name)
-{
-       struct prom_args {
-               char *service;
-               int nargs;
-               int nret;
-               const char *devspec;
-               void *phandle;
-       } args;
-
-       args.service = "finddevice";
-       args.nargs = 1;
-       args.nret = 1;
-       args.devspec = name;
-       args.phandle = (void *) -1;
-       (*prom)(&args);
-       return args.phandle;
-}
-
-void *
-claim(unsigned long virt, unsigned long size, unsigned long align)
-{
-       struct prom_args {
-               char *service;
-               int nargs;
-               int nret;
-               unsigned int virt;
-               unsigned int size;
-               unsigned int align;
-               void *ret;
-       } args;
-
-       args.service = "claim";
-       args.nargs = 3;
-       args.nret = 1;
-       args.virt = virt;
-       args.size = size;
-       args.align = align;
-       (*prom)(&args);
-       return args.ret;
-}
-
-int
-getprop(void *phandle, const char *name, void *buf, int buflen)
-{
-       struct prom_args {
-               char *service;
-               int nargs;
-               int nret;
-               void *phandle;
-               const char *name;
-               void *buf;
-               int buflen;
-               int size;
-       } args;
-
-       args.service = "getprop";
-       args.nargs = 4;
-       args.nret = 1;
-       args.phandle = phandle;
-       args.name = name;
-       args.buf = buf;
-       args.buflen = buflen;
-       args.size = -1;
-       (*prom)(&args);
-       return args.size;
-}
-
-int
-putc(int c, void *f)
-{
-       char ch = c;
-
-       if (c == '\n')
-               putc('\r', f);
-       return write(f, &ch, 1) == 1? c: -1;
-}
-
-int
-putchar(int c)
-{
-       return putc(c, stdout);
-}
-
-int
-fputs(char *str, void *f)
-{
-       int n = strlen(str);
-
-       return write(f, str, n) == n? 0: -1;
-}
-
-int
-readchar(void)
-{
-       char ch;
-
-       for (;;) {
-               switch (read(stdin, &ch, 1)) {
-               case 1:
-                       return ch;
-               case -1:
-                       printk("read(stdin) returned -1\r\n");
-                       return -1;
-               }
-       }
-}
-
-static char line[256];
-static char *lineptr;
-static int lineleft;
-
-int
-getchar(void)
-{
-       int c;
-
-       if (lineleft == 0) {
-               lineptr = line;
-               for (;;) {
-                       c = readchar();
-                       if (c == -1 || c == 4)
-                               break;
-                       if (c == '\r' || c == '\n') {
-                               *lineptr++ = '\n';
-                               putchar('\n');
-                               break;
-                       }
-                       switch (c) {
-                       case 0177:
-                       case '\b':
-                               if (lineptr > line) {
-                                       putchar('\b');
-                                       putchar(' ');
-                                       putchar('\b');
-                                       --lineptr;
-                               }
-                               break;
-                       case 'U' & 0x1F:
-                               while (lineptr > line) {
-                                       putchar('\b');
-                                       putchar(' ');
-                                       putchar('\b');
-                                       --lineptr;
-                               }
-                               break;
-                       default:
-                               if (lineptr >= &line[sizeof(line) - 1])
-                                       putchar('\a');
-                               else {
-                                       putchar(c);
-                                       *lineptr++ = c;
-                               }
-                       }
-               }
-               lineleft = lineptr - line;
-               lineptr = line;
-       }
-       if (lineleft == 0)
-               return -1;
-       --lineleft;
-       return *lineptr++;
-}
-
-
-
-/* String functions lifted from lib/vsprintf.c and lib/ctype.c */
-unsigned char _ctype[] = {
-_C,_C,_C,_C,_C,_C,_C,_C,                       /* 0-7 */
-_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,                /* 8-15 */
-_C,_C,_C,_C,_C,_C,_C,_C,                       /* 16-23 */
-_C,_C,_C,_C,_C,_C,_C,_C,                       /* 24-31 */
-_S|_SP,_P,_P,_P,_P,_P,_P,_P,                   /* 32-39 */
-_P,_P,_P,_P,_P,_P,_P,_P,                       /* 40-47 */
-_D,_D,_D,_D,_D,_D,_D,_D,                       /* 48-55 */
-_D,_D,_P,_P,_P,_P,_P,_P,                       /* 56-63 */
-_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,     /* 64-71 */
-_U,_U,_U,_U,_U,_U,_U,_U,                       /* 72-79 */
-_U,_U,_U,_U,_U,_U,_U,_U,                       /* 80-87 */
-_U,_U,_U,_P,_P,_P,_P,_P,                       /* 88-95 */
-_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,     /* 96-103 */
-_L,_L,_L,_L,_L,_L,_L,_L,                       /* 104-111 */
-_L,_L,_L,_L,_L,_L,_L,_L,                       /* 112-119 */
-_L,_L,_L,_P,_P,_P,_P,_C,                       /* 120-127 */
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,               /* 128-143 */
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,               /* 144-159 */
-_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
-_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
-_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
-_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
-_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
-_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
-
-size_t strnlen(const char * s, size_t count)
-{
-       const char *sc;
-
-       for (sc = s; count-- && *sc != '\0'; ++sc)
-               /* nothing */;
-       return sc - s;
-}
-
-unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
-{
-       unsigned long result = 0,value;
-
-       if (!base) {
-               base = 10;
-               if (*cp == '0') {
-                       base = 8;
-                       cp++;
-                       if ((*cp == 'x') && isxdigit(cp[1])) {
-                               cp++;
-                               base = 16;
-                       }
-               }
-       }
-       while (isxdigit(*cp) &&
-              (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
-               result = result*base + value;
-               cp++;
-       }
-       if (endp)
-               *endp = (char *)cp;
-       return result;
-}
-
-long simple_strtol(const char *cp,char **endp,unsigned int base)
-{
-       if(*cp=='-')
-               return -simple_strtoul(cp+1,endp,base);
-       return simple_strtoul(cp,endp,base);
-}
-
-static int skip_atoi(const char **s)
-{
-       int i=0;
-
-       while (isdigit(**s))
-               i = i*10 + *((*s)++) - '0';
-       return i;
-}
-
-#define ZEROPAD        1               /* pad with zero */
-#define SIGN   2               /* unsigned/signed long */
-#define PLUS   4               /* show plus */
-#define SPACE  8               /* space if plus */
-#define LEFT   16              /* left justified */
-#define SPECIAL        32              /* 0x */
-#define LARGE  64              /* use 'ABCDEF' instead of 'abcdef' */
-
-static char * number(char * str, long long num, int base, int size, int 
precision, int type)
-{
-       char c,sign,tmp[66];
-       const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
-       int i;
-
-       if (type & LARGE)
-               digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-       if (type & LEFT)
-               type &= ~ZEROPAD;
-       if (base < 2 || base > 36)
-               return 0;
-       c = (type & ZEROPAD) ? '0' : ' ';
-       sign = 0;
-       if (type & SIGN) {
-               if (num < 0) {
-                       sign = '-';
-                       num = -num;
-                       size--;
-               } else if (type & PLUS) {
-                       sign = '+';
-                       size--;
-               } else if (type & SPACE) {
-                       sign = ' ';
-                       size--;
-               }
-       }
-       if (type & SPECIAL) {
-               if (base == 16)
-                       size -= 2;
-               else if (base == 8)
-                       size--;
-       }
-       i = 0;
-       if (num == 0)
-               tmp[i++]='0';
-       else while (num != 0)
-               tmp[i++] = digits[do_div(num,base)];
-       if (i > precision)
-               precision = i;
-       size -= precision;
-       if (!(type&(ZEROPAD+LEFT)))
-               while(size-->0)
-                       *str++ = ' ';
-       if (sign)
-               *str++ = sign;
-       if (type & SPECIAL) {
-               if (base==8)
-                       *str++ = '0';
-               else if (base==16) {
-                       *str++ = '0';
-                       *str++ = digits[33];
-               }
-       }
-       if (!(type & LEFT))
-               while (size-- > 0)
-                       *str++ = c;
-       while (i < precision--)
-               *str++ = '0';
-       while (i-- > 0)
-               *str++ = tmp[i];
-       while (size-- > 0)
-               *str++ = ' ';
-       return str;
-}
-
-/* Forward decl. needed for IP address printing stuff... */
-int sprintf(char * buf, const char *fmt, ...);
-
-int vsprintf(char *buf, const char *fmt, va_list args)
-{
-       int len;
-       unsigned long long num;
-       int i, base;
-       char * str;
-       const char *s;
-
-       int flags;              /* flags to number() */
-
-       int field_width;        /* width of output field */
-       int precision;          /* min. # of digits for integers; max
-                                  number of chars for from string */
-       int qualifier;          /* 'h', 'l', or 'L' for integer fields */
-                               /* 'z' support added 23/7/1999 S.H.    */
-                               /* 'z' changed to 'Z' --davidm 1/25/99 */
-
-       
-       for (str=buf ; *fmt ; ++fmt) {
-               if (*fmt != '%') {
-                       *str++ = *fmt;
-                       continue;
-               }
-                       
-               /* process flags */
-               flags = 0;
-               repeat:
-                       ++fmt;          /* this also skips first '%' */
-                       switch (*fmt) {
-                               case '-': flags |= LEFT; goto repeat;
-                               case '+': flags |= PLUS; goto repeat;
-                               case ' ': flags |= SPACE; goto repeat;
-                               case '#': flags |= SPECIAL; goto repeat;
-                               case '0': flags |= ZEROPAD; goto repeat;
-                               }
-               
-               /* get field width */
-               field_width = -1;
-               if (isdigit(*fmt))
-                       field_width = skip_atoi(&fmt);
-               else if (*fmt == '*') {
-                       ++fmt;
-                       /* it's the next argument */
-                       field_width = va_arg(args, int);
-                       if (field_width < 0) {
-                               field_width = -field_width;
-                               flags |= LEFT;
-                       }
-               }
-
-               /* get the precision */
-               precision = -1;
-               if (*fmt == '.') {
-                       ++fmt;  
-                       if (isdigit(*fmt))
-                               precision = skip_atoi(&fmt);
-                       else if (*fmt == '*') {
-                               ++fmt;
-                               /* it's the next argument */
-                               precision = va_arg(args, int);
-                       }
-                       if (precision < 0)
-                               precision = 0;
-               }
-
-               /* get the conversion qualifier */
-               qualifier = -1;
-               if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
-                       qualifier = *fmt;
-                       ++fmt;
-               }
-
-               /* default base */
-               base = 10;
-
-               switch (*fmt) {
-               case 'c':
-                       if (!(flags & LEFT))
-                               while (--field_width > 0)
-                                       *str++ = ' ';
-                       *str++ = (unsigned char) va_arg(args, int);
-                       while (--field_width > 0)
-                               *str++ = ' ';
-                       continue;
-
-               case 's':
-                       s = va_arg(args, char *);
-                       if (!s)
-                               s = "<NULL>";
-
-                       len = strnlen(s, precision);
-
-                       if (!(flags & LEFT))
-                               while (len < field_width--)
-                                       *str++ = ' ';
-                       for (i = 0; i < len; ++i)
-                               *str++ = *s++;
-                       while (len < field_width--)
-                               *str++ = ' ';
-                       continue;
-
-               case 'p':
-                       if (field_width == -1) {
-                               field_width = 2*sizeof(void *);
-                               flags |= ZEROPAD;
-                       }
-                       str = number(str,
-                               (unsigned long) va_arg(args, void *), 16,
-                               field_width, precision, flags);
-                       continue;
-
-
-               case 'n':
-                       if (qualifier == 'l') {
-                               long * ip = va_arg(args, long *);
-                               *ip = (str - buf);
-                       } else if (qualifier == 'Z') {
-                               size_t * ip = va_arg(args, size_t *);
-                               *ip = (str - buf);
-                       } else {
-                               int * ip = va_arg(args, int *);
-                               *ip = (str - buf);
-                       }
-                       continue;
-
-               case '%':
-                       *str++ = '%';
-                       continue;
-
-               /* integer number formats - set up the flags and "break" */
-               case 'o':
-                       base = 8;
-                       break;
-
-               case 'X':
-                       flags |= LARGE;
-               case 'x':
-                       base = 16;
-                       break;
-
-               case 'd':
-               case 'i':
-                       flags |= SIGN;
-               case 'u':
-                       break;
-
-               default:
-                       *str++ = '%';
-                       if (*fmt)
-                               *str++ = *fmt;
-                       else
-                               --fmt;
-                       continue;
-               }
-               if (qualifier == 'L')
-                       num = va_arg(args, long long);
-               else if (qualifier == 'l') {
-                       num = va_arg(args, unsigned long);
-                       if (flags & SIGN)
-                               num = (signed long) num;
-               } else if (qualifier == 'Z') {
-                       num = va_arg(args, size_t);
-               } else if (qualifier == 'h') {
-                       num = (unsigned short) va_arg(args, int);
-                       if (flags & SIGN)
-                               num = (signed short) num;
-               } else {
-                       num = va_arg(args, unsigned int);
-                       if (flags & SIGN)
-                               num = (signed int) num;
-               }
-               str = number(str, num, base, field_width, precision, flags);
-       }
-       *str = '\0';
-       return str-buf;
-}
-
-int sprintf(char * buf, const char *fmt, ...)
-{
-       va_list args;
-       int i;
-
-       va_start(args, fmt);
-       i=vsprintf(buf,fmt,args);
-       va_end(args);
-       return i;
-}
-
-static char sprint_buf[1024];
-
-void
-printk(char *fmt, ...)
-{
-       va_list args;
-       int n;
-
-       va_start(args, fmt);
-       n = vsprintf(sprint_buf, fmt, args);
-       va_end(args);
-       write(stdout, sprint_buf, n);
-}
-
-int
-printf(char *fmt, ...)
-{
-       va_list args;
-       int n;
-
-       va_start(args, fmt);
-       n = vsprintf(sprint_buf, fmt, args);
-       va_end(args);
-       write(stdout, sprint_buf, n);
-       return n;
-}
diff -urN linux/arch/ppc64/kernel/HvLpEvent.c 
linux/arch/ppc64/kernel/HvLpEvent.c
--- linux/arch/ppc64/kernel/HvLpEvent.c 2005/01/25 04:28:03     1.4
+++ linux/arch/ppc64/kernel/HvLpEvent.c 2005/05/19 12:08:14     1.5
@@ -45,7 +45,7 @@
                        /* We now sleep until all other CPUs have scheduled. 
This ensures that
                         * the deletion is seen by all other CPUs, and that the 
deleted handler
                         * isn't still running on another CPU when we return. */
-                       synchronize_kernel();
+                       synchronize_rcu();
                }
        }
        return rc;
diff -urN linux/arch/ppc64/kernel/misc.S linux/arch/ppc64/kernel/misc.S
--- linux/arch/ppc64/kernel/misc.S      2005/04/08 18:58:02     1.42
+++ linux/arch/ppc64/kernel/misc.S      2005/05/19 12:08:14     1.43
@@ -32,7 +32,7 @@
        .text
 
 /*
- * Returns (address we're running at) - (address we were linked at)
+ * Returns (address we were linked at) - (address we are running at)
  * for use before the text and data are mapped to KERNELBASE.
  */
 
diff -urN linux/arch/ppc64/kernel/nvram.c linux/arch/ppc64/kernel/nvram.c
--- linux/arch/ppc64/kernel/nvram.c     2005/04/08 18:58:02     1.13
+++ linux/arch/ppc64/kernel/nvram.c     2005/05/19 12:08:14     1.14
@@ -339,9 +339,9 @@
 static int nvram_create_os_partition(void)
 {
        struct list_head * p;
-       struct nvram_partition * part;
-       struct nvram_partition * new_part = NULL;
-       struct nvram_partition * free_part = NULL;
+       struct nvram_partition *part = NULL;
+       struct nvram_partition *new_part = NULL;
+       struct nvram_partition *free_part = NULL;
        int seq_init[2] = { 0, 0 };
        loff_t tmp_index;
        long size = 0;
@@ -364,13 +364,11 @@
                        free_part = part;
                }
        }
-       if (!size) {
+       if (!size)
                return -ENOSPC;
-       }
        
        /* Create our OS partition */
-       new_part = (struct nvram_partition *)
-               kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
+       new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
        if (!new_part) {
                printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n");
                return -ENOMEM;
@@ -379,7 +377,7 @@
        new_part->index = free_part->index;
        new_part->header.signature = NVRAM_SIG_OS;
        new_part->header.length = size;
-       sprintf(new_part->header.name, "ppc64,linux");
+       strcpy(new_part->header.name, "ppc64,linux");
        new_part->header.checksum = nvram_checksum(&new_part->header);
 
        rc = nvram_write_header(new_part);
@@ -394,7 +392,8 @@
        tmp_index = new_part->index + NVRAM_HEADER_LEN;
        rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), 
&tmp_index);
        if (rc <= 0) {
-               printk(KERN_ERR "nvram_create_os_partition: nvram_write failed 
(%d)\n", rc);
+               printk(KERN_ERR "nvram_create_os_partition: nvram_write "
+                               "failed (%d)\n", rc);
                return rc;
        }
        
diff -urN linux/arch/ppc64/kernel/pSeries_hvCall.S 
linux/arch/ppc64/kernel/pSeries_hvCall.S
--- linux/arch/ppc64/kernel/pSeries_hvCall.S    2005/04/08 18:58:02     1.6
+++ linux/arch/ppc64/kernel/pSeries_hvCall.S    2005/05/19 12:08:14     1.7
@@ -28,6 +28,8 @@
                        unsigned long *out3);           R10
  */
 _GLOBAL(plpar_hcall)
+       HMT_MEDIUM
+
        mfcr    r0
 
        std     r8,STK_PARM(r8)(r1)     /* Save out ptrs */
@@ -53,6 +55,8 @@
 
 /* Simple interface with no output values (other than status) */
 _GLOBAL(plpar_hcall_norets)
+       HMT_MEDIUM
+
        mfcr    r0
        stw     r0,8(r1)
 
@@ -75,6 +79,8 @@
                        unsigned long *out1);           120(R1)
  */
 _GLOBAL(plpar_hcall_8arg_2ret)
+       HMT_MEDIUM
+
        mfcr    r0
        ld      r11,STK_PARM(r11)(r1)   /* put arg8 in R11 */
        stw     r0,8(r1)
@@ -99,6 +105,8 @@
                        unsigned long *out4);           112(R1)
  */
 _GLOBAL(plpar_hcall_4out)
+       HMT_MEDIUM
+
        mfcr    r0
        stw     r0,8(r1)
 
diff -urN linux/arch/ppc64/kernel/pSeries_smp.c 
linux/arch/ppc64/kernel/pSeries_smp.c
--- linux/arch/ppc64/kernel/pSeries_smp.c       2005/04/08 18:58:02     1.7
+++ linux/arch/ppc64/kernel/pSeries_smp.c       2005/05/19 12:08:14     1.8
@@ -326,13 +326,6 @@
 
        cpu_clear(cpu, of_spin_map);
 
-       /*
-        * Put the calling processor into the GIQ.  This is really only
-        * necessary from a secondary thread as the OF start-cpu interface
-        * performs this function for us on primary threads.
-        */
-       rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
-               (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
 }
 
 static DEFINE_SPINLOCK(timebase_lock);
diff -urN linux/arch/ppc64/kernel/pci.c linux/arch/ppc64/kernel/pci.c
--- linux/arch/ppc64/kernel/pci.c       2005/04/29 11:15:04     1.32
+++ linux/arch/ppc64/kernel/pci.c       2005/05/19 12:08:14     1.33
@@ -438,7 +438,7 @@
        int i;
 
        if (page_is_ram(offset >> PAGE_SHIFT))
-               return prot;
+               return __pgprot(prot);
 
        prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
 
diff -urN linux/arch/ppc64/kernel/prom.c linux/arch/ppc64/kernel/prom.c
--- linux/arch/ppc64/kernel/prom.c      2005/04/29 11:15:04     1.43
+++ linux/arch/ppc64/kernel/prom.c      2005/05/19 12:08:14     1.44
@@ -321,6 +321,10 @@
                        char *name = get_property(ic->parent, "name", NULL);
                        if (name && !strcmp(name, "u3"))
                                np->intrs[intrcount].line += 128;
+                       else if (!(name && !strcmp(name, "mac-io")))
+                               /* ignore other cascaded controllers, such as
+                                  the k2-sata-root */
+                               break;
                }
                np->intrs[intrcount].sense = 1;
                if (n > 1)
@@ -830,7 +834,7 @@
 {
        unsigned long start, mem, size;
        struct device_node **allnextp = &allnodes;
-       char *p;
+       char *p = NULL;
        int l = 0;
 
        DBG(" -> unflatten_device_tree()\n");
diff -urN linux/arch/ppc64/kernel/prom_init.c 
linux/arch/ppc64/kernel/prom_init.c
--- linux/arch/ppc64/kernel/prom_init.c 2005/04/08 18:58:02     1.10
+++ linux/arch/ppc64/kernel/prom_init.c 2005/05/19 12:08:14     1.11
@@ -493,6 +493,113 @@
 }
 
 /*
+ * To tell the firmware what our capabilities are, we have to pass
+ * it a fake 32-bit ELF header containing a couple of PT_NOTE sections
+ * that contain structures that contain the actual values.
+ */
+static struct fake_elf {
+       Elf32_Ehdr      elfhdr;
+       Elf32_Phdr      phdr[2];
+       struct chrpnote {
+               u32     namesz;
+               u32     descsz;
+               u32     type;
+               char    name[8];        /* "PowerPC" */
+               struct chrpdesc {
+                       u32     real_mode;
+                       u32     real_base;
+                       u32     real_size;
+                       u32     virt_base;
+                       u32     virt_size;
+                       u32     load_base;
+               } chrpdesc;
+       } chrpnote;
+       struct rpanote {
+               u32     namesz;
+               u32     descsz;
+               u32     type;
+               char    name[24];       /* "IBM,RPA-Client-Config" */
+               struct rpadesc {
+                       u32     lpar_affinity;
+                       u32     min_rmo_size;
+                       u32     min_rmo_percent;
+                       u32     max_pft_size;
+                       u32     splpar;
+                       u32     min_load;
+                       u32     new_mem_def;
+                       u32     ignore_me;
+               } rpadesc;
+       } rpanote;
+} fake_elf = {
+       .elfhdr = {
+               .e_ident = { 0x7f, 'E', 'L', 'F',
+                            ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
+               .e_type = ET_EXEC,      /* yeah right */
+               .e_machine = EM_PPC,
+               .e_version = EV_CURRENT,
+               .e_phoff = offsetof(struct fake_elf, phdr),
+               .e_phentsize = sizeof(Elf32_Phdr),
+               .e_phnum = 2
+       },
+       .phdr = {
+               [0] = {
+                       .p_type = PT_NOTE,
+                       .p_offset = offsetof(struct fake_elf, chrpnote),
+                       .p_filesz = sizeof(struct chrpnote)
+               }, [1] = {
+                       .p_type = PT_NOTE,
+                       .p_offset = offsetof(struct fake_elf, rpanote),
+                       .p_filesz = sizeof(struct rpanote)
+               }
+       },
+       .chrpnote = {
+               .namesz = sizeof("PowerPC"),
+               .descsz = sizeof(struct chrpdesc),
+               .type = 0x1275,
+               .name = "PowerPC",
+               .chrpdesc = {
+                       .real_mode = ~0U,       /* ~0 means "don't care" */
+                       .real_base = ~0U,
+                       .real_size = ~0U,
+                       .virt_base = ~0U,
+                       .virt_size = ~0U,
+                       .load_base = ~0U
+               },
+       },
+       .rpanote = {
+               .namesz = sizeof("IBM,RPA-Client-Config"),
+               .descsz = sizeof(struct rpadesc),
+               .type = 0x12759999,
+               .name = "IBM,RPA-Client-Config",
+               .rpadesc = {
+                       .lpar_affinity = 0,
+                       .min_rmo_size = 64,     /* in megabytes */
+                       .min_rmo_percent = 0,
+                       .max_pft_size = 48,     /* 2^48 bytes max PFT size */
+                       .splpar = 1,
+                       .min_load = ~0U,
+                       .new_mem_def = 0
+               }
+       }
+};
+
+static void __init prom_send_capabilities(void)
+{
+       unsigned long offset = reloc_offset();
+       ihandle elfloader;
+       int ret;
+
+       elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
+       if (elfloader == 0) {
+               prom_printf("couldn't open /packages/elf-loader\n");
+               return;
+       }
+       ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"),
+                       elfloader, ADDR(&fake_elf));
+       call_prom("close", 1, 0, elfloader);
+}
+
+/*
  * Memory allocation strategy... our layout is normally:
  *
  *  at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, 
initrd
@@ -1448,6 +1555,12 @@
        }
 }
 
+/*
+ * The Open Firmware 1275 specification states properties must be 31 bytes or
+ * less, however not all firmwares obey this. Make it 64 bytes to be safe.
+ */
+#define MAX_PROPERTY_NAME 64
+
 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                                        unsigned long *mem_end)
 {
@@ -1457,7 +1570,7 @@
        unsigned long soff;
        unsigned char *valp;
        unsigned long offset = reloc_offset();
-       char pname[32];
+       char pname[MAX_PROPERTY_NAME];
        char *path;
 
        path = RELOC(prom_scratch);
diff -urN linux/arch/ppc64/kernel/ptrace.c linux/arch/ppc64/kernel/ptrace.c
--- linux/arch/ppc64/kernel/ptrace.c    2005/04/08 18:58:02     1.16
+++ linux/arch/ppc64/kernel/ptrace.c    2005/05/19 12:08:14     1.17
@@ -28,6 +28,7 @@
 #include <linux/security.h>
 #include <linux/audit.h>
 #include <linux/seccomp.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -162,7 +163,7 @@
        case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall 
*/
        case PTRACE_CONT: { /* restart after signal. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                if (request == PTRACE_SYSCALL)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -194,7 +195,7 @@
 
        case PTRACE_SINGLESTEP: {  /* set the trap flag. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                set_single_step(child);
@@ -304,14 +305,17 @@
 
 void do_syscall_trace_enter(struct pt_regs *regs)
 {
+       if (test_thread_flag(TIF_SYSCALL_TRACE)
+           && (current->ptrace & PT_PTRACED))
+               do_syscall_trace();
+
        if (unlikely(current->audit_context))
-               audit_syscall_entry(current, regs->gpr[0],
+               audit_syscall_entry(current,
+                                   
test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64,
+                                   regs->gpr[0],
                                    regs->gpr[3], regs->gpr[4],
                                    regs->gpr[5], regs->gpr[6]);
 
-       if (test_thread_flag(TIF_SYSCALL_TRACE)
-           && (current->ptrace & PT_PTRACED))
-               do_syscall_trace();
 }
 
 void do_syscall_trace_leave(struct pt_regs *regs)
@@ -319,7 +323,9 @@
        secure_computing(regs->gpr[0]);
 
        if (unlikely(current->audit_context))
-               audit_syscall_exit(current, regs->result);
+               audit_syscall_exit(current, 
+                                  
(regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+                                  regs->result);
 
        if ((test_thread_flag(TIF_SYSCALL_TRACE)
             || test_thread_flag(TIF_SINGLESTEP))
diff -urN linux/arch/ppc64/kernel/ptrace32.c linux/arch/ppc64/kernel/ptrace32.c
--- linux/arch/ppc64/kernel/ptrace32.c  2004/10/25 20:44:18     1.13
+++ linux/arch/ppc64/kernel/ptrace32.c  2005/05/19 12:08:14     1.14
@@ -26,6 +26,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -293,7 +294,7 @@
        case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall 
*/
        case PTRACE_CONT: { /* restart after signal. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                if (request == PTRACE_SYSCALL)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -325,7 +326,7 @@
 
        case PTRACE_SINGLESTEP: {  /* set the trap flag. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                set_single_step(child);
diff -urN linux/arch/ppc64/kernel/rtas_flash.c 
linux/arch/ppc64/kernel/rtas_flash.c
--- linux/arch/ppc64/kernel/rtas_flash.c        2005/03/18 17:36:59     1.14
+++ linux/arch/ppc64/kernel/rtas_flash.c        2005/05/19 12:08:14     1.15
@@ -218,7 +218,7 @@
 }
 
 /* Reading the proc file will show status (not the firmware contents) */
-static ssize_t rtas_flash_read(struct file *file, char *buf,
+static ssize_t rtas_flash_read(struct file *file, char __user *buf,
                               size_t count, loff_t *ppos)
 {
        struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
@@ -256,7 +256,7 @@
  * count is.  If the system is low on memory it will be just as well
  * that we fail....
  */
-static ssize_t rtas_flash_write(struct file *file, const char *buffer,
+static ssize_t rtas_flash_write(struct file *file, const char __user *buffer,
                                size_t count, loff_t *off)
 {
        struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
@@ -356,7 +356,7 @@
        args_buf->status = rc;
 }
 
-static ssize_t manage_flash_read(struct file *file, char *buf,
+static ssize_t manage_flash_read(struct file *file, char __user *buf,
                               size_t count, loff_t *ppos)
 {
        struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
@@ -386,7 +386,7 @@
        return msglen;
 }
 
-static ssize_t manage_flash_write(struct file *file, const char *buf,
+static ssize_t manage_flash_write(struct file *file, const char __user *buf,
                                size_t count, loff_t *off)
 {
        struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
@@ -466,7 +466,7 @@
        return n;
 }
 
-static ssize_t validate_flash_read(struct file *file, char *buf,
+static ssize_t validate_flash_read(struct file *file, char __user *buf,
                               size_t count, loff_t *ppos)
 {
        struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
@@ -494,7 +494,7 @@
        return msglen;
 }
 
-static ssize_t validate_flash_write(struct file *file, const char *buf,
+static ssize_t validate_flash_write(struct file *file, const char __user *buf,
                                    size_t count, loff_t *off)
 {
        struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
diff -urN linux/arch/ppc64/kernel/scanlog.c linux/arch/ppc64/kernel/scanlog.c
--- linux/arch/ppc64/kernel/scanlog.c   2005/03/18 17:36:59     1.10
+++ linux/arch/ppc64/kernel/scanlog.c   2005/05/19 12:08:14     1.11
@@ -43,7 +43,7 @@
 static unsigned int ibm_scan_log_dump;                 /* RTAS token */
 static struct proc_dir_entry *proc_ppc64_scan_log_dump;        /* The proc 
file */
 
-static ssize_t scanlog_read(struct file *file, char *buf,
+static ssize_t scanlog_read(struct file *file, char __user *buf,
                            size_t count, loff_t *ppos)
 {
         struct inode * inode = file->f_dentry->d_inode;
@@ -129,7 +129,7 @@
        /*NOTREACHED*/
 }
 
-static ssize_t scanlog_write(struct file * file, const char * buf,
+static ssize_t scanlog_write(struct file * file, const char __user * buf,
                             size_t count, loff_t *ppos)
 {
        char stkbuf[20];
diff -urN linux/arch/ppc64/kernel/signal.c linux/arch/ppc64/kernel/signal.c
--- linux/arch/ppc64/kernel/signal.c    2005/03/18 17:36:59     1.32
+++ linux/arch/ppc64/kernel/signal.c    2005/05/19 12:08:14     1.33
@@ -42,11 +42,7 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-#ifndef MIN
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-#define GP_REGS_SIZE   MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs))
+#define GP_REGS_SIZE   min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
 #define FP_REGS_SIZE   sizeof(elf_fpregset_t)
 
 #define TRAMP_TRACEBACK        3
diff -urN linux/arch/ppc64/kernel/signal32.c linux/arch/ppc64/kernel/signal32.c
--- linux/arch/ppc64/kernel/signal32.c  2005/03/18 17:36:59     1.36
+++ linux/arch/ppc64/kernel/signal32.c  2005/05/19 12:08:14     1.37
@@ -657,7 +657,7 @@
 
        /* Save user registers on the stack */
        frame = &rt_sf->uc.uc_mcontext;
-       if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
+       if (put_user(regs->gpr[1], (u32 __user *)newsp))
                goto badframe;
 
        if (vdso32_rt_sigtramp && current->thread.vdso_base) {
@@ -842,7 +842,7 @@
                regs->link = (unsigned long) frame->mctx.tramp;
        }
 
-       if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
+       if (put_user(regs->gpr[1], (u32 __user *)newsp))
                goto badframe;
        regs->gpr[1] = (unsigned long) newsp;
        regs->gpr[3] = sig;
diff -urN linux/arch/ppc64/kernel/smp.c linux/arch/ppc64/kernel/smp.c
--- linux/arch/ppc64/kernel/smp.c       2005/04/08 18:58:02     1.48
+++ linux/arch/ppc64/kernel/smp.c       2005/05/19 12:08:14     1.49
@@ -125,7 +125,7 @@
         * the processor will continue on to secondary_start
         */
        paca[nr].cpu_start = 1;
-       mb();
+       smp_mb();
 }
 
 #endif /* CONFIG_PPC_MULTIPLATFORM */
@@ -256,7 +256,7 @@
        }
 
        call_data = &data;
-       wmb();
+       smp_wmb();
        /* Send a message to all other CPUs and wait for them to respond */
        smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION);
 
@@ -431,7 +431,7 @@
 
        /* get the target out of it's holding state */
        per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
-       wmb();
+       smp_wmb();
 
        while (!cpu_online(cpu))
                cpu_relax();
@@ -447,7 +447,7 @@
        int i;
 
        for (i = 0; i < 100; i++) {
-               rmb();
+               smp_rmb();
                if (per_cpu(cpu_state, cpu) == CPU_DEAD)
                        return;
                msleep(100);
@@ -463,7 +463,7 @@
        cpu = smp_processor_id();
        printk(KERN_DEBUG "CPU%d offline\n", cpu);
        __get_cpu_var(cpu_state) = CPU_DEAD;
-       wmb();
+       smp_wmb();
        while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
                cpu_relax();
 
@@ -515,7 +515,7 @@
         * be written out to main store before we release
         * the processor.
         */
-       mb();
+       smp_mb();
 
        /* wake up cpus */
        DBG("smp: kicking cpu %d\n", cpu);
diff -urN linux/arch/ppc64/kernel/time.c linux/arch/ppc64/kernel/time.c
--- linux/arch/ppc64/kernel/time.c      2005/03/18 17:36:59     1.33
+++ linux/arch/ppc64/kernel/time.c      2005/05/19 12:08:14     1.34
@@ -221,15 +221,15 @@
        temp_varp->tb_to_xs = do_gtod.varp->tb_to_xs;
        temp_varp->tb_orig_stamp = new_tb_orig_stamp;
        temp_varp->stamp_xsec = new_stamp_xsec;
-       mb();
+       smp_mb();
        do_gtod.varp = temp_varp;
        do_gtod.var_idx = temp_idx;
 
        ++(systemcfg->tb_update_count);
-       wmb();
+       smp_wmb();
        systemcfg->tb_orig_stamp = new_tb_orig_stamp;
        systemcfg->stamp_xsec = new_stamp_xsec;
-       wmb();
+       smp_wmb();
        ++(systemcfg->tb_update_count);
 }
 
@@ -648,7 +648,7 @@
        temp_varp->tb_to_xs = new_tb_to_xs;
        temp_varp->stamp_xsec = new_stamp_xsec;
        temp_varp->tb_orig_stamp = do_gtod.varp->tb_orig_stamp;
-       mb();
+       smp_mb();
        do_gtod.varp = temp_varp;
        do_gtod.var_idx = temp_idx;
 
@@ -662,10 +662,10 @@
         * loops back and reads them again until this criteria is met.
         */
        ++(systemcfg->tb_update_count);
-       wmb();
+       smp_wmb();
        systemcfg->tb_to_xs = new_tb_to_xs;
        systemcfg->stamp_xsec = new_stamp_xsec;
-       wmb();
+       smp_wmb();
        ++(systemcfg->tb_update_count);
 
        write_sequnlock_irqrestore( &xtime_lock, flags );
diff -urN linux/arch/ppc64/kernel/xics.c linux/arch/ppc64/kernel/xics.c
--- linux/arch/ppc64/kernel/xics.c      2005/03/18 17:36:59     1.31
+++ linux/arch/ppc64/kernel/xics.c      2005/05/19 12:08:14     1.32
@@ -432,6 +432,7 @@
 {
        ops->qirr_info(cpu, IPI_PRIORITY);
 }
+#endif /* CONFIG_SMP */
 
 void xics_setup_cpu(void)
 {
@@ -439,9 +440,17 @@
 
        ops->cppr_info(cpu, 0xff);
        iosync();
-}
 
-#endif /* CONFIG_SMP */
+       /*
+        * Put the calling processor into the GIQ.  This is really only
+        * necessary from a secondary thread as the OF start-cpu interface
+        * performs this function for us on primary threads.
+        *
+        * XXX: undo of teardown on kexec needs this too, as may hotplug
+        */
+       rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+               (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
+}
 
 void xics_init_IRQ(void)
 {
@@ -563,8 +572,7 @@
        for (; i < NR_IRQS; ++i)
                get_irq_desc(i)->handler = &xics_pic;
 
-       ops->cppr_info(boot_cpuid, 0xff);
-       iosync();
+       xics_setup_cpu();
 
        ppc64_boot_msg(0x21, "XICS Done");
 }
diff -urN linux/arch/ppc64/kernel/vdso32/note.S 
linux/arch/ppc64/kernel/vdso32/note.S
--- linux/arch/ppc64/kernel/vdso32/note.S       1970/01/01 00:00:00
+++ linux/arch/ppc64/kernel/vdso32/note.S       2005-05-19 13:08:14.829980000 
+0100     1.1
@@ -0,0 +1,25 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+
+#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type)                        \
+       .section name, flags;                                                 \
+       .balign 4;                                                            \
+       .long 1f - 0f;          /* name length */                             \
+       .long 3f - 2f;          /* data length */                             \
+       .long type;             /* note type */                               \
+0:     .asciz vendor;          /* vendor name */                             \
+1:     .balign 4;                                                            \
+2:
+
+#define ASM_ELF_NOTE_END                                                     \
+3:     .balign 4;              /* pad out section */                         \
+       .previous
+
+       ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0)
+       .long LINUX_VERSION_CODE
+       ASM_ELF_NOTE_END
diff -urN linux/arch/ppc64/kernel/vdso32/Makefile 
linux/arch/ppc64/kernel/vdso32/Makefile
--- linux/arch/ppc64/kernel/vdso32/Makefile     2005/03/18 17:37:00     1.1
+++ linux/arch/ppc64/kernel/vdso32/Makefile     2005/05/19 12:08:14     1.2
@@ -1,7 +1,7 @@
 
 # List of files in the vdso, has to be asm only for now
 
-obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o
+obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
 
 # Build rules
 
diff -urN linux/arch/ppc64/kernel/vdso32/cacheflush.S 
linux/arch/ppc64/kernel/vdso32/cacheflush.S
--- linux/arch/ppc64/kernel/vdso32/cacheflush.S 2005/03/18 17:37:00     1.1
+++ linux/arch/ppc64/kernel/vdso32/cacheflush.S 2005/05/19 12:08:14     1.2
@@ -47,6 +47,7 @@
        addi    r6,r6,128
        bdnz    1b
        isync
+       li      r3,0
        blr
   .cfi_endproc
 V_FUNCTION_END(__kernel_sync_dicache)
@@ -59,6 +60,7 @@
   .cfi_startproc
        sync
        isync
+       li      r3,0
        blr
   .cfi_endproc
 V_FUNCTION_END(__kernel_sync_dicache_p5)
diff -urN linux/arch/ppc64/kernel/vdso32/gettimeofday.S 
linux/arch/ppc64/kernel/vdso32/gettimeofday.S
--- linux/arch/ppc64/kernel/vdso32/gettimeofday.S       2005/03/18 17:37:00     
1.1
+++ linux/arch/ppc64/kernel/vdso32/gettimeofday.S       2005/05/19 12:08:14     
1.2
@@ -58,6 +58,7 @@
        stw     r5,TZONE_TZ_DSTTIME(r11)
 
 1:     mtlr    r12
+       li      r3,0
        blr
 
 2:     mr      r3,r10
diff -urN linux/arch/ppc64/kernel/vdso32/vdso32.lds.S 
linux/arch/ppc64/kernel/vdso32/vdso32.lds.S
--- linux/arch/ppc64/kernel/vdso32/vdso32.lds.S 2005/03/18 17:37:00     1.1
+++ linux/arch/ppc64/kernel/vdso32/vdso32.lds.S 2005/05/19 12:08:14     1.2
@@ -20,6 +20,8 @@
   .gnu.version_d  : { *(.gnu.version_d) }
   .gnu.version_r  : { *(.gnu.version_r) }
 
+  .note                  : { *(.note.*) }                      :text   :note
+
   . = ALIGN (16);
   .text :
   {
@@ -87,6 +89,7 @@
 PHDRS
 {
   text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+  note PT_NOTE FLAGS(4); /* PF_R */
   dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
   eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
 }
diff -urN linux/arch/ppc64/kernel/vdso64/note.S 
linux/arch/ppc64/kernel/vdso64/note.S
--- linux/arch/ppc64/kernel/vdso64/note.S       1970/01/01 00:00:00
+++ linux/arch/ppc64/kernel/vdso64/note.S       2005-05-19 13:08:14.957932000 
+0100     1.1
@@ -0,0 +1 @@
+#include "../vdso32/note.S"
diff -urN linux/arch/ppc64/kernel/vdso64/Makefile 
linux/arch/ppc64/kernel/vdso64/Makefile
--- linux/arch/ppc64/kernel/vdso64/Makefile     2005/03/18 17:37:00     1.1
+++ linux/arch/ppc64/kernel/vdso64/Makefile     2005/05/19 12:08:14     1.2
@@ -1,6 +1,6 @@
 # List of files in the vdso, has to be asm only for now
 
-obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o
+obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
 
 # Build rules
 
diff -urN linux/arch/ppc64/kernel/vdso64/cacheflush.S 
linux/arch/ppc64/kernel/vdso64/cacheflush.S
--- linux/arch/ppc64/kernel/vdso64/cacheflush.S 2005/03/18 17:37:00     1.1
+++ linux/arch/ppc64/kernel/vdso64/cacheflush.S 2005/05/19 12:08:14     1.2
@@ -47,6 +47,7 @@
        addi    r6,r6,128
        bdnz    1b
        isync
+       li      r3,0
        blr
   .cfi_endproc
 V_FUNCTION_END(__kernel_sync_dicache)
@@ -59,6 +60,7 @@
   .cfi_startproc
        sync
        isync
+       li      r3,0
        blr
   .cfi_endproc
 V_FUNCTION_END(__kernel_sync_dicache_p5)
diff -urN linux/arch/ppc64/kernel/vdso64/vdso64.lds.S 
linux/arch/ppc64/kernel/vdso64/vdso64.lds.S
--- linux/arch/ppc64/kernel/vdso64/vdso64.lds.S 2005/03/18 17:37:00     1.1
+++ linux/arch/ppc64/kernel/vdso64/vdso64.lds.S 2005/05/19 12:08:14     1.2
@@ -18,12 +18,14 @@
   .gnu.version_d  : { *(.gnu.version_d) }
   .gnu.version_r  : { *(.gnu.version_r) }
 
+  .note                  : { *(.note.*) }              :text   :note
+
   . = ALIGN (16);
   .text           :
   {
     *(.text .stub .text.* .gnu.linkonce.t.*)
     *(.sfpr .glink)
-  }
+  }                                            :text
   PROVIDE (__etext = .);
   PROVIDE (_etext = .);
   PROVIDE (etext = .);
@@ -88,6 +90,7 @@
 PHDRS
 {
   text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+  note PT_NOTE FLAGS(4); /* PF_R */
   dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
   eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
 }
diff -urN linux/arch/ppc64/mm/hash_low.S linux/arch/ppc64/mm/hash_low.S
--- linux/arch/ppc64/mm/hash_low.S      2005/03/18 17:37:00     1.9
+++ linux/arch/ppc64/mm/hash_low.S      2005/05/19 12:08:15     1.10
@@ -85,7 +85,10 @@
        bne-    htab_wrong_access
        /* Check if PTE is busy */
        andi.   r0,r31,_PAGE_BUSY
-       bne-    1b
+       /* If so, just bail out and refault if needed. Someone else
+        * is changing this PTE anyway and might hash it.
+        */
+       bne-    bail_ok
        /* Prepare new PTE value (turn access RW into DIRTY, then
         * add BUSY,HASHPTE and ACCESSED)
         */
@@ -215,6 +218,10 @@
        /* Try all again */
        b       htab_insert_pte 
 
+bail_ok:
+       li      r3,0
+       b       bail
+
 htab_pte_insert_ok:
        /* Insert slot number & secondary bit in PTE */
        rldimi  r30,r3,12,63-15
diff -urN linux/arch/ppc64/mm/hash_native.c linux/arch/ppc64/mm/hash_native.c
--- linux/arch/ppc64/mm/hash_native.c   2005/03/18 17:37:00     1.7
+++ linux/arch/ppc64/mm/hash_native.c   2005/05/19 12:08:15     1.8
@@ -320,8 +320,7 @@
 
        j = 0;
        for (i = 0; i < number; i++) {
-               if ((batch->addr[i] >= USER_START) &&
-                   (batch->addr[i] <= USER_END))
+               if (batch->addr[i] < KERNELBASE)
                        vsid = get_vsid(context, batch->addr[i]);
                else
                        vsid = get_kernel_vsid(batch->addr[i]);
diff -urN linux/arch/ppc64/mm/hash_utils.c linux/arch/ppc64/mm/hash_utils.c
--- linux/arch/ppc64/mm/hash_utils.c    2005/04/08 18:58:03     1.13
+++ linux/arch/ppc64/mm/hash_utils.c    2005/05/19 12:08:15     1.14
@@ -298,24 +298,23 @@
        int local = 0;
        cpumask_t tmp;
 
+       if ((ea & ~REGION_MASK) > EADDR_MASK)
+               return 1;
+
        switch (REGION_ID(ea)) {
        case USER_REGION_ID:
                user_region = 1;
                mm = current->mm;
-               if ((ea > USER_END) || (! mm))
+               if (! mm)
                        return 1;
 
                vsid = get_vsid(mm->context.id, ea);
                break;
        case IO_REGION_ID:
-               if (ea > IMALLOC_END)
-                       return 1;
                mm = &ioremap_mm;
                vsid = get_kernel_vsid(ea);
                break;
        case VMALLOC_REGION_ID:
-               if (ea > VMALLOC_END)
-                       return 1;
                mm = &init_mm;
                vsid = get_kernel_vsid(ea);
                break;
@@ -362,7 +361,7 @@
        unsigned long vsid, vpn, va, hash, secondary, slot;
        unsigned long huge = pte_huge(pte);
 
-       if ((ea >= USER_START) && (ea <= USER_END))
+       if (ea < KERNELBASE)
                vsid = get_vsid(context, ea);
        else
                vsid = get_kernel_vsid(ea);
diff -urN linux/arch/ppc64/mm/hugetlbpage.c linux/arch/ppc64/mm/hugetlbpage.c
--- linux/arch/ppc64/mm/hugetlbpage.c   2005/04/29 11:15:04     1.20
+++ linux/arch/ppc64/mm/hugetlbpage.c   2005/05/19 12:08:15     1.21
@@ -42,7 +42,7 @@
        return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT;
 }
 
-static pgd_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)
+static pud_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)
 {
        int index;
 
@@ -52,21 +52,21 @@
 
        index = hugepgd_index(addr);
        BUG_ON(index >= PTRS_PER_HUGEPGD);
-       return mm->context.huge_pgdir + index;
+       return (pud_t *)(mm->context.huge_pgdir + index);
 }
 
-static inline pte_t *hugepte_offset(pgd_t *dir, unsigned long addr)
+static inline pte_t *hugepte_offset(pud_t *dir, unsigned long addr)
 {
        int index;
 
-       if (pgd_none(*dir))
+       if (pud_none(*dir))
                return NULL;
 
        index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE;
-       return (pte_t *)pgd_page(*dir) + index;
+       return (pte_t *)pud_page(*dir) + index;
 }
 
-static pgd_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)
+static pud_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)
 {
        BUG_ON(! in_hugepage_area(mm->context, addr));
 
@@ -90,10 +90,9 @@
        return hugepgd_offset(mm, addr);
 }
 
-static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir,
-                           unsigned long addr)
+static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long 
addr)
 {
-       if (! pgd_present(*dir)) {
+       if (! pud_present(*dir)) {
                pte_t *new;
 
                spin_unlock(&mm->page_table_lock);
@@ -104,7 +103,7 @@
                 * Because we dropped the lock, we should re-check the
                 * entry, as somebody else could have populated it..
                 */
-               if (pgd_present(*dir)) {
+               if (pud_present(*dir)) {
                        if (new)
                                kmem_cache_free(zero_cache, new);
                } else {
@@ -115,7 +114,7 @@
                        ptepage = virt_to_page(new);
                        ptepage->mapping = (void *) mm;
                        ptepage->index = addr & HUGEPGDIR_MASK;
-                       pgd_populate(mm, dir, new);
+                       pud_populate(mm, dir, new);
                }
        }
 
@@ -124,28 +123,28 @@
 
 static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
-       pgd_t *pgd;
+       pud_t *pud;
 
        BUG_ON(! in_hugepage_area(mm->context, addr));
 
-       pgd = hugepgd_offset(mm, addr);
-       if (! pgd)
+       pud = hugepgd_offset(mm, addr);
+       if (! pud)
                return NULL;
 
-       return hugepte_offset(pgd, addr);
+       return hugepte_offset(pud, addr);
 }
 
 static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
-       pgd_t *pgd;
+       pud_t *pud;
 
        BUG_ON(! in_hugepage_area(mm->context, addr));
 
-       pgd = hugepgd_alloc(mm, addr);
-       if (! pgd)
+       pud = hugepgd_alloc(mm, addr);
+       if (! pud)
                return NULL;
 
-       return hugepte_alloc(mm, pgd, addr);
+       return hugepte_alloc(mm, pud, addr);
 }
 
 static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
@@ -709,10 +708,10 @@
 
        /* cleanup any hugepte pages leftover */
        for (i = 0; i < PTRS_PER_HUGEPGD; i++) {
-               pgd_t *pgd = pgdir + i;
+               pud_t *pud = (pud_t *)(pgdir + i);
 
-               if (! pgd_none(*pgd)) {
-                       pte_t *pte = (pte_t *)pgd_page(*pgd);
+               if (! pud_none(*pud)) {
+                       pte_t *pte = (pte_t *)pud_page(*pud);
                        struct page *ptepage = virt_to_page(pte);
 
                        ptepage->mapping = NULL;
@@ -720,7 +719,7 @@
                        BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE));
                        kmem_cache_free(zero_cache, pte);
                }
-               pgd_clear(pgd);
+               pud_clear(pud);
        }
 
        BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE));
diff -urN linux/arch/ppc64/mm/imalloc.c linux/arch/ppc64/mm/imalloc.c
--- linux/arch/ppc64/mm/imalloc.c       2004/08/24 15:10:06     1.6
+++ linux/arch/ppc64/mm/imalloc.c       2005/05/19 12:08:15     1.7
@@ -14,6 +14,7 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/semaphore.h>
+#include <asm/imalloc.h>
 
 static DECLARE_MUTEX(imlist_sem);
 struct vm_struct * imlist = NULL;
@@ -23,11 +24,11 @@
        unsigned long addr;
        struct vm_struct **p, *tmp;
 
-       addr = IMALLOC_START;
+       addr = ioremap_bot;
        for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
                if (size + addr < (unsigned long) tmp->addr)
                        break;
-               if ((unsigned long)tmp->addr >= IMALLOC_START) 
+               if ((unsigned long)tmp->addr >= ioremap_bot)
                        addr = tmp->size + (unsigned long) tmp->addr;
                if (addr > IMALLOC_END-size) 
                        return 1;
diff -urN linux/arch/ppc64/mm/init.c linux/arch/ppc64/mm/init.c
--- linux/arch/ppc64/mm/init.c  2005/04/29 11:15:04     1.44
+++ linux/arch/ppc64/mm/init.c  2005/05/19 12:08:15     1.45
@@ -64,6 +64,7 @@
 #include <asm/iommu.h>
 #include <asm/abs_addr.h>
 #include <asm/vdso.h>
+#include <asm/imalloc.h>
 
 int mem_init_done;
 unsigned long ioremap_bot = IMALLOC_BASE;
@@ -136,14 +137,78 @@
 
 #else
 
+static void unmap_im_area_pte(pmd_t *pmd, unsigned long addr,
+                                 unsigned long end)
+{
+       pte_t *pte;
+
+       pte = pte_offset_kernel(pmd, addr);
+       do {
+               pte_t ptent = ptep_get_and_clear(&ioremap_mm, addr, pte);
+               WARN_ON(!pte_none(ptent) && !pte_present(ptent));
+       } while (pte++, addr += PAGE_SIZE, addr != end);
+}
+
+static inline void unmap_im_area_pmd(pud_t *pud, unsigned long addr,
+                                    unsigned long end)
+{
+       pmd_t *pmd;
+       unsigned long next;
+
+       pmd = pmd_offset(pud, addr);
+       do {
+               next = pmd_addr_end(addr, end);
+               if (pmd_none_or_clear_bad(pmd))
+                       continue;
+               unmap_im_area_pte(pmd, addr, next);
+       } while (pmd++, addr = next, addr != end);
+}
+
+static inline void unmap_im_area_pud(pgd_t *pgd, unsigned long addr,
+                                    unsigned long end)
+{
+       pud_t *pud;
+       unsigned long next;
+
+       pud = pud_offset(pgd, addr);
+       do {
+               next = pud_addr_end(addr, end);
+               if (pud_none_or_clear_bad(pud))
+                       continue;
+               unmap_im_area_pmd(pud, addr, next);
+       } while (pud++, addr = next, addr != end);
+}
+
+static void unmap_im_area(unsigned long addr, unsigned long end)
+{
+       struct mm_struct *mm = &ioremap_mm;
+       unsigned long next;
+       pgd_t *pgd;
+
+       spin_lock(&mm->page_table_lock);
+
+       pgd = pgd_offset_i(addr);
+       flush_cache_vunmap(addr, end);
+       do {
+               next = pgd_addr_end(addr, end);
+               if (pgd_none_or_clear_bad(pgd))
+                       continue;
+               unmap_im_area_pud(pgd, addr, next);
+       } while (pgd++, addr = next, addr != end);
+       flush_tlb_kernel_range(start, end);
+
+       spin_unlock(&mm->page_table_lock);
+}
+
 /*
  * map_io_page currently only called by __ioremap
  * map_io_page adds an entry to the ioremap page table
  * and adds an entry to the HPT, possibly bolting it
  */
-static void map_io_page(unsigned long ea, unsigned long pa, int flags)
+static int map_io_page(unsigned long ea, unsigned long pa, int flags)
 {
        pgd_t *pgdp;
+       pud_t *pudp;
        pmd_t *pmdp;
        pte_t *ptep;
        unsigned long vsid;
@@ -151,9 +216,15 @@
        if (mem_init_done) {
                spin_lock(&ioremap_mm.page_table_lock);
                pgdp = pgd_offset_i(ea);
-               pmdp = pmd_alloc(&ioremap_mm, pgdp, ea);
+               pudp = pud_alloc(&ioremap_mm, pgdp, ea);
+               if (!pudp)
+                       return -ENOMEM;
+               pmdp = pmd_alloc(&ioremap_mm, pudp, ea);
+               if (!pmdp)
+                       return -ENOMEM;
                ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea);
-
+               if (!ptep)
+                       return -ENOMEM;
                pa = abs_to_phys(pa);
                set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
                                                          __pgprot(flags)));
@@ -181,6 +252,7 @@
                        panic("map_io_page: could not insert mapping");
                }
        }
+       return 0;
 }
 
 
@@ -194,9 +266,14 @@
                flags |= pgprot_val(PAGE_KERNEL);
 
        for (i = 0; i < size; i += PAGE_SIZE)
-               map_io_page(ea+i, pa+i, flags);
+               if (map_io_page(ea+i, pa+i, flags))
+                       goto failure;
 
        return (void __iomem *) (ea + (addr & ~PAGE_MASK));
+ failure:
+       if (mem_init_done)
+               unmap_im_area(ea, ea + size);
+       return NULL;
 }
 
 
@@ -206,10 +283,11 @@
        return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
 }
 
-void __iomem *
-__ioremap(unsigned long addr, unsigned long size, unsigned long flags)
+void __iomem * __ioremap(unsigned long addr, unsigned long size,
+                        unsigned long flags)
 {
        unsigned long pa, ea;
+       void __iomem *ret;
 
        /*
         * Choose an address to map it to.
@@ -232,12 +310,16 @@
                if (area == NULL)
                        return NULL;
                ea = (unsigned long)(area->addr);
+               ret = __ioremap_com(addr, pa, ea, size, flags);
+               if (!ret)
+                       im_free(area->addr);
        } else {
                ea = ioremap_bot;
-               ioremap_bot += size;
+               ret = __ioremap_com(addr, pa, ea, size, flags);
+               if (ret)
+                       ioremap_bot += size;
        }
-
-       return __ioremap_com(addr, pa, ea, size, flags);
+       return ret;
 }
 
 #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
@@ -246,6 +328,7 @@
                       unsigned long size, unsigned long flags)
 {
        struct vm_struct *area;
+       void __iomem *ret;
        
        /* For now, require page-aligned values for pa, ea, and size */
        if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) ||
@@ -276,7 +359,12 @@
                }
        }
        
-       if (__ioremap_com(pa, pa, ea, size, flags) != (void *) ea) {
+       ret = __ioremap_com(pa, pa, ea, size, flags);
+       if (ret == NULL) {
+               printk(KERN_ERR "ioremap_explicit() allocation failure !\n");
+               return 1;
+       }
+       if (ret != (void *) ea) {
                printk(KERN_ERR "__ioremap_com() returned unexpected addr\n");
                return 1;
        }
@@ -284,69 +372,6 @@
        return 0;
 }
 
-static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
-                                 unsigned long size)
-{
-       unsigned long base, end;
-       pte_t *pte;
-
-       if (pmd_none(*pmd))
-               return;
-       if (pmd_bad(*pmd)) {
-               pmd_ERROR(*pmd);
-               pmd_clear(pmd);
-               return;
-       }
-
-       pte = pte_offset_kernel(pmd, address);
-       base = address & PMD_MASK;
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-
-       do {
-               pte_t page;
-               page = ptep_get_and_clear(&ioremap_mm, base + address, pte);
-               address += PAGE_SIZE;
-               pte++;
-               if (pte_none(page))
-                       continue;
-               if (pte_present(page))
-                       continue;
-               printk(KERN_CRIT "Whee.. Swapped out page in kernel page"
-                      " table\n");
-       } while (address < end);
-}
-
-static void unmap_im_area_pmd(pgd_t *dir, unsigned long address,
-                                 unsigned long size)
-{
-       unsigned long base, end;
-       pmd_t *pmd;
-
-       if (pgd_none(*dir))
-               return;
-       if (pgd_bad(*dir)) {
-               pgd_ERROR(*dir);
-               pgd_clear(dir);
-               return;
-       }
-
-       pmd = pmd_offset(dir, address);
-       base = address & PGDIR_MASK;
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-
-       do {
-               unmap_im_area_pte(pmd, base + address, end - address);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address < end);
-}
-
 /*  
  * Unmap an IO region and remove it from imalloc'd list.
  * Access to IO memory should be serialized by driver.
@@ -356,39 +381,19 @@
  */
 void iounmap(volatile void __iomem *token)
 {
-       unsigned long address, start, end, size;
-       struct mm_struct *mm;
-       pgd_t *dir;
+       unsigned long address, size;
        void *addr;
 
-       if (!mem_init_done) {
+       if (!mem_init_done)
                return;
-       }
        
        addr = (void *) ((unsigned long __force) token & PAGE_MASK);
        
-       if ((size = im_free(addr)) == 0) {
+       if ((size = im_free(addr)) == 0)
                return;
-       }
 
        address = (unsigned long)addr; 
-       start = address;
-       end = address + size;
-
-       mm = &ioremap_mm;
-       spin_lock(&mm->page_table_lock);
-
-       dir = pgd_offset_i(address);
-       flush_cache_vunmap(address, end);
-       do {
-               unmap_im_area_pmd(dir, address, end - address);
-               address = (address + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       } while (address && (address < end));
-       flush_tlb_kernel_range(start, end);
-
-       spin_unlock(&mm->page_table_lock);
-       return;
+       unmap_im_area(address, address + size);
 }
 
 static int iounmap_subset_regions(unsigned long addr, unsigned long size)
@@ -664,7 +669,7 @@
        zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
        zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
 
-       free_area_init_node(0, &contig_page_data, zones_size,
+       free_area_init_node(0, NODE_DATA(0), zones_size,
                            __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
 }
 #endif /* CONFIG_DISCONTIGMEM */
diff -urN linux/arch/ppc64/mm/slb.c linux/arch/ppc64/mm/slb.c
--- linux/arch/ppc64/mm/slb.c   2005/03/18 17:37:00     1.6
+++ linux/arch/ppc64/mm/slb.c   2005/05/19 12:08:15     1.7
@@ -33,8 +33,8 @@
        return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags;
 }
 
-static inline void create_slbe(unsigned long ea, unsigned long vsid,
-                              unsigned long flags, unsigned long entry)
+static inline void create_slbe(unsigned long ea, unsigned long flags,
+                              unsigned long entry)
 {
        asm volatile("slbmte  %0,%1" :
                     : "r" (mk_vsid_data(ea, flags)),
@@ -145,9 +145,8 @@
        asm volatile("isync":::"memory");
        asm volatile("slbmte  %0,%0"::"r" (0) : "memory");
        asm volatile("isync; slbia; isync":::"memory");
-       create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE), flags, 0);
-       create_slbe(VMALLOCBASE, get_kernel_vsid(KERNELBASE),
-                   SLB_VSID_KERNEL, 1);
+       create_slbe(KERNELBASE, flags, 0);
+       create_slbe(VMALLOCBASE, SLB_VSID_KERNEL, 1);
        /* We don't bolt the stack for the time being - we're in boot,
         * so the stack is in the bolted segment.  By the time it goes
         * elsewhere, we'll call _switch() which will bolt in the new
diff -urN linux/arch/ppc64/mm/stab.c linux/arch/ppc64/mm/stab.c
--- linux/arch/ppc64/mm/stab.c  2005/03/18 17:37:00     1.4
+++ linux/arch/ppc64/mm/stab.c  2005/05/19 12:08:15     1.5
@@ -19,6 +19,11 @@
 #include <asm/paca.h>
 #include <asm/cputable.h>
 
+struct stab_entry {
+       unsigned long esid_data;
+       unsigned long vsid_data;
+};
+
 /* Both the segment table and SLB code uses the following cache */
 #define NR_STAB_CACHE_ENTRIES 8
 DEFINE_PER_CPU(long, stab_cache_ptr);
diff -urN linux/arch/ppc64/xmon/ppc-opc.c linux/arch/ppc64/xmon/ppc-opc.c
--- linux/arch/ppc64/xmon/ppc-opc.c     2004/06/06 02:12:40     1.4
+++ linux/arch/ppc64/xmon/ppc-opc.c     2005/05/19 12:08:15     1.5
@@ -20,6 +20,7 @@
    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA.  */
 
+#include <linux/stddef.h>
 #include "nonstdio.h"
 #include "ppc.h"
 
@@ -110,12 +111,12 @@
   /* The zero index is used to indicate the end of the list of
      operands.  */
 #define UNUSED 0
-  { 0, 0, 0, 0, 0 },
+  { 0, 0, NULL, NULL, 0 },
 
   /* The BA field in an XL form instruction.  */
 #define BA UNUSED + 1
 #define BA_MASK (0x1f << 16)
-  { 5, 16, 0, 0, PPC_OPERAND_CR },
+  { 5, 16, NULL, NULL, PPC_OPERAND_CR },
 
   /* The BA field in an XL form instruction when it must be the same
      as the BT field in the same instruction.  */
@@ -125,7 +126,7 @@
   /* The BB field in an XL form instruction.  */
 #define BB BAT + 1
 #define BB_MASK (0x1f << 11)
-  { 5, 11, 0, 0, PPC_OPERAND_CR },
+  { 5, 11, NULL, NULL, PPC_OPERAND_CR },
 
   /* The BB field in an XL form instruction when it must be the same
      as the BA field in the same instruction.  */
@@ -168,21 +169,21 @@
 
   /* The BF field in an X or XL form instruction.  */
 #define BF BDPA + 1
-  { 3, 23, 0, 0, PPC_OPERAND_CR },
+  { 3, 23, NULL, NULL, PPC_OPERAND_CR },
 
   /* An optional BF field.  This is used for comparison instructions,
      in which an omitted BF field is taken as zero.  */
 #define OBF BF + 1
-  { 3, 23, 0, 0, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+  { 3, 23, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
 
   /* The BFA field in an X or XL form instruction.  */
 #define BFA OBF + 1
-  { 3, 18, 0, 0, PPC_OPERAND_CR },
+  { 3, 18, NULL, NULL, PPC_OPERAND_CR },
 
   /* The BI field in a B form or XL form instruction.  */
 #define BI BFA + 1
 #define BI_MASK (0x1f << 16)
-  { 5, 16, 0, 0, PPC_OPERAND_CR },
+  { 5, 16, NULL, NULL, PPC_OPERAND_CR },
 
   /* The BO field in a B form instruction.  Certain values are
      illegal.  */
@@ -197,36 +198,36 @@
 
   /* The BT field in an X or XL form instruction.  */
 #define BT BOE + 1
-  { 5, 21, 0, 0, PPC_OPERAND_CR },
+  { 5, 21, NULL, NULL, PPC_OPERAND_CR },
 
   /* The condition register number portion of the BI field in a B form
      or XL form instruction.  This is used for the extended
      conditional branch mnemonics, which set the lower two bits of the
      BI field.  This field is optional.  */
 #define CR BT + 1
-  { 3, 18, 0, 0, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
+  { 3, 18, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL },
 
   /* The CRB field in an X form instruction.  */
 #define CRB CR + 1
-  { 5, 6, 0, 0, 0 },
+  { 5, 6, NULL, NULL, 0 },
 
   /* The CRFD field in an X form instruction.  */
 #define CRFD CRB + 1
-  { 3, 23, 0, 0, PPC_OPERAND_CR },
+  { 3, 23, NULL, NULL, PPC_OPERAND_CR },
 
   /* The CRFS field in an X form instruction.  */
 #define CRFS CRFD + 1
-  { 3, 0, 0, 0, PPC_OPERAND_CR },
+  { 3, 0, NULL, NULL, PPC_OPERAND_CR },
 
   /* The CT field in an X form instruction.  */
 #define CT CRFS + 1
-  { 5, 21, 0, 0, PPC_OPERAND_OPTIONAL },
+  { 5, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
 
   /* The D field in a D form instruction.  This is a displacement off
      a register, and implies that the next operand is a register in
      parentheses.  */
 #define D CT + 1
-  { 16, 0, 0, 0, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
+  { 16, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED },
 
   /* The DE field in a DE form instruction.  This is like D, but is 12
      bits only.  */
@@ -252,40 +253,40 @@
 
   /* The E field in a wrteei instruction.  */
 #define E DS + 1
-  { 1, 15, 0, 0, 0 },
+  { 1, 15, NULL, NULL, 0 },
 
   /* The FL1 field in a POWER SC form instruction.  */
 #define FL1 E + 1
-  { 4, 12, 0, 0, 0 },
+  { 4, 12, NULL, NULL, 0 },
 
   /* The FL2 field in a POWER SC form instruction.  */
 #define FL2 FL1 + 1
-  { 3, 2, 0, 0, 0 },
+  { 3, 2, NULL, NULL, 0 },
 
   /* The FLM field in an XFL form instruction.  */
 #define FLM FL2 + 1
-  { 8, 17, 0, 0, 0 },
+  { 8, 17, NULL, NULL, 0 },
 
   /* The FRA field in an X or A form instruction.  */
 #define FRA FLM + 1
 #define FRA_MASK (0x1f << 16)
-  { 5, 16, 0, 0, PPC_OPERAND_FPR },
+  { 5, 16, NULL, NULL, PPC_OPERAND_FPR },
 
   /* The FRB field in an X or A form instruction.  */
 #define FRB FRA + 1
 #define FRB_MASK (0x1f << 11)
-  { 5, 11, 0, 0, PPC_OPERAND_FPR },
+  { 5, 11, NULL, NULL, PPC_OPERAND_FPR },
 
   /* The FRC field in an A form instruction.  */
 #define FRC FRB + 1
 #define FRC_MASK (0x1f << 6)
-  { 5, 6, 0, 0, PPC_OPERAND_FPR },
+  { 5, 6, NULL, NULL, PPC_OPERAND_FPR },
 
   /* The FRS field in an X form instruction or the FRT field in a D, X
      or A form instruction.  */
 #define FRS FRC + 1
 #define FRT FRS
-  { 5, 21, 0, 0, PPC_OPERAND_FPR },
+  { 5, 21, NULL, NULL, PPC_OPERAND_FPR },
 
   /* The FXM field in an XFX instruction.  */
 #define FXM FRS + 1
@@ -298,11 +299,11 @@
 
   /* The L field in a D or X form instruction.  */
 #define L FXM4 + 1
-  { 1, 21, 0, 0, PPC_OPERAND_OPTIONAL },
+  { 1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
 
   /* The LEV field in a POWER SC form instruction.  */
 #define LEV L + 1
-  { 7, 5, 0, 0, 0 },
+  { 7, 5, NULL, NULL, 0 },
 
   /* The LI field in an I form instruction.  The lower two bits are
      forced to zero.  */
@@ -316,24 +317,24 @@
 
   /* The LS field in an X (sync) form instruction.  */
 #define LS LIA + 1
-  { 2, 21, 0, 0, PPC_OPERAND_OPTIONAL },
+  { 2, 21, NULL, NULL, PPC_OPERAND_OPTIONAL },
 
   /* The MB field in an M form instruction.  */
 #define MB LS + 1
 #define MB_MASK (0x1f << 6)
-  { 5, 6, 0, 0, 0 },
+  { 5, 6, NULL, NULL, 0 },
 
   /* The ME field in an M form instruction.  */
 #define ME MB + 1
 #define ME_MASK (0x1f << 1)
-  { 5, 1, 0, 0, 0 },
+  { 5, 1, NULL, NULL, 0 },
 
   /* The MB and ME fields in an M form instruction expressed a single
      operand which is a bitmask indicating which bits to select.  This
      is a two operand form using PPC_OPERAND_NEXT.  See the
      description in opcode/ppc.h for what this means.  */
 #define MBE ME + 1
-  { 5, 6, 0, 0, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT },
+  { 5, 6, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT },
   { 32, 0, insert_mbe, extract_mbe, 0 },
 
   /* The MB or ME field in an MD or MDS form instruction.  The high
@@ -345,7 +346,7 @@
 
   /* The MO field in an mbar instruction.  */
 #define MO MB6 + 1
-  { 5, 21, 0, 0, 0 },
+  { 5, 21, NULL, NULL, 0 },
 
   /* The NB field in an X form instruction.  The value 32 is stored as
      0.  */
@@ -361,34 +362,34 @@
   /* The RA field in an D, DS, DQ, X, XO, M, or MDS form instruction.  */
 #define RA NSI + 1
 #define RA_MASK (0x1f << 16)
-  { 5, 16, 0, 0, PPC_OPERAND_GPR },
+  { 5, 16, NULL, NULL, PPC_OPERAND_GPR },
 
   /* The RA field in the DQ form lq instruction, which has special
      value restrictions.  */
 #define RAQ RA + 1
-  { 5, 16, insert_raq, 0, PPC_OPERAND_GPR },
+  { 5, 16, insert_raq, NULL, PPC_OPERAND_GPR },
 
   /* The RA field in a D or X form instruction which is an updating
      load, which means that the RA field may not be zero and may not
      equal the RT field.  */
 #define RAL RAQ + 1
-  { 5, 16, insert_ral, 0, PPC_OPERAND_GPR },
+  { 5, 16, insert_ral, NULL, PPC_OPERAND_GPR },
 
   /* The RA field in an lmw instruction, which has special value
      restrictions.  */
 #define RAM RAL + 1
-  { 5, 16, insert_ram, 0, PPC_OPERAND_GPR },
+  { 5, 16, insert_ram, NULL, PPC_OPERAND_GPR },
 
   /* The RA field in a D or X form instruction which is an updating
      store or an updating floating point load, which means that the RA
      field may not be zero.  */
 #define RAS RAM + 1
-  { 5, 16, insert_ras, 0, PPC_OPERAND_GPR },
+  { 5, 16, insert_ras, NULL, PPC_OPERAND_GPR },
 
   /* The RB field in an X, XO, M, or MDS form instruction.  */
 #define RB RAS + 1
 #define RB_MASK (0x1f << 11)
-  { 5, 11, 0, 0, PPC_OPERAND_GPR },
+  { 5, 11, NULL, NULL, PPC_OPERAND_GPR },
 
   /* The RB field in an X form instruction when it must be the same as
      the RS field in the instruction.  This is used for extended
@@ -402,22 +403,22 @@
 #define RS RBS + 1
 #define RT RS
 #define RT_MASK (0x1f << 21)
-  { 5, 21, 0, 0, PPC_OPERAND_GPR },
+  { 5, 21, NULL, NULL, PPC_OPERAND_GPR },
 
   /* The RS field of the DS form stq instruction, which has special
      value restrictions.  */
 #define RSQ RS + 1
-  { 5, 21, insert_rsq, 0, PPC_OPERAND_GPR },
+  { 5, 21, insert_rsq, NULL, PPC_OPERAND_GPR },
 
   /* The RT field of the DQ form lq instruction, which has special
      value restrictions.  */
 #define RTQ RSQ + 1
-  { 5, 21, insert_rtq, 0, PPC_OPERAND_GPR },
+  { 5, 21, insert_rtq, NULL, PPC_OPERAND_GPR },
 
   /* The SH field in an X or M form instruction.  */
 #define SH RTQ + 1
 #define SH_MASK (0x1f << 11)
-  { 5, 11, 0, 0, 0 },
+  { 5, 11, NULL, NULL, 0 },
 
   /* The SH field in an MD form instruction.  This is split.  */
 #define SH6 SH + 1
@@ -426,12 +427,12 @@
 
   /* The SI field in a D form instruction.  */
 #define SI SH6 + 1
-  { 16, 0, 0, 0, PPC_OPERAND_SIGNED },
+  { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED },
 
   /* The SI field in a D form instruction when we accept a wide range
      of positive values.  */
 #define SISIGNOPT SI + 1
-  { 16, 0, 0, 0, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT },
+  { 16, 0, NULL, NULL, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT },
 
   /* The SPR field in an XFX form instruction.  This is flipped--the
      lower 5 bits are stored in the upper 5 and vice- versa.  */
@@ -443,25 +444,25 @@
   /* The BAT index number in an XFX form m[ft]ibat[lu] instruction.  */
 #define SPRBAT SPR + 1
 #define SPRBAT_MASK (0x3 << 17)
-  { 2, 17, 0, 0, 0 },
+  { 2, 17, NULL, NULL, 0 },
 
   /* The SPRG register number in an XFX form m[ft]sprg instruction.  */
 #define SPRG SPRBAT + 1
 #define SPRG_MASK (0x3 << 16)
-  { 2, 16, 0, 0, 0 },
+  { 2, 16, NULL, NULL, 0 },
 
   /* The SR field in an X form instruction.  */
 #define SR SPRG + 1
-  { 4, 16, 0, 0, 0 },
+  { 4, 16, NULL, NULL, 0 },
 
   /* The STRM field in an X AltiVec form instruction.  */
 #define STRM SR + 1
 #define STRM_MASK (0x3 << 21)
-  { 2, 21, 0, 0, 0 },
+  { 2, 21, NULL, NULL, 0 },
 
   /* The SV field in a POWER SC form instruction.  */
 #define SV STRM + 1
-  { 14, 2, 0, 0, 0 },
+  { 14, 2, NULL, NULL, 0 },
 
   /* The TBR field in an XFX form instruction.  This is like the SPR
      field, but it is optional.  */
@@ -471,52 +472,52 @@
   /* The TO field in a D or X form instruction.  */
 #define TO TBR + 1
 #define TO_MASK (0x1f << 21)
-  { 5, 21, 0, 0, 0 },
+  { 5, 21, NULL, NULL, 0 },
 
   /* The U field in an X form instruction.  */
 #define U TO + 1
-  { 4, 12, 0, 0, 0 },
+  { 4, 12, NULL, NULL, 0 },
 
   /* The UI field in a D form instruction.  */
 #define UI U + 1
-  { 16, 0, 0, 0, 0 },
+  { 16, 0, NULL, NULL, 0 },
 
   /* The VA field in a VA, VX or VXR form instruction.  */
 #define VA UI + 1
 #define VA_MASK        (0x1f << 16)
-  { 5, 16, 0, 0, PPC_OPERAND_VR },
+  { 5, 16, NULL, NULL, PPC_OPERAND_VR },
 
   /* The VB field in a VA, VX or VXR form instruction.  */
 #define VB VA + 1
 #define VB_MASK (0x1f << 11)
-  { 5, 11, 0, 0, PPC_OPERAND_VR },
+  { 5, 11, NULL, NULL, PPC_OPERAND_VR },
 
   /* The VC field in a VA form instruction.  */
 #define VC VB + 1
 #define VC_MASK (0x1f << 6)
-  { 5, 6, 0, 0, PPC_OPERAND_VR },
+  { 5, 6, NULL, NULL, PPC_OPERAND_VR },
 
   /* The VD or VS field in a VA, VX, VXR or X form instruction.  */
 #define VD VC + 1
 #define VS VD
 #define VD_MASK (0x1f << 21)
-  { 5, 21, 0, 0, PPC_OPERAND_VR },
+  { 5, 21, NULL, NULL, PPC_OPERAND_VR },
 
   /* The SIMM field in a VX form instruction.  */
 #define SIMM VD + 1
-  { 5, 16, 0, 0, PPC_OPERAND_SIGNED},
+  { 5, 16, NULL, NULL, PPC_OPERAND_SIGNED},
 
   /* The UIMM field in a VX form instruction.  */
 #define UIMM SIMM + 1
-  { 5, 16, 0, 0, 0 },
+  { 5, 16, NULL, NULL, 0 },
 
   /* The SHB field in a VA form instruction.  */
 #define SHB UIMM + 1
-  { 4, 6, 0, 0, 0 },
+  { 4, 6, NULL, NULL, 0 },
 
   /* The other UIMM field in a EVX form instruction.  */
 #define EVUIMM SHB + 1
-  { 5, 11, 0, 0, 0 },
+  { 5, 11, NULL, NULL, 0 },
 
   /* The other UIMM field in a half word EVX form instruction.  */
 #define EVUIMM_2 EVUIMM + 1
@@ -533,11 +534,11 @@
   /* The WS field.  */
 #define WS EVUIMM_8 + 1
 #define WS_MASK (0x7 << 11)
-  { 3, 11, 0, 0, 0 },
+  { 3, 11, NULL, NULL, 0 },
 
   /* The L field in an mtmsrd instruction */
 #define MTMSRD_L WS + 1
-  { 1, 16, 0, 0, PPC_OPERAND_OPTIONAL },
+  { 1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL },
 
 };
 
diff -urN linux/arch/s390/defconfig linux/arch/s390/defconfig
--- linux/arch/s390/defconfig   2005/03/18 17:37:01     1.45
+++ linux/arch/s390/defconfig   2005/05/19 12:08:15     1.46
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11
-# Wed Mar  2 16:57:55 2005
+# Linux kernel version: 2.6.12-rc3
+# Fri Apr 22 15:30:58 2005
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -15,6 +15,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -26,24 +27,25 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -261,7 +263,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
@@ -329,6 +330,7 @@
 CONFIG_NET_QOS=y
 CONFIG_NET_ESTIMATOR=y
 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
@@ -338,6 +340,7 @@
 # CONFIG_NET_CLS_IND 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
 
@@ -393,6 +396,8 @@
 CONFIG_IUCV=m
 # CONFIG_NETIUCV is not set
 # CONFIG_SMSGIUCV is not set
+# CONFIG_CLAW is not set
+# CONFIG_MPC is not set
 CONFIG_QETH=y
 
 #
@@ -532,10 +537,13 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
@@ -560,6 +568,7 @@
 # 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_DES_Z990 is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
diff -urN linux/arch/s390/kernel/compat_ioctl.c 
linux/arch/s390/kernel/compat_ioctl.c
--- linux/arch/s390/kernel/compat_ioctl.c       2005/03/18 17:37:01     1.9
+++ linux/arch/s390/kernel/compat_ioctl.c       2005/05/19 12:08:15     1.10
@@ -16,6 +16,7 @@
 #define CODE
 #include "../../../fs/compat_ioctl.c"
 #include <asm/dasd.h>
+#include <asm/cmb.h>
 #include <asm/tape390.h>
 
 static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
@@ -58,7 +59,11 @@
 COMPATIBLE_IOCTL(BIODASDPSRD)
 COMPATIBLE_IOCTL(BIODASDGATTR)
 COMPATIBLE_IOCTL(BIODASDSATTR)
-
+#if defined(CONFIG_DASD_CMB) || defined(CONFIG_DASD_CMB_MODULE)
+COMPATIBLE_IOCTL(BIODASDCMFENABLE)
+COMPATIBLE_IOCTL(BIODASDCMFDISABLE)
+COMPATIBLE_IOCTL(BIODASDREADALLCMB)
+#endif
 #endif
 
 #if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE)
diff -urN linux/arch/s390/kernel/ptrace.c linux/arch/s390/kernel/ptrace.c
--- linux/arch/s390/kernel/ptrace.c     2005/03/18 17:37:01     1.24
+++ linux/arch/s390/kernel/ptrace.c     2005/05/19 12:08:15     1.25
@@ -32,6 +32,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
+#include <linux/signal.h>
 
 #include <asm/segment.h>
 #include <asm/page.h>
@@ -609,7 +610,7 @@
                /* continue and stop at next (return from) syscall */
        case PTRACE_CONT:
                /* restart after signal. */
-               if ((unsigned long) data >= _NSIG)
+               if (!valid_signal(data))
                        return -EIO;
                if (request == PTRACE_SYSCALL)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -637,7 +638,7 @@
 
        case PTRACE_SINGLESTEP:
                /* set the trap flag. */
-               if ((unsigned long) data >= _NSIG)
+               if (!valid_signal(data))
                        return -EIO;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                child->exit_code = data;
@@ -711,18 +712,13 @@
 asmlinkage void
 syscall_trace(struct pt_regs *regs, int entryexit)
 {
-       if (unlikely(current->audit_context)) {
-               if (!entryexit)
-                       audit_syscall_entry(current, regs->gprs[2],
-                                           regs->orig_gpr2, regs->gprs[3],
-                                           regs->gprs[4], regs->gprs[5]);
-               else
-                       audit_syscall_exit(current, regs->gprs[2]);
-       }
+       if (unlikely(current->audit_context) && entryexit)
+               audit_syscall_exit(current, AUDITSC_RESULT(regs->gprs[2]), 
regs->gprs[2]);
+
        if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
+               goto out;
        if (!(current->ptrace & PT_PTRACED))
-               return;
+               goto out;
        ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
                                 ? 0x80 : 0));
 
@@ -735,4 +731,10 @@
                send_sig(current->exit_code, current, 1);
                current->exit_code = 0;
        }
+ out:
+       if (unlikely(current->audit_context) && !entryexit)
+               audit_syscall_entry(current, 
+                                   
test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
+                                   regs->gprs[2], regs->orig_gpr2, 
regs->gprs[3],
+                                   regs->gprs[4], regs->gprs[5]);
 }
diff -urN linux/arch/s390/kernel/s390_ksyms.c 
linux/arch/s390/kernel/s390_ksyms.c
--- linux/arch/s390/kernel/s390_ksyms.c 2005/02/13 20:16:19     1.23
+++ linux/arch/s390/kernel/s390_ksyms.c 2005/05/19 12:08:15     1.24
@@ -34,7 +34,6 @@
 EXPORT_SYMBOL(__strncpy_from_user_asm);
 EXPORT_SYMBOL(__strnlen_user_asm);
 EXPORT_SYMBOL(diag10);
-EXPORT_SYMBOL(default_storage_key);
 
 /*
  * semaphore ops
diff -urN linux/arch/s390/kernel/setup.c linux/arch/s390/kernel/setup.c
--- linux/arch/s390/kernel/setup.c      2005/02/13 20:16:19     1.36
+++ linux/arch/s390/kernel/setup.c      2005/05/19 12:08:15     1.37
@@ -44,6 +44,8 @@
 #include <asm/cpcmd.h>
 #include <asm/lowcore.h>
 #include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
 
 /*
  * Machine setup..
@@ -53,13 +55,14 @@
 unsigned int console_irq = -1;
 unsigned long memory_size = 0;
 unsigned long machine_flags = 0;
-unsigned int default_storage_key = 0;
 struct {
        unsigned long addr, size, type;
 } memory_chunk[MEMORY_CHUNKS] = { { 0 } };
 #define CHUNK_READ_WRITE 0
 #define CHUNK_READ_ONLY 1
 volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
+unsigned long __initdata zholes_size[MAX_NR_ZONES];
+static unsigned long __initdata memory_end;
 
 /*
  * Setup options
@@ -78,11 +81,15 @@
 
 static struct resource code_resource = {
        .name  = "Kernel code",
+       .start = (unsigned long) &_text,
+       .end = (unsigned long) &_etext - 1,
        .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
 };
 
 static struct resource data_resource = {
        .name = "Kernel data",
+       .start = (unsigned long) &_etext,
+       .end = (unsigned long) &_edata - 1,
        .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
 };
 
@@ -310,90 +317,50 @@
 
 EXPORT_SYMBOL(machine_power_off);
 
-/*
- * Setup function called from init/main.c just after the banner
- * was printed.
- */
-extern char _pstart, _pend, _stext;
-
-void __init setup_arch(char **cmdline_p)
+static void __init
+add_memory_hole(unsigned long start, unsigned long end)
 {
-        unsigned long bootmap_size;
-        unsigned long memory_start, memory_end;
-        char c = ' ', cn, *to = command_line, *from = COMMAND_LINE;
-       unsigned long start_pfn, end_pfn;
-        static unsigned int smptrap=0;
-        unsigned long delay = 0;
-       struct _lowcore *lc;
-       int i;
+       unsigned long dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
 
-        if (smptrap)
-                return;
-        smptrap=1;
+       if (end <= dma_pfn)
+               zholes_size[ZONE_DMA] += end - start + 1;
+       else if (start > dma_pfn)
+               zholes_size[ZONE_NORMAL] += end - start + 1;
+       else {
+               zholes_size[ZONE_DMA] += dma_pfn - start + 1;
+               zholes_size[ZONE_NORMAL] += end - dma_pfn;
+       }
+}
 
-        /*
-         * print what head.S has found out about the machine 
-         */
-#ifndef CONFIG_ARCH_S390X
-       printk((MACHINE_IS_VM) ?
-              "We are running under VM (31 bit mode)\n" :
-              "We are running native (31 bit mode)\n");
-       printk((MACHINE_HAS_IEEE) ?
-              "This machine has an IEEE fpu\n" :
-              "This machine has no IEEE fpu\n");
-#else /* CONFIG_ARCH_S390X */
-       printk((MACHINE_IS_VM) ?
-              "We are running under VM (64 bit mode)\n" :
-              "We are running native (64 bit mode)\n");
-#endif /* CONFIG_ARCH_S390X */
+static void __init
+parse_cmdline_early(char **cmdline_p)
+{
+       char c = ' ', cn, *to = command_line, *from = COMMAND_LINE;
+       unsigned long delay = 0;
 
-        ROOT_DEV = Root_RAM0;
-        memory_start = (unsigned long) &_end;    /* fixit if use $CODELO etc*/
-#ifndef CONFIG_ARCH_S390X
-       memory_end = memory_size & ~0x400000UL;  /* align memory end to 4MB */
-        /*
-         * We need some free virtual space to be able to do vmalloc.
-         * On a machine with 2GB memory we make sure that we have at
-         * least 128 MB free space for vmalloc.
-         */
-        if (memory_end > 1920*1024*1024)
-                memory_end = 1920*1024*1024;
-#else /* CONFIG_ARCH_S390X */
-       memory_end = memory_size & ~0x200000UL;  /* detected in head.s */
-#endif /* CONFIG_ARCH_S390X */
-        init_mm.start_code = PAGE_OFFSET;
-        init_mm.end_code = (unsigned long) &_etext;
-        init_mm.end_data = (unsigned long) &_edata;
-        init_mm.brk = (unsigned long) &_end;
-
-       code_resource.start = (unsigned long) &_text;
-       code_resource.end = (unsigned long) &_etext - 1;
-       data_resource.start = (unsigned long) &_etext;
-       data_resource.end = (unsigned long) &_edata - 1;
-
-        /* Save unparsed command line copy for /proc/cmdline */
-        memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-        saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
-
-        for (;;) {
-                /*
-                 * "mem=XXX[kKmM]" sets memsize 
-                 */
-                if (c == ' ' && strncmp(from, "mem=", 4) == 0) {
-                        memory_end = simple_strtoul(from+4, &from, 0);
-                        if ( *from == 'K' || *from == 'k' ) {
-                                memory_end = memory_end << 10;
-                                from++;
-                        } else if ( *from == 'M' || *from == 'm' ) {
-                                memory_end = memory_end << 20;
-                                from++;
-                        }
-                }
-                /*
-                 * "ipldelay=XXX[sm]" sets ipl delay in seconds or minutes
-                 */
-                if (c == ' ' && strncmp(from, "ipldelay=", 9) == 0) {
-                        delay = simple_strtoul(from+9, &from, 0);
+       /* Save unparsed command line copy for /proc/cmdline */
+       memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+       saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+
+       for (;;) {
+               /*
+                * "mem=XXX[kKmM]" sets memsize
+                */
+               if (c == ' ' && strncmp(from, "mem=", 4) == 0) {
+                       memory_end = simple_strtoul(from+4, &from, 0);
+                       if ( *from == 'K' || *from == 'k' ) {
+                               memory_end = memory_end << 10;
+                               from++;
+                       } else if ( *from == 'M' || *from == 'm' ) {
+                               memory_end = memory_end << 20;
+                               from++;
+                       }
+               }
+               /*
+                * "ipldelay=XXX[sm]" sets ipl delay in seconds or minutes
+                */
+               if (c == ' ' && strncmp(from, "ipldelay=", 9) == 0) {
+                       delay = simple_strtoul(from+9, &from, 0);
                        if (*from == 's' || *from == 'S') {
                                delay = delay*1000000;
                                from++;
@@ -403,24 +370,110 @@
                        }
                        /* now wait for the requested amount of time */
                        udelay(delay);
-                }
-                cn = *(from++);
-                if (!cn)
-                        break;
-                if (cn == '\n')
-                        cn = ' ';  /* replace newlines with space */
+               }
+               cn = *(from++);
+               if (!cn)
+                       break;
+               if (cn == '\n')
+                       cn = ' ';  /* replace newlines with space */
                if (cn == 0x0d)
                        cn = ' ';  /* replace 0x0d with space */
-                if (cn == ' ' && c == ' ')
-                        continue;  /* remove additional spaces */
-                c = cn;
-                if (to - command_line >= COMMAND_LINE_SIZE)
-                        break;
-                *(to++) = c;
-        }
-        if (c == ' ' && to > command_line) to--;
-        *to = '\0';
-        *cmdline_p = command_line;
+               if (cn == ' ' && c == ' ')
+                       continue;  /* remove additional spaces */
+               c = cn;
+               if (to - command_line >= COMMAND_LINE_SIZE)
+                       break;
+               *(to++) = c;
+       }
+       if (c == ' ' && to > command_line) to--;
+       *to = '\0';
+       *cmdline_p = command_line;
+}
+
+static void __init
+setup_lowcore(void)
+{
+       struct _lowcore *lc;
+       int lc_pages;
+
+       /*
+        * Setup lowcore for boot cpu
+        */
+       lc_pages = sizeof(void *) == 8 ? 2 : 1;
+       lc = (struct _lowcore *)
+               __alloc_bootmem(lc_pages * PAGE_SIZE, lc_pages * PAGE_SIZE, 0);
+       memset(lc, 0, lc_pages * PAGE_SIZE);
+       lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+       lc->restart_psw.addr =
+               PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
+       lc->external_new_psw.mask = PSW_KERNEL_BITS;
+       lc->external_new_psw.addr =
+               PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
+       lc->svc_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT;
+       lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
+       lc->program_new_psw.mask = PSW_KERNEL_BITS;
+       lc->program_new_psw.addr =
+               PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
+       lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
+       lc->mcck_new_psw.addr =
+               PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
+       lc->io_new_psw.mask = PSW_KERNEL_BITS;
+       lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
+       lc->ipl_device = S390_lowcore.ipl_device;
+       lc->jiffy_timer = -1LL;
+       lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
+       lc->async_stack = (unsigned long)
+               __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
+#ifdef CONFIG_CHECK_STACK
+       lc->panic_stack = (unsigned long)
+               __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
+#endif
+       lc->current_task = (unsigned long) init_thread_union.thread_info.task;
+       lc->thread_info = (unsigned long) &init_thread_union;
+#ifdef CONFIG_ARCH_S390X
+       if (MACHINE_HAS_DIAG44)
+               lc->diag44_opcode = 0x83000044;
+       else
+               lc->diag44_opcode = 0x07000700;
+#endif /* CONFIG_ARCH_S390X */
+       set_prefix((u32)(unsigned long) lc);
+}
+
+static void __init
+setup_resources(void)
+{
+       struct resource *res;
+       int i;
+
+       for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+               res = alloc_bootmem_low(sizeof(struct resource));
+               res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+               switch (memory_chunk[i].type) {
+               case CHUNK_READ_WRITE:
+                       res->name = "System RAM";
+                       break;
+               case CHUNK_READ_ONLY:
+                       res->name = "System ROM";
+                       res->flags |= IORESOURCE_READONLY;
+                       break;
+               default:
+                       res->name = "reserved";
+               }
+               res->start = memory_chunk[i].addr;
+               res->end = memory_chunk[i].addr +  memory_chunk[i].size - 1;
+               request_resource(&iomem_resource, res);
+               request_resource(res, &code_resource);
+               request_resource(res, &data_resource);
+       }
+}
+
+static void __init
+setup_memory(void)
+{
+        unsigned long bootmap_size;
+       unsigned long start_pfn, end_pfn, init_pfn;
+       unsigned long last_rw_end;
+       int i;
 
        /*
         * partially used pages are not usable - thus
@@ -429,6 +482,10 @@
        start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT;
        end_pfn = max_pfn = memory_end >> PAGE_SHIFT;
 
+       /* Initialize storage key for kernel pages */
+       for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++)
+               page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
+
        /*
         * Initialize the boot-time allocator (with low memory only):
         */
@@ -437,7 +494,9 @@
        /*
         * Register RAM areas with the bootmem allocator.
         */
-       for (i = 0; i < 16 && memory_chunk[i].size > 0; i++) {
+       last_rw_end = start_pfn;
+
+       for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
                unsigned long start_chunk, end_chunk;
 
                if (memory_chunk[i].type != CHUNK_READ_WRITE)
@@ -450,102 +509,98 @@
                        start_chunk = start_pfn;
                if (end_chunk > end_pfn)
                        end_chunk = end_pfn;
-               if (start_chunk < end_chunk)
+               if (start_chunk < end_chunk) {
+                       /* Initialize storage key for RAM pages */
+                       for (init_pfn = start_chunk ; init_pfn < end_chunk;
+                            init_pfn++)
+                               page_set_storage_key(init_pfn << PAGE_SHIFT,
+                                                    PAGE_DEFAULT_KEY);
                        free_bootmem(start_chunk << PAGE_SHIFT,
                                     (end_chunk - start_chunk) << PAGE_SHIFT);
+                       if (last_rw_end < start_chunk)
+                               add_memory_hole(last_rw_end, start_chunk - 1);
+                       last_rw_end = end_chunk;
+               }
        }
 
-        /*
-         * Reserve the bootmem bitmap itself as well. We do this in two
-         * steps (first step was init_bootmem()) because this catches
-         * the (very unlikely) case of us accidentally initializing the
-         * bootmem allocator with an invalid RAM area.
-         */
-        reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size);
+       psw_set_key(PAGE_DEFAULT_KEY);
+
+       if (last_rw_end < end_pfn - 1)
+               add_memory_hole(last_rw_end, end_pfn - 1);
+
+       /*
+        * Reserve the bootmem bitmap itself as well. We do this in two
+        * steps (first step was init_bootmem()) because this catches
+        * the (very unlikely) case of us accidentally initializing the
+        * bootmem allocator with an invalid RAM area.
+        */
+       reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size);
 
 #ifdef CONFIG_BLK_DEV_INITRD
-        if (INITRD_START) {
+       if (INITRD_START) {
                if (INITRD_START + INITRD_SIZE <= memory_end) {
                        reserve_bootmem(INITRD_START, INITRD_SIZE);
                        initrd_start = INITRD_START;
                        initrd_end = initrd_start + INITRD_SIZE;
                } else {
-                        printk("initrd extends beyond end of memory "
-                               "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
-                               initrd_start + INITRD_SIZE, memory_end);
-                        initrd_start = initrd_end = 0;
+                       printk("initrd extends beyond end of memory "
+                              "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+                              initrd_start + INITRD_SIZE, memory_end);
+                       initrd_start = initrd_end = 0;
                }
-        }
+       }
 #endif
+}
 
-       for (i = 0; i < 16 && memory_chunk[i].size > 0; i++) {
-               struct resource *res;
-
-               res = alloc_bootmem_low(sizeof(struct resource));
-               res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
-
-               switch (memory_chunk[i].type) {
-               case CHUNK_READ_WRITE:
-                       res->name = "System RAM";
-                       break;
-               case CHUNK_READ_ONLY:
-                       res->name = "System ROM";
-                       res->flags |= IORESOURCE_READONLY;
-                       break;
-               default:
-                       res->name = "reserved";
-               }
-               res->start = memory_chunk[i].addr;
-               res->end = memory_chunk[i].addr +  memory_chunk[i].size - 1;
-               request_resource(&iomem_resource, res);
-               request_resource(res, &code_resource);
-               request_resource(res, &data_resource);
-       }
+/*
+ * Setup function called from init/main.c just after the banner
+ * was printed.
+ */
 
+void __init
+setup_arch(char **cmdline_p)
+{
         /*
-         * Setup lowcore for boot cpu
+         * print what head.S has found out about the machine
          */
 #ifndef CONFIG_ARCH_S390X
-       lc = (struct _lowcore *) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
-       memset(lc, 0, PAGE_SIZE);
+       printk((MACHINE_IS_VM) ?
+              "We are running under VM (31 bit mode)\n" :
+              "We are running native (31 bit mode)\n");
+       printk((MACHINE_HAS_IEEE) ?
+              "This machine has an IEEE fpu\n" :
+              "This machine has no IEEE fpu\n");
 #else /* CONFIG_ARCH_S390X */
-       lc = (struct _lowcore *) __alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0);
-       memset(lc, 0, 2*PAGE_SIZE);
+       printk((MACHINE_IS_VM) ?
+              "We are running under VM (64 bit mode)\n" :
+              "We are running native (64 bit mode)\n");
 #endif /* CONFIG_ARCH_S390X */
-       lc->restart_psw.mask = PSW_BASE_BITS;
-       lc->restart_psw.addr =
-               PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
-       lc->external_new_psw.mask = PSW_KERNEL_BITS;
-       lc->external_new_psw.addr =
-               PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
-       lc->svc_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT;
-       lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
-       lc->program_new_psw.mask = PSW_KERNEL_BITS;
-       lc->program_new_psw.addr =
-               PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
-       lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
-       lc->mcck_new_psw.addr =
-               PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
-       lc->io_new_psw.mask = PSW_KERNEL_BITS;
-       lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
-       lc->ipl_device = S390_lowcore.ipl_device;
-       lc->jiffy_timer = -1LL;
-       lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
-       lc->async_stack = (unsigned long)
-               __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
-#ifdef CONFIG_CHECK_STACK
-       lc->panic_stack = (unsigned long)
-               __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
-#endif
-       lc->current_task = (unsigned long) init_thread_union.thread_info.task;
-       lc->thread_info = (unsigned long) &init_thread_union;
-#ifdef CONFIG_ARCH_S390X
-       if (MACHINE_HAS_DIAG44)
-               lc->diag44_opcode = 0x83000044;
-       else
-               lc->diag44_opcode = 0x07000700;
+
+        ROOT_DEV = Root_RAM0;
+#ifndef CONFIG_ARCH_S390X
+       memory_end = memory_size & ~0x400000UL;  /* align memory end to 4MB */
+        /*
+         * We need some free virtual space to be able to do vmalloc.
+         * On a machine with 2GB memory we make sure that we have at
+         * least 128 MB free space for vmalloc.
+         */
+        if (memory_end > 1920*1024*1024)
+                memory_end = 1920*1024*1024;
+#else /* CONFIG_ARCH_S390X */
+       memory_end = memory_size & ~0x200000UL;  /* detected in head.s */
 #endif /* CONFIG_ARCH_S390X */
-       set_prefix((u32)(unsigned long) lc);
+
+       init_mm.start_code = PAGE_OFFSET;
+       init_mm.end_code = (unsigned long) &_etext;
+       init_mm.end_data = (unsigned long) &_edata;
+       init_mm.brk = (unsigned long) &_end;
+
+       parse_cmdline_early(cmdline_p);
+
+       setup_memory();
+       setup_resources();
+       setup_lowcore();
+
         cpu_init();
         __cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
 
diff -urN linux/arch/s390/kernel/time.c linux/arch/s390/kernel/time.c
--- linux/arch/s390/kernel/time.c       2005/04/08 18:58:03     1.27
+++ linux/arch/s390/kernel/time.c       2005/05/19 12:08:15     1.28
@@ -244,7 +244,7 @@
  */
 static inline void stop_hz_timer(void)
 {
-       __u64 timer;
+       __u64 timer, todval;
 
        if (sysctl_hz_timer != 0)
                return;
@@ -265,8 +265,14 @@
         * for the next event.
         */
        timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
-       timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
-       asm volatile ("SCKC %0" : : "m" (timer));
+       todval = -1ULL;
+       /* Be careful about overflows. */
+       if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
+               timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
+               if (timer >= jiffies_timer_cc)
+                       todval = timer;
+       }
+       asm volatile ("SCKC %0" : : "m" (todval));
 }
 
 /*
diff -urN linux/arch/s390/kernel/vtime.c linux/arch/s390/kernel/vtime.c
--- linux/arch/s390/kernel/vtime.c      2005/04/08 18:58:03     1.4
+++ linux/arch/s390/kernel/vtime.c      2005/05/19 12:08:15     1.5
@@ -122,12 +122,17 @@
        struct vtimer_queue *vt_list;
 
        vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
-       set_vtimer(vt_list->idle);
+
+       /* CPU timer interrupt is pending, don't reprogramm it */
+       if (vt_list->idle & 1LL<<63)
+               return;
+
+       if (!list_empty(&vt_list->list))
+               set_vtimer(vt_list->idle);
 }
 
 static void stop_cpu_timer(void)
 {
-       __u64 done;
        struct vtimer_queue *vt_list;
 
        vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
@@ -138,21 +143,17 @@
                goto fire;
        }
 
-       /* store progress */
-       asm volatile ("STPT %0" : "=m" (done));
+       /* store the actual expire value */
+       asm volatile ("STPT %0" : "=m" (vt_list->idle));
 
        /*
-        * If done is negative we do not stop the CPU timer
-        * because we will get instantly an interrupt that
-        * will start the CPU timer again.
+        * If the CPU timer is negative we don't reprogramm
+        * it because we will get instantly an interrupt.
         */
-       if (done & 1LL<<63)
+       if (vt_list->idle & 1LL<<63)
                return;
-       else
-               vt_list->offset += vt_list->to_expire - done;
 
-       /* save the actual expire value */
-       vt_list->idle = done;
+       vt_list->offset += vt_list->to_expire - vt_list->idle;
 
        /*
         * We cannot halt the CPU timer, we just write a value that
diff -urN linux/arch/s390/mm/cmm.c linux/arch/s390/mm/cmm.c
--- linux/arch/s390/mm/cmm.c    2005/02/13 20:16:19     1.5
+++ linux/arch/s390/mm/cmm.c    2005/05/19 12:08:15     1.6
@@ -20,6 +20,11 @@
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
 
+static char *sender = "VMRMSVM";
+module_param(sender, charp, 0);
+MODULE_PARM_DESC(sender,
+                "Guest name that may send SMSG messages (default VMRMSVM)");
+
 #include "../../../drivers/s390/net/smsgiucv.h"
 
 #define CMM_NR_PAGES ((PAGE_SIZE / sizeof(unsigned long)) - 2)
@@ -367,10 +372,12 @@
 #ifdef CONFIG_CMM_IUCV
 #define SMSG_PREFIX "CMM"
 static void
-cmm_smsg_target(char *msg)
+cmm_smsg_target(char *from, char *msg)
 {
        long pages, seconds;
 
+       if (strlen(sender) > 0 && strcmp(from, sender) != 0)
+               return;
        if (!cmm_skip_blanks(msg + strlen(SMSG_PREFIX), &msg))
                return;
        if (strncmp(msg, "SHRINK", 6) == 0) {
diff -urN linux/arch/s390/mm/init.c linux/arch/s390/mm/init.c
--- linux/arch/s390/mm/init.c   2005/03/18 17:37:01     1.26
+++ linux/arch/s390/mm/init.c   2005/05/19 12:08:15     1.27
@@ -101,6 +101,7 @@
 extern unsigned long __init_begin;
 extern unsigned long __init_end;
 
+extern unsigned long __initdata zholes_size[];
 /*
  * paging_init() sets up the page tables
  */
@@ -163,10 +164,13 @@
         local_flush_tlb();
 
        {
-               unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0};
+               unsigned long zones_size[MAX_NR_ZONES];
 
+               memset(zones_size, 0, sizeof(zones_size));
                zones_size[ZONE_DMA] = max_low_pfn;
-               free_area_init(zones_size);
+               free_area_init_node(0, &contig_page_data, zones_size,
+                                   __pa(PAGE_OFFSET) >> PAGE_SHIFT,
+                                   zholes_size);
        }
         return;
 }
@@ -184,9 +188,10 @@
           _KERN_REGION_TABLE;
        static const int ssm_mask = 0x04000000L;
 
-       unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+       unsigned long zones_size[MAX_NR_ZONES];
        unsigned long dma_pfn, high_pfn;
 
+       memset(zones_size, 0, sizeof(zones_size));
        dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
        high_pfn = max_low_pfn;
 
@@ -198,8 +203,8 @@
        }
 
        /* Initialize mem_map[].  */
-       free_area_init(zones_size);
-
+       free_area_init_node(0, &contig_page_data, zones_size,
+                           __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
 
        /*
         * map whole physical memory to virtual memory (identity mapping) 
diff -urN linux/arch/sh/Kconfig linux/arch/sh/Kconfig
--- linux/arch/sh/Kconfig       2005/04/08 18:58:03     1.29
+++ linux/arch/sh/Kconfig       2005/05/19 12:08:15     1.30
@@ -693,6 +693,10 @@
 
 endmenu
 
+config ISA_DMA_API
+       bool
+       depends on MPC1211
+       default y
 
 menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
 
diff -urN linux/arch/sh/kernel/ptrace.c linux/arch/sh/kernel/ptrace.c
--- linux/arch/sh/kernel/ptrace.c       2005/03/18 17:37:02     1.16
+++ linux/arch/sh/kernel/ptrace.c       2005/05/19 12:08:15     1.17
@@ -20,6 +20,7 @@
 #include <linux/user.h>
 #include <linux/slab.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -197,7 +198,7 @@
        case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall 
*/
        case PTRACE_CONT: { /* restart after signal. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                if (request == PTRACE_SYSCALL)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -228,7 +229,7 @@
                struct pt_regs *dummy = NULL;
 
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                if ((child->ptrace & PT_DTRACE) == 0) {
diff -urN linux/arch/sh64/kernel/ptrace.c linux/arch/sh64/kernel/ptrace.c
--- linux/arch/sh64/kernel/ptrace.c     2005/03/18 17:37:03     1.6
+++ linux/arch/sh64/kernel/ptrace.c     2005/05/19 12:08:15     1.7
@@ -27,6 +27,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/signal.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -255,7 +256,7 @@
        case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall 
*/
        case PTRACE_CONT: { /* restart after signal. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                if (request == PTRACE_SYSCALL)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -285,7 +286,7 @@
                struct pt_regs *regs;
 
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                if ((child->ptrace & PT_DTRACE) == 0) {
diff -urN linux/arch/sh64/kernel/sys_sh64.c linux/arch/sh64/kernel/sys_sh64.c
--- linux/arch/sh64/kernel/sys_sh64.c   2005/03/18 17:37:03     1.3
+++ linux/arch/sh64/kernel/sys_sh64.c   2005/05/19 12:08:15     1.4
@@ -283,18 +283,3 @@
        up_read(&uts_sem);
        return err?-EFAULT:0;
 }
-
-/* Copy from mips version */
-asmlinkage long sys_shmatcall(int shmid, char __user *shmaddr,
-               int shmflg)
-{
-       unsigned long raddr;
-       int err;
-
-       err = do_shmat(shmid, shmaddr, shmflg, &raddr);
-       if (err)
-               return err;
-
-       err = raddr;
-       return err;
-}
diff -urN linux/arch/sh64/kernel/syscalls.S linux/arch/sh64/kernel/syscalls.S
--- linux/arch/sh64/kernel/syscalls.S   2005/03/18 17:37:03     1.2
+++ linux/arch/sh64/kernel/syscalls.S   2005/05/19 12:08:15     1.3
@@ -268,7 +268,7 @@
        .long sys_msgrcv
        .long sys_msgget
        .long sys_msgctl
-       .long sys_shmatcall
+       .long sys_shmat
        .long sys_shmdt                 /* 245 */
        .long sys_shmget
        .long sys_shmctl
diff -urN linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- linux/arch/sparc/kernel/process.c   2005/02/28 15:45:12     1.63
+++ linux/arch/sparc/kernel/process.c   2005/05/19 12:08:15     1.64
@@ -83,9 +83,6 @@
  */
 void cpu_idle(void)
 {
-       if (current->pid != 0)
-               goto out;
-
        /* endless idle loop with no priority at all */
        for (;;) {
                if (ARCH_SUN4C_SUN4) {
@@ -126,8 +123,6 @@
                schedule();
                check_pgt_cache();
        }
-out:
-       return;
 }
 
 #else
@@ -333,6 +328,17 @@
        printk("\n");
 }
 
+void dump_stack(void)
+{
+       unsigned long *ksp;
+
+       __asm__ __volatile__("mov       %%fp, %0"
+                            : "=r" (ksp));
+       show_stack(current, ksp);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
 /*
  * Note: sparc64 has a pretty intricated thread_saved_pc, check it out.
  */
diff -urN linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c
--- linux/arch/sparc/kernel/ptrace.c    2005/04/29 11:15:04     1.32
+++ linux/arch/sparc/kernel/ptrace.c    2005/05/19 12:08:15     1.33
@@ -18,6 +18,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -526,7 +527,7 @@
                addr = 1;
 
        case PTRACE_CONT: { /* restart after signal. */
-               if (data > _NSIG) {
+               if (!valid_signal(data)) {
                        pt_error_return(regs, EIO);
                        goto out_tsk;
                }
diff -urN linux/arch/sparc/kernel/sparc_ksyms.c 
linux/arch/sparc/kernel/sparc_ksyms.c
--- linux/arch/sparc/kernel/sparc_ksyms.c       2005/04/08 18:58:04     1.57
+++ linux/arch/sparc/kernel/sparc_ksyms.c       2005/05/19 12:08:15     1.58
@@ -20,6 +20,7 @@
 #include <linux/in6.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
+#include <linux/syscalls.h>
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
 #endif
@@ -89,6 +90,9 @@
 extern void ___set_bit(void);
 extern void ___clear_bit(void);
 extern void ___change_bit(void);
+extern void ___rw_read_enter(void);
+extern void ___rw_read_exit(void);
+extern void ___rw_write_enter(void);
 
 /* Alias functions whose names begin with "." and export the aliases.
  * The module references will be fixed up by module_frob_arch_sections.
@@ -121,9 +125,9 @@
 #endif
 #else
 // XXX find what uses (or used) these.
-// EXPORT_SYMBOL_PRIVATE(_rw_read_enter);
-// EXPORT_SYMBOL_PRIVATE(_rw_read_exit);
-// EXPORT_SYMBOL_PRIVATE(_rw_write_enter);
+EXPORT_SYMBOL(___rw_read_enter);
+EXPORT_SYMBOL(___rw_read_exit);
+EXPORT_SYMBOL(___rw_write_enter);
 #endif
 /* semaphores */
 EXPORT_SYMBOL(__up);
@@ -144,6 +148,9 @@
 EXPORT_SYMBOL(___clear_bit);
 EXPORT_SYMBOL(___change_bit);
 
+/* Per-CPU information table */
+EXPORT_PER_CPU_SYMBOL(__cpu_data);
+
 #ifdef CONFIG_SMP
 /* IRQ implementation. */
 EXPORT_SYMBOL(synchronize_irq);
@@ -151,6 +158,10 @@
 /* Misc SMP information */
 EXPORT_SYMBOL(__cpu_number_map);
 EXPORT_SYMBOL(__cpu_logical_map);
+
+/* CPU online map and active count. */
+EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(phys_cpu_present_map);
 #endif
 
 EXPORT_SYMBOL(__udelay);
@@ -332,3 +343,6 @@
 
 /* Sun Power Management Idle Handler */
 EXPORT_SYMBOL(pm_idle);
+
+/* Binfmt_misc needs this */
+EXPORT_SYMBOL(sys_close);
diff -urN linux/arch/sparc/prom/memory.c linux/arch/sparc/prom/memory.c
--- linux/arch/sparc/prom/memory.c      2004/06/06 02:12:41     1.7
+++ linux/arch/sparc/prom/memory.c      2005/05/19 12:08:16     1.8
@@ -47,9 +47,9 @@
        char *tmpaddr;
        char *lowest;
 
-       for(i=0; thislist[i].theres_more != 0; i++) {
+       for(i=0; thislist[i].theres_more; i++) {
                lowest = thislist[i].start_adr;
-               for(mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++)
+               for(mitr = i+1; thislist[mitr-1].theres_more; mitr++)
                        if(thislist[mitr].start_adr < lowest) {
                                lowest = thislist[mitr].start_adr;
                                swapi = mitr;
@@ -85,7 +85,7 @@
                        prom_phys_total[iter].num_bytes = mptr->num_bytes;
                        prom_phys_total[iter].theres_more = 
&prom_phys_total[iter+1];
                }
-               prom_phys_total[iter-1].theres_more = 0x0;
+               prom_phys_total[iter-1].theres_more = NULL;
                /* Second, the total prom taken descriptors. */
                for(mptr = (*(romvec->pv_v0mem.v0_prommap)), iter=0;
                    mptr; mptr=mptr->theres_more, iter++) {
@@ -93,7 +93,7 @@
                        prom_prom_taken[iter].num_bytes = mptr->num_bytes;
                        prom_prom_taken[iter].theres_more = 
&prom_prom_taken[iter+1];
                }
-               prom_prom_taken[iter-1].theres_more = 0x0;
+               prom_prom_taken[iter-1].theres_more = NULL;
                /* Last, the available physical descriptors. */
                for(mptr = (*(romvec->pv_v0mem.v0_available)), iter=0;
                    mptr; mptr=mptr->theres_more, iter++) {
@@ -101,7 +101,7 @@
                        prom_phys_avail[iter].num_bytes = mptr->num_bytes;
                        prom_phys_avail[iter].theres_more = 
&prom_phys_avail[iter+1];
                }
-               prom_phys_avail[iter-1].theres_more = 0x0;
+               prom_phys_avail[iter-1].theres_more = NULL;
                /* Sort all the lists. */
                prom_sortmemlist(prom_phys_total);
                prom_sortmemlist(prom_prom_taken);
@@ -124,7 +124,7 @@
                        prom_phys_avail[iter].theres_more =
                                &prom_phys_avail[iter+1];
                }
-               prom_phys_avail[iter-1].theres_more = 0x0;
+               prom_phys_avail[iter-1].theres_more = NULL;
 
                num_regs = prom_getproperty(node, "reg",
                                            (char *) prom_reg_memlist,
@@ -138,7 +138,7 @@
                        prom_phys_total[iter].theres_more =
                                &prom_phys_total[iter+1];
                }
-               prom_phys_total[iter-1].theres_more = 0x0;
+               prom_phys_total[iter-1].theres_more = NULL;
 
                node = prom_getchild(prom_root_node);
                node = prom_searchsiblings(node, "virtual-memory");
@@ -158,7 +158,7 @@
                        prom_prom_taken[iter].theres_more =
                                &prom_prom_taken[iter+1];
                }
-               prom_prom_taken[iter-1].theres_more = 0x0;
+               prom_prom_taken[iter-1].theres_more = NULL;
 
                prom_sortmemlist(prom_prom_taken);
 
@@ -182,15 +182,15 @@
        case PROM_SUN4:
 #ifdef CONFIG_SUN4     
                /* how simple :) */
-               prom_phys_total[0].start_adr = 0x0;
+               prom_phys_total[0].start_adr = NULL;
                prom_phys_total[0].num_bytes = *(sun4_romvec->memorysize);
-               prom_phys_total[0].theres_more = 0x0;
-               prom_prom_taken[0].start_adr = 0x0; 
+               prom_phys_total[0].theres_more = NULL;
+               prom_prom_taken[0].start_adr = NULL; 
                prom_prom_taken[0].num_bytes = 0x0;
-               prom_prom_taken[0].theres_more = 0x0;
-               prom_phys_avail[0].start_adr = 0x0;
+               prom_prom_taken[0].theres_more = NULL;
+               prom_phys_avail[0].start_adr = NULL;
                prom_phys_avail[0].num_bytes = *(sun4_romvec->memoryavail);
-               prom_phys_avail[0].theres_more = 0x0;
+               prom_phys_avail[0].theres_more = NULL;
 #endif
                break;
 
diff -urN linux/arch/sparc/prom/sun4prom.c linux/arch/sparc/prom/sun4prom.c
--- linux/arch/sparc/prom/sun4prom.c    1999/10/09 00:01:06     1.2
+++ linux/arch/sparc/prom/sun4prom.c    2005/05/19 12:08:16     1.3
@@ -151,7 +151,7 @@
         * have more time, we can teach the penguin to say "By your
         * command" or "Activating turbo boost, Michael". :-)
         */
-       sun4_romvec->setLEDs(0x0);
+       sun4_romvec->setLEDs(NULL);
        
        printk("PROMLIB: Old Sun4 boot PROM monitor %s, romvec version %d\n",
                sun4_romvec->monid,
diff -urN linux/arch/sparc64/Kconfig linux/arch/sparc64/Kconfig
--- linux/arch/sparc64/Kconfig  2005/04/08 18:58:04     1.42
+++ linux/arch/sparc64/Kconfig  2005/05/19 12:08:16     1.43
@@ -118,6 +118,7 @@
 
 config HW_CONSOLE
        bool
+       depends on VT
        default y
 
 config SMP
diff -urN linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- linux/arch/sparc64/kernel/irq.c     2005/03/18 17:37:04     1.59
+++ linux/arch/sparc64/kernel/irq.c     2005/05/19 12:08:16     1.60
@@ -756,7 +756,7 @@
                clear_softint(clr_mask);
        }
 #else
-       int should_forward = 1;
+       int should_forward = 0;
 
        clear_softint(1 << irq);
 #endif
@@ -1007,10 +1007,10 @@
        }
        upa_writel(tid | IMAP_VALID, imap);
 
-       while (!cpu_online(goal_cpu)) {
+       do {
                if (++goal_cpu >= NR_CPUS)
                        goal_cpu = 0;
-       }
+       } while (!cpu_online(goal_cpu));
 
        return goal_cpu;
 }
diff -urN linux/arch/sparc64/kernel/process.c 
linux/arch/sparc64/kernel/process.c
--- linux/arch/sparc64/kernel/process.c 2005/02/13 20:16:19     1.74
+++ linux/arch/sparc64/kernel/process.c 2005/05/19 12:08:16     1.75
@@ -62,9 +62,6 @@
  */
 void cpu_idle(void)
 {
-       if (current->pid != 0)
-               return;
-
        /* endless idle loop with no priority at all */
        for (;;) {
                /* If current->work.need_resched is zero we should really
@@ -80,7 +77,6 @@
                schedule();
                check_pgt_cache();
        }
-       return;
 }
 
 #else
diff -urN linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c
--- linux/arch/sparc64/kernel/ptrace.c  2005/04/29 11:15:04     1.35
+++ linux/arch/sparc64/kernel/ptrace.c  2005/05/19 12:08:16     1.36
@@ -19,6 +19,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/asi.h>
 #include <asm/pgtable.h>
@@ -559,7 +560,7 @@
                addr = 1;
 
        case PTRACE_CONT: { /* restart after signal. */
-               if (data > _NSIG) {
+               if (!valid_signal(data)) {
                        pt_error_return(regs, EIO);
                        goto out_tsk;
                }
diff -urN linux/arch/sparc64/kernel/sparc64_ksyms.c 
linux/arch/sparc64/kernel/sparc64_ksyms.c
--- linux/arch/sparc64/kernel/sparc64_ksyms.c   2005/04/08 18:58:04     1.86
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c   2005/05/19 12:08:16     1.87
@@ -278,7 +278,7 @@
 
 EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(__pte_alloc_one_kernel);
+EXPORT_SYMBOL(pte_alloc_one_kernel);
 #ifndef CONFIG_SMP
 EXPORT_SYMBOL(pgt_quicklists);
 #endif
diff -urN linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- linux/arch/sparc64/kernel/time.c    2005/03/18 17:37:04     1.60
+++ linux/arch/sparc64/kernel/time.c    2005/05/19 12:08:16     1.61
@@ -48,7 +48,7 @@
 
 DEFINE_SPINLOCK(mostek_lock);
 DEFINE_SPINLOCK(rtc_lock);
-unsigned long mstk48t02_regs = 0UL;
+void __iomem *mstk48t02_regs = NULL;
 #ifdef CONFIG_PCI
 unsigned long ds1287_regs = 0UL;
 #endif
@@ -59,8 +59,8 @@
 
 EXPORT_SYMBOL(jiffies_64);
 
-static unsigned long mstk48t08_regs = 0UL;
-static unsigned long mstk48t59_regs = 0UL;
+static void __iomem *mstk48t08_regs;
+static void __iomem *mstk48t59_regs;
 
 static int set_rtc_mmss(unsigned long);
 
@@ -520,7 +520,7 @@
 /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
 static void __init kick_start_clock(void)
 {
-       unsigned long regs = mstk48t02_regs;
+       void __iomem *regs = mstk48t02_regs;
        u8 sec, tmp;
        int i, count;
 
@@ -604,7 +604,7 @@
 /* Return nonzero if the clock chip battery is low. */
 static int __init has_low_battery(void)
 {
-       unsigned long regs = mstk48t02_regs;
+       void __iomem *regs = mstk48t02_regs;
        u8 data1, data2;
 
        spin_lock_irq(&mostek_lock);
@@ -623,7 +623,7 @@
 static void __init set_system_time(void)
 {
        unsigned int year, mon, day, hour, min, sec;
-       unsigned long mregs = mstk48t02_regs;
+       void __iomem *mregs = mstk48t02_regs;
 #ifdef CONFIG_PCI
        unsigned long dregs = ds1287_regs;
 #else
@@ -843,7 +843,8 @@
                            !strcmp(model, "m5823")) {
                                ds1287_regs = edev->resource[0].start;
                        } else {
-                               mstk48t59_regs = edev->resource[0].start;
+                               mstk48t59_regs = (void __iomem *)
+                                       edev->resource[0].start;
                                mstk48t02_regs = mstk48t59_regs + 
MOSTEK_48T59_48T02;
                        }
                        break;
@@ -865,7 +866,8 @@
                            !strcmp(model, "m5823")) {
                                ds1287_regs = isadev->resource.start;
                        } else {
-                               mstk48t59_regs = isadev->resource.start;
+                               mstk48t59_regs = (void __iomem *)
+                                       isadev->resource.start;
                                mstk48t02_regs = mstk48t59_regs + 
MOSTEK_48T59_48T02;
                        }
                        break;
@@ -893,21 +895,24 @@
                }
 
                if(model[5] == '0' && model[6] == '2') {
-                       mstk48t02_regs = (((u64)clk_reg[0].phys_addr) |
-                                         (((u64)clk_reg[0].which_io)<<32UL));
+                       mstk48t02_regs = (void __iomem *)
+                               (((u64)clk_reg[0].phys_addr) |
+                                (((u64)clk_reg[0].which_io)<<32UL));
                } else if(model[5] == '0' && model[6] == '8') {
-                       mstk48t08_regs = (((u64)clk_reg[0].phys_addr) |
-                                         (((u64)clk_reg[0].which_io)<<32UL));
+                       mstk48t08_regs = (void __iomem *)
+                               (((u64)clk_reg[0].phys_addr) |
+                                (((u64)clk_reg[0].which_io)<<32UL));
                        mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
                } else {
-                       mstk48t59_regs = (((u64)clk_reg[0].phys_addr) |
-                                         (((u64)clk_reg[0].which_io)<<32UL));
+                       mstk48t59_regs = (void __iomem *)
+                               (((u64)clk_reg[0].phys_addr) |
+                                (((u64)clk_reg[0].which_io)<<32UL));
                        mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
                }
                break;
        }
 
-       if (mstk48t02_regs != 0UL) {
+       if (mstk48t02_regs != NULL) {
                /* Report a low battery voltage condition. */
                if (has_low_battery())
                        prom_printf("NVRAM: Low battery voltage!\n");
@@ -1087,7 +1092,7 @@
 static int set_rtc_mmss(unsigned long nowtime)
 {
        int real_seconds, real_minutes, chip_minutes;
-       unsigned long mregs = mstk48t02_regs;
+       void __iomem *mregs = mstk48t02_regs;
 #ifdef CONFIG_PCI
        unsigned long dregs = ds1287_regs;
 #else
diff -urN linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- linux/arch/sparc64/mm/init.c        2005/04/29 11:15:04     1.89
+++ linux/arch/sparc64/mm/init.c        2005/05/19 12:08:16     1.90
@@ -1114,7 +1114,7 @@
 #else
 #define DC_ALIAS_SHIFT 0
 #endif
-pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
        struct page *page;
        unsigned long color;
diff -urN linux/arch/um/Kconfig linux/arch/um/Kconfig
--- linux/arch/um/Kconfig       2005/04/08 18:58:06     1.18
+++ linux/arch/um/Kconfig       2005/05/19 12:08:16     1.19
@@ -244,6 +244,7 @@
 
 config HIGHMEM
        bool "Highmem support"
+       depends on !64BIT
 
 config KERNEL_STACK_ORDER
        int "Kernel stack size order"
diff -urN linux/arch/um/Kconfig_i386 linux/arch/um/Kconfig_i386
--- linux/arch/um/Kconfig_i386  2005/02/13 20:16:20     1.2
+++ linux/arch/um/Kconfig_i386  2005/05/19 12:08:16     1.3
@@ -1,4 +1,8 @@
-config 64_BIT
+config UML_X86
+       bool
+       default y
+
+config 64BIT
        bool
        default n
 
diff -urN linux/arch/um/Kconfig_x86_64 linux/arch/um/Kconfig_x86_64
--- linux/arch/um/Kconfig_x86_64        2005/02/13 20:16:20     1.2
+++ linux/arch/um/Kconfig_x86_64        2005/05/19 12:08:16     1.3
@@ -1,4 +1,8 @@
-config 64_BIT
+config UML_X86
+       bool
+       default y
+
+config 64BIT
        bool
        default y
 
diff -urN linux/arch/um/Makefile linux/arch/um/Makefile
--- linux/arch/um/Makefile      2005/03/18 17:37:05     1.21
+++ linux/arch/um/Makefile      2005/05/19 12:08:16     1.22
@@ -17,7 +17,7 @@
 
 # Have to precede the include because the included Makefiles reference them.
 SYMLINK_HEADERS := archparam.h system.h sigcontext.h processor.h ptrace.h \
-       arch-signal.h module.h vm-flags.h
+       module.h vm-flags.h elf.h
 SYMLINK_HEADERS := $(foreach 
header,$(SYMLINK_HEADERS),include/asm-um/$(header))
 
 # XXX: The "os" symlink is only used by arch/um/include/os.h, which includes
@@ -44,6 +44,11 @@
 endif
 
 ARCH_INCLUDE   := -I$(ARCH_DIR)/include
+ifneq ($(KBUILD_SRC),)
+ARCH_INCLUDE   += -I$(ARCH_DIR)/include2
+ARCH_INCLUDE   += -I$(srctree)/$(ARCH_DIR)/include
+MRPROPER_DIRS  += $(ARCH_DIR)/include2
+endif
 SYS_DIR                := $(ARCH_DIR)/include/sysdep-$(SUBARCH)
 
 include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
@@ -94,17 +99,18 @@
   echo '                  find in the kernel root.'
 endef
 
+ifneq ($(KBUILD_SRC),)
+$(shell mkdir -p $(ARCH_DIR) && ln -fsn 
$(srctree)/$(ARCH_DIR)/Kconfig_$(SUBARCH) $(ARCH_DIR)/Kconfig_arch)
+CLEAN_FILES += $(ARCH_DIR)/Kconfig_arch
+else
 $(shell cd $(ARCH_DIR) && ln -sf Kconfig_$(SUBARCH) Kconfig_arch)
+endif
 
-prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) \
-       $(ARCH_DIR)/kernel/vmlinux.lds.S
+prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
 
 LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
 
-LD_SCRIPT-$(CONFIG_LD_SCRIPT_STATIC) := uml.lds.S
-LD_SCRIPT-$(CONFIG_LD_SCRIPT_DYN) := dyn.lds.S
-
 CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT
 CONFIG_KERNEL_STACK_ORDER ?= 2
 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
@@ -126,7 +132,7 @@
        $(CC) $(CFLAGS_vmlinux) -o $@ \
        -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
        -Wl,--start-group $(vmlinux-main) -Wl,--end-group \
-       -L/usr/lib -lutil \
+       -lutil \
        $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) \
        FORCE ,$^) ; rm -f linux
 endef
@@ -145,31 +151,42 @@
        @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
                -o -name '*.gcov' \) -type f -print | xargs rm -f
 
-#We need to re-preprocess this when the symlink dest changes.
-#So we touch it when needed.
-$(ARCH_DIR)/kernel/vmlinux.lds.S: FORCE
-       $(Q)if [ "$(shell readlink $@)" != "$(LD_SCRIPT-y)" ]; then \
-               echo '  SYMLINK $@'; \
-               ln -sf $(LD_SCRIPT-y) $@; \
-               touch $@; \
-       fi;
-
 $(SYMLINK_HEADERS):
        @echo '  SYMLINK $@'
+ifneq ($(KBUILD_SRC),)
+       ln -fsn $(srctree)/include/asm-um/$(basename $(notdir 
$@))-$(SUBARCH)$(suffix $@) $@
+else
        $(Q)cd $(TOPDIR)/$(dir $@) ; \
        ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
+endif
 
 include/asm-um/arch:
        @echo '  SYMLINK $@'
+ifneq ($(KBUILD_SRC),)
+       $(Q)mkdir -p include/asm-um
+       $(Q)ln -fsn $(srctree)/include/asm-$(SUBARCH) include/asm-um/arch
+else
        $(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
+endif
 
 $(ARCH_DIR)/include/sysdep:
        @echo '  SYMLINK $@'
+ifneq ($(KBUILD_SRC),)
+       $(Q)mkdir -p $(ARCH_DIR)/include
+       $(Q)mkdir -p $(ARCH_DIR)/include2
+       $(Q)ln -fsn sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep
+       $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) 
$(ARCH_DIR)/include2/sysdep
+else
        $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
+endif
 
 $(ARCH_DIR)/os:
        @echo '  SYMLINK $@'
+ifneq ($(KBUILD_SRC),)
+       $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/os-$(OS) $(ARCH_DIR)/os
+else
        $(Q)cd $(ARCH_DIR) && ln -sf os-$(OS) os
+endif
 
 # Generated files
 define filechk_umlconfig
@@ -179,10 +196,31 @@
 $(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
        $(call filechk,umlconfig)
 
+$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
+       $(CC) $(USER_CFLAGS) -S -o $@ $<
+
+$(ARCH_DIR)/user-offsets.h: $(ARCH_DIR)/user-offsets.s
+       $(call filechk,gen-asm-offsets)
+
+CLEAN_FILES += $(ARCH_DIR)/user-offsets.s  $(ARCH_DIR)/user-offsets.h
+
+$(ARCH_DIR)/kernel-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/kernel-offsets.c \
+                                  $(ARCH_SYMLINKS) \
+                                  $(SYS_DIR)/sc.h \
+                                  include/asm include/linux/version.h \
+                                  include/config/MARKER \
+                                  $(ARCH_DIR)/include/user_constants.h
+       $(CC) $(CFLAGS) $(NOSTDINC_FLAGS) $(CPPFLAGS) -S -o $@ $<
+
+$(ARCH_DIR)/kernel-offsets.h: $(ARCH_DIR)/kernel-offsets.s
+       $(call filechk,gen-asm-offsets)
+
+CLEAN_FILES += $(ARCH_DIR)/kernel-offsets.s  $(ARCH_DIR)/kernel-offsets.h
+
 $(ARCH_DIR)/include/task.h: $(ARCH_DIR)/util/mk_task
        $(call filechk,gen_header)
 
-$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/os/util/mk_user_constants
+$(ARCH_DIR)/include/user_constants.h: 
$(ARCH_DIR)/os-$(OS)/util/mk_user_constants
        $(call filechk,gen_header)
 
 $(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants
@@ -191,20 +229,20 @@
 $(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs
        $(call filechk,gen_header)
 
-$(ARCH_DIR)/os/util/mk_user_constants: $(ARCH_DIR)/os/util FORCE ;
+$(ARCH_DIR)/os-$(OS)/util/mk_user_constants: $(ARCH_DIR)/os-$(OS)/util FORCE ;
 
 $(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: 
$(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/util \
        FORCE ;
 
 $(ARCH_DIR)/kernel/skas/util/mk_ptregs: $(ARCH_DIR)/kernel/skas/util FORCE ;
 
-$(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h FORCE
+$(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h $(ARCH_DIR)/kernel-offsets.h 
FORCE
        $(Q)$(MAKE) $(build)=$@
 
-$(ARCH_DIR)/kernel/skas/util: scripts_basic FORCE
+$(ARCH_DIR)/kernel/skas/util: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
        $(Q)$(MAKE) $(build)=$@
 
-$(ARCH_DIR)/os/util: scripts_basic FORCE
+$(ARCH_DIR)/os-$(OS)/util: scripts_basic FORCE
        $(Q)$(MAKE) $(build)=$@
 
 export SUBARCH USER_CFLAGS OS
diff -urN linux/arch/um/Makefile-i386 linux/arch/um/Makefile-i386
--- linux/arch/um/Makefile-i386 2005/01/13 14:05:39     1.9
+++ linux/arch/um/Makefile-i386 2005/05/19 12:08:16     1.10
@@ -1,4 +1,4 @@
-SUBARCH_CORE := arch/um/sys-i386/
+SUBARCH_CORE := arch/um/sys-i386/ arch/i386/crypto/
 
 TOP_ADDR := $(CONFIG_TOP_ADDR)
 
@@ -32,10 +32,10 @@
 $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread 
        $(call filechk,gen_header)
 
-$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE
+$(SYS_UTIL_DIR)/mk_sc: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
        $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
-$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE
+$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_DIR)/kernel-offsets.h FORCE
        $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
 $(SYS_UTIL_DIR): scripts_basic include/asm FORCE
diff -urN linux/arch/um/Makefile-x86_64 linux/arch/um/Makefile-x86_64
--- linux/arch/um/Makefile-x86_64       2005/04/08 18:58:06     1.3
+++ linux/arch/um/Makefile-x86_64       2005/05/19 12:08:16     1.4
@@ -23,10 +23,10 @@
 $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
        $(call filechk,gen_header)
 
-$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE
+$(SYS_UTIL_DIR)/mk_sc: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
        $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
-$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE
+$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(GEN_HEADERS) 
$(ARCH_DIR)/kernel-offsets.h FORCE
        $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
 CLEAN_FILES += $(SYS_HEADERS)
diff -urN linux/arch/um/defconfig linux/arch/um/defconfig
--- linux/arch/um/defconfig     2005/04/08 18:58:06     1.14
+++ linux/arch/um/defconfig     2005/05/19 12:08:16     1.15
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk1
-# Sun Mar 20 16:53:00 2005
+# Linux kernel version: 2.6.12-rc3-skas3-v9-pre2
+# Sun Apr 24 19:46:10 2005
 #
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_UML=y
@@ -15,7 +15,8 @@
 #
 CONFIG_MODE_TT=y
 CONFIG_MODE_SKAS=y
-# CONFIG_64_BIT is not set
+CONFIG_UML_X86=y
+# CONFIG_64BIT is not set
 CONFIG_TOP_ADDR=0xc0000000
 # CONFIG_3_LEVEL_PGTABLES is not set
 CONFIG_ARCH_HAS_SC_SIGNALS=y
@@ -41,6 +42,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -158,7 +160,6 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -412,6 +413,5 @@
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_PT_PROXY=y
-# CONFIG_GPROF is not set
 # CONFIG_GCOV is not set
 # CONFIG_SYSCALL_DEBUG is not set
diff -urN linux/arch/um/drivers/chan_kern.c linux/arch/um/drivers/chan_kern.c
--- linux/arch/um/drivers/chan_kern.c   2005/04/08 18:58:06     1.10
+++ linux/arch/um/drivers/chan_kern.c   2005/05/19 12:08:16     1.11
@@ -22,7 +22,7 @@
 #ifdef CONFIG_NOCONFIG_CHAN
 static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       printf(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(NULL);
 }
@@ -30,27 +30,27 @@
 static int not_configged_open(int input, int output, int primary, void *data,
                              char **dev_out)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       printf(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-ENODEV);
 }
 
 static void not_configged_close(int fd, void *data)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       printf(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
 }
 
 static int not_configged_read(int fd, char *c_out, void *data)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       printf(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
 
 static int not_configged_write(int fd, const char *buf, int len, void *data)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       printf(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
@@ -58,7 +58,7 @@
 static int not_configged_console_write(int fd, const char *buf, int len,
                                       void *data)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       printf(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
@@ -66,14 +66,14 @@
 static int not_configged_window_size(int fd, void *data, unsigned short *rows,
                                     unsigned short *cols)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       printf(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-ENODEV);
 }
 
 static void not_configged_free(void *data)
 {
-       printk(KERN_ERR "Using a channel type which is configured out of "
+       printf(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
 }
 
diff -urN linux/arch/um/drivers/line.c linux/arch/um/drivers/line.c
--- linux/arch/um/drivers/line.c        2005/04/08 18:58:06     1.16
+++ linux/arch/um/drivers/line.c        2005/05/19 12:08:16     1.17
@@ -39,19 +39,69 @@
        line_interrupt(line->driver->read_irq, arg, NULL);
 }
 
-static int write_room(struct line *dev)
+/* Returns the free space inside the ring buffer of this line.
+ *
+ * Should be called while holding line->lock (this does not modify datas).
+ */
+static int write_room(struct line *line)
 {
        int n;
 
-       if (dev->buffer == NULL)
-               return (LINE_BUFSIZE - 1);
+       if (line->buffer == NULL)
+               return LINE_BUFSIZE - 1;
+
+       /* This is for the case where the buffer is wrapped! */
+       n = line->head - line->tail;
 
-       n = dev->head - dev->tail;
        if (n <= 0)
-               n = LINE_BUFSIZE + n;
-       return (n - 1);
+               n = LINE_BUFSIZE + n; /* The other case */
+       return n - 1;
+}
+
+int line_write_room(struct tty_struct *tty)
+{
+       struct line *line = tty->driver_data;
+       unsigned long flags;
+       int room;
+
+       if (tty->stopped)
+               return 0;
+
+       spin_lock_irqsave(&line->lock, flags);
+       room = write_room(line);
+       spin_unlock_irqrestore(&line->lock, flags);
+
+       /*XXX: Warning to remove */
+       if (0 == room)
+               printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
+                      __FUNCTION__,tty->name);
+       return room;
+}
+
+int line_chars_in_buffer(struct tty_struct *tty)
+{
+       struct line *line = tty->driver_data;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&line->lock, flags);
+
+       /*write_room subtracts 1 for the needed NULL, so we readd it.*/
+       ret = LINE_BUFSIZE - (write_room(line) + 1);
+       spin_unlock_irqrestore(&line->lock, flags);
+
+       return ret;
 }
 
+/*
+ * This copies the content of buf into the circular buffer associated with
+ * this line.
+ * The return value is the number of characters actually copied, i.e. the ones
+ * for which there was space: this function is not supposed to ever flush out
+ * the circular buffer.
+ *
+ * Must be called while holding line->lock!
+ */
 static int buffer_data(struct line *line, const char *buf, int len)
 {
        int end, room;
@@ -70,48 +120,95 @@
        len = (len > room) ? room : len;
 
        end = line->buffer + LINE_BUFSIZE - line->tail;
-       if(len < end){
+
+       if (len < end){
                memcpy(line->tail, buf, len);
                line->tail += len;
-       }
-       else {
+       } else {
+               /* The circular buffer is wrapping */
                memcpy(line->tail, buf, end);
                buf += end;
                memcpy(line->buffer, buf, len - end);
                line->tail = line->buffer + len - end;
        }
 
-       return(len);
+       return len;
 }
 
+/*
+ * Flushes the ring buffer to the output channels. That is, write_chan is
+ * called, passing it line->head as buffer, and an appropriate count.
+ *
+ * On exit, returns 1 when the buffer is empty,
+ * 0 when the buffer is not empty on exit,
+ * and -errno when an error occurred.
+ *
+ * Must be called while holding line->lock!*/
 static int flush_buffer(struct line *line)
 {
        int n, count;
 
        if ((line->buffer == NULL) || (line->head == line->tail))
-               return(1);
+               return 1;
 
        if (line->tail < line->head) {
+               /* line->buffer + LINE_BUFSIZE is the end of the buffer! */
                count = line->buffer + LINE_BUFSIZE - line->head;
+
                n = write_chan(&line->chan_list, line->head, count,
                               line->driver->write_irq);
                if (n < 0)
-                       return(n);
-               if (n == count)
+                       return n;
+               if (n == count) {
+                       /* We have flushed from ->head to buffer end, now we
+                        * must flush only from the beginning to ->tail.*/
                        line->head = line->buffer;
-               else {
+               } else {
                        line->head += n;
-                       return(0);
+                       return 0;
                }
        }
 
        count = line->tail - line->head;
        n = write_chan(&line->chan_list, line->head, count, 
                       line->driver->write_irq);
-       if(n < 0) return(n);
+
+       if(n < 0)
+               return n;
 
        line->head += n;
-       return(line->head == line->tail);
+       return line->head == line->tail;
+}
+
+void line_flush_buffer(struct tty_struct *tty)
+{
+       struct line *line = tty->driver_data;
+       unsigned long flags;
+       int err;
+
+       /*XXX: copied from line_write, verify if it is correct!*/
+       if(tty->stopped)
+               return;
+               //return 0;
+
+       spin_lock_irqsave(&line->lock, flags);
+       err = flush_buffer(line);
+       /*if (err == 1)
+               err = 0;*/
+       spin_unlock_irqrestore(&line->lock, flags);
+       //return err;
+}
+
+/* We map both ->flush_chars and ->put_char (which go in pair) onto 
->flush_buffer
+ * and ->write. Hope it's not that bad.*/
+void line_flush_chars(struct tty_struct *tty)
+{
+       line_flush_buffer(tty);
+}
+
+void line_put_char(struct tty_struct *tty, unsigned char ch)
+{
+       line_write(tty, &ch, sizeof(ch));
 }
 
 int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
@@ -120,38 +217,31 @@
        unsigned long flags;
        int n, err, ret = 0;
 
-       if(tty->stopped) return 0;
+       if(tty->stopped)
+               return 0;
 
-       down(&line->sem);
-       if(line->head != line->tail){
-               local_irq_save(flags);
+       spin_lock_irqsave(&line->lock, flags);
+       if (line->head != line->tail) {
                ret = buffer_data(line, buf, len);
                err = flush_buffer(line);
-               local_irq_restore(flags);
-               if(err <= 0 && (err != -EAGAIN || !ret))
+               if (err <= 0 && (err != -EAGAIN || !ret))
                        ret = err;
-       }
-       else {
+       } else {
                n = write_chan(&line->chan_list, buf, len, 
                               line->driver->write_irq);
-               if(n < 0){
+               if (n < 0) {
                        ret = n;
                        goto out_up;
                }
 
                len -= n;
                ret += n;
-               if(len > 0)
+               if (len > 0)
                        ret += buffer_data(line, buf + n, len);
        }
- out_up:
-       up(&line->sem);
-       return(ret);
-}
-
-void line_put_char(struct tty_struct *tty, unsigned char ch)
-{
-       line_write(tty, &ch, sizeof(ch));
+out_up:
+       spin_unlock_irqrestore(&line->lock, flags);
+       return ret;
 }
 
 void line_set_termios(struct tty_struct *tty, struct termios * old)
@@ -159,11 +249,6 @@
        /* nothing */
 }
 
-int line_chars_in_buffer(struct tty_struct *tty)
-{
-       return 0;
-}
-
 static struct {
        int  cmd;
        char *level;
@@ -250,7 +335,7 @@
                ret = -ENOIOCTLCMD;
                break;
        }
-       return(ret);
+       return ret;
 }
 
 static irqreturn_t line_write_interrupt(int irq, void *data,
@@ -260,18 +345,23 @@
        struct line *line = tty->driver_data;
        int err;
 
+       /* Interrupts are enabled here because we registered the interrupt with
+        * SA_INTERRUPT (see line_setup_irq).*/
+
+       spin_lock_irq(&line->lock);
        err = flush_buffer(line);
-       if(err == 0)
-               return(IRQ_NONE);
-       else if(err < 0){
+       if (err == 0) {
+               return IRQ_NONE;
+       } else if(err < 0) {
                line->head = line->buffer;
                line->tail = line->buffer;
        }
+       spin_unlock_irq(&line->lock);
 
        if(tty == NULL)
-               return(IRQ_NONE);
+               return IRQ_NONE;
 
-       if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
+       if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
           (tty->ldisc.write_wakeup != NULL))
                (tty->ldisc.write_wakeup)(tty);
        
@@ -281,9 +371,9 @@
         * writes.
         */
 
-       if(waitqueue_active(&tty->write_wait))
+       if (waitqueue_active(&tty->write_wait))
                wake_up_interruptible(&tty->write_wait);
-       return(IRQ_HANDLED);
+       return IRQ_HANDLED;
 }
 
 int line_setup_irq(int fd, int input, int output, struct tty_struct *tty)
@@ -292,15 +382,18 @@
        struct line_driver *driver = line->driver;
        int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
 
-       if(input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, 
+       if (input)
+               err = um_request_irq(driver->read_irq, fd, IRQ_READ,
                                       line_interrupt, flags, 
                                       driver->read_irq_name, tty);
-       if(err) return(err);
-       if(output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, 
+       if (err)
+               return err;
+       if (output)
+               err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
                                        line_write_interrupt, flags, 
                                        driver->write_irq_name, tty);
        line->have_irq = 1;
-       return(err);
+       return err;
 }
 
 void line_disable(struct tty_struct *tty, int current_irq)
@@ -336,7 +429,9 @@
        line = &lines[tty->index];
        tty->driver_data = line;
 
-       down(&line->sem);
+       /* The IRQ which takes this lock is not yet enabled and won't be run
+        * before the end, so we don't need to use spin_lock_irq.*/
+       spin_lock(&line->lock);
        if (tty->count == 1) {
                if (!line->valid) {
                        err = -ENODEV;
@@ -349,6 +444,7 @@
                        err = open_chan(&line->chan_list);
                        if(err) goto out;
                }
+               /* Here the interrupt is registered.*/
                enable_chan(&line->chan_list, tty);
                INIT_WORK(&line->task, line_timer_cb, tty);
        }
@@ -362,21 +458,36 @@
        line->count++;
 
 out:
-       up(&line->sem);
-       return(err);
+       spin_unlock(&line->lock);
+       return err;
 }
 
+static void unregister_winch(struct tty_struct *tty);
+
 void line_close(struct tty_struct *tty, struct file * filp)
 {
        struct line *line = tty->driver_data;
 
-       down(&line->sem);
+       /* XXX: I assume this should be called in process context, not with
+         *  interrupts disabled!
+         */
+       spin_lock_irq(&line->lock);
+
+       /* We ignore the error anyway! */
+       flush_buffer(line);
+
        line->count--;
        if (tty->count == 1) {
                line_disable(tty, -1);
                tty->driver_data = NULL;
        }
-       up(&line->sem);
+
+        if((line->count == 0) && line->sigio){
+                unregister_winch(tty);
+                line->sigio = 0;
+        }
+
+       spin_unlock_irq(&line->lock);
 }
 
 void close_lines(struct line *lines, int nlines)
@@ -387,31 +498,41 @@
                close_chan(&lines[i].chan_list);
 }
 
-int line_setup(struct line *lines, int num, char *init, int all_allowed)
+/* Common setup code for both startup command line and mconsole initialization.
+ * @lines contains the the array (of size @num) to modify;
+ * @init is the setup string;
+ * @all_allowed is a boolean saying if we can setup the whole @lines
+ * at once. For instance, it will be usually true for startup init. (where we
+ * can use con=xterm) and false for mconsole.*/
+
+int line_setup(struct line *lines, unsigned int num, char *init, int 
all_allowed)
 {
        int i, n;
        char *end;
 
-       if(*init == '=') n = -1;
-       else {
+       if(*init == '=') {
+               /* We said con=/ssl= instead of con#=, so we are configuring all
+                * consoles at once.*/
+               n = -1;
+       } else {
                n = simple_strtoul(init, &end, 0);
                if(*end != '='){
                        printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 
                               init);
-                       return(0);
+                       return 0;
                }
                init = end;
        }
        init++;
-       if((n >= 0) && (n >= num)){
+
+       if (n >= (signed int) num) {
                printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
                       n, num - 1);
-               return(0);
-       }
-       else if (n >= 0){
+               return 0;
+       } else if (n >= 0){
                if (lines[n].count > 0) {
                        printk("line_setup - device %d is open\n", n);
-                       return(0);
+                       return 0;
                }
                if (lines[n].init_pri <= INIT_ONE){
                        lines[n].init_pri = INIT_ONE;
@@ -422,13 +543,11 @@
                                lines[n].valid = 1;
                        }       
                }
-       }
-       else if(!all_allowed){
+       } else if(!all_allowed){
                printk("line_setup - can't configure all devices from "
                       "mconsole\n");
-               return(0);
-       }
-       else {
+               return 0;
+       } else {
                for(i = 0; i < num; i++){
                        if(lines[i].init_pri <= INIT_ALL){
                                lines[i].init_pri = INIT_ALL;
@@ -440,21 +559,21 @@
                        }
                }
        }
-       return(1);
+       return 1;
 }
 
-int line_config(struct line *lines, int num, char *str)
+int line_config(struct line *lines, unsigned int num, char *str)
 {
        char *new = uml_strdup(str);
 
        if(new == NULL){
                printk("line_config - uml_strdup failed\n");
-               return(-ENOMEM);
+               return -ENOMEM;
        }
-       return(!line_setup(lines, num, new, 0));
+       return !line_setup(lines, num, new, 0);
 }
 
-int line_get_config(char *name, struct line *lines, int num, char *str, 
+int line_get_config(char *name, struct line *lines, unsigned int num, char 
*str,
                    int size, char **error_out)
 {
        struct line *line;
@@ -464,47 +583,33 @@
        dev = simple_strtoul(name, &end, 0);
        if((*end != '\0') || (end == name)){
                *error_out = "line_get_config failed to parse device number";
-               return(0);
+               return 0;
        }
 
        if((dev < 0) || (dev >= num)){
-               *error_out = "device number of of range";
-               return(0);
+               *error_out = "device number out of range";
+               return 0;
        }
 
        line = &lines[dev];
 
-       down(&line->sem);
+       spin_lock(&line->lock);
        if(!line->valid)
                CONFIG_CHUNK(str, size, n, "none", 1);
        else if(line->count == 0)
                CONFIG_CHUNK(str, size, n, line->init_str, 1);
        else n = chan_config_string(&line->chan_list, str, size, error_out);
-       up(&line->sem);
+       spin_unlock(&line->lock);
 
-       return(n);
+       return n;
 }
 
-int line_remove(struct line *lines, int num, char *str)
+int line_remove(struct line *lines, unsigned int num, char *str)
 {
        char config[sizeof("conxxxx=none\0")];
 
        sprintf(config, "%s=none", str);
-       return(!line_setup(lines, num, config, 0));
-}
-
-int line_write_room(struct tty_struct *tty)
-{
-       struct line *dev = tty->driver_data;
-       int room;
-
-       if (tty->stopped)
-               return 0;
-       room = write_room(dev);
-       if (0 == room)
-               printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
-                      __FUNCTION__,tty->name);
-       return room;
+       return !line_setup(lines, num, config, 0);
 }
 
 struct tty_driver *line_register_devfs(struct lines *set,
@@ -553,7 +658,7 @@
        for(i = 0; i < nlines; i++){
                line = &lines[i];
                INIT_LIST_HEAD(&line->chan_list);
-               sema_init(&line->sem, 1);
+               spin_lock_init(&line->lock);
                if(line->init_str != NULL){
                        line->init_str = uml_strdup(line->init_str);
                        if(line->init_str == NULL)
@@ -587,7 +692,7 @@
                                       "errno = %d\n", -err);
                                printk("fd %d is losing SIGWINCH support\n",
                                       winch->tty_fd);
-                               return(IRQ_HANDLED);
+                               return IRQ_HANDLED;
                        }
                        goto out;
                }
@@ -603,7 +708,7 @@
  out:
        if(winch->fd != -1)
                reactivate_fd(winch->fd, WINCH_IRQ);
-       return(IRQ_HANDLED);
+       return IRQ_HANDLED;
 }
 
 DECLARE_MUTEX(winch_handler_sem);
@@ -625,7 +730,7 @@
                                   .pid         = pid,
                                   .tty         = tty });
        list_add(&winch->list, &winch_handlers);
-       if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 
+       if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
                          SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 
                          "winch", winch) < 0)
                printk("register_winch_irq - failed to register IRQ\n");
@@ -633,6 +738,34 @@
        up(&winch_handler_sem);
 }
 
+static void unregister_winch(struct tty_struct *tty)
+{
+       struct list_head *ele;
+       struct winch *winch, *found = NULL;
+
+       down(&winch_handler_sem);
+       list_for_each(ele, &winch_handlers){
+               winch = list_entry(ele, struct winch, list);
+                if(winch->tty == tty){
+                        found = winch;
+                        break;
+                }
+        }
+
+        if(found == NULL)
+                goto out;
+
+        if(winch->pid != -1)
+                os_kill_process(winch->pid, 1);
+
+        free_irq_by_irq_and_dev(WINCH_IRQ, winch);
+        free_irq(WINCH_IRQ, winch);
+        list_del(&winch->list);
+        kfree(winch);
+ out:
+       up(&winch_handler_sem);
+}
+
 static void winch_cleanup(void)
 {
        struct list_head *ele;
@@ -656,26 +789,16 @@
        int len;
 
        umid = get_umid(1);
-       if(umid == NULL) return(base);
+       if(umid == NULL)
+               return base;
        
        len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
        title = kmalloc(len, GFP_KERNEL);
        if(title == NULL){
                printk("Failed to allocate buffer for xterm title\n");
-               return(base);
+               return base;
        }
 
        snprintf(title, len, "%s (%s)", base, umid);
-       return(title);
+       return title;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -urN linux/arch/um/drivers/ssl.c linux/arch/um/drivers/ssl.c
--- linux/arch/um/drivers/ssl.c 2005/01/13 14:05:39     1.10
+++ linux/arch/um/drivers/ssl.c 2005/05/19 12:08:16     1.11
@@ -107,11 +107,6 @@
 }
 
 #if 0
-static int ssl_chars_in_buffer(struct tty_struct *tty)
-{
-       return(0);
-}
-
 static void ssl_flush_buffer(struct tty_struct *tty)
 {
        return;
@@ -149,11 +144,11 @@
        .put_char               = line_put_char,
        .write_room             = line_write_room,
        .chars_in_buffer        = line_chars_in_buffer,
+       .flush_buffer           = line_flush_buffer,
+       .flush_chars            = line_flush_chars,
        .set_termios            = line_set_termios,
        .ioctl                  = line_ioctl,
 #if 0
-       .flush_chars            = ssl_flush_chars,
-       .flush_buffer           = ssl_flush_buffer,
        .throttle               = ssl_throttle,
        .unthrottle             = ssl_unthrottle,
        .stop                   = ssl_stop,
@@ -171,10 +166,11 @@
                              unsigned len)
 {
        struct line *line = &serial_lines[c->index];
+       unsigned long flags;
 
-       down(&line->sem);
+       spin_lock_irqsave(&line->lock, flags);
        console_write_chan(&line->chan_list, string, len);
-       up(&line->sem);
+       spin_unlock_irqrestore(&line->lock, flags);
 }
 
 static struct tty_driver *ssl_console_device(struct console *c, int *index)
@@ -238,14 +234,3 @@
 
 __setup("ssl", ssl_chan_setup);
 __channel_help(ssl_chan_setup, "ssl");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -urN linux/arch/um/drivers/stdio_console.c 
linux/arch/um/drivers/stdio_console.c
--- linux/arch/um/drivers/stdio_console.c       2005/01/13 14:05:39     1.13
+++ linux/arch/um/drivers/stdio_console.c       2005/05/19 12:08:16     1.14
@@ -116,8 +116,11 @@
        .open                   = con_open,
        .close                  = line_close,
        .write                  = line_write,
+       .put_char               = line_put_char,
        .write_room             = line_write_room,
        .chars_in_buffer        = line_chars_in_buffer,
+       .flush_buffer           = line_flush_buffer,
+       .flush_chars            = line_flush_chars,
        .set_termios            = line_set_termios,
        .ioctl                  = line_ioctl,
 };
@@ -126,10 +129,11 @@
                          unsigned len)
 {
        struct line *line = &vts[console->index];
+       unsigned long flags;
 
-       down(&line->sem);
+       spin_lock_irqsave(&line->lock, flags);
        console_write_chan(&line->chan_list, string, len);
-       up(&line->sem);
+       spin_unlock_irqrestore(&line->lock, flags);
 }
 
 static struct tty_driver *uml_console_device(struct console *c, int *index)
@@ -192,14 +196,3 @@
 }
 __setup("con", console_chan_setup);
 __channel_help(console_chan_setup, "con");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -urN linux/arch/um/drivers/ubd_kern.c linux/arch/um/drivers/ubd_kern.c
--- linux/arch/um/drivers/ubd_kern.c    2005/03/18 17:37:05     1.21
+++ linux/arch/um/drivers/ubd_kern.c    2005/05/19 12:08:16     1.22
@@ -156,6 +156,7 @@
 static struct openflags global_openflags = OPEN_FLAGS;
 
 struct cow {
+       /* This is the backing file, actually */
        char *file;
        int fd;
        unsigned long *bitmap;
@@ -927,10 +928,14 @@
                }
        }
        dev->count++;
-       if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){
+       set_disk_ro(disk, !dev->openflags.w);
+
+       /* This should no more be needed. And it didn't work anyway to exclude
+        * read-write remounting of filesystems.*/
+       /*if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){
                if(--dev->count == 0) ubd_close(dev);
                err = -EROFS;
-       }
+       }*/
  out:
        return(err);
 }
@@ -1096,6 +1101,7 @@
 
        if(req->rq_status == RQ_INACTIVE) return(1);
 
+       /* This should be impossible now */
        if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
                printk("Write attempted on readonly ubd device %s\n", 
                       disk->disk_name);
@@ -1243,6 +1249,7 @@
 
                /* It's a write to a ubd device */
 
+               /* This should be impossible now */
                if(!dev->openflags.w){
                        /* It's a write access on a read-only device - probably
                         * shouldn't happen.  If the kernel is trying to change
@@ -1605,8 +1612,7 @@
                                }
                        } while((n < len) && (n != 0));
                        if (n < len) memset(&buf[n], 0, len - n);
-               }
-               else {
+               } else {
                        n = os_write_file(req->fds[bit], buf, len);
                        if(n != len){
                                printk("do_io - write failed err = %d "
diff -urN linux/arch/um/drivers/xterm_kern.c linux/arch/um/drivers/xterm_kern.c
--- linux/arch/um/drivers/xterm_kern.c  2005/03/18 17:37:05     1.7
+++ linux/arch/um/drivers/xterm_kern.c  2005/05/19 12:08:16     1.8
@@ -7,7 +7,6 @@
 #include "linux/slab.h"
 #include "linux/signal.h"
 #include "linux/interrupt.h"
-#include "asm/semaphore.h"
 #include "asm/irq.h"
 #include "irq_user.h"
 #include "irq_kern.h"
diff -urN linux/arch/um/include/common-offsets.h 
linux/arch/um/include/common-offsets.h
--- linux/arch/um/include/common-offsets.h      1970/01/01 00:00:00
+++ linux/arch/um/include/common-offsets.h      2005-05-19 13:08:16.939813000 
+0100     1.1
@@ -0,0 +1,14 @@
+/* for use by sys-$SUBARCH/kernel-offsets.c */
+
+OFFSET(TASK_REGS, task_struct, thread.regs);
+OFFSET(TASK_PID, task_struct, pid);
+DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
+DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
+DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
+DEFINE_STR(UM_KERN_ALERT, KERN_ALERT);
+DEFINE_STR(UM_KERN_CRIT, KERN_CRIT);
+DEFINE_STR(UM_KERN_ERR, KERN_ERR);
+DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
+DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
+DEFINE_STR(UM_KERN_INFO, KERN_INFO);
+DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
diff -urN linux/arch/um/include/kern_util.h linux/arch/um/include/kern_util.h
--- linux/arch/um/include/kern_util.h   2004/12/04 18:16:01     1.8
+++ linux/arch/um/include/kern_util.h   2005/05/19 12:08:16     1.9
@@ -8,6 +8,7 @@
 
 #include "linux/threads.h"
 #include "sysdep/ptrace.h"
+#include "sysdep/faultinfo.h"
 
 extern int ncpus;
 extern char *linux_prog;
@@ -31,8 +32,8 @@
 extern unsigned long alloc_stack(int order, int atomic);
 extern int do_signal(void);
 extern int is_stack_fault(unsigned long sp);
-extern unsigned long segv(unsigned long address, unsigned long ip, 
-                         int is_write, int is_user, void *sc);
+extern unsigned long segv(struct faultinfo fi, unsigned long ip,
+                         int is_user, void *sc);
 extern int handle_page_fault(unsigned long address, unsigned long ip,
                             int is_write, int is_user, int *code_out);
 extern void syscall_ready(void);
@@ -82,7 +83,7 @@
 extern void unprotect_stack(unsigned long stack);
 extern void do_uml_exitcalls(void);
 extern int attach_debugger(int idle_pid, int pid, int stop);
-extern void bad_segv(unsigned long address, unsigned long ip, int is_write);
+extern void bad_segv(struct faultinfo fi, unsigned long ip);
 extern int config_gdb(char *str);
 extern int remove_gdb(void);
 extern char *uml_strdup(char *string);
diff -urN linux/arch/um/include/line.h linux/arch/um/include/line.h
--- linux/arch/um/include/line.h        2005/01/13 14:05:39     1.8
+++ linux/arch/um/include/line.h        2005/05/19 12:08:16     1.9
@@ -10,7 +10,7 @@
 #include "linux/workqueue.h"
 #include "linux/tty.h"
 #include "linux/interrupt.h"
-#include "asm/semaphore.h"
+#include "linux/spinlock.h"
 #include "chan_user.h"
 #include "mconsole_kern.h"
 
@@ -37,10 +37,18 @@
        struct list_head chan_list;
        int valid;
        int count;
-       struct semaphore sem;
+       /*This lock is actually, mostly, local to*/
+       spinlock_t lock;
+
+       /* Yes, this is a real circular buffer.
+        * XXX: And this should become a struct kfifo!
+        *
+        * buffer points to a buffer allocated on demand, of length
+        * LINE_BUFSIZE, head to the start of the ring, tail to the end.*/
        char *buffer;
        char *head;
        char *tail;
+
        int sigio;
        struct work_struct task;
        struct line_driver *driver;
@@ -52,7 +60,6 @@
          init_pri :    INIT_STATIC, \
          chan_list :   { }, \
          valid :       1, \
-         sem :         { }, \
          buffer :      NULL, \
          head :        NULL, \
          tail :        NULL, \
@@ -69,15 +76,18 @@
 extern void line_close(struct tty_struct *tty, struct file * filp);
 extern int line_open(struct line *lines, struct tty_struct *tty, 
                     struct chan_opts *opts);
-extern int line_setup(struct line *lines, int num, char *init, 
+extern int line_setup(struct line *lines, unsigned int sizeof_lines, char 
*init,
                      int all_allowed);
 extern int line_write(struct tty_struct *tty, const unsigned char *buf, int 
len);
 extern void line_put_char(struct tty_struct *tty, unsigned char ch);
 extern void line_set_termios(struct tty_struct *tty, struct termios * old);
 extern int line_chars_in_buffer(struct tty_struct *tty);
+extern void line_flush_buffer(struct tty_struct *tty);
+extern void line_flush_chars(struct tty_struct *tty);
 extern int line_write_room(struct tty_struct *tty);
 extern int line_ioctl(struct tty_struct *tty, struct file * file,
                      unsigned int cmd, unsigned long arg);
+
 extern char *add_xterm_umid(char *base);
 extern int line_setup_irq(int fd, int input, int output, struct tty_struct 
*tty);
 extern void line_close_chan(struct line *line);
@@ -89,20 +99,10 @@
                                int nlines);
 extern void lines_init(struct line *lines, int nlines);
 extern void close_lines(struct line *lines, int nlines);
-extern int line_config(struct line *lines, int num, char *str);
-extern int line_remove(struct line *lines, int num, char *str);
-extern int line_get_config(char *dev, struct line *lines, int num, char *str, 
+
+extern int line_config(struct line *lines, unsigned int sizeof_lines, char 
*str);
+extern int line_remove(struct line *lines, unsigned int sizeof_lines, char 
*str);
+extern int line_get_config(char *dev, struct line *lines, unsigned int 
sizeof_lines, char *str,
                           int size, char **error_out);
 
 #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:
- */
diff -urN linux/arch/um/include/os.h linux/arch/um/include/os.h
--- linux/arch/um/include/os.h  2004/11/15 11:49:21     1.6
+++ linux/arch/um/include/os.h  2005/05/19 12:08:16     1.7
@@ -160,6 +160,7 @@
 extern void os_kill_ptraced_process(int pid, int reap_child);
 extern void os_usr1_process(int pid);
 extern int os_getpid(void);
+extern int os_getpgrp(void);
 
 extern int os_map_memory(void *virt, int fd, unsigned long long off,
                         unsigned long len, int r, int w, int x);
diff -urN linux/arch/um/include/skas_ptrace.h 
linux/arch/um/include/skas_ptrace.h
--- linux/arch/um/include/skas_ptrace.h 2004/09/19 12:30:07     1.2
+++ linux/arch/um/include/skas_ptrace.h 2005/05/19 12:08:16     1.3
@@ -6,22 +6,11 @@
 #ifndef __SKAS_PTRACE_H
 #define __SKAS_PTRACE_H
 
-struct ptrace_faultinfo {
-       int is_write;
-       unsigned long addr;
-};
-
-struct ptrace_ldt {
-       int func;
-       void *ptr;
-       unsigned long bytecount;
-};
-
 #define PTRACE_FAULTINFO 52
-#define PTRACE_SIGPENDING 53
-#define PTRACE_LDT 54
 #define PTRACE_SWITCH_MM 55
 
+#include "sysdep/skas_ptrace.h"
+
 #endif
 
 /*
diff -urN linux/arch/um/include/user_util.h linux/arch/um/include/user_util.h
--- linux/arch/um/include/user_util.h   2005/04/08 18:58:06     1.10
+++ linux/arch/um/include/user_util.h   2005/05/19 12:08:16     1.11
@@ -67,7 +67,6 @@
 extern int switcheroo(int fd, int prot, void *from, void *to, int size);
 extern void setup_machinename(char *machine_out);
 extern void setup_hostinfo(void);
-extern void add_arg(char *arg);
 extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
 extern void init_new_thread_signals(int altstack);
 extern void do_exec(int old_pid, int new_pid);
diff -urN linux/arch/um/include/sysdep-i386/faultinfo.h 
linux/arch/um/include/sysdep-i386/faultinfo.h
--- linux/arch/um/include/sysdep-i386/faultinfo.h       1970/01/01 00:00:00
+++ linux/arch/um/include/sysdep-i386/faultinfo.h       2005-05-19 
13:08:17.095611000 +0100     1.1
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_I386_H
+#define __FAULTINFO_I386_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+#define PTRACE_FULL_FAULTINFO 0
+
+#endif
diff -urN linux/arch/um/include/sysdep-i386/skas_ptrace.h 
linux/arch/um/include/sysdep-i386/skas_ptrace.h
--- linux/arch/um/include/sysdep-i386/skas_ptrace.h     1970/01/01 00:00:00
+++ linux/arch/um/include/sysdep-i386/skas_ptrace.h     2005-05-19 
13:08:17.106484000 +0100     1.1
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_I386_SKAS_PTRACE_H
+#define __SYSDEP_I386_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff -urN linux/arch/um/include/sysdep-i386/checksum.h 
linux/arch/um/include/sysdep-i386/checksum.h
--- linux/arch/um/include/sysdep-i386/checksum.h        2005/03/18 17:37:05     
1.6
+++ linux/arch/um/include/sysdep-i386/checksum.h        2005/05/19 12:08:17     
1.7
@@ -24,19 +24,6 @@
                          unsigned int sum);
 
 /*
- * the same as csum_partial, but copies from src while it
- * checksums, and handles user-space pointer exceptions correctly, when needed.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-unsigned int csum_partial_copy_to(const unsigned char *src, unsigned char *dst,
-                                 int len, int sum, int *err_ptr);
-unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char 
*dst,
-                                   int len, int sum, int *err_ptr);
-
-/*
  *     Note: when you get a NULL pointer exception here this means someone
  *     passed in an incorrect kernel address to one of these functions.
  *
@@ -52,11 +39,24 @@
        return(csum_partial(dst, len, sum));
 }
 
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
 static __inline__
 unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned 
char *dst,
                                         int len, int sum, int *err_ptr)
 {
-       return csum_partial_copy_from(src, dst, len, sum, err_ptr);
+       if(copy_from_user(dst, src, len)){
+               *err_ptr = -EFAULT;
+               return(-1);
+       }
+
+       return csum_partial(dst, len, sum);
 }
 
 /*
@@ -67,7 +67,6 @@
  */
 
 #define csum_partial_copy_fromuser csum_partial_copy_from_user
-unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst, 
int len, int sum);
 
 /*
  *     This is a version of ip_compute_csum() optimized for IP headers,
@@ -196,8 +195,14 @@
                                                     unsigned char *dst,
                                                     int len, int sum, int 
*err_ptr)
 {
-       if (access_ok(VERIFY_WRITE, dst, len))
-               return(csum_partial_copy_to(src, dst, len, sum, err_ptr));
+       if (access_ok(VERIFY_WRITE, dst, len)){
+               if(copy_to_user(dst, src, len)){
+                       *err_ptr = -EFAULT;
+                       return(-1);
+               }
+
+               return csum_partial(src, len, sum);
+       }
 
        if (len)
                *err_ptr = -EFAULT;
diff -urN linux/arch/um/include/sysdep-i386/ptrace.h 
linux/arch/um/include/sysdep-i386/ptrace.h
--- linux/arch/um/include/sysdep-i386/ptrace.h  2005/04/08 18:58:06     1.6
+++ linux/arch/um/include/sysdep-i386/ptrace.h  2005/05/19 12:08:17     1.7
@@ -31,6 +31,7 @@
 #ifdef UML_CONFIG_MODE_SKAS
 
 #include "skas_ptregs.h"
+#include "sysdep/faultinfo.h"
 
 #define REGS_IP(r) ((r)[HOST_IP])
 #define REGS_SP(r) ((r)[HOST_SP])
@@ -53,12 +54,6 @@
 
 #define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
 
-#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
-
-#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
-
-#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
-
 #endif
 #ifndef PTRACE_SYSEMU_SINGLESTEP
 #define PTRACE_SYSEMU_SINGLESTEP 32
@@ -71,6 +66,7 @@
        struct tt_regs {
                long syscall;
                void *sc;
+                struct faultinfo faultinfo;
        } tt;
 #endif
 #ifdef UML_CONFIG_MODE_SKAS
@@ -78,9 +74,7 @@
                unsigned long regs[HOST_FRAME_SIZE];
                unsigned long fp[HOST_FP_SIZE];
                unsigned long xfp[HOST_XFP_SIZE];
-               unsigned long fault_addr;
-               unsigned long fault_type;
-               unsigned long trap_type;
+                struct faultinfo faultinfo;
                long syscall;
                int is_user;
        } skas;
@@ -217,15 +211,8 @@
 #define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r)
 #define UPT_SYSCALL_RET(r) UPT_EAX(r)
 
-#define UPT_SEGV_IS_FIXABLE(r) \
-       CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \
-                    REGS_SEGV_IS_FIXABLE(&r->skas))
-
-#define UPT_FAULT_ADDR(r) \
-       __CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
-
-#define UPT_FAULT_WRITE(r) \
-       CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
+#define UPT_FAULTINFO(r) \
+        CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
 
 #endif
 
diff -urN linux/arch/um/include/sysdep-i386/sigcontext.h 
linux/arch/um/include/sysdep-i386/sigcontext.h
--- linux/arch/um/include/sysdep-i386/sigcontext.h      2005/04/08 18:58:06     
1.5
+++ linux/arch/um/include/sysdep-i386/sigcontext.h      2005/05/19 12:08:17     
1.6
@@ -13,15 +13,12 @@
 #define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc))
 #define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result)
 
-#define SC_FAULT_ADDR(sc) SC_CR2(sc)
-#define SC_FAULT_TYPE(sc) SC_ERR(sc)
-
-#define FAULT_WRITE(err) (err & 2)
-#define TO_SC_ERR(is_write) ((is_write) ? 2 : 0)
-
-#define SC_FAULT_WRITE(sc) (FAULT_WRITE(SC_ERR(sc)))
-
-#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc)
+#define GET_FAULTINFO_FROM_SC(fi,sc) \
+       { \
+               (fi).cr2 = SC_CR2(sc); \
+               (fi).error_code = SC_ERR(sc); \
+               (fi).trap_no = SC_TRAPNO(sc); \
+       }
 
 /* ptrace expects that, at the start of a system call, %eax contains
  * -ENOSYS, so this makes it so.
@@ -29,9 +26,7 @@
 #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
 
 /* This is Page Fault */
-#define SEGV_IS_FIXABLE(trap) (trap == 14)
-
-#define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
+#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
 
 extern unsigned long *sc_sigmask(void *sc_ptr);
 extern int sc_get_fpregs(unsigned long buf, void *sc_ptr);
diff -urN linux/arch/um/include/sysdep-i386/signal.h 
linux/arch/um/include/sysdep-i386/signal.h
--- linux/arch/um/include/sysdep-i386/signal.h  2005/01/13 14:05:40     1.1
+++ linux/arch/um/include/sysdep-i386/signal.h  2005/05/19 12:08:17     1.2
@@ -8,6 +8,8 @@
 
 #include <signal.h>
 
+#define ARCH_SIGHDLR_PARAM int sig
+
 #define ARCH_GET_SIGCONTEXT(sc, sig) \
        do sc = (struct sigcontext *) (&sig + 1); while(0)
 
diff -urN linux/arch/um/include/sysdep-i386/syscalls.h 
linux/arch/um/include/sysdep-i386/syscalls.h
--- linux/arch/um/include/sysdep-i386/syscalls.h        2005/04/08 18:58:06     
1.5
+++ linux/arch/um/include/sysdep-i386/syscalls.h        2005/05/19 12:08:17     
1.6
@@ -22,102 +22,3 @@
 extern long sys_mmap2(unsigned long addr, unsigned long len,
                      unsigned long prot, unsigned long flags,
                      unsigned long fd, unsigned long pgoff);
-
-/* On i386 they choose a meaningless naming.*/
-#define __NR_kexec_load __NR_sys_kexec_load
-
-#define ARCH_SYSCALLS \
-       [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, \
-       [ __NR_break ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_oldstat ] = (syscall_handler_t *) sys_stat, \
-       [ __NR_umount ] = (syscall_handler_t *) sys_oldumount, \
-       [ __NR_stime ] = um_stime, \
-       [ __NR_oldfstat ] = (syscall_handler_t *) sys_fstat, \
-       [ __NR_stty ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_gtty ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_nice ] = (syscall_handler_t *) sys_nice, \
-       [ __NR_ftime ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_prof ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_signal ] = (syscall_handler_t *) sys_signal, \
-       [ __NR_lock ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_mpx ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_ulimit ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_oldolduname ] = (syscall_handler_t *) sys_olduname, \
-       [ __NR_sigaction ] = (syscall_handler_t *) sys_sigaction, \
-       [ __NR_sgetmask ] = (syscall_handler_t *) sys_sgetmask, \
-       [ __NR_ssetmask ] = (syscall_handler_t *) sys_ssetmask, \
-       [ __NR_sigsuspend ] = (syscall_handler_t *) sys_sigsuspend, \
-       [ __NR_sigpending ] = (syscall_handler_t *) sys_sigpending, \
-       [ __NR_oldlstat ] = (syscall_handler_t *) sys_lstat, \
-       [ __NR_readdir ] = old_readdir, \
-       [ __NR_profil ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_socketcall ] = (syscall_handler_t *) sys_socketcall, \
-       [ __NR_olduname ] = (syscall_handler_t *) sys_uname, \
-       [ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_idle ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_ipc ] = (syscall_handler_t *) sys_ipc, \
-       [ __NR_sigreturn ] = (syscall_handler_t *) sys_sigreturn, \
-       [ __NR_sigprocmask ] = (syscall_handler_t *) sys_sigprocmask, \
-       [ __NR_bdflush ] = (syscall_handler_t *) sys_bdflush, \
-       [ __NR__llseek ] = (syscall_handler_t *) sys_llseek, \
-       [ __NR__newselect ] = (syscall_handler_t *) sys_select, \
-       [ __NR_vm86 ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_mmap ] = (syscall_handler_t *) old_mmap_i386, \
-       [ __NR_ugetrlimit ] = (syscall_handler_t *) sys_getrlimit, \
-       [ __NR_mmap2 ] = (syscall_handler_t *) sys_mmap2, \
-       [ __NR_truncate64 ] = (syscall_handler_t *) sys_truncate64, \
-       [ __NR_ftruncate64 ] = (syscall_handler_t *) sys_ftruncate64, \
-       [ __NR_stat64 ] = (syscall_handler_t *) sys_stat64, \
-       [ __NR_lstat64 ] = (syscall_handler_t *) sys_lstat64, \
-       [ __NR_fstat64 ] = (syscall_handler_t *) sys_fstat64, \
-       [ __NR_fcntl64 ] = (syscall_handler_t *) sys_fcntl64, \
-       [ __NR_sendfile64 ] = (syscall_handler_t *) sys_sendfile64, \
-       [ __NR_statfs64 ] = (syscall_handler_t *) sys_statfs64, \
-       [ __NR_fstatfs64 ] = (syscall_handler_t *) sys_fstatfs64, \
-       [ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64, \
-       [ __NR_select ] = (syscall_handler_t *) old_select, \
-       [ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
-       [ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \
-       [ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \
-       [ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \
-       [ __NR_geteuid32 ] = (syscall_handler_t *) sys_geteuid, \
-       [ __NR_getegid32 ] = (syscall_handler_t *) sys_getegid, \
-       [ __NR_setreuid32 ] = (syscall_handler_t *) sys_setreuid, \
-       [ __NR_setregid32 ] = (syscall_handler_t *) sys_setregid, \
-       [ __NR_getgroups32 ] = (syscall_handler_t *) sys_getgroups, \
-       [ __NR_setgroups32 ] = (syscall_handler_t *) sys_setgroups, \
-       [ __NR_fchown32 ] = (syscall_handler_t *) sys_fchown, \
-       [ __NR_setresuid32 ] = (syscall_handler_t *) sys_setresuid, \
-       [ __NR_getresuid32 ] = (syscall_handler_t *) sys_getresuid, \
-       [ __NR_setresgid32 ] = (syscall_handler_t *) sys_setresgid, \
-       [ __NR_getresgid32 ] = (syscall_handler_t *) sys_getresgid, \
-       [ __NR_chown32 ] = (syscall_handler_t *) sys_chown, \
-       [ __NR_setuid32 ] = (syscall_handler_t *) sys_setuid, \
-       [ __NR_setgid32 ] = (syscall_handler_t *) sys_setgid, \
-       [ __NR_setfsuid32 ] = (syscall_handler_t *) sys_setfsuid, \
-       [ __NR_setfsgid32 ] = (syscall_handler_t *) sys_setfsgid, \
-       [ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
-       [ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
-       [ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
-       [ 222 ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ 223 ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ 251 ] = (syscall_handler_t *) sys_ni_syscall, \
-       [ 285 ] = (syscall_handler_t *) sys_ni_syscall,
-
-/* 222 doesn't yet have a name in include/asm-i386/unistd.h */
-
-#define LAST_ARCH_SYSCALL 285
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -urN linux/arch/um/include/sysdep-ia64/skas_ptrace.h 
linux/arch/um/include/sysdep-ia64/skas_ptrace.h
--- linux/arch/um/include/sysdep-ia64/skas_ptrace.h     1970/01/01 00:00:00
+++ linux/arch/um/include/sysdep-ia64/skas_ptrace.h     2005-05-19 
13:08:17.248507000 +0100     1.1
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_IA64_SKAS_PTRACE_H
+#define __SYSDEP_IA64_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff -urN linux/arch/um/include/sysdep-ppc/skas_ptrace.h 
linux/arch/um/include/sysdep-ppc/skas_ptrace.h
--- linux/arch/um/include/sysdep-ppc/skas_ptrace.h      1970/01/01 00:00:00
+++ linux/arch/um/include/sysdep-ppc/skas_ptrace.h      2005-05-19 
13:08:17.306547000 +0100     1.1
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_PPC_SKAS_PTRACE_H
+#define __SYSDEP_PPC_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff -urN linux/arch/um/include/sysdep-x86_64/faultinfo.h 
linux/arch/um/include/sysdep-x86_64/faultinfo.h
--- linux/arch/um/include/sysdep-x86_64/faultinfo.h     1970/01/01 00:00:00
+++ linux/arch/um/include/sysdep-x86_64/faultinfo.h     2005-05-19 
13:08:17.374514000 +0100     1.1
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ * Licensed under the GPL
+ */
+
+#ifndef __FAULTINFO_X86_64_H
+#define __FAULTINFO_X86_64_H
+
+/* this structure contains the full arch-specific faultinfo
+ * from the traps.
+ * On i386, ptrace_faultinfo unfortunately doesn't provide
+ * all the info, since trap_no is missing.
+ * All common elements are defined at the same position in
+ * both structures, thus making it easy to copy the
+ * contents without knowledge about the structure elements.
+ */
+struct faultinfo {
+        int error_code; /* in ptrace_faultinfo misleadingly called is_write */
+        unsigned long cr2; /* in ptrace_faultinfo called addr */
+        int trap_no; /* missing in ptrace_faultinfo */
+};
+
+#define FAULT_WRITE(fi) ((fi).error_code & 2)
+#define FAULT_ADDRESS(fi) ((fi).cr2)
+
+#define PTRACE_FULL_FAULTINFO 1
+
+#endif
diff -urN linux/arch/um/include/sysdep-x86_64/skas_ptrace.h 
linux/arch/um/include/sysdep-x86_64/skas_ptrace.h
--- linux/arch/um/include/sysdep-x86_64/skas_ptrace.h   1970/01/01 00:00:00
+++ linux/arch/um/include/sysdep-x86_64/skas_ptrace.h   2005-05-19 
13:08:17.385475000 +0100     1.1
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_X86_64_SKAS_PTRACE_H
+#define __SYSDEP_X86_64_SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+        int is_write;
+        unsigned long addr;
+};
+
+struct ptrace_ldt {
+        int func;
+        void *ptr;
+        unsigned long bytecount;
+};
+
+#define PTRACE_LDT 54
+
+#endif
diff -urN linux/arch/um/include/sysdep-x86_64/ptrace.h 
linux/arch/um/include/sysdep-x86_64/ptrace.h
--- linux/arch/um/include/sysdep-x86_64/ptrace.h        2005/04/08 18:58:06     
1.3
+++ linux/arch/um/include/sysdep-x86_64/ptrace.h        2005/05/19 12:08:17     
1.4
@@ -9,6 +9,7 @@
 
 #include "uml-config.h"
 #include "user_constants.h"
+#include "sysdep/faultinfo.h"
 
 #define MAX_REG_OFFSET (UM_FRAME_SIZE)
 #define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
@@ -83,6 +84,7 @@
                long syscall;
                unsigned long orig_rax;
                void *sc;
+                struct faultinfo faultinfo;
        } tt;
 #endif
 #ifdef UML_CONFIG_MODE_SKAS
@@ -90,9 +92,7 @@
                /* XXX */
                unsigned long regs[27];
                unsigned long fp[65];
-               unsigned long fault_addr;
-               unsigned long fault_type;
-               unsigned long trap_type;
+                struct faultinfo faultinfo;
                long syscall;
                int is_user;
        } skas;
@@ -241,14 +241,8 @@
        CHOOSE_MODE(SC_SEGV_IS_FIXABLE(UPT_SC(r)), \
                     REGS_SEGV_IS_FIXABLE(&r->skas))
 
-#define UPT_FAULT_ADDR(r) \
-       __CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
-
-#define UPT_FAULT_WRITE(r) \
-       CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
-
-#define UPT_TRAP(r) __CHOOSE_MODE(SC_TRAP_TYPE(UPT_SC(r)), REGS_TRAP(&r->skas))
-#define UPT_ERR(r) __CHOOSE_MODE(SC_FAULT_TYPE(UPT_SC(r)), REGS_ERR(&r->skas))
+#define UPT_FAULTINFO(r) \
+        CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
 
 #endif
 
diff -urN linux/arch/um/include/sysdep-x86_64/sigcontext.h 
linux/arch/um/include/sysdep-x86_64/sigcontext.h
--- linux/arch/um/include/sysdep-x86_64/sigcontext.h    2005/04/08 18:58:06     
1.2
+++ linux/arch/um/include/sysdep-x86_64/sigcontext.h    2005/05/19 12:08:17     
1.3
@@ -17,11 +17,12 @@
 #define SC_FAULT_ADDR(sc) SC_CR2(sc)
 #define SC_FAULT_TYPE(sc) SC_ERR(sc)
 
-#define FAULT_WRITE(err) ((err) & 2)
-
-#define SC_FAULT_WRITE(sc) FAULT_WRITE(SC_FAULT_TYPE(sc))
-
-#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc)
+#define GET_FAULTINFO_FROM_SC(fi,sc) \
+       { \
+               (fi).cr2 = SC_CR2(sc); \
+               (fi).error_code = SC_ERR(sc); \
+               (fi).trap_no = SC_TRAPNO(sc); \
+       }
 
 /* ptrace expects that, at the start of a system call, %eax contains
  * -ENOSYS, so this makes it so.
@@ -29,8 +30,8 @@
 
 #define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0)
 
-#define SEGV_IS_FIXABLE(trap) ((trap) == 14)
-#define SC_SEGV_IS_FIXABLE(sc) SEGV_IS_FIXABLE(SC_TRAP_TYPE(sc))
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
 
 extern unsigned long *sc_sigmask(void *sc_ptr);
 
diff -urN linux/arch/um/include/sysdep-x86_64/signal.h 
linux/arch/um/include/sysdep-x86_64/signal.h
--- linux/arch/um/include/sysdep-x86_64/signal.h        2005/01/13 14:05:40     
1.1
+++ linux/arch/um/include/sysdep-x86_64/signal.h        2005/05/19 12:08:17     
1.2
@@ -6,6 +6,8 @@
 #ifndef __X86_64_SIGNAL_H_
 #define __X86_64_SIGNAL_H_
 
+#define ARCH_SIGHDLR_PARAM int sig
+
 #define ARCH_GET_SIGCONTEXT(sc, sig_addr) \
        do { \
                struct ucontext *__uc; \
diff -urN linux/arch/um/include/sysdep-x86_64/syscalls.h 
linux/arch/um/include/sysdep-x86_64/syscalls.h
--- linux/arch/um/include/sysdep-x86_64/syscalls.h      2005/04/08 18:58:06     
1.2
+++ linux/arch/um/include/sysdep-x86_64/syscalls.h      2005/05/19 12:08:17     
1.3
@@ -26,66 +26,9 @@
 extern long old_mmap(unsigned long addr, unsigned long len,
                     unsigned long prot, unsigned long flags,
                     unsigned long fd, unsigned long pgoff);
-extern syscall_handler_t wrap_sys_shmat;
 extern syscall_handler_t sys_modify_ldt;
 extern syscall_handler_t sys_arch_prctl;
 
-#define ARCH_SYSCALLS \
-       [ __NR_mmap ] = (syscall_handler_t *) old_mmap, \
-       [ __NR_select ] = (syscall_handler_t *) sys_select, \
-       [ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
-       [ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
-       [ __NR_shmget ] = (syscall_handler_t *) sys_shmget, \
-       [ __NR_shmat ] = (syscall_handler_t *) wrap_sys_shmat, \
-       [ __NR_shmctl ] = (syscall_handler_t *) sys_shmctl, \
-       [ __NR_semop ] = (syscall_handler_t *) sys_semop, \
-       [ __NR_semget ] = (syscall_handler_t *) sys_semget, \
-       [ __NR_semctl ] = (syscall_handler_t *) sys_semctl, \
-       [ __NR_shmdt ] = (syscall_handler_t *) sys_shmdt, \
-       [ __NR_msgget ] = (syscall_handler_t *) s