Merge branch 'scsi-scan'
authorJeff Garzik <jgarzik@pobox.com>
Tue, 4 Oct 2005 18:24:04 +0000 (14:24 -0400)
committerJeff Garzik <jgarzik@pobox.com>
Tue, 4 Oct 2005 18:24:04 +0000 (14:24 -0400)
430 files changed:
Documentation/Changes
Documentation/DocBook/libata.tmpl
Documentation/SubmittingPatches
Documentation/keys.txt
MAINTAINERS
Makefile
arch/alpha/kernel/entry.S
arch/alpha/kernel/traps.c
arch/arm/Makefile
arch/arm/common/gic.c
arch/arm/common/locomo.c
arch/arm/configs/ixp4xx_defconfig
arch/arm/kernel/io.c
arch/arm/mach-clps711x/fortunet.c
arch/arm/mach-imx/leds-mx1ads.c
arch/arm/mach-iop3xx/common.c
arch/arm/mach-iop3xx/iop321-time.c
arch/arm/mach-iop3xx/iop331-time.c
arch/arm/mach-iop3xx/iq31244-mm.c
arch/arm/mach-iop3xx/iq80321-mm.c
arch/arm/mach-iop3xx/iq80331-mm.c
arch/arm/mach-iop3xx/iq80332-mm.c
arch/arm/mach-ixp2000/core.c
arch/arm/mach-ixp2000/pci.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/ixdp425-setup.c
arch/arm/mach-l7200/core.c
arch/arm/mach-pxa/corgi_lcd.c
arch/arm/mach-pxa/generic.c
arch/arm/mach-s3c2410/usb-simtec.c
arch/arm/mach-versatile/core.c
arch/arm/mach-versatile/pci.c
arch/arm/mm/abort-ev6.S
arch/arm/mm/cache-v6.S
arch/arm/mm/flush.c
arch/arm/plat-omap/common.c
arch/arm/plat-omap/cpu-omap.c
arch/arm/plat-omap/usb.c
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/apic.c
arch/i386/kernel/cpu/amd.c
arch/i386/kernel/cpu/mcheck/k7.c
arch/i386/kernel/cpu/mcheck/non-fatal.c
arch/i386/kernel/cpu/mcheck/p4.c
arch/i386/kernel/cpu/mcheck/p5.c
arch/i386/kernel/cpu/mcheck/p6.c
arch/i386/kernel/cpu/mcheck/winchip.c
arch/i386/kernel/crash.c
arch/i386/kernel/i8259.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/mpparse.c
arch/i386/kernel/nmi.c
arch/i386/kernel/process.c
arch/i386/kernel/smp.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/timers/timer_pit.c
arch/i386/kernel/traps.c
arch/i386/mach-default/setup.c
arch/i386/mach-visws/setup.c
arch/i386/mach-visws/visws_apic.c
arch/i386/mach-voyager/setup.c
arch/i386/mach-voyager/voyager_basic.c
arch/i386/mach-voyager/voyager_smp.c
arch/i386/mach-voyager/voyager_thread.c
arch/i386/oprofile/nmi_timer_int.c
arch/i386/pci/acpi.c
arch/i386/pci/irq.c
arch/i386/power/cpu.c
arch/m32r/Makefile
arch/m32r/lib/usercopy.c
arch/ppc/boot/ld.script
arch/ppc/kernel/perfmon.c
arch/ppc/platforms/4xx/bamboo.c
arch/ppc/platforms/4xx/ebony.c
arch/ppc/platforms/4xx/luan.c
arch/ppc/platforms/4xx/ocotea.c
arch/ppc/platforms/83xx/mpc834x_sys.c
arch/ppc/platforms/85xx/mpc8540_ads.c
arch/ppc/platforms/85xx/mpc8560_ads.c
arch/ppc/platforms/85xx/mpc85xx_ads_common.c
arch/ppc/platforms/85xx/mpc85xx_cds_common.c
arch/ppc/platforms/85xx/sbc8560.c
arch/ppc/platforms/85xx/sbc85xx.c
arch/ppc/platforms/85xx/stx_gp3.c
arch/ppc/platforms/chestnut.c
arch/ppc/platforms/chrp_setup.c
arch/ppc/platforms/gemini_setup.c
arch/ppc/platforms/mvme5100.c
arch/ppc/platforms/pmac_cpufreq.c
arch/ppc/platforms/pmac_feature.c
arch/ppc/platforms/pmac_setup.c
arch/ppc/platforms/powerpmc250.c
arch/ppc/platforms/pplus.c
arch/ppc/platforms/prpmc750.c
arch/ppc/platforms/prpmc800.c
arch/ppc/platforms/radstone_ppc7d.c
arch/ppc/platforms/sandpoint.c
arch/ppc/syslib/mv64x60.c
arch/ppc/syslib/open_pic.c
arch/ppc/syslib/open_pic2.c
arch/ppc/syslib/ppc4xx_setup.c
arch/ppc64/kernel/bpa_iommu.c
arch/ppc64/kernel/kprobes.c
arch/ppc64/kernel/machine_kexec.c
arch/ppc64/mm/hash_native.c
arch/ppc64/mm/tlb.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/signal.c
arch/sparc/kernel/setup.c
arch/sparc64/Kconfig.debug
arch/sparc64/kernel/cpu.c
arch/sparc64/kernel/devices.c
arch/sparc64/kernel/dtlb_backend.S
arch/sparc64/kernel/dtlb_base.S
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/head.S
arch/sparc64/kernel/ktlb.S [new file with mode: 0644]
arch/sparc64/kernel/pci_schizo.c
arch/sparc64/kernel/ptrace.c
arch/sparc64/kernel/setup.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sys32.S
arch/sparc64/kernel/trampoline.S
arch/sparc64/kernel/traps.c
arch/sparc64/kernel/una_asm.S
arch/sparc64/kernel/unaligned.c
arch/sparc64/kernel/us3_cpufreq.c
arch/sparc64/kernel/vmlinux.lds.S
arch/sparc64/lib/strncpy_from_user.S
arch/sparc64/lib/user_fixup.c
arch/sparc64/mm/Makefile
arch/sparc64/mm/extable.c [deleted file]
arch/sparc64/mm/fault.c
arch/sparc64/mm/init.c
arch/sparc64/mm/ultra.S
arch/sparc64/prom/Makefile
arch/sparc64/prom/console.c
arch/sparc64/prom/devops.c
arch/sparc64/prom/init.c
arch/sparc64/prom/map.S [deleted file]
arch/sparc64/prom/memory.c [deleted file]
arch/sparc64/prom/misc.c
arch/sparc64/prom/p1275.c
arch/sparc64/prom/printf.c
arch/sparc64/prom/tree.c
arch/um/Makefile
arch/um/Makefile-i386
arch/um/Makefile-skas
arch/um/Makefile-x86_64
arch/um/drivers/mconsole_user.c
arch/um/drivers/port_kern.c
arch/um/include/common-offsets.h
arch/um/include/os.h
arch/um/include/skas_ptregs.h [new file with mode: 0644]
arch/um/include/sysdep-i386/sc.h [new file with mode: 0644]
arch/um/include/sysdep-i386/sigcontext.h
arch/um/include/sysdep-i386/thread.h [new file with mode: 0644]
arch/um/include/sysdep-x86_64/sc.h [new file with mode: 0644]
arch/um/include/sysdep-x86_64/sigcontext.h
arch/um/include/sysdep-x86_64/thread.h [new file with mode: 0644]
arch/um/include/task.h [new file with mode: 0644]
arch/um/kernel/irq.c
arch/um/kernel/skas/Makefile
arch/um/kernel/skas/util/Makefile [deleted file]
arch/um/kernel/skas/util/mk_ptregs-i386.c [deleted file]
arch/um/kernel/skas/util/mk_ptregs-x86_64.c [deleted file]
arch/um/kernel/trap_kern.c
arch/um/kernel/um_arch.c
arch/um/os-Linux/elf_aux.c
arch/um/os-Linux/util/Makefile [deleted file]
arch/um/os-Linux/util/mk_user_constants.c [deleted file]
arch/um/sys-i386/Makefile
arch/um/sys-i386/kernel-offsets.c
arch/um/sys-i386/user-offsets.c
arch/um/sys-i386/util/Makefile [deleted file]
arch/um/sys-i386/util/mk_sc.c [deleted file]
arch/um/sys-i386/util/mk_thread.c [deleted file]
arch/um/sys-x86_64/Makefile
arch/um/sys-x86_64/kernel-offsets.c
arch/um/sys-x86_64/user-offsets.c
arch/um/sys-x86_64/util/Makefile [deleted file]
arch/um/sys-x86_64/util/mk_sc.c [deleted file]
arch/um/sys-x86_64/util/mk_thread.c [deleted file]
arch/um/util/Makefile [deleted file]
arch/um/util/mk_constants.c [deleted file]
arch/um/util/mk_task.c [deleted file]
arch/x86_64/kernel/kprobes.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/time.c
arch/x86_64/mm/numa.c
drivers/char/drm/drm_drv.c
drivers/char/drm/drm_proc.c
drivers/char/ipmi/ipmi_poweroff.c
drivers/char/n_r3964.c
drivers/char/watchdog/mv64x60_wdt.c
drivers/connector/cn_queue.c
drivers/connector/connector.c
drivers/ide/legacy/ide-cs.c
drivers/ieee1394/amdtp.c
drivers/ieee1394/csr1212.h
drivers/ieee1394/dv1394.c
drivers/ieee1394/eth1394.c
drivers/ieee1394/eth1394.h
drivers/ieee1394/hosts.c
drivers/ieee1394/hosts.h
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/nodemgr.c
drivers/ieee1394/ohci1394.c
drivers/ieee1394/raw1394.c
drivers/ieee1394/sbp2.c
drivers/ieee1394/video1394.c
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/mthca/mthca_cmd.c
drivers/infiniband/hw/mthca/mthca_eq.c
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/input/input.c
drivers/isdn/divert/divert_procfs.c
drivers/isdn/hardware/eicon/diva_didd.c
drivers/isdn/hardware/eicon/divasproc.c
drivers/isdn/hysdn/hysdn_procconf.c
drivers/macintosh/smu.c
drivers/md/dm-ioctl.c
drivers/md/dm-mpath.c
drivers/media/dvb/frontends/tda10021.c
drivers/media/video/bttv-cards.c
drivers/media/video/cpia.c
drivers/media/video/rds.h
drivers/media/video/saa6588.c
drivers/mfd/ucb1x00-ts.c
drivers/mtd/maps/bast-flash.c
drivers/mtd/maps/ixp2000.c
drivers/mtd/maps/ixp4xx.c
drivers/mtd/maps/omap_nor.c
drivers/mtd/maps/sa1100-flash.c
drivers/mtd/nand/s3c2410.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/arm/am79c961a.c
drivers/net/bmac.c
drivers/net/cassini.c [new file with mode: 0644]
drivers/net/cassini.h [new file with mode: 0644]
drivers/net/cs89x0.c
drivers/net/ibmveth.c
drivers/net/irda/vlsi_ir.c
drivers/net/pppoe.c
drivers/net/r8169.c
drivers/net/sk98lin/skge.c
drivers/net/tg3.c
drivers/net/tg3.h
drivers/net/wireless/orinoco.c
drivers/pcmcia/Kconfig
drivers/pcmcia/cardbus.c
drivers/pcmcia/omap_cf.c
drivers/pcmcia/rsrc_nonstatic.c
drivers/pcmcia/ti113x.h
drivers/pcmcia/yenta_socket.c
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
drivers/scsi/sata_mv.c
drivers/scsi/sata_nv.c
drivers/scsi/sata_promise.c
drivers/scsi/sata_sis.c
drivers/scsi/sata_uli.c
drivers/scsi/sata_via.c
drivers/scsi/sg.c
drivers/serial/clps711x.c
drivers/serial/imx.c
drivers/serial/ioc4_serial.c
drivers/serial/s3c2410.c
drivers/serial/serial_cs.c
drivers/usb/core/hcd-pci.c
drivers/usb/host/ohci-lh7a404.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-s3c2410.c
drivers/usb/media/vicam.c
drivers/video/Kconfig
drivers/video/aty/radeon_base.c
drivers/video/aty/radeon_pm.c
drivers/video/aty/radeonfb.h
drivers/video/backlight/corgi_bl.c
drivers/video/cyblafb.c
drivers/video/i810/i810-i2c.c
drivers/video/imxfb.c
drivers/video/intelfb/intelfbdrv.c
drivers/video/pxafb.c
drivers/video/pxafb.h
drivers/video/s3c2410fb.c
fs/9p/fid.c
fs/9p/fid.h
fs/9p/vfs_dentry.c
fs/9p/vfs_dir.c
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/9p/vfs_super.c
fs/Kconfig
fs/aio.c
fs/eventpoll.c
fs/ext2/ialloc.c
fs/ext3/ialloc.c
fs/fuse/dir.c
fs/fuse/file.c
fs/hostfs/hostfs_kern.c
fs/ntfs/ChangeLog
fs/ntfs/layout.h
fs/ntfs/lcnalloc.c
fs/ntfs/lcnalloc.h
fs/ntfs/logfile.c
fs/ntfs/logfile.h
fs/ntfs/mft.c
fs/read_write.c
include/asm-arm/arch-rpc/hardware.h
include/asm-arm/arch-s3c2410/anubis-map.h
include/asm-arm/arch-versatile/io.h
include/asm-arm/elf.h
include/asm-arm/io.h
include/asm-arm/signal.h
include/asm-generic/pgtable.h
include/asm-i386/hw_irq.h
include/asm-ia64/uaccess.h
include/asm-m32r/io.h
include/asm-m32r/uaccess.h
include/asm-mips/pgtable.h
include/asm-ppc/io.h
include/asm-ppc/mv64x60.h
include/asm-ppc64/tlbflush.h
include/asm-ppc64/uaccess.h
include/asm-s390/sigcontext.h
include/asm-s390/signal.h
include/asm-sparc/pgtable.h
include/asm-sparc64/cacheflush.h
include/asm-sparc64/cpudata.h
include/asm-sparc64/head.h
include/asm-sparc64/openprom.h
include/asm-sparc64/oplib.h
include/asm-sparc64/page.h
include/asm-sparc64/pgtable.h
include/asm-sparc64/uaccess.h
include/asm-um/uaccess.h
include/asm-x86_64/msr.h
include/asm-x86_64/pgtable.h
include/linux/aio.h
include/linux/ata.h
include/linux/connector.h
include/linux/if_ether.h
include/linux/key-ui.h
include/linux/key.h
include/linux/libata.h
include/linux/mod_devicetable.h
include/linux/netdevice.h
include/linux/netfilter_ipv4/ip_nat_core.h
include/linux/pci_ids.h
include/linux/sched.h
include/linux/sysctl.h
include/net/llc.h
include/net/llc_conn.h
include/net/llc_sap.h
include/pcmcia/ss.h
include/rdma/ib_verbs.h
ipc/mqueue.c
kernel/cpuset.c
kernel/exit.c
kernel/params.c
kernel/power/power.h
kernel/power/swsusp.c
kernel/signal.c
mm/bootmem.c
mm/mremap.c
mm/slab.c
net/802/p8022.c
net/802/psnap.c
net/802/tr.c
net/appletalk/ddp.c
net/atm/addr.c
net/atm/common.c
net/atm/ioctl.c
net/atm/lec.c
net/atm/signaling.c
net/atm/svc.c
net/core/datagram.c
net/core/dev.c
net/core/neighbour.c
net/core/pktgen.c
net/core/sock.c
net/ethernet/eth.c
net/ieee80211/ieee80211_module.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Makefile
net/ipv4/netfilter/ip_conntrack_proto_gre.c
net/ipv4/netfilter/ip_conntrack_proto_sctp.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/ip_nat_core.c
net/ipv4/netfilter/ip_nat_helper.c
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/netfilter/Kconfig
net/ipv6/netfilter/Makefile
net/irda/irttp.c
net/llc/Makefile
net/llc/af_llc.c
net/llc/llc_c_ac.c
net/llc/llc_c_ev.c
net/llc/llc_conn.c
net/llc/llc_core.c
net/llc/llc_if.c
net/llc/llc_input.c
net/llc/llc_output.c
net/llc/llc_proc.c
net/llc/llc_s_ac.c
net/llc/llc_sap.c
net/llc/llc_station.c
net/llc/sysctl_net_llc.c [new file with mode: 0644]
net/packet/af_packet.c
net/rose/af_rose.c
net/socket.c
scripts/mod/file2alias.c
security/keys/internal.h
security/keys/key.c
security/keys/keyctl.c
security/keys/keyring.c
security/keys/proc.c
security/keys/process_keys.c
security/keys/request_key.c
security/keys/request_key_auth.c
security/selinux/hooks.c

index 5eaab0441d7629dbbae004317df4292ca724e57f..27232be26e1a94eb3b258eeb3a28132326d6bd80 100644 (file)
@@ -237,6 +237,12 @@ udev
 udev is a userspace application for populating /dev dynamically with
 only entries for devices actually present. udev replaces devfs.
 
+FUSE
+----
+
+Needs libfuse 2.4.0 or later.  Absolute minimum is 2.3.0 but mount
+options 'direct_io' and 'kernel_cache' won't work.
+
 Networking
 ==========
 
@@ -390,6 +396,10 @@ udev
 ----
 o <http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html>
 
+FUSE
+----
+o <http://sourceforge.net/projects/fuse>
+
 Networking
 **********
 
index 375ae760dc1ed1112d47874adde4de738ba5079e..d260d92089ade348879bda74b2bf9ae48714d110 100644 (file)
@@ -415,6 +415,362 @@ and other resources, etc.
      </sect1>
   </chapter>
 
+  <chapter id="libataEH">
+        <title>Error handling</title>
+
+       <para>
+       This chapter describes how errors are handled under libata.
+       Readers are advised to read SCSI EH
+       (Documentation/scsi/scsi_eh.txt) and ATA exceptions doc first.
+       </para>
+
+       <sect1><title>Origins of commands</title>
+       <para>
+       In libata, a command is represented with struct ata_queued_cmd
+       or qc.  qc's are preallocated during port initialization and
+       repetitively used for command executions.  Currently only one
+       qc is allocated per port but yet-to-be-merged NCQ branch
+       allocates one for each tag and maps each qc to NCQ tag 1-to-1.
+       </para>
+       <para>
+       libata commands can originate from two sources - libata itself
+       and SCSI midlayer.  libata internal commands are used for
+       initialization and error handling.  All normal blk requests
+       and commands for SCSI emulation are passed as SCSI commands
+       through queuecommand callback of SCSI host template.
+       </para>
+       </sect1>
+
+       <sect1><title>How commands are issued</title>
+
+       <variablelist>
+
+       <varlistentry><term>Internal commands</term>
+       <listitem>
+       <para>
+       First, qc is allocated and initialized using
+       ata_qc_new_init().  Although ata_qc_new_init() doesn't
+       implement any wait or retry mechanism when qc is not
+       available, internal commands are currently issued only during
+       initialization and error recovery, so no other command is
+       active and allocation is guaranteed to succeed.
+       </para>
+       <para>
+       Once allocated qc's taskfile is initialized for the command to
+       be executed.  qc currently has two mechanisms to notify
+       completion.  One is via qc->complete_fn() callback and the
+       other is completion qc->waiting.  qc->complete_fn() callback
+       is the asynchronous path used by normal SCSI translated
+       commands and qc->waiting is the synchronous (issuer sleeps in
+       process context) path used by internal commands.
+       </para>
+       <para>
+       Once initialization is complete, host_set lock is acquired
+       and the qc is issued.
+       </para>
+       </listitem>
+       </varlistentry>
+
+       <varlistentry><term>SCSI commands</term>
+       <listitem>
+       <para>
+       All libata drivers use ata_scsi_queuecmd() as
+       hostt->queuecommand callback.  scmds can either be simulated
+       or translated.  No qc is involved in processing a simulated
+       scmd.  The result is computed right away and the scmd is
+       completed.
+       </para>
+       <para>
+       For a translated scmd, ata_qc_new_init() is invoked to
+       allocate a qc and the scmd is translated into the qc.  SCSI
+       midlayer's completion notification function pointer is stored
+       into qc->scsidone.
+       </para>
+       <para>
+       qc->complete_fn() callback is used for completion
+       notification.  ATA commands use ata_scsi_qc_complete() while
+       ATAPI commands use atapi_qc_complete().  Both functions end up
+       calling qc->scsidone to notify upper layer when the qc is
+       finished.  After translation is completed, the qc is issued
+       with ata_qc_issue().
+       </para>
+       <para>
+       Note that SCSI midlayer invokes hostt->queuecommand while
+       holding host_set lock, so all above occur while holding
+       host_set lock.
+       </para>
+       </listitem>
+       </varlistentry>
+
+       </variablelist>
+       </sect1>
+
+       <sect1><title>How commands are processed</title>
+       <para>
+       Depending on which protocol and which controller are used,
+       commands are processed differently.  For the purpose of
+       discussion, a controller which uses taskfile interface and all
+       standard callbacks is assumed.
+       </para>
+       <para>
+       Currently 6 ATA command protocols are used.  They can be
+       sorted into the following four categories according to how
+       they are processed.
+       </para>
+
+       <variablelist>
+          <varlistentry><term>ATA NO DATA or DMA</term>
+          <listitem>
+          <para>
+          ATA_PROT_NODATA and ATA_PROT_DMA fall into this category.
+          These types of commands don't require any software
+          intervention once issued.  Device will raise interrupt on
+          completion.
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry><term>ATA PIO</term>
+          <listitem>
+          <para>
+          ATA_PROT_PIO is in this category.  libata currently
+          implements PIO with polling.  ATA_NIEN bit is set to turn
+          off interrupt and pio_task on ata_wq performs polling and
+          IO.
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry><term>ATAPI NODATA or DMA</term>
+          <listitem>
+          <para>
+          ATA_PROT_ATAPI_NODATA and ATA_PROT_ATAPI_DMA are in this
+          category.  packet_task is used to poll BSY bit after
+          issuing PACKET command.  Once BSY is turned off by the
+          device, packet_task transfers CDB and hands off processing
+          to interrupt handler.
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry><term>ATAPI PIO</term>
+          <listitem>
+          <para>
+          ATA_PROT_ATAPI is in this category.  ATA_NIEN bit is set
+          and, as in ATAPI NODATA or DMA, packet_task submits cdb.
+          However, after submitting cdb, further processing (data
+          transfer) is handed off to pio_task.
+          </para>
+          </listitem>
+          </varlistentry>
+       </variablelist>
+        </sect1>
+
+       <sect1><title>How commands are completed</title>
+       <para>
+       Once issued, all qc's are either completed with
+       ata_qc_complete() or time out.  For commands which are handled
+       by interrupts, ata_host_intr() invokes ata_qc_complete(), and,
+       for PIO tasks, pio_task invokes ata_qc_complete().  In error
+       cases, packet_task may also complete commands.
+       </para>
+       <para>
+       ata_qc_complete() does the following.
+       </para>
+
+       <orderedlist>
+
+       <listitem>
+       <para>
+       DMA memory is unmapped.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       ATA_QCFLAG_ACTIVE is clared from qc->flags.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       qc->complete_fn() callback is invoked.  If the return value of
+       the callback is not zero.  Completion is short circuited and
+       ata_qc_complete() returns.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       __ata_qc_complete() is called, which does
+          <orderedlist>
+
+          <listitem>
+          <para>
+          qc->flags is cleared to zero.
+          </para>
+          </listitem>
+
+          <listitem>
+          <para>
+          ap->active_tag and qc->tag are poisoned.
+          </para>
+          </listitem>
+
+          <listitem>
+          <para>
+          qc->waiting is claread &amp; completed (in that order).
+          </para>
+          </listitem>
+
+          <listitem>
+          <para>
+          qc is deallocated by clearing appropriate bit in ap->qactive.
+          </para>
+          </listitem>
+
+          </orderedlist>
+       </para>
+       </listitem>
+
+       </orderedlist>
+
+       <para>
+       So, it basically notifies upper layer and deallocates qc.  One
+       exception is short-circuit path in #3 which is used by
+       atapi_qc_complete().
+       </para>
+       <para>
+       For all non-ATAPI commands, whether it fails or not, almost
+       the same code path is taken and very little error handling
+       takes place.  A qc is completed with success status if it
+       succeeded, with failed status otherwise.
+       </para>
+       <para>
+       However, failed ATAPI commands require more handling as
+       REQUEST SENSE is needed to acquire sense data.  If an ATAPI
+       command fails, ata_qc_complete() is invoked with error status,
+       which in turn invokes atapi_qc_complete() via
+       qc->complete_fn() callback.
+       </para>
+       <para>
+       This makes atapi_qc_complete() set scmd->result to
+       SAM_STAT_CHECK_CONDITION, complete the scmd and return 1.  As
+       the sense data is empty but scmd->result is CHECK CONDITION,
+       SCSI midlayer will invoke EH for the scmd, and returning 1
+       makes ata_qc_complete() to return without deallocating the qc.
+       This leads us to ata_scsi_error() with partially completed qc.
+       </para>
+
+       </sect1>
+
+       <sect1><title>ata_scsi_error()</title>
+       <para>
+       ata_scsi_error() is the current hostt->eh_strategy_handler()
+       for libata.  As discussed above, this will be entered in two
+       cases - timeout and ATAPI error completion.  This function
+       calls low level libata driver's eng_timeout() callback, the
+       standard callback for which is ata_eng_timeout().  It checks
+       if a qc is active and calls ata_qc_timeout() on the qc if so.
+       Actual error handling occurs in ata_qc_timeout().
+       </para>
+       <para>
+       If EH is invoked for timeout, ata_qc_timeout() stops BMDMA and
+       completes the qc.  Note that as we're currently in EH, we
+       cannot call scsi_done.  As described in SCSI EH doc, a
+       recovered scmd should be either retried with
+       scsi_queue_insert() or finished with scsi_finish_command().
+       Here, we override qc->scsidone with scsi_finish_command() and
+       calls ata_qc_complete().
+       </para>
+       <para>
+       If EH is invoked due to a failed ATAPI qc, the qc here is
+       completed but not deallocated.  The purpose of this
+       half-completion is to use the qc as place holder to make EH
+       code reach this place.  This is a bit hackish, but it works.
+       </para>
+       <para>
+       Once control reaches here, the qc is deallocated by invoking
+       __ata_qc_complete() explicitly.  Then, internal qc for REQUEST
+       SENSE is issued.  Once sense data is acquired, scmd is
+       finished by directly invoking scsi_finish_command() on the
+       scmd.  Note that as we already have completed and deallocated
+       the qc which was associated with the scmd, we don't need
+       to/cannot call ata_qc_complete() again.
+       </para>
+
+       </sect1>
+
+       <sect1><title>Problems with the current EH</title>
+
+       <itemizedlist>
+
+       <listitem>
+       <para>
+       Error representation is too crude.  Currently any and all
+       error conditions are represented with ATA STATUS and ERROR
+       registers.  Errors which aren't ATA device errors are treated
+       as ATA device errors by setting ATA_ERR bit.  Better error
+       descriptor which can properly represent ATA and other
+       errors/exceptions is needed.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       When handling timeouts, no action is taken to make device
+       forget about the timed out command and ready for new commands.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       EH handling via ata_scsi_error() is not properly protected
+       from usual command processing.  On EH entrance, the device is
+       not in quiescent state.  Timed out commands may succeed or
+       fail any time.  pio_task and atapi_task may still be running.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Too weak error recovery.  Devices / controllers causing HSM
+       mismatch errors and other errors quite often require reset to
+       return to known state.  Also, advanced error handling is
+       necessary to support features like NCQ and hotplug.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       ATA errors are directly handled in the interrupt handler and
+       PIO errors in pio_task.  This is problematic for advanced
+       error handling for the following reasons.
+       </para>
+       <para>
+       First, advanced error handling often requires context and
+       internal qc execution.
+       </para>
+       <para>
+       Second, even a simple failure (say, CRC error) needs
+       information gathering and could trigger complex error handling
+       (say, resetting &amp; reconfiguring).  Having multiple code
+       paths to gather information, enter EH and trigger actions
+       makes life painful.
+       </para>
+       <para>
+       Third, scattered EH code makes implementing low level drivers
+       difficult.  Low level drivers override libata callbacks.  If
+       EH is scattered over several places, each affected callbacks
+       should perform its part of error handling.  This can be error
+       prone and painful.
+       </para>
+       </listitem>
+
+       </itemizedlist>
+       </sect1>
+  </chapter>
+
   <chapter id="libataExt">
      <title>libata Library</title>
 !Edrivers/scsi/libata-core.c
@@ -431,6 +787,722 @@ and other resources, etc.
 !Idrivers/scsi/libata-scsi.c
   </chapter>
 
+  <chapter id="ataExceptions">
+     <title>ATA errors &amp; exceptions</title>
+
+  <para>
+  This chapter tries to identify what error/exception conditions exist
+  for ATA/ATAPI devices and describe how they should be handled in
+  implementation-neutral way.
+  </para>
+
+  <para>
+  The term 'error' is used to describe conditions where either an
+  explicit error condition is reported from device or a command has
+  timed out.
+  </para>
+
+  <para>
+  The term 'exception' is either used to describe exceptional
+  conditions which are not errors (say, power or hotplug events), or
+  to describe both errors and non-error exceptional conditions.  Where
+  explicit distinction between error and exception is necessary, the
+  term 'non-error exception' is used.
+  </para>
+
+  <sect1 id="excat">
+     <title>Exception categories</title>
+     <para>
+     Exceptions are described primarily with respect to legacy
+     taskfile + bus master IDE interface.  If a controller provides
+     other better mechanism for error reporting, mapping those into
+     categories described below shouldn't be difficult.
+     </para>
+
+     <para>
+     In the following sections, two recovery actions - reset and
+     reconfiguring transport - are mentioned.  These are described
+     further in <xref linkend="exrec"/>.
+     </para>
+
+     <sect2 id="excatHSMviolation">
+        <title>HSM violation</title>
+        <para>
+        This error is indicated when STATUS value doesn't match HSM
+        requirement during issuing or excution any ATA/ATAPI command.
+        </para>
+
+       <itemizedlist>
+       <title>Examples</title>
+
+        <listitem>
+       <para>
+       ATA_STATUS doesn't contain !BSY &amp;&amp; DRDY &amp;&amp; !DRQ while trying
+       to issue a command.
+        </para>
+       </listitem>
+
+        <listitem>
+       <para>
+       !BSY &amp;&amp; !DRQ during PIO data transfer.
+        </para>
+       </listitem>
+
+        <listitem>
+       <para>
+       DRQ on command completion.
+        </para>
+       </listitem>
+
+        <listitem>
+       <para>
+       !BSY &amp;&amp; ERR after CDB tranfer starts but before the
+        last byte of CDB is transferred.  ATA/ATAPI standard states
+        that &quot;The device shall not terminate the PACKET command
+        with an error before the last byte of the command packet has
+        been written&quot; in the error outputs description of PACKET
+        command and the state diagram doesn't include such
+        transitions.
+       </para>
+       </listitem>
+
+       </itemizedlist>
+
+       <para>
+       In these cases, HSM is violated and not much information
+       regarding the error can be acquired from STATUS or ERROR
+       register.  IOW, this error can be anything - driver bug,
+       faulty device, controller and/or cable.
+       </para>
+
+       <para>
+       As HSM is violated, reset is necessary to restore known state.
+       Reconfiguring transport for lower speed might be helpful too
+       as transmission errors sometimes cause this kind of errors.
+       </para>
+     </sect2>
+     
+     <sect2 id="excatDevErr">
+        <title>ATA/ATAPI device error (non-NCQ / non-CHECK CONDITION)</title>
+
+       <para>
+       These are errors detected and reported by ATA/ATAPI devices
+       indicating device problems.  For this type of errors, STATUS
+       and ERROR register values are valid and describe error
+       condition.  Note that some of ATA bus errors are detected by
+       ATA/ATAPI devices and reported using the same mechanism as
+       device errors.  Those cases are described later in this
+       section.
+       </para>
+
+       <para>
+       For ATA commands, this type of errors are indicated by !BSY
+       &amp;&amp; ERR during command execution and on completion.
+       </para>
+
+       <para>For ATAPI commands,</para>
+
+       <itemizedlist>
+
+       <listitem>
+       <para>
+       !BSY &amp;&amp; ERR &amp;&amp; ABRT right after issuing PACKET
+       indicates that PACKET command is not supported and falls in
+       this category.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       !BSY &amp;&amp; ERR(==CHK) &amp;&amp; !ABRT after the last
+       byte of CDB is transferred indicates CHECK CONDITION and
+       doesn't fall in this category.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       !BSY &amp;&amp; ERR(==CHK) &amp;&amp; ABRT after the last byte
+        of CDB is transferred *probably* indicates CHECK CONDITION and
+        doesn't fall in this category.
+       </para>
+       </listitem>
+
+       </itemizedlist>
+
+       <para>
+       Of errors detected as above, the followings are not ATA/ATAPI
+       device errors but ATA bus errors and should be handled
+       according to <xref linkend="excatATAbusErr"/>.
+       </para>
+
+       <variablelist>
+
+          <varlistentry>
+          <term>CRC error during data transfer</term>
+          <listitem>
+          <para>
+          This is indicated by ICRC bit in the ERROR register and
+          means that corruption occurred during data transfer.  Upto
+          ATA/ATAPI-7, the standard specifies that this bit is only
+          applicable to UDMA transfers but ATA/ATAPI-8 draft revision
+          1f says that the bit may be applicable to multiword DMA and
+          PIO.
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry>
+          <term>ABRT error during data transfer or on completion</term>
+          <listitem>
+          <para>
+          Upto ATA/ATAPI-7, the standard specifies that ABRT could be
+          set on ICRC errors and on cases where a device is not able
+          to complete a command.  Combined with the fact that MWDMA
+          and PIO transfer errors aren't allowed to use ICRC bit upto
+          ATA/ATAPI-7, it seems to imply that ABRT bit alone could
+          indicate tranfer errors.
+          </para>
+          <para>
+          However, ATA/ATAPI-8 draft revision 1f removes the part
+          that ICRC errors can turn on ABRT.  So, this is kind of
+          gray area.  Some heuristics are needed here.
+          </para>
+          </listitem>
+          </varlistentry>
+
+       </variablelist>
+
+       <para>
+       ATA/ATAPI device errors can be further categorized as follows.
+       </para>
+
+       <variablelist>
+
+          <varlistentry>
+          <term>Media errors</term>
+          <listitem>
+          <para>
+          This is indicated by UNC bit in the ERROR register.  ATA
+          devices reports UNC error only after certain number of
+          retries cannot recover the data, so there's nothing much
+          else to do other than notifying upper layer.
+          </para>
+          <para>
+          READ and WRITE commands report CHS or LBA of the first
+          failed sector but ATA/ATAPI standard specifies that the
+          amount of transferred data on error completion is
+          indeterminate, so we cannot assume that sectors preceding
+          the failed sector have been transferred and thus cannot
+          complete those sectors successfully as SCSI does.
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry>
+          <term>Media changed / media change requested error</term>
+          <listitem>
+          <para>
+          &lt;&lt;TODO: fill here&gt;&gt;
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry><term>Address error</term>
+          <listitem>
+          <para>
+          This is indicated by IDNF bit in the ERROR register.
+          Report to upper layer.
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry><term>Other errors</term>
+          <listitem>
+          <para>
+          This can be invalid command or parameter indicated by ABRT
+          ERROR bit or some other error condition.  Note that ABRT
+          bit can indicate a lot of things including ICRC and Address
+          errors.  Heuristics needed.
+          </para>
+          </listitem>
+          </varlistentry>
+
+       </variablelist>
+
+       <para>
+       Depending on commands, not all STATUS/ERROR bits are
+       applicable.  These non-applicable bits are marked with
+       &quot;na&quot; in the output descriptions but upto ATA/ATAPI-7
+       no definition of &quot;na&quot; can be found.  However,
+       ATA/ATAPI-8 draft revision 1f describes &quot;N/A&quot; as
+       follows.
+       </para>
+
+       <blockquote>
+       <variablelist>
+          <varlistentry><term>3.2.3.3a N/A</term>
+          <listitem>
+          <para>
+          A keyword the indicates a field has no defined value in
+          this standard and should not be checked by the host or
+          device. N/A fields should be cleared to zero.
+          </para>
+          </listitem>
+          </varlistentry>
+       </variablelist>
+       </blockquote>
+
+       <para>
+       So, it seems reasonable to assume that &quot;na&quot; bits are
+       cleared to zero by devices and thus need no explicit masking.
+       </para>
+
+     </sect2>
+
+     <sect2 id="excatATAPIcc">
+        <title>ATAPI device CHECK CONDITION</title>
+
+       <para>
+       ATAPI device CHECK CONDITION error is indicated by set CHK bit
+       (ERR bit) in the STATUS register after the last byte of CDB is
+       transferred for a PACKET command.  For this kind of errors,
+       sense data should be acquired to gather information regarding
+       the errors.  REQUEST SENSE packet command should be used to
+       acquire sense data.
+       </para>
+
+       <para>
+       Once sense data is acquired, this type of errors can be
+       handled similary to other SCSI errors.  Note that sense data
+       may indicate ATA bus error (e.g. Sense Key 04h HARDWARE ERROR
+       &amp;&amp; ASC/ASCQ 47h/00h SCSI PARITY ERROR).  In such
+       cases, the error should be considered as an ATA bus error and
+       handled according to <xref linkend="excatATAbusErr"/>.
+       </para>
+
+     </sect2>
+
+     <sect2 id="excatNCQerr">
+        <title>ATA device error (NCQ)</title>
+
+       <para>
+       NCQ command error is indicated by cleared BSY and set ERR bit
+       during NCQ command phase (one or more NCQ commands
+       outstanding).  Although STATUS and ERROR registers will
+       contain valid values describing the error, READ LOG EXT is
+       required to clear the error condition, determine which command
+       has failed and acquire more information.
+       </para>
+
+       <para>
+       READ LOG EXT Log Page 10h reports which tag has failed and
+       taskfile register values describing the error.  With this
+       information the failed command can be handled as a normal ATA
+       command error as in <xref linkend="excatDevErr"/> and all
+       other in-flight commands must be retried.  Note that this
+       retry should not be counted - it's likely that commands
+       retried this way would have completed normally if it were not
+       for the failed command.
+       </para>
+
+       <para>
+       Note that ATA bus errors can be reported as ATA device NCQ
+       errors.  This should be handled as described in <xref
+       linkend="excatATAbusErr"/>.
+       </para>
+
+       <para>
+       If READ LOG EXT Log Page 10h fails or reports NQ, we're
+       thoroughly screwed.  This condition should be treated
+       according to <xref linkend="excatHSMviolation"/>.
+       </para>
+
+     </sect2>
+
+     <sect2 id="excatATAbusErr">
+        <title>ATA bus error</title>
+
+       <para>
+       ATA bus error means that data corruption occurred during
+       transmission over ATA bus (SATA or PATA).  This type of errors
+       can be indicated by
+       </para>
+
+       <itemizedlist>
+
+       <listitem>
+       <para>
+       ICRC or ABRT error as described in <xref linkend="excatDevErr"/>.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Controller-specific error completion with error information
+       indicating transmission error.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       On some controllers, command timeout.  In this case, there may
+       be a mechanism to determine that the timeout is due to
+       transmission error.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Unknown/random errors, timeouts and all sorts of weirdities.
+       </para>
+       </listitem>
+
+       </itemizedlist>
+
+       <para>
+       As described above, transmission errors can cause wide variety
+       of symptoms ranging from device ICRC error to random device
+       lockup, and, for many cases, there is no way to tell if an
+       error condition is due to transmission error or not;
+       therefore, it's necessary to employ some kind of heuristic
+       when dealing with errors and timeouts.  For example,
+       encountering repetitive ABRT errors for known supported
+       command is likely to indicate ATA bus error.
+       </para>
+
+       <para>
+       Once it's determined that ATA bus errors have possibly
+       occurred, lowering ATA bus transmission speed is one of
+       actions which may alleviate the problem.  See <xref
+       linkend="exrecReconf"/> for more information.
+       </para>
+
+     </sect2>
+
+     <sect2 id="excatPCIbusErr">
+        <title>PCI bus error</title>
+
+       <para>
+       Data corruption or other failures during transmission over PCI
+       (or other system bus).  For standard BMDMA, this is indicated
+       by Error bit in the BMDMA Status register.  This type of
+       errors must be logged as it indicates something is very wrong
+       with the system.  Resetting host controller is recommended.
+       </para>
+
+     </sect2>
+
+     <sect2 id="excatLateCompletion">
+        <title>Late completion</title>
+
+       <para>
+       This occurs when timeout occurs and the timeout handler finds
+       out that the timed out command has completed successfully or
+       with error.  This is usually caused by lost interrupts.  This
+       type of errors must be logged.  Resetting host controller is
+       recommended.
+       </para>
+
+     </sect2>
+
+     <sect2 id="excatUnknown">
+        <title>Unknown error (timeout)</title>
+
+       <para>
+       This is when timeout occurs and the command is still
+       processing or the host and device are in unknown state.  When
+       this occurs, HSM could be in any valid or invalid state.  To
+       bring the device to known state and make it forget about the
+       timed out command, resetting is necessary.  The timed out
+       command may be retried.
+       </para>
+
+       <para>
+       Timeouts can also be caused by transmission errors.  Refer to
+       <xref linkend="excatATAbusErr"/> for more details.
+       </para>
+
+     </sect2>
+
+     <sect2 id="excatHoplugPM">
+        <title>Hotplug and power management exceptions</title>
+
+       <para>
+       &lt;&lt;TODO: fill here&gt;&gt;
+       </para>
+
+     </sect2>
+
+  </sect1>
+
+  <sect1 id="exrec">
+     <title>EH recovery actions</title>
+
+     <para>
+     This section discusses several important recovery actions.
+     </para>
+
+     <sect2 id="exrecClr">
+        <title>Clearing error condition</title>
+
+       <para>
+       Many controllers require its error registers to be cleared by
+       error handler.  Different controllers may have different
+       requirements.
+       </para>
+
+       <para>
+       For SATA, it's strongly recommended to clear at least SError
+       register during error handling.
+       </para>
+     </sect2>
+
+     <sect2 id="exrecRst">
+        <title>Reset</title>
+
+       <para>
+       During EH, resetting is necessary in the following cases.
+       </para>
+
+       <itemizedlist>
+
+       <listitem>
+       <para>
+       HSM is in unknown or invalid state
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       HBA is in unknown or invalid state
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       EH needs to make HBA/device forget about in-flight commands
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       HBA/device behaves weirdly
+       </para>
+       </listitem>
+
+       </itemizedlist>
+
+       <para>
+       Resetting during EH might be a good idea regardless of error
+       condition to improve EH robustness.  Whether to reset both or
+       either one of HBA and device depends on situation but the
+       following scheme is recommended.
+       </para>
+
+       <itemizedlist>
+
+       <listitem>
+       <para>
+       When it's known that HBA is in ready state but ATA/ATAPI
+       device in in unknown state, reset only device.
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       If HBA is in unknown state, reset both HBA and device.
+       </para>
+       </listitem>
+
+       </itemizedlist>
+
+       <para>
+       HBA resetting is implementation specific.  For a controller
+       complying to taskfile/BMDMA PCI IDE, stopping active DMA
+       transaction may be sufficient iff BMDMA state is the only HBA
+       context.  But even mostly taskfile/BMDMA PCI IDE complying
+       controllers may have implementation specific requirements and
+       mechanism to reset themselves.  This must be addressed by
+       specific drivers.
+       </para>
+
+       <para>
+       OTOH, ATA/ATAPI standard describes in detail ways to reset
+       ATA/ATAPI devices.
+       </para>
+
+       <variablelist>
+
+          <varlistentry><term>PATA hardware reset</term>
+          <listitem>
+          <para>
+          This is hardware initiated device reset signalled with
+          asserted PATA RESET- signal.  There is no standard way to
+          initiate hardware reset from software although some
+          hardware provides registers that allow driver to directly
+          tweak the RESET- signal.
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry><term>Software reset</term>
+          <listitem>
+          <para>
+          This is achieved by turning CONTROL SRST bit on for at
+          least 5us.  Both PATA and SATA support it but, in case of
+          SATA, this may require controller-specific support as the
+          second Register FIS to clear SRST should be transmitted
+          while BSY bit is still set.  Note that on PATA, this resets
+          both master and slave devices on a channel.
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry><term>EXECUTE DEVICE DIAGNOSTIC command</term>
+          <listitem>
+          <para>
+          Although ATA/ATAPI standard doesn't describe exactly, EDD
+          implies some level of resetting, possibly similar level
+          with software reset.  Host-side EDD protocol can be handled
+          with normal command processing and most SATA controllers
+          should be able to handle EDD's just like other commands.
+          As in software reset, EDD affects both devices on a PATA
+          bus.
+          </para>
+          <para>
+          Although EDD does reset devices, this doesn't suit error
+          handling as EDD cannot be issued while BSY is set and it's
+          unclear how it will act when device is in unknown/weird
+          state.
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry><term>ATAPI DEVICE RESET command</term>
+          <listitem>
+          <para>
+          This is very similar to software reset except that reset
+          can be restricted to the selected device without affecting
+          the other device sharing the cable.
+          </para>
+          </listitem>
+          </varlistentry>
+
+          <varlistentry><term>SATA phy reset</term>
+          <listitem>
+          <para>
+          This is the preferred way of resetting a SATA device.  In
+          effect, it's identical to PATA hardware reset.  Note that
+          this can be done with the standard SCR Control register.
+          As such, it's usually easier to implement than software
+          reset.
+          </para>
+          </listitem>
+          </varlistentry>
+
+       </variablelist>
+
+       <para>
+       One more thing to consider when resetting devices is that
+       resetting clears certain configuration parameters and they
+       need to be set to their previous or newly adjusted values
+       after reset.
+       </para>
+
+       <para>
+       Parameters affected are.
+       </para>
+
+       <itemizedlist>
+
+       <listitem>
+       <para>
+       CHS set up with INITIALIZE DEVICE PARAMETERS (seldomly used)
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Parameters set with SET FEATURES including transfer mode setting
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Block count set with SET MULTIPLE MODE
+       </para>
+       </listitem>
+
+       <listitem>
+       <para>
+       Other parameters (SET MAX, MEDIA LOCK...)
+       </para>
+       </listitem>
+
+       </itemizedlist>
+
+       <para>
+       ATA/ATAPI standard specifies that some parameters must be
+       maintained across hardware or software reset, but doesn't
+       strictly specify all of them.  Always reconfiguring needed
+       parameters after reset is required for robustness.  Note that
+       this also applies when resuming from deep sleep (power-off).
+       </para>
+
+       <para>
+       Also, ATA/ATAPI standard requires that IDENTIFY DEVICE /
+       IDENTIFY PACKET DEVICE is issued after any configuration
+       parameter is updated or a hardware reset and the result used
+       for further operation.  OS driver is required to implement
+       revalidation mechanism to support this.
+       </para>
+
+     </sect2>
+
+     <sect2 id="exrecReconf">
+        <title>Reconfigure transport</title>
+
+       <para>
+       For both PATA and SATA, a lot of corners are cut for cheap
+       connectors, cables or controllers and it's quite common to see
+       high transmission error rate.  This can be mitigated by
+       lowering transmission speed.
+       </para>
+
+       <para>
+       The following is a possible scheme Jeff Garzik suggested.
+       </para>
+
+       <blockquote>
+       <para>
+       If more than $N (3?) transmission errors happen in 15 minutes,
+       </para> 
+       <itemizedlist>
+       <listitem>
+       <para>
+       if SATA, decrease SATA PHY speed.  if speed cannot be decreased,
+       </para>
+       </listitem>
+       <listitem>
+       <para>
+       decrease UDMA xfer speed.  if at UDMA0, switch to PIO4,
+       </para>
+       </listitem>
+       <listitem>
+       <para>
+       decrease PIO xfer speed.  if at PIO3, complain, but continue
+       </para>
+       </listitem>
+       </itemizedlist>
+       </blockquote>
+
+     </sect2>
+
+  </sect1>
+
+  </chapter>
+
   <chapter id="PiixInt">
      <title>ata_piix Internals</title>
 !Idrivers/scsi/ata_piix.c
index 7f43b040311e526e3e3fdf36f1f3a6f7d98f0f18..1d96efec5e8f9615ba0446f0ea7c87731b0ca553 100644 (file)
@@ -301,8 +301,68 @@ now, but you can do this to mark internal company procedures or just
 point out some special detail about the sign-off. 
 
 
+12) The canonical patch format
 
-12) More references for submitting patches
+The canonical patch subject line is:
+
+    Subject: [PATCH 001/123] [<area>:] <explanation>
+
+The canonical patch message body contains the following:
+
+  - A "from" line specifying the patch author.
+
+  - An empty line.
+
+  - The body of the explanation, which will be copied to the
+    permanent changelog to describe this patch.
+
+  - The "Signed-off-by:" lines, described above, which will
+    also go in the changelog.
+
+  - A marker line containing simply "---".
+
+  - Any additional comments not suitable for the changelog.
+
+  - The actual patch (diff output).
+
+The Subject line format makes it very easy to sort the emails
+alphabetically by subject line - pretty much any email reader will
+support that - since because the sequence number is zero-padded,
+the numerical and alphabetic sort is the same.
+
+See further details on how to phrase the "<explanation>" in the
+"Subject:" line in Andrew Morton's "The perfect patch", referenced
+below.
+
+The "from" line must be the very first line in the message body,
+and has the form:
+
+        From: Original Author <author@example.com>
+
+The "from" line specifies who will be credited as the author of the
+patch in the permanent changelog.  If the "from" line is missing,
+then the "From:" line from the email header will be used to determine
+the patch author in the changelog.
+
+The explanation body will be committed to the permanent source
+changelog, so should make sense to a competent reader who has long
+since forgotten the immediate details of the discussion that might
+have led to this patch.
+
+The "---" marker line serves the essential purpose of marking for patch
+handling tools where the changelog message ends.
+
+One good use for the additional comments after the "---" marker is for
+a diffstat, to show what files have changed, and the number of inserted
+and deleted lines per file.  A diffstat is especially useful on bigger
+patches.  Other comments relevant only to the moment or the maintainer,
+not suitable for the permanent changelog, should also go here.
+
+See more details on the proper patch format in the following
+references.
+
+
+13) More references for submitting patches
 
 Andrew Morton, "The perfect patch" (tpp).
   <http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt>
@@ -310,6 +370,14 @@ Andrew Morton, "The perfect patch" (tpp).
 Jeff Garzik, "Linux kernel patch submission format."
   <http://linux.yyz.us/patch-format.html>
 
+Greg KH, "How to piss off a kernel subsystem maintainer"
+  <http://www.kroah.com/log/2005/03/31/>
+
+Kernel Documentation/CodingStyle
+  <http://sosdg.org/~coywolf/lxr/source/Documentation/CodingStyle>
+
+Linus Torvald's mail on the canonical patch format:
+  <http://lkml.org/lkml/2005/4/7/183>
 
 
 -----------------------------------
index 0321ded4b9ae2df9b8dc469f8e8aa1dd5c216da8..b22e7c8d059a1666d3c3d4f02e2a01b464b19fab 100644 (file)
@@ -195,8 +195,8 @@ KEY ACCESS PERMISSIONS
 ======================
 
 Keys have an owner user ID, a group access ID, and a permissions mask. The mask
-has up to eight bits each for user, group and other access. Only five of each
-set of eight bits are defined. These permissions granted are:
+has up to eight bits each for possessor, user, group and other access. Only
+five of each set of eight bits are defined. These permissions granted are:
 
  (*) View
 
@@ -241,16 +241,16 @@ about the status of the key service:
      type, description and permissions. The payload of the key is not available
      this way:
 
-       SERIAL   FLAGS  USAGE EXPY PERM   UID   GID   TYPE      DESCRIPTION: SUMMARY
-       00000001 I-----    39 perm 1f0000     0     0 keyring   _uid_ses.0: 1/4
-       00000002 I-----     2 perm 1f0000     0     0 keyring   _uid.0: empty
-       00000007 I-----     1 perm 1f0000     0     0 keyring   _pid.1: empty
-       0000018d I-----     1 perm 1f0000     0     0 keyring   _pid.412: empty
-       000004d2 I--Q--     1 perm 1f0000    32    -1 keyring   _uid.32: 1/4
-       000004d3 I--Q--     3 perm 1f0000    32    -1 keyring   _uid_ses.32: empty
-       00000892 I--QU-     1 perm 1f0000     0     0 user      metal:copper: 0
-       00000893 I--Q-N     1  35s 1f0000     0     0 user      metal:silver: 0
-       00000894 I--Q--     1  10h 1f0000     0     0 user      metal:gold: 0
+       SERIAL   FLAGS  USAGE EXPY PERM     UID   GID   TYPE      DESCRIPTION: SUMMARY
+       00000001 I-----    39 perm 1f1f0000     0     0 keyring   _uid_ses.0: 1/4
+       00000002 I-----     2 perm 1f1f0000     0     0 keyring   _uid.0: empty
+       00000007 I-----     1 perm 1f1f0000     0     0 keyring   _pid.1: empty
+       0000018d I-----     1 perm 1f1f0000     0     0 keyring   _pid.412: empty
+       000004d2 I--Q--     1 perm 1f1f0000    32    -1 keyring   _uid.32: 1/4
+       000004d3 I--Q--     3 perm 1f1f0000    32    -1 keyring   _uid_ses.32: empty
+       00000892 I--QU-     1 perm 1f000000     0     0 user      metal:copper: 0
+       00000893 I--Q-N     1  35s 1f1f0000     0     0 user      metal:silver: 0
+       00000894 I--Q--     1  10h 001f0000     0     0 user      metal:gold: 0
 
      The flags are:
 
@@ -637,6 +637,34 @@ call, and the key released upon close. How to deal with conflicting keys due to
 two different users opening the same file is left to the filesystem author to
 solve.
 
+Note that there are two different types of pointers to keys that may be
+encountered:
+
+ (*) struct key *
+
+     This simply points to the key structure itself. Key structures will be at
+     least four-byte aligned.
+
+ (*) key_ref_t
+
+     This is equivalent to a struct key *, but the least significant bit is set
+     if the caller "possesses" the key. By "possession" it is meant that the
+     calling processes has a searchable link to the key from one of its
+     keyrings. There are three functions for dealing with these:
+
+       key_ref_t make_key_ref(const struct key *key,
+                              unsigned long possession);
+
+       struct key *key_ref_to_ptr(const key_ref_t key_ref);
+
+       unsigned long is_key_possessed(const key_ref_t key_ref);
+
+     The first function constructs a key reference from a key pointer and
+     possession information (which must be 0 or 1 and not any other value).
+
+     The second function retrieves the key pointer from a reference and the
+     third retrieves the possession flag.
+
 When accessing a key's payload contents, certain precautions must be taken to
 prevent access vs modification races. See the section "Notes on accessing
 payload contents" for more information.
@@ -665,7 +693,11 @@ payload contents" for more information.
 
        void key_put(struct key *key);
 
-    This can be called from interrupt context. If CONFIG_KEYS is not set then
+    Or:
+
+       void key_ref_put(key_ref_t key_ref);
+
+    These can be called from interrupt context. If CONFIG_KEYS is not set then
     the argument will not be parsed.
 
 
@@ -689,13 +721,17 @@ payload contents" for more information.
 
 (*) If a keyring was found in the search, this can be further searched by:
 
-       struct key *keyring_search(struct key *keyring,
-                                  const struct key_type *type,
-                                  const char *description)
+       key_ref_t keyring_search(key_ref_t keyring_ref,
+                                const struct key_type *type,
+                                const char *description)
 
     This searches the keyring tree specified for a matching key. Error ENOKEY
-    is returned upon failure. If successful, the returned key will need to be
-    released.
+    is returned upon failure (use IS_ERR/PTR_ERR to determine). If successful,
+    the returned key will need to be released.
+
+    The possession attribute from the keyring reference is used to control
+    access through the permissions mask and is propagated to the returned key
+    reference pointer if successful.
 
 
 (*) To check the validity of a key, this function can be called:
@@ -732,7 +768,7 @@ More complex payload contents must be allocated and a pointer to them set in
 key->payload.data. One of the following ways must be selected to access the
 data:
 
- (1) Unmodifyable key type.
+ (1) Unmodifiable key type.
 
      If the key type does not have a modify method, then the key's payload can
      be accessed without any form of locking, provided that it's known to be
index 7d1dd5bad39ad809034c7715b6a672d3483cd322..abf7f7a17ae0eac9f5cd36acfdac298a3dbf8e3e 100644 (file)
@@ -604,6 +604,15 @@ P: H. Peter Anvin
 M:     hpa@zytor.com
 S:     Maintained
 
+CPUSETS
+P:     Paul Jackson
+P:     Simon Derr
+M:     pj@sgi.com
+M:     simon.derr@bull.net
+L:     linux-kernel@vger.kernel.org
+W:     http://www.bullopensource.org/cpuset/
+S:     Supported
+
 CRAMFS FILESYSTEM
 W:     http://sourceforge.net/projects/cramfs/
 S:     Orphan
@@ -1159,11 +1168,6 @@ L:       linux1394-devel@lists.sourceforge.net
 W:     http://www.linux1394.org/
 S:     Orphan
 
-IEEE 1394 SBP2
-L:     linux1394-devel@lists.sourceforge.net
-W:     http://www.linux1394.org/
-S:     Orphan
-
 IEEE 1394 SUBSYSTEM
 P:     Ben Collins
 M:     bcollins@debian.org
@@ -1198,6 +1202,15 @@ L:       linux1394-devel@lists.sourceforge.net
 W:     http://www.linux1394.org/
 S:     Maintained
 
+IEEE 1394 SBP2
+P:     Ben Collins
+M:     bcollins@debian.org
+P:     Stefan Richter
+M:     stefanr@s5r6.in-berlin.de
+L:     linux1394-devel@lists.sourceforge.net
+W:     http://www.linux1394.org/
+S:     Maintained
+
 IMS TWINTURBO FRAMEBUFFER DRIVER
 P:     Paul Mundt
 M:     lethal@chaoticdreams.org
@@ -1734,8 +1747,11 @@ S:       Maintained
 IPVS
 P:     Wensong Zhang
 M:     wensong@linux-vs.org
+P:     Simon Horman
+M:     horms@verge.net.au
 P:     Julian Anastasov
 M:     ja@ssi.bg
+L:     netdev@vger.kernel.org
 S:     Maintained
 
 NFS CLIENT
@@ -1906,6 +1922,13 @@ M:       joern@wh.fh-wedel.de
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
 
+PKTCDVD DRIVER
+P:     Peter Osterlund
+M:     petero2@telia.com
+L:     linux-kernel@vger.kernel.org
+L:     packet-writing@suse.com
+S:     Maintained
+
 POSIX CLOCKS and TIMERS
 P:     George Anzinger
 M:     george@mvista.com
index 8cf6becf68dcf3352d0b1ebe8d87c1d1eb5df033..fdb96bc85080700d0e8b551aff06dcf27b5ede7e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 14
-EXTRAVERSION =-rc2
+EXTRAVERSION =-rc3
 NAME=Affluent Albatross
 
 # *DOCUMENTATION*
index 76cc0cb5fc2e429ebe0a98026271bbff7a6225f9..e38671c922bc673016771d1ec94e18edf34b8b9f 100644 (file)
@@ -196,6 +196,7 @@ entUna:
        stq     $26, 208($sp)
        stq     $27, 216($sp)
        stq     $28, 224($sp)
+       mov     $sp, $19
        stq     $gp, 232($sp)
        lda     $8, 0x3fff
        stq     $31, 248($sp)
index 6f509a644bddade182f7b27dade5e971fffb0f13..f9d12319e0fbba45ec9dc97cfd9e31e5581fadea 100644 (file)
@@ -446,16 +446,15 @@ struct unaligned_stat {
 
 
 /* Macro for exception fixup code to access integer registers.  */
-#define una_reg(r)  (regs.regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)])
+#define una_reg(r)  (regs->regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)])
 
 
 asmlinkage void
 do_entUna(void * va, unsigned long opcode, unsigned long reg,
-         unsigned long a3, unsigned long a4, unsigned long a5,
-         struct allregs regs)
+         struct allregs *regs)
 {
        long error, tmp1, tmp2, tmp3, tmp4;
-       unsigned long pc = regs.pc - 4;
+       unsigned long pc = regs->pc - 4;
        const struct exception_table_entry *fixup;
 
        unaligned[0].count++;
@@ -636,7 +635,7 @@ got_exception:
                printk("Forwarding unaligned exception at %lx (%lx)\n",
                       pc, newpc);
 
-               (&regs)->pc = newpc;
+               regs->pc = newpc;
                return;
        }
 
@@ -650,7 +649,7 @@ got_exception:
               current->comm, current->pid);
 
        printk("pc = [<%016lx>]  ra = [<%016lx>]  ps = %04lx\n",
-              pc, una_reg(26), regs.ps);
+              pc, una_reg(26), regs->ps);
        printk("r0 = %016lx  r1 = %016lx  r2 = %016lx\n",
               una_reg(0), una_reg(1), una_reg(2));
        printk("r3 = %016lx  r4 = %016lx  r5 = %016lx\n",
@@ -670,10 +669,10 @@ got_exception:
               una_reg(22), una_reg(23), una_reg(24));
        printk("r25= %016lx  r27= %016lx  r28= %016lx\n",
               una_reg(25), una_reg(27), una_reg(28));
-       printk("gp = %016lx  sp = %p\n", regs.gp, &regs+1);
+       printk("gp = %016lx  sp = %p\n", regs->gp, regs+1);
 
        dik_show_code((unsigned int *)pc);
-       dik_show_trace((unsigned long *)(&regs+1));
+       dik_show_trace((unsigned long *)(regs+1));
 
        if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
                printk("die_if_kernel recursion detected.\n");
index 130e6228b58713465c5fe4ef0061bb878b0cb4c2..7779f2d1acad00845f99f6b5931650d3205ac085 100644 (file)
@@ -175,10 +175,10 @@ else
 endif
        @touch $@
 
-archprepare: maketools include/asm-arm/.arch
+archprepare: maketools
 
 .PHONY: maketools FORCE
-maketools: include/linux/version.h FORCE
+maketools: include/linux/version.h include/asm-arm/.arch FORCE
        $(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
 
 # Convert bzImage to zImage
index d7499071755976a0a14b7b0c26eb8db62555e7b9..c02dc8116a18ef5facc08dbf61655c0144cfdaec 100644 (file)
@@ -68,6 +68,7 @@ static void gic_unmask_irq(unsigned int irq)
        writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4);
 }
 
+#ifdef CONFIG_SMP
 static void gic_set_cpu(struct irqdesc *desc, unsigned int irq, unsigned int cpu)
 {
        void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3);
@@ -78,6 +79,7 @@ static void gic_set_cpu(struct irqdesc *desc, unsigned int irq, unsigned int cpu
        val |= 1 << (cpu + shift);
        writel(val, reg);
 }
+#endif
 
 static struct irqchip gic_chip = {
        .ack            = gic_ack_irq,
index a7bd857001522651709ff4fafd57c427ca036ad3..e8053d16829b877bf6f5a8c4269900549bada9f1 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/spinlock.h>
 
 #include <asm/hardware.h>
-#include <asm/mach-types.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
index 94aafec5fb465dcc5d724c669192d1e31af39a8d..c279e41ed10e72acb94b6fdf3bd587b9b0de375a 100644 (file)
@@ -1,14 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 22:53:40 2005
+# Linux kernel version: 2.6.14-rc1-git5
+# Tue Sep 20 17:26:28 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
@@ -16,11 +15,13 @@ CONFIG_GENERIC_IOMAP=y
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -31,10 +32,13 @@ CONFIG_SYSCTL=y
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -81,6 +85,7 @@ CONFIG_ARCH_IXP4XX=y
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
 CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
 
 #
@@ -90,15 +95,16 @@ CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
 #
 # IXP4xx Platforms
 #
-# CONFIG_ARCH_AVILA is not set
+CONFIG_ARCH_AVILA=y
 CONFIG_ARCH_ADI_COYOTE=y
 CONFIG_ARCH_IXDP425=y
-# CONFIG_MACH_IXDPG425 is not set
-# CONFIG_MACH_IXDP465 is not set
+CONFIG_MACH_IXDPG425=y
+CONFIG_MACH_IXDP465=y
 CONFIG_ARCH_IXCDP1100=y
 CONFIG_ARCH_PRPMC1100=y
 CONFIG_ARCH_IXDP4XX=y
-# CONFIG_MACH_GTWX5715 is not set
+CONFIG_CPU_IXP46X=y
+CONFIG_MACH_GTWX5715=y
 
 #
 # IXP4xx Options
@@ -114,7 +120,6 @@ CONFIG_CPU_32v5=y
 CONFIG_CPU_ABRT_EV5T=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -127,9 +132,10 @@ CONFIG_DMABOUNCE=y
 #
 # Bus support
 #
+CONFIG_ISA_DMA_API=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -140,6 +146,15 @@ CONFIG_PCI_NAMES=y
 # Kernel Features
 #
 # CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -174,6 +189,241 @@ CONFIG_BINFMT_ELF=y
 CONFIG_PM=y
 CONFIG_APM=y
 
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+# CONFIG_IP_VS_PROTO_TCP is not set
+# CONFIG_IP_VS_PROTO_UDP is not set
+# CONFIG_IP_VS_PROTO_ESP is not set
+# CONFIG_IP_VS_PROTO_AH is not set
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+# CONFIG_IP_VS_SED is not set
+# CONFIG_IP_VS_NQ is not set
+
+#
+# IPVS application helper
+#
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+# CONFIG_NETFILTER_NETLINK is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+CONFIG_IP_NF_MATCH_MAC=m
+# CONFIG_IP_NF_MATCH_PKTTYPE is not set
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_DSCP is not set
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+# CONFIG_IP_NF_MATCH_HELPER is not set
+CONFIG_IP_NF_MATCH_STATE=m
+# CONFIG_IP_NF_MATCH_CONNTRACK is not set
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_PHYSDEV is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_DCCP is not set
+# CONFIG_IP_NF_MATCH_COMMENT is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+# CONFIG_IP_NF_MATCH_STRING is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_DSCP is not set
+CONFIG_IP_NF_TARGET_MARK=m
+# CONFIG_IP_NF_TARGET_CLASSIFY is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+# CONFIG_IP_NF_RAW is not set
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+# CONFIG_IP_NF_ARP_MANGLE is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+CONFIG_ATM=y
+CONFIG_ATM_CLIP=y
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=y
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+# CONFIG_NET_DIVERT is not set
+CONFIG_ECONET=m
+CONFIG_ECONET_AUNUDP=y
+CONFIG_ECONET_NATIVE=y
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_ATM is not set
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=m
+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
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_NET_CLS_IND is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
 #
 # Device Drivers
 #
@@ -244,6 +494,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_IXP4XX=y
 # CONFIG_MTD_EDB7312 is not set
 # CONFIG_MTD_PCI is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -283,7 +534,6 @@ CONFIG_MTD_NAND_IDS=m
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD 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
@@ -297,7 +547,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
 
 #
@@ -351,6 +600,7 @@ CONFIG_BLK_DEV_CMD64X=y
 CONFIG_BLK_DEV_HPT366=y
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 CONFIG_BLK_DEV_PDC202XX_NEW=y
@@ -369,6 +619,7 @@ CONFIG_BLK_DEV_IDEDMA=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -379,6 +630,7 @@ CONFIG_BLK_DEV_IDEDMA=y
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -391,241 +643,24 @@ CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_I2O is not set
 
 #
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=m
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=m
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-# CONFIG_ARPD is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-CONFIG_INET_TUNNEL=m
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-CONFIG_IP_VS=m
-CONFIG_IP_VS_DEBUG=y
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS transport protocol load balancing support
-#
-# CONFIG_IP_VS_PROTO_TCP is not set
-# CONFIG_IP_VS_PROTO_UDP is not set
-# CONFIG_IP_VS_PROTO_ESP is not set
-# CONFIG_IP_VS_PROTO_AH is not set
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-# CONFIG_IP_VS_SED is not set
-# CONFIG_IP_VS_NQ is not set
-
-#
-# IPVS application helper
-#
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_BRIDGE_NETFILTER=y
-
-#
-# IP: Netfilter Configuration
+# Network device support
 #
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-# CONFIG_IP_NF_MATCH_IPRANGE is not set
-CONFIG_IP_NF_MATCH_MAC=m
-# CONFIG_IP_NF_MATCH_PKTTYPE is not set
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-# CONFIG_IP_NF_MATCH_RECENT is not set
-# CONFIG_IP_NF_MATCH_ECN is not set
-# CONFIG_IP_NF_MATCH_DSCP is not set
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-# CONFIG_IP_NF_MATCH_HELPER is not set
-CONFIG_IP_NF_MATCH_STATE=m
-# CONFIG_IP_NF_MATCH_CONNTRACK is not set
-CONFIG_IP_NF_MATCH_OWNER=m
-# CONFIG_IP_NF_MATCH_PHYSDEV is not set
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-# CONFIG_IP_NF_MATCH_SCTP is not set
-# CONFIG_IP_NF_MATCH_COMMENT is not set
-# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-# CONFIG_IP_NF_TARGET_NETMAP is not set
-# CONFIG_IP_NF_TARGET_SAME is not set
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-# CONFIG_IP_NF_TARGET_ECN is not set
-# CONFIG_IP_NF_TARGET_DSCP is not set
-CONFIG_IP_NF_TARGET_MARK=m
-# CONFIG_IP_NF_TARGET_CLASSIFY is not set
-# CONFIG_IP_NF_RAW is not set
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-# CONFIG_IP_NF_ARP_MANGLE is not set
-
-#
-# Bridge: Netfilter Configuration
-#
-# CONFIG_BRIDGE_NF_EBTABLES is not set
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-CONFIG_ATM=y
-CONFIG_ATM_CLIP=y
-# CONFIG_ATM_CLIP_NO_ICMP is not set
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-# CONFIG_ATM_BR2684_IPFILTER is not set
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-# CONFIG_DECNET is not set
-CONFIG_LLC=m
-# CONFIG_LLC2 is not set
-CONFIG_IPX=m
-# CONFIG_IPX_INTERN is not set
-CONFIG_ATALK=m
-CONFIG_DEV_APPLETALK=y
-CONFIG_IPDDP=m
-CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
-CONFIG_X25=m
-CONFIG_LAPB=m
-# CONFIG_NET_DIVERT is not set
-CONFIG_ECONET=m
-CONFIG_ECONET_AUNUDP=y
-CONFIG_ECONET_NATIVE=y
-CONFIG_WAN_ROUTER=m
-
-#
-# QoS and/or fair queueing
-#
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CLK_JIFFIES=y
-# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
-# CONFIG_NET_SCH_CLK_CPU is not set
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-# CONFIG_NET_SCH_HFSC is not set
-# CONFIG_NET_SCH_ATM is not set
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-# CONFIG_NET_SCH_NETEM is not set
-CONFIG_NET_SCH_INGRESS=m
-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
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-# CONFIG_CLS_U32_PERF is not set
-# CONFIG_NET_CLS_IND is not set
-# CONFIG_CLS_U32_MARK is not set
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-# CONFIG_NET_EMATCH is not set
-# CONFIG_NET_CLS_ACT is not set
-CONFIG_NET_CLS_POLICE=y
-
-#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
 
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -635,6 +670,7 @@ CONFIG_MII=y
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
 
 #
 # Tulip family network device support
@@ -671,13 +707,17 @@ CONFIG_EEPRO100=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 
@@ -702,6 +742,7 @@ CONFIG_NET_RADIO=y
 CONFIG_HERMES=y
 # CONFIG_PLX_HERMES is not set
 # CONFIG_TMD_HERMES is not set
+# CONFIG_NORTEL_HERMES is not set
 CONFIG_PCI_HERMES=y
 # CONFIG_ATMEL is not set
 
@@ -709,6 +750,7 @@ CONFIG_PCI_HERMES=y
 # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
 #
 # CONFIG_PRISM54 is not set
+# CONFIG_HOSTAP is not set
 CONFIG_NET_WIRELESS=y
 
 #
@@ -758,6 +800,8 @@ CONFIG_ATM_TCP=m
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -795,7 +839,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -816,6 +859,7 @@ CONFIG_SERIAL_8250_NR_UARTS=2
 #
 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
@@ -882,12 +926,11 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_AMD8111 is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_IOP3XX is not set
-# CONFIG_I2C_ISA is not set
 CONFIG_I2C_IXP4XX=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 # CONFIG_SCx200_ACB is not set
@@ -901,14 +944,33 @@ CONFIG_I2C_IXP4XX=y
 # CONFIG_I2C_PCA_ISA is not set
 
 #
-# Hardware Sensors Chip support
+# Miscellaneous I2C Chip support
 #
-CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
 # CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
 # CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
@@ -924,30 +986,26 @@ CONFIG_I2C_SENSOR=y
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
-# Other I2C Chip support
+# Misc devices
 #
-CONFIG_SENSORS_EEPROM=y
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
 
 #
-# Misc devices
+# Multimedia Capabilities Port drivers
 #
 
 #
@@ -994,6 +1052,7 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
@@ -1004,17 +1063,15 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1034,12 +1091,10 @@ CONFIG_DNOTIFY=y
 #
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1054,8 +1109,7 @@ CONFIG_RAMFS=y
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -1072,12 +1126,14 @@ CONFIG_JFFS2_RTIME=y
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -1086,6 +1142,7 @@ CONFIG_SUNRPC=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -1124,6 +1181,7 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1158,6 +1216,7 @@ CONFIG_DEBUG_LL=y
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
index 6c20c1188b6056a5b5bed539fa760875cc071392..1f6822dfae7404fd57218537f1d67e1252351ffe 100644 (file)
@@ -7,7 +7,7 @@
  * Copy data from IO memory space to "real" memory space.
  * This needs to be optimized.
  */
-void _memcpy_fromio(void *to, void __iomem *from, size_t count)
+void _memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
 {
        unsigned char *t = to;
        while (count) {
@@ -22,7 +22,7 @@ void _memcpy_fromio(void *to, void __iomem *from, size_t count)
  * Copy data from "real" memory space to IO memory space.
  * This needs to be optimized.
  */
-void _memcpy_toio(void __iomem *to, const void *from, size_t count)
+void _memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
 {
        const unsigned char *f = from;
        while (count) {
@@ -37,7 +37,7 @@ void _memcpy_toio(void __iomem *to, const void *from, size_t count)
  * "memset" on IO memory space.
  * This needs to be optimized.
  */
-void _memset_io(void __iomem *dst, int c, size_t count)
+void _memset_io(volatile void __iomem *dst, int c, size_t count)
 {
        while (count) {
                count--;
index f83a59761e0276e3732661ce1723c98056e17732..3d88da0c287b93e5f9389881ad7637335c4331fc 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <asm/mach/arch.h>
 
+#include <asm/memory.h>
+
 #include "common.h"
 
 struct meminfo memmap = {
index e6399b06e4a4742580f74f6f31289ad41c36052d..79236404aec2571b1f26b383b7d0e7a370ad2e19 100644 (file)
@@ -17,7 +17,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/leds.h>
-#include <asm/mach-types.h>
 #include "leds.h"
 
 /*
index bda7394ec06cf38283575c4fea528630ef038f1a..fdeeef489a73592039c605ed55a2156ac277801f 100644 (file)
@@ -27,7 +27,6 @@ unsigned long iop3xx_pcibios_min_mem = 0;
 /*
  * Default power-off for EP80219
  */
-#include <asm/mach-types.h>
 
 static inline void ep80219_send_to_pic(__u8 c) {
 }
index 0039793b694a20cd63da8930386a5ba3c6cbf9d1..d67ac0e5d4381ef06bba8dca5a3848d9b4d9a4f4 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
-#include <asm/mach-types.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
index 8eddfac7e2b046450d74a6074837b9f73e0fff1b..3c1f0ebbd636e42e8160fddae779bf81d90c9e9c 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
-#include <asm/mach-types.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
index b01042f7de71f5b0a699f869edba99368335e9fe..55992ab586baf87d2418f2f91c865460321b04a0 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/page.h>
 
 #include <asm/mach/map.h>
-#include <asm/mach-types.h>
 
 
 /*
index 1580c7ed2b9d24e5364436c266fa99104a6205b2..bb3e9e5a9aff0e218ec0e9967e680cdecd2160e7 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/page.h>
 
 #include <asm/mach/map.h>
-#include <asm/mach-types.h>
 
 
 /*
index ee8c333e115f6fffa4e08451e8babb8cadfd88a5..129eb49b0670e161d971f4c4db0672c381523c4e 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/page.h>
 
 #include <asm/mach/map.h>
-#include <asm/mach-types.h>
 
 
 /*
index 084afcdfb1eb84ce72ddf0168873b77cdd58616a..2feaf7591f5315ca8fa0f5312ab1bde7b4ad2aa4 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/page.h>
 
 #include <asm/mach/map.h>
-#include <asm/mach-types.h>
 
 
 /*
index 74bd2fd602d45181ed333bb3ee7fb9e9cc6aaf5e..f4d7f1f6ef851253d3466b39d403815dd07209fb 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/hardware.h>
-#include <asm/mach-types.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/tlbflush.h>
@@ -168,7 +167,7 @@ static struct plat_serial8250_port ixp2000_serial_port[] = {
 
 static struct resource ixp2000_uart_resource = {
        .start          = IXP2000_UART_PHYS_BASE,
-       .end            = IXP2000_UART_PHYS_BASE + 0xffff,
+       .end            = IXP2000_UART_PHYS_BASE + 0x1f,
        .flags          = IORESOURCE_MEM,
 };
 
index 0788fb2b5c10e6ae6e2023649930205cc3afb016..522205acb316fc6745d73732481fddf5cd094de7 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <asm/mach-types.h>
 #include <asm/hardware.h>
 
 #include <asm/mach/pci.h>
index 52ad11328e961225465a6e461b5aa8d564039a45..36b6045213eec8b4265da0dda508590e565ff7fe 100644 (file)
@@ -125,7 +125,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
        } else if (type & IRQT_LOW) {
                int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
                irq_type = IXP4XX_IRQ_LEVEL;
-       }
+       } else
+               return -EINVAL;
 
        ixp4xx_config_irq(irq, irq_type);
 
@@ -142,6 +143,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
 
        /* Set the new style */
        *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
+
+       return 0;
 }
 
 static void ixp4xx_irq_mask(unsigned int irq)
index 39b06ed806462b69a1afd5ac39c5e49430b1b844..0a41080d2266c27083503f55384bce245cfb8a07 100644 (file)
@@ -123,7 +123,7 @@ static void __init ixdp425_init(void)
        platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
 }
 
-#ifdef CONFIG_ARCH_IXDP465
+#ifdef CONFIG_ARCH_IXDP425
 MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
        /* Maintainer: MontaVista Software, Inc. */
        .phys_ram       = PHYS_OFFSET,
index 2a7fee2a7635109212810c0f5cbc5ca959f364b3..5fd8c9f97f9adab013f423d05f778311853b94e1 100644 (file)
@@ -12,7 +12,6 @@
 #include <asm/page.h>
 
 #include <asm/mach/map.h>
-#include <asm/arch/hardware.h>
 
 /*
  * IRQ base register
index c5efcd04fcbc8011c01961ca334a080dcf62005a..c02ef7c0f7ef6cf45b3bfdad6f68468b4f0e8dc9 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/module.h>
-#include <asm/mach-types.h>
 #include <asm/arch/akita.h>
 #include <asm/arch/corgi.h>
 #include <asm/arch/hardware.h>
index a45aaa115a76664bb81438455b06a6ff890886f7..d0660a8c4b704429111daa3bc607e3ac0b582550 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/i2c.h>
 
 #include "generic.h"
 
index f021fd82be52cb7260c91be5c02a8ce0c4d2ef49..5098b50158a332ce81b8bdd36945c5916d9f8cb3 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/mach-types.h>
 
 #include "devs.h"
 #include "usb-simtec.h"
index 3c8862fde51ad18a362713f821757b1cba4a3903..a30e0451df72230d731978257c23e8570de6f72c 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
-#include <asm/mach-types.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba_clcd.h>
 #include <asm/hardware/arm_timer.h>
@@ -52,8 +51,9 @@
  *
  * Setup a VA for the Versatile Vectored Interrupt Controller.
  */
-#define VA_VIC_BASE             IO_ADDRESS(VERSATILE_VIC_BASE)
-#define VA_SIC_BASE             IO_ADDRESS(VERSATILE_SIC_BASE)
+#define __io_address(n)                __io(IO_ADDRESS(n))
+#define VA_VIC_BASE            __io_address(VERSATILE_VIC_BASE)
+#define VA_SIC_BASE            __io_address(VERSATILE_SIC_BASE)
 
 static void vic_mask_irq(unsigned int irq)
 {
@@ -214,7 +214,7 @@ void __init versatile_map_io(void)
        iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc));
 }
 
-#define VERSATILE_REFCOUNTER   (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET)
+#define VERSATILE_REFCOUNTER   (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET)
 
 /*
  * This is the Versatile sched_clock implementation.  This has
@@ -231,7 +231,7 @@ unsigned long long sched_clock(void)
 }
 
 
-#define VERSATILE_FLASHCTRL    (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET)
+#define VERSATILE_FLASHCTRL    (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET)
 
 static int versatile_flash_init(void)
 {
@@ -309,7 +309,7 @@ static struct platform_device smc91x_device = {
        .resource       = smc91x_resources,
 };
 
-#define VERSATILE_SYSMCI       (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
+#define VERSATILE_SYSMCI       (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_MCI_OFFSET)
 
 unsigned int mmc_status(struct device *dev)
 {
@@ -343,11 +343,11 @@ static const struct icst307_params versatile_oscvco_params = {
 
 static void versatile_oscvco_set(struct clk *clk, struct icst307_vco vco)
 {
-       unsigned long sys_lock = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET;
+       void __iomem *sys_lock = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET;
 #if defined(CONFIG_ARCH_VERSATILE_PB)
-       unsigned long sys_osc = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC4_OFFSET;
+       void __iomem *sys_osc = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC4_OFFSET;
 #elif defined(CONFIG_MACH_VERSATILE_AB)
-       unsigned long sys_osc = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC1_OFFSET;
+       void __iomem *sys_osc = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSC1_OFFSET;
 #endif
        u32 val;
 
@@ -483,7 +483,7 @@ static struct clcd_panel epson_2_2_in = {
  */
 static struct clcd_panel *versatile_clcd_panel(void)
 {
-       unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+       void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
        struct clcd_panel *panel = &vga;
        u32 val;
 
@@ -510,7 +510,7 @@ static struct clcd_panel *versatile_clcd_panel(void)
  */
 static void versatile_clcd_disable(struct clcd_fb *fb)
 {
-       unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+       void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
        u32 val;
 
        val = readl(sys_clcd);
@@ -522,7 +522,7 @@ static void versatile_clcd_disable(struct clcd_fb *fb)
         * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off
         */
        if (fb->panel == &sanyo_2_5_in) {
-               unsigned long versatile_ib2_ctrl = IO_ADDRESS(VERSATILE_IB2_CTRL);
+               void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL);
                unsigned long ctrl;
 
                ctrl = readl(versatile_ib2_ctrl);
@@ -537,7 +537,7 @@ static void versatile_clcd_disable(struct clcd_fb *fb)
  */
 static void versatile_clcd_enable(struct clcd_fb *fb)
 {
-       unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+       void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
        u32 val;
 
        val = readl(sys_clcd);
@@ -571,7 +571,7 @@ static void versatile_clcd_enable(struct clcd_fb *fb)
         * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on
         */
        if (fb->panel == &sanyo_2_5_in) {
-               unsigned long versatile_ib2_ctrl = IO_ADDRESS(VERSATILE_IB2_CTRL);
+               void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL);
                unsigned long ctrl;
 
                ctrl = readl(versatile_ib2_ctrl);
@@ -720,7 +720,7 @@ static struct amba_device *amba_devs[] __initdata = {
 };
 
 #ifdef CONFIG_LEDS
-#define VA_LEDS_BASE (IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
+#define VA_LEDS_BASE (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET)
 
 static void versatile_leds_event(led_event_t ledevt)
 {
@@ -778,11 +778,11 @@ void __init versatile_init(void)
 /*
  * Where is the timer (VA)?
  */
-#define TIMER0_VA_BASE          IO_ADDRESS(VERSATILE_TIMER0_1_BASE)
-#define TIMER1_VA_BASE         (IO_ADDRESS(VERSATILE_TIMER0_1_BASE) + 0x20)
-#define TIMER2_VA_BASE          IO_ADDRESS(VERSATILE_TIMER2_3_BASE)
-#define TIMER3_VA_BASE         (IO_ADDRESS(VERSATILE_TIMER2_3_BASE) + 0x20)
-#define VA_IC_BASE              IO_ADDRESS(VERSATILE_VIC_BASE) 
+#define TIMER0_VA_BASE          __io_address(VERSATILE_TIMER0_1_BASE)
+#define TIMER1_VA_BASE         (__io_address(VERSATILE_TIMER0_1_BASE) + 0x20)
+#define TIMER2_VA_BASE          __io_address(VERSATILE_TIMER2_3_BASE)
+#define TIMER3_VA_BASE         (__io_address(VERSATILE_TIMER2_3_BASE) + 0x20)
+#define VA_IC_BASE              __io_address(VERSATILE_VIC_BASE) 
 
 /*
  * How long is the timer interval?
@@ -877,12 +877,12 @@ static void __init versatile_timer_init(void)
         *      VERSATILE_REFCLK is 32KHz
         *      VERSATILE_TIMCLK is 1MHz
         */
-       val = readl(IO_ADDRESS(VERSATILE_SCTL_BASE));
+       val = readl(__io_address(VERSATILE_SCTL_BASE));
        writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) |
               (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
               (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) |
               (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val,
-              IO_ADDRESS(VERSATILE_SCTL_BASE));
+              __io_address(VERSATILE_SCTL_BASE));
 
        /*
         * Initialise to a known state (all timers off)
index d1565e851f0e01f6b6e63f73939455214c817ef0..b80d57d516991b64a08ba47f6fc67d325396389a 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/mach/pci.h>
-#include <asm/mach-types.h>
 
 /*
  * these spaces are mapped using the following base registers:
index 8f76f3df7b4cf03e949b51f2817e7f0c4af4b44a..dbd346033122140df010997b1c85cb4615b133c1 100644 (file)
  */
        .align  5
 ENTRY(v6_early_abort)
+#ifdef CONFIG_CPU_MPCORE
+       clrex
+#else
+       strex   r0, r1, [sp]                    @ Clear the exclusive monitor
+#endif
        mrc     p15, 0, r1, c5, c0, 0           @ get FSR
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
 /*
index 85c10a71e7c62ef779ec8810d7a5bb537d7c21d3..72966d90e956b88ed001605c332128efa081ee58 100644 (file)
@@ -18,6 +18,7 @@
 #define HARVARD_CACHE
 #define CACHE_LINE_SIZE                32
 #define D_CACHE_LINE_SIZE      32
+#define BTB_FLUSH_SIZE         8
 
 /*
  *     v6_flush_cache_all()
@@ -98,7 +99,13 @@ ENTRY(v6_coherent_user_range)
        mcr     p15, 0, r0, c7, c5, 1           @ invalidate I line
 #endif
        mcr     p15, 0, r0, c7, c5, 7           @ invalidate BTB entry
-       add     r0, r0, #CACHE_LINE_SIZE
+       add     r0, r0, #BTB_FLUSH_SIZE
+       mcr     p15, 0, r0, c7, c5, 7           @ invalidate BTB entry
+       add     r0, r0, #BTB_FLUSH_SIZE
+       mcr     p15, 0, r0, c7, c5, 7           @ invalidate BTB entry
+       add     r0, r0, #BTB_FLUSH_SIZE
+       mcr     p15, 0, r0, c7, c5, 7           @ invalidate BTB entry
+       add     r0, r0, #BTB_FLUSH_SIZE
        cmp     r0, r1
        blo     1b
 #ifdef HARVARD_CACHE
index b0208c9925764940db06976ec69665b66d7275e0..c9a03981b785895a0d2379706e780847ccef1ed6 100644 (file)
 
 #ifdef CONFIG_CPU_CACHE_VIPT
 
+#define ALIAS_FLUSH_START      0xffff4000
+
+#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
+
+static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
+{
+       unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
+
+       set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL));
+       flush_tlb_kernel_page(to);
+
+       asm(    "mcrr   p15, 0, %1, %0, c14\n"
+       "       mcrr    p15, 0, %1, %0, c5\n"
+           :
+           : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES)
+           : "cc");
+}
+
 void flush_cache_mm(struct mm_struct *mm)
 {
        if (cache_is_vivt()) {
@@ -67,24 +85,6 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsig
        if (cache_is_vipt_aliasing())
                flush_pfn_alias(pfn, user_addr);
 }
-
-#define ALIAS_FLUSH_START      0xffff4000
-
-#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
-
-static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
-{
-       unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
-
-       set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL));
-       flush_tlb_kernel_page(to);
-
-       asm(    "mcrr   p15, 0, %1, %0, c14\n"
-       "       mcrr    p15, 0, %1, %0, c5\n"
-           :
-           : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES)
-           : "cc");
-}
 #else
 #define flush_pfn_alias(pfn,vaddr)     do { } while (0)
 #endif
index 6cb20aea7f518b22dbd9b25a6d93cc6ac93fd1ff..02bcc6c1cd1b136284d4a76d1fb067e714544f4a 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/mach/map.h>
 #include <asm/hardware/clock.h>
 #include <asm/io.h>
-#include <asm/mach-types.h>
 #include <asm/setup.h>
 
 #include <asm/arch/board.h>
index 409aac2c4b9de75400cf0f34bc50131362bb7125..fd894bb00107bf1c1ad42ec375c691abe224bc44 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/err.h>
 
 #include <asm/hardware.h>
-#include <asm/mach-types.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
index 98f1c76f86606f039dad4501651f371f7056f099..14a836d7ac250a4ebee43b3cca8edf1b5e70cba8 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/hardware.h>
-#include <asm/mach-types.h>
 
 #include <asm/arch/mux.h>
 #include <asm/arch/usb.h>
index a63351c085c66dceeafb990ba75214963fad1cea..b66c13c0cc0f8b45742021e35119067b3778d6dc 100644 (file)
 #include <linux/config.h>
 #include <linux/acpi.h>
 #include <linux/efi.h>
-#include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/dmi.h>
+#include <linux/irq.h>
 
 #include <asm/pgtable.h>
 #include <asm/io_apic.h>
 #include <asm/apic.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/mpspec.h>
 
 #ifdef CONFIG_X86_64
index a22a866de8f9db44472cc65f933383ce6589591a..5546ddebec33dc994c93b5f3f604867da4e94413 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/smp_lock.h>
index 73aeaf5a9d4e493f7e2be65ac67a285d966e062c..4c1ddf2b57cc37d4196091ee41ea5c5035993023 100644 (file)
@@ -28,6 +28,22 @@ static void __init init_amd(struct cpuinfo_x86 *c)
        int mbytes = num_physpages >> (20-PAGE_SHIFT);
        int r;
 
+#ifdef CONFIG_SMP
+       unsigned long value;
+
+       /* Disable TLB flush filter by setting HWCR.FFDIS on K8
+        * bit 6 of msr C001_0015
+        *
+        * Errata 63 for SH-B3 steppings
+        * Errata 122 for all steppings (F+ have it disabled by default)
+        */
+       if (c->x86 == 15) {
+               rdmsrl(MSR_K7_HWCR, value);
+               value |= 1 << 6;
+               wrmsrl(MSR_K7_HWCR, value);
+       }
+#endif
+
        /*
         *      FIXME: We should handle the K5 here. Set up the write
         *      range and also turn on MSR 83 bits 4 and 31 (write alloc,
index c4abe76573978fff801b487ebee33f050fd1cb79..7c6b9c73522fe3fe5ca4ece85654226c56d86963 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/config.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 
index 7864ddfccf0779619478b3c0af2d866456fc9de9..82dffe0d4954b8db6cc8b8cf2dcf50eaf8417370 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
 #include <linux/config.h>
-#include <linux/irq.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
index 0abccb6fdf9e1344dff1d79c409bcc97e1e9abf1..1d1e885f500ae9592d007844aec7000e06ff3017 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/config.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 
index ec0614cd29250a6d15050781eabec475d439bdef..3a2e24baddc78ee63ab546d9fc78760c2880310d 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 
index f01b73f947e1e010f5c3887ffeabb5aee91c5ea4..3c035b8fa3d9bb9f0fd121826ce2eac01f69413d 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 
index 7bae68fa168fcbbe8325362730dfbf82ca9744ed..5b9d2dd411d3a9e469a7c2806bb4e0f41a221889 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 
 #include <asm/processor.h> 
index 913be77bb8446569d99175f0ff6556567bea531b..0248e084017ceddd74bcc7e92052cef801b897ff 100644 (file)
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
-#include <linux/irq.h>
 #include <linux/reboot.h>
 #include <linux/kexec.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/elf.h>
 #include <linux/elfcore.h>
index 178f4e9bac9d14c84a5046b6c967982000120f73..323ef8ab3244e880c1b32468a12122990ba0ceba 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/timer.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
@@ -25,8 +24,6 @@
 #include <asm/arch_hooks.h>
 #include <asm/i8259.h>
 
-#include <linux/irq.h>
-
 #include <io_ports.h>
 
 /*
index 378313b0cce9ac9ba8de933303e5e432959cfa05..fb3991e8229e5e65cf696cc4d2d7eec55546cd28 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/delay.h>
index 15949fd081095c76a44b217fdb5fad7384174146..27aabfceb67ec3c90800c7fe9b06f7ee5bfc153d 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/delay.h>
index 0178457db72130b54d3170dfd8150742b8addfe1..72515b8a1b129bf6a6b69c01fb4441ad0fce2956 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/smp_lock.h>
index b45cbf93d4391b49411cfdaecf7c1e084e184c33..7a14fdfd3af95423275cab21ea56624bd4e1f4e7 100644 (file)
 #include <asm/ldt.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
-#include <asm/irq.h>
 #include <asm/desc.h>
 #ifdef CONFIG_MATH_EMULATION
 #include <asm/math_emu.h>
 #endif
 
-#include <linux/irq.h>
 #include <linux/err.h>
 
 #include <asm/tlbflush.h>
index 48b55db3680f3eaac2b1a67274343677ceb1a32d..218d725a5a1e89ff7f3dc7175ca22c59624e7b96 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
index 5f0a95d76a4f16fa3c95ba57c131c6eb3c967046..1fb26d0e30b6b79d243de220cab1859f3729e82e 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/smp_lock.h>
-#include <linux/irq.h>
 #include <linux/bootmem.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
index eddb640382342db9b2cee7483d228d0648a64e00..e42e46d351591d583782921f6b30e5b302b2285a 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <linux/device.h>
-#include <linux/irq.h>
 #include <linux/sysdev.h>
 #include <linux/timex.h>
 #include <asm/delay.h>
index 431a551e46ea5f191498eaa6fbe7a6fc7d7273fa..19e90bdd84eac1834efe26127429b0cec15f1670 100644 (file)
@@ -52,7 +52,6 @@
 #include <asm/arch_hooks.h>
 #include <asm/kdebug.h>
 
-#include <linux/irq.h>
 #include <linux/module.h>
 
 #include "mach_traps.h"
index e5a1a83d09ef8d6c4efe1e74c7fa1d77c5f371dc..b4a7455c69939dbd226ed269bb1885352e2553a9 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/config.h>
 #include <linux/smp.h>
 #include <linux/init.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <asm/acpi.h>
 #include <asm/arch_hooks.h>
index 26ada6fc0d774f082f5379550ef1e9063f8a0f2d..07fac7e749c7406aa642528dbd292b4fb036c189 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <linux/smp.h>
 #include <linux/init.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 
 #include <asm/fixmap.h>
index 04e6585849a2f6d25f3e76cff2bd8763fa89bb40..3e64fb7212911bc4db9fe8db9f67ab75a40ecd36 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/config.h>
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 
index df123fc487bb0e65fe172cf9391683ebed8c1047..7d8a3acb9441f785cd9df284577a85dafee862fa 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <asm/acpi.h>
 #include <asm/arch_hooks.h>
index cc69875d979b9445b3ebcc0549906656ee3f2767..aa49a33a572cf29ec5ff684d3f20d39fc7568efc 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/voyager.h>
 #include <asm/vic.h>
 #include <linux/pm.h>
-#include <linux/irq.h>
 #include <asm/tlbflush.h>
 #include <asm/arch_hooks.h>
 #include <asm/i8253.h>
index 46b0cf4a31e006fc6002569ae3eac4b7a5478a6a..72a1b9cae2e41beb4b80bd4a523382504ff67e9f 100644 (file)
@@ -30,8 +30,6 @@
 #include <asm/tlbflush.h>
 #include <asm/arch_hooks.h>
 
-#include <linux/irq.h>
-
 /* TLB state -- visible externally, indexed physically */
 DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 };
 
index a9341b0eebffa396199db1b268707b6ba893b782..2b03884fdb2a968a904ca08f29c9f8c017e22788 100644 (file)
@@ -31,8 +31,6 @@
 #include <asm/mtrr.h>
 #include <asm/msr.h>
 
-#include <linux/irq.h>
-
 #define THREAD_NAME "kvoyagerd"
 
 /* external variables */
index ad93cdd55d63bf20f20b8bf4ad7ab0329910017b..930a1127bb309e0ff9030384f452e1641d59ea96 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <linux/init.h>
 #include <linux/smp.h>
-#include <linux/irq.h>
+#include <linux/errno.h>
 #include <linux/oprofile.h>
 #include <linux/rcupdate.h>
 
index 2941674f35eb5aae272a3000edd491993ec1b0aa..4c4522b43be5e9a6951e0b4cb7252f2ee67b73e9 100644 (file)
@@ -2,7 +2,6 @@
 #include <linux/acpi.h>
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <asm/hw_irq.h>
 #include <asm/numa.h>
 #include "pci.h"
 
index 326a2edc38349ca19f278521ab7068563a8c2c13..cddafe33ff7c522ca007569e0d73faade5465fc7 100644 (file)
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/dmi.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/io_apic.h>
-#include <asm/hw_irq.h>
+#include <linux/irq.h>
 #include <linux/acpi.h>
 
 #include "pci.h"
index 7b0b9ad848e58eb9a723c16c87af4b1eb0aaa566..b27c5acc79d01fbd5ef053add840609bb4215365 100644 (file)
@@ -8,25 +8,8 @@
  */
 
 #include <linux/config.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/poll.h>
-#include <linux/delay.h>
-#include <linux/sysrq.h>
-#include <linux/proc_fs.h>
-#include <linux/irq.h>
-#include <linux/pm.h>
-#include <linux/device.h>
 #include <linux/suspend.h>
-#include <linux/acpi.h>
-
-#include <asm/uaccess.h>
-#include <asm/acpi.h>
-#include <asm/tlbflush.h>
-#include <asm/processor.h>
 
 static struct saved_context saved_context;
 
index dd4418d846e97562bd50ba6a04a7a14936b89a5e..983d438b14b61470b0daa57bca585f81c17f71d8 100644 (file)
@@ -24,7 +24,7 @@ aflags-$(CONFIG_ISA_M32R)     += -DNO_FPU -Wa,-no-bitinst
 CFLAGS += $(cflags-y)
 AFLAGS += $(aflags-y)
 
-CHECKFLAGS     := $(CHECK) -D__m32r__
+CHECKFLAGS     += -D__m32r__ -D__BIG_ENDIAN__=1
 
 head-y := arch/m32r/kernel/head.o arch/m32r/kernel/init_task.o
 
index 6c6855f1aa05f758a46f01c37a789c9b32e06309..ce16bbe26a522f57a61aaa1cb0c7faca8f145581 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/uaccess.h>
 
 unsigned long
-__generic_copy_to_user(void *to, const void *from, unsigned long n)
+__generic_copy_to_user(void __user *to, const void *from, unsigned long n)
 {
        prefetch(from);
        if (access_ok(VERIFY_WRITE, to, n))
@@ -22,7 +22,7 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n)
 }
 
 unsigned long
-__generic_copy_from_user(void *to, const void *from, unsigned long n)
+__generic_copy_from_user(void *to, const void __user *from, unsigned long n)
 {
        prefetchw(to);
        if (access_ok(VERIFY_READ, from, n))
@@ -111,7 +111,7 @@ do {                                                                        \
 #endif /* CONFIG_ISA_DUAL_ISSUE */
 
 long
-__strncpy_from_user(char *dst, const char *src, long count)
+__strncpy_from_user(char *dst, const char __user *src, long count)
 {
        long res;
        __do_strncpy_from_user(dst, src, count, res);
@@ -119,7 +119,7 @@ __strncpy_from_user(char *dst, const char *src, long count)
 }
 
 long
-strncpy_from_user(char *dst, const char *src, long count)
+strncpy_from_user(char *dst, const char __user *src, long count)
 {
        long res = -EFAULT;
        if (access_ok(VERIFY_READ, src, 1))
@@ -222,7 +222,7 @@ do {                                                                        \
 #endif /* not CONFIG_ISA_DUAL_ISSUE */
 
 unsigned long
-clear_user(void *to, unsigned long n)
+clear_user(void __user *to, unsigned long n)
 {
        if (access_ok(VERIFY_WRITE, to, n))
                __do_clear_user(to, n);
@@ -230,7 +230,7 @@ clear_user(void *to, unsigned long n)
 }
 
 unsigned long
-__clear_user(void *to, unsigned long n)
+__clear_user(void __user *to, unsigned long n)
 {
        __do_clear_user(to, n);
        return n;
@@ -244,7 +244,7 @@ __clear_user(void *to, unsigned long n)
 
 #ifdef CONFIG_ISA_DUAL_ISSUE
 
-long strnlen_user(const char *s, long n)
+long strnlen_user(const char __user *s, long n)
 {
        unsigned long mask = -__addr_ok(s);
        unsigned long res;
@@ -313,7 +313,7 @@ long strnlen_user(const char *s, long n)
 
 #else /* not CONFIG_ISA_DUAL_ISSUE */
 
-long strnlen_user(const char *s, long n)
+long strnlen_user(const char __user *s, long n)
 {
        unsigned long mask = -__addr_ok(s);
        unsigned long res;
index 9362193742aceecf5dd52110767f6cfb502acdd4..d4dd8f15395ecb3495289f6ce8bb91c9da6162d1 100644 (file)
@@ -1,4 +1,4 @@
-OUTPUT_ARCH(powerpc)
+OUTPUT_ARCH(powerpc:common)
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
index 04c18788e85ff088c453985ac9b3aa86d231a318..22df9a596a0faab9f9cd2ba7d3087178c72d6c3a 100644 (file)
@@ -45,9 +45,8 @@ static void dummy_perf(struct pt_regs *regs)
        mtpmr(PMRN_PMGC0, pmgc0);
 }
 
-#elif CONFIG_6xx
+#elif defined(CONFIG_6xx)
 /* Ensure exceptions are disabled */
-
 static void dummy_perf(struct pt_regs *regs)
 {
        unsigned int mmcr0 = mfspr(SPRN_MMCR0);
index ac391d463d78af752e05b3dddff082e1604e6927..78a403b48dba9c861fe54f27ee94cab2c3db09be 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/delay.h>
 #include <linux/ide.h>
 #include <linux/initrd.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/tty.h>
index d6b2b1965dcb30a179689705a1db8d627ac01abe..27b778ab903b89b40c15ed354d3eb9cda471e887 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/delay.h>
 #include <linux/ide.h>
 #include <linux/initrd.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/tty.h>
index a38e6f9ef858ae78db73688c3a80b52d217303da..16d953bda22cf13b50f2d43c42a8187d7d4e6e81 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/delay.h>
 #include <linux/ide.h>
 #include <linux/initrd.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/tty.h>
index 80028df1b445b422ece4a9edfc02186b8aced50e..506949c5dd29d4c069ce518e0e02ef22d0427b1b 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/delay.h>
 #include <linux/ide.h>
 #include <linux/initrd.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/tty.h>
index b38a851a64ecc2250a4b1dca23377083e703aeb4..79b3f533d0a3a698d2159dbec8f46d39428c2d3b 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/major.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/serial.h>
index f761fdf160db5ee353c8cd56518f45ac955102f6..7dc8a68acfd03a99e5c9c5fe18fae9b3b94b5a31 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/major.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/serial.h>
index f2748c88665ac5e044565d165fa6c4bf126c7065..8841fd7da6eeb2246349f5a6313b593b8021f880 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/major.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/serial.h>
index 18e952d1767cd7a481f38a4c372e8af1b602c1ae..bd3ac0136756bc260c31cec5f0686826d055adcd 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/major.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/serial.h>
 #include <linux/module.h>
index 6267b294f7047496eaf854aeec37fb4739d44ee3..9f9039498ae523f3c65f72ff0c53b9c6ba2908e1 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/major.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/serial.h>
 #include <linux/module.h>
index 165df94d4aa6d6d248479220e64b8005333aef1c..c76760a781c173089aa065f0d9371c5d24f8af98 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/major.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/serial.h>
index 4f6d1ddd6fb8073cc76d7923b3721e77ac80028a..c02f110219f5e7a8d221e40639db5ac3195f9b7b 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/major.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/serial.h>
 #include <linux/module.h>
index c99b365d6110e5534edd483e778301d024eda1f8..20940f4044f477aee7f53fab6edcbeb411eee97b 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/blkdev.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/root_dev.h>
 #include <linux/seq_file.h>
 #include <linux/serial.h>
index 7786818bd9d03709253dbdecc76edd1c472073f6..df6ff98c023ac048d387878ba937371cc0d9a531 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/time.h>
 #include <asm/dma.h>
 #include <asm/io.h>
-#include <linux/irq.h>
 #include <asm/hw_irq.h>
 #include <asm/machdep.h>
 #include <asm/kgdb.h>
index 57f29ab29bdae072f6f25090f3f4952b401e8e71..66346f0de7ec14178b218146a75d7e716b0c3577 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
-#include <linux/irq.h>
 #include <linux/console.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
index e391e52383c7e1455b7e3da5047522eedcca937b..3a5ff9fb71d6e1cae9e8806cc2f63e3115e545c0 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/major.h>
 #include <linux/initrd.h>
 #include <linux/console.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/bcd.h>
index b292b44b760c4960da0abbb2583cc9441944293d..ce2ce88c80337d0416a9e8d4576e996ed263d26f 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/initrd.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/ide.h>
 #include <linux/seq_file.h>
 #include <linux/kdev_t.h>
index c0605244edda159d58b2afc5e66013d0a21a34d6..d4bc5f67ec5358f42aa79c0f68b58ac1e55f7920 100644 (file)
@@ -695,6 +695,13 @@ static int __init pmac_cpufreq_setup(void)
                set_speed_proc = pmu_set_cpu_speed;
                is_pmu_based = 1;
        }
+       /* Else check for TiPb 550 */
+       else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) {
+               hi_freq = cur_freq;
+               low_freq = 500000;
+               set_speed_proc = pmu_set_cpu_speed;
+               is_pmu_based = 1;
+       }
        /* Else check for TiPb 400 & 500 */
        else if (machine_is_compatible("PowerBook3,2")) {
                /* We only know about the 400 MHz and the 500Mhz model
index 867336ad5d36b284b12d0d682f9fd28b7867a3ac..dd6d45ae0501cac648d845ea701bb24faa21685c 100644 (file)
@@ -2337,6 +2337,10 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
                PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
                PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
        },
+       {       "PowerBook6,7",                 "iBook G4",
+               PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
+               PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+       },
        {       "PowerBook6,8",                 "PowerBook G4 12\"",
                PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
                PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
index 4c56a4734aec53333b0f328c31c98e765097b99d..d6356f480d906b97f8545ab69684743060e1b67e 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/pmu.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
 #include <linux/bitops.h>
index 0abe15159e6ca2cfd804444b8eca5e882593cf5b..e6b520e6e13feaec3e9c073616f57821d1d9a97d 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/initrd.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 #include <linux/ide.h>
index 65705c9117950d097792f06068a0388f88db8f4a..e70aae20d6f9c3a83a5d3ba3d4f771e8e762eb73 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/ioport.h>
 #include <linux/console.h>
 #include <linux/pci.h>
-#include <linux/irq.h>
 #include <linux/ide.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
index 24ae1caafc618a4447e91abd2f7a869c0868c5d0..0bb14a5e824caba79a67d8f636ffa4f0dea3e09a 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/initrd.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/ide.h>
 #include <linux/root_dev.h>
index 8b09fa69b35b2addd6d264fcdc8c6f3597691347..de7baefacd3aa43094ee4213a36206f9f72226bc 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/initrd.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/ide.h>
 #include <linux/root_dev.h>
index c30607a972d87121079bd93c5399b1d6b8fc393e..0376c8cff5d1e33bcd22e28d4dac37e4ceeb8921 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/initrd.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/ide.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
@@ -59,7 +58,6 @@
 #include <asm/mpc10x.h>
 #include <asm/pci-bridge.h>
 #include <asm/mv64x60.h>
-#include <asm/i8259.h>
 
 #include "radstone_ppc7d.h"
 
index 21e31346b12ba6856db725af94f7ac648ab00e5f..5232283c1974a554658998de11cbf02d3a309b3a 100644 (file)
@@ -74,7 +74,6 @@
 #include <linux/initrd.h>
 #include <linux/console.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/ide.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
index 839f8872826f40480088397ddb9da28f716f1356..4849850a59edd55c872bbb92a13c327842b7ad0e 100644 (file)
@@ -34,7 +34,7 @@ u8 mv64x60_pci_exclude_bridge = 1;
 DEFINE_SPINLOCK(mv64x60_lock);
 
 static phys_addr_t     mv64x60_bridge_pbase;
-static void            *mv64x60_bridge_vbase;
+static void            __iomem *mv64x60_bridge_vbase;
 static u32             mv64x60_bridge_type = MV64x60_TYPE_INVALID;
 static u32             mv64x60_bridge_rev;
 #if defined(CONFIG_SYSFS) && !defined(CONFIG_GT64260)
@@ -938,7 +938,7 @@ mv64x60_setup_for_chip(struct mv64x60_handle *bh)
  *
  * Return the virtual address of the bridge's registers.
  */
-void *
+void __iomem *
 mv64x60_get_bridge_vbase(void)
 {
        return mv64x60_bridge_vbase;
index 53da58523e39f3380e303f4f33e0ca20c32db81d..1cf5de21a3fd3a0ffc6b3e26823d7fb236962163 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
 #include <linux/errno.h>
index 9a7e8748e2b2460353adc9d3f2974f81aa3e083d..16cff91d9f41899cbbdb9ec525d26c0e889f42ec 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
 #include <linux/errno.h>
index b843c4fef25e694ba56182ff2ff68e0fe9a0b269..bf83240689dc3b6b84ecde3afce81a6bfe0578b1 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/smp.h>
 #include <linux/threads.h>
 #include <linux/spinlock.h>
-#include <linux/irq.h>
 #include <linux/reboot.h>
 #include <linux/param.h>
 #include <linux/string.h>
index f33a7bccb0d780ed4e66f03b0acf8113c5776cfe..507eb9d0223faef5f97d430051ebbd658f19c5b8 100644 (file)
@@ -99,7 +99,11 @@ get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_
                break;
 
        default: /* not a known compile time constant */
-               BUILD_BUG_ON(1);
+               {
+                       /* BUILD_BUG_ON() is not usable here */
+                       extern void __get_iost_entry_bad_page_size(void);
+                       __get_iost_entry_bad_page_size();
+               }
                break;
        }
 
index 7e80d49c589a3bf2f5eea3e68f3d3690b1ceeb03..9c6facc24f703240d1dd9fe0ecc3771d2c267dc1 100644 (file)
@@ -59,9 +59,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 
        /* insn must be on a special executable page on ppc64 */
        if (!ret) {
-               up(&kprobe_mutex);
-               p->ainsn.insn = get_insn_slot();
                down(&kprobe_mutex);
+               p->ainsn.insn = get_insn_slot();
+               up(&kprobe_mutex);
                if (!p->ainsn.insn)
                        ret = -ENOMEM;
        }
@@ -90,9 +90,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-       up(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn);
        down(&kprobe_mutex);
+       free_insn_slot(p->ainsn.insn);
+       up(&kprobe_mutex);
 }
 
 static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
index 4775f12a013c5b1a728b5f4ef57f81ef4f07e0be..bf7cc4f8210f125b245d1e36b0dd4ec60ef263fc 100644 (file)
@@ -205,6 +205,7 @@ static void kexec_prepare_cpus(void)
                        continue;
 
                while (paca[i].hw_cpu_id != -1) {
+                       barrier();
                        if (!cpu_possible(i)) {
                                printk("kexec: cpu %d hw_cpu_id %d is not"
                                                " possible, ignoring\n",
index eb1bbb5b6c160bcf3b4e2e1a8f630951c3209be8..bfd385b7713c7c53063226cb01e48260f7896f30 100644 (file)
@@ -343,7 +343,7 @@ static void native_flush_hash_range(unsigned long context,
        hpte_t *hptep;
        unsigned long hpte_v;
        struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
-       unsigned long large;
+       unsigned long large = batch->large;
 
        local_irq_save(flags);
 
@@ -356,7 +356,6 @@ static void native_flush_hash_range(unsigned long context,
 
                va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
                batch->vaddr[j] = va;
-               large = pte_huge(batch->pte[i]);
                if (large)
                        vpn = va >> HPAGE_SHIFT;
                else
@@ -406,7 +405,7 @@ static void native_flush_hash_range(unsigned long context,
                asm volatile("ptesync":::"memory");
 
                for (i = 0; i < j; i++)
-                       __tlbie(batch->vaddr[i], 0);
+                       __tlbie(batch->vaddr[i], large);
 
                asm volatile("eieio; tlbsync; ptesync":::"memory");
 
index d8a6593a13f0ad98fd0b64310b514551b02047e4..21fbffb23a43df153b114f36bba67f5f27ab4b52 100644 (file)
@@ -143,7 +143,8 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
         * up scanning and resetting referenced bits then our batch context
         * will change mid stream.
         */
-       if (unlikely(i != 0 && context != batch->context)) {
+       if (i != 0 && (context != batch->context ||
+                      batch->large != pte_huge(pte))) {
                flush_tlb_pending();
                i = 0;
        }
@@ -151,6 +152,7 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
        if (i == 0) {
                batch->context = context;
                batch->mm = mm;
+               batch->large = pte_huge(pte);
        }
        batch->pte[i] = __pte(pte);
        batch->addr[i] = addr;
index 7358cdb8441fbf960a1f1bb5371780f3f5e798c6..4ff6808456ea40798acaacdeb0c4f09481eda3d8 100644 (file)
@@ -143,7 +143,7 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
                        break;
                case __SI_FAULT >> 16:
                        err |= __get_user(tmp, &from->si_addr);
-                       to->si_addr = (void *)(u64) (tmp & PSW32_ADDR_INSN);
+                       to->si_addr = (void __user *)(u64) (tmp & PSW32_ADDR_INSN);
                        break;
                case __SI_POLL >> 16:
                        err |= __get_user(to->si_band, &from->si_band);
@@ -338,7 +338,7 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
                err |= __get_user(kss.ss_flags, &uss->ss_flags);
                if (err)
                        return -EFAULT;
-               kss.ss_sp = (void *) ss_sp;
+               kss.ss_sp = (void __user *) ss_sp;
        }
 
        set_fs (KERNEL_DS);
@@ -461,7 +461,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
                goto badframe;
 
        err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
-       st.ss_sp = (void *) A((unsigned long)ss_sp);
+       st.ss_sp = compat_ptr(ss_sp);
        err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size);
        err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags);
        if (err)
index 6a3f5b7473a91b7c1a5ad08238430966f839e9f1..6e0110d71191fe176c24fa655879605a9fdbf3b8 100644 (file)
@@ -376,8 +376,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Create the ucontext.  */
        err |= __put_user(0, &frame->uc.uc_flags);
-       err |= __put_user(0, &frame->uc.uc_link);
-       err |= __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+       err |= __put_user(NULL, &frame->uc.uc_link);
+       err |= __put_user((void __user *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
        err |= __put_user(sas_ss_flags(regs->gprs[15]),
                          &frame->uc.uc_stack.ss_flags);
        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
index 53c192a4982f7210d8bd5587c2f0d99987a86b7b..3509e43055322b69d3bf41641ae6d833b2833a30 100644 (file)
@@ -249,8 +249,6 @@ struct tt_entry *sparc_ttable;
 
 struct pt_regs fake_swapper_regs;
 
-extern void paging_init(void);
-
 void __init setup_arch(char **cmdline_p)
 {
        int i;
index af0e9411b83e62fbbb6539eadc0bd2cdcdc34f13..fa06ea04837b9525da90580e0c4db0a3d9f3a952 100644 (file)
@@ -33,6 +33,14 @@ config DEBUG_BOOTMEM
        depends on DEBUG_KERNEL
        bool "Debug BOOTMEM initialization"
 
+config DEBUG_PAGEALLOC
+       bool "Page alloc debugging"
+       depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND
+       help
+         Unmap pages from the kernel linear mapping after free_pages().
+         This results in a large slowdown, but helps to find certain types
+         of memory corruptions.
+
 config MCOUNT
        bool
        depends on STACK_DEBUG
index 48756958116b56156c774498a8567e75d573f9e7..77ef5df4e5a7c7bb40b8b5f0ff96036083fd9078 100644 (file)
@@ -39,6 +39,8 @@ struct cpu_fp_info linux_sparc_fpu[] = {
   { 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"},
   { 0x3e, 0x16, 0, "UltraSparc IIIi integrated FPU"},
   { 0x3e, 0x18, 0, "UltraSparc IV integrated FPU"},
+  { 0x3e, 0x19, 0, "UltraSparc IV+ integrated FPU"},
+  { 0x3e, 0x22, 0, "UltraSparc IIIi+ integrated FPU"},
 };
 
 #define NSPARCFPU  (sizeof(linux_sparc_fpu)/sizeof(struct cpu_fp_info))
@@ -53,6 +55,8 @@ struct cpu_iu_info linux_sparc_chips[] = {
   { 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"},
   { 0x3e, 0x16, "TI UltraSparc IIIi (Jalapeno)"},
   { 0x3e, 0x18, "TI UltraSparc IV (Jaguar)"},
+  { 0x3e, 0x19, "TI UltraSparc IV+ (Panther)"},
+  { 0x3e, 0x22, "TI UltraSparc IIIi+ (Serrano)"},
 };
 
 #define NSPARCCHIPS  (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info))
index d710274e516bf6a400b573473692611b6dbe024c..df9a1ca8fd773ad7e97418bf69fba2428a07aa99 100644 (file)
@@ -135,6 +135,28 @@ void __init device_scan(void)
                cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
                                                            "clock-frequency",
                                                            0);
+               cpu_data(0).dcache_size = prom_getintdefault(cpu_node,
+                                                            "dcache-size",
+                                                            16 * 1024);
+               cpu_data(0).dcache_line_size =
+                       prom_getintdefault(cpu_node, "dcache-line-size", 32);
+               cpu_data(0).icache_size = prom_getintdefault(cpu_node,
+                                                            "icache-size",
+                                                            16 * 1024);
+               cpu_data(0).icache_line_size =
+                       prom_getintdefault(cpu_node, "icache-line-size", 32);
+               cpu_data(0).ecache_size = prom_getintdefault(cpu_node,
+                                                            "ecache-size",
+                                                            4 * 1024 * 1024);
+               cpu_data(0).ecache_line_size =
+                       prom_getintdefault(cpu_node, "ecache-line-size", 64);
+               printk("CPU[0]: Caches "
+                      "D[sz(%d):line_sz(%d)] "
+                      "I[sz(%d):line_sz(%d)] "
+                      "E[sz(%d):line_sz(%d)]\n",
+                      cpu_data(0).dcache_size, cpu_data(0).dcache_line_size,
+                      cpu_data(0).icache_size, cpu_data(0).icache_line_size,
+                      cpu_data(0).ecache_size, cpu_data(0).ecache_line_size);
        }
 #endif
 
index 538522848ad4ee6661ba545c0232849fc4a5d3ff..acc889a7f9c1f3cd78e620cbcaeea37edfb0f5c3 100644 (file)
@@ -9,17 +9,7 @@
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 
-#if PAGE_SHIFT == 13
-#define SZ_BITS                _PAGE_SZ8K
-#elif PAGE_SHIFT == 16
-#define SZ_BITS                _PAGE_SZ64K
-#elif PAGE_SHIFT == 19
-#define SZ_BITS                _PAGE_SZ512K
-#elif PAGE_SHIFT == 22
-#define SZ_BITS                _PAGE_SZ4MB
-#endif
-
-#define VALID_SZ_BITS  (_PAGE_VALID | SZ_BITS)
+#define VALID_SZ_BITS  (_PAGE_VALID | _PAGE_SZBITS)
 
 #define VPTE_BITS              (_PAGE_CP | _PAGE_CV | _PAGE_P )
 #define VPTE_SHIFT             (PAGE_SHIFT - 3)
@@ -163,7 +153,6 @@ sparc64_vpte_continue:
        stxa            %g4, [%g1 + %g1] ASI_DMMU       ! Restore previous TAG_ACCESS
        retry                                           ! Load PTE once again
 
-#undef SZ_BITS
 #undef VALID_SZ_BITS
 #undef VPTE_SHIFT
 #undef VPTE_BITS
index ded2fed23fcc5654245f658d6d98388d61eb33df..702d349c1e88f7d22cf208f93150913600f78a26 100644 (file)
@@ -71,7 +71,7 @@
 from_tl1_trap:
        rdpr            %tl, %g5                        ! For TL==3 test
        CREATE_VPTE_OFFSET1(%g4, %g6)                   ! Create VPTE offset
-       be,pn           %xcc, 3f                        ! Yep, special processing
+       be,pn           %xcc, kvmap                     ! Yep, special processing
         CREATE_VPTE_OFFSET2(%g4, %g6)                  ! Create VPTE offset
        cmp             %g5, 4                          ! Last trap level?
        be,pn           %xcc, longpath                  ! Yep, cannot risk VPTE miss
@@ -83,9 +83,9 @@ from_tl1_trap:
         nop                                            ! Delay-slot
 9:     stxa            %g5, [%g0] ASI_DTLB_DATA_IN     ! Reload TLB
        retry                                           ! Trap return
-3:     brlz,pt         %g4, 9b                         ! Kernel virtual map?
-        xor            %g2, %g4, %g5                   ! Finish bit twiddles
-       ba,a,pt         %xcc, kvmap                     ! Yep, go check for obp/vmalloc
+       nop
+       nop
+       nop
 
 /* DTLB ** ICACHE line 3: winfixups+real_faults                */
 longpath:
index b48349527853eff14a0eaab5befc217f66273a0a..2879b10729217ca6e5ea5777e76b5f767607ecca 100644 (file)
        .text
        .align          32
 
-       .globl          sparc64_vpte_patchme1
-       .globl          sparc64_vpte_patchme2
-/*
- * On a second level vpte miss, check whether the original fault is to the OBP 
- * range (note that this is only possible for instruction miss, data misses to
- * obp range do not use vpte). If so, go back directly to the faulting address.
- * This is because we want to read the tpc, otherwise we have no way of knowing
- * the 8k aligned faulting address if we are using >8k kernel pagesize. This
- * also ensures no vpte range addresses are dropped into tlb while obp is
- * executing (see inherit_locked_prom_mappings() rant).
- */
-sparc64_vpte_nucleus:
-       /* Note that kvmap below has verified that the address is
-        * in the range MODULES_VADDR --> VMALLOC_END already.  So
-        * here we need only check if it is an OBP address or not.
-        */
-       sethi           %hi(LOW_OBP_ADDRESS), %g5
-       cmp             %g4, %g5
-       blu,pn          %xcc, sparc64_vpte_patchme1
-        mov            0x1, %g5
-       sllx            %g5, 32, %g5
-       cmp             %g4, %g5
-       blu,pn          %xcc, obp_iaddr_patch
-        nop
-
-       /* These two instructions are patched by paginig_init().  */
-sparc64_vpte_patchme1:
-       sethi           %hi(0), %g5
-sparc64_vpte_patchme2:
-       or              %g5, %lo(0), %g5
-
-       /* With kernel PGD in %g5, branch back into dtlb_backend.  */
-       ba,pt           %xcc, sparc64_kpte_continue
-        andn           %g1, 0x3, %g1   /* Finish PMD offset adjustment.  */
-
-vpte_noent:
-       /* Restore previous TAG_ACCESS, %g5 is zero, and we will
-        * skip over the trap instruction so that the top level
-        * TLB miss handler will thing this %g5 value is just an
-        * invalid PTE, thus branching to full fault processing.
-        */
-       mov             TLB_SFSR, %g1
-       stxa            %g4, [%g1 + %g1] ASI_DMMU
-       done
-
-       .globl          obp_iaddr_patch
-obp_iaddr_patch:
-       /* These two instructions patched by inherit_prom_mappings().  */
-       sethi           %hi(0), %g5
-       or              %g5, %lo(0), %g5
-
-       /* Behave as if we are at TL0.  */
-       wrpr            %g0, 1, %tl
-       rdpr            %tpc, %g4       /* Find original faulting iaddr */
-       srlx            %g4, 13, %g4    /* Throw out context bits */
-       sllx            %g4, 13, %g4    /* g4 has vpn + ctx0 now */
-
-       /* Restore previous TAG_ACCESS.  */
-       mov             TLB_SFSR, %g1
-       stxa            %g4, [%g1 + %g1] ASI_IMMU
-
-       /* Get PMD offset.  */
-       srlx            %g4, 23, %g6
-       and             %g6, 0x7ff, %g6
-       sllx            %g6, 2, %g6
-
-       /* Load PMD, is it valid?  */
-       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brz,pn          %g5, longpath
-        sllx           %g5, 11, %g5
-
-       /* Get PTE offset.  */
-       srlx            %g4, 13, %g6
-       and             %g6, 0x3ff, %g6
-       sllx            %g6, 3, %g6
-
-       /* Load PTE.  */
-       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brgez,pn        %g5, longpath
-        nop
-
-       /* TLB load and return from trap.  */
-       stxa            %g5, [%g0] ASI_ITLB_DATA_IN
-       retry
-
-       .globl          obp_daddr_patch
-obp_daddr_patch:
-       /* These two instructions patched by inherit_prom_mappings().  */
-       sethi           %hi(0), %g5
-       or              %g5, %lo(0), %g5
-
-       /* Get PMD offset.  */
-       srlx            %g4, 23, %g6
-       and             %g6, 0x7ff, %g6
-       sllx            %g6, 2, %g6
-
-       /* Load PMD, is it valid?  */
-       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brz,pn          %g5, longpath
-        sllx           %g5, 11, %g5
-
-       /* Get PTE offset.  */
-       srlx            %g4, 13, %g6
-       and             %g6, 0x3ff, %g6
-       sllx            %g6, 3, %g6
-
-       /* Load PTE.  */
-       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
-       brgez,pn        %g5, longpath
-        nop
-
-       /* TLB load and return from trap.  */
-       stxa            %g5, [%g0] ASI_DTLB_DATA_IN
-       retry
-
-/*
- * On a first level data miss, check whether this is to the OBP range (note
- * that such accesses can be made by prom, as well as by kernel using
- * prom_getproperty on "address"), and if so, do not use vpte access ...
- * rather, use information saved during inherit_prom_mappings() using 8k
- * pagesize.
- */
-       .align          32
-kvmap:
-       sethi           %hi(MODULES_VADDR), %g5
-       cmp             %g4, %g5
-       blu,pn          %xcc, longpath
-        mov            (VMALLOC_END >> 24), %g5
-       sllx            %g5, 24, %g5
-       cmp             %g4, %g5
-       bgeu,pn         %xcc, longpath
-        nop
-
-kvmap_check_obp:
-       sethi           %hi(LOW_OBP_ADDRESS), %g5
-       cmp             %g4, %g5
-       blu,pn          %xcc, kvmap_vmalloc_addr
-        mov            0x1, %g5
-       sllx            %g5, 32, %g5
-       cmp             %g4, %g5
-       blu,pn          %xcc, obp_daddr_patch
-        nop
-
-kvmap_vmalloc_addr:
-       /* If we get here, a vmalloc addr was accessed, load kernel VPTE.  */
-       ldxa            [%g3 + %g6] ASI_N, %g5
-       brgez,pn        %g5, longpath
-        nop
-
-       /* PTE is valid, load into TLB and return from trap.  */
-       stxa            %g5, [%g0] ASI_DTLB_DATA_IN     ! Reload TLB
-       retry
-
        /* This is trivial with the new code... */
        .globl          do_fpdis
 do_fpdis:
@@ -525,14 +372,13 @@ cheetah_plus_patch_fpdis:
         *
         * DATA 0: [low 32-bits]  Address of function to call, jmp to this
         *         [high 32-bits] MMU Context Argument 0, place in %g5
-        * DATA 1: Address Argument 1, place in %g6
+        * DATA 1: Address Argument 1, place in %g1
         * DATA 2: Address Argument 2, place in %g7
         *
         * With this method we can do most of the cross-call tlb/cache
         * flushing very quickly.
         *
-        * Current CPU's IRQ worklist table is locked into %g1,
-        * don't touch.
+        * Current CPU's IRQ worklist table is locked into %g6, don't touch.
         */
        .text
        .align          32
@@ -1006,13 +852,14 @@ cheetah_plus_dcpe_trap_vector:
        nop
 
 do_cheetah_plus_data_parity:
-       ba,pt           %xcc, etrap
+       rdpr            %pil, %g2
+       wrpr            %g0, 15, %pil
+       ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
        mov             0x0, %o0
        call            cheetah_plus_parity_error
         add            %sp, PTREGS_OFF, %o1
-       ba,pt           %xcc, rtrap
-        clr            %l6
+       ba,a,pt         %xcc, rtrap_irq
 
 cheetah_plus_dcpe_trap_vector_tl1:
        membar          #Sync
@@ -1036,13 +883,14 @@ cheetah_plus_icpe_trap_vector:
        nop
 
 do_cheetah_plus_insn_parity:
-       ba,pt           %xcc, etrap
+       rdpr            %pil, %g2
+       wrpr            %g0, 15, %pil
+       ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
        mov             0x1, %o0
        call            cheetah_plus_parity_error
         add            %sp, PTREGS_OFF, %o1
-       ba,pt           %xcc, rtrap
-        clr            %l6
+       ba,a,pt         %xcc, rtrap_irq
 
 cheetah_plus_icpe_trap_vector_tl1:
        membar          #Sync
@@ -1075,6 +923,10 @@ do_dcpe_tl1:
         nop
        wrpr            %g1, %tl                ! Restore original trap level
 do_dcpe_tl1_nonfatal:  /* Ok we may use interrupt globals safely. */
+       sethi           %hi(dcache_parity_tl1_occurred), %g2
+       lduw            [%g2 + %lo(dcache_parity_tl1_occurred)], %g1
+       add             %g1, 1, %g1
+       stw             %g1, [%g2 + %lo(dcache_parity_tl1_occurred)]
        /* Reset D-cache parity */
        sethi           %hi(1 << 16), %g1       ! D-cache size
        mov             (1 << 5), %g2           ! D-cache line size
@@ -1121,6 +973,10 @@ do_icpe_tl1:
         nop
        wrpr            %g1, %tl                ! Restore original trap level
 do_icpe_tl1_nonfatal:  /* Ok we may use interrupt globals safely. */
+       sethi           %hi(icache_parity_tl1_occurred), %g2
+       lduw            [%g2 + %lo(icache_parity_tl1_occurred)], %g1
+       add             %g1, 1, %g1
+       stw             %g1, [%g2 + %lo(icache_parity_tl1_occurred)]
        /* Flush I-cache */
        sethi           %hi(1 << 15), %g1       ! I-cache size
        mov             (1 << 5), %g2           ! I-cache line size
index 1fa06c4e3bdb8da1c5496dc14fa5547a69fe79f0..89406f9649a9cf6ed4f3d7d995bb38484e780c39 100644 (file)
@@ -80,15 +80,165 @@ sparc_ramdisk_image64:
        .xword  0
        .word   _end
 
-       /* We must be careful, 32-bit OpenBOOT will get confused if it
-        * tries to save away a register window to a 64-bit kernel
-        * stack address.  Flush all windows, disable interrupts,
-        * remap if necessary, jump onto kernel trap table, then kernel
-        * stack, or else we die.
+       /* PROM cif handler code address is in %o4.  */
+sparc64_boot:
+1:     rd      %pc, %g7
+       set     1b, %g1
+       cmp     %g1, %g7
+       be,pn   %xcc, sparc64_boot_after_remap
+        mov    %o4, %l7
+
+       /* We need to remap the kernel.  Use position independant
+        * code to remap us to KERNBASE.
         *
-        * PROM entry point is on %o4
+        * SILO can invoke us with 32-bit address masking enabled,
+        * so make sure that's clear.
         */
-sparc64_boot:
+       rdpr    %pstate, %g1
+       andn    %g1, PSTATE_AM, %g1
+       wrpr    %g1, 0x0, %pstate
+       ba,a,pt %xcc, 1f
+
+       .globl  prom_finddev_name, prom_chosen_path
+       .globl  prom_getprop_name, prom_mmu_name
+       .globl  prom_callmethod_name, prom_translate_name
+       .globl  prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache
+       .globl  prom_boot_mapped_pc, prom_boot_mapping_mode
+       .globl  prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
+prom_finddev_name:
+       .asciz  "finddevice"
+prom_chosen_path:
+       .asciz  "/chosen"
+prom_getprop_name:
+       .asciz  "getprop"
+prom_mmu_name:
+       .asciz  "mmu"
+prom_callmethod_name:
+       .asciz  "call-method"
+prom_translate_name:
+       .asciz  "translate"
+prom_map_name:
+       .asciz  "map"
+prom_unmap_name:
+       .asciz  "unmap"
+       .align  4
+prom_mmu_ihandle_cache:
+       .word   0
+prom_boot_mapped_pc:
+       .word   0
+prom_boot_mapping_mode:
+       .word   0
+       .align  8
+prom_boot_mapping_phys_high:
+       .xword  0
+prom_boot_mapping_phys_low:
+       .xword  0
+1:
+       rd      %pc, %l0
+       mov     (1b - prom_finddev_name), %l1
+       mov     (1b - prom_chosen_path), %l2
+       mov     (1b - prom_boot_mapped_pc), %l3
+       sub     %l0, %l1, %l1
+       sub     %l0, %l2, %l2
+       sub     %l0, %l3, %l3
+       stw     %l0, [%l3]
+       sub     %sp, (192 + 128), %sp
+
+       /* chosen_node = prom_finddevice("/chosen") */
+       stx     %l1, [%sp + 2047 + 128 + 0x00]  ! service, "finddevice"
+       mov     1, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 1
+       stx     %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
+       stx     %l2, [%sp + 2047 + 128 + 0x18]  ! arg1, "/chosen"
+       stx     %g0, [%sp + 2047 + 128 + 0x20]  ! ret1
+       call    %l7
+        add    %sp, (2047 + 128), %o0          ! argument array
+
+       ldx     [%sp + 2047 + 128 + 0x20], %l4  ! chosen device node
+
+       mov     (1b - prom_getprop_name), %l1
+       mov     (1b - prom_mmu_name), %l2
+       mov     (1b - prom_mmu_ihandle_cache), %l5
+       sub     %l0, %l1, %l1
+       sub     %l0, %l2, %l2
+       sub     %l0, %l5, %l5
+
+       /* prom_mmu_ihandle_cache = prom_getint(chosen_node, "mmu") */
+       stx     %l1, [%sp + 2047 + 128 + 0x00]  ! service, "getprop"
+       mov     4, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 4
+       mov     1, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
+       stx     %l4, [%sp + 2047 + 128 + 0x18]  ! arg1, chosen_node
+       stx     %l2, [%sp + 2047 + 128 + 0x20]  ! arg2, "mmu"
+       stx     %l5, [%sp + 2047 + 128 + 0x28]  ! arg3, &prom_mmu_ihandle_cache
+       mov     4, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x30]  ! arg4, sizeof(arg3)
+       stx     %g0, [%sp + 2047 + 128 + 0x38]  ! ret1
+       call    %l7
+        add    %sp, (2047 + 128), %o0          ! argument array
+
+       mov     (1b - prom_callmethod_name), %l1
+       mov     (1b - prom_translate_name), %l2
+       sub     %l0, %l1, %l1
+       sub     %l0, %l2, %l2
+       lduw    [%l5], %l5                      ! prom_mmu_ihandle_cache
+
+       stx     %l1, [%sp + 2047 + 128 + 0x00]  ! service, "call-method"
+       mov     3, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 3
+       mov     5, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 5
+       stx     %l2, [%sp + 2047 + 128 + 0x18]  ! arg1: "translate"
+       stx     %l5, [%sp + 2047 + 128 + 0x20]  ! arg2: prom_mmu_ihandle_cache
+       srlx    %l0, 22, %l3
+       sllx    %l3, 22, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x28]  ! arg3: vaddr, our PC
+       stx     %g0, [%sp + 2047 + 128 + 0x30]  ! res1
+       stx     %g0, [%sp + 2047 + 128 + 0x38]  ! res2
+       stx     %g0, [%sp + 2047 + 128 + 0x40]  ! res3
+       stx     %g0, [%sp + 2047 + 128 + 0x48]  ! res4
+       stx     %g0, [%sp + 2047 + 128 + 0x50]  ! res5
+       call    %l7
+        add    %sp, (2047 + 128), %o0          ! argument array
+
+       ldx     [%sp + 2047 + 128 + 0x40], %l1  ! translation mode
+       mov     (1b - prom_boot_mapping_mode), %l4
+       sub     %l0, %l4, %l4
+       stw     %l1, [%l4]
+       mov     (1b - prom_boot_mapping_phys_high), %l4
+       sub     %l0, %l4, %l4
+       ldx     [%sp + 2047 + 128 + 0x48], %l2  ! physaddr high
+       stx     %l2, [%l4 + 0x0]
+       ldx     [%sp + 2047 + 128 + 0x50], %l3  ! physaddr low
+       stx     %l3, [%l4 + 0x8]
+
+       /* Leave service as-is, "call-method" */
+       mov     7, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 7
+       mov     1, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
+       mov     (1b - prom_map_name), %l3
+       sub     %l0, %l3, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x18]  ! arg1: "map"
+       /* Leave arg2 as-is, prom_mmu_ihandle_cache */
+       mov     -1, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x28]  ! arg3: mode (-1 default)
+       sethi   %hi(8 * 1024 * 1024), %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x30]  ! arg4: size (8MB)
+       sethi   %hi(KERNBASE), %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x38]  ! arg5: vaddr (KERNBASE)
+       stx     %g0, [%sp + 2047 + 128 + 0x40]  ! arg6: empty
+       mov     (1b - prom_boot_mapping_phys_low), %l3
+       sub     %l0, %l3, %l3
+       ldx     [%l3], %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x48]  ! arg7: phys addr
+       call    %l7
+        add    %sp, (2047 + 128), %o0          ! argument array
+
+       add     %sp, (192 + 128), %sp
+
+sparc64_boot_after_remap:
        BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot)
        BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
        ba,pt   %xcc, spitfire_boot
@@ -125,185 +275,7 @@ cheetah_generic_boot:
        stxa    %g0, [%g3] ASI_IMMU
        membar  #Sync
 
-       wrpr    %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
-       wr      %g0, 0, %fprs
-
-       /* Just like for Spitfire, we probe itlb-2 for a mapping which
-        * matches our current %pc.  We take the physical address in
-        * that mapping and use it to make our own.
-        */
-
-       /* %g5 holds the tlb data */
-        sethi   %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
-        sllx    %g5, 32, %g5
-        or      %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
-
-       /* Put PADDR tlb data mask into %g3. */
-       sethi   %uhi(_PAGE_PADDR), %g3
-       or      %g3, %ulo(_PAGE_PADDR), %g3
-       sllx    %g3, 32, %g3
-       sethi   %hi(_PAGE_PADDR), %g7
-       or      %g7, %lo(_PAGE_PADDR), %g7
-       or      %g3, %g7, %g3
-
-       set     2 << 16, %l0            /* TLB entry walker. */
-       set     0x1fff, %l2             /* Page mask. */
-       rd      %pc, %l3
-       andn    %l3, %l2, %g2           /* vaddr comparator */
-
-1:     ldxa    [%l0] ASI_ITLB_TAG_READ, %g1
-       membar  #Sync
-       andn    %g1, %l2, %g1
-       cmp     %g1, %g2
-       be,pn   %xcc, cheetah_got_tlbentry
-        nop
-       and     %l0, (127 << 3), %g1
-       cmp     %g1, (127 << 3)
-       blu,pt  %xcc, 1b
-        add    %l0, (1 << 3), %l0
-
-       /* Search the small TLB.  OBP never maps us like that but
-        * newer SILO can.
-        */
-       clr     %l0
-
-1:     ldxa    [%l0] ASI_ITLB_TAG_READ, %g1
-       membar  #Sync
-       andn    %g1, %l2, %g1
-       cmp     %g1, %g2
-       be,pn   %xcc, cheetah_got_tlbentry
-        nop
-       cmp     %l0, (15 << 3)
-       blu,pt  %xcc, 1b
-        add    %l0, (1 << 3), %l0
-
-       /* BUG() if we get here... */
-       ta      0x5
-
-cheetah_got_tlbentry:
-       ldxa    [%l0] ASI_ITLB_DATA_ACCESS, %g0
-       ldxa    [%l0] ASI_ITLB_DATA_ACCESS, %g1
-       membar  #Sync
-       and     %g1, %g3, %g1
-       set     0x5fff, %l0
-       andn    %g1, %l0, %g1
-       or      %g5, %g1, %g5
-
-       /* Clear out any KERNBASE area entries. */
-       set     2 << 16, %l0
-       sethi   %hi(KERNBASE), %g3
-       sethi   %hi(KERNBASE<<1), %g7
-       mov     TLB_TAG_ACCESS, %l7
-
-       /* First, check ITLB */
-1:     ldxa    [%l0] ASI_ITLB_TAG_READ, %g1
-       membar  #Sync
-       andn    %g1, %l2, %g1
-       cmp     %g1, %g3
-       blu,pn  %xcc, 2f
-        cmp    %g1, %g7
-       bgeu,pn %xcc, 2f
-        nop
-       stxa    %g0, [%l7] ASI_IMMU
-       membar  #Sync
-       stxa    %g0, [%l0] ASI_ITLB_DATA_ACCESS
-       membar  #Sync
-
-2:     and     %l0, (127 << 3), %g1
-       cmp     %g1, (127 << 3)
-       blu,pt  %xcc, 1b
-        add    %l0, (1 << 3), %l0
-
-       /* Next, check DTLB */
-       set     2 << 16, %l0
-1:     ldxa    [%l0] ASI_DTLB_TAG_READ, %g1
-       membar  #Sync
-       andn    %g1, %l2, %g1
-       cmp     %g1, %g3
-       blu,pn  %xcc, 2f
-        cmp    %g1, %g7
-       bgeu,pn %xcc, 2f
-        nop
-       stxa    %g0, [%l7] ASI_DMMU
-       membar  #Sync
-       stxa    %g0, [%l0] ASI_DTLB_DATA_ACCESS
-       membar  #Sync
-       
-2:     and     %l0, (511 << 3), %g1
-       cmp     %g1, (511 << 3)
-       blu,pt  %xcc, 1b
-        add    %l0, (1 << 3), %l0
-
-       /* On Cheetah+, have to check second DTLB.  */
-       BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,l0,2f)
-       ba,pt   %xcc, 9f
-        nop
-
-2:     set     3 << 16, %l0
-1:     ldxa    [%l0] ASI_DTLB_TAG_READ, %g1
-       membar  #Sync
-       andn    %g1, %l2, %g1
-       cmp     %g1, %g3
-       blu,pn  %xcc, 2f
-        cmp    %g1, %g7
-       bgeu,pn %xcc, 2f
-        nop
-       stxa    %g0, [%l7] ASI_DMMU
-       membar  #Sync
-       stxa    %g0, [%l0] ASI_DTLB_DATA_ACCESS
-       membar  #Sync
-       
-2:     and     %l0, (511 << 3), %g1
-       cmp     %g1, (511 << 3)
-       blu,pt  %xcc, 1b
-        add    %l0, (1 << 3), %l0
-
-9:
-
-       /* Now lock the TTE we created into ITLB-0 and DTLB-0,
-        * entry 15 (and maybe 14 too).
-        */
-       sethi   %hi(KERNBASE), %g3
-       set     (0 << 16) | (15 << 3), %g7
-       stxa    %g3, [%l7] ASI_DMMU
-       membar  #Sync
-       stxa    %g5, [%g7] ASI_DTLB_DATA_ACCESS
-       membar  #Sync
-       stxa    %g3, [%l7] ASI_IMMU
-       membar  #Sync
-       stxa    %g5, [%g7] ASI_ITLB_DATA_ACCESS
-       membar  #Sync
-       flush   %g3
-       membar  #Sync
-       sethi   %hi(_end), %g3                  /* Check for bigkernel case */
-       or      %g3, %lo(_end), %g3
-       srl     %g3, 23, %g3                    /* Check if _end > 8M */
-       brz,pt  %g3, 1f
-        sethi  %hi(KERNBASE), %g3              /* Restore for fixup code below */
-       sethi   %hi(0x400000), %g3
-       or      %g3, %lo(0x400000), %g3
-       add     %g5, %g3, %g5                   /* New tte data */
-       andn    %g5, (_PAGE_G), %g5
-       sethi   %hi(KERNBASE+0x400000), %g3
-       or      %g3, %lo(KERNBASE+0x400000), %g3
-       set     (0 << 16) | (14 << 3), %g7
-       stxa    %g3, [%l7] ASI_DMMU
-       membar  #Sync
-       stxa    %g5, [%g7] ASI_DTLB_DATA_ACCESS
-       membar  #Sync
-       stxa    %g3, [%l7] ASI_IMMU
-       membar  #Sync
-       stxa    %g5, [%g7] ASI_ITLB_DATA_ACCESS
-       membar  #Sync
-       flush   %g3
-       membar  #Sync
-       sethi   %hi(KERNBASE), %g3              /* Restore for fixup code below */
-       ba,pt   %xcc, 1f
-        nop
-
-1:     set     sun4u_init, %g2
-       jmpl    %g2 + %g0, %g0
-        nop
+       ba,a,pt %xcc, jump_to_sun4u_init
 
 spitfire_boot:
        /* Typically PROM has already enabled both MMU's and both on-chip
@@ -313,6 +285,7 @@ spitfire_boot:
        stxa    %g1, [%g0] ASI_LSU_CONTROL
        membar  #Sync
 
+jump_to_sun4u_init:
        /*
         * Make sure we are in privileged mode, have address masking,
          * using the ordinary globals and have enabled floating
@@ -324,151 +297,6 @@ spitfire_boot:
        wrpr    %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
        wr      %g0, 0, %fprs
 
-spitfire_create_mappings:
-       /* %g5 holds the tlb data */
-        sethi   %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
-        sllx    %g5, 32, %g5
-        or      %g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
-
-       /* Base of physical memory cannot reliably be assumed to be
-        * at 0x0!  Figure out where it happens to be. -DaveM
-        */
-
-       /* Put PADDR tlb data mask into %g3. */
-       sethi   %uhi(_PAGE_PADDR_SF), %g3
-       or      %g3, %ulo(_PAGE_PADDR_SF), %g3
-       sllx    %g3, 32, %g3
-       sethi   %hi(_PAGE_PADDR_SF), %g7
-       or      %g7, %lo(_PAGE_PADDR_SF), %g7
-       or      %g3, %g7, %g3
-
-       /* Walk through entire ITLB, looking for entry which maps
-        * our %pc currently, stick PADDR from there into %g5 tlb data.
-        */
-       clr     %l0                     /* TLB entry walker. */
-       set     0x1fff, %l2             /* Page mask. */
-       rd      %pc, %l3
-       andn    %l3, %l2, %g2           /* vaddr comparator */
-1:
-       /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
-       ldxa    [%l0] ASI_ITLB_TAG_READ, %g1
-       nop
-       nop
-       nop
-       andn    %g1, %l2, %g1           /* Get vaddr */
-       cmp     %g1, %g2
-       be,a,pn %xcc, spitfire_got_tlbentry
-        ldxa   [%l0] ASI_ITLB_DATA_ACCESS, %g1
-       cmp     %l0, (63 << 3)
-       blu,pt  %xcc, 1b
-        add    %l0, (1 << 3), %l0
-
-       /* BUG() if we get here... */
-       ta      0x5
-
-spitfire_got_tlbentry:
-       /* Nops here again, perhaps Cheetah/Blackbird are better behaved... */
-       nop
-       nop
-       nop
-       and     %g1, %g3, %g1           /* Mask to just get paddr bits.       */
-       set     0x5fff, %l3             /* Mask offset to get phys base.      */
-       andn    %g1, %l3, %g1
-
-       /* NOTE: We hold on to %g1 paddr base as we need it below to lock
-        * NOTE: the PROM cif code into the TLB.
-        */
-
-       or      %g5, %g1, %g5           /* Or it into TAG being built.        */
-
-       clr     %l0                     /* TLB entry walker. */
-       sethi   %hi(KERNBASE), %g3      /* 4M lower limit */
-       sethi   %hi(KERNBASE<<1), %g7   /* 8M upper limit */
-       mov     TLB_TAG_ACCESS, %l7
-1:
-       /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
-       ldxa    [%l0] ASI_ITLB_TAG_READ, %g1
-       nop
-       nop
-       nop
-       andn    %g1, %l2, %g1           /* Get vaddr */
-       cmp     %g1, %g3
-       blu,pn  %xcc, 2f
-        cmp    %g1, %g7
-       bgeu,pn %xcc, 2f
-        nop
-       stxa    %g0, [%l7] ASI_IMMU
-       stxa    %g0, [%l0] ASI_ITLB_DATA_ACCESS
-       membar  #Sync
-2:
-       cmp     %l0, (63 << 3)
-       blu,pt  %xcc, 1b
-        add    %l0, (1 << 3), %l0
-
-       nop; nop; nop
-
-       clr     %l0                     /* TLB entry walker. */
-1:
-       /* Yes, the nops seem to be necessary for now, don't ask me why. -DaveM */
-       ldxa    [%l0] ASI_DTLB_TAG_READ, %g1
-       nop
-       nop
-       nop
-       andn    %g1, %l2, %g1           /* Get vaddr */
-       cmp     %g1, %g3
-       blu,pn  %xcc, 2f
-        cmp    %g1, %g7
-       bgeu,pn %xcc, 2f
-        nop
-       stxa    %g0, [%l7] ASI_DMMU
-       stxa    %g0, [%l0] ASI_DTLB_DATA_ACCESS
-       membar  #Sync
-2:
-       cmp     %l0, (63 << 3)
-       blu,pt  %xcc, 1b
-        add    %l0, (1 << 3), %l0
-
-       nop; nop; nop
-
-
-       /* PROM never puts any TLB entries into the MMU with the lock bit
-        * set.  So we gladly use tlb entry 63 for KERNBASE. And maybe 62 too.
-        */
-
-       sethi   %hi(KERNBASE), %g3
-       mov     (63 << 3), %g7
-       stxa    %g3, [%l7] ASI_DMMU             /* KERNBASE into TLB TAG        */
-       stxa    %g5, [%g7] ASI_DTLB_DATA_ACCESS /* TTE into TLB DATA            */
-       membar  #Sync
-       stxa    %g3, [%l7] ASI_IMMU             /* KERNBASE into TLB TAG        */
-       stxa    %g5, [%g7] ASI_ITLB_DATA_ACCESS /* TTE into TLB DATA            */
-       membar  #Sync
-       flush   %g3
-       membar  #Sync
-       sethi   %hi(_end), %g3                  /* Check for bigkernel case */
-       or      %g3, %lo(_end), %g3
-       srl     %g3, 23, %g3                    /* Check if _end > 8M */
-       brz,pt  %g3, 2f
-        sethi  %hi(KERNBASE), %g3              /* Restore for fixup code below */
-       sethi   %hi(0x400000), %g3
-       or      %g3, %lo(0x400000), %g3
-       add     %g5, %g3, %g5                   /* New tte data */
-       andn    %g5, (_PAGE_G), %g5
-       sethi   %hi(KERNBASE+0x400000), %g3
-       or      %g3, %lo(KERNBASE+0x400000), %g3
-       mov     (62 << 3), %g7
-       stxa    %g3, [%l7] ASI_DMMU
-       stxa    %g5, [%g7] ASI_DTLB_DATA_ACCESS
-       membar  #Sync
-       stxa    %g3, [%l7] ASI_IMMU
-       stxa    %g5, [%g7] ASI_ITLB_DATA_ACCESS
-       membar  #Sync
-       flush   %g3
-       membar  #Sync
-       sethi   %hi(KERNBASE), %g3              /* Restore for fixup code below */
-2:     ba,pt   %xcc, 1f
-        nop
-1:
        set     sun4u_init, %g2
        jmpl    %g2 + %g0, %g0
         nop
@@ -483,38 +311,12 @@ sun4u_init:
        stxa    %g0, [%g7] ASI_DMMU
        membar  #Sync
 
-       /* We are now safely (we hope) in Nucleus context (0), rewrite
-        * the KERNBASE TTE's so they no longer have the global bit set.
-        * Don't forget to setup TAG_ACCESS first 8-)
-        */
-       mov     TLB_TAG_ACCESS, %g2
-       stxa    %g3, [%g2] ASI_IMMU
-       stxa    %g3, [%g2] ASI_DMMU
-       membar  #Sync
-
        BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup)
 
        ba,pt   %xcc, spitfire_tlb_fixup
         nop
 
 cheetah_tlb_fixup:
-       set     (0 << 16) | (15 << 3), %g7
-       ldxa    [%g7] ASI_ITLB_DATA_ACCESS, %g0
-       ldxa    [%g7] ASI_ITLB_DATA_ACCESS, %g1
-       andn    %g1, (_PAGE_G), %g1
-       stxa    %g1, [%g7] ASI_ITLB_DATA_ACCESS
-       membar  #Sync
-
-       ldxa    [%g7] ASI_DTLB_DATA_ACCESS, %g0
-       ldxa    [%g7] ASI_DTLB_DATA_ACCESS, %g1
-       andn    %g1, (_PAGE_G), %g1
-       stxa    %g1, [%g7] ASI_DTLB_DATA_ACCESS
-       membar  #Sync
-
-       /* Kill instruction prefetch queues. */
-       flush   %g3
-       membar  #Sync
-
        mov     2, %g2          /* Set TLB type to cheetah+. */
        BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
 
@@ -551,21 +353,6 @@ cheetah_tlb_fixup:
         nop
 
 spitfire_tlb_fixup:
-       mov     (63 << 3), %g7
-       ldxa    [%g7] ASI_ITLB_DATA_ACCESS, %g1
-       andn    %g1, (_PAGE_G), %g1
-       stxa    %g1, [%g7] ASI_ITLB_DATA_ACCESS
-       membar  #Sync
-
-       ldxa    [%g7] ASI_DTLB_DATA_ACCESS, %g1
-       andn    %g1, (_PAGE_G), %g1
-       stxa    %g1, [%g7] ASI_DTLB_DATA_ACCESS
-       membar  #Sync
-
-       /* Kill instruction prefetch queues. */
-       flush   %g3
-       membar  #Sync
-
        /* Set TLB type to spitfire. */
        mov     0, %g2
        sethi   %hi(tlb_type), %g1
@@ -578,24 +365,6 @@ tlb_fixup_done:
        mov     %sp, %l6
        mov     %o4, %l7
 
-#if 0  /* We don't do it like this anymore, but for historical hack value
-        * I leave this snippet here to show how crazy we can be sometimes. 8-)
-        */
-
-       /* Setup "Linux Current Register", thanks Sun 8-) */
-       wr      %g0, 0x1, %pcr
-
-       /* Blackbird errata workaround.  See commentary in
-        * smp.c:smp_percpu_timer_interrupt() for more
-        * information.
-        */
-       ba,pt   %xcc, 99f
-        nop
-       .align  64
-99:    wr      %g6, %g0, %pic
-       rd      %pic, %g0
-#endif
-
        wr      %g0, ASI_P, %asi
        mov     1, %g1
        sllx    %g1, THREAD_SHIFT, %g1
@@ -756,12 +525,7 @@ bootup_user_stack_end:
 
 #include "ttable.S"
 #include "systbls.S"
-
-       .align  1024
-       .globl  swapper_pg_dir
-swapper_pg_dir:
-       .word   0
-
+#include "ktlb.S"
 #include "etrap.S"
 #include "rtrap.S"
 #include "winfixup.S"
@@ -776,8 +540,11 @@ swapper_pg_dir:
 prom_tba:      .xword  0
 tlb_type:      .word   0       /* Must NOT end up in BSS */
        .section        ".fixup",#alloc,#execinstr
-       .globl  __ret_efault
+
+       .globl  __ret_efault, __retl_efault
 __ret_efault:
        ret
         restore %g0, -EFAULT, %o0
-
+__retl_efault:
+       retl
+        mov    -EFAULT, %o0
diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S
new file mode 100644 (file)
index 0000000..7796b37
--- /dev/null
@@ -0,0 +1,198 @@
+/* arch/sparc64/kernel/ktlb.S: Kernel mapping TLB miss handling.
+ *
+ * Copyright (C) 1995, 1997, 2005 David S. Miller <davem@davemloft.net>
+ * Copyright (C) 1996 Eddie C. Dost        (ecd@brainaid.de)
+ * Copyright (C) 1996 Miguel de Icaza      (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1996,98,99 Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
+*/
+
+#include <linux/config.h>
+#include <asm/head.h>
+#include <asm/asi.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+       .text
+       .align          32
+
+/*
+ * On a second level vpte miss, check whether the original fault is to the OBP 
+ * range (note that this is only possible for instruction miss, data misses to
+ * obp range do not use vpte). If so, go back directly to the faulting address.
+ * This is because we want to read the tpc, otherwise we have no way of knowing
+ * the 8k aligned faulting address if we are using >8k kernel pagesize. This
+ * also ensures no vpte range addresses are dropped into tlb while obp is
+ * executing (see inherit_locked_prom_mappings() rant).
+ */
+sparc64_vpte_nucleus:
+       /* Note that kvmap below has verified that the address is
+        * in the range MODULES_VADDR --> VMALLOC_END already.  So
+        * here we need only check if it is an OBP address or not.
+        */
+       sethi           %hi(LOW_OBP_ADDRESS), %g5
+       cmp             %g4, %g5
+       blu,pn          %xcc, kern_vpte
+        mov            0x1, %g5
+       sllx            %g5, 32, %g5
+       cmp             %g4, %g5
+       blu,pn          %xcc, vpte_insn_obp
+        nop
+
+       /* These two instructions are patched by paginig_init().  */
+kern_vpte:
+       sethi           %hi(swapper_pgd_zero), %g5
+       lduw            [%g5 + %lo(swapper_pgd_zero)], %g5
+
+       /* With kernel PGD in %g5, branch back into dtlb_backend.  */
+       ba,pt           %xcc, sparc64_kpte_continue
+        andn           %g1, 0x3, %g1   /* Finish PMD offset adjustment.  */
+
+vpte_noent:
+       /* Restore previous TAG_ACCESS, %g5 is zero, and we will
+        * skip over the trap instruction so that the top level
+        * TLB miss handler will thing this %g5 value is just an
+        * invalid PTE, thus branching to full fault processing.
+        */
+       mov             TLB_SFSR, %g1
+       stxa            %g4, [%g1 + %g1] ASI_DMMU
+       done
+
+vpte_insn_obp:
+       sethi           %hi(prom_pmd_phys), %g5
+       ldx             [%g5 + %lo(prom_pmd_phys)], %g5
+
+       /* Behave as if we are at TL0.  */
+       wrpr            %g0, 1, %tl
+       rdpr            %tpc, %g4       /* Find original faulting iaddr */
+       srlx            %g4, 13, %g4    /* Throw out context bits */
+       sllx            %g4, 13, %g4    /* g4 has vpn + ctx0 now */
+
+       /* Restore previous TAG_ACCESS.  */
+       mov             TLB_SFSR, %g1
+       stxa            %g4, [%g1 + %g1] ASI_IMMU
+
+       /* Get PMD offset.  */
+       srlx            %g4, 23, %g6
+       and             %g6, 0x7ff, %g6
+       sllx            %g6, 2, %g6
+
+       /* Load PMD, is it valid?  */
+       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
+       brz,pn          %g5, longpath
+        sllx           %g5, 11, %g5
+
+       /* Get PTE offset.  */
+       srlx            %g4, 13, %g6
+       and             %g6, 0x3ff, %g6
+       sllx            %g6, 3, %g6
+
+       /* Load PTE.  */
+       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
+       brgez,pn        %g5, longpath
+        nop
+
+       /* TLB load and return from trap.  */
+       stxa            %g5, [%g0] ASI_ITLB_DATA_IN
+       retry
+
+kvmap_do_obp:
+       sethi           %hi(prom_pmd_phys), %g5
+       ldx             [%g5 + %lo(prom_pmd_phys)], %g5
+
+       /* Get PMD offset.  */
+       srlx            %g4, 23, %g6
+       and             %g6, 0x7ff, %g6
+       sllx            %g6, 2, %g6
+
+       /* Load PMD, is it valid?  */
+       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
+       brz,pn          %g5, longpath
+        sllx           %g5, 11, %g5
+
+       /* Get PTE offset.  */
+       srlx            %g4, 13, %g6
+       and             %g6, 0x3ff, %g6
+       sllx            %g6, 3, %g6
+
+       /* Load PTE.  */
+       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
+       brgez,pn        %g5, longpath
+        nop
+
+       /* TLB load and return from trap.  */
+       stxa            %g5, [%g0] ASI_DTLB_DATA_IN
+       retry
+
+/*
+ * On a first level data miss, check whether this is to the OBP range (note
+ * that such accesses can be made by prom, as well as by kernel using
+ * prom_getproperty on "address"), and if so, do not use vpte access ...
+ * rather, use information saved during inherit_prom_mappings() using 8k
+ * pagesize.
+ */
+       .align          32
+kvmap:
+       brgez,pn        %g4, kvmap_nonlinear
+        nop
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+       .globl          kvmap_linear_patch
+kvmap_linear_patch:
+#endif
+       ba,pt           %xcc, kvmap_load
+        xor            %g2, %g4, %g5
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+       sethi           %hi(swapper_pg_dir), %g5
+       or              %g5, %lo(swapper_pg_dir), %g5
+       sllx            %g4, 64 - (PGDIR_SHIFT + PGDIR_BITS), %g6
+       srlx            %g6, 64 - PAGE_SHIFT, %g6
+       andn            %g6, 0x3, %g6
+       lduw            [%g5 + %g6], %g5
+       brz,pn          %g5, longpath
+        sllx           %g4, 64 - (PMD_SHIFT + PMD_BITS), %g6
+       srlx            %g6, 64 - PAGE_SHIFT, %g6
+       sllx            %g5, 11, %g5
+       andn            %g6, 0x3, %g6
+       lduwa           [%g5 + %g6] ASI_PHYS_USE_EC, %g5
+       brz,pn          %g5, longpath
+        sllx           %g4, 64 - PMD_SHIFT, %g6
+       srlx            %g6, 64 - PAGE_SHIFT, %g6
+       sllx            %g5, 11, %g5
+       andn            %g6, 0x7, %g6
+       ldxa            [%g5 + %g6] ASI_PHYS_USE_EC, %g5
+       brz,pn          %g5, longpath
+        nop
+       ba,a,pt         %xcc, kvmap_load
+#endif
+
+kvmap_nonlinear:
+       sethi           %hi(MODULES_VADDR), %g5
+       cmp             %g4, %g5
+       blu,pn          %xcc, longpath
+        mov            (VMALLOC_END >> 24), %g5
+       sllx            %g5, 24, %g5
+       cmp             %g4, %g5
+       bgeu,pn         %xcc, longpath
+        nop
+
+kvmap_check_obp:
+       sethi           %hi(LOW_OBP_ADDRESS), %g5
+       cmp             %g4, %g5
+       blu,pn          %xcc, kvmap_vmalloc_addr
+        mov            0x1, %g5
+       sllx            %g5, 32, %g5
+       cmp             %g4, %g5
+       blu,pn          %xcc, kvmap_do_obp
+        nop
+
+kvmap_vmalloc_addr:
+       /* If we get here, a vmalloc addr was accessed, load kernel VPTE.  */
+       ldxa            [%g3 + %g6] ASI_N, %g5
+       brgez,pn        %g5, longpath
+        nop
+
+kvmap_load:
+       /* PTE is valid, load into TLB and return from trap.  */
+       stxa            %g5, [%g0] ASI_DTLB_DATA_IN     ! Reload TLB
+       retry
index 331382e1a75d40d80680206b31b1c3eb26f129d3..cae5b61fe2f0ed76e9afbad05121fb08605c15e7 100644 (file)
@@ -330,7 +330,7 @@ static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
 static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)
 {
        unsigned long sync_reg = (unsigned long) _arg2;
-       u64 mask = 1 << (__irq_ino(__irq(bucket)) & IMAP_INO);
+       u64 mask = 1UL << (__irq_ino(__irq(bucket)) & IMAP_INO);
        u64 val;
        int limit;
 
index 5efbff90d66862054ce827bb3c327bd636d280bc..774ecbb8a0319061c909c9ad72b39d32b11a2737 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/visasm.h>
 #include <asm/spitfire.h>
 #include <asm/page.h>
+#include <asm/cpudata.h>
 
 /* Returning from ptrace is a bit tricky because the syscall return
  * low level code assumes any value returned which is negative and
@@ -132,12 +133,16 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
        if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
                unsigned long start = __pa(kaddr);
                unsigned long end = start + len;
+               unsigned long dcache_line_size;
+
+               dcache_line_size = local_cpu_data().dcache_line_size;
 
                if (tlb_type == spitfire) {
-                       for (; start < end; start += 32)
+                       for (; start < end; start += dcache_line_size)
                                spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
                } else {
-                       for (; start < end; start += 32)
+                       start &= ~(dcache_line_size - 1);
+                       for (; start < end; start += dcache_line_size)
                                __asm__ __volatile__(
                                        "stxa %%g0, [%0] %1\n\t"
                                        "membar #Sync"
@@ -150,8 +155,11 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
        if (write && tlb_type == spitfire) {
                unsigned long start = (unsigned long) kaddr;
                unsigned long end = start + len;
+               unsigned long icache_line_size;
+
+               icache_line_size = local_cpu_data().icache_line_size;
 
-               for (; start < end; start += 32)
+               for (; start < end; start += icache_line_size)
                        flushi(start);
        }
 }
index ddbed3341a232770b7c929291fc4f959862d9a17..4c9c8f2417489c6ac7874c5b8b77581b43850bd3 100644 (file)
@@ -464,8 +464,6 @@ static void __init boot_flags_init(char *commands)
        }
 }
 
-extern int prom_probe_memory(void);
-extern unsigned long start, end;
 extern void panic_setup(char *, int *);
 
 extern unsigned short root_flags;
@@ -492,13 +490,8 @@ void register_prom_callbacks(void)
                   "' linux-.soft2 to .soft2");
 }
 
-extern void paging_init(void);
-
 void __init setup_arch(char **cmdline_p)
 {
-       unsigned long highest_paddr;
-       int i;
-
        /* Initialize PROM console and command line. */
        *cmdline_p = prom_getbootargs();
        strcpy(saved_command_line, *cmdline_p);
@@ -517,40 +510,6 @@ void __init setup_arch(char **cmdline_p)
        boot_flags_init(*cmdline_p);
 
        idprom_init();
-       (void) prom_probe_memory();
-
-       /* In paging_init() we tip off this value to see if we need
-        * to change init_mm.pgd to point to the real alias mapping.
-        */
-       phys_base = 0xffffffffffffffffUL;
-       highest_paddr = 0UL;
-       for (i = 0; sp_banks[i].num_bytes != 0; i++) {
-               unsigned long top;
-
-               if (sp_banks[i].base_addr < phys_base)
-                       phys_base = sp_banks[i].base_addr;
-               top = sp_banks[i].base_addr +
-                       sp_banks[i].num_bytes;
-               if (highest_paddr < top)
-                       highest_paddr = top;
-       }
-       pfn_base = phys_base >> PAGE_SHIFT;
-
-       switch (tlb_type) {
-       default:
-       case spitfire:
-               kern_base = spitfire_get_itlb_data(sparc64_highest_locked_tlbent());
-               kern_base &= _PAGE_PADDR_SF;
-               break;
-
-       case cheetah:
-       case cheetah_plus:
-               kern_base = cheetah_get_litlb_data(sparc64_highest_locked_tlbent());
-               kern_base &= _PAGE_PADDR;
-               break;
-       };
-
-       kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
 
        if (!root_flags)
                root_mountflags &= ~MS_RDONLY;
@@ -625,6 +584,9 @@ extern void smp_info(struct seq_file *);
 extern void smp_bogo(struct seq_file *);
 extern void mmu_info(struct seq_file *);
 
+unsigned int dcache_parity_tl1_occurred;
+unsigned int icache_parity_tl1_occurred;
+
 static int show_cpuinfo(struct seq_file *m, void *__unused)
 {
        seq_printf(m, 
@@ -635,6 +597,8 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
                   "type\t\t: sun4u\n"
                   "ncpus probed\t: %ld\n"
                   "ncpus active\t: %ld\n"
+                  "D$ parity tl1\t: %u\n"
+                  "I$ parity tl1\t: %u\n"
 #ifndef CONFIG_SMP
                   "Cpu0Bogo\t: %lu.%02lu\n"
                   "Cpu0ClkTck\t: %016lx\n"
@@ -647,7 +611,9 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
                   (prom_prev >> 8) & 0xff,
                   prom_prev & 0xff,
                   (long)num_possible_cpus(),
-                  (long)num_online_cpus()
+                  (long)num_online_cpus(),
+                  dcache_parity_tl1_occurred,
+                  icache_parity_tl1_occurred
 #ifndef CONFIG_SMP
                   , cpu_data(0).udelay_val/(500000/HZ),
                   (cpu_data(0).udelay_val/(5000/HZ)) % 100,
index b4fc6a5462b2192065052a1693d194e375066910..590df5a16f5a2d11a56c138b3e8e43d2017f9dd9 100644 (file)
@@ -93,6 +93,27 @@ void __init smp_store_cpu_info(int id)
        cpu_data(id).pte_cache[1]               = NULL;
        cpu_data(id).pgd_cache                  = NULL;
        cpu_data(id).idle_volume                = 1;
+
+       cpu_data(id).dcache_size = prom_getintdefault(cpu_node, "dcache-size",
+                                                     16 * 1024);
+       cpu_data(id).dcache_line_size =
+               prom_getintdefault(cpu_node, "dcache-line-size", 32);
+       cpu_data(id).icache_size = prom_getintdefault(cpu_node, "icache-size",
+                                                     16 * 1024);
+       cpu_data(id).icache_line_size =
+               prom_getintdefault(cpu_node, "icache-line-size", 32);
+       cpu_data(id).ecache_size = prom_getintdefault(cpu_node, "ecache-size",
+                                                     4 * 1024 * 1024);
+       cpu_data(id).ecache_line_size =
+               prom_getintdefault(cpu_node, "ecache-line-size", 64);
+       printk("CPU[%d]: Caches "
+              "D[sz(%d):line_sz(%d)] "
+              "I[sz(%d):line_sz(%d)] "
+              "E[sz(%d):line_sz(%d)]\n",
+              id,
+              cpu_data(id).dcache_size, cpu_data(id).dcache_line_size,
+              cpu_data(id).icache_size, cpu_data(id).icache_line_size,
+              cpu_data(id).ecache_size, cpu_data(id).ecache_line_size);
 }
 
 static void smp_setup_percpu_timer(void);
index 5f9e4fae612efbb2814801386e68484d67de0dd5..9cd272ac3ac10342de0e8ff4f5e0e4c45a860013 100644 (file)
@@ -157,173 +157,199 @@ sys32_socketcall:       /* %o0=call, %o1=args */
        or              %g2, %lo(__socketcall_table_begin), %g2
        jmpl            %g2 + %o0, %g0
         nop
+do_einval:
+       retl
+        mov            -EINVAL, %o0
 
-       /* Each entry is exactly 32 bytes. */
        .align          32
 __socketcall_table_begin:
+
+       /* Each entry is exactly 32 bytes. */
 do_sys_socket: /* sys_socket(int, int, int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+1:     ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_socket), %g1
-       ldswa           [%o1 + 0x8] %asi, %o2
+2:     ldswa           [%o1 + 0x8] %asi, %o2
        jmpl            %g1 + %lo(sys_socket), %g0
-        ldswa          [%o1 + 0x4] %asi, %o1
+3:      ldswa          [%o1 + 0x4] %asi, %o1
        nop
        nop
        nop
 do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+4:     ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_bind), %g1
-       ldswa           [%o1 + 0x8] %asi, %o2
+5:     ldswa           [%o1 + 0x8] %asi, %o2
        jmpl            %g1 + %lo(sys_bind), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+6:      lduwa          [%o1 + 0x4] %asi, %o1
        nop
        nop
        nop
 do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+7:     ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_connect), %g1
-       ldswa           [%o1 + 0x8] %asi, %o2
+8:     ldswa           [%o1 + 0x8] %asi, %o2
        jmpl            %g1 + %lo(sys_connect), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+9:      lduwa          [%o1 + 0x4] %asi, %o1
        nop
        nop
        nop
 do_sys_listen: /* sys_listen(int, int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+10:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_listen), %g1
        jmpl            %g1 + %lo(sys_listen), %g0
-        ldswa          [%o1 + 0x4] %asi, %o1
+11:     ldswa          [%o1 + 0x4] %asi, %o1
        nop
        nop
        nop
        nop
 do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+12:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_accept), %g1
-       lduwa           [%o1 + 0x8] %asi, %o2
+13:    lduwa           [%o1 + 0x8] %asi, %o2
        jmpl            %g1 + %lo(sys_accept), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+14:     lduwa          [%o1 + 0x4] %asi, %o1
        nop
        nop
        nop
 do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+15:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_getsockname), %g1
-       lduwa           [%o1 + 0x8] %asi, %o2
+16:    lduwa           [%o1 + 0x8] %asi, %o2
        jmpl            %g1 + %lo(sys_getsockname), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+17:     lduwa          [%o1 + 0x4] %asi, %o1
        nop
        nop
        nop
 do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+18:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_getpeername), %g1
-       lduwa           [%o1 + 0x8] %asi, %o2
+19:    lduwa           [%o1 + 0x8] %asi, %o2
        jmpl            %g1 + %lo(sys_getpeername), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+20:     lduwa          [%o1 + 0x4] %asi, %o1
        nop
        nop
        nop
 do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+21:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_socketpair), %g1
-       ldswa           [%o1 + 0x8] %asi, %o2
-       lduwa           [%o1 + 0xc] %asi, %o3
+22:    ldswa           [%o1 + 0x8] %asi, %o2
+23:    lduwa           [%o1 + 0xc] %asi, %o3
        jmpl            %g1 + %lo(sys_socketpair), %g0
-        ldswa          [%o1 + 0x4] %asi, %o1
+24:     ldswa          [%o1 + 0x4] %asi, %o1
        nop
        nop
 do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+25:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_send), %g1
-       lduwa           [%o1 + 0x8] %asi, %o2
-       lduwa           [%o1 + 0xc] %asi, %o3
+26:    lduwa           [%o1 + 0x8] %asi, %o2
+27:    lduwa           [%o1 + 0xc] %asi, %o3
        jmpl            %g1 + %lo(sys_send), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+28:     lduwa          [%o1 + 0x4] %asi, %o1
        nop
        nop
 do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+29:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_recv), %g1
-       lduwa           [%o1 + 0x8] %asi, %o2
-       lduwa           [%o1 + 0xc] %asi, %o3
+30:    lduwa           [%o1 + 0x8] %asi, %o2
+31:    lduwa           [%o1 + 0xc] %asi, %o3
        jmpl            %g1 + %lo(sys_recv), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+32:     lduwa          [%o1 + 0x4] %asi, %o1
        nop
        nop
 do_sys_sendto: /* sys_sendto(int, u32, compat_size_t, unsigned int, u32, int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+33:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_sendto), %g1
-       lduwa           [%o1 + 0x8] %asi, %o2
-       lduwa           [%o1 + 0xc] %asi, %o3
-       lduwa           [%o1 + 0x10] %asi, %o4
-       ldswa           [%o1 + 0x14] %asi, %o5
+34:    lduwa           [%o1 + 0x8] %asi, %o2
+35:    lduwa           [%o1 + 0xc] %asi, %o3
+36:    lduwa           [%o1 + 0x10] %asi, %o4
+37:    ldswa           [%o1 + 0x14] %asi, %o5
        jmpl            %g1 + %lo(sys_sendto), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+38:     lduwa          [%o1 + 0x4] %asi, %o1
 do_sys_recvfrom: /* sys_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+39:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_recvfrom), %g1
-       lduwa           [%o1 + 0x8] %asi, %o2
-       lduwa           [%o1 + 0xc] %asi, %o3
-       lduwa           [%o1 + 0x10] %asi, %o4
-       lduwa           [%o1 + 0x14] %asi, %o5
+40:    lduwa           [%o1 + 0x8] %asi, %o2
+41:    lduwa           [%o1 + 0xc] %asi, %o3
+42:    lduwa           [%o1 + 0x10] %asi, %o4
+43:    lduwa           [%o1 + 0x14] %asi, %o5
        jmpl            %g1 + %lo(sys_recvfrom), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+44:     lduwa          [%o1 + 0x4] %asi, %o1
 do_sys_shutdown: /* sys_shutdown(int, int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+45:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(sys_shutdown), %g1
        jmpl            %g1 + %lo(sys_shutdown), %g0
-        ldswa          [%o1 + 0x4] %asi, %o1
+46:     ldswa          [%o1 + 0x4] %asi, %o1
        nop
        nop
        nop
        nop
 do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+47:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(compat_sys_setsockopt), %g1
-       ldswa           [%o1 + 0x8] %asi, %o2
-       lduwa           [%o1 + 0xc] %asi, %o3
-       ldswa           [%o1 + 0x10] %asi, %o4
+48:    ldswa           [%o1 + 0x8] %asi, %o2
+49:    lduwa           [%o1 + 0xc] %asi, %o3
+50:    ldswa           [%o1 + 0x10] %asi, %o4
        jmpl            %g1 + %lo(compat_sys_setsockopt), %g0
-        ldswa          [%o1 + 0x4] %asi, %o1
+51:     ldswa          [%o1 + 0x4] %asi, %o1
        nop
 do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+52:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(compat_sys_getsockopt), %g1
-       ldswa           [%o1 + 0x8] %asi, %o2
-       lduwa           [%o1 + 0xc] %asi, %o3
-       lduwa           [%o1 + 0x10] %asi, %o4
+53:    ldswa           [%o1 + 0x8] %asi, %o2
+54:    lduwa           [%o1 + 0xc] %asi, %o3
+55:    lduwa           [%o1 + 0x10] %asi, %o4
        jmpl            %g1 + %lo(compat_sys_getsockopt), %g0
-        ldswa          [%o1 + 0x4] %asi, %o1
+56:     ldswa          [%o1 + 0x4] %asi, %o1
        nop
 do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+57:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(compat_sys_sendmsg), %g1
-       lduwa           [%o1 + 0x8] %asi, %o2
+58:    lduwa           [%o1 + 0x8] %asi, %o2
        jmpl            %g1 + %lo(compat_sys_sendmsg), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+59:     lduwa          [%o1 + 0x4] %asi, %o1
        nop
        nop
        nop
 do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */
-       ldswa           [%o1 + 0x0] %asi, %o0
+60:    ldswa           [%o1 + 0x0] %asi, %o0
        sethi           %hi(compat_sys_recvmsg), %g1
-       lduwa           [%o1 + 0x8] %asi, %o2
+61:    lduwa           [%o1 + 0x8] %asi, %o2
        jmpl            %g1 + %lo(compat_sys_recvmsg), %g0
-        lduwa          [%o1 + 0x4] %asi, %o1
+62:     lduwa          [%o1 + 0x4] %asi, %o1
        nop
        nop
        nop
-__socketcall_table_end:
-
-do_einval:
-       retl
-        mov            -EINVAL, %o0
-do_efault:
-       retl
-        mov            -EFAULT, %o0
 
        .section        __ex_table
        .align          4
-       .word           __socketcall_table_begin, 0, __socketcall_table_end, do_efault
+       .word           1b, __retl_efault, 2b, __retl_efault
+       .word           3b, __retl_efault, 4b, __retl_efault
+       .word           5b, __retl_efault, 6b, __retl_efault
+       .word           7b, __retl_efault, 8b, __retl_efault
+       .word           9b, __retl_efault, 10b, __retl_efault
+       .word           11b, __retl_efault, 12b, __retl_efault
+       .word           13b, __retl_efault, 14b, __retl_efault
+       .word           15b, __retl_efault, 16b, __retl_efault
+       .word           17b, __retl_efault, 18b, __retl_efault
+       .word           19b, __retl_efault, 20b, __retl_efault
+       .word           21b, __retl_efault, 22b, __retl_efault
+       .word           23b, __retl_efault, 24b, __retl_efault
+       .word           25b, __retl_efault, 26b, __retl_efault
+       .word           27b, __retl_efault, 28b, __retl_efault
+       .word           29b, __retl_efault, 30b, __retl_efault
+       .word           31b, __retl_efault, 32b, __retl_efault
+       .word           33b, __retl_efault, 34b, __retl_efault
+       .word           35b, __retl_efault, 36b, __retl_efault
+       .word           37b, __retl_efault, 38b, __retl_efault
+       .word           39b, __retl_efault, 40b, __retl_efault
+       .word           41b, __retl_efault, 42b, __retl_efault
+       .word           43b, __retl_efault, 44b, __retl_efault
+       .word           45b, __retl_efault, 46b, __retl_efault
+       .word           47b, __retl_efault, 48b, __retl_efault
+       .word           49b, __retl_efault, 50b, __retl_efault
+       .word           51b, __retl_efault, 52b, __retl_efault
+       .word           53b, __retl_efault, 54b, __retl_efault
+       .word           55b, __retl_efault, 56b, __retl_efault
+       .word           57b, __retl_efault, 58b, __retl_efault
+       .word           59b, __retl_efault, 60b, __retl_efault
+       .word           61b, __retl_efault, 62b, __retl_efault
        .previous
index 3a145fc39cf2d4b4b619bbb1038e50bd383f2bd1..89f2fcfcd662e1b6773fca85030dcfe1cb547caf 100644 (file)
@@ -119,8 +119,8 @@ startup_continue:
        sethi           %hi(itlb_load), %g2
        or              %g2, %lo(itlb_load), %g2
        stx             %g2, [%sp + 2047 + 128 + 0x18]
-       sethi           %hi(mmu_ihandle_cache), %g2
-       lduw            [%g2 + %lo(mmu_ihandle_cache)], %g2
+       sethi           %hi(prom_mmu_ihandle_cache), %g2
+       lduw            [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
        stx             %g2, [%sp + 2047 + 128 + 0x20]
        sethi           %hi(KERNBASE), %g2
        stx             %g2, [%sp + 2047 + 128 + 0x28]
@@ -156,8 +156,8 @@ startup_continue:
        sethi           %hi(itlb_load), %g2
        or              %g2, %lo(itlb_load), %g2
        stx             %g2, [%sp + 2047 + 128 + 0x18]
-       sethi           %hi(mmu_ihandle_cache), %g2
-       lduw            [%g2 + %lo(mmu_ihandle_cache)], %g2
+       sethi           %hi(prom_mmu_ihandle_cache), %g2
+       lduw            [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
        stx             %g2, [%sp + 2047 + 128 + 0x20]
        sethi           %hi(KERNBASE + 0x400000), %g2
        stx             %g2, [%sp + 2047 + 128 + 0x28]
@@ -190,8 +190,8 @@ do_dtlb:
        sethi           %hi(dtlb_load), %g2
        or              %g2, %lo(dtlb_load), %g2
        stx             %g2, [%sp + 2047 + 128 + 0x18]
-       sethi           %hi(mmu_ihandle_cache), %g2
-       lduw            [%g2 + %lo(mmu_ihandle_cache)], %g2
+       sethi           %hi(prom_mmu_ihandle_cache), %g2
+       lduw            [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
        stx             %g2, [%sp + 2047 + 128 + 0x20]
        sethi           %hi(KERNBASE), %g2
        stx             %g2, [%sp + 2047 + 128 + 0x28]
@@ -228,8 +228,8 @@ do_dtlb:
        sethi           %hi(dtlb_load), %g2
        or              %g2, %lo(dtlb_load), %g2
        stx             %g2, [%sp + 2047 + 128 + 0x18]
-       sethi           %hi(mmu_ihandle_cache), %g2
-       lduw            [%g2 + %lo(mmu_ihandle_cache)], %g2
+       sethi           %hi(prom_mmu_ihandle_cache), %g2
+       lduw            [%g2 + %lo(prom_mmu_ihandle_cache)], %g2
        stx             %g2, [%sp + 2047 + 128 + 0x20]
        sethi           %hi(KERNBASE + 0x400000), %g2
        stx             %g2, [%sp + 2047 + 128 + 0x28]
index b280b2ef674f4a80b57cfaf36dec0140be727a66..5570e7bb22bb5a34db2bc7c1fd06feeda2ffdb9f 100644 (file)
@@ -189,19 +189,18 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un
 
        if (regs->tstate & TSTATE_PRIV) {
                /* Test if this comes from uaccess places. */
-               unsigned long fixup;
-               unsigned long g2 = regs->u_regs[UREG_G2];
+               const struct exception_table_entry *entry;
 
-               if ((fixup = search_extables_range(regs->tpc, &g2))) {
-                       /* Ouch, somebody is trying ugly VM hole tricks on us... */
+               entry = search_exception_tables(regs->tpc);
+               if (entry) {
+                       /* Ouch, somebody is trying VM hole tricks on us... */
 #ifdef DEBUG_EXCEPTIONS
                        printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
-                       printk("EX_TABLE: insn<%016lx> fixup<%016lx> "
-                              "g2<%016lx>\n", regs->tpc, fixup, g2);
+                       printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n",
+                              regs->tpc, entry->fixup);
 #endif
-                       regs->tpc = fixup;
+                       regs->tpc = entry->fixup;
                        regs->tnpc = regs->tpc + 4;
-                       regs->u_regs[UREG_G2] = g2;
                        return;
                }
                /* Shit... */
@@ -758,26 +757,12 @@ void __init cheetah_ecache_flush_init(void)
        ecache_flush_size = (2 * largest_size);
        ecache_flush_linesize = smallest_linesize;
 
-       /* Discover a physically contiguous chunk of physical
-        * memory in 'sp_banks' of size ecache_flush_size calculated
-        * above.  Store the physical base of this area at
-        * ecache_flush_physbase.
-        */
-       for (node = 0; ; node++) {
-               if (sp_banks[node].num_bytes == 0)
-                       break;
-               if (sp_banks[node].num_bytes >= ecache_flush_size) {
-                       ecache_flush_physbase = sp_banks[node].base_addr;
-                       break;
-               }
-       }
+       ecache_flush_physbase = find_ecache_flush_span(ecache_flush_size);
 
-       /* Note: Zero would be a valid value of ecache_flush_physbase so
-        * don't use that as the success test. :-)
-        */
-       if (sp_banks[node].num_bytes == 0) {
+       if (ecache_flush_physbase == ~0UL) {
                prom_printf("cheetah_ecache_flush_init: Cannot find %d byte "
-                           "contiguous physical memory.\n", ecache_flush_size);
+                           "contiguous physical memory.\n",
+                           ecache_flush_size);
                prom_halt();
        }
 
@@ -869,14 +854,19 @@ static void cheetah_flush_ecache_line(unsigned long physaddr)
  */
 static void __cheetah_flush_icache(void)
 {
-       unsigned long i;
+       unsigned int icache_size, icache_line_size;
+       unsigned long addr;
+
+       icache_size = local_cpu_data().icache_size;
+       icache_line_size = local_cpu_data().icache_line_size;
 
        /* Clear the valid bits in all the tags. */
-       for (i = 0; i < (1 << 15); i += (1 << 5)) {
+       for (addr = 0; addr < icache_size; addr += icache_line_size) {
                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
                                     "membar #Sync"
                                     : /* no outputs */
-                                    : "r" (i | (2 << 3)), "i" (ASI_IC_TAG));
+                                    : "r" (addr | (2 << 3)),
+                                      "i" (ASI_IC_TAG));
        }
 }
 
@@ -904,13 +894,17 @@ static void cheetah_flush_icache(void)
 
 static void cheetah_flush_dcache(void)
 {
-       unsigned long i;
+       unsigned int dcache_size, dcache_line_size;
+       unsigned long addr;
 
-       for (i = 0; i < (1 << 16); i += (1 << 5)) {
+       dcache_size = local_cpu_data().dcache_size;
+       dcache_line_size = local_cpu_data().dcache_line_size;
+
+       for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
                __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
                                     "membar #Sync"
                                     : /* no outputs */
-                                    : "r" (i), "i" (ASI_DCACHE_TAG));
+                                    : "r" (addr), "i" (ASI_DCACHE_TAG));
        }
 }
 
@@ -921,24 +915,29 @@ static void cheetah_flush_dcache(void)
  */
 static void cheetah_plus_zap_dcache_parity(void)
 {
-       unsigned long i;
+       unsigned int dcache_size, dcache_line_size;
+       unsigned long addr;
+
+       dcache_size = local_cpu_data().dcache_size;
+       dcache_line_size = local_cpu_data().dcache_line_size;
 
-       for (i = 0; i < (1 << 16); i += (1 << 5)) {
-               unsigned long tag = (i >> 14);
-               unsigned long j;
+       for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
+               unsigned long tag = (addr >> 14);
+               unsigned long line;
 
                __asm__ __volatile__("membar    #Sync\n\t"
                                     "stxa      %0, [%1] %2\n\t"
                                     "membar    #Sync"
                                     : /* no outputs */
-                                    : "r" (tag), "r" (i),
+                                    : "r" (tag), "r" (addr),
                                       "i" (ASI_DCACHE_UTAG));
-               for (j = i; j < i + (1 << 5); j += (1 << 3))
+               for (line = addr; line < addr + dcache_line_size; line += 8)
                        __asm__ __volatile__("membar    #Sync\n\t"
                                             "stxa      %%g0, [%0] %1\n\t"
                                             "membar    #Sync"
                                             : /* no outputs */
-                                            : "r" (j), "i" (ASI_DCACHE_DATA));
+                                            : "r" (line),
+                                              "i" (ASI_DCACHE_DATA));
        }
 }
 
@@ -1332,16 +1331,12 @@ static int cheetah_fix_ce(unsigned long physaddr)
 /* Return non-zero if PADDR is a valid physical memory address. */
 static int cheetah_check_main_memory(unsigned long paddr)
 {
-       int i;
+       unsigned long vaddr = PAGE_OFFSET + paddr;
 
-       for (i = 0; ; i++) {
-               if (sp_banks[i].num_bytes == 0)
-                       break;
-               if (paddr >= sp_banks[i].base_addr &&
-                   paddr < (sp_banks[i].base_addr + sp_banks[i].num_bytes))
-                       return 1;
-       }
-       return 0;
+       if (vaddr > (unsigned long) high_memory)
+               return 0;
+
+       return kern_addr_valid(vaddr);
 }
 
 void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
@@ -1596,10 +1591,10 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
                        /* OK, usermode access. */
                        recoverable = 1;
                } else {
-                       unsigned long g2 = regs->u_regs[UREG_G2];
-                       unsigned long fixup = search_extables_range(regs->tpc, &g2);
+                       const struct exception_table_entry *entry;
 
-                       if (fixup != 0UL) {
+                       entry = search_exception_tables(regs->tpc);
+                       if (entry) {
                                /* OK, kernel access to userspace. */
                                recoverable = 1;
 
@@ -1618,9 +1613,8 @@ void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned
                                 * recoverable condition.
                                 */
                                if (recoverable) {
-                                       regs->tpc = fixup;
+                                       regs->tpc = entry->fixup;
                                        regs->tnpc = regs->tpc + 4;
-                                       regs->u_regs[UREG_G2] = g2;
                                }
                        }
                }
index da48400bcc95a8b43a7dcef27f63e62998b0489f..1f5b5b708ce7210fd36e0abaa28362dfa8518a0a 100644 (file)
@@ -6,13 +6,6 @@
 
        .text
 
-kernel_unaligned_trap_fault:
-       call    kernel_mna_trap_fault
-        nop
-       retl
-        nop
-       .size   kern_unaligned_trap_fault, .-kern_unaligned_trap_fault
-
        .globl  __do_int_store
 __do_int_store:
        rd      %asi, %o4
@@ -51,24 +44,24 @@ __do_int_store:
 0:
        wr      %o4, 0x0, %asi
        retl
-        nop
+        mov    0, %o0
        .size   __do_int_store, .-__do_int_store
 
        .section        __ex_table
-       .word           4b, kernel_unaligned_trap_fault
-       .word           5b, kernel_unaligned_trap_fault
-       .word           6b, kernel_unaligned_trap_fault
-       .word           7b, kernel_unaligned_trap_fault
-       .word           8b, kernel_unaligned_trap_fault
-       .word           9b, kernel_unaligned_trap_fault
-       .word           10b, kernel_unaligned_trap_fault
-       .word           11b, kernel_unaligned_trap_fault
-       .word           12b, kernel_unaligned_trap_fault
-       .word           13b, kernel_unaligned_trap_fault
-       .word           14b, kernel_unaligned_trap_fault
-       .word           15b, kernel_unaligned_trap_fault
-       .word           16b, kernel_unaligned_trap_fault
-       .word           17b, kernel_unaligned_trap_fault
+       .word           4b, __retl_efault
+       .word           5b, __retl_efault
+       .word           6b, __retl_efault
+       .word           7b, __retl_efault
+       .word           8b, __retl_efault
+       .word           9b, __retl_efault
+       .word           10b, __retl_efault
+       .word           11b, __retl_efault
+       .word           12b, __retl_efault
+       .word           13b, __retl_efault
+       .word           14b, __retl_efault
+       .word           15b, __retl_efault
+       .word           16b, __retl_efault
+       .word           17b, __retl_efault
        .previous
 
        .globl  do_int_load
@@ -133,21 +126,21 @@ do_int_load:
 0:
        wr      %o5, 0x0, %asi
        retl
-        nop
+        mov    0, %o0
        .size   __do_int_load, .-__do_int_load
 
        .section        __ex_table
-       .word           4b, kernel_unaligned_trap_fault
-       .word           5b, kernel_unaligned_trap_fault
-       .word           6b, kernel_unaligned_trap_fault
-       .word           7b, kernel_unaligned_trap_fault
-       .word           8b, kernel_unaligned_trap_fault
-       .word           9b, kernel_unaligned_trap_fault
-       .word           10b, kernel_unaligned_trap_fault
-       .word           11b, kernel_unaligned_trap_fault
-       .word           12b, kernel_unaligned_trap_fault
-       .word           13b, kernel_unaligned_trap_fault
-       .word           14b, kernel_unaligned_trap_fault
-       .word           15b, kernel_unaligned_trap_fault
-       .word           16b, kernel_unaligned_trap_fault
+       .word           4b, __retl_efault
+       .word           5b, __retl_efault
+       .word           6b, __retl_efault
+       .word           7b, __retl_efault
+       .word           8b, __retl_efault
+       .word           9b, __retl_efault
+       .word           10b, __retl_efault
+       .word           11b, __retl_efault
+       .word           12b, __retl_efault
+       .word           13b, __retl_efault
+       .word           14b, __retl_efault
+       .word           15b, __retl_efault
+       .word           16b, __retl_efault
        .previous
index 42718f6a7d3671ea349c3918f2355c11809c272c..70faf630603bc49a34a2cba0bfe4733092aedd36 100644 (file)
@@ -180,14 +180,14 @@ static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs)
        die_if_kernel(str, regs);
 }
 
-extern void do_int_load(unsigned long *dest_reg, int size,
-                       unsigned long *saddr, int is_signed, int asi);
+extern int do_int_load(unsigned long *dest_reg, int size,
+                      unsigned long *saddr, int is_signed, int asi);
        
-extern void __do_int_store(unsigned long *dst_addr, int size,
-                          unsigned long src_val, int asi);
+extern int __do_int_store(unsigned long *dst_addr, int size,
+                         unsigned long src_val, int asi);
 
-static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
-                               struct pt_regs *regs, int asi, int orig_asi)
+static inline int do_int_store(int reg_num, int size, unsigned long *dst_addr,
+                              struct pt_regs *regs, int asi, int orig_asi)
 {
        unsigned long zero = 0;
        unsigned long *src_val_p = &zero;
@@ -219,7 +219,7 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr,
                        break;
                };
        }
-       __do_int_store(dst_addr, size, src_val, asi);
+       return __do_int_store(dst_addr, size, src_val, asi);
 }
 
 static inline void advance(struct pt_regs *regs)
@@ -242,14 +242,14 @@ static inline int ok_for_kernel(unsigned int insn)
        return !floating_point_load_or_store_p(insn);
 }
 
-void kernel_mna_trap_fault(void)
+static void kernel_mna_trap_fault(void)
 {
        struct pt_regs *regs = current_thread_info()->kern_una_regs;
        unsigned int insn = current_thread_info()->kern_una_insn;
-       unsigned long g2 = regs->u_regs[UREG_G2];
-       unsigned long fixup = search_extables_range(regs->tpc, &g2);
+       const struct exception_table_entry *entry;
 
-       if (!fixup) {
+       entry = search_exception_tables(regs->tpc);
+       if (!entry) {
                unsigned long address;
 
                address = compute_effective_address(regs, insn,
@@ -270,9 +270,8 @@ void kernel_mna_trap_fault(void)
                die_if_kernel("Oops", regs);
                /* Not reached */
        }
-       regs->tpc = fixup;
+       regs->tpc = entry->fixup;
        regs->tnpc = regs->tpc + 4;
-       regs->u_regs [UREG_G2] = g2;
 
        regs->tstate &= ~TSTATE_ASI;
        regs->tstate |= (ASI_AIUS << 24UL);
@@ -294,8 +293,8 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
 
                kernel_mna_trap_fault();
        } else {
-               unsigned long addr;
-               int orig_asi, asi;
+               unsigned long addr, *reg_addr;
+               int orig_asi, asi, err;
 
                addr = compute_effective_address(regs, insn,
                                                 ((insn >> 25) & 0x1f));
@@ -319,11 +318,12 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
                };
                switch (dir) {
                case load:
-                       do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
-                                   size, (unsigned long *) addr,
-                                   decode_signedness(insn), asi);
-                       if (unlikely(asi != orig_asi)) {
-                               unsigned long val_in = *(unsigned long *) addr;
+                       reg_addr = fetch_reg_addr(((insn>>25)&0x1f), regs);
+                       err = do_int_load(reg_addr, size,
+                                         (unsigned long *) addr,
+                                         decode_signedness(insn), asi);
+                       if (likely(!err) && unlikely(asi != orig_asi)) {
+                               unsigned long val_in = *reg_addr;
                                switch (size) {
                                case 2:
                                        val_in = swab16(val_in);
@@ -339,21 +339,24 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u
                                        BUG();
                                        break;
                                };
-                               *(unsigned long *) addr = val_in;
+                               *reg_addr = val_in;
                        }
                        break;
 
                case store:
-                       do_int_store(((insn>>25)&0x1f), size,
-                                    (unsigned long *) addr, regs,
-                                    asi, orig_asi);
+                       err = do_int_store(((insn>>25)&0x1f), size,
+                                          (unsigned long *) addr, regs,
+                                          asi, orig_asi);
                        break;
 
                default:
                        panic("Impossible kernel unaligned trap.");
                        /* Not reached... */
                }
-               advance(regs);
+               if (unlikely(err))
+                       kernel_mna_trap_fault();
+               else
+                       advance(regs);
        }
 }
 
index 9080e7cd4bb0b8506ceea663c6e4e0d5a4f8a87e..0340041f614352a5cd22ddae1a946c8b1cf53e0f 100644 (file)
@@ -208,7 +208,10 @@ static int __init us3_freq_init(void)
        impl  = ((ver >> 32) & 0xffff);
 
        if (manuf == CHEETAH_MANUF &&
-           (impl == CHEETAH_IMPL || impl == CHEETAH_PLUS_IMPL)) {
+           (impl == CHEETAH_IMPL ||
+            impl == CHEETAH_PLUS_IMPL ||
+            impl == JAGUAR_IMPL ||
+            impl == PANTHER_IMPL)) {
                struct cpufreq_driver *driver;
 
                ret = -ENOMEM;
index f47d0be39378a2a7603e4470d0bb5962c1e2dc9e..2af0cf0a86409fbc288f61061ebd953c19d91950 100644 (file)
@@ -9,8 +9,7 @@ ENTRY(_start)
 jiffies = jiffies_64;
 SECTIONS
 {
-  swapper_pmd_dir = 0x0000000000402000;
-  empty_pg_dir = 0x0000000000403000;
+  swapper_low_pmd_dir = 0x0000000000402000;
   . = 0x4000;
   .text 0x0000000000404000 :
   {
index 09cbbaa0ebf4387427d4422cb69ba51b575056ec..e1264650ca7aa8cb31329227b8129c3c0abed0a0 100644 (file)
@@ -125,15 +125,11 @@ __strncpy_from_user:
         add    %o2, %o3, %o0
        .size   __strncpy_from_user, .-__strncpy_from_user
 
-       .section .fixup,#alloc,#execinstr
-       .align  4
-4:     retl
-        mov    -EFAULT, %o0
-
        .section __ex_table,#alloc
        .align  4
-       .word   60b, 4b
-       .word   61b, 4b
-       .word   62b, 4b
-       .word   63b, 4b
-       .word   64b, 4b
+       .word   60b, __retl_efault
+       .word   61b, __retl_efault
+       .word   62b, __retl_efault
+       .word   63b, __retl_efault
+       .word   64b, __retl_efault
+       .previous
index 0278e34125dbe773b38685bb3433797739b9ecf1..19d1fdb17d0e8b4f5b3ac6ce0a72fe7c11c65a6b 100644 (file)
 
 /* Calculating the exact fault address when using
  * block loads and stores can be very complicated.
+ *
  * Instead of trying to be clever and handling all
  * of the cases, just fix things up simply here.
  */
 
-unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
+static unsigned long compute_size(unsigned long start, unsigned long size, unsigned long *offset)
 {
-       char *dst = to;
-       const char __user *src = from;
+       unsigned long fault_addr = current_thread_info()->fault_address;
+       unsigned long end = start + size;
 
-       while (size) {
-               if (__get_user(*dst, src))
-                       break;
-               dst++;
-               src++;
-               size--;
+       if (fault_addr < start || fault_addr >= end) {
+               *offset = 0;
+       } else {
+               *offset = start - fault_addr;
+               size = end - fault_addr;
        }
+       return size;
+}
 
-       if (size)
-               memset(dst, 0, size);
+unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned long size)
+{
+       unsigned long offset;
+
+       size = compute_size((unsigned long) from, size, &offset);
+       if (likely(size))
+               memset(to + offset, 0, size);
 
        return size;
 }
 
 unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
 {
-       char __user *dst = to;
-       const char *src = from;
-
-       while (size) {
-               if (__put_user(*src, dst))
-                       break;
-               dst++;
-               src++;
-               size--;
-       }
+       unsigned long offset;
 
-       return size;
+       return compute_size((unsigned long) to, size, &offset);
 }
 
 unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
 {
-       char __user *dst = to;
-       char __user *src = from;
+       unsigned long fault_addr = current_thread_info()->fault_address;
+       unsigned long start = (unsigned long) to;
+       unsigned long end = start + size;
 
-       while (size) {
-               char tmp;
+       if (fault_addr >= start && fault_addr < end)
+               return end - fault_addr;
 
-               if (__get_user(tmp, src))
-                       break;
-               if (__put_user(tmp, dst))
-                       break;
-               dst++;
-               src++;
-               size--;
-       }
+       start = (unsigned long) from;
+       end = start + size;
+       if (fault_addr >= start && fault_addr < end)
+               return end - fault_addr;
 
        return size;
 }
index cda87333a77b819a2677968c7b5058982d485184..9d0960e69f487a94c0f23b53050267f56f35b1e9 100644 (file)
@@ -5,6 +5,6 @@
 EXTRA_AFLAGS := -ansi
 EXTRA_CFLAGS := -Werror
 
-obj-y    := ultra.o tlb.o fault.o init.o generic.o extable.o
+obj-y    := ultra.o tlb.o fault.o init.o generic.o
 
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c
deleted file mode 100644 (file)
index ec33429..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * linux/arch/sparc64/mm/extable.c
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <asm/uaccess.h>
-
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
-
-void sort_extable(struct exception_table_entry *start,
-                 struct exception_table_entry *finish)
-{
-}
-
-/* Caller knows they are in a range if ret->fixup == 0 */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *start,
-              const struct exception_table_entry *last,
-              unsigned long value)
-{
-       const struct exception_table_entry *walk;
-
-       /* Single insn entries are encoded as:
-        *      word 1: insn address
-        *      word 2: fixup code address
-        *
-        * Range entries are encoded as:
-        *      word 1: first insn address
-        *      word 2: 0
-        *      word 3: last insn address + 4 bytes
-        *      word 4: fixup code address
-        *
-        * See asm/uaccess.h for more details.
-        */
-
-       /* 1. Try to find an exact match. */
-       for (walk = start; walk <= last; walk++) {
-               if (walk->fixup == 0) {
-                       /* A range entry, skip both parts. */
-                       walk++;
-                       continue;
-               }
-
-               if (walk->insn == value)
-                       return walk;
-       }
-
-       /* 2. Try to find a range match. */
-       for (walk = start; walk <= (last - 1); walk++) {
-               if (walk->fixup)
-                       continue;
-
-               if (walk[0].insn <= value && walk[1].insn > value)
-                       return walk;
-
-               walk++;
-       }
-
-        return NULL;
-}
-
-/* Special extable search, which handles ranges.  Returns fixup */
-unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
-{
-       const struct exception_table_entry *entry;
-
-       entry = search_exception_tables(addr);
-       if (!entry)
-               return 0;
-
-       /* Inside range?  Fix g2 and return correct fixup */
-       if (!entry->fixup) {
-               *g2 = (addr - entry->insn) / 4;
-               return (entry + 1)->fixup;
-       }
-
-       return entry->fixup;
-}
index db1e3310e907dc2ba2f4c60a237f2c69664964ff..31fbc67719a1f653f643c346615a261173541a98 100644 (file)
@@ -32,8 +32,6 @@
 
 #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
 
-extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
-
 /*
  * To debug kernel to catch accesses to certain virtual/physical addresses.
  * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints.
@@ -71,53 +69,6 @@ void set_brkpt(unsigned long addr, unsigned char mask, int flags, int mode)
                             : "memory");
 }
 
-/* Nice, simple, prom library does all the sweating for us. ;) */
-unsigned long __init prom_probe_memory (void)
-{
-       register struct linux_mlist_p1275 *mlist;
-       register unsigned long bytes, base_paddr, tally;
-       register int i;
-
-       i = 0;
-       mlist = *prom_meminfo()->p1275_available;
-       bytes = tally = mlist->num_bytes;
-       base_paddr = mlist->start_adr;
-  
-       sp_banks[0].base_addr = base_paddr;
-       sp_banks[0].num_bytes = bytes;
-
-       while (mlist->theres_more != (void *) 0) {
-               i++;
-               mlist = mlist->theres_more;
-               bytes = mlist->num_bytes;
-               tally += bytes;
-               if (i >= SPARC_PHYS_BANKS-1) {
-                       printk ("The machine has more banks than "
-                               "this kernel can support\n"
-                               "Increase the SPARC_PHYS_BANKS "
-                               "setting (currently %d)\n",
-                               SPARC_PHYS_BANKS);
-                       i = SPARC_PHYS_BANKS-1;
-                       break;
-               }
-    
-               sp_banks[i].base_addr = mlist->start_adr;
-               sp_banks[i].num_bytes = mlist->num_bytes;
-       }
-
-       i++;
-       sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL;
-       sp_banks[i].num_bytes = 0;
-
-       /* Now mask all bank sizes on a page boundary, it is all we can
-        * use anyways.
-        */
-       for (i = 0; sp_banks[i].num_bytes != 0; i++)
-               sp_banks[i].num_bytes &= PAGE_MASK;
-
-       return tally;
-}
-
 static void __kprobes unhandled_fault(unsigned long address,
                                      struct task_struct *tsk,
                                      struct pt_regs *regs)
@@ -242,7 +193,6 @@ static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn)
 static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
                            unsigned int insn, unsigned long address)
 {
-       unsigned long g2;
        unsigned char asi = ASI_P;
  
        if ((!insn) && (regs->tstate & TSTATE_PRIV))
@@ -273,11 +223,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
                }
        }
                
-       g2 = regs->u_regs[UREG_G2];
-
        /* Is this in ex_table? */
        if (regs->tstate & TSTATE_PRIV) {
-               unsigned long fixup;
+               const struct exception_table_entry *entry;
 
                if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) {
                        if (insn & 0x2000)
@@ -288,10 +236,9 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code,
        
                /* Look in asi.h: All _S asis have LS bit set */
                if ((asi & 0x1) &&
-                   (fixup = search_extables_range(regs->tpc, &g2))) {
-                       regs->tpc = fixup;
+                   (entry = search_exception_tables(regs->tpc))) {
+                       regs->tpc = entry->fixup;
                        regs->tnpc = regs->tpc + 4;
-                       regs->u_regs[UREG_G2] = g2;
                        return;
                }
        } else {
@@ -461,7 +408,7 @@ good_area:
        }
 
        up_read(&mm->mmap_sem);
-       goto fault_done;
+       return;
 
        /*
         * Something tried to access memory that isn't in our memory map..
@@ -473,8 +420,7 @@ bad_area:
 
 handle_kernel_fault:
        do_kernel_fault(regs, si_code, fault_code, insn, address);
-
-       goto fault_done;
+       return;
 
 /*
  * We ran out of memory, or some other thing happened to us that made
@@ -505,9 +451,4 @@ do_sigbus:
        /* Kernel mode? Handle exceptions or die */
        if (regs->tstate & TSTATE_PRIV)
                goto handle_kernel_fault;
-
-fault_done:
-       /* These values are no longer needed, clear them. */
-       set_thread_fault_code(0);
-       current_thread_info()->fault_address = 0;
 }
index fdb1ebb308c95bad153283b87e8665b177e0df2d..5db50524f20de8dadf4b36f919048c8f4fac4c4e 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/kprobes.h>
+#include <linux/cache.h>
+#include <linux/sort.h>
 
 #include <asm/head.h>
 #include <asm/system.h>
 
 extern void device_scan(void);
 
-struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
+#define MAX_BANKS      32
 
-unsigned long *sparc64_valid_addr_bitmap;
+static struct linux_prom64_registers pavail[MAX_BANKS] __initdata;
+static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
+static int pavail_ents __initdata;
+static int pavail_rescan_ents __initdata;
+
+static int cmp_p64(const void *a, const void *b)
+{
+       const struct linux_prom64_registers *x = a, *y = b;
+
+       if (x->phys_addr > y->phys_addr)
+               return 1;
+       if (x->phys_addr < y->phys_addr)
+               return -1;
+       return 0;
+}
+
+static void __init read_obp_memory(const char *property,
+                                  struct linux_prom64_registers *regs,
+                                  int *num_ents)
+{
+       int node = prom_finddevice("/memory");
+       int prop_size = prom_getproplen(node, property);
+       int ents, ret, i;
+
+       ents = prop_size / sizeof(struct linux_prom64_registers);
+       if (ents > MAX_BANKS) {
+               prom_printf("The machine has more %s property entries than "
+                           "this kernel can support (%d).\n",
+                           property, MAX_BANKS);
+               prom_halt();
+       }
+
+       ret = prom_getproperty(node, property, (char *) regs, prop_size);
+       if (ret == -1) {
+               prom_printf("Couldn't get %s property from /memory.\n");
+               prom_halt();
+       }
+
+       *num_ents = ents;
+
+       /* Sanitize what we got from the firmware, by page aligning
+        * everything.
+        */
+       for (i = 0; i < ents; i++) {
+               unsigned long base, size;
+
+               base = regs[i].phys_addr;
+               size = regs[i].reg_size;
+
+               size &= PAGE_MASK;
+               if (base & ~PAGE_MASK) {
+                       unsigned long new_base = PAGE_ALIGN(base);
+
+                       size -= new_base - base;
+                       if ((long) size < 0L)
+                               size = 0UL;
+                       base = new_base;
+               }
+               regs[i].phys_addr = base;
+               regs[i].reg_size = size;
+       }
+       sort(regs, ents, sizeof(struct  linux_prom64_registers),
+            cmp_p64, NULL);
+}
+
+unsigned long *sparc64_valid_addr_bitmap __read_mostly;
 
 /* Ugly, but necessary... -DaveM */
-unsigned long phys_base;
-unsigned long kern_base;
-unsigned long kern_size;
-unsigned long pfn_base;
-
-/* This is even uglier. We have a problem where the kernel may not be
- * located at phys_base. However, initial __alloc_bootmem() calls need to
- * be adjusted to be within the 4-8Megs that the kernel is mapped to, else
- * those page mappings wont work. Things are ok after inherit_prom_mappings
- * is called though. Dave says he'll clean this up some other time.
- * -- BenC
- */
-static unsigned long bootmap_base;
+unsigned long phys_base __read_mostly;
+unsigned long kern_base __read_mostly;
+unsigned long kern_size __read_mostly;
+unsigned long pfn_base __read_mostly;
 
 /* get_new_mmu_context() uses "cache + 1".  */
 DEFINE_SPINLOCK(ctx_alloc_lock);
@@ -73,7 +131,7 @@ extern unsigned long sparc_ramdisk_image64;
 extern unsigned int sparc_ramdisk_image;
 extern unsigned int sparc_ramdisk_size;
 
-struct page *mem_map_zero;
+struct page *mem_map_zero __read_mostly;
 
 int bigkernel = 0;
 
@@ -179,8 +237,6 @@ static __inline__ void clear_dcache_dirty_cpu(struct page *page, unsigned long c
                             : "g1", "g7");
 }
 
-extern void __update_mmu_cache(unsigned long mmu_context_hw, unsigned long address, pte_t pte, int code);
-
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
        struct page *page;
@@ -207,10 +263,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p
 
                put_cpu();
        }
-
-       if (get_thread_fault_code())
-               __update_mmu_cache(CTX_NRBITS(vma->vm_mm->context),
-                                  address, pte, get_thread_fault_code());
 }
 
 void flush_dcache_page(struct page *page)
@@ -309,6 +361,7 @@ struct linux_prom_translation {
        unsigned long size;
        unsigned long data;
 };
+static struct linux_prom_translation prom_trans[512] __initdata;
 
 extern unsigned long prom_boot_page;
 extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
@@ -318,14 +371,63 @@ extern void register_prom_callbacks(void);
 /* Exported for SMP bootup purposes. */
 unsigned long kern_locked_tte_data;
 
-void __init early_pgtable_allocfail(char *type)
+/* Exported for kernel TLB miss handling in ktlb.S */
+unsigned long prom_pmd_phys __read_mostly;
+unsigned int swapper_pgd_zero __read_mostly;
+
+/* Allocate power-of-2 aligned chunks from the end of the
+ * kernel image.  Return physical address.
+ */
+static inline unsigned long early_alloc_phys(unsigned long size)
 {
-       prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type);
-       prom_halt();
+       unsigned long base;
+
+       BUILD_BUG_ON(size & (size - 1));
+
+       kern_size = (kern_size + (size - 1)) & ~(size - 1);
+       base = kern_base + kern_size;
+       kern_size += size;
+
+       return base;
+}
+
+static inline unsigned long load_phys32(unsigned long pa)
+{
+       unsigned long val;
+
+       __asm__ __volatile__("lduwa     [%1] %2, %0"
+                            : "=&r" (val)
+                            : "r" (pa), "i" (ASI_PHYS_USE_EC));
+
+       return val;
+}
+
+static inline unsigned long load_phys64(unsigned long pa)
+{
+       unsigned long val;
+
+       __asm__ __volatile__("ldxa      [%1] %2, %0"
+                            : "=&r" (val)
+                            : "r" (pa), "i" (ASI_PHYS_USE_EC));
+
+       return val;
+}
+
+static inline void store_phys32(unsigned long pa, unsigned long val)
+{
+       __asm__ __volatile__("stwa      %0, [%1] %2"
+                            : /* no outputs */
+                            : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC));
+}
+
+static inline void store_phys64(unsigned long pa, unsigned long val)
+{
+       __asm__ __volatile__("stxa      %0, [%1] %2"
+                            : /* no outputs */
+                            : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC));
 }
 
 #define BASE_PAGE_SIZE 8192
-static pmd_t *prompmd;
 
 /*
  * Translate PROM's mapping we capture at boot time into physical address.
@@ -333,278 +435,172 @@ static pmd_t *prompmd;
  */
 unsigned long prom_virt_to_phys(unsigned long promva, int *error)
 {
-       pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff);
-       pte_t *ptep;
+       unsigned long pmd_phys = (prom_pmd_phys +
+                                 ((promva >> 23) & 0x7ff) * sizeof(pmd_t));
+       unsigned long pte_phys;
+       pmd_t pmd_ent;
+       pte_t pte_ent;
        unsigned long base;
 
-       if (pmd_none(*pmdp)) {
+       pmd_val(pmd_ent) = load_phys32(pmd_phys);
+       if (pmd_none(pmd_ent)) {
                if (error)
                        *error = 1;
-               return(0);
+               return 0;
        }
-       ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff);
-       if (!pte_present(*ptep)) {
+
+       pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL;
+       pte_phys += ((promva >> 13) & 0x3ff) * sizeof(pte_t);
+       pte_val(pte_ent) = load_phys64(pte_phys);
+       if (!pte_present(pte_ent)) {
                if (error)
                        *error = 1;
-               return(0);
+               return 0;
        }
        if (error) {
                *error = 0;
-               return(pte_val(*ptep));
+               return pte_val(pte_ent);
        }
-       base = pte_val(*ptep) & _PAGE_PADDR;
-       return(base + (promva & (BASE_PAGE_SIZE - 1)));
+       base = pte_val(pte_ent) & _PAGE_PADDR;
+       return (base + (promva & (BASE_PAGE_SIZE - 1)));
 }
 
-static void inherit_prom_mappings(void)
+/* The obp translations are saved based on 8k pagesize, since obp can
+ * use a mixture of pagesizes. Misses to the LOW_OBP_ADDRESS ->
+ * HI_OBP_ADDRESS range are handled in entry.S and do not use the vpte
+ * scheme (also, see rant in inherit_locked_prom_mappings()).
+ */
+static void __init build_obp_range(unsigned long start, unsigned long end, unsigned long data)
 {
-       struct linux_prom_translation *trans;
-       unsigned long phys_page, tte_vaddr, tte_data;
-       void (*remap_func)(unsigned long, unsigned long, int);
-       pmd_t *pmdp;
-       pte_t *ptep;
-       int node, n, i, tsz;
-       extern unsigned int obp_iaddr_patch[2], obp_daddr_patch[2];
+       unsigned long vaddr;
 
-       node = prom_finddevice("/virtual-memory");
-       n = prom_getproplen(node, "translations");
-       if (n == 0 || n == -1) {
-               prom_printf("Couldn't get translation property\n");
-               prom_halt();
-       }
-       n += 5 * sizeof(struct linux_prom_translation);
-       for (tsz = 1; tsz < n; tsz <<= 1)
-               /* empty */;
-       trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, bootmap_base);
-       if (trans == NULL) {
-               prom_printf("inherit_prom_mappings: Cannot alloc translations.\n");
-               prom_halt();
-       }
-       memset(trans, 0, tsz);
+       for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) {
+               unsigned long val, pte_phys, pmd_phys;
+               pmd_t pmd_ent;
+               int i;
 
-       if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) {
-               prom_printf("Couldn't get translation property\n");
-               prom_halt();
-       }
-       n = n / sizeof(*trans);
+               pmd_phys = (prom_pmd_phys +
+                           (((vaddr >> 23) & 0x7ff) * sizeof(pmd_t)));
+               pmd_val(pmd_ent) = load_phys32(pmd_phys);
+               if (pmd_none(pmd_ent)) {
+                       pte_phys = early_alloc_phys(BASE_PAGE_SIZE);
 
-       /*
-        * The obp translations are saved based on 8k pagesize, since obp can
-        * use a mixture of pagesizes. Misses to the 0xf0000000 - 0x100000000,
-        * ie obp range, are handled in entry.S and do not use the vpte scheme
-        * (see rant in inherit_locked_prom_mappings()).
-        */
-#define OBP_PMD_SIZE 2048
-       prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, bootmap_base);
-       if (prompmd == NULL)
-               early_pgtable_allocfail("pmd");
-       memset(prompmd, 0, OBP_PMD_SIZE);
-       for (i = 0; i < n; i++) {
-               unsigned long vaddr;
-
-               if (trans[i].virt >= LOW_OBP_ADDRESS && trans[i].virt < HI_OBP_ADDRESS) {
-                       for (vaddr = trans[i].virt;
-                            ((vaddr < trans[i].virt + trans[i].size) && 
-                            (vaddr < HI_OBP_ADDRESS));
-                            vaddr += BASE_PAGE_SIZE) {
-                               unsigned long val;
-
-                               pmdp = prompmd + ((vaddr >> 23) & 0x7ff);
-                               if (pmd_none(*pmdp)) {
-                                       ptep = __alloc_bootmem(BASE_PAGE_SIZE,
-                                                              BASE_PAGE_SIZE,
-                                                              bootmap_base);
-                                       if (ptep == NULL)
-                                               early_pgtable_allocfail("pte");
-                                       memset(ptep, 0, BASE_PAGE_SIZE);
-                                       pmd_set(pmdp, ptep);
-                               }
-                               ptep = (pte_t *)__pmd_page(*pmdp) +
-                                               ((vaddr >> 13) & 0x3ff);
+                       for (i = 0; i < BASE_PAGE_SIZE / sizeof(pte_t); i++)
+                               store_phys64(pte_phys+i*sizeof(pte_t),0);
 
-                               val = trans[i].data;
+                       pmd_val(pmd_ent) = pte_phys >> 11UL;
+                       store_phys32(pmd_phys, pmd_val(pmd_ent));
+               }
 
-                               /* Clear diag TTE bits. */
-                               if (tlb_type == spitfire)
-                                       val &= ~0x0003fe0000000000UL;
+               pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL;
+               pte_phys += (((vaddr >> 13) & 0x3ff) * sizeof(pte_t));
 
-                               set_pte_at(&init_mm, vaddr,
-                                          ptep, __pte(val | _PAGE_MODIFIED));
-                               trans[i].data += BASE_PAGE_SIZE;
-                       }
-               }
-       }
-       phys_page = __pa(prompmd);
-       obp_iaddr_patch[0] |= (phys_page >> 10);
-       obp_iaddr_patch[1] |= (phys_page & 0x3ff);
-       flushi((long)&obp_iaddr_patch[0]);
-       obp_daddr_patch[0] |= (phys_page >> 10);
-       obp_daddr_patch[1] |= (phys_page & 0x3ff);
-       flushi((long)&obp_daddr_patch[0]);
+               val = data;
 
-       /* Now fixup OBP's idea about where we really are mapped. */
-       prom_printf("Remapping the kernel... ");
+               /* Clear diag TTE bits. */
+               if (tlb_type == spitfire)
+                       val &= ~0x0003fe0000000000UL;
 
-       /* Spitfire Errata #32 workaround */
-       /* NOTE: Using plain zero for the context value is
-        *       correct here, we are not using the Linux trap
-        *       tables yet so we should not use the special
-        *       UltraSPARC-III+ page size encodings yet.
-        */
-       __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
-                            "flush     %%g6"
-                            : /* No outputs */
-                            : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
-
-       switch (tlb_type) {
-       default:
-       case spitfire:
-               phys_page = spitfire_get_dtlb_data(sparc64_highest_locked_tlbent());
-               break;
-
-       case cheetah:
-       case cheetah_plus:
-               phys_page = cheetah_get_litlb_data(sparc64_highest_locked_tlbent());
-               break;
-       };
-
-       phys_page &= _PAGE_PADDR;
-       phys_page += ((unsigned long)&prom_boot_page -
-                     (unsigned long)KERNBASE);
+               store_phys64(pte_phys, val | _PAGE_MODIFIED);
 
-       if (tlb_type == spitfire) {
-               /* Lock this into i/d tlb entry 59 */
-               __asm__ __volatile__(
-                       "stxa   %%g0, [%2] %3\n\t"
-                       "stxa   %0, [%1] %4\n\t"
-                       "membar #Sync\n\t"
-                       "flush  %%g6\n\t"
-                       "stxa   %%g0, [%2] %5\n\t"
-                       "stxa   %0, [%1] %6\n\t"
-                       "membar #Sync\n\t"
-                       "flush  %%g6"
-                       : : "r" (phys_page | _PAGE_VALID | _PAGE_SZ8K | _PAGE_CP |
-                                _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W),
-                       "r" (59 << 3), "r" (TLB_TAG_ACCESS),
-                       "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS),
-                       "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS)
-                       : "memory");
-       } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
-               /* Lock this into i/d tlb-0 entry 11 */
-               __asm__ __volatile__(
-                       "stxa   %%g0, [%2] %3\n\t"
-                       "stxa   %0, [%1] %4\n\t"
-                       "membar #Sync\n\t"
-                       "flush  %%g6\n\t"
-                       "stxa   %%g0, [%2] %5\n\t"
-                       "stxa   %0, [%1] %6\n\t"
-                       "membar #Sync\n\t"
-                       "flush  %%g6"
-                       : : "r" (phys_page | _PAGE_VALID | _PAGE_SZ8K | _PAGE_CP |
-                                _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W),
-                       "r" ((0 << 16) | (11 << 3)), "r" (TLB_TAG_ACCESS),
-                       "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS),
-                       "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS)
-                       : "memory");
-       } else {
-               /* Implement me :-) */
-               BUG();
+               data += BASE_PAGE_SIZE;
        }
+}
 
-       tte_vaddr = (unsigned long) KERNBASE;
+static inline int in_obp_range(unsigned long vaddr)
+{
+       return (vaddr >= LOW_OBP_ADDRESS &&
+               vaddr < HI_OBP_ADDRESS);
+}
 
-       /* Spitfire Errata #32 workaround */
-       /* NOTE: Using plain zero for the context value is
-        *       correct here, we are not using the Linux trap
-        *       tables yet so we should not use the special
-        *       UltraSPARC-III+ page size encodings yet.
-        */
-       __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
-                            "flush     %%g6"
-                            : /* No outputs */
-                            : "r" (0),
-                            "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
-
-       if (tlb_type == spitfire)
-               tte_data = spitfire_get_dtlb_data(sparc64_highest_locked_tlbent());
-       else
-               tte_data = cheetah_get_ldtlb_data(sparc64_highest_locked_tlbent());
+#define OBP_PMD_SIZE 2048
+static void __init build_obp_pgtable(int prom_trans_ents)
+{
+       unsigned long i;
 
-       kern_locked_tte_data = tte_data;
+       prom_pmd_phys = early_alloc_phys(OBP_PMD_SIZE);
+       for (i = 0; i < OBP_PMD_SIZE; i += 4)
+               store_phys32(prom_pmd_phys + i, 0);
 
-       remap_func = (void *)  ((unsigned long) &prom_remap -
-                               (unsigned long) &prom_boot_page);
+       for (i = 0; i < prom_trans_ents; i++) {
+               unsigned long start, end;
 
+               if (!in_obp_range(prom_trans[i].virt))
+                       continue;
 
-       /* Spitfire Errata #32 workaround */
-       /* NOTE: Using plain zero for the context value is
-        *       correct here, we are not using the Linux trap
-        *       tables yet so we should not use the special
-        *       UltraSPARC-III+ page size encodings yet.
-        */
-       __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
-                            "flush     %%g6"
-                            : /* No outputs */
-                            : "r" (0),
-                            "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
-
-       remap_func((tlb_type == spitfire ?
-                   (spitfire_get_dtlb_data(sparc64_highest_locked_tlbent()) & _PAGE_PADDR) :
-                   (cheetah_get_litlb_data(sparc64_highest_locked_tlbent()) & _PAGE_PADDR)),
-                  (unsigned long) KERNBASE,
-                  prom_get_mmu_ihandle());
-
-       if (bigkernel)
-               remap_func(((tte_data + 0x400000) & _PAGE_PADDR),
-                       (unsigned long) KERNBASE + 0x400000, prom_get_mmu_ihandle());
-
-       /* Flush out that temporary mapping. */
-       spitfire_flush_dtlb_nucleus_page(0x0);
-       spitfire_flush_itlb_nucleus_page(0x0);
-
-       /* Now lock us back into the TLBs via OBP. */
-       prom_dtlb_load(sparc64_highest_locked_tlbent(), tte_data, tte_vaddr);
-       prom_itlb_load(sparc64_highest_locked_tlbent(), tte_data, tte_vaddr);
-       if (bigkernel) {
-               prom_dtlb_load(sparc64_highest_locked_tlbent()-1, tte_data + 0x400000, 
-                                                               tte_vaddr + 0x400000);
-               prom_itlb_load(sparc64_highest_locked_tlbent()-1, tte_data + 0x400000, 
-                                                               tte_vaddr + 0x400000);
+               start = prom_trans[i].virt;
+               end = start + prom_trans[i].size;
+               if (end > HI_OBP_ADDRESS)
+                       end = HI_OBP_ADDRESS;
+
+               build_obp_range(start, end, prom_trans[i].data);
        }
+}
+
+/* Read OBP translations property into 'prom_trans[]'.
+ * Return the number of entries.
+ */
+static int __init read_obp_translations(void)
+{
+       int n, node;
 
-       /* Re-read translations property. */
-       if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) {
-               prom_printf("Couldn't get translation property\n");
+       node = prom_finddevice("/virtual-memory");
+       n = prom_getproplen(node, "translations");
+       if (unlikely(n == 0 || n == -1)) {
+               prom_printf("prom_mappings: Couldn't get size.\n");
+               prom_halt();
+       }
+       if (unlikely(n > sizeof(prom_trans))) {
+               prom_printf("prom_mappings: Size %Zd is too big.\n", n);
                prom_halt();
        }
-       n = n / sizeof(*trans);
 
-       for (i = 0; i < n; i++) {
-               unsigned long vaddr = trans[i].virt;
-               unsigned long size = trans[i].size;
+       if ((n = prom_getproperty(node, "translations",
+                                 (char *)&prom_trans[0],
+                                 sizeof(prom_trans))) == -1) {
+               prom_printf("prom_mappings: Couldn't get property.\n");
+               prom_halt();
+       }
+       n = n / sizeof(struct linux_prom_translation);
+       return n;
+}
 
-               if (vaddr < 0xf0000000UL) {
-                       unsigned long avoid_start = (unsigned long) KERNBASE;
-                       unsigned long avoid_end = avoid_start + (4 * 1024 * 1024);
+static void __init remap_kernel(void)
+{
+       unsigned long phys_page, tte_vaddr, tte_data;
+       int tlb_ent = sparc64_highest_locked_tlbent();
 
-                       if (bigkernel)
-                               avoid_end += (4 * 1024 * 1024);
-                       if (vaddr < avoid_start) {
-                               unsigned long top = vaddr + size;
+       tte_vaddr = (unsigned long) KERNBASE;
+       phys_page = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
+       tte_data = (phys_page | (_PAGE_VALID | _PAGE_SZ4MB |
+                                _PAGE_CP | _PAGE_CV | _PAGE_P |
+                                _PAGE_L | _PAGE_W));
 
-                               if (top > avoid_start)
-                                       top = avoid_start;
-                               prom_unmap(top - vaddr, vaddr);
-                       }
-                       if ((vaddr + size) > avoid_end) {
-                               unsigned long bottom = vaddr;
+       kern_locked_tte_data = tte_data;
 
-                               if (bottom < avoid_end)
-                                       bottom = avoid_end;
-                               prom_unmap((vaddr + size) - bottom, bottom);
-                       }
-               }
+       /* Now lock us into the TLBs via OBP. */
+       prom_dtlb_load(tlb_ent, tte_data, tte_vaddr);
+       prom_itlb_load(tlb_ent, tte_data, tte_vaddr);
+       if (bigkernel) {
+               prom_dtlb_load(tlb_ent - 1,
+                              tte_data + 0x400000, 
+                              tte_vaddr + 0x400000);
+               prom_itlb_load(tlb_ent - 1,
+                              tte_data + 0x400000, 
+                              tte_vaddr + 0x400000);
        }
+}
+
+static void __init inherit_prom_mappings(void)
+{
+       int n;
+
+       n = read_obp_translations();
+       build_obp_pgtable(n);
+
+       /* Now fixup OBP's idea about where we really are mapped. */
+       prom_printf("Remapping the kernel... ");
+       remap_kernel();
 
        prom_printf("done.\n");
 
@@ -1276,14 +1272,14 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
        int i;
 
 #ifdef CONFIG_DEBUG_BOOTMEM
-       prom_printf("bootmem_init: Scan sp_banks, ");
+       prom_printf("bootmem_init: Scan pavail, ");
 #endif
 
        bytes_avail = 0UL;
-       for (i = 0; sp_banks[i].num_bytes != 0; i++) {
-               end_of_phys_memory = sp_banks[i].base_addr +
-                       sp_banks[i].num_bytes;
-               bytes_avail += sp_banks[i].num_bytes;
+       for (i = 0; i < pavail_ents; i++) {
+               end_of_phys_memory = pavail[i].phys_addr +
+                       pavail[i].reg_size;
+               bytes_avail += pavail[i].reg_size;
                if (cmdline_memory_size) {
                        if (bytes_avail > cmdline_memory_size) {
                                unsigned long slack = bytes_avail - cmdline_memory_size;
@@ -1291,12 +1287,15 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
                                bytes_avail -= slack;
                                end_of_phys_memory -= slack;
 
-                               sp_banks[i].num_bytes -= slack;
-                               if (sp_banks[i].num_bytes == 0) {
-                                       sp_banks[i].base_addr = 0xdeadbeef;
+                               pavail[i].reg_size -= slack;
+                               if ((long)pavail[i].reg_size <= 0L) {
+                                       pavail[i].phys_addr = 0xdeadbeefUL;
+                                       pavail[i].reg_size = 0UL;
+                                       pavail_ents = i;
                                } else {
-                                       sp_banks[i+1].num_bytes = 0;
-                                       sp_banks[i+1].base_addr = 0xdeadbeef;
+                                       pavail[i+1].reg_size = 0Ul;
+                                       pavail[i+1].phys_addr = 0xdeadbeefUL;
+                                       pavail_ents = i + 1;
                                }
                                break;
                        }
@@ -1347,17 +1346,15 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
 #endif
        bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, end_pfn);
 
-       bootmap_base = bootmap_pfn << PAGE_SHIFT;
-
        /* Now register the available physical memory with the
         * allocator.
         */
-       for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+       for (i = 0; i < pavail_ents; i++) {
 #ifdef CONFIG_DEBUG_BOOTMEM
-               prom_printf("free_bootmem(sp_banks:%d): base[%lx] size[%lx]\n",
-                           i, sp_banks[i].base_addr, sp_banks[i].num_bytes);
+               prom_printf("free_bootmem(pavail:%d): base[%lx] size[%lx]\n",
+                           i, pavail[i].phys_addr, pavail[i].reg_size);
 #endif
-               free_bootmem(sp_banks[i].base_addr, sp_banks[i].num_bytes);
+               free_bootmem(pavail[i].phys_addr, pavail[i].reg_size);
        }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -1398,120 +1395,167 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
        return end_pfn;
 }
 
+#ifdef CONFIG_DEBUG_PAGEALLOC
+static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend, pgprot_t prot)
+{
+       unsigned long vstart = PAGE_OFFSET + pstart;
+       unsigned long vend = PAGE_OFFSET + pend;
+       unsigned long alloc_bytes = 0UL;
+
+       if ((vstart & ~PAGE_MASK) || (vend & ~PAGE_MASK)) {
+               prom_printf("kernel_map: Unaligned physmem[%lx:%lx]\n",
+                           vstart, vend);
+               prom_halt();
+       }
+
+       while (vstart < vend) {
+               unsigned long this_end, paddr = __pa(vstart);
+               pgd_t *pgd = pgd_offset_k(vstart);
+               pud_t *pud;
+               pmd_t *pmd;
+               pte_t *pte;
+
+               pud = pud_offset(pgd, vstart);
+               if (pud_none(*pud)) {
+                       pmd_t *new;
+
+                       new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+                       alloc_bytes += PAGE_SIZE;
+                       pud_populate(&init_mm, pud, new);
+               }
+
+               pmd = pmd_offset(pud, vstart);
+               if (!pmd_present(*pmd)) {
+                       pte_t *new;
+
+                       new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+                       alloc_bytes += PAGE_SIZE;
+                       pmd_populate_kernel(&init_mm, pmd, new);
+               }
+
+               pte = pte_offset_kernel(pmd, vstart);
+               this_end = (vstart + PMD_SIZE) & PMD_MASK;
+               if (this_end > vend)
+                       this_end = vend;
+
+               while (vstart < this_end) {
+                       pte_val(*pte) = (paddr | pgprot_val(prot));
+
+                       vstart += PAGE_SIZE;
+                       paddr += PAGE_SIZE;
+                       pte++;
+               }
+       }
+
+       return alloc_bytes;
+}
+
+static struct linux_prom64_registers pall[MAX_BANKS] __initdata;
+static int pall_ents __initdata;
+
+extern unsigned int kvmap_linear_patch[1];
+
+static void __init kernel_physical_mapping_init(void)
+{
+       unsigned long i, mem_alloced = 0UL;
+
+       read_obp_memory("reg", &pall[0], &pall_ents);
+
+       for (i = 0; i < pall_ents; i++) {
+               unsigned long phys_start, phys_end;
+
+               phys_start = pall[i].phys_addr;
+               phys_end = phys_start + pall[i].reg_size;
+               mem_alloced += kernel_map_range(phys_start, phys_end,
+                                               PAGE_KERNEL);
+       }
+
+       printk("Allocated %ld bytes for kernel page tables.\n",
+              mem_alloced);
+
+       kvmap_linear_patch[0] = 0x01000000; /* nop */
+       flushi(&kvmap_linear_patch[0]);
+
+       __flush_tlb_all();
+}
+
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+       unsigned long phys_start = page_to_pfn(page) << PAGE_SHIFT;
+       unsigned long phys_end = phys_start + (numpages * PAGE_SIZE);
+
+       kernel_map_range(phys_start, phys_end,
+                        (enable ? PAGE_KERNEL : __pgprot(0)));
+
+       /* we should perform an IPI and flush all tlbs,
+        * but that can deadlock->flush only current cpu.
+        */
+       __flush_tlb_kernel_range(PAGE_OFFSET + phys_start,
+                                PAGE_OFFSET + phys_end);
+}
+#endif
+
+unsigned long __init find_ecache_flush_span(unsigned long size)
+{
+       int i;
+
+       for (i = 0; i < pavail_ents; i++) {
+               if (pavail[i].reg_size >= size)
+                       return pavail[i].phys_addr;
+       }
+
+       return ~0UL;
+}
+
 /* paging_init() sets up the page tables */
 
 extern void cheetah_ecache_flush_init(void);
 
 static unsigned long last_valid_pfn;
+pgd_t swapper_pg_dir[2048];
 
 void __init paging_init(void)
 {
-       extern pmd_t swapper_pmd_dir[1024];
-       extern unsigned int sparc64_vpte_patchme1[1];
-       extern unsigned int sparc64_vpte_patchme2[1];
-       unsigned long alias_base = kern_base + PAGE_OFFSET;
-       unsigned long second_alias_page = 0;
-       unsigned long pt, flags, end_pfn, pages_avail;
-       unsigned long shift = alias_base - ((unsigned long)KERNBASE);
-       unsigned long real_end;
+       unsigned long end_pfn, pages_avail, shift;
+       unsigned long real_end, i;
+
+       /* Find available physical memory... */
+       read_obp_memory("available", &pavail[0], &pavail_ents);
+
+       phys_base = 0xffffffffffffffffUL;
+       for (i = 0; i < pavail_ents; i++)
+               phys_base = min(phys_base, pavail[i].phys_addr);
+
+       pfn_base = phys_base >> PAGE_SHIFT;
+
+       kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
+       kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
 
        set_bit(0, mmu_context_bmap);
 
+       shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE);
+
        real_end = (unsigned long)_end;
        if ((real_end > ((unsigned long)KERNBASE + 0x400000)))
                bigkernel = 1;
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (sparc_ramdisk_image || sparc_ramdisk_image64)
-               real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size));
-#endif
-
-       /* We assume physical memory starts at some 4mb multiple,
-        * if this were not true we wouldn't boot up to this point
-        * anyways.
-        */
-       pt  = kern_base | _PAGE_VALID | _PAGE_SZ4MB;
-       pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W;
-       local_irq_save(flags);
-       if (tlb_type == spitfire) {
-               __asm__ __volatile__(
-       "       stxa    %1, [%0] %3\n"
-       "       stxa    %2, [%5] %4\n"
-       "       membar  #Sync\n"
-       "       flush   %%g6\n"
-       "       nop\n"
-       "       nop\n"
-       "       nop\n"
-               : /* No outputs */
-               : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
-                 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3)
-               : "memory");
-               if (real_end >= KERNBASE + 0x340000) {
-                       second_alias_page = alias_base + 0x400000;
-                       __asm__ __volatile__(
-               "       stxa    %1, [%0] %3\n"
-               "       stxa    %2, [%5] %4\n"
-               "       membar  #Sync\n"
-               "       flush   %%g6\n"
-               "       nop\n"
-               "       nop\n"
-               "       nop\n"
-                       : /* No outputs */
-                       : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000),
-                         "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (60 << 3)
-                       : "memory");
-               }
-       } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
-               __asm__ __volatile__(
-       "       stxa    %1, [%0] %3\n"
-       "       stxa    %2, [%5] %4\n"
-       "       membar  #Sync\n"
-       "       flush   %%g6\n"
-       "       nop\n"
-       "       nop\n"
-       "       nop\n"
-               : /* No outputs */
-               : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
-                 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (13<<3))
-               : "memory");
-               if (real_end >= KERNBASE + 0x340000) {
-                       second_alias_page = alias_base + 0x400000;
-                       __asm__ __volatile__(
-               "       stxa    %1, [%0] %3\n"
-               "       stxa    %2, [%5] %4\n"
-               "       membar  #Sync\n"
-               "       flush   %%g6\n"
-               "       nop\n"
-               "       nop\n"
-               "       nop\n"
-                       : /* No outputs */
-                       : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000),
-                         "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (12<<3))
-                       : "memory");
-               }
+       if ((real_end > ((unsigned long)KERNBASE + 0x800000))) {
+               prom_printf("paging_init: Kernel > 8MB, too large.\n");
+               prom_halt();
        }
-       local_irq_restore(flags);
-       
-       /* Now set kernel pgd to upper alias so physical page computations
+
+       /* Set kernel pgd to upper alias so physical page computations
         * work.
         */
        init_mm.pgd += ((shift) / (sizeof(pgd_t)));
        
-       memset(swapper_pmd_dir, 0, sizeof(swapper_pmd_dir));
+       memset(swapper_low_pmd_dir, 0, sizeof(swapper_low_pmd_dir));
 
        /* Now can init the kernel/bad page tables. */
        pud_set(pud_offset(&swapper_pg_dir[0], 0),
-               swapper_pmd_dir + (shift / sizeof(pgd_t)));
+               swapper_low_pmd_dir + (shift / sizeof(pgd_t)));
        
-       sparc64_vpte_patchme1[0] |=
-               (((unsigned long)pgd_val(init_mm.pgd[0])) >> 10);
-       sparc64_vpte_patchme2[0] |=
-               (((unsigned long)pgd_val(init_mm.pgd[0])) & 0x3ff);
-       flushi((long)&sparc64_vpte_patchme1[0]);
+       swapper_pgd_zero = pgd_val(swapper_pg_dir[0]);
        
-       /* Setup bootmem... */
-       pages_avail = 0;
-       last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
-
        /* Inherit non-locked OBP mappings. */
        inherit_prom_mappings();
        
@@ -1527,13 +1571,16 @@ void __init paging_init(void)
 
        inherit_locked_prom_mappings(1);
 
-       /* We only created DTLB mapping of this stuff. */
-       spitfire_flush_dtlb_nucleus_page(alias_base);
-       if (second_alias_page)
-               spitfire_flush_dtlb_nucleus_page(second_alias_page);
-
        __flush_tlb_all();
 
+       /* Setup bootmem... */
+       pages_avail = 0;
+       last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+       kernel_physical_mapping_init();
+#endif
+
        {
                unsigned long zones_size[MAX_NR_ZONES];
                unsigned long zholes_size[MAX_NR_ZONES];
@@ -1554,128 +1601,35 @@ void __init paging_init(void)
        device_scan();
 }
 
-/* Ok, it seems that the prom can allocate some more memory chunks
- * as a side effect of some prom calls we perform during the
- * boot sequence.  My most likely theory is that it is from the
- * prom_set_traptable() call, and OBP is allocating a scratchpad
- * for saving client program register state etc.
- */
-static void __init sort_memlist(struct linux_mlist_p1275 *thislist)
-{
-       int swapi = 0;
-       int i, mitr;
-       unsigned long tmpaddr, tmpsize;
-       unsigned long lowest;
-
-       for (i = 0; thislist[i].theres_more != 0; i++) {
-               lowest = thislist[i].start_adr;
-               for (mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++)
-                       if (thislist[mitr].start_adr < lowest) {
-                               lowest = thislist[mitr].start_adr;
-                               swapi = mitr;
-                       }
-               if (lowest == thislist[i].start_adr)
-                       continue;
-               tmpaddr = thislist[swapi].start_adr;
-               tmpsize = thislist[swapi].num_bytes;
-               for (mitr = swapi; mitr > i; mitr--) {
-                       thislist[mitr].start_adr = thislist[mitr-1].start_adr;
-                       thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
-               }
-               thislist[i].start_adr = tmpaddr;
-               thislist[i].num_bytes = tmpsize;
-       }
-}
-
-void __init rescan_sp_banks(void)
-{
-       struct linux_prom64_registers memlist[64];
-       struct linux_mlist_p1275 avail[64], *mlist;
-       unsigned long bytes, base_paddr;
-       int num_regs, node = prom_finddevice("/memory");
-       int i;
-
-       num_regs = prom_getproperty(node, "available",
-                                   (char *) memlist, sizeof(memlist));
-       num_regs = (num_regs / sizeof(struct linux_prom64_registers));
-       for (i = 0; i < num_regs; i++) {
-               avail[i].start_adr = memlist[i].phys_addr;
-               avail[i].num_bytes = memlist[i].reg_size;
-               avail[i].theres_more = &avail[i + 1];
-       }
-       avail[i - 1].theres_more = NULL;
-       sort_memlist(avail);
-
-       mlist = &avail[0];
-       i = 0;
-       bytes = mlist->num_bytes;
-       base_paddr = mlist->start_adr;
-  
-       sp_banks[0].base_addr = base_paddr;
-       sp_banks[0].num_bytes = bytes;
-
-       while (mlist->theres_more != NULL){
-               i++;
-               mlist = mlist->theres_more;
-               bytes = mlist->num_bytes;
-               if (i >= SPARC_PHYS_BANKS-1) {
-                       printk ("The machine has more banks than "
-                               "this kernel can support\n"
-                               "Increase the SPARC_PHYS_BANKS "
-                               "setting (currently %d)\n",
-                               SPARC_PHYS_BANKS);
-                       i = SPARC_PHYS_BANKS-1;
-                       break;
-               }
-    
-               sp_banks[i].base_addr = mlist->start_adr;
-               sp_banks[i].num_bytes = mlist->num_bytes;
-       }
-
-       i++;
-       sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL;
-       sp_banks[i].num_bytes = 0;
-
-       for (i = 0; sp_banks[i].num_bytes != 0; i++)
-               sp_banks[i].num_bytes &= PAGE_MASK;
-}
-
 static void __init taint_real_pages(void)
 {
-       struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS];
        int i;
 
-       for (i = 0; i < SPARC_PHYS_BANKS; i++) {
-               saved_sp_banks[i].base_addr =
-                       sp_banks[i].base_addr;
-               saved_sp_banks[i].num_bytes =
-                       sp_banks[i].num_bytes;
-       }
-
-       rescan_sp_banks();
+       read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents);
 
-       /* Find changes discovered in the sp_bank rescan and
+       /* Find changes discovered in the physmem available rescan and
         * reserve the lost portions in the bootmem maps.
         */
-       for (i = 0; saved_sp_banks[i].num_bytes; i++) {
+       for (i = 0; i < pavail_ents; i++) {
                unsigned long old_start, old_end;
 
-               old_start = saved_sp_banks[i].base_addr;
+               old_start = pavail[i].phys_addr;
                old_end = old_start +
-                       saved_sp_banks[i].num_bytes;
+                       pavail[i].reg_size;
                while (old_start < old_end) {
                        int n;
 
-                       for (n = 0; sp_banks[n].num_bytes; n++) {
+                       for (n = 0; pavail_rescan_ents; n++) {
                                unsigned long new_start, new_end;
 
-                               new_start = sp_banks[n].base_addr;
-                               new_end = new_start + sp_banks[n].num_bytes;
+                               new_start = pavail_rescan[n].phys_addr;
+                               new_end = new_start +
+                                       pavail_rescan[n].reg_size;
 
                                if (new_start <= old_start &&
                                    new_end >= (old_start + PAGE_SIZE)) {
-                                       set_bit (old_start >> 22,
-                                                sparc64_valid_addr_bitmap);
+                                       set_bit(old_start >> 22,
+                                               sparc64_valid_addr_bitmap);
                                        goto do_next_page;
                                }
                        }
@@ -1695,8 +1649,7 @@ void __init mem_init(void)
 
        i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
        i += 1;
-       sparc64_valid_addr_bitmap = (unsigned long *)
-               __alloc_bootmem(i << 3, SMP_CACHE_BYTES, bootmap_base);
+       sparc64_valid_addr_bitmap = (unsigned long *) alloc_bootmem(i << 3);
        if (sparc64_valid_addr_bitmap == NULL) {
                prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
                prom_halt();
@@ -1749,7 +1702,7 @@ void __init mem_init(void)
                cheetah_ecache_flush_init();
 }
 
-void free_initmem (void)
+void free_initmem(void)
 {
        unsigned long addr, initend;
 
index b2ee9b53227f5746b19351dc20ea873231831a58..058b8126c1a72793d939d72b92440f56d806fa59 100644 (file)
@@ -144,42 +144,29 @@ __flush_icache_page:      /* %o0 = phys_page */
 
 #define DTAG_MASK 0x3
 
+       /* This routine is Spitfire specific so the hardcoded
+        * D-cache size and line-size are OK.
+        */
        .align          64
        .globl          __flush_dcache_page
 __flush_dcache_page:   /* %o0=kaddr, %o1=flush_icache */
        sethi           %uhi(PAGE_OFFSET), %g1
        sllx            %g1, 32, %g1
-       sub             %o0, %g1, %o0
-       clr             %o4
-       srlx            %o0, 11, %o0
-       sethi           %hi(1 << 14), %o2
-1:     ldxa            [%o4] ASI_DCACHE_TAG, %o3       ! LSU   Group
-       add             %o4, (1 << 5), %o4              ! IEU0
-       ldxa            [%o4] ASI_DCACHE_TAG, %g1       ! LSU   Group
-       add             %o4, (1 << 5), %o4              ! IEU0
-       ldxa            [%o4] ASI_DCACHE_TAG, %g2       ! LSU   Group   o3 available
-       add             %o4, (1 << 5), %o4              ! IEU0
-       andn            %o3, DTAG_MASK, %o3             ! IEU1
-       ldxa            [%o4] ASI_DCACHE_TAG, %g3       ! LSU   Group
-       add             %o4, (1 << 5), %o4              ! IEU0
-       andn            %g1, DTAG_MASK, %g1             ! IEU1
-       cmp             %o0, %o3                        ! IEU1  Group
-       be,a,pn         %xcc, dflush1                   ! CTI
-        sub            %o4, (4 << 5), %o4              ! IEU0  (Group)
-       cmp             %o0, %g1                        ! IEU1  Group
-       andn            %g2, DTAG_MASK, %g2             ! IEU0
-       be,a,pn         %xcc, dflush2                   ! CTI
-        sub            %o4, (3 << 5), %o4              ! IEU0  (Group)
-       cmp             %o0, %g2                        ! IEU1  Group
-       andn            %g3, DTAG_MASK, %g3             ! IEU0
-       be,a,pn         %xcc, dflush3                   ! CTI
-        sub            %o4, (2 << 5), %o4              ! IEU0  (Group)
-       cmp             %o0, %g3                        ! IEU1  Group
-       be,a,pn         %xcc, dflush4                   ! CTI
-        sub            %o4, (1 << 5), %o4              ! IEU0
-2:     cmp             %o4, %o2                        ! IEU1  Group
-       bne,pt          %xcc, 1b                        ! CTI
-        nop                                            ! IEU0
+       sub             %o0, %g1, %o0                   ! physical address
+       srlx            %o0, 11, %o0                    ! make D-cache TAG
+       sethi           %hi(1 << 14), %o2               ! D-cache size
+       sub             %o2, (1 << 5), %o2              ! D-cache line size
+1:     ldxa            [%o2] ASI_DCACHE_TAG, %o3       ! load D-cache TAG
+       andcc           %o3, DTAG_MASK, %g0             ! Valid?
+       be,pn           %xcc, 2f                        ! Nope, branch
+        andn           %o3, DTAG_MASK, %o3             ! Clear valid bits
+       cmp             %o3, %o0                        ! TAG match?
+       bne,pt          %xcc, 2f                        ! Nope, branch
+        nop
+       stxa            %g0, [%o2] ASI_DCACHE_TAG       ! Invalidate TAG
+       membar          #Sync
+2:     brnz,pt         %o2, 1b
+        sub            %o2, (1 << 5), %o2              ! D-cache line size
 
        /* The I-cache does not snoop local stores so we
         * better flush that too when necessary.
@@ -189,48 +176,9 @@ __flush_dcache_page:       /* %o0=kaddr, %o1=flush_icache */
        retl
         nop
 
-dflush1:stxa           %g0, [%o4] ASI_DCACHE_TAG
-       add             %o4, (1 << 5), %o4
-dflush2:stxa           %g0, [%o4] ASI_DCACHE_TAG
-       add             %o4, (1 << 5), %o4
-dflush3:stxa           %g0, [%o4] ASI_DCACHE_TAG
-       add             %o4, (1 << 5), %o4
-dflush4:stxa           %g0, [%o4] ASI_DCACHE_TAG
-       add             %o4, (1 << 5), %o4
-       membar          #Sync
-       ba,pt           %xcc, 2b
-        nop
 #endif /* DCACHE_ALIASING_POSSIBLE */
 
-       .previous .text
-       .align          32
-__prefill_dtlb:
-       rdpr            %pstate, %g7
-       wrpr            %g7, PSTATE_IE, %pstate
-       mov             TLB_TAG_ACCESS, %g1
-       stxa            %o5, [%g1] ASI_DMMU
-       stxa            %o2, [%g0] ASI_DTLB_DATA_IN
-       flush           %g6
-       retl
-        wrpr           %g7, %pstate
-__prefill_itlb:
-       rdpr            %pstate, %g7
-       wrpr            %g7, PSTATE_IE, %pstate
-       mov             TLB_TAG_ACCESS, %g1
-       stxa            %o5, [%g1] ASI_IMMU
-       stxa            %o2, [%g0] ASI_ITLB_DATA_IN
-       flush           %g6
-       retl
-        wrpr           %g7, %pstate
-
-       .globl          __update_mmu_cache
-__update_mmu_cache:    /* %o0=hw_context, %o1=address, %o2=pte, %o3=fault_code */
-       srlx            %o1, PAGE_SHIFT, %o1
-       andcc           %o3, FAULT_CODE_DTLB, %g0
-       sllx            %o1, PAGE_SHIFT, %o5
-       bne,pt          %xcc, __prefill_dtlb
-        or             %o5, %o0, %o5
-       ba,a,pt         %xcc, __prefill_itlb
+       .previous
 
        /* Cheetah specific versions, patched at boot time. */
 __cheetah_flush_tlb_mm: /* 18 insns */
@@ -283,7 +231,7 @@ __cheetah_flush_tlb_pending:        /* 26 insns */
         wrpr           %g7, 0x0, %pstate
 
 #ifdef DCACHE_ALIASING_POSSIBLE
-flush_dcpage_cheetah: /* 11 insns */
+__cheetah_flush_dcache_page: /* 11 insns */
        sethi           %uhi(PAGE_OFFSET), %g1
        sllx            %g1, 32, %g1
        sub             %o0, %g1, %o0
@@ -329,8 +277,8 @@ cheetah_patch_cachetlbops:
 #ifdef DCACHE_ALIASING_POSSIBLE
        sethi           %hi(__flush_dcache_page), %o0
        or              %o0, %lo(__flush_dcache_page), %o0
-       sethi           %hi(flush_dcpage_cheetah), %o1
-       or              %o1, %lo(flush_dcpage_cheetah), %o1
+       sethi           %hi(__cheetah_flush_dcache_page), %o1
+       or              %o1, %lo(__cheetah_flush_dcache_page), %o1
        call            cheetah_patch_one
         mov            11, %o2
 #endif /* DCACHE_ALIASING_POSSIBLE */
index 8f2420d9e9e60a6ece3af6a07cb722db50ceed1f..3d33ed27bc27b2bb0a98a374c657e99f5e3dc5ad 100644 (file)
@@ -6,5 +6,5 @@
 EXTRA_AFLAGS := -ansi
 EXTRA_CFLAGS := -Werror
 
-lib-y   := bootstr.o devops.o init.o memory.o misc.o \
-          tree.o console.o printf.o p1275.o map.o cif.o
+lib-y   := bootstr.o devops.o init.o misc.o \
+          tree.o console.o printf.o p1275.o cif.o
index 028a53fcb1ec20e949cc925302327c9d03028d62..eae5db8dda56468ecaee4db7dfcf8fd01e60f6df 100644 (file)
@@ -67,7 +67,7 @@ prom_putchar(char c)
 }
 
 void
-prom_puts(char *s, int len)
+prom_puts(const char *s, int len)
 {
        p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
                           P1275_INOUT(3,1),
index 2c99b21b6981fac5ecf50b6479787b7192ce72f3..4641839eb39a9184966f14d07c30ab5131f1e706 100644 (file)
@@ -16,7 +16,7 @@
  * Returns 0 on failure.
  */
 int
-prom_devopen(char *dstr)
+prom_devopen(const char *dstr)
 {
        return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)|
                                  P1275_INOUT(1,1),
index 817faae058cd4116740f9a53f163d47a9beca422..f3cc2d8578b200ec8cc140dc4661abfebfea67a8 100644 (file)
@@ -27,7 +27,6 @@ int prom_chosen_node;
  * failure.  It gets passed the pointer to the PROM vector.
  */
 
-extern void prom_meminit(void);
 extern void prom_cif_init(void *, void *);
 
 void __init prom_init(void *cif_handler, void *cif_stack)
@@ -46,7 +45,7 @@ void __init prom_init(void *cif_handler, void *cif_stack)
        if((prom_root_node == 0) || (prom_root_node == -1))
                prom_halt();
 
-       prom_chosen_node = prom_finddevice("/chosen");
+       prom_chosen_node = prom_finddevice(prom_chosen_path);
        if (!prom_chosen_node || prom_chosen_node == -1)
                prom_halt();
 
@@ -90,8 +89,6 @@ void __init prom_init(void *cif_handler, void *cif_stack)
 
        printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust);
 
-       prom_meminit();
-
        /* Initialization successful. */
        return;
 
diff --git a/arch/sparc64/prom/map.S b/arch/sparc64/prom/map.S
deleted file mode 100644 (file)
index 21b3f9c..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* $Id: map.S,v 1.2 1999/11/19 05:53:02 davem Exp $
- * map.S: Tricky coding required to fixup the kernel OBP maps
- *       properly.
- *
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- */
-
-       .text
-       .align  8192
-       .globl  prom_boot_page
-prom_boot_page:
-call_method:
-       .asciz  "call-method"
-       .align  8
-map:
-       .asciz  "map"
-       .align  8
-
-       /* When we are invoked, our caller has remapped us to
-        * page zero, therefore we must use PC relative addressing
-        * for everything after we begin performing the unmap/map
-        * calls.
-        */
-       .globl  prom_remap
-prom_remap:    /* %o0 = physpage, %o1 = virtpage, %o2 = mmu_ihandle */
-       rd      %pc, %g1
-       srl     %o2, 0, %o2                     ! kill sign extension
-       sethi   %hi(p1275buf), %g2
-       or      %g2, %lo(p1275buf), %g2
-       ldx     [%g2 + 0x10], %g3               ! prom_cif_stack
-       save    %g3, -(192 + 128), %sp
-       ldx     [%g2 + 0x08], %l0               ! prom_cif_handler
-       mov     %g6, %i3
-       mov     %g4, %i4
-       mov     %g5, %i5
-       flushw
-
-       sethi   %hi(prom_remap - call_method), %g7
-       or      %g7, %lo(prom_remap - call_method), %g7
-       sub     %g1, %g7, %l2                   ! call-method string
-       sethi   %hi(prom_remap - map), %g7
-       or      %g7, %lo(prom_remap - map), %g7
-       sub     %g1, %g7, %l4                   ! map string
-
-       /* OK, map the 4MB region we really live at. */
-       stx     %l2, [%sp + 2047 + 128 + 0x00]  ! call-method
-       mov     7, %l5
-       stx     %l5, [%sp + 2047 + 128 + 0x08]  ! num_args
-       mov     1, %l5
-       stx     %l5, [%sp + 2047 + 128 + 0x10]  ! num_rets
-       stx     %l4, [%sp + 2047 + 128 + 0x18]  ! map
-       stx     %i2, [%sp + 2047 + 128 + 0x20]  ! mmu_ihandle
-       mov     -1, %l5
-       stx     %l5, [%sp + 2047 + 128 + 0x28]  ! mode == default
-       sethi   %hi(4 * 1024 * 1024), %l5
-       stx     %l5, [%sp + 2047 + 128 + 0x30]  ! size
-       stx     %i1, [%sp + 2047 + 128 + 0x38]  ! vaddr
-       stx     %g0, [%sp + 2047 + 128 + 0x40]  ! filler
-       stx     %i0, [%sp + 2047 + 128 + 0x48]  ! paddr
-       call    %l0
-        add    %sp, (2047 + 128), %o0          ! argument array
-
-       /* Restore hard-coded globals. */
-       mov     %i3, %g6
-       mov     %i4, %g4
-       mov     %i5, %g5
-
-       /* Wheee.... we are done. */
-       ret
-       restore
-
-       .align  8192
diff --git a/arch/sparc64/prom/memory.c b/arch/sparc64/prom/memory.c
deleted file mode 100644 (file)
index f4a8143..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/* $Id: memory.c,v 1.5 1999/08/31 06:55:04 davem Exp $
- * memory.c: Prom routine for acquiring various bits of information
- *           about RAM on the machine, both virtual and physical.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-
-/* This routine, for consistency, returns the ram parameters in the
- * V0 prom memory descriptor format.  I choose this format because I
- * think it was the easiest to work with.  I feel the religious
- * arguments now... ;)  Also, I return the linked lists sorted to
- * prevent paging_init() upset stomach as I have not yet written
- * the pepto-bismol kernel module yet.
- */
-
-struct linux_prom64_registers prom_reg_memlist[64];
-struct linux_prom64_registers prom_reg_tmp[64];
-
-struct linux_mlist_p1275 prom_phys_total[64];
-struct linux_mlist_p1275 prom_prom_taken[64];
-struct linux_mlist_p1275 prom_phys_avail[64];
-
-struct linux_mlist_p1275 *prom_ptot_ptr = prom_phys_total;
-struct linux_mlist_p1275 *prom_ptak_ptr = prom_prom_taken;
-struct linux_mlist_p1275 *prom_pavl_ptr = prom_phys_avail;
-
-struct linux_mem_p1275 prom_memlist;
-
-
-/* Internal Prom library routine to sort a linux_mlist_p1275 memory
- * list.  Used below in initialization.
- */
-static void __init
-prom_sortmemlist(struct linux_mlist_p1275 *thislist)
-{
-       int swapi = 0;
-       int i, mitr;
-       unsigned long tmpaddr, tmpsize;
-       unsigned long lowest;
-
-       for(i=0; thislist[i].theres_more; i++) {
-               lowest = thislist[i].start_adr;
-               for(mitr = i+1; thislist[mitr-1].theres_more; mitr++)
-                       if(thislist[mitr].start_adr < lowest) {
-                               lowest = thislist[mitr].start_adr;
-                               swapi = mitr;
-                       }
-               if(lowest == thislist[i].start_adr) continue;
-               tmpaddr = thislist[swapi].start_adr;
-               tmpsize = thislist[swapi].num_bytes;
-               for(mitr = swapi; mitr > i; mitr--) {
-                       thislist[mitr].start_adr = thislist[mitr-1].start_adr;
-                       thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
-               }
-               thislist[i].start_adr = tmpaddr;
-               thislist[i].num_bytes = tmpsize;
-       }
-}
-
-/* Initialize the memory lists based upon the prom version. */
-void __init prom_meminit(void)
-{
-       int node = 0;
-       unsigned int iter, num_regs;
-
-       node = prom_finddevice("/memory");
-       num_regs = prom_getproperty(node, "available",
-                                   (char *) prom_reg_memlist,
-                                   sizeof(prom_reg_memlist));
-       num_regs = (num_regs/sizeof(struct linux_prom64_registers));
-       for(iter=0; iter<num_regs; iter++) {
-               prom_phys_avail[iter].start_adr =
-                       prom_reg_memlist[iter].phys_addr;
-               prom_phys_avail[iter].num_bytes =
-                       prom_reg_memlist[iter].reg_size;
-               prom_phys_avail[iter].theres_more =
-                       &prom_phys_avail[iter+1];
-       }
-       prom_phys_avail[iter-1].theres_more = NULL;
-
-       num_regs = prom_getproperty(node, "reg",
-                                   (char *) prom_reg_memlist,
-                                   sizeof(prom_reg_memlist));
-       num_regs = (num_regs/sizeof(struct linux_prom64_registers));
-       for(iter=0; iter<num_regs; iter++) {
-               prom_phys_total[iter].start_adr =
-                       prom_reg_memlist[iter].phys_addr;
-               prom_phys_total[iter].num_bytes =
-                       prom_reg_memlist[iter].reg_size;
-               prom_phys_total[iter].theres_more =
-                       &prom_phys_total[iter+1];
-       }
-       prom_phys_total[iter-1].theres_more = NULL;
-
-       node = prom_finddevice("/virtual-memory");
-       num_regs = prom_getproperty(node, "available",
-                                   (char *) prom_reg_memlist,
-                                   sizeof(prom_reg_memlist));
-       num_regs = (num_regs/sizeof(struct linux_prom64_registers));
-
-       /* Convert available virtual areas to taken virtual
-        * areas.  First sort, then convert.
-        */
-       for(iter=0; iter<num_regs; iter++) {
-               prom_prom_taken[iter].start_adr =
-                       prom_reg_memlist[iter].phys_addr;
-               prom_prom_taken[iter].num_bytes =
-                       prom_reg_memlist[iter].reg_size;
-               prom_prom_taken[iter].theres_more =
-                       &prom_prom_taken[iter+1];
-       }
-       prom_prom_taken[iter-1].theres_more = NULL;
-
-       prom_sortmemlist(prom_prom_taken);
-
-       /* Finally, convert. */
-       for(iter=0; iter<num_regs; iter++) {
-               prom_prom_taken[iter].start_adr =
-                       prom_prom_taken[iter].start_adr +
-                       prom_prom_taken[iter].num_bytes;
-               prom_prom_taken[iter].num_bytes =
-                       prom_prom_taken[iter+1].start_adr -
-                       prom_prom_taken[iter].start_adr;
-       }
-       prom_prom_taken[iter-1].num_bytes =
-               -1UL - prom_prom_taken[iter-1].start_adr;
-
-       /* Sort the other two lists. */
-       prom_sortmemlist(prom_phys_total);
-       prom_sortmemlist(prom_phys_avail);
-
-       /* Link all the lists into the top-level descriptor. */
-       prom_memlist.p1275_totphys=&prom_ptot_ptr;
-       prom_memlist.p1275_prommap=&prom_ptak_ptr;
-       prom_memlist.p1275_available=&prom_pavl_ptr;
-}
-
-/* This returns a pointer to our libraries internal p1275 format
- * memory descriptor.
- */
-struct linux_mem_p1275 *
-prom_meminfo(void)
-{
-       return &prom_memlist;
-}
index 19c44e97e9eef88def0a838c4c1fd3f2991dda9b..9b895faf077b8ab02c7206d1356b7fabac6874d2 100644 (file)
 #include <asm/system.h>
 
 /* Reset and reboot the machine with the command 'bcommand'. */
-void prom_reboot(char *bcommand)
+void prom_reboot(const char *bcommand)
 {
        p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
                  P1275_INOUT(1, 0), bcommand);
 }
 
 /* Forth evaluate the expression contained in 'fstring'. */
-void prom_feval(char *fstring)
+void prom_feval(const char *fstring)
 {
        if (!fstring || fstring[0] == 0)
                return;
@@ -148,21 +148,19 @@ void prom_set_trap_table(unsigned long tba)
        p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba);
 }
 
-int mmu_ihandle_cache = 0;
-
 int prom_get_mmu_ihandle(void)
 {
        int node, ret;
 
-       if (mmu_ihandle_cache != 0)
-               return mmu_ihandle_cache;
+       if (prom_mmu_ihandle_cache != 0)
+               return prom_mmu_ihandle_cache;
 
-       node = prom_finddevice("/chosen");
-       ret = prom_getint(node, "mmu");
+       node = prom_finddevice(prom_chosen_path);
+       ret = prom_getint(node, prom_mmu_name);
        if (ret == -1 || ret == 0)
-               mmu_ihandle_cache = -1;
+               prom_mmu_ihandle_cache = -1;
        else
-               mmu_ihandle_cache = ret;
+               prom_mmu_ihandle_cache = ret;
 
        return ret;
 }
@@ -190,7 +188,7 @@ long prom_itlb_load(unsigned long index,
                    unsigned long tte_data,
                    unsigned long vaddr)
 {
-       return p1275_cmd("call-method",
+       return p1275_cmd(prom_callmethod_name,
                         (P1275_ARG(0, P1275_ARG_IN_STRING) |
                          P1275_ARG(2, P1275_ARG_IN_64B) |
                          P1275_ARG(3, P1275_ARG_IN_64B) |
@@ -207,7 +205,7 @@ long prom_dtlb_load(unsigned long index,
                    unsigned long tte_data,
                    unsigned long vaddr)
 {
-       return p1275_cmd("call-method",
+       return p1275_cmd(prom_callmethod_name,
                         (P1275_ARG(0, P1275_ARG_IN_STRING) |
                          P1275_ARG(2, P1275_ARG_IN_64B) |
                          P1275_ARG(3, P1275_ARG_IN_64B) |
@@ -223,13 +221,13 @@ long prom_dtlb_load(unsigned long index,
 int prom_map(int mode, unsigned long size,
             unsigned long vaddr, unsigned long paddr)
 {
-       int ret = p1275_cmd("call-method",
+       int ret = p1275_cmd(prom_callmethod_name,
                            (P1275_ARG(0, P1275_ARG_IN_STRING) |
                             P1275_ARG(3, P1275_ARG_IN_64B) |
                             P1275_ARG(4, P1275_ARG_IN_64B) |
                             P1275_ARG(6, P1275_ARG_IN_64B) |
                             P1275_INOUT(7, 1)),
-                           "map",
+                           prom_map_name,
                            prom_get_mmu_ihandle(),
                            mode,
                            size,
@@ -244,12 +242,12 @@ int prom_map(int mode, unsigned long size,
 
 void prom_unmap(unsigned long size, unsigned long vaddr)
 {
-       p1275_cmd("call-method",
+       p1275_cmd(prom_callmethod_name,
                  (P1275_ARG(0, P1275_ARG_IN_STRING) |
                   P1275_ARG(2, P1275_ARG_IN_64B) |
                   P1275_ARG(3, P1275_ARG_IN_64B) |
                   P1275_INOUT(4, 0)),
-                 "unmap",
+                 prom_unmap_name,
                  prom_get_mmu_ihandle(),
                  size,
                  vaddr);
@@ -258,7 +256,7 @@ void prom_unmap(unsigned long size, unsigned long vaddr)
 /* Set aside physical memory which is not touched or modified
  * across soft resets.
  */
-unsigned long prom_retain(char *name,
+unsigned long prom_retain(const char *name,
                          unsigned long pa_low, unsigned long pa_high,
                          long size, long align)
 {
@@ -290,7 +288,7 @@ int prom_getunumber(int syndrome_code,
                    unsigned long phys_addr,
                    char *buf, int buflen)
 {
-       return p1275_cmd("call-method",
+       return p1275_cmd(prom_callmethod_name,
                         (P1275_ARG(0, P1275_ARG_IN_STRING)     |
                          P1275_ARG(3, P1275_ARG_OUT_BUF)       |
                          P1275_ARG(6, P1275_ARG_IN_64B)        |
index 59fe38bba39e8d47ad56d627cad54f6730b5a86d..a5a7c5712028b2b3401d908baa3b739ca2e0117c 100644 (file)
@@ -46,7 +46,7 @@ static inline unsigned long spitfire_get_primary_context(void)
  */
 DEFINE_SPINLOCK(prom_entry_lock);
 
-long p1275_cmd (char *service, long fmt, ...)
+long p1275_cmd(const char *service, long fmt, ...)
 {
        char *p, *q;
        unsigned long flags;
index a6df82cafa0d1f87b19dd0905d3af251feb80b55..660943ee4c2ac7e431822dc1f99cf9e8bac294e7 100644 (file)
@@ -34,7 +34,7 @@ prom_write(const char *buf, unsigned int n)
 }
 
 void
-prom_printf(char *fmt, ...)
+prom_printf(const char *fmt, ...)
 {
        va_list args;
        int i;
index ccf73258ebf7079c4642c09d0ec82d2108c3ee4a..b1ff9e87dcc6a339b9387f5ae56378adc6274be4 100644 (file)
@@ -69,7 +69,7 @@ prom_getsibling(int node)
  * Return -1 on error.
  */
 __inline__ int
-prom_getproplen(int node, char *prop)
+prom_getproplen(int node, const char *prop)
 {
        if((!node) || (!prop)) return -1;
        return p1275_cmd ("getproplen", 
@@ -83,20 +83,20 @@ prom_getproplen(int node, char *prop)
  * was successful the length will be returned, else -1 is returned.
  */
 __inline__ int
-prom_getproperty(int node, char *prop, char *buffer, int bufsize)
+prom_getproperty(int node, const char *prop, char *buffer, int bufsize)
 {
        int plen;
 
        plen = prom_getproplen(node, prop);
-       if((plen > bufsize) || (plen == 0) || (plen == -1))
+       if ((plen > bufsize) || (plen == 0) || (plen == -1)) {
                return -1;
-       else {
+       else {
                /* Ok, things seem all right. */
-               return p1275_cmd ("getprop"
-                                 P1275_ARG(1,P1275_ARG_IN_STRING)|
-                                 P1275_ARG(2,P1275_ARG_OUT_BUF)|
-                                 P1275_INOUT(4, 1), 
-                                 node, prop, buffer, P1275_SIZE(plen));
+               return p1275_cmd(prom_getprop_name
+                                P1275_ARG(1,P1275_ARG_IN_STRING)|
+                                P1275_ARG(2,P1275_ARG_OUT_BUF)|
+                                P1275_INOUT(4, 1), 
+                                node, prop, buffer, P1275_SIZE(plen));
        }
 }
 
@@ -104,7 +104,7 @@ prom_getproperty(int node, char *prop, char *buffer, int bufsize)
  * on failure.
  */
 __inline__ int
-prom_getint(int node, char *prop)
+prom_getint(int node, const char *prop)
 {
        int intprop;
 
@@ -119,7 +119,7 @@ prom_getint(int node, char *prop)
  */
 
 int
-prom_getintdefault(int node, char *property, int deflt)
+prom_getintdefault(int node, const char *property, int deflt)
 {
        int retval;
 
@@ -131,7 +131,7 @@ prom_getintdefault(int node, char *property, int deflt)
 
 /* Acquire a boolean property, 1=TRUE 0=FALSE. */
 int
-prom_getbool(int node, char *prop)
+prom_getbool(int node, const char *prop)
 {
        int retval;
 
@@ -145,7 +145,7 @@ prom_getbool(int node, char *prop)
  * buffer.
  */
 void
-prom_getstring(int node, char *prop, char *user_buf, int ubuf_size)
+prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size)
 {
        int len;
 
@@ -160,7 +160,7 @@ prom_getstring(int node, char *prop, char *user_buf, int ubuf_size)
  * YES = 1   NO = 0
  */
 int
-prom_nodematch(int node, char *name)
+prom_nodematch(int node, const char *name)
 {
        char namebuf[128];
        prom_getproperty(node, "name", namebuf, sizeof(namebuf));
@@ -172,7 +172,7 @@ prom_nodematch(int node, char *name)
  * 'nodename'.  Return node if successful, zero if not.
  */
 int
-prom_searchsiblings(int node_start, char *nodename)
+prom_searchsiblings(int node_start, const char *nodename)
 {
 
        int thisnode, error;
@@ -294,7 +294,7 @@ prom_firstprop(int node, char *buffer)
  * property types for this node.
  */
 __inline__ char *
-prom_nextprop(int node, char *oprop, char *buffer)
+prom_nextprop(int node, const char *oprop, char *buffer)
 {
        char buf[32];
 
@@ -314,15 +314,17 @@ prom_nextprop(int node, char *oprop, char *buffer)
 }
 
 int
-prom_finddevice(char *name)
+prom_finddevice(const char *name)
 {
-       if(!name) return 0;
-       return p1275_cmd ("finddevice", P1275_ARG(0,P1275_ARG_IN_STRING)|
-                                       P1275_INOUT(1, 1), 
-                                       name);
+       if (!name)
+               return 0;
+       return p1275_cmd(prom_finddev_name,
+                        P1275_ARG(0,P1275_ARG_IN_STRING)|
+                        P1275_INOUT(1, 1), 
+                        name);
 }
 
-int prom_node_has_property(int node, char *prop)
+int prom_node_has_property(int node, const char *prop)
 {
        char buf [32];
         
@@ -339,7 +341,7 @@ int prom_node_has_property(int node, char *prop)
  * of 'size' bytes.  Return the number of bytes the prom accepted.
  */
 int
-prom_setprop(int node, char *pname, char *value, int size)
+prom_setprop(int node, const char *pname, char *value, int size)
 {
        if(size == 0) return 0;
        if((pname == 0) || (value == 0)) return 0;
@@ -364,7 +366,7 @@ prom_inst2pkg(int inst)
  * FIXME: Should work for v0 as well
  */
 int
-prom_pathtoinode(char *path)
+prom_pathtoinode(const char *path)
 {
        int node, inst;
 
index 5b5af95721ab16f4cee63ae8ac0c988a91aa45e0..7af37e342e331bf89f0880c2ae0ae4d690f3cbea 100644 (file)
@@ -28,8 +28,6 @@ SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
 ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
        $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
 
-GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
-
 um-modes-$(CONFIG_MODE_TT) += tt
 um-modes-$(CONFIG_MODE_SKAS) += skas
 
@@ -45,9 +43,7 @@ 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)
 
@@ -87,10 +83,6 @@ CONFIG_KERNEL_HALF_GIGS ?= 0
 
 SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
 
-ifeq ($(CONFIG_MODE_SKAS), y)
-$(SYS_HEADERS) : $(ARCH_DIR)/include/skas_ptregs.h
-endif
-
 .PHONY: linux
 
 all: linux
@@ -111,7 +103,8 @@ else
 $(shell cd $(ARCH_DIR) && ln -sf Kconfig.$(SUBARCH) Kconfig.arch)
 endif
 
-archprepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
+archprepare: $(ARCH_SYMLINKS) $(ARCH_DIR)/include/user_constants.h
+prepare: $(ARCH_DIR)/include/kern_constants.h
 
 LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
@@ -146,15 +139,13 @@ endef
 #When cleaning we don't include .config, so we don't include
 #TT or skas makefiles and don't clean skas_ptregs.h.
 CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \
-       $(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h \
-       $(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/Kconfig.arch
+       $(ARCH_DIR)/include/user_constants.h \
+       $(ARCH_DIR)/include/kern_constants.h $(ARCH_DIR)/Kconfig.arch
 
 MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
        $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os
 
 archclean:
-       $(Q)$(MAKE) $(clean)=$(ARCH_DIR)/util
-       $(Q)$(MAKE) $(clean)=$(ARCH_DIR)/os-$(OS)/util
        @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
                -o -name '*.gcov' \) -type f -print | xargs rm -f
 
@@ -180,9 +171,7 @@ $(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
+       $(Q)ln -fsn $(srctree)/$(ARCH_DIR)/include/sysdep-$(SUBARCH) $(ARCH_DIR)/include/sysdep
 else
        $(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
 endif
@@ -202,8 +191,6 @@ endef
 
 define filechk_gen-asm-offsets
         (set -e; \
-         echo "#ifndef __ASM_OFFSETS_H__"; \
-         echo "#define __ASM_OFFSETS_H__"; \
          echo "/*"; \
          echo " * DO NOT MODIFY."; \
          echo " *"; \
@@ -212,8 +199,7 @@ define filechk_gen-asm-offsets
          echo " */"; \
          echo ""; \
          sed -ne "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; \
-         echo ""; \
-         echo "#endif" )
+         echo ""; )
 endef
 
 $(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
@@ -222,50 +208,18 @@ $(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
 $(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
+$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s
        $(call filechk,gen-asm-offsets)
 
-CLEAN_FILES += $(ARCH_DIR)/user-offsets.s  $(ARCH_DIR)/user-offsets.h
+CLEAN_FILES += $(ARCH_DIR)/user-offsets.s
 
 $(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
+                                  archprepare
        $(CC) $(CFLAGS) $(NOSTDINC_FLAGS) $(CPPFLAGS) -S -o $@ $<
 
-$(ARCH_DIR)/kernel-offsets.h: $(ARCH_DIR)/kernel-offsets.s
+$(ARCH_DIR)/include/kern_constants.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-$(OS)/util/mk_user_constants
-       $(call filechk,gen_header)
-
-$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants
-       $(call filechk,gen_header)
-
-$(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs
-       $(call filechk,gen_header)
-
-$(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 $(ARCH_DIR)/kernel-offsets.h FORCE
-       $(Q)$(MAKE) $(build)=$@
-
-$(ARCH_DIR)/kernel/skas/util: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
-       $(Q)$(MAKE) $(build)=$@
-
-$(ARCH_DIR)/os-$(OS)/util: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE
-       $(Q)$(MAKE) $(build)=$@
+CLEAN_FILES += $(ARCH_DIR)/kernel-offsets.s
 
 export SUBARCH USER_CFLAGS OS
index 1ab431a53ac3d0cc3eb336d5d1c07a996e7ab554..2ee8a2858117357f3ae2fdc1412ff42fe633cedc 100644 (file)
@@ -32,25 +32,3 @@ CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
 ifneq ($(CONFIG_GPROF),y)
 ARCH_CFLAGS += -DUM_FASTCALL
 endif
-
-SYS_UTIL_DIR   := $(ARCH_DIR)/sys-i386/util
-SYS_HEADERS    := $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
-
-prepare: $(SYS_HEADERS)
-
-$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
-       $(call filechk,gen_header)
-
-$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread 
-       $(call filechk,gen_header)
-
-$(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_DIR)/kernel-offsets.h FORCE
-       $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
-
-$(SYS_UTIL_DIR): scripts_basic include/asm FORCE
-       $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR)
-
-CLEAN_FILES += $(SYS_HEADERS)
index fd18ec572271b80fd96e446edaebca889b848484..ac35de5316a6a547d4c8293b61387ddbae546476 100644 (file)
@@ -10,5 +10,3 @@ CFLAGS-$(CONFIG_GCOV) += $(GCOV_OPT)
 CFLAGS-$(CONFIG_GPROF) += $(GPROF_OPT)
 LINK-$(CONFIG_GCOV) += $(GCOV_OPT)
 LINK-$(CONFIG_GPROF) += $(GPROF_OPT)
-
-GEN_HEADERS += $(ARCH_DIR)/include/skas_ptregs.h
index 436abbba409bd3e1a9516239022ba3f6ecffabd1..4f118d5cc2ee177c381b3b3d2522071f76025498 100644 (file)
@@ -12,24 +12,3 @@ CHECKFLAGS  += -m64
 
 ELF_ARCH := i386:x86-64
 ELF_FORMAT := elf64-x86-64
-
-SYS_UTIL_DIR := $(ARCH_DIR)/sys-x86_64/util
-SYS_DIR := $(ARCH_DIR)/include/sysdep-x86_64
-
-SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
-
-prepare: $(SYS_HEADERS)
-
-$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
-       $(call filechk,gen_header)
-
-$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
-       $(call filechk,gen_header)
-
-$(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 $(GEN_HEADERS) $(ARCH_DIR)/kernel-offsets.h FORCE
-       $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
-
-CLEAN_FILES += $(SYS_HEADERS)
index 04383f98f4d5ff9258109941ac19cfe387907778..310c1f823f26713eb9a4d6689fd20d504b8e6fb2 100644 (file)
@@ -23,7 +23,7 @@ static struct mconsole_command commands[] = {
        { "reboot", mconsole_reboot, MCONSOLE_PROC },
        { "config", mconsole_config, MCONSOLE_PROC },
        { "remove", mconsole_remove, MCONSOLE_PROC },
-       { "sysrq", mconsole_sysrq, MCONSOLE_PROC },
+       { "sysrq", mconsole_sysrq, MCONSOLE_INTR },
        { "help", mconsole_help, MCONSOLE_INTR },
        { "cad", mconsole_cad, MCONSOLE_INTR },
        { "stop", mconsole_stop, MCONSOLE_PROC },
index c41efd207fcc23b33cf35b09edd94d1c841893c8..189839e4f1d4eae532241945c8bbe70b2d9aa989 100644 (file)
@@ -7,7 +7,6 @@
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/interrupt.h"
-#include "linux/irq.h"
 #include "linux/spinlock.h"
 #include "linux/errno.h"
 #include "asm/atomic.h"
index 782ac3a3baf98bd82fc16f9c176a64d323d553aa..356390d1f8b945dbedbb3ce11475fdb309b95926 100644 (file)
@@ -1,7 +1,7 @@
 /* for use by sys-$SUBARCH/kernel-offsets.c */
 
-OFFSET(TASK_REGS, task_struct, thread.regs);
-OFFSET(TASK_PID, task_struct, pid);
+OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
+OFFSET(HOST_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);
index 583329d0a539a012196b2fe0e72e68926865d127..6f766e1faeccd1bd806ddeb09546002c7e898d31 100644 (file)
@@ -157,6 +157,10 @@ extern int os_lock_file(int fd, int excl);
 extern void os_early_checks(void);
 extern int can_do_skas(void);
 
+/* Make sure they are clear when running in TT mode. Required by
+ * SEGV_MAYBE_FIXABLE */
+#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
+
 /* mem.c */
 extern int create_mem_file(unsigned long len);
 
diff --git a/arch/um/include/skas_ptregs.h b/arch/um/include/skas_ptregs.h
new file mode 100644 (file)
index 0000000..73db19e
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __SKAS_PT_REGS_
+#define __SKAS_PT_REGS_
+
+#include <user_constants.h>
+
+#endif
diff --git a/arch/um/include/sysdep-i386/sc.h b/arch/um/include/sysdep-i386/sc.h
new file mode 100644 (file)
index 0000000..c57d178
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __SYSDEP_I386_SC_H
+#define __SYSDEP_I386_SC_H
+
+#include <user_constants.h>
+
+#define SC_OFFSET(sc, field) \
+       *((unsigned long *) &(((char *) (sc))[HOST_##field]))
+#define SC_FP_OFFSET(sc, field) \
+       *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field]))
+#define SC_FP_OFFSET_PTR(sc, field, type) \
+       ((type *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field]))
+
+#define SC_IP(sc) SC_OFFSET(sc, SC_IP)
+#define SC_SP(sc) SC_OFFSET(sc, SC_SP)
+#define SC_FS(sc) SC_OFFSET(sc, SC_FS)
+#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
+#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
+#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
+#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
+#define SC_CS(sc) SC_OFFSET(sc, SC_CS)
+#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
+#define SC_EAX(sc) SC_OFFSET(sc, SC_EAX)
+#define SC_EBX(sc) SC_OFFSET(sc, SC_EBX)
+#define SC_ECX(sc) SC_OFFSET(sc, SC_ECX)
+#define SC_EDX(sc) SC_OFFSET(sc, SC_EDX)
+#define SC_EDI(sc) SC_OFFSET(sc, SC_EDI)
+#define SC_ESI(sc) SC_OFFSET(sc, SC_ESI)
+#define SC_EBP(sc) SC_OFFSET(sc, SC_EBP)
+#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO)
+#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR)
+#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2)
+#define SC_FPSTATE(sc) SC_OFFSET(sc, SC_FPSTATE)
+#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
+#define SC_FP_CW(sc) SC_FP_OFFSET(sc, SC_FP_CW)
+#define SC_FP_SW(sc) SC_FP_OFFSET(sc, SC_FP_SW)
+#define SC_FP_TAG(sc) SC_FP_OFFSET(sc, SC_FP_TAG)
+#define SC_FP_IPOFF(sc) SC_FP_OFFSET(sc, SC_FP_IPOFF)
+#define SC_FP_CSSEL(sc) SC_FP_OFFSET(sc, SC_FP_CSSEL)
+#define SC_FP_DATAOFF(sc) SC_FP_OFFSET(sc, SC_FP_DATAOFF)
+#define SC_FP_DATASEL(sc) SC_FP_OFFSET(sc, SC_FP_DATASEL)
+#define SC_FP_ST(sc) SC_FP_OFFSET_PTR(sc, SC_FP_ST, struct _fpstate)
+#define SC_FXSR_ENV(sc) SC_FP_OFFSET_PTR(sc, SC_FXSR_ENV, void)
+
+#endif
index 1fe729265167ad6cfc796cd30957e5ffcff09aa8..23fd2644d7edf596511ebae83b7f6c498f8ed40a 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef __SYS_SIGCONTEXT_I386_H
 #define __SYS_SIGCONTEXT_I386_H
 
+#include "uml-config.h"
 #include <sysdep/sc.h>
 
 #define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
 #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
 
 /* This is Page Fault */
-#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
+#define SEGV_IS_FIXABLE(fi)    ((fi)->trap_no == 14)
+
+/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
+#ifdef UML_CONFIG_MODE_SKAS
+#define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo)
+#else
+#define SEGV_MAYBE_FIXABLE(fi) 0
+#endif
 
 extern unsigned long *sc_sigmask(void *sc_ptr);
 extern int sc_get_fpregs(unsigned long buf, void *sc_ptr);
diff --git a/arch/um/include/sysdep-i386/thread.h b/arch/um/include/sysdep-i386/thread.h
new file mode 100644 (file)
index 0000000..e2bd6ba
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __UM_THREAD_H
+#define __UM_THREAD_H
+
+#include <kern_constants.h>
+
+#define TASK_DEBUGREGS(task) ((unsigned long *) &(((char *) (task))[HOST_TASK_DEBUGREGS]))
+#ifdef CONFIG_MODE_TT
+#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID]))
+#endif
+
+#endif
diff --git a/arch/um/include/sysdep-x86_64/sc.h b/arch/um/include/sysdep-x86_64/sc.h
new file mode 100644 (file)
index 0000000..a160d9f
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __SYSDEP_X86_64_SC_H
+#define __SYSDEP_X86_64_SC_H
+
+/* Copyright (C) 2003 - 2004 PathScale, Inc
+ * Released under the GPL
+ */
+
+#include <user_constants.h>
+
+#define SC_OFFSET(sc, field) \
+        *((unsigned long *) &(((char *) (sc))[HOST_##field]))
+
+#define SC_RBX(sc) SC_OFFSET(sc, SC_RBX)
+#define SC_RCX(sc) SC_OFFSET(sc, SC_RCX)
+#define SC_RDX(sc) SC_OFFSET(sc, SC_RDX)
+#define SC_RSI(sc) SC_OFFSET(sc, SC_RSI)
+#define SC_RDI(sc) SC_OFFSET(sc, SC_RDI)
+#define SC_RBP(sc) SC_OFFSET(sc, SC_RBP)
+#define SC_RAX(sc) SC_OFFSET(sc, SC_RAX)
+#define SC_R8(sc) SC_OFFSET(sc, SC_R8)
+#define SC_R9(sc) SC_OFFSET(sc, SC_R9)
+#define SC_R10(sc) SC_OFFSET(sc, SC_R10)
+#define SC_R11(sc) SC_OFFSET(sc, SC_R11)
+#define SC_R12(sc) SC_OFFSET(sc, SC_R12)
+#define SC_R13(sc) SC_OFFSET(sc, SC_R13)
+#define SC_R14(sc) SC_OFFSET(sc, SC_R14)
+#define SC_R15(sc) SC_OFFSET(sc, SC_R15)
+#define SC_IP(sc) SC_OFFSET(sc, SC_IP)
+#define SC_SP(sc) SC_OFFSET(sc, SC_SP)
+#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2)
+#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR)
+#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO)
+#define SC_CS(sc) SC_OFFSET(sc, SC_CS)
+#define SC_FS(sc) SC_OFFSET(sc, SC_FS)
+#define SC_GS(sc) SC_OFFSET(sc, SC_GS)
+#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
+#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
+#if 0
+#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX)
+#define SC_DS(sc) SC_OFFSET(sc, SC_DS)
+#define SC_ES(sc) SC_OFFSET(sc, SC_ES)
+#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
+#endif
+
+#endif
index 2a78260d15a0d550cf348d4ad9ce7f8f58a12a47..41073235e7ad751efd8701998b9561eaa5cc6a3f 100644 (file)
 #define SC_START_SYSCALL(sc) do SC_RAX(sc) = -ENOSYS; while(0)
 
 /* This is Page Fault */
-#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14)
+#define SEGV_IS_FIXABLE(fi)    ((fi)->trap_no == 14)
+
+/* No broken SKAS API, which doesn't pass trap_no, here. */
+#define SEGV_MAYBE_FIXABLE(fi) 0
 
 extern unsigned long *sc_sigmask(void *sc_ptr);
 
diff --git a/arch/um/include/sysdep-x86_64/thread.h b/arch/um/include/sysdep-x86_64/thread.h
new file mode 100644 (file)
index 0000000..6a76a7f
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __UM_THREAD_H
+#define __UM_THREAD_H
+
+#include <kern_constants.h>
+
+#ifdef CONFIG_MODE_TT
+#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID]))
+#endif
+
+#endif
diff --git a/arch/um/include/task.h b/arch/um/include/task.h
new file mode 100644 (file)
index 0000000..6375ba7
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __TASK_H
+#define __TASK_H
+
+#include <kern_constants.h>
+
+#define TASK_REGS(task) ((union uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS]))
+#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID]))
+
+#endif
index dcd814971995ca858c2ce01667800437c65f43b9..bbf94bf2921ed144a6d70990152c1264b8361b33 100644 (file)
@@ -9,7 +9,6 @@
 #include "linux/kernel.h"
 #include "linux/module.h"
 #include "linux/smp.h"
-#include "linux/irq.h"
 #include "linux/kernel_stat.h"
 #include "linux/interrupt.h"
 #include "linux/random.h"
index db36c7c9594070669c4d328f0221f10f10550ac6..8de471b59c1c8188c35887cd18280594c9dc33dc 100644 (file)
@@ -6,8 +6,6 @@
 obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
        syscall.o tlb.o trap_user.o uaccess.o
 
-subdir- := util
-
 USER_OBJS := process.o clone.o
 
 include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile
deleted file mode 100644 (file)
index f7b7eba..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-hostprogs-y            := mk_ptregs
-always                 := $(hostprogs-y)
-
-mk_ptregs-objs := mk_ptregs-$(SUBARCH).o
-HOSTCFLAGS_mk_ptregs-$(SUBARCH).o := -I$(objtree)/arch/um
diff --git a/arch/um/kernel/skas/util/mk_ptregs-i386.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c
deleted file mode 100644 (file)
index 1f96e1e..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#include <stdio.h>
-#include <user-offsets.h>
-
-#define SHOW(name) printf("#define %s %d\n", #name, name)
-
-int main(int argc, char **argv)
-{
-       printf("/* Automatically generated by "
-              "arch/um/kernel/skas/util/mk_ptregs */\n");
-       printf("\n");
-       printf("#ifndef __SKAS_PT_REGS_\n");
-       printf("#define __SKAS_PT_REGS_\n");
-       printf("\n");
-       SHOW(HOST_FRAME_SIZE);
-       SHOW(HOST_FP_SIZE);
-       SHOW(HOST_XFP_SIZE);
-
-       SHOW(HOST_IP);
-       SHOW(HOST_SP);
-       SHOW(HOST_EFLAGS);
-       SHOW(HOST_EAX);
-       SHOW(HOST_EBX);
-       SHOW(HOST_ECX);
-       SHOW(HOST_EDX);
-       SHOW(HOST_ESI);
-       SHOW(HOST_EDI);
-       SHOW(HOST_EBP);
-       SHOW(HOST_CS);
-       SHOW(HOST_SS);
-       SHOW(HOST_DS);
-       SHOW(HOST_FS);
-       SHOW(HOST_ES);
-       SHOW(HOST_GS);
-
-       printf("\n");
-       printf("#endif\n");
-       return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c
deleted file mode 100644 (file)
index 5fccbfe..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2003 PathScale, Inc.
- *
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <user-offsets.h>
-
-#define SHOW(name) \
-       printf("#define %s (%d / sizeof(unsigned long))\n", #name, name)
-
-int main(int argc, char **argv)
-{
-       printf("/* Automatically generated by "
-              "arch/um/kernel/skas/util/mk_ptregs */\n");
-       printf("\n");
-       printf("#ifndef __SKAS_PT_REGS_\n");
-       printf("#define __SKAS_PT_REGS_\n");
-       SHOW(HOST_FRAME_SIZE);
-       SHOW(HOST_RBX);
-       SHOW(HOST_RCX);
-       SHOW(HOST_RDI);
-       SHOW(HOST_RSI);
-       SHOW(HOST_RDX);
-       SHOW(HOST_RBP);
-       SHOW(HOST_RAX);
-       SHOW(HOST_R8);
-       SHOW(HOST_R9);
-       SHOW(HOST_R10);
-       SHOW(HOST_R11);
-       SHOW(HOST_R12);
-       SHOW(HOST_R13);
-       SHOW(HOST_R14);
-       SHOW(HOST_R15);
-       SHOW(HOST_ORIG_RAX);
-       SHOW(HOST_CS);
-       SHOW(HOST_SS);
-       SHOW(HOST_EFLAGS);
-#if 0
-       SHOW(HOST_FS);
-       SHOW(HOST_GS);
-       SHOW(HOST_DS);
-       SHOW(HOST_ES);
-#endif
-
-       SHOW(HOST_IP);
-       SHOW(HOST_SP);
-       printf("#define HOST_FP_SIZE 0\n");
-       printf("#define HOST_XFP_SIZE 0\n");
-       printf("\n");
-       printf("\n");
-       printf("#endif\n");
-       return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index d297429ac3605613511356fd355bf596b683c2f5..95c8f8733bafb516e67d044d6d78a87779a46c98 100644 (file)
@@ -26,6 +26,9 @@
 #include "mconsole_kern.h"
 #include "mem.h"
 #include "mem_kern.h"
+#ifdef CONFIG_MODE_SKAS
+#include "skas.h"
+#endif
 
 /* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
 int handle_page_fault(unsigned long address, unsigned long ip, 
@@ -134,7 +137,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
        else if(current->mm == NULL)
                panic("Segfault with no mm");
 
-       if (SEGV_IS_FIXABLE(&fi))
+       if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi))
                err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
        else {
                err = -EFAULT;
index f0a275947d34b18dea67b432c1543c054738d35f..93dc782dc1cc8f5d790b2151694c4caf757238d0 100644 (file)
@@ -334,6 +334,8 @@ int linux_main(int argc, char **argv)
                add_arg(DEFAULT_COMMAND_LINE);
 
        os_early_checks();
+       if (force_tt)
+               clear_can_do_skas();
        mode_tt = force_tt ? 1 : !can_do_skas();
 #ifndef CONFIG_MODE_TT
        if (mode_tt) {
index ab33cb3c74ec26e5ba282067cb701a741cfab5ca..5a99dd3fbed0477bb7443eba1324e70f0dc4bcf4 100644 (file)
@@ -12,7 +12,7 @@
 #include "init.h"
 #include "elf_user.h"
 #include "mem_user.h"
-#include <kernel-offsets.h>
+#include <kern_constants.h>
 
 /* Use the one from the kernel - the host may miss it, if having old headers. */
 #if UM_ELF_CLASS == UM_ELFCLASS32
diff --git a/arch/um/os-Linux/util/Makefile b/arch/um/os-Linux/util/Makefile
deleted file mode 100644 (file)
index 9778aed..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-hostprogs-y            := mk_user_constants
-always                 := $(hostprogs-y)
-
-HOSTCFLAGS_mk_user_constants.o := -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/util/mk_user_constants.c b/arch/um/os-Linux/util/mk_user_constants.c
deleted file mode 100644 (file)
index 4838f30..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <stdio.h>
-#include <user-offsets.h>
-
-int main(int argc, char **argv)
-{
-  printf("/*\n");
-  printf(" * Generated by mk_user_constants\n");
-  printf(" */\n");
-  printf("\n");
-  printf("#ifndef __UM_USER_CONSTANTS_H\n");
-  printf("#define __UM_USER_CONSTANTS_H\n");
-  printf("\n");
-  /* I'd like to use FRAME_SIZE from ptrace.h here, but that's wrong on
-   * x86_64 (216 vs 168 bytes).  user_regs_struct is the correct size on
-   * both x86_64 and i386.
-   */
-  printf("#define UM_FRAME_SIZE %d\n", __UM_FRAME_SIZE);
-
-  printf("\n");
-  printf("#endif\n");
-
-  return(0);
-}
index 4ca2a229da4997adebe0bc5f0425727bdda0e790..6dfeb70f6957727bf8a5a5c17fb8852599375ae2 100644 (file)
@@ -18,6 +18,4 @@ module.c-dir = kernel
 
 $(obj)/stub_segv.o : _c_flags = $(call unprofile,$(CFLAGS))
 
-subdir- := util
-
 include arch/um/scripts/Makefile.unmap
index a1070af2bcd823a1d2c580afbfb1c156b14242f5..35db850575066e5a34125f674d0257e98a24f8ee 100644 (file)
@@ -18,9 +18,9 @@
 
 void foo(void)
 {
-       OFFSET(TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
+       OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
 #ifdef CONFIG_MODE_TT
-       OFFSET(TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
+       OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
 #endif
 #include <common-offsets.h>
 }
index 3ceaabceb3d71f301afea622ba4f796532727e70..677fc26a9bbecd730d063204ab92b09f480ad6a3 100644 (file)
@@ -7,47 +7,48 @@
 #define DEFINE(sym, val) \
         asm volatile("\n->" #sym " %0 " #val : : "i" (val))
 
+#define DEFINE_LONGS(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
+
 #define OFFSET(sym, str, mem) \
        DEFINE(sym, offsetof(struct str, mem));
 
 void foo(void)
 {
-       OFFSET(SC_IP, sigcontext, eip);
-       OFFSET(SC_SP, sigcontext, esp);
-       OFFSET(SC_FS, sigcontext, fs);
-       OFFSET(SC_GS, sigcontext, gs);
-       OFFSET(SC_DS, sigcontext, ds);
-       OFFSET(SC_ES, sigcontext, es);
-       OFFSET(SC_SS, sigcontext, ss);
-       OFFSET(SC_CS, sigcontext, cs);
-       OFFSET(SC_EFLAGS, sigcontext, eflags);
-       OFFSET(SC_EAX, sigcontext, eax);
-       OFFSET(SC_EBX, sigcontext, ebx);
-       OFFSET(SC_ECX, sigcontext, ecx);
-       OFFSET(SC_EDX, sigcontext, edx);
-       OFFSET(SC_EDI, sigcontext, edi);
-       OFFSET(SC_ESI, sigcontext, esi);
-       OFFSET(SC_EBP, sigcontext, ebp);
-       OFFSET(SC_TRAPNO, sigcontext, trapno);
-       OFFSET(SC_ERR, sigcontext, err);
-       OFFSET(SC_CR2, sigcontext, cr2);
-       OFFSET(SC_FPSTATE, sigcontext, fpstate);
-       OFFSET(SC_SIGMASK, sigcontext, oldmask);
-       OFFSET(SC_FP_CW, _fpstate, cw);
-       OFFSET(SC_FP_SW, _fpstate, sw);
-       OFFSET(SC_FP_TAG, _fpstate, tag);
-       OFFSET(SC_FP_IPOFF, _fpstate, ipoff);
-       OFFSET(SC_FP_CSSEL, _fpstate, cssel);
-       OFFSET(SC_FP_DATAOFF, _fpstate, dataoff);
-       OFFSET(SC_FP_DATASEL, _fpstate, datasel);
-       OFFSET(SC_FP_ST, _fpstate, _st);
-       OFFSET(SC_FXSR_ENV, _fpstate, _fxsr_env);
+       OFFSET(HOST_SC_IP, sigcontext, eip);
+       OFFSET(HOST_SC_SP, sigcontext, esp);
+       OFFSET(HOST_SC_FS, sigcontext, fs);
+       OFFSET(HOST_SC_GS, sigcontext, gs);
+       OFFSET(HOST_SC_DS, sigcontext, ds);
+       OFFSET(HOST_SC_ES, sigcontext, es);
+       OFFSET(HOST_SC_SS, sigcontext, ss);
+       OFFSET(HOST_SC_CS, sigcontext, cs);
+       OFFSET(HOST_SC_EFLAGS, sigcontext, eflags);
+       OFFSET(HOST_SC_EAX, sigcontext, eax);
+       OFFSET(HOST_SC_EBX, sigcontext, ebx);
+       OFFSET(HOST_SC_ECX, sigcontext, ecx);
+       OFFSET(HOST_SC_EDX, sigcontext, edx);
+       OFFSET(HOST_SC_EDI, sigcontext, edi);
+       OFFSET(HOST_SC_ESI, sigcontext, esi);
+       OFFSET(HOST_SC_EBP, sigcontext, ebp);
+       OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
+       OFFSET(HOST_SC_ERR, sigcontext, err);
+       OFFSET(HOST_SC_CR2, sigcontext, cr2);
+       OFFSET(HOST_SC_FPSTATE, sigcontext, fpstate);
+       OFFSET(HOST_SC_SIGMASK, sigcontext, oldmask);
+       OFFSET(HOST_SC_FP_CW, _fpstate, cw);
+       OFFSET(HOST_SC_FP_SW, _fpstate, sw);
+       OFFSET(HOST_SC_FP_TAG, _fpstate, tag);
+       OFFSET(HOST_SC_FP_IPOFF, _fpstate, ipoff);
+       OFFSET(HOST_SC_FP_CSSEL, _fpstate, cssel);
+       OFFSET(HOST_SC_FP_DATAOFF, _fpstate, dataoff);
+       OFFSET(HOST_SC_FP_DATASEL, _fpstate, datasel);
+       OFFSET(HOST_SC_FP_ST, _fpstate, _st);
+       OFFSET(HOST_SC_FXSR_ENV, _fpstate, _fxsr_env);
 
-       DEFINE(HOST_FRAME_SIZE, FRAME_SIZE);
-       DEFINE(HOST_FP_SIZE,
-               sizeof(struct user_i387_struct) / sizeof(unsigned long));
-       DEFINE(HOST_XFP_SIZE,
-              sizeof(struct user_fxsr_struct) / sizeof(unsigned long));
+       DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE);
+       DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_i387_struct));
+       DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fxsr_struct));
 
        DEFINE(HOST_IP, EIP);
        DEFINE(HOST_SP, UESP);
@@ -65,5 +66,5 @@ void foo(void)
        DEFINE(HOST_FS, FS);
        DEFINE(HOST_ES, ES);
        DEFINE(HOST_GS, GS);
-       DEFINE(__UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+       DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
 }
diff --git a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile
deleted file mode 100644 (file)
index bf61afd..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-hostprogs-y    := mk_sc mk_thread
-always         := $(hostprogs-y)
-
-HOSTCFLAGS_mk_sc.o := -I$(objtree)/arch/um
-HOSTCFLAGS_mk_thread.o := -I$(objtree)/arch/um
diff --git a/arch/um/sys-i386/util/mk_sc.c b/arch/um/sys-i386/util/mk_sc.c
deleted file mode 100644 (file)
index 04c0d73..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#include <stdio.h>
-#include <user-offsets.h>
-
-#define SC_OFFSET(name, field) \
-  printf("#define " #name "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\
-        name)
-
-#define SC_FP_OFFSET(name, field) \
-  printf("#define " #name \
-        "(sc) *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
-        name)
-
-#define SC_FP_OFFSET_PTR(name, field, type) \
-  printf("#define " #name \
-        "(sc) ((" type " *) &(((char *) (SC_FPSTATE(sc)))[%d]))\n",\
-        name)
-
-int main(int argc, char **argv)
-{
-  SC_OFFSET(SC_IP, eip);
-  SC_OFFSET(SC_SP, esp);
-  SC_OFFSET(SC_FS, fs);
-  SC_OFFSET(SC_GS, gs);
-  SC_OFFSET(SC_DS, ds);
-  SC_OFFSET(SC_ES, es);
-  SC_OFFSET(SC_SS, ss);
-  SC_OFFSET(SC_CS, cs);
-  SC_OFFSET(SC_EFLAGS, eflags);
-  SC_OFFSET(SC_EAX, eax);
-  SC_OFFSET(SC_EBX, ebx);
-  SC_OFFSET(SC_ECX, ecx);
-  SC_OFFSET(SC_EDX, edx);
-  SC_OFFSET(SC_EDI, edi);
-  SC_OFFSET(SC_ESI, esi);
-  SC_OFFSET(SC_EBP, ebp);
-  SC_OFFSET(SC_TRAPNO, trapno);
-  SC_OFFSET(SC_ERR, err);
-  SC_OFFSET(SC_CR2, cr2);
-  SC_OFFSET(SC_FPSTATE, fpstate);
-  SC_OFFSET(SC_SIGMASK, oldmask);
-  SC_FP_OFFSET(SC_FP_CW, cw);
-  SC_FP_OFFSET(SC_FP_SW, sw);
-  SC_FP_OFFSET(SC_FP_TAG, tag);
-  SC_FP_OFFSET(SC_FP_IPOFF, ipoff);
-  SC_FP_OFFSET(SC_FP_CSSEL, cssel);
-  SC_FP_OFFSET(SC_FP_DATAOFF, dataoff);
-  SC_FP_OFFSET(SC_FP_DATASEL, datasel);
-  SC_FP_OFFSET_PTR(SC_FP_ST, _st, "struct _fpstate");
-  SC_FP_OFFSET_PTR(SC_FXSR_ENV, _fxsr_env, "void");
-  return(0);
-}
diff --git a/arch/um/sys-i386/util/mk_thread.c b/arch/um/sys-i386/util/mk_thread.c
deleted file mode 100644 (file)
index 7470d0d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <stdio.h>
-#include <kernel-offsets.h>
-
-int main(int argc, char **argv)
-{
-  printf("/*\n");
-  printf(" * Generated by mk_thread\n");
-  printf(" */\n");
-  printf("\n");
-  printf("#ifndef __UM_THREAD_H\n");
-  printf("#define __UM_THREAD_H\n");
-  printf("\n");
-  printf("#define TASK_DEBUGREGS(task) ((unsigned long *) "
-        "&(((char *) (task))[%d]))\n", TASK_DEBUGREGS);
-#ifdef TASK_EXTERN_PID
-  printf("#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[%d]))\n",
-        TASK_EXTERN_PID);
-#endif
-  printf("\n");
-  printf("#endif\n");
-  return(0);
-}
index f0ab574d1e95b6bc64a583e3ac1e6ac42ede4f03..06c3633457a2b28a9a6ad8b69dc523bb60d3ced9 100644 (file)
@@ -29,6 +29,4 @@ module.c-dir = kernel
 
 $(obj)/stub_segv.o: _c_flags = $(call unprofile,$(CFLAGS))
 
-subdir- := util
-
 include arch/um/scripts/Makefile.unmap
index 998541eade41e0cd80f16cfc0a9de8835dd8467e..bfcb104b846ee8731d3a73f1df5e09a56fcb4fb5 100644 (file)
@@ -19,7 +19,7 @@
 void foo(void)
 {
 #ifdef CONFIG_MODE_TT
-       OFFSET(TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
+       OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
 #endif
 #include <common-offsets.h>
 }
index 513d17ceafd4de4cad8a5f722837347eb038af53..5a585bfbb8c2148101f1195be7b70cdf6f054e5b 100644 (file)
@@ -16,71 +16,76 @@ typedef __u32 u32;
 #define DEFINE(sym, val) \
         asm volatile("\n->" #sym " %0 " #val : : "i" (val))
 
+#define DEFINE_LONGS(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long)))
+
 #define OFFSET(sym, str, mem) \
        DEFINE(sym, offsetof(struct str, mem));
 
 void foo(void)
 {
-       OFFSET(SC_RBX, sigcontext, rbx);
-       OFFSET(SC_RCX, sigcontext, rcx);
-       OFFSET(SC_RDX, sigcontext, rdx);
-       OFFSET(SC_RSI, sigcontext, rsi);
-       OFFSET(SC_RDI, sigcontext, rdi);
-       OFFSET(SC_RBP, sigcontext, rbp);
-       OFFSET(SC_RAX, sigcontext, rax);
-       OFFSET(SC_R8, sigcontext, r8);
-       OFFSET(SC_R9, sigcontext, r9);
-       OFFSET(SC_R10, sigcontext, r10);
-       OFFSET(SC_R11, sigcontext, r11);
-       OFFSET(SC_R12, sigcontext, r12);
-       OFFSET(SC_R13, sigcontext, r13);
-       OFFSET(SC_R14, sigcontext, r14);
-       OFFSET(SC_R15, sigcontext, r15);
-       OFFSET(SC_IP, sigcontext, rip);
-       OFFSET(SC_SP, sigcontext, rsp);
-       OFFSET(SC_CR2, sigcontext, cr2);
-       OFFSET(SC_ERR, sigcontext, err);
-       OFFSET(SC_TRAPNO, sigcontext, trapno);
-       OFFSET(SC_CS, sigcontext, cs);
-       OFFSET(SC_FS, sigcontext, fs);
-       OFFSET(SC_GS, sigcontext, gs);
-       OFFSET(SC_EFLAGS, sigcontext, eflags);
-       OFFSET(SC_SIGMASK, sigcontext, oldmask);
+       OFFSET(HOST_SC_RBX, sigcontext, rbx);
+       OFFSET(HOST_SC_RCX, sigcontext, rcx);
+       OFFSET(HOST_SC_RDX, sigcontext, rdx);
+       OFFSET(HOST_SC_RSI, sigcontext, rsi);
+       OFFSET(HOST_SC_RDI, sigcontext, rdi);
+       OFFSET(HOST_SC_RBP, sigcontext, rbp);
+       OFFSET(HOST_SC_RAX, sigcontext, rax);
+       OFFSET(HOST_SC_R8, sigcontext, r8);
+       OFFSET(HOST_SC_R9, sigcontext, r9);
+       OFFSET(HOST_SC_R10, sigcontext, r10);
+       OFFSET(HOST_SC_R11, sigcontext, r11);
+       OFFSET(HOST_SC_R12, sigcontext, r12);
+       OFFSET(HOST_SC_R13, sigcontext, r13);
+       OFFSET(HOST_SC_R14, sigcontext, r14);
+       OFFSET(HOST_SC_R15, sigcontext, r15);
+       OFFSET(HOST_SC_IP, sigcontext, rip);
+       OFFSET(HOST_SC_SP, sigcontext, rsp);
+       OFFSET(HOST_SC_CR2, sigcontext, cr2);
+       OFFSET(HOST_SC_ERR, sigcontext, err);
+       OFFSET(HOST_SC_TRAPNO, sigcontext, trapno);
+       OFFSET(HOST_SC_CS, sigcontext, cs);
+       OFFSET(HOST_SC_FS, sigcontext, fs);
+       OFFSET(HOST_SC_GS, sigcontext, gs);
+       OFFSET(HOST_SC_EFLAGS, sigcontext, eflags);
+       OFFSET(HOST_SC_SIGMASK, sigcontext, oldmask);
 #if 0
-       OFFSET(SC_ORIG_RAX, sigcontext, orig_rax);
-       OFFSET(SC_DS, sigcontext, ds);
-       OFFSET(SC_ES, sigcontext, es);
-       OFFSET(SC_SS, sigcontext, ss);
+       OFFSET(HOST_SC_ORIG_RAX, sigcontext, orig_rax);
+       OFFSET(HOST_SC_DS, sigcontext, ds);
+       OFFSET(HOST_SC_ES, sigcontext, es);
+       OFFSET(HOST_SC_SS, sigcontext, ss);
 #endif
 
-       DEFINE(HOST_FRAME_SIZE, FRAME_SIZE);
-       DEFINE(HOST_RBX, RBX);
-       DEFINE(HOST_RCX, RCX);
-       DEFINE(HOST_RDI, RDI);
-       DEFINE(HOST_RSI, RSI);
-       DEFINE(HOST_RDX, RDX);
-       DEFINE(HOST_RBP, RBP);
-       DEFINE(HOST_RAX, RAX);
-       DEFINE(HOST_R8, R8);
-       DEFINE(HOST_R9, R9);
-       DEFINE(HOST_R10, R10);
-       DEFINE(HOST_R11, R11);
-       DEFINE(HOST_R12, R12);
-       DEFINE(HOST_R13, R13);
-       DEFINE(HOST_R14, R14);
-       DEFINE(HOST_R15, R15);
-       DEFINE(HOST_ORIG_RAX, ORIG_RAX);
-       DEFINE(HOST_CS, CS);
-       DEFINE(HOST_SS, SS);
-       DEFINE(HOST_EFLAGS, EFLAGS);
+       DEFINE_LONGS(HOST_FRAME_SIZE, FRAME_SIZE);
+       DEFINE(HOST_FP_SIZE, 0);
+       DEFINE(HOST_XFP_SIZE, 0);
+       DEFINE_LONGS(HOST_RBX, RBX);
+       DEFINE_LONGS(HOST_RCX, RCX);
+       DEFINE_LONGS(HOST_RDI, RDI);
+       DEFINE_LONGS(HOST_RSI, RSI);
+       DEFINE_LONGS(HOST_RDX, RDX);
+       DEFINE_LONGS(HOST_RBP, RBP);
+       DEFINE_LONGS(HOST_RAX, RAX);
+       DEFINE_LONGS(HOST_R8, R8);
+       DEFINE_LONGS(HOST_R9, R9);
+       DEFINE_LONGS(HOST_R10, R10);
+       DEFINE_LONGS(HOST_R11, R11);
+       DEFINE_LONGS(HOST_R12, R12);
+       DEFINE_LONGS(HOST_R13, R13);
+       DEFINE_LONGS(HOST_R14, R14);
+       DEFINE_LONGS(HOST_R15, R15);
+       DEFINE_LONGS(HOST_ORIG_RAX, ORIG_RAX);
+       DEFINE_LONGS(HOST_CS, CS);
+       DEFINE_LONGS(HOST_SS, SS);
+       DEFINE_LONGS(HOST_EFLAGS, EFLAGS);
 #if 0
-       DEFINE(HOST_FS, FS);
-       DEFINE(HOST_GS, GS);
-       DEFINE(HOST_DS, DS);
-       DEFINE(HOST_ES, ES);
+       DEFINE_LONGS(HOST_FS, FS);
+       DEFINE_LONGS(HOST_GS, GS);
+       DEFINE_LONGS(HOST_DS, DS);
+       DEFINE_LONGS(HOST_ES, ES);
 #endif
 
-       DEFINE(HOST_IP, RIP);
-       DEFINE(HOST_SP, RSP);
-       DEFINE(__UM_FRAME_SIZE, sizeof(struct user_regs_struct));
+       DEFINE_LONGS(HOST_IP, RIP);
+       DEFINE_LONGS(HOST_SP, RSP);
+       DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct));
 }
diff --git a/arch/um/sys-x86_64/util/Makefile b/arch/um/sys-x86_64/util/Makefile
deleted file mode 100644 (file)
index 75b052c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright 2003 - 2004 Pathscale, Inc
-# Released under the GPL
-
-hostprogs-y    := mk_sc mk_thread
-always         := $(hostprogs-y)
-
-HOSTCFLAGS_mk_sc.o := -I$(objtree)/arch/um
-HOSTCFLAGS_mk_thread.o := -I$(objtree)/arch/um
diff --git a/arch/um/sys-x86_64/util/mk_sc.c b/arch/um/sys-x86_64/util/mk_sc.c
deleted file mode 100644 (file)
index 7619bc3..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright (C) 2003 - 2004 PathScale, Inc
- * Released under the GPL
- */
-
-#include <stdio.h>
-#include <user-offsets.h>
-
-#define SC_OFFSET(name) \
-  printf("#define " #name \
-        "(sc) *((unsigned long *) &(((char *) (sc))[%d]))\n",\
-        name)
-
-int main(int argc, char **argv)
-{
-  SC_OFFSET(SC_RBX);
-  SC_OFFSET(SC_RCX);
-  SC_OFFSET(SC_RDX);
-  SC_OFFSET(SC_RSI);
-  SC_OFFSET(SC_RDI);
-  SC_OFFSET(SC_RBP);
-  SC_OFFSET(SC_RAX);
-  SC_OFFSET(SC_R8);
-  SC_OFFSET(SC_R9);
-  SC_OFFSET(SC_R10);
-  SC_OFFSET(SC_R11);
-  SC_OFFSET(SC_R12);
-  SC_OFFSET(SC_R13);
-  SC_OFFSET(SC_R14);
-  SC_OFFSET(SC_R15);
-  SC_OFFSET(SC_IP);
-  SC_OFFSET(SC_SP);
-  SC_OFFSET(SC_CR2);
-  SC_OFFSET(SC_ERR);
-  SC_OFFSET(SC_TRAPNO);
-  SC_OFFSET(SC_CS);
-  SC_OFFSET(SC_FS);
-  SC_OFFSET(SC_GS);
-  SC_OFFSET(SC_EFLAGS);
-  SC_OFFSET(SC_SIGMASK);
-#if 0
-  SC_OFFSET(SC_ORIG_RAX);
-  SC_OFFSET(SC_DS);
-  SC_OFFSET(SC_ES);
-  SC_OFFSET(SC_SS);
-#endif
-  return(0);
-}
diff --git a/arch/um/sys-x86_64/util/mk_thread.c b/arch/um/sys-x86_64/util/mk_thread.c
deleted file mode 100644 (file)
index 1551739..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <stdio.h>
-#include <kernel-offsets.h>
-
-int main(int argc, char **argv)
-{
-  printf("/*\n");
-  printf(" * Generated by mk_thread\n");
-  printf(" */\n");
-  printf("\n");
-  printf("#ifndef __UM_THREAD_H\n");
-  printf("#define __UM_THREAD_H\n");
-  printf("\n");
-#ifdef TASK_EXTERN_PID
-  printf("#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[%d]))\n",
-        TASK_EXTERN_PID);
-#endif
-  printf("\n");
-  printf("#endif\n");
-  return(0);
-}
diff --git a/arch/um/util/Makefile b/arch/um/util/Makefile
deleted file mode 100644 (file)
index 4c7551c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-hostprogs-y            := mk_task mk_constants
-always                 := $(hostprogs-y)
-
-HOSTCFLAGS_mk_task.o := -I$(objtree)/arch/um
-HOSTCFLAGS_mk_constants.o := -I$(objtree)/arch/um
diff --git a/arch/um/util/mk_constants.c b/arch/um/util/mk_constants.c
deleted file mode 100644 (file)
index ab217be..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <stdio.h>
-#include <kernel-offsets.h>
-
-#define SHOW_INT(sym) printf("#define %s %d\n", #sym, sym)
-#define SHOW_STR(sym) printf("#define %s %s\n", #sym, sym)
-
-int main(int argc, char **argv)
-{
-  printf("/*\n");
-  printf(" * Generated by mk_constants\n");
-  printf(" */\n");
-  printf("\n");
-  printf("#ifndef __UM_CONSTANTS_H\n");
-  printf("#define __UM_CONSTANTS_H\n");
-  printf("\n");
-
-  SHOW_INT(UM_KERN_PAGE_SIZE);
-
-  SHOW_STR(UM_KERN_EMERG);
-  SHOW_STR(UM_KERN_ALERT);
-  SHOW_STR(UM_KERN_CRIT);
-  SHOW_STR(UM_KERN_ERR);
-  SHOW_STR(UM_KERN_WARNING);
-  SHOW_STR(UM_KERN_NOTICE);
-  SHOW_STR(UM_KERN_INFO);
-  SHOW_STR(UM_KERN_DEBUG);
-
-  SHOW_INT(UM_NSEC_PER_SEC);
-  printf("\n");
-  printf("#endif\n");
-  return(0);
-}
diff --git a/arch/um/util/mk_task.c b/arch/um/util/mk_task.c
deleted file mode 100644 (file)
index 36c9606..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#include <stdio.h>
-#include <kernel-offsets.h>
-
-void print_ptr(char *name, char *type, int offset)
-{
-  printf("#define %s(task) ((%s *) &(((char *) (task))[%d]))\n", name, type,
-        offset);
-}
-
-void print(char *name, char *type, int offset)
-{
-  printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
-        offset);
-}
-
-int main(int argc, char **argv)
-{
-  printf("/*\n");
-  printf(" * Generated by mk_task\n");
-  printf(" */\n");
-  printf("\n");
-  printf("#ifndef __TASK_H\n");
-  printf("#define __TASK_H\n");
-  printf("\n");
-  print_ptr("TASK_REGS", "union uml_pt_regs", TASK_REGS);
-  print("TASK_PID", "int", TASK_PID);
-  printf("\n");
-  printf("#endif\n");
-  return(0);
-}
index df08c43276a07fffee23a7dd7edf28feb92b2de7..76a28b007be95fcb17344fe48c7a1b93935a6bc0 100644 (file)
@@ -77,9 +77,9 @@ static inline int is_IF_modifier(kprobe_opcode_t *insn)
 int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
        /* insn: must be on special executable page on x86_64. */
-       up(&kprobe_mutex);
-       p->ainsn.insn = get_insn_slot();
        down(&kprobe_mutex);
+       p->ainsn.insn = get_insn_slot();
+       up(&kprobe_mutex);
        if (!p->ainsn.insn) {
                return -ENOMEM;
        }
@@ -231,9 +231,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-       up(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn);
        down(&kprobe_mutex);
+       free_insn_slot(p->ainsn.insn);
+       up(&kprobe_mutex);
 }
 
 static inline void save_previous_kprobe(void)
index 08203b07f4bd6d6c5aa26ddc9cedda58a29fda7f..69541db5ff2c46ae58d199ab3ed695fbf7165572 100644 (file)
@@ -54,9 +54,12 @@ void mce_log(struct mce *mce)
 {
        unsigned next, entry;
        mce->finished = 0;
-       smp_wmb();
+       wmb();
        for (;;) {
                entry = rcu_dereference(mcelog.next);
+               /* The rmb forces the compiler to reload next in each
+                   iteration */
+               rmb();
                for (;;) {
                        /* When the buffer fills up discard new entries. Assume
                           that the earlier errors are the more interesting. */
@@ -69,6 +72,7 @@ void mce_log(struct mce *mce)
                                entry++;
                                continue;
                        }
+                       break;
                }
                smp_rmb();
                next = entry + 1;
@@ -76,9 +80,9 @@ void mce_log(struct mce *mce)
                        break;
        }
        memcpy(mcelog.entry + entry, mce, sizeof(struct mce));
-       smp_wmb();
+       wmb();
        mcelog.entry[entry].finished = 1;
-       smp_wmb();
+       wmb();
 
        if (!test_and_set_bit(0, &console_logged))
                notify_user = 1;
index 238f73e1a834cc9b2fcb57b175416d091e6968f6..257f5ba17902c548d2910f04a3a580256a112f6b 100644 (file)
@@ -831,8 +831,6 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 #endif
 }
 
-#define HWCR 0xc0010015
-
 static int __init init_amd(struct cpuinfo_x86 *c)
 {
        int r;
@@ -841,14 +839,18 @@ static int __init init_amd(struct cpuinfo_x86 *c)
 #ifdef CONFIG_SMP
        unsigned long value;
 
-       // Disable TLB flush filter by setting HWCR.FFDIS:
-       // bit 6 of msr C001_0015
-       //
-       // Errata 63 for SH-B3 steppings
-       // Errata 122 for all(?) steppings
-       rdmsrl(HWCR, value);
-       value |= 1 << 6;
-       wrmsrl(HWCR, value);
+       /*
+        * Disable TLB flush filter by setting HWCR.FFDIS on K8
+        * bit 6 of msr C001_0015
+        *
+        * Errata 63 for SH-B3 steppings
+        * Errata 122 for all steppings (F+ have it disabled by default)
+        */
+       if (c->x86 == 15) {
+               rdmsrl(MSR_K8_HWCR, value);
+               value |= 1 << 6;
+               wrmsrl(MSR_K8_HWCR, value);
+       }
 #endif
 
        /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
index 2373cb8b86250744018a1ecdd48fc7b6da21248a..703acde2a1a58647978e48cc3b4a5cf216eabc0c 100644 (file)
@@ -959,9 +959,6 @@ static __init int unsynchronized_tsc(void)
           are handled in the OEM check above. */
        if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
                return 0;
-       /* All in a single socket - should be synchronized */
-       if (cpus_weight(cpu_core_map[0]) == num_online_cpus())
-               return 0;
 #endif
        /* Assume multi socket systems are not synchronized */
        return num_online_cpus() > 1;
index 80a49d9bd8a77941a89794b32eba75e0cc2490aa..2148038210017df1dbdbf4b286079cb4d3ce6a12 100644 (file)
@@ -167,18 +167,16 @@ void __init numa_init_array(void)
           mapping. To avoid this fill in the mapping for all possible
           CPUs, as the number of CPUs is not known yet. 
           We round robin the existing nodes. */
-       rr = 0;
+       rr = first_node(node_online_map);
        for (i = 0; i < NR_CPUS; i++) {
                if (cpu_to_node[i] != NUMA_NO_NODE)
                        continue;
+               cpu_to_node[i] = rr;
                rr = next_node(rr, node_online_map);
                if (rr == MAX_NUMNODES)
                        rr = first_node(node_online_map);
-               cpu_to_node[i] = rr;
-               rr++; 
        }
 
-       set_bit(0, &node_to_cpumask[cpu_to_node(0)]);
 }
 
 #ifdef CONFIG_NUMA_EMU
@@ -266,9 +264,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
 
 __cpuinit void numa_add_cpu(int cpu)
 {
-       /* BP is initialized elsewhere */
-       if (cpu) 
-               set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]);
+       set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]);
 } 
 
 unsigned long __init numa_free_all_bootmem(void) 
index 6ba48f346fcf2407d400e1d7217f10b2d72e0c7a..041bb47b5c39fb4f0c71e6562a2be159b4394bb5 100644 (file)
@@ -376,7 +376,7 @@ static int __init drm_core_init(void)
                goto err_p2;
        }
 
-       drm_proc_root = create_proc_entry("dri", S_IFDIR, NULL);
+       drm_proc_root = proc_mkdir("dri", NULL);
        if (!drm_proc_root) {
                DRM_ERROR("Cannot create /proc/dri\n");
                ret = -1;
index 32d2bb99462c67d7b9ef4416abd3147445afc36e..977961002488171d10897735c993d010040b5364 100644 (file)
@@ -95,7 +95,7 @@ int drm_proc_init(drm_device_t *dev, int minor,
        char                  name[64];
 
        sprintf(name, "%d", minor);
-       *dev_root = create_proc_entry(name, S_IFDIR, root);
+       *dev_root = proc_mkdir(name, root);
        if (!*dev_root) {
                DRM_ERROR("Cannot create /proc/dri/%s\n", name);
                return -1;
index e82a96ba396bb8ea49a460b26f2a71d4570f5284..f66947722e1282196a4d60e8c777d8ea250b3750 100644 (file)
@@ -55,7 +55,7 @@ extern void (*pm_power_off)(void);
 static int poweroff_powercycle;
 
 /* parameter definition to allow user to flag power cycle */
-module_param(poweroff_powercycle, int, 0);
+module_param(poweroff_powercycle, int, 0644);
 MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
 
 /* Stuff from the get device id command. */
index 2291a87e8ada6ce17070bfc38ceb41f512290568..97d6dc24b8003fabc28213e7c5090b966d481cd2 100644 (file)
@@ -229,8 +229,8 @@ static int __init r3964_init(void)
        TRACE_L("line discipline %d registered", N_R3964);
        TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, 
                tty_ldisc_N_R3964.num);
-       TRACE_L("open=%x", (int)tty_ldisc_N_R3964.open);
-       TRACE_L("tty_ldisc_N_R3964 = %x", (int)&tty_ldisc_N_R3964);
+       TRACE_L("open=%p", tty_ldisc_N_R3964.open);
+       TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964);
      }
    else
      {
@@ -267,8 +267,8 @@ static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pH
    
    spin_unlock_irqrestore(&pInfo->lock, flags);
 
-   TRACE_Q("add_tx_queue %x, length %d, tx_first = %x", 
-          (int)pHeader, pHeader->length, (int)pInfo->tx_first );
+   TRACE_Q("add_tx_queue %p, length %d, tx_first = %p", 
+          pHeader, pHeader->length, pInfo->tx_first );
 }
 
 static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
@@ -285,10 +285,10 @@ static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
       return;
 
 #ifdef DEBUG_QUEUE
-   printk("r3964: remove_from_tx_queue: %x, length %d - ",
-          (int)pHeader, (int)pHeader->length );
+   printk("r3964: remove_from_tx_queue: %p, length %u - ",
+          pHeader, pHeader->length );
    for(pDump=pHeader;pDump;pDump=pDump->next)
-        printk("%x ", (int)pDump);
+        printk("%p ", pDump);
    printk("\n");
 #endif
 
@@ -319,10 +319,10 @@ static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
    spin_unlock_irqrestore(&pInfo->lock, flags);
 
    kfree(pHeader);
-   TRACE_M("remove_from_tx_queue - kfree %x",(int)pHeader);
+   TRACE_M("remove_from_tx_queue - kfree %p",pHeader);
 
-   TRACE_Q("remove_from_tx_queue: tx_first = %x, tx_last = %x",
-          (int)pInfo->tx_first, (int)pInfo->tx_last );
+   TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p",
+          pInfo->tx_first, pInfo->tx_last );
 }
 
 static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader)
@@ -346,9 +346,9 @@ static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pH
    
    spin_unlock_irqrestore(&pInfo->lock, flags);
 
-   TRACE_Q("add_rx_queue: %x, length = %d, rx_first = %x, count = %d",
-          (int)pHeader, pHeader->length,
-          (int)pInfo->rx_first, pInfo->blocks_in_rx_queue);
+   TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d",
+          pHeader, pHeader->length,
+          pInfo->rx_first, pInfo->blocks_in_rx_queue);
 }
 
 static void remove_from_rx_queue(struct r3964_info *pInfo,
@@ -360,10 +360,10 @@ static void remove_from_rx_queue(struct r3964_info *pInfo,
    if(pHeader==NULL)
       return;
 
-   TRACE_Q("remove_from_rx_queue: rx_first = %x, rx_last = %x, count = %d",
-          (int)pInfo->rx_first, (int)pInfo->rx_last, pInfo->blocks_in_rx_queue );
-   TRACE_Q("remove_from_rx_queue: %x, length %d",
-          (int)pHeader, (int)pHeader->length );
+   TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
+          pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue );
+   TRACE_Q("remove_from_rx_queue: %p, length %u",
+          pHeader, pHeader->length );
 
    spin_lock_irqsave(&pInfo->lock, flags);
 
@@ -401,10 +401,10 @@ static void remove_from_rx_queue(struct r3964_info *pInfo,
    spin_unlock_irqrestore(&pInfo->lock, flags);
 
    kfree(pHeader);
-   TRACE_M("remove_from_rx_queue - kfree %x",(int)pHeader);
+   TRACE_M("remove_from_rx_queue - kfree %p",pHeader);
 
-   TRACE_Q("remove_from_rx_queue: rx_first = %x, rx_last = %x, count = %d",
-          (int)pInfo->rx_first, (int)pInfo->rx_last, pInfo->blocks_in_rx_queue );
+   TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d",
+          pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue );
 }
 
 static void put_char(struct r3964_info *pInfo, unsigned char ch)
@@ -506,8 +506,8 @@ static void transmit_block(struct r3964_info *pInfo)
    if(tty->driver->write_room)
       room=tty->driver->write_room(tty);
 
-   TRACE_PS("transmit_block %x, room %d, length %d", 
-          (int)pBlock, room, pBlock->length);
+   TRACE_PS("transmit_block %p, room %d, length %d", 
+          pBlock, room, pBlock->length);
    
    while(pInfo->tx_position < pBlock->length)
    {
@@ -588,7 +588,7 @@ static void on_receive_block(struct r3964_info *pInfo)
 
    /* prepare struct r3964_block_header: */
    pBlock = kmalloc(length+sizeof(struct r3964_block_header), GFP_KERNEL);
-   TRACE_M("on_receive_block - kmalloc %x",(int)pBlock);
+   TRACE_M("on_receive_block - kmalloc %p",pBlock);
 
    if(pBlock==NULL)
       return;
@@ -868,11 +868,11 @@ static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
                if(pMsg)
                {
                   kfree(pMsg);
-                  TRACE_M("enable_signals - msg kfree %x",(int)pMsg);
+                  TRACE_M("enable_signals - msg kfree %p",pMsg);
                }
             }
             kfree(pClient);
-            TRACE_M("enable_signals - kfree %x",(int)pClient);
+            TRACE_M("enable_signals - kfree %p",pClient);
             return 0;
          }
       }
@@ -890,7 +890,7 @@ static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
       {
          /* add client to client list */
          pClient=kmalloc(sizeof(struct r3964_client_info), GFP_KERNEL);
-         TRACE_M("enable_signals - kmalloc %x",(int)pClient);
+         TRACE_M("enable_signals - kmalloc %p",pClient);
          if(pClient==NULL)
             return -ENOMEM;
 
@@ -954,7 +954,7 @@ static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
 queue_the_message:
 
       pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL);
-      TRACE_M("add_msg - kmalloc %x",(int)pMsg);
+      TRACE_M("add_msg - kmalloc %p",pMsg);
       if(pMsg==NULL) {
          return;
       }
@@ -1067,11 +1067,11 @@ static int r3964_open(struct tty_struct *tty)
    struct r3964_info *pInfo;
    
    TRACE_L("open");
-   TRACE_L("tty=%x, PID=%d, disc_data=%x", 
-          (int)tty, current->pid, (int)tty->disc_data);
+   TRACE_L("tty=%p, PID=%d, disc_data=%p", 
+          tty, current->pid, tty->disc_data);
    
    pInfo=kmalloc(sizeof(struct r3964_info), GFP_KERNEL); 
-   TRACE_M("r3964_open - info kmalloc %x",(int)pInfo);
+   TRACE_M("r3964_open - info kmalloc %p",pInfo);
 
    if(!pInfo)
    {
@@ -1080,26 +1080,26 @@ static int r3964_open(struct tty_struct *tty)
    }
 
    pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
-   TRACE_M("r3964_open - rx_buf kmalloc %x",(int)pInfo->rx_buf);
+   TRACE_M("r3964_open - rx_buf kmalloc %p",pInfo->rx_buf);
 
    if(!pInfo->rx_buf)
    {
       printk(KERN_ERR "r3964: failed to alloc receive buffer\n");
       kfree(pInfo);
-      TRACE_M("r3964_open - info kfree %x",(int)pInfo);
+      TRACE_M("r3964_open - info kfree %p",pInfo);
       return -ENOMEM;
    }
    
    pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL);
-   TRACE_M("r3964_open - tx_buf kmalloc %x",(int)pInfo->tx_buf);
+   TRACE_M("r3964_open - tx_buf kmalloc %p",pInfo->tx_buf);
 
    if(!pInfo->tx_buf)
    {
       printk(KERN_ERR "r3964: failed to alloc transmit buffer\n");
       kfree(pInfo->rx_buf);
-      TRACE_M("r3964_open - rx_buf kfree %x",(int)pInfo->rx_buf);
+      TRACE_M("r3964_open - rx_buf kfree %p",pInfo->rx_buf);
       kfree(pInfo);
-      TRACE_M("r3964_open - info kfree %x",(int)pInfo);
+      TRACE_M("r3964_open - info kfree %p",pInfo);
       return -ENOMEM;
    }
 
@@ -1154,11 +1154,11 @@ static void r3964_close(struct tty_struct *tty)
           if(pMsg)
           {
              kfree(pMsg);
-             TRACE_M("r3964_close - msg kfree %x",(int)pMsg);
+             TRACE_M("r3964_close - msg kfree %p",pMsg);
           }
        }
        kfree(pClient);
-       TRACE_M("r3964_close - client kfree %x",(int)pClient);
+       TRACE_M("r3964_close - client kfree %p",pClient);
        pClient=pNext;
     }
     /* Remove jobs from tx_queue: */
@@ -1177,11 +1177,11 @@ static void r3964_close(struct tty_struct *tty)
     /* Free buffers: */
     wake_up_interruptible(&pInfo->read_wait);
     kfree(pInfo->rx_buf);
-    TRACE_M("r3964_close - rx_buf kfree %x",(int)pInfo->rx_buf);
+    TRACE_M("r3964_close - rx_buf kfree %p",pInfo->rx_buf);
     kfree(pInfo->tx_buf);
-    TRACE_M("r3964_close - tx_buf kfree %x",(int)pInfo->tx_buf);
+    TRACE_M("r3964_close - tx_buf kfree %p",pInfo->tx_buf);
     kfree(pInfo);
-    TRACE_M("r3964_close - info kfree %x",(int)pInfo);
+    TRACE_M("r3964_close - info kfree %p",pInfo);
 }
 
 static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
@@ -1234,7 +1234,7 @@ repeat:
       count = sizeof(struct r3964_client_message);
 
       kfree(pMsg);
-      TRACE_M("r3964_read - msg kfree %x",(int)pMsg);
+      TRACE_M("r3964_read - msg kfree %p",pMsg);
 
       if (copy_to_user(buf,&theMsg, count))
        return -EFAULT;
@@ -1279,7 +1279,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file,
  * Allocate a buffer for the data and copy it from the buffer with header prepended
  */
    new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL);
-   TRACE_M("r3964_write - kmalloc %x",(int)new_data);
+   TRACE_M("r3964_write - kmalloc %p",new_data);
    if (new_data == NULL) {
       if (pInfo->flags & R3964_DEBUG)
       {
index 1436aea3b28f798d0d55142bda96605b8078ca79..6d3ff0836c440b90b61697e2bc2c4559f45b085b 100644 (file)
@@ -87,6 +87,8 @@ static int mv64x60_wdt_open(struct inode *inode, struct file *file)
        mv64x60_wdt_service();
        mv64x60_wdt_handler_enable();
 
+       nonseekable_open(inode, file);
+
        return 0;
 }
 
@@ -103,12 +105,9 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static ssize_t mv64x60_wdt_write(struct file *file, const char *data,
+static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data,
                                 size_t len, loff_t * ppos)
 {
-       if (*ppos != file->f_pos)
-               return -ESPIPE;
-
        if (len)
                mv64x60_wdt_service();
 
@@ -119,6 +118,7 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
                             unsigned int cmd, unsigned long arg)
 {
        int timeout;
+       void __user *argp = (void __user *)arg;
        static struct watchdog_info info = {
                .options = WDIOF_KEEPALIVEPING,
                .firmware_version = 0,
@@ -127,13 +127,13 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
 
        switch (cmd) {
        case WDIOC_GETSUPPORT:
-               if (copy_to_user((void *)arg, &info, sizeof(info)))
+               if (copy_to_user(argp, &info, sizeof(info)))
                        return -EFAULT;
                break;
 
        case WDIOC_GETSTATUS:
        case WDIOC_GETBOOTSTATUS:
-               if (put_user(wdt_status, (int *)arg))
+               if (put_user(wdt_status, (int __user *)argp))
                        return -EFAULT;
                wdt_status &= ~WDIOF_KEEPALIVEPING;
                break;
@@ -154,7 +154,7 @@ static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
 
        case WDIOC_GETTIMEOUT:
                timeout = mv64x60_wdt_timeout * HZ;
-               if (put_user(timeout, (int *)arg))
+               if (put_user(timeout, (int __user *)argp))
                        return -EFAULT;
                break;
 
index 966632182e2db20c7094037030acb50732a16a8b..9f2f00d82917a748fb021cffcbac4a274e1434a9 100644 (file)
 #include <linux/connector.h>
 #include <linux/delay.h>
 
-static void cn_queue_wrapper(void *data)
+void cn_queue_wrapper(void *data)
 {
-       struct cn_callback_entry *cbq = data;
+       struct cn_callback_data *d = data;
 
-       cbq->cb->callback(cbq->cb->priv);
-       cbq->destruct_data(cbq->ddata);
-       cbq->ddata = NULL;
+       d->callback(d->callback_priv);
+
+       d->destruct_data(d->ddata);
+       d->ddata = NULL;
+
+       kfree(d->free);
 }
 
-static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callback *cb)
+static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *))
 {
        struct cn_callback_entry *cbq;
 
@@ -50,8 +53,11 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callbac
                return NULL;
        }
 
-       cbq->cb = cb;
-       INIT_WORK(&cbq->work, &cn_queue_wrapper, cbq);
+       snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name);
+       memcpy(&cbq->id.id, id, sizeof(struct cb_id));
+       cbq->data.callback = callback;
+       
+       INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data);
        return cbq;
 }
 
@@ -68,12 +74,12 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
        return ((i1->idx == i2->idx) && (i1->val == i2->val));
 }
 
-int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
+int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *))
 {
        struct cn_callback_entry *cbq, *__cbq;
        int found = 0;
 
-       cbq = cn_queue_alloc_callback_entry(cb);
+       cbq = cn_queue_alloc_callback_entry(name, id, callback);
        if (!cbq)
                return -ENOMEM;
 
@@ -82,7 +88,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
 
        spin_lock_bh(&dev->queue_lock);
        list_for_each_entry(__cbq, &dev->queue_list, callback_entry) {
-               if (cn_cb_equal(&__cbq->cb->id, &cb->id)) {
+               if (cn_cb_equal(&__cbq->id.id, id)) {
                        found = 1;
                        break;
                }
@@ -99,7 +105,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb)
 
        cbq->nls = dev->nls;
        cbq->seq = 0;
-       cbq->group = cbq->cb->id.idx;
+       cbq->group = cbq->id.id.idx;
 
        return 0;
 }
@@ -111,7 +117,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
 
        spin_lock_bh(&dev->queue_lock);
        list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) {
-               if (cn_cb_equal(&cbq->cb->id, id)) {
+               if (cn_cb_equal(&cbq->id.id, id)) {
                        list_del(&cbq->callback_entry);
                        found = 1;
                        break;
index aaf6d468a8b98f9d522f73e81809f5f5f977db9d..bb0b3a8de14bde88adf870f4bea29e5c6e90f6bd 100644 (file)
@@ -84,7 +84,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask)
                spin_lock_bh(&dev->cbdev->queue_lock);
                list_for_each_entry(__cbq, &dev->cbdev->queue_list,
                                    callback_entry) {
-                       if (cn_cb_equal(&__cbq->cb->id, &msg->id)) {
+                       if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
                                found = 1;
                                group = __cbq->group;
                        }
@@ -127,42 +127,56 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
 {
        struct cn_callback_entry *__cbq;
        struct cn_dev *dev = &cdev;
-       int found = 0;
+       int err = -ENODEV;
 
        spin_lock_bh(&dev->cbdev->queue_lock);
        list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
-               if (cn_cb_equal(&__cbq->cb->id, &msg->id)) {
-                       /*
-                        * Let's scream if there is some magic and the
-                        * data will arrive asynchronously here.
-                        * [i.e. netlink messages will be queued].
-                        * After the first warning I will fix it
-                        * quickly, but now I think it is
-                        * impossible. --zbr (2004_04_27).
-                        */
+               if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
                        if (likely(!test_bit(0, &__cbq->work.pending) &&
-                                       __cbq->ddata == NULL)) {
-                               __cbq->cb->priv = msg;
+                                       __cbq->data.ddata == NULL)) {
+                               __cbq->data.callback_priv = msg;
 
-                               __cbq->ddata = data;
-                               __cbq->destruct_data = destruct_data;
+                               __cbq->data.ddata = data;
+                               __cbq->data.destruct_data = destruct_data;
 
                                if (queue_work(dev->cbdev->cn_queue,
                                                &__cbq->work))
-                                       found = 1;
+                                       err = 0;
                        } else {
-                               printk("%s: cbq->data=%p, "
-                                      "work->pending=%08lx.\n",
-                                      __func__, __cbq->ddata,
-                                      __cbq->work.pending);
-                               WARN_ON(1);
+                               struct work_struct *w;
+                               struct cn_callback_data *d;
+                               
+                               w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC);
+                               if (w) {
+                                       d = (struct cn_callback_data *)(w+1);
+
+                                       d->callback_priv = msg;
+                                       d->callback = __cbq->data.callback;
+                                       d->ddata = data;
+                                       d->destruct_data = destruct_data;
+                                       d->free = w;
+
+                                       INIT_LIST_HEAD(&w->entry);
+                                       w->pending = 0;
+                                       w->func = &cn_queue_wrapper;
+                                       w->data = d;
+                                       init_timer(&w->timer);
+                                       
+                                       if (queue_work(dev->cbdev->cn_queue, w))
+                                               err = 0;
+                                       else {
+                                               kfree(w);
+                                               err = -EINVAL;
+                                       }
+                               } else
+                                       err = -ENOMEM;
                        }
                        break;
                }
        }
        spin_unlock_bh(&dev->cbdev->queue_lock);
 
-       return found ? 0 : -ENODEV;
+       return err;
 }
 
 /*
@@ -291,22 +305,10 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
 {
        int err;
        struct cn_dev *dev = &cdev;
-       struct cn_callback *cb;
-
-       cb = kzalloc(sizeof(*cb), GFP_KERNEL);
-       if (!cb)
-               return -ENOMEM;
-
-       scnprintf(cb->name, sizeof(cb->name), "%s", name);
 
-       memcpy(&cb->id, id, sizeof(cb->id));
-       cb->callback = callback;
-
-       err = cn_queue_add_callback(dev->cbdev, cb);
-       if (err) {
-               kfree(cb);
+       err = cn_queue_add_callback(dev->cbdev, name, id, callback);
+       if (err)
                return err;
-       }
 
        cn_notify(id, 0);
 
index 0ccf85fcee3478669dfb5f2a1827d9c5494a7082..a35a58bef1a4eb4d1752bc2929eb528956206035 100644 (file)
@@ -477,7 +477,7 @@ static struct pcmcia_device_id ide_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
        PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674),
        PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2      ", 0xe37be2b5, 0x8671043b),
-       PCMCIA_DEVICE_PROD_ID12(" ", "NinjaATA-", 0x3b6e20c8, 0xebe0bd79),
+       PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79),
        PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591),
        PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728),
        PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1),
index 84ae027b021a19920dede6881f2260ddefb48978..e8e28569a6684feb2c0ae4e5d41447479c5480bc 100644 (file)
@@ -1297,4 +1297,3 @@ static void __exit amdtp_exit_module (void)
 
 module_init(amdtp_init_module);
 module_exit(amdtp_exit_module);
-MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16);
index e6734263a1d3c6c16375d52fba8c7455a48ac392..28c5f4b726e2e375867ac256c746bd7c0cb40773 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/sched.h>
 #include <linux/vmalloc.h>
 #include <asm/pgalloc.h>
 
index 4538b0235ca34ebd3aca87428443153b080b4255..e34730c7a8748ab77e06242a1d9efe8bb177bae2 100644 (file)
@@ -2660,4 +2660,3 @@ static int __init dv1394_init_module(void)
 
 module_init(dv1394_init_module);
 module_exit(dv1394_exit_module);
-MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16);
index cd53c174ced171119eabe814919ff570b310006b..4802bbbb6dc9817c9b4f49b08bcad65268f8f84a 100644 (file)
@@ -89,7 +89,7 @@
 #define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
 
 static char version[] __devinitdata =
-       "$Rev: 1264 $ Ben Collins <bcollins@debian.org>";
+       "$Rev: 1312 $ Ben Collins <bcollins@debian.org>";
 
 struct fragment_info {
        struct list_head list;
@@ -221,9 +221,7 @@ static int ether1394_open (struct net_device *dev)
        if (priv->bc_state == ETHER1394_BC_ERROR) {
                /* we'll try again */
                priv->iso = hpsb_iso_recv_init(priv->host,
-                                              ETHER1394_GASP_BUFFERS * 2 *
-                                              (1 << (priv->host->csr.max_rec +
-                                                     1)),
+                                              ETHER1394_ISO_BUF_SIZE,
                                               ETHER1394_GASP_BUFFERS,
                                               priv->broadcast_channel,
                                               HPSB_ISO_DMA_PACKET_PER_BUFFER,
@@ -635,8 +633,8 @@ static void ether1394_add_host (struct hpsb_host *host)
         * be checked when the eth device is opened. */
        priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
 
-       priv->iso = hpsb_iso_recv_init(host, (ETHER1394_GASP_BUFFERS * 2 *
-                                             (1 << (host->csr.max_rec + 1))),
+       priv->iso = hpsb_iso_recv_init(host,
+                                      ETHER1394_ISO_BUF_SIZE,
                                       ETHER1394_GASP_BUFFERS,
                                       priv->broadcast_channel,
                                       HPSB_ISO_DMA_PACKET_PER_BUFFER,
@@ -1770,7 +1768,7 @@ fail:
 static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        strcpy (info->driver, driver_name);
-       strcpy (info->version, "$Rev: 1264 $");
+       strcpy (info->version, "$Rev: 1312 $");
        /* FIXME XXX provide sane businfo */
        strcpy (info->bus_info, "ieee1394");
 }
index ed8f1c4b7fd80ee38ca331d0a2df32e12bea101d..a77213cfc4837b8dd302e1b502ac36073c664d9b 100644 (file)
 
 #define ETHER1394_GASP_BUFFERS 16
 
+/* rawiso buffer size - due to a limitation in rawiso, we must limit each
+ * GASP buffer to be less than PAGE_SIZE. */
+#define ETHER1394_ISO_BUF_SIZE ETHER1394_GASP_BUFFERS *                        \
+                                  min((unsigned int)PAGE_SIZE,                 \
+                                      2 * (1U << (priv->host->csr.max_rec + 1)))
+
 /* Node set == 64 */
 #define NODE_SET                       (ALL_NODES + 1)
 
index c502c6e9c440bea39cd64c2d0225ffa96b3929b2..aeeaeb670d035c769a6f47d0f39099681f689293 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/timer.h>
+#include <linux/jiffies.h>
 
 #include "csr1212.h"
 #include "ieee1394.h"
@@ -217,7 +218,7 @@ int hpsb_update_config_rom_image(struct hpsb_host *host)
 
        /* IEEE 1394a-2000 prohibits using the same generation number
         * twice in a 60 second period. */
-       if (jiffies - host->csr.gen_timestamp[next_gen] < 60 * HZ)
+       if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ))
                /* Wait 60 seconds from the last time this generation number was
                 * used. */
                reset_delay = (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
index 739e76840d5106716be264d4f025c9a1b351b496..38f42112dff0f8b48782e038b10db69bb1241a84 100644 (file)
@@ -135,17 +135,17 @@ enum isoctl_cmd {
 
 enum reset_types {
         /* 166 microsecond reset -- only type of reset available on
-           non-1394a capable IEEE 1394 controllers */
+           non-1394a capable controllers */
         LONG_RESET,
 
         /* Short (arbitrated) reset -- only available on 1394a capable
-           IEEE 1394 capable controllers */
+           controllers */
         SHORT_RESET,
 
-       /* Variants, that set force_root before issueing the bus reset */
+       /* Variants that set force_root before issueing the bus reset */
        LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT,
 
-       /* Variants, that clear force_root before issueing the bus reset */
+       /* Variants that clear force_root before issueing the bus reset */
        LONG_RESET_NO_FORCE_ROOT, SHORT_RESET_NO_FORCE_ROOT
 };
 
index d633770fac8ee3b99a3a77c84356db02be2bf7c6..32a1e016c85e76d2ec80b02dc055621c959b74c2 100644 (file)
@@ -70,7 +70,7 @@ const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S32
 struct class *hpsb_protocol_class;
 
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-static void dump_packet(const char *text, quadlet_t *data, int size)
+static void dump_packet(const char *text, quadlet_t *data, int size, int speed)
 {
        int i;
 
@@ -78,12 +78,15 @@ static void dump_packet(const char *text, quadlet_t *data, int size)
        size = (size > 4 ? 4 : size);
 
        printk(KERN_DEBUG "ieee1394: %s", text);
+       if (speed > -1 && speed < 6)
+               printk(" at %s", hpsb_speedto_str[speed]);
+       printk(":");
        for (i = 0; i < size; i++)
                printk(" %08x", data[i]);
        printk("\n");
 }
 #else
-#define dump_packet(x,y,z)
+#define dump_packet(a,b,c,d)
 #endif
 
 static void abort_requests(struct hpsb_host *host);
@@ -544,8 +547,7 @@ int hpsb_send_packet(struct hpsb_packet *packet)
                 if (packet->data_size)
                        memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size);
 
-                dump_packet("send packet local:", packet->header,
-                            packet->header_size);
+                dump_packet("send packet local", packet->header, packet->header_size, -1);
 
                 hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
                 hpsb_packet_received(host, data, size, 0);
@@ -561,21 +563,7 @@ int hpsb_send_packet(struct hpsb_packet *packet)
                                        + NODEID_TO_NODE(packet->node_id)];
         }
 
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-        switch (packet->speed_code) {
-        case 2:
-                dump_packet("send packet 400:", packet->header,
-                            packet->header_size);
-                break;
-        case 1:
-                dump_packet("send packet 200:", packet->header,
-                            packet->header_size);
-                break;
-        default:
-                dump_packet("send packet 100:", packet->header,
-                            packet->header_size);
-        }
-#endif
+        dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
 
         return host->driver->transmit_packet(host, packet);
 }
@@ -636,7 +624,7 @@ static void handle_packet_response(struct hpsb_host *host, int tcode,
 
        if (packet == NULL) {
                 HPSB_DEBUG("unsolicited response packet received - no tlabel match");
-                dump_packet("contents:", data, 16);
+                dump_packet("contents", data, 16, -1);
                spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
                 return;
         }
@@ -677,7 +665,7 @@ static void handle_packet_response(struct hpsb_host *host, int tcode,
         if (!tcode_match) {
                spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
                 HPSB_INFO("unsolicited response packet received - tcode mismatch");
-                dump_packet("contents:", data, 16);
+                dump_packet("contents", data, 16, -1);
                 return;
         }
 
@@ -914,7 +902,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
                 return;
         }
 
-        dump_packet("received packet:", data, size);
+        dump_packet("received packet", data, size, -1);
 
         tcode = (data[0] >> 4) & 0xf;
 
index b23322523ef57b1cf147e4368239487e55ef15bc..347ece6b583c19cdf67e521dcb5ae3ebf2c1ecdd 100644 (file)
@@ -64,10 +64,10 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
        struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
        int i, ret = 0;
 
-       for (i = 0; i < 3; i++) {
+       for (i = 1; ; i++) {
                ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
                                buffer, length);
-               if (!ret)
+               if (!ret || i == 3)
                        break;
 
                if (msleep_interruptible(334))
@@ -1438,9 +1438,13 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
        if (host->busmgr_id == 0xffff && host->node_count > 1)
        {
                u16 root_node = host->node_count - 1;
-               struct node_entry *ne = find_entry_by_nodeid(host, root_node | LOCAL_BUS);
 
-               if (ne && ne->busopt.cmc)
+               /* get cycle master capability flag from root node */
+               if (host->is_cycmst ||
+                   (!hpsb_read(host, LOCAL_BUS | root_node, get_hpsb_generation(host),
+                               (CSR_REGISTER_BASE + CSR_CONFIG_ROM + 2 * sizeof(quadlet_t)),
+                               &bc, sizeof(quadlet_t)) &&
+                    be32_to_cpu(bc) & 1 << CSR_CMC_SHIFT))
                        hpsb_send_phy_config(host, root_node, -1);
                else {
                        HPSB_DEBUG("The root node is not cycle master capable; "
@@ -1557,24 +1561,19 @@ static int nodemgr_host_thread(void *__hi)
                        }
                }
 
-               if (!nodemgr_check_irm_capability(host, reset_cycles)) {
+               if (!nodemgr_check_irm_capability(host, reset_cycles) ||
+                   !nodemgr_do_irm_duties(host, reset_cycles)) {
                        reset_cycles++;
                        up(&nodemgr_serialize);
                        continue;
                }
+               reset_cycles = 0;
 
                /* Scan our nodes to get the bus options and create node
                 * entries. This does not do the sysfs stuff, since that
                 * would trigger hotplug callbacks and such, which is a
                 * bad idea at this point. */
                nodemgr_node_scan(hi, generation);
-               if (!nodemgr_do_irm_duties(host, reset_cycles)) {
-                       reset_cycles++;
-                       up(&nodemgr_serialize);
-                       continue;
-               }
-
-               reset_cycles = 0;
 
                /* This actually does the full probe, with sysfs
                 * registration. */
index 27018c8efc242ee0a660c5be9d8449597e551c42..6a6acbd80af4fb8c7b6ea0373b5075d39fa4d207 100644 (file)
@@ -162,7 +162,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
 printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
 
 static char version[] __devinitdata =
-       "$Rev: 1299 $ Ben Collins <bcollins@debian.org>";
+       "$Rev: 1313 $ Ben Collins <bcollins@debian.org>";
 
 /* Module Parameters */
 static int phys_dma = 1;
@@ -1084,7 +1084,7 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
                        initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
 
                        if (printk_ratelimit())
-                               PRINT(KERN_ERR, "IR legacy activated");
+                               DBGMSG("IR legacy activated");
                }
 
                 spin_lock_irqsave(&ohci->IR_channel_lock, flags);
index b4fa14793fe5f1a421965c8ae550ef72f7ec926f..5fe4f2ba0979713682bf6ed48adf86bc826eecbd 100644 (file)
@@ -2958,4 +2958,3 @@ static void __exit cleanup_raw1394(void)
 module_init(init_raw1394);
 module_exit(cleanup_raw1394);
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16);
index de88218ef7cce8c8eb4912aedb4bdffbd64f7561..12cec7c4a34295acc8e25607c7b383aedd973521 100644 (file)
@@ -97,16 +97,18 @@ static char version[] __devinitdata =
  */
 static int max_speed = IEEE1394_SPEED_MAX;
 module_param(max_speed, int, 0644);
-MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb default, 1 = 200mb, 0 = 100mb)");
+MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb, 1 = 200mb, 0 = 100mb)");
 
 /*
  * Set serialize_io to 1 if you'd like only one scsi command sent
  * down to us at a time (debugging). This might be necessary for very
  * badly behaved sbp2 devices.
+ *
+ * TODO: Make this configurable per device.
  */
-static int serialize_io;
+static int serialize_io = 1;
 module_param(serialize_io, int, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize all I/O coming down from the scsi drivers (default = 0)");
+MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default = 1, faster = 0)");
 
 /*
  * Bump up max_sectors if you'd like to support very large sized
@@ -596,6 +598,14 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
        spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
 }
 
+/*
+ * Is scsi_id valid? Is the 1394 node still present?
+ */
+static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_id)
+{
+       return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo;
+}
+
 \f
 
 /*********************************************
@@ -631,11 +641,23 @@ static int sbp2_remove(struct device *dev)
 {
        struct unit_directory *ud;
        struct scsi_id_instance_data *scsi_id;
+       struct scsi_device *sdev;
 
        SBP2_DEBUG("sbp2_remove");
 
        ud = container_of(dev, struct unit_directory, device);
        scsi_id = ud->device.driver_data;
+       if (!scsi_id)
+               return 0;
+
+       /* Trigger shutdown functions in scsi's highlevel. */
+       if (scsi_id->scsi_host)
+               scsi_unblock_requests(scsi_id->scsi_host);
+       sdev = scsi_id->sdev;
+       if (sdev) {
+               scsi_id->sdev = NULL;
+               scsi_remove_device(sdev);
+       }
 
        sbp2_logout_device(scsi_id);
        sbp2_remove_device(scsi_id);
@@ -2473,37 +2495,26 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
        struct scsi_id_instance_data *scsi_id =
                (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
        struct sbp2scsi_host_info *hi;
+       int result = DID_NO_CONNECT << 16;
 
        SBP2_DEBUG("sbp2scsi_queuecommand");
 
-       /*
-        * If scsi_id is null, it means there is no device in this slot,
-        * so we should return selection timeout.
-        */
-       if (!scsi_id) {
-               SCpnt->result = DID_NO_CONNECT << 16;
-               done (SCpnt);
-               return 0;
-       }
+       if (!sbp2util_node_is_available(scsi_id))
+               goto done;
 
        hi = scsi_id->hi;
 
        if (!hi) {
                SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!");
-               SCpnt->result = DID_NO_CONNECT << 16;
-               done (SCpnt);
-               return(0);
+               goto done;
        }
 
        /*
         * Until we handle multiple luns, just return selection time-out
         * to any IO directed at non-zero LUNs
         */
-       if (SCpnt->device->lun) {
-               SCpnt->result = DID_NO_CONNECT << 16;
-               done (SCpnt);
-               return(0);
-       }
+       if (SCpnt->device->lun)
+               goto done;
 
        /*
         * Check for request sense command, and handle it here
@@ -2514,7 +2525,7 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
                memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen);
                memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
                sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done);
-               return(0);
+               return 0;
        }
 
        /*
@@ -2522,9 +2533,8 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
         */
        if (!hpsb_node_entry_valid(scsi_id->ne)) {
                SBP2_ERR("Bus reset in progress - rejecting command");
-               SCpnt->result = DID_BUS_BUSY << 16;
-               done (SCpnt);
-               return(0);
+               result = DID_BUS_BUSY << 16;
+               goto done;
        }
 
        /*
@@ -2535,8 +2545,12 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
                sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
                                          SCpnt, done);
        }
+       return 0;
 
-       return(0);
+done:
+       SCpnt->result = result;
+       done(SCpnt);
+       return 0;
 }
 
 /*
@@ -2683,14 +2697,27 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
 }
 
 
-static int sbp2scsi_slave_configure (struct scsi_device *sdev)
+static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
 {
-       blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
+       ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev;
+       return 0;
+}
+
 
+static int sbp2scsi_slave_configure(struct scsi_device *sdev)
+{
+       blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
        return 0;
 }
 
 
+static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
+{
+       ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL;
+       return;
+}
+
+
 /*
  * Called by scsi stack when something has really gone wrong.  Usually
  * called when a command has timed-out for some reason.
@@ -2705,7 +2732,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
        SBP2_ERR("aborting sbp2 command");
        scsi_print_command(SCpnt);
 
-       if (scsi_id) {
+       if (sbp2util_node_is_available(scsi_id)) {
 
                /*
                 * Right now, just return any matching command structures
@@ -2742,31 +2769,24 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
 /*
  * Called by scsi stack when something has really gone wrong.
  */
-static int __sbp2scsi_reset(struct scsi_cmnd *SCpnt)
+static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
 {
        struct scsi_id_instance_data *scsi_id =
                (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
+       unsigned long flags;
 
        SBP2_ERR("reset requested");
 
-       if (scsi_id) {
+       spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
+
+       if (sbp2util_node_is_available(scsi_id)) {
                SBP2_ERR("Generating sbp2 fetch agent reset");
                sbp2_agent_reset(scsi_id, 0);
        }
 
-       return(SUCCESS);
-}
-
-static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
-{
-       unsigned long flags;
-       int rc;
-
-       spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
-       rc = __sbp2scsi_reset(SCpnt);
        spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 
-       return rc;
+       return SUCCESS;
 }
 
 static const char *sbp2scsi_info (struct Scsi_Host *host)
@@ -2817,7 +2837,9 @@ static struct scsi_host_template scsi_driver_template = {
        .eh_device_reset_handler =      sbp2scsi_reset,
        .eh_bus_reset_handler =         sbp2scsi_reset,
        .eh_host_reset_handler =        sbp2scsi_reset,
+       .slave_alloc =                  sbp2scsi_slave_alloc,
        .slave_configure =              sbp2scsi_slave_configure,
+       .slave_destroy =                sbp2scsi_slave_destroy,
        .this_id =                      -1,
        .sg_tablesize =                 SG_ALL,
        .use_clustering =               ENABLE_CLUSTERING,
@@ -2837,7 +2859,8 @@ static int sbp2_module_init(void)
 
        /* Module load debug option to force one command at a time (serializing I/O) */
        if (serialize_io) {
-               SBP2_ERR("Driver forced to serialize I/O (serialize_io = 1)");
+               SBP2_INFO("Driver forced to serialize I/O (serialize_io=1)");
+               SBP2_INFO("Try serialize_io=0 for better performance");
                scsi_driver_template.can_queue = 1;
                scsi_driver_template.cmd_per_lun = 1;
        }
index 9d6facf2f78f5751f3da65890ea94cf3f5419143..11be9c9c82a8743cf65faca95c2b23738feaae51 100644 (file)
@@ -1571,4 +1571,3 @@ static int __init video1394_init_module (void)
 
 module_init(video1394_init_module);
 module_exit(video1394_exit_module);
-MODULE_ALIAS_CHARDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16);
index b1897bed14ad40174b834b359419f9a87f2ff6e5..cc124344dd2c72335cc8ebcb476cc66e4802e75d 100644 (file)
@@ -69,6 +69,7 @@ struct ib_uverbs_event_file {
 
 struct ib_uverbs_file {
        struct kref                             ref;
+       struct semaphore                        mutex;
        struct ib_uverbs_device                *device;
        struct ib_ucontext                     *ucontext;
        struct ib_event_handler                 event_handler;
index e91ebde4648105d57be74e907e767f60663f37bb..562445165d2bee6efb2b75d506db723fdb997e8a 100644 (file)
@@ -76,8 +76,9 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
        struct ib_uverbs_get_context_resp resp;
        struct ib_udata                   udata;
        struct ib_device                 *ibdev = file->device->ib_dev;
+       struct ib_ucontext               *ucontext;
        int i;
-       int ret = in_len;
+       int ret;
 
        if (out_len < sizeof resp)
                return -ENOSPC;
@@ -85,45 +86,56 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
+       down(&file->mutex);
+
+       if (file->ucontext) {
+               ret = -EINVAL;
+               goto err;
+       }
+
        INIT_UDATA(&udata, buf + sizeof cmd,
                   (unsigned long) cmd.response + sizeof resp,
                   in_len - sizeof cmd, out_len - sizeof resp);
 
-       file->ucontext = ibdev->alloc_ucontext(ibdev, &udata);
-       if (IS_ERR(file->ucontext)) {
-               ret = PTR_ERR(file->ucontext);
-               file->ucontext = NULL;
-               return ret;
-       }
+       ucontext = ibdev->alloc_ucontext(ibdev, &udata);
+       if (IS_ERR(ucontext))
+               return PTR_ERR(file->ucontext);
 
-       file->ucontext->device = ibdev;
-       INIT_LIST_HEAD(&file->ucontext->pd_list);
-       INIT_LIST_HEAD(&file->ucontext->mr_list);
-       INIT_LIST_HEAD(&file->ucontext->mw_list);
-       INIT_LIST_HEAD(&file->ucontext->cq_list);
-       INIT_LIST_HEAD(&file->ucontext->qp_list);
-       INIT_LIST_HEAD(&file->ucontext->srq_list);
-       INIT_LIST_HEAD(&file->ucontext->ah_list);
-       spin_lock_init(&file->ucontext->lock);
+       ucontext->device = ibdev;
+       INIT_LIST_HEAD(&ucontext->pd_list);
+       INIT_LIST_HEAD(&ucontext->mr_list);
+       INIT_LIST_HEAD(&ucontext->mw_list);
+       INIT_LIST_HEAD(&ucontext->cq_list);
+       INIT_LIST_HEAD(&ucontext->qp_list);
+       INIT_LIST_HEAD(&ucontext->srq_list);
+       INIT_LIST_HEAD(&ucontext->ah_list);
 
        resp.async_fd = file->async_file.fd;
        for (i = 0; i < file->device->num_comp; ++i)
                if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab +
                                 i * sizeof (__u32),
-                                &file->comp_file[i].fd, sizeof (__u32)))
-                       goto err;
+                                &file->comp_file[i].fd, sizeof (__u32))) {
+                       ret = -EFAULT;
+                       goto err_free;
+               }
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
-                        &resp, sizeof resp))
-               goto err;
+                        &resp, sizeof resp)) {
+               ret = -EFAULT;
+               goto err_free;
+       }
+
+       file->ucontext = ucontext;
+       up(&file->mutex);
 
        return in_len;
 
-err:
-       ibdev->dealloc_ucontext(file->ucontext);
-       file->ucontext = NULL;
+err_free:
+       ibdev->dealloc_ucontext(ucontext);
 
-       return -EFAULT;
+err:
+       up(&file->mutex);
+       return ret;
 }
 
 ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
@@ -352,9 +364,9 @@ retry:
        if (ret)
                goto err_pd;
 
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_add_tail(&uobj->list, &file->ucontext->pd_list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        memset(&resp, 0, sizeof resp);
        resp.pd_handle = uobj->id;
@@ -368,9 +380,9 @@ retry:
        return in_len;
 
 err_list:
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_del(&uobj->list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        down(&ib_uverbs_idr_mutex);
        idr_remove(&ib_uverbs_pd_idr, uobj->id);
@@ -410,9 +422,9 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
 
        idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
 
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_del(&uobj->list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        kfree(uobj);
 
@@ -512,9 +524,9 @@ retry:
 
        resp.mr_handle = obj->uobject.id;
 
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
@@ -527,9 +539,9 @@ retry:
        return in_len;
 
 err_list:
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_del(&obj->uobject.list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
 err_unreg:
        ib_dereg_mr(mr);
@@ -570,9 +582,9 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
 
        idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
 
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_del(&memobj->uobject.list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        ib_umem_release(file->device->ib_dev, &memobj->umem);
        kfree(memobj);
@@ -647,9 +659,9 @@ retry:
        if (ret)
                goto err_cq;
 
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        memset(&resp, 0, sizeof resp);
        resp.cq_handle = uobj->uobject.id;
@@ -664,9 +676,9 @@ retry:
        return in_len;
 
 err_list:
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_del(&uobj->uobject.list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        down(&ib_uverbs_idr_mutex);
        idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
@@ -712,9 +724,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
 
        idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
 
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_del(&uobj->uobject.list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        spin_lock_irq(&file->comp_file[0].lock);
        list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
@@ -847,9 +859,9 @@ retry:
 
        resp.qp_handle = uobj->uobject.id;
 
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
@@ -862,9 +874,9 @@ retry:
        return in_len;
 
 err_list:
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_del(&uobj->uobject.list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
 err_destroy:
        ib_destroy_qp(qp);
@@ -989,9 +1001,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
 
        idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
 
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_del(&uobj->uobject.list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        spin_lock_irq(&file->async_file.lock);
        list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
@@ -1136,9 +1148,9 @@ retry:
 
        resp.srq_handle = uobj->uobject.id;
 
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp)) {
@@ -1151,9 +1163,9 @@ retry:
        return in_len;
 
 err_list:
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_del(&uobj->uobject.list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
 err_destroy:
        ib_destroy_srq(srq);
@@ -1227,9 +1239,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
 
        idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
 
-       spin_lock_irq(&file->ucontext->lock);
+       down(&file->mutex);
        list_del(&uobj->uobject.list);
-       spin_unlock_irq(&file->ucontext->lock);
+       up(&file->mutex);
 
        spin_lock_irq(&file->async_file.lock);
        list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
index ce5bdb7af3063408f488e4a85d59caa4edfe01a7..12511808de212673ebb5a1f6173b0f3b40155cbe 100644 (file)
@@ -448,7 +448,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
        if (hdr.in_words * 4 != count)
                return -EINVAL;
 
-       if (hdr.command < 0 || hdr.command >= ARRAY_SIZE(uverbs_cmd_table))
+       if (hdr.command < 0                             ||
+           hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
+           !uverbs_cmd_table[hdr.command])
                return -EINVAL;
 
        if (!file->ucontext                               &&
@@ -484,27 +486,29 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
        file = kmalloc(sizeof *file +
                       (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),
                       GFP_KERNEL);
-       if (!file)
-               return -ENOMEM;
+       if (!file) {
+               ret = -ENOMEM;
+               goto err;
+       }
 
        file->device = dev;
        kref_init(&file->ref);
+       init_MUTEX(&file->mutex);
 
        file->ucontext = NULL;
 
+       kref_get(&file->ref);
        ret = ib_uverbs_event_init(&file->async_file, file);
        if (ret)
-               goto err;
+               goto err_kref;
 
        file->async_file.is_async = 1;
 
-       kref_get(&file->ref);
-
        for (i = 0; i < dev->num_comp; ++i) {
+               kref_get(&file->ref);
                ret = ib_uverbs_event_init(&file->comp_file[i], file);
                if (ret)
                        goto err_async;
-               kref_get(&file->ref);
                file->comp_file[i].is_async = 0;
        }
 
@@ -524,9 +528,16 @@ err_async:
 
        ib_uverbs_event_release(&file->async_file);
 
-err:
+err_kref:
+       /*
+        * One extra kref_put() because we took a reference before the
+        * event file creation that failed and got us here.
+        */
+       kref_put(&file->ref, ib_uverbs_release_file);
        kref_put(&file->ref, ib_uverbs_release_file);
 
+err:
+       module_put(dev->ib_dev->owner);
        return ret;
 }
 
index cc758a2d2bc6cad452f73b644ada7246ea2441bc..f6a8ac026557db5639d446bf1188cf9d73b22739 100644 (file)
@@ -605,7 +605,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
                        err = -EINVAL;
                        goto out;
                }
-               for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i, ++nent) {
+               for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) {
                        if (virt != -1) {
                                pages[nent * 2] = cpu_to_be64(virt);
                                virt += 1 << lg;
@@ -616,7 +616,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
                        ts += 1 << (lg - 10);
                        ++tc;
 
-                       if (nent == MTHCA_MAILBOX_SIZE / 16) {
+                       if (++nent == MTHCA_MAILBOX_SIZE / 16) {
                                err = mthca_cmd(dev, mailbox->dma, nent, 0, op,
                                                CMD_TIME_CLASS_B, status);
                                if (err || *status)
index 78152a8ad17d82561f650c14040c7145fc2685db..c81fa8e975ef1c8a2fd611bd0b37aa9671a815e1 100644 (file)
@@ -836,7 +836,7 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
                dev->eq_table.clr_mask =
                        swab32(1 << (dev->eq_table.inta_pin & 31));
                dev->eq_table.clr_int  = dev->clr_base +
-                       (dev->eq_table.inta_pin < 31 ? 4 : 0);
+                       (dev->eq_table.inta_pin < 32 ? 4 : 0);
        }
 
        dev->eq_table.arm_mask = 0;
index 1827400f189be87a61c5c7c062147a978a16b133..7bd7a4bec7b433f2e533602681a75d7e06553940 100644 (file)
@@ -290,7 +290,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
        int i;
        u8 status;
 
-       num_icm = obj_size * nobj / MTHCA_TABLE_CHUNK_SIZE;
+       num_icm = (obj_size * nobj + MTHCA_TABLE_CHUNK_SIZE - 1) / MTHCA_TABLE_CHUNK_SIZE;
 
        table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL);
        if (!table)
@@ -529,12 +529,25 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db)
                        goto found;
                }
 
+       for (i = start; i != end; i += dir)
+               if (!dev->db_tab->page[i].db_rec) {
+                       page = dev->db_tab->page + i;
+                       goto alloc;
+               }
+
        if (dev->db_tab->max_group1 >= dev->db_tab->min_group2 - 1) {
                ret = -ENOMEM;
                goto out;
        }
 
+       if (group == 0)
+               ++dev->db_tab->max_group1;
+       else
+               --dev->db_tab->min_group2;
+
        page = dev->db_tab->page + end;
+
+alloc:
        page->db_rec = dma_alloc_coherent(&dev->pdev->dev, 4096,
                                          &page->mapping, GFP_KERNEL);
        if (!page->db_rec) {
@@ -554,10 +567,6 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db)
        }
 
        bitmap_zero(page->used, MTHCA_DB_REC_PER_PAGE);
-       if (group == 0)
-               ++dev->db_tab->max_group1;
-       else
-               --dev->db_tab->min_group2;
 
 found:
        j = find_first_zero_bit(page->used, MTHCA_DB_REC_PER_PAGE);
index 1c1c2e230871202fe4b57bcf26aa602e6b505586..3f5319a46577022378e1142ff2dbaa13bd42a71a 100644 (file)
@@ -84,7 +84,7 @@ static int mthca_query_device(struct ib_device *ibdev,
        props->vendor_id           = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
                0xffffff;
        props->vendor_part_id      = be16_to_cpup((__be16 *) (out_mad->data + 30));
-       props->hw_ver              = be16_to_cpup((__be16 *) (out_mad->data + 32));
+       props->hw_ver              = be32_to_cpup((__be32 *) (out_mad->data + 32));
        memcpy(&props->sys_image_guid, out_mad->data +  4, 8);
        memcpy(&props->node_guid,      out_mad->data + 12, 8);
 
index 88636a204525e84862972ea7034c02ae020ae4bb..14ae5583e198fa9669bf8f9a70b9a86a8fe32009 100644 (file)
@@ -308,6 +308,7 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
                MATCH_BIT(ledbit, LED_MAX);
                MATCH_BIT(sndbit, SND_MAX);
                MATCH_BIT(ffbit,  FF_MAX);
+               MATCH_BIT(swbit,  SW_MAX);
 
                return id;
        }
index e1f0d87de0eb1f072f4c38c2954c673ec509462c..0b0ea26023e59994e5c9b3836317d082d5fd33b0 100644 (file)
@@ -287,12 +287,12 @@ divert_dev_init(void)
        init_waitqueue_head(&rd_queue);
 
 #ifdef CONFIG_PROC_FS
-       isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
+       isdn_proc_entry = proc_mkdir("net/isdn", NULL);
        if (!isdn_proc_entry)
                return (-1);
        isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry);
        if (!isdn_divert_entry) {
-               remove_proc_entry("isdn", proc_net);
+               remove_proc_entry("net/isdn", NULL);
                return (-1);
        }
        isdn_divert_entry->proc_fops = &isdn_fops; 
@@ -312,7 +312,7 @@ divert_dev_deinit(void)
 
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("divert", isdn_proc_entry);
-       remove_proc_entry("isdn", proc_net);
+       remove_proc_entry("net/isdn", NULL);
 #endif /* CONFIG_PROC_FS */
 
        return (0);
index 7fdf8ae5be52e8e4d25f565821461f7fdb36ad9e..27204f4b111a7c724407abd3adfa07ab99efacb0 100644 (file)
@@ -30,8 +30,6 @@ static char *DRIVERNAME =
 static char *DRIVERLNAME = "divadidd";
 char *DRIVERRELEASE_DIDD = "2.0";
 
-static char *main_proc_dir = "eicon";
-
 MODULE_DESCRIPTION("DIDD table driver for diva drivers");
 MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
 MODULE_SUPPORTED_DEVICE("Eicon diva drivers");
@@ -89,7 +87,7 @@ proc_read(char *page, char **start, off_t off, int count, int *eof,
 
 static int DIVA_INIT_FUNCTION create_proc(void)
 {
-       proc_net_eicon = create_proc_entry(main_proc_dir, S_IFDIR, proc_net);
+       proc_net_eicon = proc_mkdir("net/eicon", NULL);
 
        if (proc_net_eicon) {
                if ((proc_didd =
@@ -105,7 +103,7 @@ static int DIVA_INIT_FUNCTION create_proc(void)
 static void DIVA_EXIT_FUNCTION remove_proc(void)
 {
        remove_proc_entry(DRIVERLNAME, proc_net_eicon);
-       remove_proc_entry(main_proc_dir, proc_net);
+       remove_proc_entry("net/eicon", NULL);
 }
 
 static int DIVA_INIT_FUNCTION divadidd_init(void)
index b6435589d459494b57608579984f3ef19973b77a..c12efa6f842917340b870f58276ad0ffa5d6b23a 100644 (file)
@@ -381,7 +381,7 @@ int create_adapter_proc(diva_os_xdi_adapter_t * a)
        char tmp[16];
 
        sprintf(tmp, "%s%d", adapter_dir_name, a->controller);
-       if (!(de = create_proc_entry(tmp, S_IFDIR, proc_net_eicon)))
+       if (!(de = proc_mkdir(tmp, proc_net_eicon)))
                return (0);
        a->proc_adapter_dir = (void *) de;
 
index 5da507e532fc5ef9bbac164516f89d8f081e4d8e..639582f61f41e416e98dbb493a70a9a3d1f7df15 100644 (file)
@@ -394,7 +394,7 @@ hysdn_procconf_init(void)
        hysdn_card *card;
        uchar conf_name[20];
 
-       hysdn_proc_entry = create_proc_entry(PROC_SUBDIR_NAME, S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
+       hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, proc_net);
        if (!hysdn_proc_entry) {
                printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n");
                return (-1);
index a85ac18dd21d13971738fbb45a93415384ed194f..9b38674fbf7558d689aab1e88e284df3e692f504 100644 (file)
@@ -153,8 +153,10 @@ static irqreturn_t smu_db_intr(int irq, void *arg, struct pt_regs *regs)
        spin_lock_irqsave(&smu->lock, flags);
 
        gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, smu->doorbell);
-       if ((gpio & 7) != 7)
+       if ((gpio & 7) != 7) {
+               spin_unlock_irqrestore(&smu->lock, flags);
                return IRQ_HANDLED;
+       }
 
        cmd = smu->cmd_cur;
        smu->cmd_cur = NULL;
index 200a0688f717c76759c1165cde20652ad14d07f7..54ec737195e00f9043a8db9dbc04aff0df09e40f 100644 (file)
@@ -230,11 +230,20 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi
 
 static void __hash_remove(struct hash_cell *hc)
 {
+       struct dm_table *table;
+
        /* remove from the dev hash */
        list_del(&hc->uuid_list);
        list_del(&hc->name_list);
        unregister_with_devfs(hc);
        dm_set_mdptr(hc->md, NULL);
+
+       table = dm_get_table(hc->md);
+       if (table) {
+               dm_table_event(table);
+               dm_table_put(table);
+       }
+
        dm_put(hc->md);
        if (hc->new_map)
                dm_table_put(hc->new_map);
index 785806bdb2485d8c5d5d8b0249b9b63bb8b5a750..f9b7b32d5d5c773bea00dfc9e2f198333ea550c1 100644 (file)
@@ -329,13 +329,17 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
 /*
  * If we run out of usable paths, should we queue I/O or error it?
  */
-static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path)
+static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path,
+                           unsigned save_old_value)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&m->lock, flags);
 
-       m->saved_queue_if_no_path = m->queue_if_no_path;
+       if (save_old_value)
+               m->saved_queue_if_no_path = m->queue_if_no_path;
+       else
+               m->saved_queue_if_no_path = queue_if_no_path;
        m->queue_if_no_path = queue_if_no_path;
        if (!m->queue_if_no_path && m->queue_size)
                queue_work(kmultipathd, &m->process_queued_ios);
@@ -677,7 +681,7 @@ static int parse_features(struct arg_set *as, struct multipath *m,
                return 0;
 
        if (!strnicmp(shift(as), MESG_STR("queue_if_no_path")))
-               return queue_if_no_path(m, 1);
+               return queue_if_no_path(m, 1, 0);
        else {
                ti->error = "Unrecognised multipath feature request";
                return -EINVAL;
@@ -1077,7 +1081,7 @@ static void multipath_presuspend(struct dm_target *ti)
 {
        struct multipath *m = (struct multipath *) ti->private;
 
-       queue_if_no_path(m, 0);
+       queue_if_no_path(m, 0, 1);
 }
 
 /*
@@ -1222,9 +1226,9 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
 
        if (argc == 1) {
                if (!strnicmp(argv[0], MESG_STR("queue_if_no_path")))
-                       return queue_if_no_path(m, 1);
+                       return queue_if_no_path(m, 1, 0);
                else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path")))
-                       return queue_if_no_path(m, 0);
+                       return queue_if_no_path(m, 0, 0);
        }
 
        if (argc != 2)
index 87d5f4d8790ffdfb47d6d78704e48fd699508005..eaf130e666d8b232b311103a95ebdcb1cfd9db27 100644 (file)
@@ -100,8 +100,8 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
 
        ret = i2c_transfer (state->i2c, msg, 2);
        if (ret != 2)
-               printk("DVB: TDA10021(%d): %s: readreg error (ret == %i)\n",
-                               state->frontend.dvb->num, __FUNCTION__, ret);
+               printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
+                               __FUNCTION__, ret);
        return b1[0];
 }
 
index 190977a1e5494598b753d3a34ea5c2a60ad989b6..6c332800d6abf511fd3333b00359a15a3895b253 100644 (file)
@@ -2398,7 +2398,7 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 2,
        .muxsel         = { 2, 3 },
        .gpiomask       = 0x00e00007,
-       .audiomux       = { 0x00400005, 0, 0, 0, 0, 0 },
+       .audiomux       = { 0x00400005, 0, 0x00000001, 0, 0x00c00007, 0 },
        .no_msp34xx     = 1,
        .no_tda9875     = 1,
        .no_tda7432     = 1,
index 8c08b7f1ad233389cb4377bdf04c154f1f7ed6f2..b7ec9bf45085ea6e31ba526938654eb24a32f647 100644 (file)
@@ -1397,7 +1397,7 @@ static void destroy_proc_cpia_cam(struct cam_data *cam)
 
 static void proc_cpia_create(void)
 {
-       cpia_proc_root = create_proc_entry("cpia", S_IFDIR, NULL);
+       cpia_proc_root = proc_mkdir("cpia", NULL);
 
        if (cpia_proc_root)
                cpia_proc_root->owner = THIS_MODULE;
index 30337d0f1a87daa0e16d6ffaabf54a5daf4dfcbe..0d30eb744e61abae812fb8098007308e65bc5c89 100644 (file)
@@ -31,7 +31,7 @@
 struct rds_command {
        unsigned int  block_count;
        int           result;
-       unsigned char *buffer;
+       unsigned char __user *buffer;
        struct file   *instance;
        poll_table    *event_list;
 };
index 1a657a70ff43c53158a50ce2140e90c55429889d..72b70eb5da1d70e5f586dabfea18e1effad28a74 100644 (file)
@@ -157,7 +157,7 @@ static struct i2c_client client_template;
 
 /* ---------------------------------------------------------------------- */
 
-static int block_to_user_buf(struct saa6588 *s, unsigned char *user_buf)
+static int block_to_user_buf(struct saa6588 *s, unsigned char __user *user_buf)
 {
        int i;
 
@@ -191,7 +191,7 @@ static void read_from_buf(struct saa6588 *s, struct rds_command *a)
 {
        unsigned long flags;
 
-       unsigned char *buf_ptr = a->buffer;     /* This is a user space buffer! */
+       unsigned char __user *buf_ptr = a->buffer;
        unsigned int i;
        unsigned int rd_blocks;
 
index a851d65c7cfef72b4d8cccfa9253c4d552ce6318..a260f83bcb021080f00f45c459435224cda8a5b2 100644 (file)
@@ -48,8 +48,8 @@ struct ucb1x00_ts {
        u16                     x_res;
        u16                     y_res;
 
-       int                     restart:1;
-       int                     adcsync:1;
+       unsigned int            restart:1;
+       unsigned int            adcsync:1;
 };
 
 static int adcsync;
index 0c45464e3f7b8636f6d816b280a150e930dea6de..0ba0ff7d43b9593489659f6ffb933e73d9d33c4f 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/mtd/partitions.h>
 
 #include <asm/io.h>
-#include <asm/mach-types.h>
 #include <asm/mach/flash.h>
 
 #include <asm/arch/map.h>
index 3e94b616743d0cec3cc123fb8952b2aedf4f236b..a9f86c7fbd52e7319c8825196070e54da6e20a0e 100644 (file)
@@ -30,7 +30,6 @@
 
 #include <asm/io.h>
 #include <asm/hardware.h>
-#include <asm/mach-types.h>
 #include <asm/mach/flash.h>
 
 #include <linux/reboot.h>
index 5afe660aa2c4f9f8eb96a10a2762f385e5548f4e..3fcc3288407437792479c456574ac09c50ee716e 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/ioport.h>
 #include <linux/device.h>
 #include <asm/io.h>
-#include <asm/mach-types.h>
 #include <asm/mach/flash.h>
 
 #include <linux/reboot.h>
@@ -254,6 +253,6 @@ module_init(ixp4xx_flash_init);
 module_exit(ixp4xx_flash_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems")
+MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems");
 MODULE_AUTHOR("Deepak Saxena");
 
index 8cc71409a3285c62e68206b5ee92a83d05527c86..b17bca657daf53599d8e8328ee1110b08cb50e95 100644 (file)
@@ -42,7 +42,6 @@
 
 #include <asm/io.h>
 #include <asm/hardware.h>
-#include <asm/mach-types.h>
 #include <asm/mach/flash.h>
 #include <asm/arch/tc.h>
 
index 52385705da09fe32d13590c7628aa2372e303e65..8dcaa357b4bb13bbaba9e543f1b45dc49ce880b3 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/concat.h>
 
-#include <asm/mach-types.h>
 #include <asm/io.h>
 #include <asm/sizes.h>
 #include <asm/mach/flash.h>
index 891e3a1b91106fa761ccbf032c4d4f0854655601..b47ebcb31e0fdf5a1116c0e2a99d387dbc2941f9 100644 (file)
@@ -58,7 +58,6 @@
 #include <linux/mtd/partitions.h>
 
 #include <asm/io.h>
-#include <asm/mach-types.h>
 #include <asm/hardware/clock.h>
 
 #include <asm/arch/regs-nand.h>
index 96f14ab1c1f52f805e64c62959fadc84d1b1e412..2a908c4690a7cd41eae1793dec2d9c6daa2e9b41 100644 (file)
@@ -548,6 +548,14 @@ config SUNGEM
          Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0.  See also
          <http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>.
 
+config CASSINI
+       tristate "Sun Cassini support"
+       depends on NET_ETHERNET && PCI
+       select CRC32
+       help
+         Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
+         <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
+
 config NET_VENDOR_3COM
        bool "3COM cards"
        depends on NET_ETHERNET && (ISA || EISA || MCA || PCI)
index 8645c843cf4d0216c8e8e4a53b202d7a576c2b07..8aeec9f2495b5e712879b7735e95bf141ce49e05 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_SUNQE) += sunqe.o
 obj-$(CONFIG_SUNBMAC) += sunbmac.o
 obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
 obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
+obj-$(CONFIG_CASSINI) += cassini.o
 
 obj-$(CONFIG_MACE) += mace.o
 obj-$(CONFIG_BMAC) += bmac.o
index 9b659e3c8d674280bc283dd99f7a872c7b2b7d0d..c56d86d371a9c6d15eac175a7770c80f96d26b60 100644 (file)
  */
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/fcntl.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/in.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/crc32.h>
@@ -33,7 +30,6 @@
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/dma.h>
 
 #define TX_BUFFERS 15
 #define RX_BUFFERS 25
@@ -85,7 +81,7 @@ static inline unsigned short read_ireg(u_long base_addr, u_int reg)
        u_short v;
        __asm__(
        "str%?h %1, [%2]        @ NAT_RAP\n\t"
-       "str%?h %0, [%2, #8]    @ NET_IDP\n\t"
+       "ldr%?h %0, [%2, #8]    @ NET_IDP\n\t"
        : "=r" (v)
        : "r" (reg), "r" (ISAIO_BASE + 0x0464));
        return v;
@@ -288,7 +284,7 @@ static void am79c961_timer(unsigned long data)
        else if (!lnkstat && carrier)
                netif_carrier_off(dev);
 
-       mod_timer(&priv->timer, jiffies + 5*HZ);
+       mod_timer(&priv->timer, jiffies + msecs_to_jiffies(500));
 }
 
 /*
@@ -709,13 +705,9 @@ static int __init am79c961_init(void)
                goto release;
 
        am79c961_banner();
-       printk(KERN_INFO "%s: ether address ", dev->name);
 
-       /* Retrive and print the ethernet address. */
-       for (i = 0; i < 6; i++) {
+       for (i = 0; i < 6; i++)
                dev->dev_addr[i] = inb(dev->base_addr + i * 2) & 0xff;
-               printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
-       }
 
        spin_lock_init(&priv->chip_lock);
        init_timer(&priv->timer);
@@ -736,8 +728,14 @@ static int __init am79c961_init(void)
 #endif
 
        ret = register_netdev(dev);
-       if (ret == 0)
+       if (ret == 0) {
+               printk(KERN_INFO "%s: ether address ", dev->name);
+
+               for (i = 0; i < 6; i++)
+                       printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
+
                return 0;
+       }
 
 release:
        release_region(dev->base_addr, 0x18);
index 8dc657fc8afb37f18623efb160e58b216a615520..60dba4a1ca5ce8d57081088c22d16eeb7a2ee8f6 100644 (file)
@@ -218,7 +218,7 @@ void bmwrite(struct net_device *dev, unsigned long reg_offset, unsigned data )
 
 
 static inline
-volatile unsigned short bmread(struct net_device *dev, unsigned long reg_offset )
+unsigned short bmread(struct net_device *dev, unsigned long reg_offset )
 {
        return in_le16((void __iomem *)dev->base_addr + reg_offset);
 }
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
new file mode 100644 (file)
index 0000000..45831fb
--- /dev/null
@@ -0,0 +1,5311 @@
+/* cassini.c: Sun Microsystems Cassini(+) ethernet driver.
+ *
+ * Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (C) 2003 Adrian Sun (asun@darksunrising.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * This driver uses the sungem driver (c) David Miller
+ * (davem@redhat.com) as its basis.
+ *
+ * The cassini chip has a number of features that distinguish it from
+ * the gem chip:
+ *  4 transmit descriptor rings that are used for either QoS (VLAN) or
+ *      load balancing (non-VLAN mode)
+ *  batching of multiple packets
+ *  multiple CPU dispatching
+ *  page-based RX descriptor engine with separate completion rings
+ *  Gigabit support (GMII and PCS interface)
+ *  MIF link up/down detection works
+ *
+ * RX is handled by page sized buffers that are attached as fragments to
+ * the skb. here's what's done:
+ *  -- driver allocates pages at a time and keeps reference counts
+ *     on them.
+ *  -- the upper protocol layers assume that the header is in the skb
+ *     itself. as a result, cassini will copy a small amount (64 bytes)
+ *     to make them happy.
+ *  -- driver appends the rest of the data pages as frags to skbuffs
+ *     and increments the reference count
+ *  -- on page reclamation, the driver swaps the page with a spare page.
+ *     if that page is still in use, it frees its reference to that page,
+ *     and allocates a new page for use. otherwise, it just recycles the
+ *     the page. 
+ *
+ * NOTE: cassini can parse the header. however, it's not worth it
+ *       as long as the network stack requires a header copy.
+ *
+ * TX has 4 queues. currently these queues are used in a round-robin
+ * fashion for load balancing. They can also be used for QoS. for that
+ * to work, however, QoS information needs to be exposed down to the driver
+ * level so that subqueues get targetted to particular transmit rings.
+ * alternatively, the queues can be configured via use of the all-purpose
+ * ioctl.
+ *
+ * RX DATA: the rx completion ring has all the info, but the rx desc
+ * ring has all of the data. RX can conceivably come in under multiple
+ * interrupts, but the INT# assignment needs to be set up properly by
+ * the BIOS and conveyed to the driver. PCI BIOSes don't know how to do
+ * that. also, the two descriptor rings are designed to distinguish between
+ * encrypted and non-encrypted packets, but we use them for buffering 
+ * instead.
+ *
+ * by default, the selective clear mask is set up to process rx packets.  
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/crc32.h>
+#include <linux/random.h>
+#include <linux/mii.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+#include <net/checksum.h>
+
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#define cas_page_map(x)      kmap_atomic((x), KM_SKB_DATA_SOFTIRQ)
+#define cas_page_unmap(x)    kunmap_atomic((x), KM_SKB_DATA_SOFTIRQ)
+#define CAS_NCPUS            num_online_cpus()
+
+#if defined(CONFIG_CASSINI_NAPI) && defined(HAVE_NETDEV_POLL)
+#define USE_NAPI
+#define cas_skb_release(x)  netif_receive_skb(x)
+#else
+#define cas_skb_release(x)  netif_rx(x)
+#endif
+
+/* select which firmware to use */
+#define USE_HP_WORKAROUND     
+#define HP_WORKAROUND_DEFAULT /* select which firmware to use as default */
+#define CAS_HP_ALT_FIRMWARE   cas_prog_null /* alternate firmware */
+
+#include "cassini.h"
+
+#define USE_TX_COMPWB      /* use completion writeback registers */
+#define USE_CSMA_CD_PROTO  /* standard CSMA/CD */
+#define USE_RX_BLANK       /* hw interrupt mitigation */
+#undef USE_ENTROPY_DEV     /* don't test for entropy device */
+
+/* NOTE: these aren't useable unless PCI interrupts can be assigned.
+ * also, we need to make cp->lock finer-grained.
+ */
+#undef  USE_PCI_INTB
+#undef  USE_PCI_INTC
+#undef  USE_PCI_INTD
+#undef  USE_QOS
+
+#undef  USE_VPD_DEBUG       /* debug vpd information if defined */
+
+/* rx processing options */
+#define USE_PAGE_ORDER      /* specify to allocate large rx pages */
+#define RX_DONT_BATCH  0    /* if 1, don't batch flows */
+#define RX_COPY_ALWAYS 0    /* if 0, use frags */
+#define RX_COPY_MIN    64   /* copy a little to make upper layers happy */
+#undef  RX_COUNT_BUFFERS    /* define to calculate RX buffer stats */
+
+#define DRV_MODULE_NAME                "cassini"
+#define PFX DRV_MODULE_NAME    ": "
+#define DRV_MODULE_VERSION     "1.4"
+#define DRV_MODULE_RELDATE     "1 July 2004"
+
+#define CAS_DEF_MSG_ENABLE       \
+       (NETIF_MSG_DRV          | \
+        NETIF_MSG_PROBE        | \
+        NETIF_MSG_LINK         | \
+        NETIF_MSG_TIMER        | \
+        NETIF_MSG_IFDOWN       | \
+        NETIF_MSG_IFUP         | \
+        NETIF_MSG_RX_ERR       | \
+        NETIF_MSG_TX_ERR)
+
+/* length of time before we decide the hardware is borked,
+ * and dev->tx_timeout() should be called to fix the problem
+ */
+#define CAS_TX_TIMEOUT                 (HZ)
+#define CAS_LINK_TIMEOUT                (22*HZ/10)
+#define CAS_LINK_FAST_TIMEOUT           (1)
+
+/* timeout values for state changing. these specify the number
+ * of 10us delays to be used before giving up.
+ */
+#define STOP_TRIES_PHY 1000
+#define STOP_TRIES     5000
+
+/* specify a minimum frame size to deal with some fifo issues 
+ * max mtu == 2 * page size - ethernet header - 64 - swivel =
+ *            2 * page_size - 0x50
+ */
+#define CAS_MIN_FRAME                  97
+#define CAS_1000MB_MIN_FRAME            255
+#define CAS_MIN_MTU                     60
+#define CAS_MAX_MTU                     min(((cp->page_size << 1) - 0x50), 9000)
+
+#if 1
+/*
+ * Eliminate these and use separate atomic counters for each, to
+ * avoid a race condition.
+ */
+#else
+#define CAS_RESET_MTU                   1
+#define CAS_RESET_ALL                   2
+#define CAS_RESET_SPARE                 3
+#endif
+
+static char version[] __devinitdata =
+       DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)");
+MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver");
+MODULE_LICENSE("GPL");
+MODULE_PARM(cassini_debug, "i");
+MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value");
+MODULE_PARM(link_mode, "i");
+MODULE_PARM_DESC(link_mode, "default link mode");
+
+/*
+ * Work around for a PCS bug in which the link goes down due to the chip
+ * being confused and never showing a link status of "up."
+ */
+#define DEFAULT_LINKDOWN_TIMEOUT 5
+/* 
+ * Value in seconds, for user input.
+ */
+static int linkdown_timeout = DEFAULT_LINKDOWN_TIMEOUT;
+MODULE_PARM(linkdown_timeout, "i");
+MODULE_PARM_DESC(linkdown_timeout,
+"min reset interval in sec. for PCS linkdown issue; disabled if not positive");
+
+/*
+ * value in 'ticks' (units used by jiffies). Set when we init the
+ * module because 'HZ' in actually a function call on some flavors of
+ * Linux.  This will default to DEFAULT_LINKDOWN_TIMEOUT * HZ.
+ */
+static int link_transition_timeout;
+
+
+static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */
+static int link_mode;
+
+static u16 link_modes[] __devinitdata = {
+       BMCR_ANENABLE,                   /* 0 : autoneg */
+       0,                               /* 1 : 10bt half duplex */
+       BMCR_SPEED100,                   /* 2 : 100bt half duplex */
+       BMCR_FULLDPLX,                   /* 3 : 10bt full duplex */
+       BMCR_SPEED100|BMCR_FULLDPLX,     /* 4 : 100bt full duplex */
+       CAS_BMCR_SPEED1000|BMCR_FULLDPLX /* 5 : 1000bt full duplex */
+};
+
+static struct pci_device_id cas_pci_tbl[] __devinitdata = {
+       { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_CASSINI,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SATURN,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, cas_pci_tbl);
+
+static void cas_set_link_modes(struct cas *cp);
+
+static inline void cas_lock_tx(struct cas *cp)
+{
+       int i;
+
+       for (i = 0; i < N_TX_RINGS; i++)  
+               spin_lock(&cp->tx_lock[i]);
+}
+
+static inline void cas_lock_all(struct cas *cp)
+{
+       spin_lock_irq(&cp->lock);
+       cas_lock_tx(cp);
+}
+
+/* WTZ: QA was finding deadlock problems with the previous
+ * versions after long test runs with multiple cards per machine.
+ * See if replacing cas_lock_all with safer versions helps. The
+ * symptoms QA is reporting match those we'd expect if interrupts
+ * aren't being properly restored, and we fixed a previous deadlock
+ * with similar symptoms by using save/restore versions in other
+ * places.
+ */
+#define cas_lock_all_save(cp, flags) \
+do { \
+       struct cas *xxxcp = (cp); \
+       spin_lock_irqsave(&xxxcp->lock, flags); \
+       cas_lock_tx(xxxcp); \
+} while (0)
+
+static inline void cas_unlock_tx(struct cas *cp)
+{
+       int i;
+
+       for (i = N_TX_RINGS; i > 0; i--)  
+               spin_unlock(&cp->tx_lock[i - 1]);  
+}
+
+static inline void cas_unlock_all(struct cas *cp)
+{
+       cas_unlock_tx(cp);
+       spin_unlock_irq(&cp->lock);
+}
+
+#define cas_unlock_all_restore(cp, flags) \
+do { \
+       struct cas *xxxcp = (cp); \
+       cas_unlock_tx(xxxcp); \
+       spin_unlock_irqrestore(&xxxcp->lock, flags); \
+} while (0)
+
+static void cas_disable_irq(struct cas *cp, const int ring)
+{
+       /* Make sure we won't get any more interrupts */
+       if (ring == 0) {
+               writel(0xFFFFFFFF, cp->regs + REG_INTR_MASK);
+               return;
+       }
+
+       /* disable completion interrupts and selectively mask */
+       if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+               switch (ring) {
+#if defined (USE_PCI_INTB) || defined(USE_PCI_INTC) || defined(USE_PCI_INTD)
+#ifdef USE_PCI_INTB
+               case 1:
+#endif
+#ifdef USE_PCI_INTC
+               case 2:
+#endif
+#ifdef USE_PCI_INTD
+               case 3:
+#endif
+                       writel(INTRN_MASK_CLEAR_ALL | INTRN_MASK_RX_EN, 
+                              cp->regs + REG_PLUS_INTRN_MASK(ring));
+                       break;
+#endif
+               default:
+                       writel(INTRN_MASK_CLEAR_ALL, cp->regs +
+                              REG_PLUS_INTRN_MASK(ring));
+                       break;
+               }
+       }
+}
+
+static inline void cas_mask_intr(struct cas *cp)
+{
+       int i;
+
+       for (i = 0; i < N_RX_COMP_RINGS; i++)
+               cas_disable_irq(cp, i);
+}
+
+static void cas_enable_irq(struct cas *cp, const int ring)
+{
+       if (ring == 0) { /* all but TX_DONE */
+               writel(INTR_TX_DONE, cp->regs + REG_INTR_MASK);
+               return;
+       }
+
+       if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+               switch (ring) {
+#if defined (USE_PCI_INTB) || defined(USE_PCI_INTC) || defined(USE_PCI_INTD)
+#ifdef USE_PCI_INTB
+               case 1:
+#endif
+#ifdef USE_PCI_INTC
+               case 2:
+#endif
+#ifdef USE_PCI_INTD
+               case 3:
+#endif
+                       writel(INTRN_MASK_RX_EN, cp->regs +
+                              REG_PLUS_INTRN_MASK(ring));
+                       break;
+#endif
+               default:
+                       break;
+               }
+       }
+}
+
+static inline void cas_unmask_intr(struct cas *cp)
+{
+       int i;
+
+       for (i = 0; i < N_RX_COMP_RINGS; i++)
+               cas_enable_irq(cp, i);
+}
+
+static inline void cas_entropy_gather(struct cas *cp)
+{
+#ifdef USE_ENTROPY_DEV
+       if ((cp->cas_flags & CAS_FLAG_ENTROPY_DEV) == 0)
+               return;
+
+       batch_entropy_store(readl(cp->regs + REG_ENTROPY_IV),
+                           readl(cp->regs + REG_ENTROPY_IV),
+                           sizeof(uint64_t)*8);
+#endif
+}
+
+static inline void cas_entropy_reset(struct cas *cp)
+{
+#ifdef USE_ENTROPY_DEV
+       if ((cp->cas_flags & CAS_FLAG_ENTROPY_DEV) == 0)
+               return;
+
+       writel(BIM_LOCAL_DEV_PAD | BIM_LOCAL_DEV_PROM | BIM_LOCAL_DEV_EXT, 
+              cp->regs + REG_BIM_LOCAL_DEV_EN);
+       writeb(ENTROPY_RESET_STC_MODE, cp->regs + REG_ENTROPY_RESET);
+       writeb(0x55, cp->regs + REG_ENTROPY_RAND_REG);
+
+       /* if we read back 0x0, we don't have an entropy device */
+       if (readb(cp->regs + REG_ENTROPY_RAND_REG) == 0)
+               cp->cas_flags &= ~CAS_FLAG_ENTROPY_DEV;
+#endif
+}
+
+/* access to the phy. the following assumes that we've initialized the MIF to 
+ * be in frame rather than bit-bang mode
+ */
+static u16 cas_phy_read(struct cas *cp, int reg)
+{
+       u32 cmd;
+       int limit = STOP_TRIES_PHY;
+
+       cmd = MIF_FRAME_ST | MIF_FRAME_OP_READ;
+       cmd |= CAS_BASE(MIF_FRAME_PHY_ADDR, cp->phy_addr);
+       cmd |= CAS_BASE(MIF_FRAME_REG_ADDR, reg);
+       cmd |= MIF_FRAME_TURN_AROUND_MSB;
+       writel(cmd, cp->regs + REG_MIF_FRAME);
+       
+       /* poll for completion */
+       while (limit-- > 0) {
+               udelay(10);
+               cmd = readl(cp->regs + REG_MIF_FRAME);
+               if (cmd & MIF_FRAME_TURN_AROUND_LSB)
+                       return (cmd & MIF_FRAME_DATA_MASK);
+       }
+       return 0xFFFF; /* -1 */
+}
+
+static int cas_phy_write(struct cas *cp, int reg, u16 val)
+{
+       int limit = STOP_TRIES_PHY;
+       u32 cmd;
+
+       cmd = MIF_FRAME_ST | MIF_FRAME_OP_WRITE;
+       cmd |= CAS_BASE(MIF_FRAME_PHY_ADDR, cp->phy_addr);
+       cmd |= CAS_BASE(MIF_FRAME_REG_ADDR, reg);
+       cmd |= MIF_FRAME_TURN_AROUND_MSB;
+       cmd |= val & MIF_FRAME_DATA_MASK;
+       writel(cmd, cp->regs + REG_MIF_FRAME);
+       
+       /* poll for completion */
+       while (limit-- > 0) {
+               udelay(10);
+               cmd = readl(cp->regs + REG_MIF_FRAME);
+               if (cmd & MIF_FRAME_TURN_AROUND_LSB)
+                       return 0;
+       }
+       return -1;
+}
+
+static void cas_phy_powerup(struct cas *cp)
+{
+       u16 ctl = cas_phy_read(cp, MII_BMCR);   
+
+       if ((ctl & BMCR_PDOWN) == 0)
+               return;
+       ctl &= ~BMCR_PDOWN;
+       cas_phy_write(cp, MII_BMCR, ctl);
+}
+
+static void cas_phy_powerdown(struct cas *cp)
+{
+       u16 ctl = cas_phy_read(cp, MII_BMCR);   
+
+       if (ctl & BMCR_PDOWN)
+               return;
+       ctl |= BMCR_PDOWN;
+       cas_phy_write(cp, MII_BMCR, ctl);
+}
+
+/* cp->lock held. note: the last put_page will free the buffer */
+static int cas_page_free(struct cas *cp, cas_page_t *page)
+{
+       pci_unmap_page(cp->pdev, page->dma_addr, cp->page_size, 
+                      PCI_DMA_FROMDEVICE);
+       __free_pages(page->buffer, cp->page_order);
+       kfree(page);
+       return 0;
+}
+
+#ifdef RX_COUNT_BUFFERS
+#define RX_USED_ADD(x, y)       ((x)->used += (y))
+#define RX_USED_SET(x, y)       ((x)->used  = (y))
+#else
+#define RX_USED_ADD(x, y) 
+#define RX_USED_SET(x, y)
+#endif
+
+/* local page allocation routines for the receive buffers. jumbo pages
+ * require at least 8K contiguous and 8K aligned buffers.
+ */
+static cas_page_t *cas_page_alloc(struct cas *cp, const int flags)
+{
+       cas_page_t *page;
+
+       page = kmalloc(sizeof(cas_page_t), flags);
+       if (!page)
+               return NULL;
+
+       INIT_LIST_HEAD(&page->list);
+       RX_USED_SET(page, 0);
+       page->buffer = alloc_pages(flags, cp->page_order);
+       if (!page->buffer)
+               goto page_err;
+       page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0,
+                                     cp->page_size, PCI_DMA_FROMDEVICE);
+       return page;
+
+page_err:
+       kfree(page);
+       return NULL;
+}
+
+/* initialize spare pool of rx buffers, but allocate during the open */
+static void cas_spare_init(struct cas *cp)
+{
+       spin_lock(&cp->rx_inuse_lock);
+       INIT_LIST_HEAD(&cp->rx_inuse_list);
+       spin_unlock(&cp->rx_inuse_lock);
+
+       spin_lock(&cp->rx_spare_lock);
+       INIT_LIST_HEAD(&cp->rx_spare_list);
+       cp->rx_spares_needed = RX_SPARE_COUNT;
+       spin_unlock(&cp->rx_spare_lock);
+}
+
+/* used on close. free all the spare buffers. */
+static void cas_spare_free(struct cas *cp)
+{
+       struct list_head list, *elem, *tmp;
+
+       /* free spare buffers */
+       INIT_LIST_HEAD(&list);
+       spin_lock(&cp->rx_spare_lock);
+       list_splice(&cp->rx_spare_list, &list);
+       INIT_LIST_HEAD(&cp->rx_spare_list);
+       spin_unlock(&cp->rx_spare_lock);
+       list_for_each_safe(elem, tmp, &list) {
+               cas_page_free(cp, list_entry(elem, cas_page_t, list));
+       }
+
+       INIT_LIST_HEAD(&list);
+#if 1
+       /*
+        * Looks like Adrian had protected this with a different
+        * lock than used everywhere else to manipulate this list.
+        */
+       spin_lock(&cp->rx_inuse_lock);
+       list_splice(&cp->rx_inuse_list, &list);
+       INIT_LIST_HEAD(&cp->rx_inuse_list);
+       spin_unlock(&cp->rx_inuse_lock);
+#else
+       spin_lock(&cp->rx_spare_lock);
+       list_splice(&cp->rx_inuse_list, &list);
+       INIT_LIST_HEAD(&cp->rx_inuse_list);
+       spin_unlock(&cp->rx_spare_lock);
+#endif
+       list_for_each_safe(elem, tmp, &list) {
+               cas_page_free(cp, list_entry(elem, cas_page_t, list));
+       }
+}
+
+/* replenish spares if needed */
+static void cas_spare_recover(struct cas *cp, const int flags)
+{
+       struct list_head list, *elem, *tmp;
+       int needed, i;
+
+       /* check inuse list. if we don't need any more free buffers,
+        * just free it
+        */
+
+       /* make a local copy of the list */
+       INIT_LIST_HEAD(&list);
+       spin_lock(&cp->rx_inuse_lock);
+       list_splice(&cp->rx_inuse_list, &list);
+       INIT_LIST_HEAD(&cp->rx_inuse_list);
+       spin_unlock(&cp->rx_inuse_lock);
+       
+       list_for_each_safe(elem, tmp, &list) {
+               cas_page_t *page = list_entry(elem, cas_page_t, list);
+
+               if (page_count(page->buffer) > 1) 
+                       continue;
+
+               list_del(elem);
+               spin_lock(&cp->rx_spare_lock);
+               if (cp->rx_spares_needed > 0) {
+                       list_add(elem, &cp->rx_spare_list);
+                       cp->rx_spares_needed--;
+                       spin_unlock(&cp->rx_spare_lock);
+               } else {
+                       spin_unlock(&cp->rx_spare_lock);
+                       cas_page_free(cp, page);
+               }
+       }
+
+       /* put any inuse buffers back on the list */
+       if (!list_empty(&list)) {
+               spin_lock(&cp->rx_inuse_lock);
+               list_splice(&list, &cp->rx_inuse_list);
+               spin_unlock(&cp->rx_inuse_lock);
+       }
+       
+       spin_lock(&cp->rx_spare_lock);
+       needed = cp->rx_spares_needed;
+       spin_unlock(&cp->rx_spare_lock);
+       if (!needed)
+               return;
+
+       /* we still need spares, so try to allocate some */
+       INIT_LIST_HEAD(&list);
+       i = 0;
+       while (i < needed) {
+               cas_page_t *spare = cas_page_alloc(cp, flags);
+               if (!spare) 
+                       break;
+               list_add(&spare->list, &list);
+               i++;
+       }
+
+       spin_lock(&cp->rx_spare_lock);
+       list_splice(&list, &cp->rx_spare_list);
+       cp->rx_spares_needed -= i;
+       spin_unlock(&cp->rx_spare_lock);
+}
+
+/* pull a page from the list. */
+static cas_page_t *cas_page_dequeue(struct cas *cp)
+{
+       struct list_head *entry;
+       int recover;
+
+       spin_lock(&cp->rx_spare_lock);
+       if (list_empty(&cp->rx_spare_list)) {
+               /* try to do a quick recovery */
+               spin_unlock(&cp->rx_spare_lock);
+               cas_spare_recover(cp, GFP_ATOMIC);
+               spin_lock(&cp->rx_spare_lock);
+               if (list_empty(&cp->rx_spare_list)) {
+                       if (netif_msg_rx_err(cp))
+                               printk(KERN_ERR "%s: no spare buffers "
+                                      "available.\n", cp->dev->name);
+                       spin_unlock(&cp->rx_spare_lock);
+                       return NULL;
+               }
+       }
+
+       entry = cp->rx_spare_list.next;
+       list_del(entry);
+       recover = ++cp->rx_spares_needed;
+       spin_unlock(&cp->rx_spare_lock);
+
+       /* trigger the timer to do the recovery */
+       if ((recover & (RX_SPARE_RECOVER_VAL - 1)) == 0) {
+#if 1
+               atomic_inc(&cp->reset_task_pending);
+               atomic_inc(&cp->reset_task_pending_spare);
+               schedule_work(&cp->reset_task);
+#else
+               atomic_set(&cp->reset_task_pending, CAS_RESET_SPARE);
+               schedule_work(&cp->reset_task);
+#endif
+       }
+       return list_entry(entry, cas_page_t, list);
+}
+
+
+static void cas_mif_poll(struct cas *cp, const int enable)
+{
+       u32 cfg;
+       
+       cfg  = readl(cp->regs + REG_MIF_CFG); 
+       cfg &= (MIF_CFG_MDIO_0 | MIF_CFG_MDIO_1);
+
+       if (cp->phy_type & CAS_PHY_MII_MDIO1)
+               cfg |= MIF_CFG_PHY_SELECT; 
+
+       /* poll and interrupt on link status change. */
+       if (enable) {
+               cfg |= MIF_CFG_POLL_EN;
+               cfg |= CAS_BASE(MIF_CFG_POLL_REG, MII_BMSR);
+               cfg |= CAS_BASE(MIF_CFG_POLL_PHY, cp->phy_addr);
+       }
+       writel((enable) ? ~(BMSR_LSTATUS | BMSR_ANEGCOMPLETE) : 0xFFFF, 
+              cp->regs + REG_MIF_MASK); 
+       writel(cfg, cp->regs + REG_MIF_CFG);
+}
+
+/* Must be invoked under cp->lock */
+static void cas_begin_auto_negotiation(struct cas *cp, struct ethtool_cmd *ep)
+{
+       u16 ctl;
+#if 1
+       int lcntl;
+       int changed = 0;
+       int oldstate = cp->lstate;
+       int link_was_not_down = !(oldstate == link_down);
+#endif
+       /* Setup link parameters */
+       if (!ep)
+               goto start_aneg;
+       lcntl = cp->link_cntl;
+       if (ep->autoneg == AUTONEG_ENABLE)
+               cp->link_cntl = BMCR_ANENABLE;
+       else {
+               cp->link_cntl = 0;
+               if (ep->speed == SPEED_100)
+                       cp->link_cntl |= BMCR_SPEED100;
+               else if (ep->speed == SPEED_1000)
+                       cp->link_cntl |= CAS_BMCR_SPEED1000;
+               if (ep->duplex == DUPLEX_FULL)
+                       cp->link_cntl |= BMCR_FULLDPLX;
+       }
+#if 1
+       changed = (lcntl != cp->link_cntl);
+#endif
+start_aneg:
+       if (cp->lstate == link_up) {
+               printk(KERN_INFO "%s: PCS link down.\n",
+                      cp->dev->name);
+       } else {
+               if (changed) {
+                       printk(KERN_INFO "%s: link configuration changed\n",
+                              cp->dev->name);
+               }
+       }
+       cp->lstate = link_down;
+       cp->link_transition = LINK_TRANSITION_LINK_DOWN;
+       if (!cp->hw_running)
+               return;
+#if 1
+       /*
+        * WTZ: If the old state was link_up, we turn off the carrier
+        * to replicate everything we do elsewhere on a link-down
+        * event when we were already in a link-up state..  
+        */
+       if (oldstate == link_up)
+               netif_carrier_off(cp->dev);
+       if (changed  && link_was_not_down) {
+               /*
+                * WTZ: This branch will simply schedule a full reset after
+                * we explicitly changed link modes in an ioctl. See if this
+                * fixes the link-problems we were having for forced mode. 
+                */
+               atomic_inc(&cp->reset_task_pending);
+               atomic_inc(&cp->reset_task_pending_all);
+               schedule_work(&cp->reset_task);
+               cp->timer_ticks = 0;
+               mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT);
+               return;
+       }
+#endif
+       if (cp->phy_type & CAS_PHY_SERDES) {
+               u32 val = readl(cp->regs + REG_PCS_MII_CTRL);
+
+               if (cp->link_cntl & BMCR_ANENABLE) {
+                       val |= (PCS_MII_RESTART_AUTONEG | PCS_MII_AUTONEG_EN);
+                       cp->lstate = link_aneg;
+               } else {
+                       if (cp->link_cntl & BMCR_FULLDPLX)
+                               val |= PCS_MII_CTRL_DUPLEX;
+                       val &= ~PCS_MII_AUTONEG_EN;
+                       cp->lstate = link_force_ok;
+               }
+               cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
+               writel(val, cp->regs + REG_PCS_MII_CTRL);
+
+       } else {
+               cas_mif_poll(cp, 0);
+               ctl = cas_phy_read(cp, MII_BMCR);
+               ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | 
+                        CAS_BMCR_SPEED1000 | BMCR_ANENABLE);
+               ctl |= cp->link_cntl;
+               if (ctl & BMCR_ANENABLE) {
+                       ctl |= BMCR_ANRESTART;
+                       cp->lstate = link_aneg;
+               } else {
+                       cp->lstate = link_force_ok;
+               }
+               cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
+               cas_phy_write(cp, MII_BMCR, ctl);
+               cas_mif_poll(cp, 1);
+       }
+
+       cp->timer_ticks = 0;
+       mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT);
+}
+
+/* Must be invoked under cp->lock. */
+static int cas_reset_mii_phy(struct cas *cp)
+{
+       int limit = STOP_TRIES_PHY;
+       u16 val;
+       
+       cas_phy_write(cp, MII_BMCR, BMCR_RESET);
+       udelay(100);
+       while (limit--) {
+               val = cas_phy_read(cp, MII_BMCR);
+               if ((val & BMCR_RESET) == 0)
+                       break;
+               udelay(10);
+       }
+       return (limit <= 0);
+}
+
+static void cas_saturn_firmware_load(struct cas *cp)
+{
+       cas_saturn_patch_t *patch = cas_saturn_patch;
+
+       cas_phy_powerdown(cp);
+
+       /* expanded memory access mode */
+       cas_phy_write(cp, DP83065_MII_MEM, 0x0);
+
+       /* pointer configuration for new firmware */
+       cas_phy_write(cp, DP83065_MII_REGE, 0x8ff9);
+       cas_phy_write(cp, DP83065_MII_REGD, 0xbd);
+       cas_phy_write(cp, DP83065_MII_REGE, 0x8ffa);
+       cas_phy_write(cp, DP83065_MII_REGD, 0x82);
+       cas_phy_write(cp, DP83065_MII_REGE, 0x8ffb);
+       cas_phy_write(cp, DP83065_MII_REGD, 0x0);
+       cas_phy_write(cp, DP83065_MII_REGE, 0x8ffc);
+       cas_phy_write(cp, DP83065_MII_REGD, 0x39);
+
+       /* download new firmware */
+       cas_phy_write(cp, DP83065_MII_MEM, 0x1);
+       cas_phy_write(cp, DP83065_MII_REGE, patch->addr);
+       while (patch->addr) {
+               cas_phy_write(cp, DP83065_MII_REGD, patch->val);
+               patch++;
+       }
+
+       /* enable firmware */
+       cas_phy_write(cp, DP83065_MII_REGE, 0x8ff8);
+       cas_phy_write(cp, DP83065_MII_REGD, 0x1);
+}
+
+
+/* phy initialization */
+static void cas_phy_init(struct cas *cp)
+{
+       u16 val;
+
+       /* if we're in MII/GMII mode, set up phy */
+       if (CAS_PHY_MII(cp->phy_type)) {
+               writel(PCS_DATAPATH_MODE_MII,
+                      cp->regs + REG_PCS_DATAPATH_MODE);
+
+               cas_mif_poll(cp, 0);
+               cas_reset_mii_phy(cp); /* take out of isolate mode */
+
+               if (PHY_LUCENT_B0 == cp->phy_id) {
+                       /* workaround link up/down issue with lucent */
+                       cas_phy_write(cp, LUCENT_MII_REG, 0x8000);
+                       cas_phy_write(cp, MII_BMCR, 0x00f1);
+                       cas_phy_write(cp, LUCENT_MII_REG, 0x0);
+
+               } else if (PHY_BROADCOM_B0 == (cp->phy_id & 0xFFFFFFFC)) {
+                       /* workarounds for broadcom phy */
+                       cas_phy_write(cp, BROADCOM_MII_REG8, 0x0C20);
+                       cas_phy_write(cp, BROADCOM_MII_REG7, 0x0012);
+                       cas_phy_write(cp, BROADCOM_MII_REG5, 0x1804);
+                       cas_phy_write(cp, BROADCOM_MII_REG7, 0x0013);
+                       cas_phy_write(cp, BROADCOM_MII_REG5, 0x1204);
+                       cas_phy_write(cp, BROADCOM_MII_REG7, 0x8006);
+                       cas_phy_write(cp, BROADCOM_MII_REG5, 0x0132);
+                       cas_phy_write(cp, BROADCOM_MII_REG7, 0x8006);
+                       cas_phy_write(cp, BROADCOM_MII_REG5, 0x0232);
+                       cas_phy_write(cp, BROADCOM_MII_REG7, 0x201F);
+                       cas_phy_write(cp, BROADCOM_MII_REG5, 0x0A20);
+
+               } else if (PHY_BROADCOM_5411 == cp->phy_id) {
+                       val = cas_phy_read(cp, BROADCOM_MII_REG4);
+                       val = cas_phy_read(cp, BROADCOM_MII_REG4);
+                       if (val & 0x0080) {
+                               /* link workaround */
+                               cas_phy_write(cp, BROADCOM_MII_REG4, 
+                                             val & ~0x0080);
+                       }
+                       
+               } else if (cp->cas_flags & CAS_FLAG_SATURN) {
+                       writel((cp->phy_type & CAS_PHY_MII_MDIO0) ? 
+                              SATURN_PCFG_FSI : 0x0, 
+                              cp->regs + REG_SATURN_PCFG);
+
+                       /* load firmware to address 10Mbps auto-negotiation
+                        * issue. NOTE: this will need to be changed if the 
+                        * default firmware gets fixed.
+                        */
+                       if (PHY_NS_DP83065 == cp->phy_id) {
+                               cas_saturn_firmware_load(cp);
+                       }
+                       cas_phy_powerup(cp);
+               }
+
+               /* advertise capabilities */
+               val = cas_phy_read(cp, MII_BMCR);
+               val &= ~BMCR_ANENABLE;
+               cas_phy_write(cp, MII_BMCR, val);
+               udelay(10);
+
+               cas_phy_write(cp, MII_ADVERTISE,
+                             cas_phy_read(cp, MII_ADVERTISE) |
+                             (ADVERTISE_10HALF | ADVERTISE_10FULL |
+                              ADVERTISE_100HALF | ADVERTISE_100FULL |
+                              CAS_ADVERTISE_PAUSE | 
+                              CAS_ADVERTISE_ASYM_PAUSE));
+               
+               if (cp->cas_flags & CAS_FLAG_1000MB_CAP) {
+                       /* make sure that we don't advertise half
+                        * duplex to avoid a chip issue
+                        */
+                       val  = cas_phy_read(cp, CAS_MII_1000_CTRL);
+                       val &= ~CAS_ADVERTISE_1000HALF;
+                       val |= CAS_ADVERTISE_1000FULL;
+                       cas_phy_write(cp, CAS_MII_1000_CTRL, val);
+               }
+
+       } else {
+               /* reset pcs for serdes */
+               u32 val;
+               int limit;
+
+               writel(PCS_DATAPATH_MODE_SERDES,
+                      cp->regs + REG_PCS_DATAPATH_MODE);
+
+               /* enable serdes pins on saturn */
+               if (cp->cas_flags & CAS_FLAG_SATURN)
+                       writel(0, cp->regs + REG_SATURN_PCFG);
+
+               /* Reset PCS unit. */
+               val = readl(cp->regs + REG_PCS_MII_CTRL);
+               val |= PCS_MII_RESET;
+               writel(val, cp->regs + REG_PCS_MII_CTRL);
+
+               limit = STOP_TRIES;
+               while (limit-- > 0) {
+                       udelay(10);
+                       if ((readl(cp->regs + REG_PCS_MII_CTRL) & 
+                            PCS_MII_RESET) == 0)
+                               break;
+               }
+               if (limit <= 0)
+                       printk(KERN_WARNING "%s: PCS reset bit would not "
+                              "clear [%08x].\n", cp->dev->name,
+                              readl(cp->regs + REG_PCS_STATE_MACHINE));
+
+               /* Make sure PCS is disabled while changing advertisement
+                * configuration.
+                */
+               writel(0x0, cp->regs + REG_PCS_CFG);
+
+               /* Advertise all capabilities except half-duplex. */
+               val  = readl(cp->regs + REG_PCS_MII_ADVERT);
+               val &= ~PCS_MII_ADVERT_HD;
+               val |= (PCS_MII_ADVERT_FD | PCS_MII_ADVERT_SYM_PAUSE | 
+                       PCS_MII_ADVERT_ASYM_PAUSE);
+               writel(val, cp->regs + REG_PCS_MII_ADVERT);
+
+               /* enable PCS */
+               writel(PCS_CFG_EN, cp->regs + REG_PCS_CFG);
+
+               /* pcs workaround: enable sync detect */
+               writel(PCS_SERDES_CTRL_SYNCD_EN,
+                      cp->regs + REG_PCS_SERDES_CTRL);
+       }
+}
+
+
+static int cas_pcs_link_check(struct cas *cp)
+{
+       u32 stat, state_machine;
+       int retval = 0;
+
+       /* The link status bit latches on zero, so you must
+        * read it twice in such a case to see a transition
+        * to the link being up.
+        */
+       stat = readl(cp->regs + REG_PCS_MII_STATUS);
+       if ((stat & PCS_MII_STATUS_LINK_STATUS) == 0)
+               stat = readl(cp->regs + REG_PCS_MII_STATUS);
+
+       /* The remote-fault indication is only valid
+        * when autoneg has completed.
+        */
+       if ((stat & (PCS_MII_STATUS_AUTONEG_COMP |
+                    PCS_MII_STATUS_REMOTE_FAULT)) ==
+           (PCS_MII_STATUS_AUTONEG_COMP | PCS_MII_STATUS_REMOTE_FAULT)) {
+               if (netif_msg_link(cp))
+                       printk(KERN_INFO "%s: PCS RemoteFault\n", 
+                              cp->dev->name);
+       }
+
+       /* work around link detection issue by querying the PCS state
+        * machine directly.
+        */
+       state_machine = readl(cp->regs + REG_PCS_STATE_MACHINE);
+       if ((state_machine & PCS_SM_LINK_STATE_MASK) != SM_LINK_STATE_UP) {
+               stat &= ~PCS_MII_STATUS_LINK_STATUS;
+       } else if (state_machine & PCS_SM_WORD_SYNC_STATE_MASK) {
+               stat |= PCS_MII_STATUS_LINK_STATUS;
+       }
+
+       if (stat & PCS_MII_STATUS_LINK_STATUS) {
+               if (cp->lstate != link_up) {
+                       if (cp->opened) {
+                               cp->lstate = link_up;
+                               cp->link_transition = LINK_TRANSITION_LINK_UP;
+                               
+                               cas_set_link_modes(cp);
+                               netif_carrier_on(cp->dev);
+                       }
+               }
+       } else if (cp->lstate == link_up) {
+               cp->lstate = link_down;
+               if (link_transition_timeout != 0 &&
+                   cp->link_transition != LINK_TRANSITION_REQUESTED_RESET &&
+                   !cp->link_transition_jiffies_valid) {
+                       /*
+                        * force a reset, as a workaround for the 
+                        * link-failure problem. May want to move this to a 
+                        * point a bit earlier in the sequence. If we had
+                        * generated a reset a short time ago, we'll wait for
+                        * the link timer to check the status until a
+                        * timer expires (link_transistion_jiffies_valid is
+                        * true when the timer is running.)  Instead of using
+                        * a system timer, we just do a check whenever the
+                        * link timer is running - this clears the flag after
+                        * a suitable delay.
+                        */
+                       retval = 1;
+                       cp->link_transition = LINK_TRANSITION_REQUESTED_RESET;
+                       cp->link_transition_jiffies = jiffies;
+                       cp->link_transition_jiffies_valid = 1;
+               } else {
+                       cp->link_transition = LINK_TRANSITION_ON_FAILURE;
+               }
+               netif_carrier_off(cp->dev);
+               if (cp->opened && netif_msg_link(cp)) {
+                       printk(KERN_INFO "%s: PCS link down.\n",
+                              cp->dev->name);
+               }
+
+               /* Cassini only: if you force a mode, there can be
+                * sync problems on link down. to fix that, the following
+                * things need to be checked:
+                * 1) read serialink state register
+                * 2) read pcs status register to verify link down.
+                * 3) if link down and serial link == 0x03, then you need
+                *    to global reset the chip.
+                */
+               if ((cp->cas_flags & CAS_FLAG_REG_PLUS) == 0) {
+                       /* should check to see if we're in a forced mode */
+                       stat = readl(cp->regs + REG_PCS_SERDES_STATE);
+                       if (stat == 0x03)
+                               return 1;
+               }
+       } else if (cp->lstate == link_down) {
+               if (link_transition_timeout != 0 &&
+                   cp->link_transition != LINK_TRANSITION_REQUESTED_RESET &&
+                   !cp->link_transition_jiffies_valid) {
+                       /* force a reset, as a workaround for the
+                        * link-failure problem.  May want to move
+                        * this to a point a bit earlier in the
+                        * sequence.
+                        */
+                       retval = 1;
+                       cp->link_transition = LINK_TRANSITION_REQUESTED_RESET;
+                       cp->link_transition_jiffies = jiffies;
+                       cp->link_transition_jiffies_valid = 1;
+               } else {
+                       cp->link_transition = LINK_TRANSITION_STILL_FAILED;
+               }
+       }
+
+       return retval;
+}
+
+static int cas_pcs_interrupt(struct net_device *dev, 
+                            struct cas *cp, u32 status)
+{
+       u32 stat = readl(cp->regs + REG_PCS_INTR_STATUS);
+
+       if ((stat & PCS_INTR_STATUS_LINK_CHANGE) == 0) 
+               return 0;
+       return cas_pcs_link_check(cp);
+}
+
+static int cas_txmac_interrupt(struct net_device *dev, 
+                              struct cas *cp, u32 status)
+{
+       u32 txmac_stat = readl(cp->regs + REG_MAC_TX_STATUS);
+
+       if (!txmac_stat)
+               return 0;
+
+       if (netif_msg_intr(cp))
+               printk(KERN_DEBUG "%s: txmac interrupt, txmac_stat: 0x%x\n",
+                       cp->dev->name, txmac_stat);
+
+       /* Defer timer expiration is quite normal,
+        * don't even log the event.
+        */
+       if ((txmac_stat & MAC_TX_DEFER_TIMER) &&
+           !(txmac_stat & ~MAC_TX_DEFER_TIMER))
+               return 0;
+
+       spin_lock(&cp->stat_lock[0]);
+       if (txmac_stat & MAC_TX_UNDERRUN) {
+               printk(KERN_ERR "%s: TX MAC xmit underrun.\n",
+                      dev->name);
+               cp->net_stats[0].tx_fifo_errors++;
+       }
+
+       if (txmac_stat & MAC_TX_MAX_PACKET_ERR) {
+               printk(KERN_ERR "%s: TX MAC max packet size error.\n",
+                      dev->name);
+               cp->net_stats[0].tx_errors++;
+       }
+
+       /* The rest are all cases of one of the 16-bit TX
+        * counters expiring.
+        */
+       if (txmac_stat & MAC_TX_COLL_NORMAL)
+               cp->net_stats[0].collisions += 0x10000;
+
+       if (txmac_stat & MAC_TX_COLL_EXCESS) {
+               cp->net_stats[0].tx_aborted_errors += 0x10000;
+               cp->net_stats[0].collisions += 0x10000;
+       }
+
+       if (txmac_stat & MAC_TX_COLL_LATE) {
+               cp->net_stats[0].tx_aborted_errors += 0x10000;
+               cp->net_stats[0].collisions += 0x10000;
+       }
+       spin_unlock(&cp->stat_lock[0]);
+
+       /* We do not keep track of MAC_TX_COLL_FIRST and
+        * MAC_TX_PEAK_ATTEMPTS events.
+        */
+       return 0;
+}
+
+static void cas_load_firmware(struct cas *cp, cas_hp_inst_t *firmware) 
+{
+       cas_hp_inst_t *inst;
+       u32 val;
+       int i;
+
+       i = 0;
+       while ((inst = firmware) && inst->note) {
+               writel(i, cp->regs + REG_HP_INSTR_RAM_ADDR);
+
+               val = CAS_BASE(HP_INSTR_RAM_HI_VAL, inst->val);
+               val |= CAS_BASE(HP_INSTR_RAM_HI_MASK, inst->mask);
+               writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_HI);
+
+               val = CAS_BASE(HP_INSTR_RAM_MID_OUTARG, inst->outarg >> 10);
+               val |= CAS_BASE(HP_INSTR_RAM_MID_OUTOP, inst->outop);
+               val |= CAS_BASE(HP_INSTR_RAM_MID_FNEXT, inst->fnext);
+               val |= CAS_BASE(HP_INSTR_RAM_MID_FOFF, inst->foff);
+               val |= CAS_BASE(HP_INSTR_RAM_MID_SNEXT, inst->snext);
+               val |= CAS_BASE(HP_INSTR_RAM_MID_SOFF, inst->soff);
+               val |= CAS_BASE(HP_INSTR_RAM_MID_OP, inst->op);
+               writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_MID);
+
+               val = CAS_BASE(HP_INSTR_RAM_LOW_OUTMASK, inst->outmask);
+               val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTSHIFT, inst->outshift);
+               val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTEN, inst->outenab);
+               val |= CAS_BASE(HP_INSTR_RAM_LOW_OUTARG, inst->outarg);
+               writel(val, cp->regs + REG_HP_INSTR_RAM_DATA_LOW);
+               ++firmware;
+               ++i;
+       }
+}
+
+static void cas_init_rx_dma(struct cas *cp)
+{
+       u64 desc_dma = cp->block_dvma; 
+       u32 val;
+       int i, size;
+
+       /* rx free descriptors */
+       val = CAS_BASE(RX_CFG_SWIVEL, RX_SWIVEL_OFF_VAL); 
+       val |= CAS_BASE(RX_CFG_DESC_RING, RX_DESC_RINGN_INDEX(0));
+       val |= CAS_BASE(RX_CFG_COMP_RING, RX_COMP_RINGN_INDEX(0));
+       if ((N_RX_DESC_RINGS > 1) &&
+           (cp->cas_flags & CAS_FLAG_REG_PLUS))  /* do desc 2 */
+               val |= CAS_BASE(RX_CFG_DESC_RING1, RX_DESC_RINGN_INDEX(1));
+       writel(val, cp->regs + REG_RX_CFG);
+
+       val = (unsigned long) cp->init_rxds[0] - 
+               (unsigned long) cp->init_block;
+       writel((desc_dma + val) >> 32, cp->regs + REG_RX_DB_HI);
+       writel((desc_dma + val) & 0xffffffff, cp->regs + REG_RX_DB_LOW);
+       writel(RX_DESC_RINGN_SIZE(0) - 4, cp->regs + REG_RX_KICK);
+
+       if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+               /* rx desc 2 is for IPSEC packets. however, 
+                * we don't it that for that purpose.
+                */
+               val = (unsigned long) cp->init_rxds[1] - 
+                       (unsigned long) cp->init_block;
+               writel((desc_dma + val) >> 32, cp->regs + REG_PLUS_RX_DB1_HI);
+               writel((desc_dma + val) & 0xffffffff, cp->regs + 
+                      REG_PLUS_RX_DB1_LOW);
+               writel(RX_DESC_RINGN_SIZE(1) - 4, cp->regs + 
+                      REG_PLUS_RX_KICK1);
+       }
+       
+       /* rx completion registers */
+       val = (unsigned long) cp->init_rxcs[0] - 
+               (unsigned long) cp->init_block;
+       writel((desc_dma + val) >> 32, cp->regs + REG_RX_CB_HI);
+       writel((desc_dma + val) & 0xffffffff, cp->regs + REG_RX_CB_LOW);
+
+       if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+               /* rx comp 2-4 */
+               for (i = 1; i < MAX_RX_COMP_RINGS; i++) {
+                       val = (unsigned long) cp->init_rxcs[i] - 
+                               (unsigned long) cp->init_block;
+                       writel((desc_dma + val) >> 32, cp->regs + 
+                              REG_PLUS_RX_CBN_HI(i));
+                       writel((desc_dma + val) & 0xffffffff, cp->regs + 
+                              REG_PLUS_RX_CBN_LOW(i));
+               }
+       }
+
+       /* read selective clear regs to prevent spurious interrupts
+        * on reset because complete == kick.
+        * selective clear set up to prevent interrupts on resets
+        */
+       readl(cp->regs + REG_INTR_STATUS_ALIAS);
+       writel(INTR_RX_DONE | INTR_RX_BUF_UNAVAIL, cp->regs + REG_ALIAS_CLEAR);
+       if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+               for (i = 1; i < N_RX_COMP_RINGS; i++)
+                       readl(cp->regs + REG_PLUS_INTRN_STATUS_ALIAS(i));
+
+               /* 2 is different from 3 and 4 */
+               if (N_RX_COMP_RINGS > 1)
+                       writel(INTR_RX_DONE_ALT | INTR_RX_BUF_UNAVAIL_1, 
+                              cp->regs + REG_PLUS_ALIASN_CLEAR(1));
+
+               for (i = 2; i < N_RX_COMP_RINGS; i++) 
+                       writel(INTR_RX_DONE_ALT, 
+                              cp->regs + REG_PLUS_ALIASN_CLEAR(i));
+       }
+
+       /* set up pause thresholds */
+       val  = CAS_BASE(RX_PAUSE_THRESH_OFF,
+                       cp->rx_pause_off / RX_PAUSE_THRESH_QUANTUM);
+       val |= CAS_BASE(RX_PAUSE_THRESH_ON, 
+                       cp->rx_pause_on / RX_PAUSE_THRESH_QUANTUM);
+       writel(val, cp->regs + REG_RX_PAUSE_THRESH);
+       
+       /* zero out dma reassembly buffers */
+       for (i = 0; i < 64; i++) {
+               writel(i, cp->regs + REG_RX_TABLE_ADDR);
+               writel(0x0, cp->regs + REG_RX_TABLE_DATA_LOW);
+               writel(0x0, cp->regs + REG_RX_TABLE_DATA_MID);
+               writel(0x0, cp->regs + REG_RX_TABLE_DATA_HI);
+       }
+
+       /* make sure address register is 0 for normal operation */
+       writel(0x0, cp->regs + REG_RX_CTRL_FIFO_ADDR);
+       writel(0x0, cp->regs + REG_RX_IPP_FIFO_ADDR);
+
+       /* interrupt mitigation */
+#ifdef USE_RX_BLANK
+       val = CAS_BASE(RX_BLANK_INTR_TIME, RX_BLANK_INTR_TIME_VAL);
+       val |= CAS_BASE(RX_BLANK_INTR_PKT, RX_BLANK_INTR_PKT_VAL);
+       writel(val, cp->regs + REG_RX_BLANK);
+#else
+       writel(0x0, cp->regs + REG_RX_BLANK);
+#endif
+
+       /* interrupt generation as a function of low water marks for
+        * free desc and completion entries. these are used to trigger
+        * housekeeping for rx descs. we don't use the free interrupt
+        * as it's not very useful
+        */
+       /* val = CAS_BASE(RX_AE_THRESH_FREE, RX_AE_FREEN_VAL(0)); */
+       val = CAS_BASE(RX_AE_THRESH_COMP, RX_AE_COMP_VAL);
+       writel(val, cp->regs + REG_RX_AE_THRESH);
+       if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+               val = CAS_BASE(RX_AE1_THRESH_FREE, RX_AE_FREEN_VAL(1));
+               writel(val, cp->regs + REG_PLUS_RX_AE1_THRESH);
+       }
+
+       /* Random early detect registers. useful for congestion avoidance.
+        * this should be tunable.
+        */
+       writel(0x0, cp->regs + REG_RX_RED);
+       
+       /* receive page sizes. default == 2K (0x800) */
+       val = 0;
+       if (cp->page_size == 0x1000)
+               val = 0x1;
+       else if (cp->page_size == 0x2000)
+               val = 0x2;
+       else if (cp->page_size == 0x4000)
+               val = 0x3;
+       
+       /* round mtu + offset. constrain to page size. */
+       size = cp->dev->mtu + 64;
+       if (size > cp->page_size)
+               size = cp->page_size;
+
+       if (size <= 0x400)
+               i = 0x0;
+       else if (size <= 0x800)
+               i = 0x1;
+       else if (size <= 0x1000)
+               i = 0x2;
+       else
+               i = 0x3;
+
+       cp->mtu_stride = 1 << (i + 10);
+       val  = CAS_BASE(RX_PAGE_SIZE, val);
+       val |= CAS_BASE(RX_PAGE_SIZE_MTU_STRIDE, i); 
+       val |= CAS_BASE(RX_PAGE_SIZE_MTU_COUNT, cp->page_size >> (i + 10));
+       val |= CAS_BASE(RX_PAGE_SIZE_MTU_OFF, 0x1);
+       writel(val, cp->regs + REG_RX_PAGE_SIZE);
+       
+       /* enable the header parser if desired */
+       if (CAS_HP_FIRMWARE == cas_prog_null)
+               return;
+
+       val = CAS_BASE(HP_CFG_NUM_CPU, CAS_NCPUS > 63 ? 0 : CAS_NCPUS);
+       val |= HP_CFG_PARSE_EN | HP_CFG_SYN_INC_MASK;
+       val |= CAS_BASE(HP_CFG_TCP_THRESH, HP_TCP_THRESH_VAL);
+       writel(val, cp->regs + REG_HP_CFG);
+}
+
+static inline void cas_rxc_init(struct cas_rx_comp *rxc)
+{
+       memset(rxc, 0, sizeof(*rxc));
+       rxc->word4 = cpu_to_le64(RX_COMP4_ZERO); 
+}
+
+/* NOTE: we use the ENC RX DESC ring for spares. the rx_page[0,1]
+ * flipping is protected by the fact that the chip will not
+ * hand back the same page index while it's being processed.
+ */
+static inline cas_page_t *cas_page_spare(struct cas *cp, const int index)
+{
+       cas_page_t *page = cp->rx_pages[1][index];
+       cas_page_t *new;
+
+       if (page_count(page->buffer) == 1)
+               return page;
+
+       new = cas_page_dequeue(cp);
+       if (new) {
+               spin_lock(&cp->rx_inuse_lock);
+               list_add(&page->list, &cp->rx_inuse_list);
+               spin_unlock(&cp->rx_inuse_lock);
+       }
+       return new;
+}
+                                  
+/* this needs to be changed if we actually use the ENC RX DESC ring */
+static cas_page_t *cas_page_swap(struct cas *cp, const int ring, 
+                                const int index)
+{
+       cas_page_t **page0 = cp->rx_pages[0];
+       cas_page_t **page1 = cp->rx_pages[1];
+
+       /* swap if buffer is in use */
+       if (page_count(page0[index]->buffer) > 1) {
+               cas_page_t *new = cas_page_spare(cp, index);
+               if (new) {
+                       page1[index] = page0[index];
+                       page0[index] = new;
+               }
+       } 
+       RX_USED_SET(page0[index], 0);
+       return page0[index];
+}
+
+static void cas_clean_rxds(struct cas *cp)
+{
+       /* only clean ring 0 as ring 1 is used for spare buffers */
+        struct cas_rx_desc *rxd = cp->init_rxds[0];
+       int i, size;
+
+       /* release all rx flows */
+       for (i = 0; i < N_RX_FLOWS; i++) {
+               struct sk_buff *skb;
+               while ((skb = __skb_dequeue(&cp->rx_flows[i]))) {
+                       cas_skb_release(skb);
+               }
+       }
+
+       /* initialize descriptors */
+       size = RX_DESC_RINGN_SIZE(0);
+       for (i = 0; i < size; i++) {
+               cas_page_t *page = cas_page_swap(cp, 0, i);
+               rxd[i].buffer = cpu_to_le64(page->dma_addr);
+               rxd[i].index  = cpu_to_le64(CAS_BASE(RX_INDEX_NUM, i) | 
+                                           CAS_BASE(RX_INDEX_RING, 0));
+       }
+
+       cp->rx_old[0]  = RX_DESC_RINGN_SIZE(0) - 4; 
+       cp->rx_last[0] = 0;
+       cp->cas_flags &= ~CAS_FLAG_RXD_POST(0);
+}
+
+static void cas_clean_rxcs(struct cas *cp)
+{
+       int i, j;
+
+       /* take ownership of rx comp descriptors */
+       memset(cp->rx_cur, 0, sizeof(*cp->rx_cur)*N_RX_COMP_RINGS);
+       memset(cp->rx_new, 0, sizeof(*cp->rx_new)*N_RX_COMP_RINGS);
+       for (i = 0; i < N_RX_COMP_RINGS; i++) {
+               struct cas_rx_comp *rxc = cp->init_rxcs[i];
+               for (j = 0; j < RX_COMP_RINGN_SIZE(i); j++) {
+                       cas_rxc_init(rxc + j);
+               }
+       }
+}
+
+#if 0
+/* When we get a RX fifo overflow, the RX unit is probably hung
+ * so we do the following.
+ *
+ * If any part of the reset goes wrong, we return 1 and that causes the
+ * whole chip to be reset.
+ */
+static int cas_rxmac_reset(struct cas *cp)
+{
+       struct net_device *dev = cp->dev;
+       int limit;
+       u32 val;
+
+       /* First, reset MAC RX. */
+       writel(cp->mac_rx_cfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
+       for (limit = 0; limit < STOP_TRIES; limit++) {
+               if (!(readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_EN))
+                       break;
+               udelay(10);
+       }
+       if (limit == STOP_TRIES) {
+               printk(KERN_ERR "%s: RX MAC will not disable, resetting whole "
+                      "chip.\n", dev->name);
+               return 1;
+       }
+
+       /* Second, disable RX DMA. */
+       writel(0, cp->regs + REG_RX_CFG);
+       for (limit = 0; limit < STOP_TRIES; limit++) {
+               if (!(readl(cp->regs + REG_RX_CFG) & RX_CFG_DMA_EN))
+                       break;
+               udelay(10);
+       }
+       if (limit == STOP_TRIES) {
+               printk(KERN_ERR "%s: RX DMA will not disable, resetting whole "
+                      "chip.\n", dev->name);
+               return 1;
+       }
+
+       mdelay(5);
+
+       /* Execute RX reset command. */
+       writel(SW_RESET_RX, cp->regs + REG_SW_RESET);
+       for (limit = 0; limit < STOP_TRIES; limit++) {
+               if (!(readl(cp->regs + REG_SW_RESET) & SW_RESET_RX))
+                       break;
+               udelay(10);
+       }
+       if (limit == STOP_TRIES) {
+               printk(KERN_ERR "%s: RX reset command will not execute, "
+                      "resetting whole chip.\n", dev->name);
+               return 1;
+       }
+
+       /* reset driver rx state */
+       cas_clean_rxds(cp);
+       cas_clean_rxcs(cp);
+
+       /* Now, reprogram the rest of RX unit. */
+       cas_init_rx_dma(cp);
+
+       /* re-enable */
+       val = readl(cp->regs + REG_RX_CFG);
+       writel(val | RX_CFG_DMA_EN, cp->regs + REG_RX_CFG);
+       writel(MAC_RX_FRAME_RECV, cp->regs + REG_MAC_RX_MASK);
+       val = readl(cp->regs + REG_MAC_RX_CFG);
+       writel(val | MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
+       return 0;
+}
+#endif
+
+static int cas_rxmac_interrupt(struct net_device *dev, struct cas *cp,
+                              u32 status)
+{
+       u32 stat = readl(cp->regs + REG_MAC_RX_STATUS);
+
+       if (!stat)
+               return 0;
+
+       if (netif_msg_intr(cp))
+               printk(KERN_DEBUG "%s: rxmac interrupt, stat: 0x%x\n",
+                       cp->dev->name, stat);
+
+       /* these are all rollovers */
+       spin_lock(&cp->stat_lock[0]);
+       if (stat & MAC_RX_ALIGN_ERR) 
+               cp->net_stats[0].rx_frame_errors += 0x10000;
+
+       if (stat & MAC_RX_CRC_ERR)
+               cp->net_stats[0].rx_crc_errors += 0x10000;
+
+       if (stat & MAC_RX_LEN_ERR)
+               cp->net_stats[0].rx_length_errors += 0x10000;
+
+       if (stat & MAC_RX_OVERFLOW) {
+               cp->net_stats[0].rx_over_errors++;
+               cp->net_stats[0].rx_fifo_errors++;
+       }
+
+       /* We do not track MAC_RX_FRAME_COUNT and MAC_RX_VIOL_ERR
+        * events.
+        */
+       spin_unlock(&cp->stat_lock[0]);
+       return 0;
+}
+
+static int cas_mac_interrupt(struct net_device *dev, struct cas *cp,
+                            u32 status)
+{
+       u32 stat = readl(cp->regs + REG_MAC_CTRL_STATUS);
+
+       if (!stat)
+               return 0;
+
+       if (netif_msg_intr(cp))
+               printk(KERN_DEBUG "%s: mac interrupt, stat: 0x%x\n",
+                       cp->dev->name, stat);
+
+       /* This interrupt is just for pause frame and pause
+        * tracking.  It is useful for diagnostics and debug
+        * but probably by default we will mask these events.
+        */
+       if (stat & MAC_CTRL_PAUSE_STATE)
+               cp->pause_entered++;
+
+       if (stat & MAC_CTRL_PAUSE_RECEIVED)
+               cp->pause_last_time_recvd = (stat >> 16);
+
+       return 0;
+}
+
+       
+/* Must be invoked under cp->lock. */
+static inline int cas_mdio_link_not_up(struct cas *cp)
+{
+       u16 val;
+       
+       switch (cp->lstate) {
+       case link_force_ret:
+               if (netif_msg_link(cp))
+                       printk(KERN_INFO "%s: Autoneg failed again, keeping"
+                               " forced mode\n", cp->dev->name);
+               cas_phy_write(cp, MII_BMCR, cp->link_fcntl);
+               cp->timer_ticks = 5;
+               cp->lstate = link_force_ok;
+               cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
+               break;
+               
+       case link_aneg:
+               val = cas_phy_read(cp, MII_BMCR);
+
+               /* Try forced modes. we try things in the following order:
+                * 1000 full -> 100 full/half -> 10 half
+                */
+               val &= ~(BMCR_ANRESTART | BMCR_ANENABLE);
+               val |= BMCR_FULLDPLX;
+               val |= (cp->cas_flags & CAS_FLAG_1000MB_CAP) ? 
+                       CAS_BMCR_SPEED1000 : BMCR_SPEED100;
+               cas_phy_write(cp, MII_BMCR, val);
+               cp->timer_ticks = 5;
+               cp->lstate = link_force_try;
+               cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
+               break;
+
+       case link_force_try:
+               /* Downgrade from 1000 to 100 to 10 Mbps if necessary. */
+               val = cas_phy_read(cp, MII_BMCR);
+               cp->timer_ticks = 5;
+               if (val & CAS_BMCR_SPEED1000) { /* gigabit */
+                       val &= ~CAS_BMCR_SPEED1000;
+                       val |= (BMCR_SPEED100 | BMCR_FULLDPLX);
+                       cas_phy_write(cp, MII_BMCR, val);
+                       break;
+               }
+
+               if (val & BMCR_SPEED100) {
+                       if (val & BMCR_FULLDPLX) /* fd failed */
+                               val &= ~BMCR_FULLDPLX;
+                       else { /* 100Mbps failed */
+                               val &= ~BMCR_SPEED100;
+                       }
+                       cas_phy_write(cp, MII_BMCR, val);
+                       break;
+               }
+       default:
+               break;
+       }
+       return 0;
+}
+
+
+/* must be invoked with cp->lock held */
+static int cas_mii_link_check(struct cas *cp, const u16 bmsr)
+{
+       int restart;
+
+       if (bmsr & BMSR_LSTATUS) {
+               /* Ok, here we got a link. If we had it due to a forced
+                * fallback, and we were configured for autoneg, we 
+                * retry a short autoneg pass. If you know your hub is
+                * broken, use ethtool ;)
+                */
+               if ((cp->lstate == link_force_try) && 
+                   (cp->link_cntl & BMCR_ANENABLE)) {
+                       cp->lstate = link_force_ret;
+                       cp->link_transition = LINK_TRANSITION_LINK_CONFIG;
+                       cas_mif_poll(cp, 0);
+                       cp->link_fcntl = cas_phy_read(cp, MII_BMCR);
+                       cp->timer_ticks = 5;
+                       if (cp->opened && netif_msg_link(cp))
+                               printk(KERN_INFO "%s: Got link after fallback, retrying"
+                                      " autoneg once...\n", cp->dev->name);
+                       cas_phy_write(cp, MII_BMCR,
+                                     cp->link_fcntl | BMCR_ANENABLE |
+                                     BMCR_ANRESTART);
+                       cas_mif_poll(cp, 1);
+
+               } else if (cp->lstate != link_up) {
+                       cp->lstate = link_up;
+                       cp->link_transition = LINK_TRANSITION_LINK_UP;
+
+                       if (cp->opened) {
+                               cas_set_link_modes(cp);
+                               netif_carrier_on(cp->dev);
+                       }
+               }
+               return 0;
+       }
+
+       /* link not up. if the link was previously up, we restart the
+        * whole process
+        */
+       restart = 0;
+       if (cp->lstate == link_up) {
+               cp->lstate = link_down;
+               cp->link_transition = LINK_TRANSITION_LINK_DOWN;
+
+               netif_carrier_off(cp->dev);
+               if (cp->opened && netif_msg_link(cp))
+                       printk(KERN_INFO "%s: Link down\n",
+                              cp->dev->name);
+               restart = 1;
+               
+       } else if (++cp->timer_ticks > 10)
+               cas_mdio_link_not_up(cp);
+               
+       return restart;
+}
+
+static int cas_mif_interrupt(struct net_device *dev, struct cas *cp,
+                            u32 status)
+{
+       u32 stat = readl(cp->regs + REG_MIF_STATUS);
+       u16 bmsr;
+
+       /* check for a link change */
+       if (CAS_VAL(MIF_STATUS_POLL_STATUS, stat) == 0)
+               return 0;
+
+       bmsr = CAS_VAL(MIF_STATUS_POLL_DATA, stat);
+       return cas_mii_link_check(cp, bmsr);
+}
+
+static int cas_pci_interrupt(struct net_device *dev, struct cas *cp,
+                            u32 status)
+{
+       u32 stat = readl(cp->regs + REG_PCI_ERR_STATUS);
+
+       if (!stat)
+               return 0;
+
+       printk(KERN_ERR "%s: PCI error [%04x:%04x] ", dev->name, stat,
+              readl(cp->regs + REG_BIM_DIAG));
+
+       /* cassini+ has this reserved */
+       if ((stat & PCI_ERR_BADACK) &&
+           ((cp->cas_flags & CAS_FLAG_REG_PLUS) == 0))
+               printk("<No ACK64# during ABS64 cycle> ");
+
+       if (stat & PCI_ERR_DTRTO)
+               printk("<Delayed transaction timeout> ");
+       if (stat & PCI_ERR_OTHER)
+               printk("<other> ");
+       if (stat & PCI_ERR_BIM_DMA_WRITE)
+               printk("<BIM DMA 0 write req> ");
+       if (stat & PCI_ERR_BIM_DMA_READ)
+               printk("<BIM DMA 0 read req> ");
+       printk("\n");
+
+       if (stat & PCI_ERR_OTHER) {
+               u16 cfg;
+
+               /* Interrogate PCI config space for the
+                * true cause.
+                */
+               pci_read_config_word(cp->pdev, PCI_STATUS, &cfg);
+               printk(KERN_ERR "%s: Read PCI cfg space status [%04x]\n",
+                      dev->name, cfg);
+               if (cfg & PCI_STATUS_PARITY)
+                       printk(KERN_ERR "%s: PCI parity error detected.\n",
+                              dev->name);
+               if (cfg & PCI_STATUS_SIG_TARGET_ABORT)
+                       printk(KERN_ERR "%s: PCI target abort.\n",
+                              dev->name);
+               if (cfg & PCI_STATUS_REC_TARGET_ABORT)
+                       printk(KERN_ERR "%s: PCI master acks target abort.\n",
+                              dev->name);
+               if (cfg & PCI_STATUS_REC_MASTER_ABORT)
+                       printk(KERN_ERR "%s: PCI master abort.\n", dev->name);
+               if (cfg & PCI_STATUS_SIG_SYSTEM_ERROR)
+                       printk(KERN_ERR "%s: PCI system error SERR#.\n",
+                              dev->name);
+               if (cfg & PCI_STATUS_DETECTED_PARITY)
+                       printk(KERN_ERR "%s: PCI parity error.\n",
+                              dev->name);
+
+               /* Write the error bits back to clear them. */
+               cfg &= (PCI_STATUS_PARITY |
+                       PCI_STATUS_SIG_TARGET_ABORT |
+                       PCI_STATUS_REC_TARGET_ABORT |
+                       PCI_STATUS_REC_MASTER_ABORT |
+                       PCI_STATUS_SIG_SYSTEM_ERROR |
+                       PCI_STATUS_DETECTED_PARITY);
+               pci_write_config_word(cp->pdev, PCI_STATUS, cfg);
+       }
+
+       /* For all PCI errors, we should reset the chip. */
+       return 1;
+}
+
+/* All non-normal interrupt conditions get serviced here.
+ * Returns non-zero if we should just exit the interrupt
+ * handler right now (ie. if we reset the card which invalidates
+ * all of the other original irq status bits).
+ */
+static int cas_abnormal_irq(struct net_device *dev, struct cas *cp,
+                           u32 status)
+{
+       if (status & INTR_RX_TAG_ERROR) {
+               /* corrupt RX tag framing */
+               if (netif_msg_rx_err(cp))
+                       printk(KERN_DEBUG "%s: corrupt rx tag framing\n",
+                               cp->dev->name);
+               spin_lock(&cp->stat_lock[0]);
+               cp->net_stats[0].rx_errors++;
+               spin_unlock(&cp->stat_lock[0]);
+               goto do_reset;
+       }
+
+       if (status & INTR_RX_LEN_MISMATCH) {
+               /* length mismatch. */
+               if (netif_msg_rx_err(cp))
+                       printk(KERN_DEBUG "%s: length mismatch for rx frame\n",
+                               cp->dev->name);
+               spin_lock(&cp->stat_lock[0]);
+               cp->net_stats[0].rx_errors++;
+               spin_unlock(&cp->stat_lock[0]);
+               goto do_reset;
+       }
+
+       if (status & INTR_PCS_STATUS) {
+               if (cas_pcs_interrupt(dev, cp, status))
+                       goto do_reset;
+       }
+
+       if (status & INTR_TX_MAC_STATUS) {
+               if (cas_txmac_interrupt(dev, cp, status))
+                       goto do_reset;
+       }
+
+       if (status & INTR_RX_MAC_STATUS) {
+               if (cas_rxmac_interrupt(dev, cp, status))
+                       goto do_reset;
+       }
+
+       if (status & INTR_MAC_CTRL_STATUS) {
+               if (cas_mac_interrupt(dev, cp, status))
+                       goto do_reset;
+       }
+
+       if (status & INTR_MIF_STATUS) {
+               if (cas_mif_interrupt(dev, cp, status))
+                       goto do_reset;
+       }
+
+       if (status & INTR_PCI_ERROR_STATUS) {
+               if (cas_pci_interrupt(dev, cp, status))
+                       goto do_reset;
+       }
+       return 0;
+
+do_reset:
+#if 1
+       atomic_inc(&cp->reset_task_pending);
+       atomic_inc(&cp->reset_task_pending_all);
+       printk(KERN_ERR "%s:reset called in cas_abnormal_irq [0x%x]\n",
+              dev->name, status);
+       schedule_work(&cp->reset_task);
+#else
+       atomic_set(&cp->reset_task_pending, CAS_RESET_ALL);
+       printk(KERN_ERR "reset called in cas_abnormal_irq\n");
+       schedule_work(&cp->reset_task);
+#endif
+       return 1;
+}
+
+/* NOTE: CAS_TABORT returns 1 or 2 so that it can be used when
+ *       determining whether to do a netif_stop/wakeup
+ */
+#define CAS_TABORT(x)      (((x)->cas_flags & CAS_FLAG_TARGET_ABORT) ? 2 : 1)
+#define CAS_ROUND_PAGE(x)  (((x) + PAGE_SIZE - 1) & PAGE_MASK)
+static inline int cas_calc_tabort(struct cas *cp, const unsigned long addr,
+                                 const int len)
+{
+       unsigned long off = addr + len;
+
+       if (CAS_TABORT(cp) == 1)
+               return 0;
+       if ((CAS_ROUND_PAGE(off) - off) > TX_TARGET_ABORT_LEN)
+               return 0;
+       return TX_TARGET_ABORT_LEN;
+}
+
+static inline void cas_tx_ringN(struct cas *cp, int ring, int limit)
+{
+       struct cas_tx_desc *txds;
+       struct sk_buff **skbs;
+       struct net_device *dev = cp->dev;
+       int entry, count;
+
+       spin_lock(&cp->tx_lock[ring]);
+       txds = cp->init_txds[ring];
+       skbs = cp->tx_skbs[ring];
+       entry = cp->tx_old[ring];
+
+       count = TX_BUFF_COUNT(ring, entry, limit);
+       while (entry != limit) {
+               struct sk_buff *skb = skbs[entry];
+               dma_addr_t daddr;
+               u32 dlen;
+               int frag;
+
+               if (!skb) {
+                       /* this should never occur */
+                       entry = TX_DESC_NEXT(ring, entry);
+                       continue;
+               }
+
+               /* however, we might get only a partial skb release. */
+               count -= skb_shinfo(skb)->nr_frags +
+                       + cp->tx_tiny_use[ring][entry].nbufs + 1;
+               if (count < 0)
+                       break;
+
+               if (netif_msg_tx_done(cp))
+                       printk(KERN_DEBUG "%s: tx[%d] done, slot %d\n",
+                              cp->dev->name, ring, entry);
+
+               skbs[entry] = NULL;
+               cp->tx_tiny_use[ring][entry].nbufs = 0;
+               
+               for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) {
+                       struct cas_tx_desc *txd = txds + entry;
+
+                       daddr = le64_to_cpu(txd->buffer);
+                       dlen = CAS_VAL(TX_DESC_BUFLEN,
+                                      le64_to_cpu(txd->control));
+                       pci_unmap_page(cp->pdev, daddr, dlen,
+                                      PCI_DMA_TODEVICE);
+                       entry = TX_DESC_NEXT(ring, entry);
+
+                       /* tiny buffer may follow */
+                       if (cp->tx_tiny_use[ring][entry].used) {
+                               cp->tx_tiny_use[ring][entry].used = 0;
+                               entry = TX_DESC_NEXT(ring, entry);
+                       } 
+               }
+
+               spin_lock(&cp->stat_lock[ring]);
+               cp->net_stats[ring].tx_packets++;
+               cp->net_stats[ring].tx_bytes += skb->len;
+               spin_unlock(&cp->stat_lock[ring]);
+               dev_kfree_skb_irq(skb);
+       }
+       cp->tx_old[ring] = entry;
+
+       /* this is wrong for multiple tx rings. the net device needs
+        * multiple queues for this to do the right thing.  we wait
+        * for 2*packets to be available when using tiny buffers
+        */
+       if (netif_queue_stopped(dev) &&
+           (TX_BUFFS_AVAIL(cp, ring) > CAS_TABORT(cp)*(MAX_SKB_FRAGS + 1)))
+               netif_wake_queue(dev);
+       spin_unlock(&cp->tx_lock[ring]);
+}
+
+static void cas_tx(struct net_device *dev, struct cas *cp,
+                  u32 status)
+{
+        int limit, ring;
+#ifdef USE_TX_COMPWB
+       u64 compwb = le64_to_cpu(cp->init_block->tx_compwb);
+#endif
+       if (netif_msg_intr(cp))
+               printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %lx\n",
+                       cp->dev->name, status, compwb);
+       /* process all the rings */
+       for (ring = 0; ring < N_TX_RINGS; ring++) {
+#ifdef USE_TX_COMPWB
+               /* use the completion writeback registers */
+               limit = (CAS_VAL(TX_COMPWB_MSB, compwb) << 8) |
+                       CAS_VAL(TX_COMPWB_LSB, compwb);
+               compwb = TX_COMPWB_NEXT(compwb);
+#else
+               limit = readl(cp->regs + REG_TX_COMPN(ring));
+#endif
+               if (cp->tx_old[ring] != limit) 
+                       cas_tx_ringN(cp, ring, limit);
+       }
+}
+
+
+static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, 
+                             int entry, const u64 *words, 
+                             struct sk_buff **skbref)
+{
+       int dlen, hlen, len, i, alloclen;
+       int off, swivel = RX_SWIVEL_OFF_VAL;
+       struct cas_page *page;
+       struct sk_buff *skb;
+       void *addr, *crcaddr;
+       char *p; 
+
+       hlen = CAS_VAL(RX_COMP2_HDR_SIZE, words[1]);
+       dlen = CAS_VAL(RX_COMP1_DATA_SIZE, words[0]);
+       len  = hlen + dlen;
+
+       if (RX_COPY_ALWAYS || (words[2] & RX_COMP3_SMALL_PKT)) 
+               alloclen = len;
+       else 
+               alloclen = max(hlen, RX_COPY_MIN);
+
+       skb = dev_alloc_skb(alloclen + swivel + cp->crc_size);
+       if (skb == NULL) 
+               return -1;
+
+       *skbref = skb;
+       skb->dev = cp->dev;
+       skb_reserve(skb, swivel);
+
+       p = skb->data;
+       addr = crcaddr = NULL;
+       if (hlen) { /* always copy header pages */
+               i = CAS_VAL(RX_COMP2_HDR_INDEX, words[1]);
+               page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
+               off = CAS_VAL(RX_COMP2_HDR_OFF, words[1]) * 0x100 + 
+                       swivel;
+
+               i = hlen;
+               if (!dlen) /* attach FCS */
+                       i += cp->crc_size;
+               pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i,
+                                   PCI_DMA_FROMDEVICE);
+               addr = cas_page_map(page->buffer);
+               memcpy(p, addr + off, i);
+               pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i,
+                                   PCI_DMA_FROMDEVICE);
+               cas_page_unmap(addr);
+               RX_USED_ADD(page, 0x100);
+               p += hlen;
+               swivel = 0;
+       } 
+
+
+       if (alloclen < (hlen + dlen)) {
+               skb_frag_t *frag = skb_shinfo(skb)->frags;
+
+               /* normal or jumbo packets. we use frags */
+               i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]);
+               page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
+               off = CAS_VAL(RX_COMP1_DATA_OFF, words[0]) + swivel;
+
+               hlen = min(cp->page_size - off, dlen);
+               if (hlen < 0) {
+                       if (netif_msg_rx_err(cp)) {
+                               printk(KERN_DEBUG "%s: rx page overflow: "
+                                      "%d\n", cp->dev->name, hlen);
+                       }
+                       dev_kfree_skb_irq(skb);
+                       return -1;
+               }
+               i = hlen;
+               if (i == dlen)  /* attach FCS */
+                       i += cp->crc_size;
+               pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i,
+                                   PCI_DMA_FROMDEVICE);
+
+               /* make sure we always copy a header */
+               swivel = 0;
+               if (p == (char *) skb->data) { /* not split */
+                       addr = cas_page_map(page->buffer);
+                       memcpy(p, addr + off, RX_COPY_MIN);
+                       pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i,
+                                       PCI_DMA_FROMDEVICE);
+                       cas_page_unmap(addr);
+                       off += RX_COPY_MIN;
+                       swivel = RX_COPY_MIN;
+                       RX_USED_ADD(page, cp->mtu_stride);
+               } else {
+                       RX_USED_ADD(page, hlen);
+               }
+               skb_put(skb, alloclen);
+
+               skb_shinfo(skb)->nr_frags++;
+               skb->data_len += hlen - swivel;
+               skb->len      += hlen - swivel;
+
+               get_page(page->buffer);
+               frag->page = page->buffer;
+               frag->page_offset = off;
+               frag->size = hlen - swivel;
+               
+               /* any more data? */
+               if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) {
+                       hlen = dlen;
+                       off = 0;
+
+                       i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]);
+                       page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
+                       pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr, 
+                                           hlen + cp->crc_size, 
+                                           PCI_DMA_FROMDEVICE);
+                       pci_dma_sync_single_for_device(cp->pdev, page->dma_addr,
+                                           hlen + cp->crc_size,
+                                           PCI_DMA_FROMDEVICE);
+
+                       skb_shinfo(skb)->nr_frags++;
+                       skb->data_len += hlen;
+                       skb->len      += hlen; 
+                       frag++;
+
+                       get_page(page->buffer);
+                       frag->page = page->buffer;
+                       frag->page_offset = 0;
+                       frag->size = hlen;
+                       RX_USED_ADD(page, hlen + cp->crc_size);
+               }
+
+               if (cp->crc_size) {
+                       addr = cas_page_map(page->buffer);
+                       crcaddr  = addr + off + hlen;
+               }
+
+       } else {
+               /* copying packet */
+               if (!dlen)
+                       goto end_copy_pkt;
+
+               i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]);
+               page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
+               off = CAS_VAL(RX_COMP1_DATA_OFF, words[0]) + swivel;
+               hlen = min(cp->page_size - off, dlen);
+               if (hlen < 0) {
+                       if (netif_msg_rx_err(cp)) {
+                               printk(KERN_DEBUG "%s: rx page overflow: "
+                                      "%d\n", cp->dev->name, hlen);
+                       }
+                       dev_kfree_skb_irq(skb);
+                       return -1;
+               }
+               i = hlen;
+               if (i == dlen) /* attach FCS */
+                       i += cp->crc_size;
+               pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr + off, i,
+                                   PCI_DMA_FROMDEVICE);
+               addr = cas_page_map(page->buffer);
+               memcpy(p, addr + off, i);
+               pci_dma_sync_single_for_device(cp->pdev, page->dma_addr + off, i,
+                                   PCI_DMA_FROMDEVICE);
+               cas_page_unmap(addr);
+               if (p == (char *) skb->data) /* not split */
+                       RX_USED_ADD(page, cp->mtu_stride);
+               else
+                       RX_USED_ADD(page, i);
+       
+               /* any more data? */
+               if ((words[0] & RX_COMP1_SPLIT_PKT) && ((dlen -= hlen) > 0)) {
+                       p += hlen;
+                       i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]);
+                       page = cp->rx_pages[CAS_VAL(RX_INDEX_RING, i)][CAS_VAL(RX_INDEX_NUM, i)];
+                       pci_dma_sync_single_for_cpu(cp->pdev, page->dma_addr, 
+                                           dlen + cp->crc_size, 
+                                           PCI_DMA_FROMDEVICE);
+                       addr = cas_page_map(page->buffer);
+                       memcpy(p, addr, dlen + cp->crc_size);
+                       pci_dma_sync_single_for_device(cp->pdev, page->dma_addr,
+                                           dlen + cp->crc_size,
+                                           PCI_DMA_FROMDEVICE);
+                       cas_page_unmap(addr);
+                       RX_USED_ADD(page, dlen + cp->crc_size); 
+               }
+end_copy_pkt:
+               if (cp->crc_size) {
+                       addr    = NULL;
+                       crcaddr = skb->data + alloclen;
+               }
+               skb_put(skb, alloclen);
+       }
+
+       i = CAS_VAL(RX_COMP4_TCP_CSUM, words[3]);
+       if (cp->crc_size) {
+               /* checksum includes FCS. strip it out. */
+               i = csum_fold(csum_partial(crcaddr, cp->crc_size, i));
+               if (addr)
+                       cas_page_unmap(addr);
+       }
+       skb->csum = ntohs(i ^ 0xffff);
+       skb->ip_summed = CHECKSUM_HW;
+       skb->protocol = eth_type_trans(skb, cp->dev);
+       return len;
+}
+
+
+/* we can handle up to 64 rx flows at a time. we do the same thing
+ * as nonreassm except that we batch up the buffers. 
+ * NOTE: we currently just treat each flow as a bunch of packets that
+ *       we pass up. a better way would be to coalesce the packets
+ *       into a jumbo packet. to do that, we need to do the following:
+ *       1) the first packet will have a clean split between header and
+ *          data. save both.
+ *       2) each time the next flow packet comes in, extend the
+ *          data length and merge the checksums.
+ *       3) on flow release, fix up the header.
+ *       4) make sure the higher layer doesn't care.
+ * because packets get coalesced, we shouldn't run into fragment count 
+ * issues.
+ */
+static inline void cas_rx_flow_pkt(struct cas *cp, const u64 *words,
+                                  struct sk_buff *skb)
+{
+       int flowid = CAS_VAL(RX_COMP3_FLOWID, words[2]) & (N_RX_FLOWS - 1);
+       struct sk_buff_head *flow = &cp->rx_flows[flowid];
+       
+       /* this is protected at a higher layer, so no need to 
+        * do any additional locking here. stick the buffer
+        * at the end.
+        */
+       __skb_insert(skb, flow->prev, (struct sk_buff *) flow, flow);
+       if (words[0] & RX_COMP1_RELEASE_FLOW) {
+               while ((skb = __skb_dequeue(flow))) {
+                       cas_skb_release(skb);
+               }
+       }
+}
+
+/* put rx descriptor back on ring. if a buffer is in use by a higher
+ * layer, this will need to put in a replacement.
+ */
+static void cas_post_page(struct cas *cp, const int ring, const int index)
+{
+       cas_page_t *new;
+       int entry;
+
+       entry = cp->rx_old[ring];
+
+       new = cas_page_swap(cp, ring, index);
+       cp->init_rxds[ring][entry].buffer = cpu_to_le64(new->dma_addr);
+       cp->init_rxds[ring][entry].index  =
+               cpu_to_le64(CAS_BASE(RX_INDEX_NUM, index) | 
+                           CAS_BASE(RX_INDEX_RING, ring));
+
+       entry = RX_DESC_ENTRY(ring, entry + 1);
+       cp->rx_old[ring] = entry;
+       
+       if (entry % 4)
+               return;
+
+       if (ring == 0)
+               writel(entry, cp->regs + REG_RX_KICK);
+       else if ((N_RX_DESC_RINGS > 1) &&
+                (cp->cas_flags & CAS_FLAG_REG_PLUS)) 
+               writel(entry, cp->regs + REG_PLUS_RX_KICK1);
+}
+
+
+/* only when things are bad */
+static int cas_post_rxds_ringN(struct cas *cp, int ring, int num)
+{
+       unsigned int entry, last, count, released;
+       int cluster;
+       cas_page_t **page = cp->rx_pages[ring];
+
+       entry = cp->rx_old[ring];
+
+       if (netif_msg_intr(cp))
+               printk(KERN_DEBUG "%s: rxd[%d] interrupt, done: %d\n",
+                      cp->dev->name, ring, entry);
+
+       cluster = -1;
+       count = entry & 0x3; 
+       last = RX_DESC_ENTRY(ring, num ? entry + num - 4: entry - 4);
+       released = 0;
+       while (entry != last) {
+               /* make a new buffer if it's still in use */
+               if (page_count(page[entry]->buffer) > 1) {
+                       cas_page_t *new = cas_page_dequeue(cp);
+                       if (!new) {
+                               /* let the timer know that we need to 
+                                * do this again
+                                */
+                               cp->cas_flags |= CAS_FLAG_RXD_POST(ring);
+                               if (!timer_pending(&cp->link_timer))
+                                       mod_timer(&cp->link_timer, jiffies + 
+                                                 CAS_LINK_FAST_TIMEOUT);
+                               cp->rx_old[ring]  = entry;
+                               cp->rx_last[ring] = num ? num - released : 0;
+                               return -ENOMEM;
+                       }
+                       spin_lock(&cp->rx_inuse_lock);
+                       list_add(&page[entry]->list, &cp->rx_inuse_list);
+                       spin_unlock(&cp->rx_inuse_lock);
+                       cp->init_rxds[ring][entry].buffer = 
+                               cpu_to_le64(new->dma_addr);
+                       page[entry] = new;
+                       
+               }
+
+               if (++count == 4) {
+                       cluster = entry;
+                       count = 0;
+               }
+               released++;
+               entry = RX_DESC_ENTRY(ring, entry + 1);
+       }
+       cp->rx_old[ring] = entry;
+
+       if (cluster < 0) 
+               return 0;
+
+       if (ring == 0)
+               writel(cluster, cp->regs + REG_RX_KICK);
+       else if ((N_RX_DESC_RINGS > 1) &&
+                (cp->cas_flags & CAS_FLAG_REG_PLUS)) 
+               writel(cluster, cp->regs + REG_PLUS_RX_KICK1);
+       return 0;
+}
+
+
+/* process a completion ring. packets are set up in three basic ways:
+ * small packets: should be copied header + data in single buffer.
+ * large packets: header and data in a single buffer.
+ * split packets: header in a separate buffer from data. 
+ *                data may be in multiple pages. data may be > 256
+ *                bytes but in a single page. 
+ *
+ * NOTE: RX page posting is done in this routine as well. while there's
+ *       the capability of using multiple RX completion rings, it isn't
+ *       really worthwhile due to the fact that the page posting will
+ *       force serialization on the single descriptor ring. 
+ */
+static int cas_rx_ringN(struct cas *cp, int ring, int budget)
+{
+       struct cas_rx_comp *rxcs = cp->init_rxcs[ring];
+       int entry, drops;
+       int npackets = 0;
+
+       if (netif_msg_intr(cp))
+               printk(KERN_DEBUG "%s: rx[%d] interrupt, done: %d/%d\n",
+                      cp->dev->name, ring,
+                      readl(cp->regs + REG_RX_COMP_HEAD), 
+                      cp->rx_new[ring]);
+
+       entry = cp->rx_new[ring];
+       drops = 0;
+       while (1) {
+               struct cas_rx_comp *rxc = rxcs + entry;
+               struct sk_buff *skb;
+               int type, len;
+               u64 words[4];
+               int i, dring;
+
+               words[0] = le64_to_cpu(rxc->word1);
+               words[1] = le64_to_cpu(rxc->word2);
+               words[2] = le64_to_cpu(rxc->word3);
+               words[3] = le64_to_cpu(rxc->word4);
+
+               /* don't touch if still owned by hw */
+               type = CAS_VAL(RX_COMP1_TYPE, words[0]);
+               if (type == 0)
+                       break;
+
+               /* hw hasn't cleared the zero bit yet */
+               if (words[3] & RX_COMP4_ZERO) {
+                       break;
+               }
+
+               /* get info on the packet */
+               if (words[3] & (RX_COMP4_LEN_MISMATCH | RX_COMP4_BAD)) {
+                       spin_lock(&cp->stat_lock[ring]);
+                       cp->net_stats[ring].rx_errors++;
+                       if (words[3] & RX_COMP4_LEN_MISMATCH)
+                               cp->net_stats[ring].rx_length_errors++;
+                       if (words[3] & RX_COMP4_BAD)
+                               cp->net_stats[ring].rx_crc_errors++;
+                       spin_unlock(&cp->stat_lock[ring]);
+
+                       /* We'll just return it to Cassini. */
+               drop_it:
+                       spin_lock(&cp->stat_lock[ring]);
+                       ++cp->net_stats[ring].rx_dropped;
+                       spin_unlock(&cp->stat_lock[ring]);
+                       goto next;
+               }
+
+               len = cas_rx_process_pkt(cp, rxc, entry, words, &skb);
+               if (len < 0) {
+                       ++drops;
+                       goto drop_it;
+               }
+
+               /* see if it's a flow re-assembly or not. the driver
+                * itself handles release back up.
+                */
+               if (RX_DONT_BATCH || (type == 0x2)) {
+                       /* non-reassm: these always get released */
+                       cas_skb_release(skb); 
+               } else {
+                       cas_rx_flow_pkt(cp, words, skb);
+               }
+
+               spin_lock(&cp->stat_lock[ring]);
+               cp->net_stats[ring].rx_packets++;
+               cp->net_stats[ring].rx_bytes += len;
+               spin_unlock(&cp->stat_lock[ring]);
+               cp->dev->last_rx = jiffies;
+
+       next:
+               npackets++;
+
+               /* should it be released? */
+               if (words[0] & RX_COMP1_RELEASE_HDR) {
+                       i = CAS_VAL(RX_COMP2_HDR_INDEX, words[1]);
+                       dring = CAS_VAL(RX_INDEX_RING, i);
+                       i = CAS_VAL(RX_INDEX_NUM, i);
+                       cas_post_page(cp, dring, i);
+               }
+               
+               if (words[0] & RX_COMP1_RELEASE_DATA) {
+                       i = CAS_VAL(RX_COMP1_DATA_INDEX, words[0]);
+                       dring = CAS_VAL(RX_INDEX_RING, i);
+                       i = CAS_VAL(RX_INDEX_NUM, i);
+                       cas_post_page(cp, dring, i);
+               }
+
+               if (words[0] & RX_COMP1_RELEASE_NEXT) {
+                       i = CAS_VAL(RX_COMP2_NEXT_INDEX, words[1]);
+                       dring = CAS_VAL(RX_INDEX_RING, i);
+                       i = CAS_VAL(RX_INDEX_NUM, i);
+                       cas_post_page(cp, dring, i);
+               }
+
+               /* skip to the next entry */
+               entry = RX_COMP_ENTRY(ring, entry + 1 + 
+                                     CAS_VAL(RX_COMP1_SKIP, words[0]));
+#ifdef USE_NAPI
+               if (budget && (npackets >= budget))
+                       break;
+#endif
+       }
+       cp->rx_new[ring] = entry;
+
+       if (drops)
+               printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
+                      cp->dev->name);
+       return npackets;
+}
+
+
+/* put completion entries back on the ring */
+static void cas_post_rxcs_ringN(struct net_device *dev,
+                               struct cas *cp, int ring)
+{
+       struct cas_rx_comp *rxc = cp->init_rxcs[ring];
+       int last, entry;
+
+       last = cp->rx_cur[ring];
+       entry = cp->rx_new[ring]; 
+       if (netif_msg_intr(cp))
+               printk(KERN_DEBUG "%s: rxc[%d] interrupt, done: %d/%d\n",
+                      dev->name, ring, readl(cp->regs + REG_RX_COMP_HEAD),
+                      entry);
+       
+       /* zero and re-mark descriptors */
+       while (last != entry) {
+               cas_rxc_init(rxc + last);
+               last = RX_COMP_ENTRY(ring, last + 1);
+       }
+       cp->rx_cur[ring] = last;
+
+       if (ring == 0)
+               writel(last, cp->regs + REG_RX_COMP_TAIL);
+       else if (cp->cas_flags & CAS_FLAG_REG_PLUS) 
+               writel(last, cp->regs + REG_PLUS_RX_COMPN_TAIL(ring));
+}
+
+
+
+/* cassini can use all four PCI interrupts for the completion ring. 
+ * rings 3 and 4 are identical
+ */
+#if defined(USE_PCI_INTC) || defined(USE_PCI_INTD)
+static inline void cas_handle_irqN(struct net_device *dev, 
+                                  struct cas *cp, const u32 status,
+                                  const int ring)
+{
+       if (status & (INTR_RX_COMP_FULL_ALT | INTR_RX_COMP_AF_ALT)) 
+               cas_post_rxcs_ringN(dev, cp, ring);
+}
+
+static irqreturn_t cas_interruptN(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = dev_id;
+       struct cas *cp = netdev_priv(dev);
+       unsigned long flags;
+       int ring;
+       u32 status = readl(cp->regs + REG_PLUS_INTRN_STATUS(ring));
+
+       /* check for shared irq */
+       if (status == 0)
+               return IRQ_NONE;
+
+       ring = (irq == cp->pci_irq_INTC) ? 2 : 3;
+       spin_lock_irqsave(&cp->lock, flags);
+       if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
+#ifdef USE_NAPI
+               cas_mask_intr(cp);
+               netif_rx_schedule(dev);
+#else
+               cas_rx_ringN(cp, ring, 0);
+#endif
+               status &= ~INTR_RX_DONE_ALT;
+       }
+
+       if (status)
+               cas_handle_irqN(dev, cp, status, ring);
+       spin_unlock_irqrestore(&cp->lock, flags);
+       return IRQ_HANDLED;
+}
+#endif
+
+#ifdef USE_PCI_INTB
+/* everything but rx packets */
+static inline void cas_handle_irq1(struct cas *cp, const u32 status)
+{
+       if (status & INTR_RX_BUF_UNAVAIL_1) {
+               /* Frame arrived, no free RX buffers available. 
+                * NOTE: we can get this on a link transition. */
+               cas_post_rxds_ringN(cp, 1, 0);
+               spin_lock(&cp->stat_lock[1]);
+               cp->net_stats[1].rx_dropped++;
+               spin_unlock(&cp->stat_lock[1]);
+       }
+
+       if (status & INTR_RX_BUF_AE_1) 
+               cas_post_rxds_ringN(cp, 1, RX_DESC_RINGN_SIZE(1) - 
+                                   RX_AE_FREEN_VAL(1));
+
+       if (status & (INTR_RX_COMP_AF | INTR_RX_COMP_FULL))
+               cas_post_rxcs_ringN(cp, 1);
+}
+
+/* ring 2 handles a few more events than 3 and 4 */
+static irqreturn_t cas_interrupt1(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = dev_id;
+       struct cas *cp = netdev_priv(dev);
+       unsigned long flags;
+       u32 status = readl(cp->regs + REG_PLUS_INTRN_STATUS(1));
+
+       /* check for shared interrupt */
+       if (status == 0)
+               return IRQ_NONE;
+
+       spin_lock_irqsave(&cp->lock, flags);
+       if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
+#ifdef USE_NAPI
+               cas_mask_intr(cp);
+               netif_rx_schedule(dev);
+#else
+               cas_rx_ringN(cp, 1, 0);
+#endif
+               status &= ~INTR_RX_DONE_ALT;
+       }
+       if (status)
+               cas_handle_irq1(cp, status);
+       spin_unlock_irqrestore(&cp->lock, flags);
+       return IRQ_HANDLED;
+}
+#endif
+
+static inline void cas_handle_irq(struct net_device *dev,
+                                 struct cas *cp, const u32 status)
+{
+       /* housekeeping interrupts */
+       if (status & INTR_ERROR_MASK)
+               cas_abnormal_irq(dev, cp, status);
+
+       if (status & INTR_RX_BUF_UNAVAIL) {
+               /* Frame arrived, no free RX buffers available. 
+                * NOTE: we can get this on a link transition.
+                */
+               cas_post_rxds_ringN(cp, 0, 0);
+               spin_lock(&cp->stat_lock[0]);
+               cp->net_stats[0].rx_dropped++;
+               spin_unlock(&cp->stat_lock[0]);
+       } else if (status & INTR_RX_BUF_AE) {
+               cas_post_rxds_ringN(cp, 0, RX_DESC_RINGN_SIZE(0) -
+                                   RX_AE_FREEN_VAL(0));
+       }
+
+       if (status & (INTR_RX_COMP_AF | INTR_RX_COMP_FULL))
+               cas_post_rxcs_ringN(dev, cp, 0);
+}
+
+static irqreturn_t cas_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = dev_id;
+       struct cas *cp = netdev_priv(dev);
+       unsigned long flags;
+       u32 status = readl(cp->regs + REG_INTR_STATUS);
+
+       if (status == 0)
+               return IRQ_NONE;
+
+       spin_lock_irqsave(&cp->lock, flags);
+       if (status & (INTR_TX_ALL | INTR_TX_INTME)) {
+               cas_tx(dev, cp, status);
+               status &= ~(INTR_TX_ALL | INTR_TX_INTME);
+       }
+
+       if (status & INTR_RX_DONE) {
+#ifdef USE_NAPI
+               cas_mask_intr(cp);
+               netif_rx_schedule(dev);
+#else
+               cas_rx_ringN(cp, 0, 0);
+#endif
+               status &= ~INTR_RX_DONE;
+       }
+
+       if (status)
+               cas_handle_irq(dev, cp, status);
+       spin_unlock_irqrestore(&cp->lock, flags);
+       return IRQ_HANDLED;
+}
+
+
+#ifdef USE_NAPI
+static int cas_poll(struct net_device *dev, int *budget)
+{
+       struct cas *cp = netdev_priv(dev);
+       int i, enable_intr, todo, credits;
+       u32 status = readl(cp->regs + REG_INTR_STATUS);
+       unsigned long flags;
+
+       spin_lock_irqsave(&cp->lock, flags);
+       cas_tx(dev, cp, status);
+       spin_unlock_irqrestore(&cp->lock, flags);
+
+       /* NAPI rx packets. we spread the credits across all of the
+        * rxc rings
+        */
+       todo = min(*budget, dev->quota);
+
+       /* to make sure we're fair with the work we loop through each
+        * ring N_RX_COMP_RING times with a request of 
+        * todo / N_RX_COMP_RINGS
+        */
+       enable_intr = 1;
+       credits = 0;
+       for (i = 0; i < N_RX_COMP_RINGS; i++) {
+               int j;
+               for (j = 0; j < N_RX_COMP_RINGS; j++) {
+                       credits += cas_rx_ringN(cp, j, todo / N_RX_COMP_RINGS);
+                       if (credits >= todo) {
+                               enable_intr = 0;
+                               goto rx_comp;
+                       }
+               }
+       }
+
+rx_comp:
+       *budget    -= credits;
+       dev->quota -= credits;
+
+       /* final rx completion */
+       spin_lock_irqsave(&cp->lock, flags);
+       if (status)
+               cas_handle_irq(dev, cp, status);
+
+#ifdef USE_PCI_INTB
+       if (N_RX_COMP_RINGS > 1) {
+               status = readl(cp->regs + REG_PLUS_INTRN_STATUS(1));
+               if (status)
+                       cas_handle_irq1(dev, cp, status);
+       }
+#endif
+
+#ifdef USE_PCI_INTC
+       if (N_RX_COMP_RINGS > 2) {
+               status = readl(cp->regs + REG_PLUS_INTRN_STATUS(2));
+               if (status)
+                       cas_handle_irqN(dev, cp, status, 2);
+       }
+#endif
+
+#ifdef USE_PCI_INTD
+       if (N_RX_COMP_RINGS > 3) {
+               status = readl(cp->regs + REG_PLUS_INTRN_STATUS(3));
+               if (status)
+                       cas_handle_irqN(dev, cp, status, 3);
+       }
+#endif
+       spin_unlock_irqrestore(&cp->lock, flags);
+       if (enable_intr) {
+               netif_rx_complete(dev);
+               cas_unmask_intr(cp);
+               return 0;
+       }
+       return 1;
+}
+#endif
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void cas_netpoll(struct net_device *dev)
+{
+       struct cas *cp = netdev_priv(dev);
+
+       cas_disable_irq(cp, 0);
+       cas_interrupt(cp->pdev->irq, dev, NULL);
+       cas_enable_irq(cp, 0);
+
+#ifdef USE_PCI_INTB
+       if (N_RX_COMP_RINGS > 1) {
+               /* cas_interrupt1(); */
+       }
+#endif
+#ifdef USE_PCI_INTC
+       if (N_RX_COMP_RINGS > 2) {
+               /* cas_interruptN(); */
+       }
+#endif
+#ifdef USE_PCI_INTD
+       if (N_RX_COMP_RINGS > 3) {
+               /* cas_interruptN(); */
+       }
+#endif
+}
+#endif
+
+static void cas_tx_timeout(struct net_device *dev)
+{
+       struct cas *cp = netdev_priv(dev);
+
+       printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
+       if (!cp->hw_running) {
+               printk("%s: hrm.. hw not running!\n", dev->name);
+               return;
+       }
+
+       printk(KERN_ERR "%s: MIF_STATE[%08x]\n",
+              dev->name, readl(cp->regs + REG_MIF_STATE_MACHINE));
+
+       printk(KERN_ERR "%s: MAC_STATE[%08x]\n",
+              dev->name, readl(cp->regs + REG_MAC_STATE_MACHINE));
+
+       printk(KERN_ERR "%s: TX_STATE[%08x:%08x:%08x] "
+              "FIFO[%08x:%08x:%08x] SM1[%08x] SM2[%08x]\n",
+              dev->name,
+              readl(cp->regs + REG_TX_CFG),
+              readl(cp->regs + REG_MAC_TX_STATUS),
+              readl(cp->regs + REG_MAC_TX_CFG),
+              readl(cp->regs + REG_TX_FIFO_PKT_CNT),
+              readl(cp->regs + REG_TX_FIFO_WRITE_PTR),
+              readl(cp->regs + REG_TX_FIFO_READ_PTR),
+              readl(cp->regs + REG_TX_SM_1),
+              readl(cp->regs + REG_TX_SM_2));
+
+       printk(KERN_ERR "%s: RX_STATE[%08x:%08x:%08x]\n",
+              dev->name,
+              readl(cp->regs + REG_RX_CFG),
+              readl(cp->regs + REG_MAC_RX_STATUS),
+              readl(cp->regs + REG_MAC_RX_CFG));
+
+       printk(KERN_ERR "%s: HP_STATE[%08x:%08x:%08x:%08x]\n",
+              dev->name,
+              readl(cp->regs + REG_HP_STATE_MACHINE),
+              readl(cp->regs + REG_HP_STATUS0),
+              readl(cp->regs + REG_HP_STATUS1),
+              readl(cp->regs + REG_HP_STATUS2));
+
+#if 1
+       atomic_inc(&cp->reset_task_pending);
+       atomic_inc(&cp->reset_task_pending_all);
+       schedule_work(&cp->reset_task);
+#else
+       atomic_set(&cp->reset_task_pending, CAS_RESET_ALL);
+       schedule_work(&cp->reset_task);
+#endif
+}
+
+static inline int cas_intme(int ring, int entry)
+{
+       /* Algorithm: IRQ every 1/2 of descriptors. */
+       if (!(entry & ((TX_DESC_RINGN_SIZE(ring) >> 1) - 1)))
+               return 1;
+       return 0;
+}
+
+
+static void cas_write_txd(struct cas *cp, int ring, int entry,
+                         dma_addr_t mapping, int len, u64 ctrl, int last)
+{
+       struct cas_tx_desc *txd = cp->init_txds[ring] + entry;
+
+       ctrl |= CAS_BASE(TX_DESC_BUFLEN, len);
+       if (cas_intme(ring, entry))
+               ctrl |= TX_DESC_INTME;
+       if (last)
+               ctrl |= TX_DESC_EOF;
+       txd->control = cpu_to_le64(ctrl);
+       txd->buffer = cpu_to_le64(mapping);
+}
+
+static inline void *tx_tiny_buf(struct cas *cp, const int ring, 
+                               const int entry)
+{
+       return cp->tx_tiny_bufs[ring] + TX_TINY_BUF_LEN*entry;
+}
+
+static inline dma_addr_t tx_tiny_map(struct cas *cp, const int ring, 
+                                    const int entry, const int tentry)
+{
+       cp->tx_tiny_use[ring][tentry].nbufs++;
+       cp->tx_tiny_use[ring][entry].used = 1;
+       return cp->tx_tiny_dvma[ring] + TX_TINY_BUF_LEN*entry;
+}
+
+static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, 
+                                   struct sk_buff *skb)
+{
+       struct net_device *dev = cp->dev;
+       int entry, nr_frags, frag, tabort, tentry;
+       dma_addr_t mapping;
+       unsigned long flags;
+       u64 ctrl;
+       u32 len;
+
+       spin_lock_irqsave(&cp->tx_lock[ring], flags);
+
+       /* This is a hard error, log it. */
+       if (TX_BUFFS_AVAIL(cp, ring) <= 
+           CAS_TABORT(cp)*(skb_shinfo(skb)->nr_frags + 1)) {
+               netif_stop_queue(dev);
+               spin_unlock_irqrestore(&cp->tx_lock[ring], flags);
+               printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
+                      "queue awake!\n", dev->name);
+               return 1;
+       }
+
+       ctrl = 0;
+       if (skb->ip_summed == CHECKSUM_HW) {
+               u64 csum_start_off, csum_stuff_off;
+
+               csum_start_off = (u64) (skb->h.raw - skb->data);
+               csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data);
+
+               ctrl =  TX_DESC_CSUM_EN | 
+                       CAS_BASE(TX_DESC_CSUM_START, csum_start_off) |
+                       CAS_BASE(TX_DESC_CSUM_STUFF, csum_stuff_off);
+       }
+
+       entry = cp->tx_new[ring];
+       cp->tx_skbs[ring][entry] = skb;
+
+       nr_frags = skb_shinfo(skb)->nr_frags;
+       len = skb_headlen(skb);
+       mapping = pci_map_page(cp->pdev, virt_to_page(skb->data),
+                              offset_in_page(skb->data), len,
+                              PCI_DMA_TODEVICE);
+
+       tentry = entry;
+       tabort = cas_calc_tabort(cp, (unsigned long) skb->data, len);
+       if (unlikely(tabort)) {
+               /* NOTE: len is always >  tabort */
+               cas_write_txd(cp, ring, entry, mapping, len - tabort, 
+                             ctrl | TX_DESC_SOF, 0);
+               entry = TX_DESC_NEXT(ring, entry);
+
+               memcpy(tx_tiny_buf(cp, ring, entry), skb->data + 
+                      len - tabort, tabort);
+               mapping = tx_tiny_map(cp, ring, entry, tentry);
+               cas_write_txd(cp, ring, entry, mapping, tabort, ctrl,
+                             (nr_frags == 0));
+       } else {
+               cas_write_txd(cp, ring, entry, mapping, len, ctrl | 
+                             TX_DESC_SOF, (nr_frags == 0));
+       }
+       entry = TX_DESC_NEXT(ring, entry);
+
+       for (frag = 0; frag < nr_frags; frag++) {
+               skb_frag_t *fragp = &skb_shinfo(skb)->frags[frag];
+
+               len = fragp->size;
+               mapping = pci_map_page(cp->pdev, fragp->page,
+                                      fragp->page_offset, len,
+                                      PCI_DMA_TODEVICE);
+
+               tabort = cas_calc_tabort(cp, fragp->page_offset, len);
+               if (unlikely(tabort)) {
+                       void *addr;
+
+                       /* NOTE: len is always > tabort */
+                       cas_write_txd(cp, ring, entry, mapping, len - tabort,
+                                     ctrl, 0);
+                       entry = TX_DESC_NEXT(ring, entry);
+                       
+                       addr = cas_page_map(fragp->page);
+                       memcpy(tx_tiny_buf(cp, ring, entry),
+                              addr + fragp->page_offset + len - tabort, 
+                              tabort);
+                       cas_page_unmap(addr);
+                       mapping = tx_tiny_map(cp, ring, entry, tentry);
+                       len     = tabort;
+               }
+
+               cas_write_txd(cp, ring, entry, mapping, len, ctrl,
+                             (frag + 1 == nr_frags));
+               entry = TX_DESC_NEXT(ring, entry);
+       }
+
+       cp->tx_new[ring] = entry;
+       if (TX_BUFFS_AVAIL(cp, ring) <= CAS_TABORT(cp)*(MAX_SKB_FRAGS + 1))
+               netif_stop_queue(dev);
+
+       if (netif_msg_tx_queued(cp))
+               printk(KERN_DEBUG "%s: tx[%d] queued, slot %d, skblen %d, "
+                      "avail %d\n",
+                      dev->name, ring, entry, skb->len, 
+                      TX_BUFFS_AVAIL(cp, ring));
+       writel(entry, cp->regs + REG_TX_KICKN(ring));
+       spin_unlock_irqrestore(&cp->tx_lock[ring], flags);
+       return 0;
+} 
+
+static int cas_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct cas *cp = netdev_priv(dev);
+
+       /* this is only used as a load-balancing hint, so it doesn't
+        * need to be SMP safe
+        */
+       static int ring; 
+
+       skb = skb_padto(skb, cp->min_frame_size);
+       if (!skb)
+               return 0;
+
+       /* XXX: we need some higher-level QoS hooks to steer packets to
+        *      individual queues.
+        */
+       if (cas_xmit_tx_ringN(cp, ring++ & N_TX_RINGS_MASK, skb))
+               return 1;
+       dev->trans_start = jiffies;
+       return 0;
+}
+
+static void cas_init_tx_dma(struct cas *cp)
+{
+       u64 desc_dma = cp->block_dvma;
+       unsigned long off;
+       u32 val;
+       int i;
+
+       /* set up tx completion writeback registers. must be 8-byte aligned */
+#ifdef USE_TX_COMPWB
+       off = offsetof(struct cas_init_block, tx_compwb);
+       writel((desc_dma + off) >> 32, cp->regs + REG_TX_COMPWB_DB_HI);
+       writel((desc_dma + off) & 0xffffffff, cp->regs + REG_TX_COMPWB_DB_LOW);
+#endif
+
+       /* enable completion writebacks, enable paced mode,
+        * disable read pipe, and disable pre-interrupt compwbs
+        */
+       val =   TX_CFG_COMPWB_Q1 | TX_CFG_COMPWB_Q2 | 
+               TX_CFG_COMPWB_Q3 | TX_CFG_COMPWB_Q4 |
+               TX_CFG_DMA_RDPIPE_DIS | TX_CFG_PACED_MODE | 
+               TX_CFG_INTR_COMPWB_DIS;
+
+       /* write out tx ring info and tx desc bases */
+       for (i = 0; i < MAX_TX_RINGS; i++) {
+               off = (unsigned long) cp->init_txds[i] - 
+                       (unsigned long) cp->init_block;
+
+               val |= CAS_TX_RINGN_BASE(i);
+               writel((desc_dma + off) >> 32, cp->regs + REG_TX_DBN_HI(i));
+               writel((desc_dma + off) & 0xffffffff, cp->regs +
+                      REG_TX_DBN_LOW(i));
+               /* don't zero out the kick register here as the system
+                * will wedge
+                */
+       }
+       writel(val, cp->regs + REG_TX_CFG);
+
+       /* program max burst sizes. these numbers should be different
+        * if doing QoS.
+        */
+#ifdef USE_QOS
+       writel(0x800, cp->regs + REG_TX_MAXBURST_0);
+       writel(0x1600, cp->regs + REG_TX_MAXBURST_1);
+       writel(0x2400, cp->regs + REG_TX_MAXBURST_2);
+       writel(0x4800, cp->regs + REG_TX_MAXBURST_3);
+#else
+       writel(0x800, cp->regs + REG_TX_MAXBURST_0);
+       writel(0x800, cp->regs + REG_TX_MAXBURST_1);
+       writel(0x800, cp->regs + REG_TX_MAXBURST_2);
+       writel(0x800, cp->regs + REG_TX_MAXBURST_3);
+#endif
+}
+
+/* Must be invoked under cp->lock. */
+static inline void cas_init_dma(struct cas *cp)
+{
+       cas_init_tx_dma(cp);
+       cas_init_rx_dma(cp);
+}
+
+/* Must be invoked under cp->lock. */
+static u32 cas_setup_multicast(struct cas *cp)
+{
+       u32 rxcfg = 0;
+       int i;
+       
+       if (cp->dev->flags & IFF_PROMISC) {
+               rxcfg |= MAC_RX_CFG_PROMISC_EN;
+
+       } else if (cp->dev->flags & IFF_ALLMULTI) {
+               for (i=0; i < 16; i++)
+                       writel(0xFFFF, cp->regs + REG_MAC_HASH_TABLEN(i));
+               rxcfg |= MAC_RX_CFG_HASH_FILTER_EN;
+
+       } else {
+               u16 hash_table[16];
+               u32 crc;
+               struct dev_mc_list *dmi = cp->dev->mc_list;
+               int i;
+
+               /* use the alternate mac address registers for the
+                * first 15 multicast addresses
+                */
+               for (i = 1; i <= CAS_MC_EXACT_MATCH_SIZE; i++) {
+                       if (!dmi) {
+                               writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 0));
+                               writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 1));
+                               writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 2));
+                               continue;
+                       }
+                       writel((dmi->dmi_addr[4] << 8) | dmi->dmi_addr[5], 
+                              cp->regs + REG_MAC_ADDRN(i*3 + 0));
+                       writel((dmi->dmi_addr[2] << 8) | dmi->dmi_addr[3], 
+                              cp->regs + REG_MAC_ADDRN(i*3 + 1));
+                       writel((dmi->dmi_addr[0] << 8) | dmi->dmi_addr[1], 
+                              cp->regs + REG_MAC_ADDRN(i*3 + 2));
+                       dmi = dmi->next;
+               }
+
+               /* use hw hash table for the next series of 
+                * multicast addresses
+                */
+               memset(hash_table, 0, sizeof(hash_table));
+               while (dmi) {
+                       crc = ether_crc_le(ETH_ALEN, dmi->dmi_addr);
+                       crc >>= 24;
+                       hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
+                       dmi = dmi->next;
+               }
+               for (i=0; i < 16; i++)
+                       writel(hash_table[i], cp->regs + 
+                              REG_MAC_HASH_TABLEN(i));
+               rxcfg |= MAC_RX_CFG_HASH_FILTER_EN;
+       }
+
+       return rxcfg;
+}
+
+/* must be invoked under cp->stat_lock[N_TX_RINGS] */
+static void cas_clear_mac_err(struct cas *cp)
+{
+       writel(0, cp->regs + REG_MAC_COLL_NORMAL);
+       writel(0, cp->regs + REG_MAC_COLL_FIRST);
+       writel(0, cp->regs + REG_MAC_COLL_EXCESS);
+       writel(0, cp->regs + REG_MAC_COLL_LATE);
+       writel(0, cp->regs + REG_MAC_TIMER_DEFER);
+       writel(0, cp->regs + REG_MAC_ATTEMPTS_PEAK);
+       writel(0, cp->regs + REG_MAC_RECV_FRAME);
+       writel(0, cp->regs + REG_MAC_LEN_ERR);
+       writel(0, cp->regs + REG_MAC_ALIGN_ERR);
+       writel(0, cp->regs + REG_MAC_FCS_ERR);
+       writel(0, cp->regs + REG_MAC_RX_CODE_ERR);
+}
+
+
+static void cas_mac_reset(struct cas *cp)
+{
+       int i;
+
+       /* do both TX and RX reset */
+       writel(0x1, cp->regs + REG_MAC_TX_RESET);
+       writel(0x1, cp->regs + REG_MAC_RX_RESET);
+
+       /* wait for TX */
+       i = STOP_TRIES;
+       while (i-- > 0) {
+               if (readl(cp->regs + REG_MAC_TX_RESET) == 0)
+                       break;
+               udelay(10);
+       }
+
+       /* wait for RX */
+       i = STOP_TRIES;
+       while (i-- > 0) {
+               if (readl(cp->regs + REG_MAC_RX_RESET) == 0)
+                       break;
+               udelay(10);
+       }
+
+       if (readl(cp->regs + REG_MAC_TX_RESET) |
+           readl(cp->regs + REG_MAC_RX_RESET))
+               printk(KERN_ERR "%s: mac tx[%d]/rx[%d] reset failed [%08x]\n",
+                      cp->dev->name, readl(cp->regs + REG_MAC_TX_RESET),
+                      readl(cp->regs + REG_MAC_RX_RESET),
+                      readl(cp->regs + REG_MAC_STATE_MACHINE));
+}
+
+
+/* Must be invoked under cp->lock. */
+static void cas_init_mac(struct cas *cp)
+{
+       unsigned char *e = &cp->dev->dev_addr[0];
+       int i;
+#ifdef CONFIG_CASSINI_MULTICAST_REG_WRITE
+       u32 rxcfg;
+#endif
+       cas_mac_reset(cp);
+
+       /* setup core arbitration weight register */
+       writel(CAWR_RR_DIS, cp->regs + REG_CAWR);
+
+       /* XXX Use pci_dma_burst_advice() */
+#if !defined(CONFIG_SPARC64) && !defined(CONFIG_ALPHA)
+       /* set the infinite burst register for chips that don't have
+        * pci issues.
+        */
+       if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) == 0)
+               writel(INF_BURST_EN, cp->regs + REG_INF_BURST);
+#endif
+
+       writel(0x1BF0, cp->regs + REG_MAC_SEND_PAUSE);
+
+       writel(0x00, cp->regs + REG_MAC_IPG0);
+       writel(0x08, cp->regs + REG_MAC_IPG1);
+       writel(0x04, cp->regs + REG_MAC_IPG2);
+       
+       /* change later for 802.3z */
+       writel(0x40, cp->regs + REG_MAC_SLOT_TIME); 
+
+       /* min frame + FCS */
+       writel(ETH_ZLEN + 4, cp->regs + REG_MAC_FRAMESIZE_MIN);
+
+       /* Ethernet payload + header + FCS + optional VLAN tag. NOTE: we
+        * specify the maximum frame size to prevent RX tag errors on 
+        * oversized frames.
+        */
+       writel(CAS_BASE(MAC_FRAMESIZE_MAX_BURST, 0x2000) |
+              CAS_BASE(MAC_FRAMESIZE_MAX_FRAME, 
+                       (CAS_MAX_MTU + ETH_HLEN + 4 + 4)), 
+              cp->regs + REG_MAC_FRAMESIZE_MAX);
+
+       /* NOTE: crc_size is used as a surrogate for half-duplex. 
+        * workaround saturn half-duplex issue by increasing preamble
+        * size to 65 bytes.
+        */
+       if ((cp->cas_flags & CAS_FLAG_SATURN) && cp->crc_size)
+               writel(0x41, cp->regs + REG_MAC_PA_SIZE);
+       else
+               writel(0x07, cp->regs + REG_MAC_PA_SIZE);
+       writel(0x04, cp->regs + REG_MAC_JAM_SIZE);
+       writel(0x10, cp->regs + REG_MAC_ATTEMPT_LIMIT);
+       writel(0x8808, cp->regs + REG_MAC_CTRL_TYPE);
+
+       writel((e[5] | (e[4] << 8)) & 0x3ff, cp->regs + REG_MAC_RANDOM_SEED);
+
+       writel(0, cp->regs + REG_MAC_ADDR_FILTER0);
+       writel(0, cp->regs + REG_MAC_ADDR_FILTER1);
+       writel(0, cp->regs + REG_MAC_ADDR_FILTER2);
+       writel(0, cp->regs + REG_MAC_ADDR_FILTER2_1_MASK);
+       writel(0, cp->regs + REG_MAC_ADDR_FILTER0_MASK);
+
+       /* setup mac address in perfect filter array */
+       for (i = 0; i < 45; i++)
+               writel(0x0, cp->regs + REG_MAC_ADDRN(i));
+
+       writel((e[4] << 8) | e[5], cp->regs + REG_MAC_ADDRN(0));
+       writel((e[2] << 8) | e[3], cp->regs + REG_MAC_ADDRN(1));
+       writel((e[0] << 8) | e[1], cp->regs + REG_MAC_ADDRN(2));
+
+       writel(0x0001, cp->regs + REG_MAC_ADDRN(42));
+       writel(0xc200, cp->regs + REG_MAC_ADDRN(43));
+       writel(0x0180, cp->regs + REG_MAC_ADDRN(44));
+
+#ifndef CONFIG_CASSINI_MULTICAST_REG_WRITE
+       cp->mac_rx_cfg = cas_setup_multicast(cp);
+#else
+       /* WTZ: Do what Adrian did in cas_set_multicast. Doing
+        * a writel does not seem to be necessary because Cassini
+        * seems to preserve the configuration when we do the reset.
+        * If the chip is in trouble, though, it is not clear if we
+        * can really count on this behavior. cas_set_multicast uses
+        * spin_lock_irqsave, but we are called only in cas_init_hw and
+        * cas_init_hw is protected by cas_lock_all, which calls
+        * spin_lock_irq (so it doesn't need to save the flags, and
+        * we should be OK for the writel, as that is the only 
+        * difference).
+        */
+       cp->mac_rx_cfg = rxcfg = cas_setup_multicast(cp);
+       writel(rxcfg, cp->regs + REG_MAC_RX_CFG);
+#endif
+       spin_lock(&cp->stat_lock[N_TX_RINGS]);
+       cas_clear_mac_err(cp);
+       spin_unlock(&cp->stat_lock[N_TX_RINGS]);
+
+       /* Setup MAC interrupts.  We want to get all of the interesting
+        * counter expiration events, but we do not want to hear about
+        * normal rx/tx as the DMA engine tells us that.
+        */
+       writel(MAC_TX_FRAME_XMIT, cp->regs + REG_MAC_TX_MASK);
+       writel(MAC_RX_FRAME_RECV, cp->regs + REG_MAC_RX_MASK);
+
+       /* Don't enable even the PAUSE interrupts for now, we
+        * make no use of those events other than to record them.
+        */
+       writel(0xffffffff, cp->regs + REG_MAC_CTRL_MASK);
+}
+
+/* Must be invoked under cp->lock. */
+static void cas_init_pause_thresholds(struct cas *cp)
+{
+       /* Calculate pause thresholds.  Setting the OFF threshold to the
+        * full RX fifo size effectively disables PAUSE generation
+        */
+       if (cp->rx_fifo_size <= (2 * 1024)) {
+               cp->rx_pause_off = cp->rx_pause_on = cp->rx_fifo_size;
+       } else {
+               int max_frame = (cp->dev->mtu + ETH_HLEN + 4 + 4 + 64) & ~63;
+               if (max_frame * 3 > cp->rx_fifo_size) {
+                       cp->rx_pause_off = 7104;
+                       cp->rx_pause_on  = 960;
+               } else {
+                       int off = (cp->rx_fifo_size - (max_frame * 2));
+                       int on = off - max_frame;
+                       cp->rx_pause_off = off;
+                       cp->rx_pause_on = on;
+               }
+       }
+}
+
+static int cas_vpd_match(const void __iomem *p, const char *str)
+{
+       int len = strlen(str) + 1;
+       int i;
+       
+       for (i = 0; i < len; i++) {
+               if (readb(p + i) != str[i])
+                       return 0;
+       }
+       return 1;
+}
+
+
+/* get the mac address by reading the vpd information in the rom.
+ * also get the phy type and determine if there's an entropy generator.
+ * NOTE: this is a bit convoluted for the following reasons:
+ *  1) vpd info has order-dependent mac addresses for multinic cards
+ *  2) the only way to determine the nic order is to use the slot
+ *     number.
+ *  3) fiber cards don't have bridges, so their slot numbers don't
+ *     mean anything.
+ *  4) we don't actually know we have a fiber card until after 
+ *     the mac addresses are parsed.
+ */
+static int cas_get_vpd_info(struct cas *cp, unsigned char *dev_addr,
+                           const int offset)
+{
+       void __iomem *p = cp->regs + REG_EXPANSION_ROM_RUN_START;
+       void __iomem *base, *kstart;
+       int i, len;
+       int found = 0;
+#define VPD_FOUND_MAC        0x01
+#define VPD_FOUND_PHY        0x02
+
+       int phy_type = CAS_PHY_MII_MDIO0; /* default phy type */
+       int mac_off  = 0;
+
+       /* give us access to the PROM */
+       writel(BIM_LOCAL_DEV_PROM | BIM_LOCAL_DEV_PAD,
+              cp->regs + REG_BIM_LOCAL_DEV_EN);
+
+       /* check for an expansion rom */
+       if (readb(p) != 0x55 || readb(p + 1) != 0xaa)
+               goto use_random_mac_addr;
+
+       /* search for beginning of vpd */
+       base = NULL;
+       for (i = 2; i < EXPANSION_ROM_SIZE; i++) {
+               /* check for PCIR */
+               if ((readb(p + i + 0) == 0x50) &&
+                   (readb(p + i + 1) == 0x43) &&
+                   (readb(p + i + 2) == 0x49) &&
+                   (readb(p + i + 3) == 0x52)) {
+                       base = p + (readb(p + i + 8) | 
+                                   (readb(p + i + 9) << 8));
+                       break;
+               }               
+       }
+
+       if (!base || (readb(base) != 0x82))
+               goto use_random_mac_addr;
+       
+       i = (readb(base + 1) | (readb(base + 2) << 8)) + 3;
+       while (i < EXPANSION_ROM_SIZE) {
+               if (readb(base + i) != 0x90) /* no vpd found */
+                       goto use_random_mac_addr;
+
+               /* found a vpd field */
+               len = readb(base + i + 1) | (readb(base + i + 2) << 8);
+
+               /* extract keywords */
+               kstart = base + i + 3;
+               p = kstart;
+               while ((p - kstart) < len) {
+                       int klen = readb(p + 2);
+                       int j;
+                       char type;
+
+                       p += 3;
+                       
+                       /* look for the following things:
+                        * -- correct length == 29
+                        * 3 (type) + 2 (size) + 
+                        * 18 (strlen("local-mac-address") + 1) + 
+                        * 6 (mac addr) 
+                        * -- VPD Instance 'I'
+                        * -- VPD Type Bytes 'B'
+                        * -- VPD data length == 6
+                        * -- property string == local-mac-address
+                        * 
+                        * -- correct length == 24
+                        * 3 (type) + 2 (size) + 
+                        * 12 (strlen("entropy-dev") + 1) + 
+                        * 7 (strlen("vms110") + 1)
+                        * -- VPD Instance 'I'
+                        * -- VPD Type String 'B'
+                        * -- VPD data length == 7
+                        * -- property string == entropy-dev
+                        *
+                        * -- correct length == 18
+                        * 3 (type) + 2 (size) + 
+                        * 9 (strlen("phy-type") + 1) + 
+                        * 4 (strlen("pcs") + 1)
+                        * -- VPD Instance 'I'
+                        * -- VPD Type String 'S'
+                        * -- VPD data length == 4
+                        * -- property string == phy-type
+                        * 
+                        * -- correct length == 23
+                        * 3 (type) + 2 (size) + 
+                        * 14 (strlen("phy-interface") + 1) + 
+                        * 4 (strlen("pcs") + 1)
+                        * -- VPD Instance 'I'
+                        * -- VPD Type String 'S'
+                        * -- VPD data length == 4
+                        * -- property string == phy-interface
+                        */
+                       if (readb(p) != 'I')
+                               goto next;
+
+                       /* finally, check string and length */
+                       type = readb(p + 3);
+                       if (type == 'B') {
+                               if ((klen == 29) && readb(p + 4) == 6 &&
+                                   cas_vpd_match(p + 5, 
+                                                 "local-mac-address")) {
+                                       if (mac_off++ > offset) 
+                                               goto next;
+
+                                       /* set mac address */
+                                       for (j = 0; j < 6; j++) 
+                                               dev_addr[j] = 
+                                                       readb(p + 23 + j);
+                                       goto found_mac;
+                               }
+                       }
+
+                       if (type != 'S')
+                               goto next;
+
+#ifdef USE_ENTROPY_DEV
+                       if ((klen == 24) && 
+                           cas_vpd_match(p + 5, "entropy-dev") &&
+                           cas_vpd_match(p + 17, "vms110")) {
+                               cp->cas_flags |= CAS_FLAG_ENTROPY_DEV;
+                               goto next;
+                       }
+#endif
+
+                       if (found & VPD_FOUND_PHY)
+                               goto next;
+
+                       if ((klen == 18) && readb(p + 4) == 4 &&
+                           cas_vpd_match(p + 5, "phy-type")) {
+                               if (cas_vpd_match(p + 14, "pcs")) {
+                                       phy_type = CAS_PHY_SERDES;
+                                       goto found_phy;
+                               }
+                       }
+                       
+                       if ((klen == 23) && readb(p + 4) == 4 &&
+                           cas_vpd_match(p + 5, "phy-interface")) {
+                               if (cas_vpd_match(p + 19, "pcs")) {
+                                       phy_type = CAS_PHY_SERDES;
+                                       goto found_phy;
+                               }
+                       }
+found_mac:
+                       found |= VPD_FOUND_MAC;
+                       goto next;
+
+found_phy:
+                       found |= VPD_FOUND_PHY;
+
+next:
+                       p += klen;
+               }
+               i += len + 3;
+       }
+
+use_random_mac_addr:
+       if (found & VPD_FOUND_MAC)
+               goto done;
+
+       /* Sun MAC prefix then 3 random bytes. */
+       printk(PFX "MAC address not found in ROM VPD\n");
+       dev_addr[0] = 0x08;
+       dev_addr[1] = 0x00;
+       dev_addr[2] = 0x20;
+       get_random_bytes(dev_addr + 3, 3);
+
+done:
+       writel(0, cp->regs + REG_BIM_LOCAL_DEV_EN);
+       return phy_type;
+}
+
+/* check pci invariants */
+static void cas_check_pci_invariants(struct cas *cp)
+{
+       struct pci_dev *pdev = cp->pdev;
+       u8 rev;
+
+       cp->cas_flags = 0;
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+       if ((pdev->vendor == PCI_VENDOR_ID_SUN) &&
+           (pdev->device == PCI_DEVICE_ID_SUN_CASSINI)) {
+               if (rev >= CAS_ID_REVPLUS)
+                       cp->cas_flags |= CAS_FLAG_REG_PLUS;
+               if (rev < CAS_ID_REVPLUS02u)
+                       cp->cas_flags |= CAS_FLAG_TARGET_ABORT;
+
+               /* Original Cassini supports HW CSUM, but it's not
+                * enabled by default as it can trigger TX hangs.
+                */
+               if (rev < CAS_ID_REV2)
+                       cp->cas_flags |= CAS_FLAG_NO_HW_CSUM;
+       } else {
+               /* Only sun has original cassini chips.  */
+               cp->cas_flags |= CAS_FLAG_REG_PLUS;
+
+               /* We use a flag because the same phy might be externally
+                * connected.
+                */
+               if ((pdev->vendor == PCI_VENDOR_ID_NS) &&
+                   (pdev->device == PCI_DEVICE_ID_NS_SATURN))
+                       cp->cas_flags |= CAS_FLAG_SATURN;
+       }
+}
+
+
+static int cas_check_invariants(struct cas *cp)
+{
+       struct pci_dev *pdev = cp->pdev;
+       u32 cfg;
+       int i;
+
+       /* get page size for rx buffers. */
+       cp->page_order = 0; 
+#ifdef USE_PAGE_ORDER
+       if (PAGE_SHIFT < CAS_JUMBO_PAGE_SHIFT) {
+               /* see if we can allocate larger pages */
+               struct page *page = alloc_pages(GFP_ATOMIC, 
+                                               CAS_JUMBO_PAGE_SHIFT - 
+                                               PAGE_SHIFT);
+               if (page) {
+                       __free_pages(page, CAS_JUMBO_PAGE_SHIFT - PAGE_SHIFT);
+                       cp->page_order = CAS_JUMBO_PAGE_SHIFT - PAGE_SHIFT;
+               } else {
+                       printk(PFX "MTU limited to %d bytes\n", CAS_MAX_MTU);
+               }
+       }
+#endif
+       cp->page_size = (PAGE_SIZE << cp->page_order);
+
+       /* Fetch the FIFO configurations. */
+       cp->tx_fifo_size = readl(cp->regs + REG_TX_FIFO_SIZE) * 64;
+       cp->rx_fifo_size = RX_FIFO_SIZE;
+
+       /* finish phy determination. MDIO1 takes precedence over MDIO0 if 
+        * they're both connected.
+        */
+       cp->phy_type = cas_get_vpd_info(cp, cp->dev->dev_addr, 
+                                       PCI_SLOT(pdev->devfn));
+       if (cp->phy_type & CAS_PHY_SERDES) {
+               cp->cas_flags |= CAS_FLAG_1000MB_CAP;
+               return 0; /* no more checking needed */
+       } 
+
+       /* MII */
+       cfg = readl(cp->regs + REG_MIF_CFG);
+       if (cfg & MIF_CFG_MDIO_1) {
+               cp->phy_type = CAS_PHY_MII_MDIO1;
+       } else if (cfg & MIF_CFG_MDIO_0) {
+               cp->phy_type = CAS_PHY_MII_MDIO0;
+       }
+
+       cas_mif_poll(cp, 0);
+       writel(PCS_DATAPATH_MODE_MII, cp->regs + REG_PCS_DATAPATH_MODE);
+
+       for (i = 0; i < 32; i++) {
+               u32 phy_id;
+               int j;
+
+               for (j = 0; j < 3; j++) {
+                       cp->phy_addr = i;
+                       phy_id = cas_phy_read(cp, MII_PHYSID1) << 16;
+                       phy_id |= cas_phy_read(cp, MII_PHYSID2);
+                       if (phy_id && (phy_id != 0xFFFFFFFF)) {
+                               cp->phy_id = phy_id;
+                               goto done;
+                       }
+               }
+       }
+       printk(KERN_ERR PFX "MII phy did not respond [%08x]\n",
+              readl(cp->regs + REG_MIF_STATE_MACHINE));
+       return -1;
+
+done:
+       /* see if we can do gigabit */
+       cfg = cas_phy_read(cp, MII_BMSR);
+       if ((cfg & CAS_BMSR_1000_EXTEND) && 
+           cas_phy_read(cp, CAS_MII_1000_EXTEND))
+               cp->cas_flags |= CAS_FLAG_1000MB_CAP;
+       return 0;
+}
+
+/* Must be invoked under cp->lock. */
+static inline void cas_start_dma(struct cas *cp)
+{
+       int i;
+       u32 val;
+       int txfailed = 0;
+       
+       /* enable dma */
+       val = readl(cp->regs + REG_TX_CFG) | TX_CFG_DMA_EN;
+       writel(val, cp->regs + REG_TX_CFG);
+       val = readl(cp->regs + REG_RX_CFG) | RX_CFG_DMA_EN;
+       writel(val, cp->regs + REG_RX_CFG);
+
+       /* enable the mac */
+       val = readl(cp->regs + REG_MAC_TX_CFG) | MAC_TX_CFG_EN;
+       writel(val, cp->regs + REG_MAC_TX_CFG);
+       val = readl(cp->regs + REG_MAC_RX_CFG) | MAC_RX_CFG_EN;
+       writel(val, cp->regs + REG_MAC_RX_CFG);
+
+       i = STOP_TRIES;
+       while (i-- > 0) {
+               val = readl(cp->regs + REG_MAC_TX_CFG);
+               if ((val & MAC_TX_CFG_EN))
+                       break;
+               udelay(10);
+       }
+       if (i < 0) txfailed = 1;
+       i = STOP_TRIES;
+       while (i-- > 0) {
+               val = readl(cp->regs + REG_MAC_RX_CFG);
+               if ((val & MAC_RX_CFG_EN)) {
+                       if (txfailed) {
+                         printk(KERN_ERR 
+                                "%s: enabling mac failed [tx:%08x:%08x].\n", 
+                                cp->dev->name,
+                                readl(cp->regs + REG_MIF_STATE_MACHINE),
+                                readl(cp->regs + REG_MAC_STATE_MACHINE));
+                       }
+                       goto enable_rx_done;
+               }
+               udelay(10);
+       }
+       printk(KERN_ERR "%s: enabling mac failed [%s:%08x:%08x].\n", 
+              cp->dev->name,
+              (txfailed? "tx,rx":"rx"),
+              readl(cp->regs + REG_MIF_STATE_MACHINE),
+              readl(cp->regs + REG_MAC_STATE_MACHINE));
+
+enable_rx_done:
+       cas_unmask_intr(cp); /* enable interrupts */
+       writel(RX_DESC_RINGN_SIZE(0) - 4, cp->regs + REG_RX_KICK);
+       writel(0, cp->regs + REG_RX_COMP_TAIL);
+
+       if (cp->cas_flags & CAS_FLAG_REG_PLUS) {
+               if (N_RX_DESC_RINGS > 1) 
+                       writel(RX_DESC_RINGN_SIZE(1) - 4, 
+                              cp->regs + REG_PLUS_RX_KICK1);
+
+               for (i = 1; i < N_RX_COMP_RINGS; i++) 
+                       writel(0, cp->regs + REG_PLUS_RX_COMPN_TAIL(i));
+       }
+}
+
+/* Must be invoked under cp->lock. */
+static void cas_read_pcs_link_mode(struct cas *cp, int *fd, int *spd,
+                                  int *pause)
+{
+       u32 val = readl(cp->regs + REG_PCS_MII_LPA);
+       *fd     = (val & PCS_MII_LPA_FD) ? 1 : 0;
+       *pause  = (val & PCS_MII_LPA_SYM_PAUSE) ? 0x01 : 0x00;
+       if (val & PCS_MII_LPA_ASYM_PAUSE)
+               *pause |= 0x10;
+       *spd = 1000;
+}
+
+/* Must be invoked under cp->lock. */
+static void cas_read_mii_link_mode(struct cas *cp, int *fd, int *spd,
+                                  int *pause)
+{
+       u32 val;
+
+       *fd = 0;
+       *spd = 10;
+       *pause = 0;
+       
+       /* use GMII registers */
+       val = cas_phy_read(cp, MII_LPA);
+       if (val & CAS_LPA_PAUSE)
+               *pause = 0x01;
+
+       if (val & CAS_LPA_ASYM_PAUSE)
+               *pause |= 0x10;
+
+       if (val & LPA_DUPLEX)
+               *fd = 1;
+       if (val & LPA_100)
+               *spd = 100;
+
+       if (cp->cas_flags & CAS_FLAG_1000MB_CAP) {
+               val = cas_phy_read(cp, CAS_MII_1000_STATUS);
+               if (val & (CAS_LPA_1000FULL | CAS_LPA_1000HALF))
+                       *spd = 1000;
+               if (val & CAS_LPA_1000FULL)
+                       *fd = 1;
+       }
+}
+
+/* A link-up condition has occurred, initialize and enable the
+ * rest of the chip.
+ *
+ * Must be invoked under cp->lock.
+ */
+static void cas_set_link_modes(struct cas *cp)
+{
+       u32 val;
+       int full_duplex, speed, pause;
+
+       full_duplex = 0;
+       speed = 10;
+       pause = 0;
+
+       if (CAS_PHY_MII(cp->phy_type)) {
+               cas_mif_poll(cp, 0);
+               val = cas_phy_read(cp, MII_BMCR);
+               if (val & BMCR_ANENABLE) {
+                       cas_read_mii_link_mode(cp, &full_duplex, &speed, 
+                                              &pause);
+               } else {
+                       if (val & BMCR_FULLDPLX)
+                               full_duplex = 1;
+
+                       if (val & BMCR_SPEED100)
+                               speed = 100;
+                       else if (val & CAS_BMCR_SPEED1000)
+                               speed = (cp->cas_flags & CAS_FLAG_1000MB_CAP) ?
+                                       1000 : 100;
+               }
+               cas_mif_poll(cp, 1);
+
+       } else {
+               val = readl(cp->regs + REG_PCS_MII_CTRL);
+               cas_read_pcs_link_mode(cp, &full_duplex, &speed, &pause);
+               if ((val & PCS_MII_AUTONEG_EN) == 0) {
+                       if (val & PCS_MII_CTRL_DUPLEX)
+                               full_duplex = 1;
+               }
+       }
+
+       if (netif_msg_link(cp))
+               printk(KERN_INFO "%s: Link up at %d Mbps, %s-duplex.\n",
+                      cp->dev->name, speed, (full_duplex ? "full" : "half"));
+
+       val = MAC_XIF_TX_MII_OUTPUT_EN | MAC_XIF_LINK_LED;
+       if (CAS_PHY_MII(cp->phy_type)) {
+               val |= MAC_XIF_MII_BUFFER_OUTPUT_EN;
+               if (!full_duplex)
+                       val |= MAC_XIF_DISABLE_ECHO;
+       }
+       if (full_duplex) 
+               val |= MAC_XIF_FDPLX_LED;
+       if (speed == 1000)
+               val |= MAC_XIF_GMII_MODE;
+       writel(val, cp->regs + REG_MAC_XIF_CFG);
+
+       /* deal with carrier and collision detect. */
+       val = MAC_TX_CFG_IPG_EN;
+       if (full_duplex) {
+               val |= MAC_TX_CFG_IGNORE_CARRIER;
+               val |= MAC_TX_CFG_IGNORE_COLL;
+       } else {
+#ifndef USE_CSMA_CD_PROTO
+               val |= MAC_TX_CFG_NEVER_GIVE_UP_EN;
+               val |= MAC_TX_CFG_NEVER_GIVE_UP_LIM;
+#endif
+       }
+       /* val now set up for REG_MAC_TX_CFG */
+
+       /* If gigabit and half-duplex, enable carrier extension
+        * mode.  increase slot time to 512 bytes as well. 
+        * else, disable it and make sure slot time is 64 bytes.
+        * also activate checksum bug workaround
+        */
+       if ((speed == 1000) && !full_duplex) {
+               writel(val | MAC_TX_CFG_CARRIER_EXTEND, 
+                      cp->regs + REG_MAC_TX_CFG);
+
+               val = readl(cp->regs + REG_MAC_RX_CFG);
+               val &= ~MAC_RX_CFG_STRIP_FCS; /* checksum workaround */
+               writel(val | MAC_RX_CFG_CARRIER_EXTEND, 
+                      cp->regs + REG_MAC_RX_CFG);
+
+               writel(0x200, cp->regs + REG_MAC_SLOT_TIME);
+
+               cp->crc_size = 4;
+               /* minimum size gigabit frame at half duplex */
+               cp->min_frame_size = CAS_1000MB_MIN_FRAME;
+
+       } else {
+               writel(val, cp->regs + REG_MAC_TX_CFG);
+
+               /* checksum bug workaround. don't strip FCS when in 
+                * half-duplex mode
+                */
+               val = readl(cp->regs + REG_MAC_RX_CFG);
+               if (full_duplex) {
+                       val |= MAC_RX_CFG_STRIP_FCS;
+                       cp->crc_size = 0;
+                       cp->min_frame_size = CAS_MIN_MTU;
+               } else {
+                       val &= ~MAC_RX_CFG_STRIP_FCS;
+                       cp->crc_size = 4;
+                       cp->min_frame_size = CAS_MIN_FRAME;
+               }
+               writel(val & ~MAC_RX_CFG_CARRIER_EXTEND, 
+                      cp->regs + REG_MAC_RX_CFG);
+               writel(0x40, cp->regs + REG_MAC_SLOT_TIME);
+       }
+
+       if (netif_msg_link(cp)) {
+               if (pause & 0x01) {
+                       printk(KERN_INFO "%s: Pause is enabled "
+                              "(rxfifo: %d off: %d on: %d)\n",
+                              cp->dev->name,
+                              cp->rx_fifo_size,
+                              cp->rx_pause_off,
+                              cp->rx_pause_on);
+               } else if (pause & 0x10) {
+                       printk(KERN_INFO "%s: TX pause enabled\n",
+                              cp->dev->name);
+               } else {
+                       printk(KERN_INFO "%s: Pause is disabled\n",
+                              cp->dev->name);
+               }
+       }
+
+       val = readl(cp->regs + REG_MAC_CTRL_CFG);
+       val &= ~(MAC_CTRL_CFG_SEND_PAUSE_EN | MAC_CTRL_CFG_RECV_PAUSE_EN);
+       if (pause) { /* symmetric or asymmetric pause */
+               val |= MAC_CTRL_CFG_SEND_PAUSE_EN;
+               if (pause & 0x01) { /* symmetric pause */
+                       val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
+               } 
+       }
+       writel(val, cp->regs + REG_MAC_CTRL_CFG);
+       cas_start_dma(cp);
+}
+
+/* Must be invoked under cp->lock. */
+static void cas_init_hw(struct cas *cp, int restart_link)
+{
+       if (restart_link)
+               cas_phy_init(cp);
+
+       cas_init_pause_thresholds(cp);
+       cas_init_mac(cp);
+       cas_init_dma(cp);
+
+       if (restart_link) {
+               /* Default aneg parameters */
+               cp->timer_ticks = 0;
+               cas_begin_auto_negotiation(cp, NULL);
+       } else if (cp->lstate == link_up) {
+               cas_set_link_modes(cp);
+               netif_carrier_on(cp->dev);
+       }
+}
+
+/* Must be invoked under cp->lock. on earlier cassini boards,
+ * SOFT_0 is tied to PCI reset. we use this to force a pci reset,
+ * let it settle out, and then restore pci state.
+ */
+static void cas_hard_reset(struct cas *cp)
+{
+       writel(BIM_LOCAL_DEV_SOFT_0, cp->regs + REG_BIM_LOCAL_DEV_EN); 
+       udelay(20);
+       pci_restore_state(cp->pdev);
+}
+
+
+static void cas_global_reset(struct cas *cp, int blkflag)
+{
+       int limit;
+
+       /* issue a global reset. don't use RSTOUT. */
+       if (blkflag && !CAS_PHY_MII(cp->phy_type)) {
+               /* For PCS, when the blkflag is set, we should set the
+                * SW_REST_BLOCK_PCS_SLINK bit to prevent the results of
+                * the last autonegotiation from being cleared.  We'll
+                * need some special handling if the chip is set into a
+                * loopback mode.
+                */
+               writel((SW_RESET_TX | SW_RESET_RX | SW_RESET_BLOCK_PCS_SLINK), 
+                      cp->regs + REG_SW_RESET);
+       } else {
+               writel(SW_RESET_TX | SW_RESET_RX, cp->regs + REG_SW_RESET);
+       }
+
+       /* need to wait at least 3ms before polling register */
+       mdelay(3);
+
+       limit = STOP_TRIES;
+       while (limit-- > 0) {
+               u32 val = readl(cp->regs + REG_SW_RESET);
+               if ((val & (SW_RESET_TX | SW_RESET_RX)) == 0)
+                       goto done;
+               udelay(10);
+       }
+       printk(KERN_ERR "%s: sw reset failed.\n", cp->dev->name);
+
+done:
+       /* enable various BIM interrupts */
+       writel(BIM_CFG_DPAR_INTR_ENABLE | BIM_CFG_RMA_INTR_ENABLE | 
+              BIM_CFG_RTA_INTR_ENABLE, cp->regs + REG_BIM_CFG);
+
+       /* clear out pci error status mask for handled errors.
+        * we don't deal with DMA counter overflows as they happen
+        * all the time.
+        */
+       writel(0xFFFFFFFFU & ~(PCI_ERR_BADACK | PCI_ERR_DTRTO | 
+                              PCI_ERR_OTHER | PCI_ERR_BIM_DMA_WRITE | 
+                              PCI_ERR_BIM_DMA_READ), cp->regs + 
+              REG_PCI_ERR_STATUS_MASK);
+
+       /* set up for MII by default to address mac rx reset timeout
+        * issue
+        */
+       writel(PCS_DATAPATH_MODE_MII, cp->regs + REG_PCS_DATAPATH_MODE);
+}
+
+static void cas_reset(struct cas *cp, int blkflag)
+{
+       u32 val;
+
+       cas_mask_intr(cp);
+       cas_global_reset(cp, blkflag);
+       cas_mac_reset(cp);
+       cas_entropy_reset(cp);
+
+       /* disable dma engines. */
+       val = readl(cp->regs + REG_TX_CFG);
+       val &= ~TX_CFG_DMA_EN;
+       writel(val, cp->regs + REG_TX_CFG);
+
+       val = readl(cp->regs + REG_RX_CFG);
+       val &= ~RX_CFG_DMA_EN;
+       writel(val, cp->regs + REG_RX_CFG);
+
+       /* program header parser */
+       if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) ||
+           (CAS_HP_ALT_FIRMWARE == cas_prog_null)) {
+               cas_load_firmware(cp, CAS_HP_FIRMWARE);
+       } else {
+               cas_load_firmware(cp, CAS_HP_ALT_FIRMWARE);
+       }
+
+       /* clear out error registers */
+       spin_lock(&cp->stat_lock[N_TX_RINGS]);
+       cas_clear_mac_err(cp);
+       spin_unlock(&cp->stat_lock[N_TX_RINGS]);
+}
+
+/* Shut down the chip, must be called with pm_sem held.  */
+static void cas_shutdown(struct cas *cp)
+{
+       unsigned long flags;
+
+       /* Make us not-running to avoid timers respawning */
+       cp->hw_running = 0;
+
+       del_timer_sync(&cp->link_timer);
+
+       /* Stop the reset task */
+#if 0
+       while (atomic_read(&cp->reset_task_pending_mtu) ||
+              atomic_read(&cp->reset_task_pending_spare) ||
+              atomic_read(&cp->reset_task_pending_all))
+               schedule();
+
+#else
+       while (atomic_read(&cp->reset_task_pending))
+               schedule();
+#endif 
+       /* Actually stop the chip */
+       cas_lock_all_save(cp, flags);
+       cas_reset(cp, 0);
+       if (cp->cas_flags & CAS_FLAG_SATURN)
+               cas_phy_powerdown(cp);
+       cas_unlock_all_restore(cp, flags);
+}
+
+static int cas_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct cas *cp = netdev_priv(dev);
+
+       if (new_mtu < CAS_MIN_MTU || new_mtu > CAS_MAX_MTU)
+               return -EINVAL;
+
+       dev->mtu = new_mtu;
+       if (!netif_running(dev) || !netif_device_present(dev))
+               return 0;
+
+       /* let the reset task handle it */
+#if 1
+       atomic_inc(&cp->reset_task_pending);
+       if ((cp->phy_type & CAS_PHY_SERDES)) {
+               atomic_inc(&cp->reset_task_pending_all);
+       } else {
+               atomic_inc(&cp->reset_task_pending_mtu);
+       }
+       schedule_work(&cp->reset_task);
+#else
+       atomic_set(&cp->reset_task_pending, (cp->phy_type & CAS_PHY_SERDES) ? 
+                  CAS_RESET_ALL : CAS_RESET_MTU);
+       printk(KERN_ERR "reset called in cas_change_mtu\n");
+       schedule_work(&cp->reset_task);
+#endif
+
+       flush_scheduled_work();
+       return 0;
+}
+
+static void cas_clean_txd(struct cas *cp, int ring)
+{
+       struct cas_tx_desc *txd = cp->init_txds[ring];
+       struct sk_buff *skb, **skbs = cp->tx_skbs[ring];
+       u64 daddr, dlen;
+       int i, size;
+
+       size = TX_DESC_RINGN_SIZE(ring);
+       for (i = 0; i < size; i++) {
+               int frag;
+
+               if (skbs[i] == NULL)
+                       continue;
+
+               skb = skbs[i];
+               skbs[i] = NULL;
+
+               for (frag = 0; frag <= skb_shinfo(skb)->nr_frags;  frag++) {
+                       int ent = i & (size - 1);
+
+                       /* first buffer is never a tiny buffer and so
+                        * needs to be unmapped.
+                        */
+                       daddr = le64_to_cpu(txd[ent].buffer);
+                       dlen  =  CAS_VAL(TX_DESC_BUFLEN, 
+                                        le64_to_cpu(txd[ent].control));
+                       pci_unmap_page(cp->pdev, daddr, dlen,
+                                      PCI_DMA_TODEVICE);
+
+                       if (frag != skb_shinfo(skb)->nr_frags) {
+                               i++;
+
+                               /* next buffer might by a tiny buffer.
+                                * skip past it.
+                                */
+                               ent = i & (size - 1);
+                               if (cp->tx_tiny_use[ring][ent].used)
+                                       i++;
+                       }
+               }
+               dev_kfree_skb_any(skb);
+       }
+
+       /* zero out tiny buf usage */
+       memset(cp->tx_tiny_use[ring], 0, size*sizeof(*cp->tx_tiny_use[ring]));
+}
+
+/* freed on close */
+static inline void cas_free_rx_desc(struct cas *cp, int ring)
+{
+       cas_page_t **page = cp->rx_pages[ring];
+       int i, size;
+
+       size = RX_DESC_RINGN_SIZE(ring);
+       for (i = 0; i < size; i++) {
+               if (page[i]) {
+                       cas_page_free(cp, page[i]);
+                       page[i] = NULL;
+               }
+       }
+}
+
+static void cas_free_rxds(struct cas *cp)
+{
+       int i;
+
+       for (i = 0; i < N_RX_DESC_RINGS; i++)
+               cas_free_rx_desc(cp, i);
+}
+
+/* Must be invoked under cp->lock. */
+static void cas_clean_rings(struct cas *cp)
+{
+       int i;
+
+       /* need to clean all tx rings */
+       memset(cp->tx_old, 0, sizeof(*cp->tx_old)*N_TX_RINGS);
+       memset(cp->tx_new, 0, sizeof(*cp->tx_new)*N_TX_RINGS);
+       for (i = 0; i < N_TX_RINGS; i++)
+               cas_clean_txd(cp, i);
+
+       /* zero out init block */
+       memset(cp->init_block, 0, sizeof(struct cas_init_block));
+       cas_clean_rxds(cp);
+       cas_clean_rxcs(cp);
+}
+
+/* allocated on open */
+static inline int cas_alloc_rx_desc(struct cas *cp, int ring)
+{
+       cas_page_t **page = cp->rx_pages[ring];
+       int size, i = 0;
+
+       size = RX_DESC_RINGN_SIZE(ring);
+       for (i = 0; i < size; i++) {
+               if ((page[i] = cas_page_alloc(cp, GFP_KERNEL)) == NULL) 
+                       return -1;
+       }
+       return 0;
+}
+
+static int cas_alloc_rxds(struct cas *cp)
+{
+       int i;
+
+       for (i = 0; i < N_RX_DESC_RINGS; i++) {
+               if (cas_alloc_rx_desc(cp, i) < 0) {
+                       cas_free_rxds(cp);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+static void cas_reset_task(void *data)
+{
+       struct cas *cp = (struct cas *) data;
+#if 0
+       int pending = atomic_read(&cp->reset_task_pending);
+#else
+       int pending_all = atomic_read(&cp->reset_task_pending_all);
+       int pending_spare = atomic_read(&cp->reset_task_pending_spare);
+       int pending_mtu = atomic_read(&cp->reset_task_pending_mtu);
+
+       if (pending_all == 0 && pending_spare == 0 && pending_mtu == 0) {
+               /* We can have more tasks scheduled than actually
+                * needed.
+                */
+               atomic_dec(&cp->reset_task_pending);
+               return;
+       }
+#endif
+       /* The link went down, we reset the ring, but keep
+        * DMA stopped. Use this function for reset
+        * on error as well.
+        */
+       if (cp->hw_running) {
+               unsigned long flags;
+
+               /* Make sure we don't get interrupts or tx packets */
+               netif_device_detach(cp->dev);
+               cas_lock_all_save(cp, flags);
+
+               if (cp->opened) {
+                       /* We call cas_spare_recover when we call cas_open.
+                        * but we do not initialize the lists cas_spare_recover
+                        * uses until cas_open is called.
+                        */
+                       cas_spare_recover(cp, GFP_ATOMIC);
+               }
+#if 1
+               /* test => only pending_spare set */
+               if (!pending_all && !pending_mtu)
+                       goto done;
+#else
+               if (pending == CAS_RESET_SPARE)
+                       goto done;
+#endif
+               /* when pending == CAS_RESET_ALL, the following
+                * call to cas_init_hw will restart auto negotiation.
+                * Setting the second argument of cas_reset to
+                * !(pending == CAS_RESET_ALL) will set this argument
+                * to 1 (avoiding reinitializing the PHY for the normal 
+                * PCS case) when auto negotiation is not restarted.
+                */
+#if 1
+               cas_reset(cp, !(pending_all > 0));
+               if (cp->opened)
+                       cas_clean_rings(cp);
+               cas_init_hw(cp, (pending_all > 0));
+#else
+               cas_reset(cp, !(pending == CAS_RESET_ALL));
+               if (cp->opened)
+                       cas_clean_rings(cp);
+               cas_init_hw(cp, pending == CAS_RESET_ALL);
+#endif
+
+done:
+               cas_unlock_all_restore(cp, flags);
+               netif_device_attach(cp->dev);
+       }
+#if 1
+       atomic_sub(pending_all, &cp->reset_task_pending_all);
+       atomic_sub(pending_spare, &cp->reset_task_pending_spare);
+       atomic_sub(pending_mtu, &cp->reset_task_pending_mtu);
+       atomic_dec(&cp->reset_task_pending);
+#else
+       atomic_set(&cp->reset_task_pending, 0);
+#endif
+}
+
+static void cas_link_timer(unsigned long data)
+{
+       struct cas *cp = (struct cas *) data;
+       int mask, pending = 0, reset = 0;
+       unsigned long flags;
+
+       if (link_transition_timeout != 0 &&
+           cp->link_transition_jiffies_valid &&
+           ((jiffies - cp->link_transition_jiffies) > 
+             (link_transition_timeout))) {
+               /* One-second counter so link-down workaround doesn't 
+                * cause resets to occur so fast as to fool the switch
+                * into thinking the link is down.
+                */
+               cp->link_transition_jiffies_valid = 0;
+       }
+
+       if (!cp->hw_running)
+               return;
+
+       spin_lock_irqsave(&cp->lock, flags);
+       cas_lock_tx(cp);
+       cas_entropy_gather(cp);
+
+       /* If the link task is still pending, we just
+        * reschedule the link timer
+        */
+#if 1
+       if (atomic_read(&cp->reset_task_pending_all) ||
+           atomic_read(&cp->reset_task_pending_spare) ||
+           atomic_read(&cp->reset_task_pending_mtu)) 
+               goto done;
+#else
+       if (atomic_read(&cp->reset_task_pending)) 
+               goto done;
+#endif
+
+       /* check for rx cleaning */
+       if ((mask = (cp->cas_flags & CAS_FLAG_RXD_POST_MASK))) {
+               int i, rmask;
+
+               for (i = 0; i < MAX_RX_DESC_RINGS; i++) {
+                       rmask = CAS_FLAG_RXD_POST(i);
+                       if ((mask & rmask) == 0)
+                               continue;
+
+                       /* post_rxds will do a mod_timer */
+                       if (cas_post_rxds_ringN(cp, i, cp->rx_last[i]) < 0) {
+                               pending = 1;
+                               continue;
+                       }
+                       cp->cas_flags &= ~rmask;
+               }
+       }
+
+       if (CAS_PHY_MII(cp->phy_type)) {
+               u16 bmsr;
+               cas_mif_poll(cp, 0);
+               bmsr = cas_phy_read(cp, MII_BMSR);
+               /* WTZ: Solaris driver reads this twice, but that
+                * may be due to the PCS case and the use of a
+                * common implementation. Read it twice here to be
+                * safe.
+                */
+               bmsr = cas_phy_read(cp, MII_BMSR);
+               cas_mif_poll(cp, 1);
+               readl(cp->regs + REG_MIF_STATUS); /* avoid dups */
+               reset = cas_mii_link_check(cp, bmsr);
+       } else {
+               reset = cas_pcs_link_check(cp);
+       }
+
+       if (reset)
+               goto done;
+
+       /* check for tx state machine confusion */
+       if ((readl(cp->regs + REG_MAC_TX_STATUS) & MAC_TX_FRAME_XMIT) == 0) {
+               u32 val = readl(cp->regs + REG_MAC_STATE_MACHINE);
+               u32 wptr, rptr;
+               int tlm  = CAS_VAL(MAC_SM_TLM, val);
+
+               if (((tlm == 0x5) || (tlm == 0x3)) &&
+                   (CAS_VAL(MAC_SM_ENCAP_SM, val) == 0)) {
+                       if (netif_msg_tx_err(cp))
+                               printk(KERN_DEBUG "%s: tx err: "
+                                      "MAC_STATE[%08x]\n",
+                                      cp->dev->name, val);
+                       reset = 1;
+                       goto done;
+               }
+
+               val  = readl(cp->regs + REG_TX_FIFO_PKT_CNT);
+               wptr = readl(cp->regs + REG_TX_FIFO_WRITE_PTR);
+               rptr = readl(cp->regs + REG_TX_FIFO_READ_PTR);
+               if ((val == 0) && (wptr != rptr)) {
+                       if (netif_msg_tx_err(cp))
+                               printk(KERN_DEBUG "%s: tx err: "
+                                      "TX_FIFO[%08x:%08x:%08x]\n",
+                                      cp->dev->name, val, wptr, rptr);
+                       reset = 1;
+               }
+
+               if (reset)
+                       cas_hard_reset(cp);
+       }
+
+done:
+       if (reset) {
+#if 1
+               atomic_inc(&cp->reset_task_pending);
+               atomic_inc(&cp->reset_task_pending_all);
+               schedule_work(&cp->reset_task);
+#else
+               atomic_set(&cp->reset_task_pending, CAS_RESET_ALL);
+               printk(KERN_ERR "reset called in cas_link_timer\n");
+               schedule_work(&cp->reset_task);
+#endif
+       }
+
+       if (!pending)
+               mod_timer(&cp->link_timer, jiffies + CAS_LINK_TIMEOUT);
+       cas_unlock_tx(cp);
+       spin_unlock_irqrestore(&cp->lock, flags);
+}
+
+/* tiny buffers are used to avoid target abort issues with 
+ * older cassini's
+ */
+static void cas_tx_tiny_free(struct cas *cp)
+{
+       struct pci_dev *pdev = cp->pdev;
+       int i;
+
+       for (i = 0; i < N_TX_RINGS; i++) {
+               if (!cp->tx_tiny_bufs[i])
+                       continue;
+
+               pci_free_consistent(pdev, TX_TINY_BUF_BLOCK, 
+                                   cp->tx_tiny_bufs[i],
+                                   cp->tx_tiny_dvma[i]);
+               cp->tx_tiny_bufs[i] = NULL;
+       }
+}
+
+static int cas_tx_tiny_alloc(struct cas *cp)
+{
+       struct pci_dev *pdev = cp->pdev;
+       int i;
+
+       for (i = 0; i < N_TX_RINGS; i++) {
+               cp->tx_tiny_bufs[i] = 
+                       pci_alloc_consistent(pdev, TX_TINY_BUF_BLOCK,
+                                            &cp->tx_tiny_dvma[i]);
+               if (!cp->tx_tiny_bufs[i]) {
+                       cas_tx_tiny_free(cp);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+
+static int cas_open(struct net_device *dev)
+{
+       struct cas *cp = netdev_priv(dev);
+       int hw_was_up, err;
+       unsigned long flags;
+
+       down(&cp->pm_sem);
+
+       hw_was_up = cp->hw_running;
+
+       /* The power-management semaphore protects the hw_running
+        * etc. state so it is safe to do this bit without cp->lock
+        */
+       if (!cp->hw_running) {
+               /* Reset the chip */
+               cas_lock_all_save(cp, flags);
+               /* We set the second arg to cas_reset to zero
+                * because cas_init_hw below will have its second 
+                * argument set to non-zero, which will force
+                * autonegotiation to start.
+                */
+               cas_reset(cp, 0);
+               cp->hw_running = 1;
+               cas_unlock_all_restore(cp, flags);
+       }
+
+       if (cas_tx_tiny_alloc(cp) < 0)
+               return -ENOMEM;
+
+       /* alloc rx descriptors */
+       err = -ENOMEM;
+       if (cas_alloc_rxds(cp) < 0)
+               goto err_tx_tiny;
+       
+       /* allocate spares */
+       cas_spare_init(cp);
+       cas_spare_recover(cp, GFP_KERNEL);
+
+       /* We can now request the interrupt as we know it's masked
+        * on the controller. cassini+ has up to 4 interrupts
+        * that can be used, but you need to do explicit pci interrupt 
+        * mapping to expose them
+        */
+       if (request_irq(cp->pdev->irq, cas_interrupt,
+                       SA_SHIRQ, dev->name, (void *) dev)) {
+               printk(KERN_ERR "%s: failed to request irq !\n", 
+                      cp->dev->name);
+               err = -EAGAIN;
+               goto err_spare;
+       }
+
+       /* init hw */
+       cas_lock_all_save(cp, flags);
+       cas_clean_rings(cp);
+       cas_init_hw(cp, !hw_was_up);
+       cp->opened = 1;
+       cas_unlock_all_restore(cp, flags);
+
+       netif_start_queue(dev);
+       up(&cp->pm_sem);
+       return 0;
+
+err_spare:
+       cas_spare_free(cp);
+       cas_free_rxds(cp);
+err_tx_tiny:
+       cas_tx_tiny_free(cp);
+       up(&cp->pm_sem);
+       return err;
+}
+
+static int cas_close(struct net_device *dev)
+{
+       unsigned long flags;
+       struct cas *cp = netdev_priv(dev);
+
+       /* Make sure we don't get distracted by suspend/resume */
+       down(&cp->pm_sem);
+
+       netif_stop_queue(dev);
+
+       /* Stop traffic, mark us closed */
+       cas_lock_all_save(cp, flags);
+       cp->opened = 0; 
+       cas_reset(cp, 0);
+       cas_phy_init(cp); 
+       cas_begin_auto_negotiation(cp, NULL);
+       cas_clean_rings(cp);
+       cas_unlock_all_restore(cp, flags);
+
+       free_irq(cp->pdev->irq, (void *) dev);
+       cas_spare_free(cp);
+       cas_free_rxds(cp);
+       cas_tx_tiny_free(cp);
+       up(&cp->pm_sem);
+       return 0;
+}
+
+static struct {
+       const char name[ETH_GSTRING_LEN];
+} ethtool_cassini_statnames[] = {
+       {"collisions"},
+       {"rx_bytes"},
+       {"rx_crc_errors"},
+       {"rx_dropped"},
+       {"rx_errors"},
+       {"rx_fifo_errors"},
+       {"rx_frame_errors"},
+       {"rx_length_errors"},
+       {"rx_over_errors"},
+       {"rx_packets"},
+       {"tx_aborted_errors"},
+       {"tx_bytes"},
+       {"tx_dropped"},
+       {"tx_errors"},
+       {"tx_fifo_errors"},
+       {"tx_packets"}
+};
+#define CAS_NUM_STAT_KEYS (sizeof(ethtool_cassini_statnames)/ETH_GSTRING_LEN)
+
+static struct {
+       const int offsets;      /* neg. values for 2nd arg to cas_read_phy */
+} ethtool_register_table[] = {
+       {-MII_BMSR},
+       {-MII_BMCR},
+       {REG_CAWR},
+       {REG_INF_BURST},
+       {REG_BIM_CFG},
+       {REG_RX_CFG},
+       {REG_HP_CFG},
+       {REG_MAC_TX_CFG},
+       {REG_MAC_RX_CFG},
+       {REG_MAC_CTRL_CFG},
+       {REG_MAC_XIF_CFG},
+       {REG_MIF_CFG},
+       {REG_PCS_CFG},
+       {REG_SATURN_PCFG},
+       {REG_PCS_MII_STATUS},
+       {REG_PCS_STATE_MACHINE},
+       {REG_MAC_COLL_EXCESS},
+       {REG_MAC_COLL_LATE}
+};
+#define CAS_REG_LEN    (sizeof(ethtool_register_table)/sizeof(int))
+#define CAS_MAX_REGS   (sizeof (u32)*CAS_REG_LEN)
+
+static u8 *cas_get_regs(struct cas *cp)
+{
+       u8 *ptr = kmalloc(CAS_MAX_REGS, GFP_KERNEL);
+       u8 *p;
+       int i;
+       unsigned long flags;
+
+       if (!ptr)
+               return NULL;
+
+       spin_lock_irqsave(&cp->lock, flags);
+       for (i = 0, p = ptr; i < CAS_REG_LEN ; i ++, p += sizeof(u32)) {
+               u16 hval;
+               u32 val;
+               if (ethtool_register_table[i].offsets < 0) {
+                       hval = cas_phy_read(cp,
+                                   -ethtool_register_table[i].offsets);
+                       val = hval;
+               } else {
+                       val= readl(cp->regs+ethtool_register_table[i].offsets);
+               }
+               memcpy(p, (u8 *)&val, sizeof(u32));
+       }
+       spin_unlock_irqrestore(&cp->lock, flags);
+
+       return ptr;
+}
+
+static struct net_device_stats *cas_get_stats(struct net_device *dev)
+{
+       struct cas *cp = netdev_priv(dev);
+       struct net_device_stats *stats = cp->net_stats;
+       unsigned long flags;
+       int i;
+       unsigned long tmp;
+
+       /* we collate all of the stats into net_stats[N_TX_RING] */
+       if (!cp->hw_running)
+               return stats + N_TX_RINGS;
+       
+       /* collect outstanding stats */
+       /* WTZ: the Cassini spec gives these as 16 bit counters but
+        * stored in 32-bit words.  Added a mask of 0xffff to be safe,
+        * in case the chip somehow puts any garbage in the other bits.
+        * Also, counter usage didn't seem to mach what Adrian did
+        * in the parts of the code that set these quantities. Made
+        * that consistent.
+        */
+       spin_lock_irqsave(&cp->stat_lock[N_TX_RINGS], flags);
+       stats[N_TX_RINGS].rx_crc_errors += 
+         readl(cp->regs + REG_MAC_FCS_ERR) & 0xffff;
+       stats[N_TX_RINGS].rx_frame_errors += 
+               readl(cp->regs + REG_MAC_ALIGN_ERR) &0xffff;
+       stats[N_TX_RINGS].rx_length_errors += 
+               readl(cp->regs + REG_MAC_LEN_ERR) & 0xffff;
+#if 1
+       tmp = (readl(cp->regs + REG_MAC_COLL_EXCESS) & 0xffff) +
+               (readl(cp->regs + REG_MAC_COLL_LATE) & 0xffff);
+       stats[N_TX_RINGS].tx_aborted_errors += tmp;
+       stats[N_TX_RINGS].collisions +=
+         tmp + (readl(cp->regs + REG_MAC_COLL_NORMAL) & 0xffff);
+#else
+       stats[N_TX_RINGS].tx_aborted_errors += 
+               readl(cp->regs + REG_MAC_COLL_EXCESS);
+       stats[N_TX_RINGS].collisions += readl(cp->regs + REG_MAC_COLL_EXCESS) +
+               readl(cp->regs + REG_MAC_COLL_LATE);
+#endif
+       cas_clear_mac_err(cp);
+
+       /* saved bits that are unique to ring 0 */
+       spin_lock(&cp->stat_lock[0]);
+       stats[N_TX_RINGS].collisions        += stats[0].collisions;
+       stats[N_TX_RINGS].rx_over_errors    += stats[0].rx_over_errors;
+       stats[N_TX_RINGS].rx_frame_errors   += stats[0].rx_frame_errors;
+       stats[N_TX_RINGS].rx_fifo_errors    += stats[0].rx_fifo_errors;
+       stats[N_TX_RINGS].tx_aborted_errors += stats[0].tx_aborted_errors;
+       stats[N_TX_RINGS].tx_fifo_errors    += stats[0].tx_fifo_errors;
+       spin_unlock(&cp->stat_lock[0]);
+
+       for (i = 0; i < N_TX_RINGS; i++) {
+               spin_lock(&cp->stat_lock[i]);
+               stats[N_TX_RINGS].rx_length_errors += 
+                       stats[i].rx_length_errors;
+               stats[N_TX_RINGS].rx_crc_errors += stats[i].rx_crc_errors;
+               stats[N_TX_RINGS].rx_packets    += stats[i].rx_packets;
+               stats[N_TX_RINGS].tx_packets    += stats[i].tx_packets;
+               stats[N_TX_RINGS].rx_bytes      += stats[i].rx_bytes;
+               stats[N_TX_RINGS].tx_bytes      += stats[i].tx_bytes;
+               stats[N_TX_RINGS].rx_errors     += stats[i].rx_errors;
+               stats[N_TX_RINGS].tx_errors     += stats[i].tx_errors;
+               stats[N_TX_RINGS].rx_dropped    += stats[i].rx_dropped;
+               stats[N_TX_RINGS].tx_dropped    += stats[i].tx_dropped;
+               memset(stats + i, 0, sizeof(struct net_device_stats));
+               spin_unlock(&cp->stat_lock[i]);
+       }
+       spin_unlock_irqrestore(&cp->stat_lock[N_TX_RINGS], flags);
+       return stats + N_TX_RINGS;
+}
+
+
+static void cas_set_multicast(struct net_device *dev)
+{
+       struct cas *cp = netdev_priv(dev);
+       u32 rxcfg, rxcfg_new;
+       unsigned long flags;
+       int limit = STOP_TRIES;
+       
+       if (!cp->hw_running)
+               return;
+               
+       spin_lock_irqsave(&cp->lock, flags);
+       rxcfg = readl(cp->regs + REG_MAC_RX_CFG);
+
+       /* disable RX MAC and wait for completion */
+       writel(rxcfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
+       while (readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_EN) {
+               if (!limit--)
+                       break;
+               udelay(10);
+       }
+
+       /* disable hash filter and wait for completion */
+       limit = STOP_TRIES;
+       rxcfg &= ~(MAC_RX_CFG_PROMISC_EN | MAC_RX_CFG_HASH_FILTER_EN);
+       writel(rxcfg & ~MAC_RX_CFG_EN, cp->regs + REG_MAC_RX_CFG);
+       while (readl(cp->regs + REG_MAC_RX_CFG) & MAC_RX_CFG_HASH_FILTER_EN) {
+               if (!limit--)
+                       break;
+               udelay(10);
+       }
+
+       /* program hash filters */
+       cp->mac_rx_cfg = rxcfg_new = cas_setup_multicast(cp);
+       rxcfg |= rxcfg_new;
+       writel(rxcfg, cp->regs + REG_MAC_RX_CFG);
+       spin_unlock_irqrestore(&cp->lock, flags);
+}
+
+/* Eventually add support for changing the advertisement
+ * on autoneg.
+ */
+static int cas_ethtool_ioctl(struct net_device *dev, void __user *ep_user)
+{
+       struct cas *cp = netdev_priv(dev);
+       u16 bmcr;
+       int full_duplex, speed, pause;
+       struct ethtool_cmd ecmd;
+       unsigned long flags;
+       enum link_state linkstate = link_up;
+
+       if (copy_from_user(&ecmd, ep_user, sizeof(ecmd)))
+               return -EFAULT;
+               
+       switch(ecmd.cmd) {
+        case ETHTOOL_GDRVINFO: {
+               struct ethtool_drvinfo info = { .cmd = ETHTOOL_GDRVINFO };
+
+               strncpy(info.driver, DRV_MODULE_NAME,
+                       ETHTOOL_BUSINFO_LEN);
+               strncpy(info.version, DRV_MODULE_VERSION,
+                       ETHTOOL_BUSINFO_LEN);
+               info.fw_version[0] = '\0';
+               strncpy(info.bus_info, pci_name(cp->pdev),
+                       ETHTOOL_BUSINFO_LEN);
+               info.regdump_len = cp->casreg_len < CAS_MAX_REGS ?
+                       cp->casreg_len : CAS_MAX_REGS;
+               info.n_stats = CAS_NUM_STAT_KEYS;
+               if (copy_to_user(ep_user, &info, sizeof(info)))
+                       return -EFAULT;
+
+               return 0;
+       }
+
+       case ETHTOOL_GSET:
+               ecmd.advertising = 0;
+               ecmd.supported = SUPPORTED_Autoneg;
+               if (cp->cas_flags & CAS_FLAG_1000MB_CAP) {
+                       ecmd.supported |= SUPPORTED_1000baseT_Full;
+                       ecmd.advertising |= ADVERTISED_1000baseT_Full;
+               }
+
+               /* Record PHY settings if HW is on. */
+               spin_lock_irqsave(&cp->lock, flags);
+               bmcr = 0;
+               linkstate = cp->lstate;
+               if (CAS_PHY_MII(cp->phy_type)) {
+                       ecmd.port = PORT_MII;
+                       ecmd.transceiver = (cp->cas_flags & CAS_FLAG_SATURN) ?
+                               XCVR_INTERNAL : XCVR_EXTERNAL;
+                       ecmd.phy_address = cp->phy_addr;
+                       ecmd.advertising |= ADVERTISED_TP | ADVERTISED_MII |
+                               ADVERTISED_10baseT_Half | 
+                               ADVERTISED_10baseT_Full | 
+                               ADVERTISED_100baseT_Half | 
+                               ADVERTISED_100baseT_Full;
+
+                       ecmd.supported |=
+                               (SUPPORTED_10baseT_Half | 
+                                SUPPORTED_10baseT_Full |
+                                SUPPORTED_100baseT_Half | 
+                                SUPPORTED_100baseT_Full |
+                                SUPPORTED_TP | SUPPORTED_MII);
+
+                       if (cp->hw_running) {
+                               cas_mif_poll(cp, 0);
+                               bmcr = cas_phy_read(cp, MII_BMCR);
+                               cas_read_mii_link_mode(cp, &full_duplex, 
+                                                      &speed, &pause);
+                               cas_mif_poll(cp, 1);
+                       }
+
+               } else {
+                       ecmd.port = PORT_FIBRE;
+                       ecmd.transceiver = XCVR_INTERNAL;
+                       ecmd.phy_address = 0;
+                       ecmd.supported   |= SUPPORTED_FIBRE;
+                       ecmd.advertising |= ADVERTISED_FIBRE;
+
+                       if (cp->hw_running) {
+                               /* pcs uses the same bits as mii */ 
+                               bmcr = readl(cp->regs + REG_PCS_MII_CTRL);
+                               cas_read_pcs_link_mode(cp, &full_duplex, 
+                                                      &speed, &pause);
+                       }
+               }
+               spin_unlock_irqrestore(&cp->lock, flags);
+
+               if (bmcr & BMCR_ANENABLE) {
+                       ecmd.advertising |= ADVERTISED_Autoneg;
+                       ecmd.autoneg = AUTONEG_ENABLE;
+                       ecmd.speed = ((speed == 10) ?
+                                     SPEED_10 :
+                                     ((speed == 1000) ?
+                                      SPEED_1000 : SPEED_100));
+                       ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+               } else {
+                       ecmd.autoneg = AUTONEG_DISABLE;
+                       ecmd.speed =
+                               (bmcr & CAS_BMCR_SPEED1000) ?
+                               SPEED_1000 : 
+                               ((bmcr & BMCR_SPEED100) ? SPEED_100: 
+                                SPEED_10);
+                       ecmd.duplex =
+                               (bmcr & BMCR_FULLDPLX) ?
+                               DUPLEX_FULL : DUPLEX_HALF;
+               }
+               if (linkstate != link_up) {
+                       /* Force these to "unknown" if the link is not up and
+                        * autonogotiation in enabled. We can set the link 
+                        * speed to 0, but not ecmd.duplex,
+                        * because its legal values are 0 and 1.  Ethtool will
+                        * print the value reported in parentheses after the
+                        * word "Unknown" for unrecognized values.
+                        *
+                        * If in forced mode, we report the speed and duplex
+                        * settings that we configured.
+                        */
+                       if (cp->link_cntl & BMCR_ANENABLE) {
+                               ecmd.speed = 0;
+                               ecmd.duplex = 0xff;
+                       } else {
+                               ecmd.speed = SPEED_10;
+                               if (cp->link_cntl & BMCR_SPEED100) {
+                                       ecmd.speed = SPEED_100;
+                               } else if (cp->link_cntl & CAS_BMCR_SPEED1000) {
+                                       ecmd.speed = SPEED_1000;
+                               }
+                               ecmd.duplex = (cp->link_cntl & BMCR_FULLDPLX)?
+                                       DUPLEX_FULL : DUPLEX_HALF;
+                       }
+               }
+               if (copy_to_user(ep_user, &ecmd, sizeof(ecmd)))
+                       return -EFAULT;
+               return 0;
+
+       case ETHTOOL_SSET:
+               if (!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+
+               /* Verify the settings we care about. */
+               if (ecmd.autoneg != AUTONEG_ENABLE &&
+                   ecmd.autoneg != AUTONEG_DISABLE)
+                       return -EINVAL;
+
+               if (ecmd.autoneg == AUTONEG_DISABLE &&
+                   ((ecmd.speed != SPEED_1000 &&
+                     ecmd.speed != SPEED_100 &&
+                     ecmd.speed != SPEED_10) ||
+                    (ecmd.duplex != DUPLEX_HALF &&
+                     ecmd.duplex != DUPLEX_FULL)))
+                       return -EINVAL;
+
+               /* Apply settings and restart link process. */
+               spin_lock_irqsave(&cp->lock, flags);
+               cas_begin_auto_negotiation(cp, &ecmd);
+               spin_unlock_irqrestore(&cp->lock, flags);
+               return 0;
+
+       case ETHTOOL_NWAY_RST:
+               if ((cp->link_cntl & BMCR_ANENABLE) == 0)
+                       return -EINVAL;
+
+               /* Restart link process. */
+               spin_lock_irqsave(&cp->lock, flags);
+               cas_begin_auto_negotiation(cp, NULL);
+               spin_unlock_irqrestore(&cp->lock, flags);
+
+               return 0;
+
+       case ETHTOOL_GWOL:
+       case ETHTOOL_SWOL:
+               break; /* doesn't exist */
+
+       /* get link status */
+       case ETHTOOL_GLINK: {
+               struct ethtool_value edata = { .cmd = ETHTOOL_GLINK };
+
+               edata.data = (cp->lstate == link_up);
+               if (copy_to_user(ep_user, &edata, sizeof(edata)))
+                       return -EFAULT;
+               return 0;
+       }
+
+       /* get message-level */
+       case ETHTOOL_GMSGLVL: {
+               struct ethtool_value edata = { .cmd = ETHTOOL_GMSGLVL };
+
+               edata.data = cp->msg_enable;
+               if (copy_to_user(ep_user, &edata, sizeof(edata)))
+                       return -EFAULT;
+               return 0;
+       }
+
+       /* set message-level */
+       case ETHTOOL_SMSGLVL: {
+               struct ethtool_value edata;
+
+               if (!capable(CAP_NET_ADMIN)) {
+                       return (-EPERM);
+               }
+               if (copy_from_user(&edata, ep_user, sizeof(edata)))
+                       return -EFAULT;
+               cp->msg_enable = edata.data;
+               return 0;
+       }
+
+       case ETHTOOL_GREGS: {
+               struct ethtool_regs edata;
+               u8 *ptr;
+               int len = cp->casreg_len < CAS_MAX_REGS ?
+                       cp->casreg_len: CAS_MAX_REGS;
+
+               if (copy_from_user(&edata, ep_user, sizeof (edata)))
+                       return -EFAULT;
+
+               if (edata.len > len)
+                       edata.len = len;
+               edata.version = 0;
+               if (copy_to_user (ep_user, &edata, sizeof(edata)))
+                       return -EFAULT;
+
+               /* cas_get_regs handles locks (cp->lock).  */
+               ptr = cas_get_regs(cp);
+               if (ptr == NULL)
+                       return -ENOMEM;
+               if (copy_to_user(ep_user + sizeof (edata), ptr, edata.len))
+                       return -EFAULT;
+
+               kfree(ptr);
+               return (0);
+       }
+       case ETHTOOL_GSTRINGS: {
+               struct ethtool_gstrings edata;
+               int len;
+
+               if (copy_from_user(&edata, ep_user, sizeof(edata)))
+                       return -EFAULT;
+
+               len = edata.len;
+               switch(edata.string_set) {
+               case ETH_SS_STATS:
+                       edata.len = (len < CAS_NUM_STAT_KEYS) ?
+                               len : CAS_NUM_STAT_KEYS;
+                       if (copy_to_user(ep_user, &edata, sizeof(edata)))
+                               return -EFAULT;
+
+                       if (copy_to_user(ep_user + sizeof(edata),
+                                        &ethtool_cassini_statnames, 
+                                        (edata.len * ETH_GSTRING_LEN)))
+                               return -EFAULT;
+                       return 0;
+               default:
+                       return -EINVAL;
+               }
+       }
+       case ETHTOOL_GSTATS: {
+               int i = 0;
+               u64 *tmp;
+               struct ethtool_stats edata;
+               struct net_device_stats *stats;
+               int len;
+
+               if (copy_from_user(&edata, ep_user, sizeof(edata)))
+                       return -EFAULT;
+
+               len = edata.n_stats;
+               stats = cas_get_stats(cp->dev);
+               edata.cmd = ETHTOOL_GSTATS;
+               edata.n_stats = (len < CAS_NUM_STAT_KEYS) ?
+                       len : CAS_NUM_STAT_KEYS;
+               if (copy_to_user(ep_user, &edata, sizeof (edata)))
+                       return -EFAULT;
+
+               tmp = kmalloc(sizeof(u64)*CAS_NUM_STAT_KEYS, GFP_KERNEL);
+               if (tmp) {
+                       tmp[i++] = stats->collisions;
+                       tmp[i++] = stats->rx_bytes;
+                       tmp[i++] = stats->rx_crc_errors;
+                       tmp[i++] = stats->rx_dropped;
+                       tmp[i++] = stats->rx_errors;
+                       tmp[i++] = stats->rx_fifo_errors;
+                       tmp[i++] = stats->rx_frame_errors;
+                       tmp[i++] = stats->rx_length_errors;
+                       tmp[i++] = stats->rx_over_errors;
+                       tmp[i++] = stats->rx_packets;
+                       tmp[i++] = stats->tx_aborted_errors;
+                       tmp[i++] = stats->tx_bytes;
+                       tmp[i++] = stats->tx_dropped;
+                       tmp[i++] = stats->tx_errors;
+                       tmp[i++] = stats->tx_fifo_errors;
+                       tmp[i++] = stats->tx_packets;
+                       BUG_ON(i != CAS_NUM_STAT_KEYS);
+
+                       i = copy_to_user(ep_user + sizeof(edata),
+                                        tmp, sizeof(u64)*edata.n_stats);
+                       kfree(tmp);
+               } else {
+                       return -ENOMEM;
+               }
+               if (i)
+                       return -EFAULT;
+               return 0;
+       }
+       }
+
+       return -EOPNOTSUPP;
+}
+
+static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+       struct cas *cp = netdev_priv(dev);
+       struct mii_ioctl_data *data = if_mii(ifr);
+       unsigned long flags;
+       int rc = -EOPNOTSUPP;
+       
+       /* Hold the PM semaphore while doing ioctl's or we may collide
+        * with open/close and power management and oops.
+        */
+       down(&cp->pm_sem);
+       switch (cmd) {
+       case SIOCETHTOOL:
+               rc = cas_ethtool_ioctl(dev, ifr->ifr_data);
+               break;
+
+       case SIOCGMIIPHY:               /* Get address of MII PHY in use. */
+               data->phy_id = cp->phy_addr;
+               /* Fallthrough... */
+
+       case SIOCGMIIREG:               /* Read MII PHY register. */
+               spin_lock_irqsave(&cp->lock, flags);
+               cas_mif_poll(cp, 0);
+               data->val_out = cas_phy_read(cp, data->reg_num & 0x1f);
+               cas_mif_poll(cp, 1);
+               spin_unlock_irqrestore(&cp->lock, flags);
+               rc = 0;
+               break;
+
+       case SIOCSMIIREG:               /* Write MII PHY register. */
+               if (!capable(CAP_NET_ADMIN)) {
+                       rc = -EPERM;
+                       break;
+               }
+               spin_lock_irqsave(&cp->lock, flags);
+               cas_mif_poll(cp, 0);
+               rc = cas_phy_write(cp, data->reg_num & 0x1f, data->val_in);
+               cas_mif_poll(cp, 1);
+               spin_unlock_irqrestore(&cp->lock, flags);
+               break;
+       default:
+               break;
+       };
+
+       up(&cp->pm_sem);
+       return rc;
+}
+
+static int __devinit cas_init_one(struct pci_dev *pdev,
+                                 const struct pci_device_id *ent)
+{
+       static int cas_version_printed = 0;
+       unsigned long casreg_base, casreg_len;
+       struct net_device *dev;
+       struct cas *cp;
+       int i, err, pci_using_dac;
+       u16 pci_cmd;
+       u8 orig_cacheline_size = 0, cas_cacheline_size = 0;
+
+       if (cas_version_printed++ == 0)
+               printk(KERN_INFO "%s", version);
+
+       err = pci_enable_device(pdev);
+       if (err) {
+               printk(KERN_ERR PFX "Cannot enable PCI device, "
+                      "aborting.\n");
+               return err;
+       }
+
+       if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+               printk(KERN_ERR PFX "Cannot find proper PCI device "
+                      "base address, aborting.\n");
+               err = -ENODEV;
+               goto err_out_disable_pdev;
+       }
+
+       dev = alloc_etherdev(sizeof(*cp));
+       if (!dev) {
+               printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+               err = -ENOMEM;
+               goto err_out_disable_pdev;
+       }
+       SET_MODULE_OWNER(dev);
+       SET_NETDEV_DEV(dev, &pdev->dev);
+
+       err = pci_request_regions(pdev, dev->name);
+       if (err) {
+               printk(KERN_ERR PFX "Cannot obtain PCI resources, "
+                      "aborting.\n");
+               goto err_out_free_netdev;
+       }
+       pci_set_master(pdev);
+
+       /* we must always turn on parity response or else parity
+        * doesn't get generated properly. disable SERR/PERR as well.
+        * in addition, we want to turn MWI on.
+        */
+       pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
+       pci_cmd &= ~PCI_COMMAND_SERR;
+       pci_cmd |= PCI_COMMAND_PARITY;
+       pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
+       pci_set_mwi(pdev);
+       /*
+        * On some architectures, the default cache line size set
+        * by pci_set_mwi reduces perforamnce.  We have to increase
+        * it for this case.  To start, we'll print some configuration
+        * data.
+        */
+#if 1
+       pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE,
+                            &orig_cacheline_size);
+       if (orig_cacheline_size < CAS_PREF_CACHELINE_SIZE) {
+               cas_cacheline_size = 
+                       (CAS_PREF_CACHELINE_SIZE < SMP_CACHE_BYTES) ? 
+                       CAS_PREF_CACHELINE_SIZE : SMP_CACHE_BYTES;
+               if (pci_write_config_byte(pdev, 
+                                         PCI_CACHE_LINE_SIZE, 
+                                         cas_cacheline_size)) {
+                       printk(KERN_ERR PFX "Could not set PCI cache "
+                              "line size\n");
+                       goto err_write_cacheline;
+               }
+       }
+#endif
+
+
+       /* Configure DMA attributes. */
+       if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+               pci_using_dac = 1;
+               err = pci_set_consistent_dma_mask(pdev,
+                                                 DMA_64BIT_MASK);
+               if (err < 0) {
+                       printk(KERN_ERR PFX "Unable to obtain 64-bit DMA "
+                              "for consistent allocations\n");
+                       goto err_out_free_res;
+               }
+
+       } else {
+               err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               if (err) {
+                       printk(KERN_ERR PFX "No usable DMA configuration, "
+                              "aborting.\n");
+                       goto err_out_free_res;
+               }
+               pci_using_dac = 0;
+       }
+
+       casreg_base = pci_resource_start(pdev, 0);
+       casreg_len = pci_resource_len(pdev, 0);
+
+       cp = netdev_priv(dev);
+       cp->pdev = pdev;
+#if 1
+       /* A value of 0 indicates we never explicitly set it */
+       cp->orig_cacheline_size = cas_cacheline_size ? orig_cacheline_size: 0;
+#endif
+       cp->dev = dev;
+       cp->msg_enable = (cassini_debug < 0) ? CAS_DEF_MSG_ENABLE : 
+         cassini_debug;
+
+       cp->link_transition = LINK_TRANSITION_UNKNOWN;
+       cp->link_transition_jiffies_valid = 0;
+
+       spin_lock_init(&cp->lock);
+       spin_lock_init(&cp->rx_inuse_lock);
+       spin_lock_init(&cp->rx_spare_lock);
+       for (i = 0; i < N_TX_RINGS; i++) {
+               spin_lock_init(&cp->stat_lock[i]);
+               spin_lock_init(&cp->tx_lock[i]);
+       }
+       spin_lock_init(&cp->stat_lock[N_TX_RINGS]);
+       init_MUTEX(&cp->pm_sem);
+
+       init_timer(&cp->link_timer);
+       cp->link_timer.function = cas_link_timer;
+       cp->link_timer.data = (unsigned long) cp;
+
+#if 1
+       /* Just in case the implementation of atomic operations
+        * change so that an explicit initialization is necessary.
+        */
+       atomic_set(&cp->reset_task_pending, 0);
+       atomic_set(&cp->reset_task_pending_all, 0);
+       atomic_set(&cp->reset_task_pending_spare, 0);
+       atomic_set(&cp->reset_task_pending_mtu, 0);
+#endif
+       INIT_WORK(&cp->reset_task, cas_reset_task, cp);
+
+       /* Default link parameters */
+       if (link_mode >= 0 && link_mode <= 6)
+               cp->link_cntl = link_modes[link_mode];
+       else
+               cp->link_cntl = BMCR_ANENABLE;
+       cp->lstate = link_down;
+       cp->link_transition = LINK_TRANSITION_LINK_DOWN;
+       netif_carrier_off(cp->dev);
+       cp->timer_ticks = 0;
+
+       /* give us access to cassini registers */
+       cp->regs = ioremap(casreg_base, casreg_len);
+       if (cp->regs == 0UL) {
+               printk(KERN_ERR PFX "Cannot map device registers, "
+                      "aborting.\n");
+               goto err_out_free_res;
+       }
+       cp->casreg_len = casreg_len;
+
+       pci_save_state(pdev);
+       cas_check_pci_invariants(cp);
+       cas_hard_reset(cp);
+       cas_reset(cp, 0);
+       if (cas_check_invariants(cp))
+               goto err_out_iounmap;
+
+       cp->init_block = (struct cas_init_block *)
+               pci_alloc_consistent(pdev, sizeof(struct cas_init_block),
+                                    &cp->block_dvma);
+       if (!cp->init_block) {
+               printk(KERN_ERR PFX "Cannot allocate init block, "
+                      "aborting.\n");
+               goto err_out_iounmap;
+       }
+
+       for (i = 0; i < N_TX_RINGS; i++) 
+               cp->init_txds[i] = cp->init_block->txds[i];
+
+       for (i = 0; i < N_RX_DESC_RINGS; i++) 
+               cp->init_rxds[i] = cp->init_block->rxds[i];
+
+       for (i = 0; i < N_RX_COMP_RINGS; i++) 
+               cp->init_rxcs[i] = cp->init_block->rxcs[i];
+
+       for (i = 0; i < N_RX_FLOWS; i++)
+               skb_queue_head_init(&cp->rx_flows[i]);
+
+       dev->open = cas_open;
+       dev->stop = cas_close;
+       dev->hard_start_xmit = cas_start_xmit;
+       dev->get_stats = cas_get_stats;
+       dev->set_multicast_list = cas_set_multicast;
+       dev->do_ioctl = cas_ioctl;
+       dev->tx_timeout = cas_tx_timeout;
+       dev->watchdog_timeo = CAS_TX_TIMEOUT;
+       dev->change_mtu = cas_change_mtu;
+#ifdef USE_NAPI
+       dev->poll = cas_poll;
+       dev->weight = 64;
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller = cas_netpoll;
+#endif
+       dev->irq = pdev->irq;
+       dev->dma = 0;
+
+       /* Cassini features. */
+       if ((cp->cas_flags & CAS_FLAG_NO_HW_CSUM) == 0)
+               dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+
+       if (pci_using_dac)
+               dev->features |= NETIF_F_HIGHDMA;
+
+       if (register_netdev(dev)) {
+               printk(KERN_ERR PFX "Cannot register net device, "
+                      "aborting.\n");
+               goto err_out_free_consistent;
+       }
+
+       i = readl(cp->regs + REG_BIM_CFG);
+       printk(KERN_INFO "%s: Sun Cassini%s (%sbit/%sMHz PCI/%s) "
+              "Ethernet[%d] ",  dev->name, 
+              (cp->cas_flags & CAS_FLAG_REG_PLUS) ? "+" : "", 
+              (i & BIM_CFG_32BIT) ? "32" : "64",
+              (i & BIM_CFG_66MHZ) ? "66" : "33",
+              (cp->phy_type == CAS_PHY_SERDES) ? "Fi" : "Cu", pdev->irq); 
+
+       for (i = 0; i < 6; i++)
+               printk("%2.2x%c", dev->dev_addr[i],
+                      i == 5 ? ' ' : ':');
+       printk("\n");
+
+       pci_set_drvdata(pdev, dev);
+       cp->hw_running = 1;
+       cas_entropy_reset(cp);
+       cas_phy_init(cp);
+       cas_begin_auto_negotiation(cp, NULL);
+       return 0;
+
+err_out_free_consistent:
+       pci_free_consistent(pdev, sizeof(struct cas_init_block),
+                           cp->init_block, cp->block_dvma);
+
+err_out_iounmap:
+       down(&cp->pm_sem);
+       if (cp->hw_running)
+               cas_shutdown(cp);
+       up(&cp->pm_sem);
+
+       iounmap(cp->regs);
+
+
+err_out_free_res:
+       pci_release_regions(pdev);
+
+err_write_cacheline:
+       /* Try to restore it in case the error occured after we
+        * set it. 
+        */
+       pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, orig_cacheline_size);
+
+err_out_free_netdev:
+       free_netdev(dev);
+
+err_out_disable_pdev:
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+       return -ENODEV;
+}
+
+static void __devexit cas_remove_one(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct cas *cp;
+       if (!dev)
+               return;
+
+       cp = netdev_priv(dev);
+       unregister_netdev(dev);
+
+       down(&cp->pm_sem);
+       flush_scheduled_work();
+       if (cp->hw_running)
+               cas_shutdown(cp);
+       up(&cp->pm_sem);
+
+#if 1
+       if (cp->orig_cacheline_size) {
+               /* Restore the cache line size if we had modified
+                * it.
+                */
+               pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 
+                                     cp->orig_cacheline_size);
+       }
+#endif
+       pci_free_consistent(pdev, sizeof(struct cas_init_block),
+                           cp->init_block, cp->block_dvma);
+       iounmap(cp->regs);
+       free_netdev(dev);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int cas_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct cas *cp = netdev_priv(dev);
+       unsigned long flags;
+
+       /* We hold the PM semaphore during entire driver
+        * sleep time
+        */
+       down(&cp->pm_sem);
+       
+       /* If the driver is opened, we stop the DMA */
+       if (cp->opened) {
+               netif_device_detach(dev);
+
+               cas_lock_all_save(cp, flags);
+
+               /* We can set the second arg of cas_reset to 0
+                * because on resume, we'll call cas_init_hw with
+                * its second arg set so that autonegotiation is
+                * restarted.
+                */
+               cas_reset(cp, 0);
+               cas_clean_rings(cp);
+               cas_unlock_all_restore(cp, flags);
+       }
+
+       if (cp->hw_running)
+               cas_shutdown(cp);
+
+       return 0;
+}
+
+static int cas_resume(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+       struct cas *cp = netdev_priv(dev);
+
+       printk(KERN_INFO "%s: resuming\n", dev->name);
+
+       cas_hard_reset(cp);
+       if (cp->opened) {
+               unsigned long flags;
+               cas_lock_all_save(cp, flags);
+               cas_reset(cp, 0);
+               cp->hw_running = 1;
+               cas_clean_rings(cp);
+               cas_init_hw(cp, 1);
+               cas_unlock_all_restore(cp, flags);
+
+               netif_device_attach(dev);
+       }
+       up(&cp->pm_sem);
+       return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct pci_driver cas_driver = {
+       .name           = DRV_MODULE_NAME,
+       .id_table       = cas_pci_tbl,
+       .probe          = cas_init_one,
+       .remove         = __devexit_p(cas_remove_one),
+#ifdef CONFIG_PM
+       .suspend        = cas_suspend,
+       .resume         = cas_resume
+#endif
+};
+
+static int __init cas_init(void)
+{
+       if (linkdown_timeout > 0)
+               link_transition_timeout = linkdown_timeout * HZ;
+       else
+               link_transition_timeout = 0;
+
+       return pci_module_init(&cas_driver);
+}
+
+static void __exit cas_cleanup(void)
+{
+       pci_unregister_driver(&cas_driver);
+}
+
+module_init(cas_init);
+module_exit(cas_cleanup);
diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h
new file mode 100644 (file)
index 0000000..88063ef
--- /dev/null
@@ -0,0 +1,4425 @@
+/* $Id: cassini.h,v 1.16 2004/08/17 21:15:16 zaumen Exp $
+ * cassini.h: Definitions for Sun Microsystems Cassini(+) ethernet driver.
+ *
+ * Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (c) 2003 Adrian Sun (asun@darksunrising.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * vendor id: 0x108E (Sun Microsystems, Inc.)
+ * device id: 0xabba (Cassini)
+ * revision ids: 0x01 = Cassini 
+ *               0x02 = Cassini rev 2
+ *               0x10 = Cassini+
+ *               0x11 = Cassini+ 0.2u
+ *
+ * vendor id: 0x100b (National Semiconductor)
+ * device id: 0x0035 (DP83065/Saturn)
+ * revision ids: 0x30 = Saturn B2
+ *
+ * rings are all offset from 0.
+ *
+ * there are two clock domains:
+ * PCI:  33/66MHz clock
+ * chip: 125MHz clock
+ */
+
+#ifndef _CASSINI_H
+#define _CASSINI_H
+
+/* cassini register map: 2M memory mapped in 32-bit memory space accessible as
+ * 32-bit words. there is no i/o port access. REG_ addresses are
+ * shared between cassini and cassini+. REG_PLUS_ addresses only
+ * appear in cassini+. REG_MINUS_ addresses only appear in cassini.
+ */
+#define CAS_ID_REV2          0x02
+#define CAS_ID_REVPLUS       0x10 
+#define CAS_ID_REVPLUS02u    0x11 
+#define CAS_ID_REVSATURNB2   0x30
+
+/** global resources **/
+
+/* this register sets the weights for the weighted round robin arbiter. e.g.,
+ * if rx weight == 1 and tx weight == 0, rx == 2x tx transfer credit
+ * for its next turn to access the pci bus. 
+ * map: 0x0 = x1, 0x1 = x2, 0x2 = x4, 0x3 = x8 
+ * DEFAULT: 0x0, SIZE: 5 bits
+ */
+#define  REG_CAWR                     0x0004  /* core arbitration weight */
+#define    CAWR_RX_DMA_WEIGHT_SHIFT    0
+#define    CAWR_RX_DMA_WEIGHT_MASK     0x03    /* [0:1] */
+#define    CAWR_TX_DMA_WEIGHT_SHIFT    2
+#define    CAWR_TX_DMA_WEIGHT_MASK     0x0C    /* [3:2] */
+#define    CAWR_RR_DIS                 0x10    /* [4] */
+
+/* if enabled, BIM can send bursts across PCI bus > cacheline size. burst
+ * sizes determined by length of packet or descriptor transfer and the 
+ * max length allowed by the target. 
+ * DEFAULT: 0x0, SIZE: 1 bit
+ */
+#define  REG_INF_BURST                 0x0008  /* infinite burst enable reg */
+#define    INF_BURST_EN                0x1     /* enable */
+
+/* top level interrupts [0-9] are auto-cleared to 0 when the status
+ * register is read. second level interrupts [13 - 18] are cleared at
+ * the source. tx completion register 3 is replicated in [19 - 31] 
+ * DEFAULT: 0x00000000, SIZE: 29 bits
+ */
+#define  REG_INTR_STATUS               0x000C  /* interrupt status register */
+#define    INTR_TX_INTME               0x00000001  /* frame w/ INT ME desc bit set 
+                                                     xferred from host queue to
+                                                     TX FIFO */
+#define    INTR_TX_ALL                 0x00000002  /* all xmit frames xferred into
+                                                     TX FIFO. i.e.,
+                                                     TX Kick == TX complete. if 
+                                                     PACED_MODE set, then TX FIFO
+                                                     also empty */
+#define    INTR_TX_DONE                0x00000004  /* any frame xferred into tx 
+                                                     FIFO */
+#define    INTR_TX_TAG_ERROR           0x00000008  /* TX FIFO tag framing 
+                                                     corrupted. FATAL ERROR */
+#define    INTR_RX_DONE                0x00000010  /* at least 1 frame xferred
+                                                     from RX FIFO to host mem.
+                                                     RX completion reg updated.
+                                                     may be delayed by recv
+                                                     intr blanking. */
+#define    INTR_RX_BUF_UNAVAIL         0x00000020  /* no more receive buffers.
+                                                     RX Kick == RX complete */
+#define    INTR_RX_TAG_ERROR           0x00000040  /* RX FIFO tag framing 
+                                                     corrupted. FATAL ERROR */
+#define    INTR_RX_COMP_FULL           0x00000080  /* no more room in completion
+                                                     ring to post descriptors.
+                                                     RX complete head incr to
+                                                     almost reach RX complete
+                                                     tail */
+#define    INTR_RX_BUF_AE              0x00000100  /* less than the 
+                                                     programmable threshold #
+                                                     of free descr avail for
+                                                     hw use */
+#define    INTR_RX_COMP_AF             0x00000200  /* less than the 
+                                                     programmable threshold #
+                                                     of descr spaces for hw
+                                                     use in completion descr
+                                                     ring */
+#define    INTR_RX_LEN_MISMATCH        0x00000400  /* len field from MAC !=
+                                                     len of non-reassembly pkt
+                                                     from fifo during DMA or
+                                                     header parser provides TCP
+                                                     header and payload size >
+                                                     MAC packet size. 
+                                                     FATAL ERROR */
+#define    INTR_SUMMARY                0x00001000  /* summary interrupt bit. this
+                                                     bit will be set if an interrupt 
+                                                     generated on the pci bus. useful
+                                                     when driver is polling for 
+                                                     interrupts */
+#define    INTR_PCS_STATUS             0x00002000  /* PCS interrupt status register */
+#define    INTR_TX_MAC_STATUS          0x00004000  /* TX MAC status register has at 
+                                                     least 1 unmasked interrupt set */
+#define    INTR_RX_MAC_STATUS          0x00008000  /* RX MAC status register has at 
+                                                     least 1 unmasked interrupt set */
+#define    INTR_MAC_CTRL_STATUS        0x00010000  /* MAC control status register has
+                                                     at least 1 unmasked interrupt
+                                                     set */
+#define    INTR_MIF_STATUS             0x00020000  /* MIF status register has at least
+                                                     1 unmasked interrupt set */
+#define    INTR_PCI_ERROR_STATUS       0x00040000  /* PCI error status register in the
+                                                     BIF has at least 1 unmasked 
+                                                     interrupt set */
+#define    INTR_TX_COMP_3_MASK         0xFFF80000  /* mask for TX completion 
+                                                     3 reg data */
+#define    INTR_TX_COMP_3_SHIFT        19
+#define    INTR_ERROR_MASK (INTR_MIF_STATUS | INTR_PCI_ERROR_STATUS | \
+                            INTR_PCS_STATUS | INTR_RX_LEN_MISMATCH | \
+                            INTR_TX_MAC_STATUS | INTR_RX_MAC_STATUS | \
+                            INTR_TX_TAG_ERROR | INTR_RX_TAG_ERROR | \
+                            INTR_MAC_CTRL_STATUS)
+
+/* determines which status events will cause an interrupt. layout same
+ * as REG_INTR_STATUS. 
+ * DEFAULT: 0xFFFFFFFF, SIZE: 16 bits
+ */
+#define  REG_INTR_MASK                 0x0010  /* Interrupt mask */
+
+/* top level interrupt bits that are cleared during read of REG_INTR_STATUS_ALIAS.
+ * useful when driver is polling for interrupts. layout same as REG_INTR_MASK.
+ * DEFAULT: 0x00000000, SIZE: 12 bits
+ */
+#define  REG_ALIAS_CLEAR               0x0014  /* alias clear mask 
+                                                 (used w/ status alias) */
+/* same as REG_INTR_STATUS except that only bits cleared are those selected by
+ * REG_ALIAS_CLEAR 
+ * DEFAULT: 0x00000000, SIZE: 29 bits
+ */
+#define  REG_INTR_STATUS_ALIAS         0x001C  /* interrupt status alias 
+                                                 (selective clear) */
+
+/* DEFAULT: 0x0, SIZE: 3 bits */
+#define  REG_PCI_ERR_STATUS            0x1000  /* PCI error status */
+#define    PCI_ERR_BADACK              0x01    /* reserved in Cassini+. 
+                                                 set if no ACK64# during ABS64 cycle
+                                                 in Cassini. */
+#define    PCI_ERR_DTRTO               0x02    /* delayed xaction timeout. set if
+                                                 no read retry after 2^15 clocks */
+#define    PCI_ERR_OTHER               0x04    /* other PCI errors */
+#define    PCI_ERR_BIM_DMA_WRITE       0x08    /* BIM received 0 count DMA write req.
+                                                 unused in Cassini. */
+#define    PCI_ERR_BIM_DMA_READ        0x10    /* BIM received 0 count DMA read req.
+                                                 unused in Cassini. */
+#define    PCI_ERR_BIM_DMA_TIMEOUT     0x20    /* BIM received 255 retries during 
+                                                 DMA. unused in cassini. */
+
+/* mask for PCI status events that will set PCI_ERR_STATUS. if cleared, event
+ * causes an interrupt to be generated. 
+ * DEFAULT: 0x7, SIZE: 3 bits
+ */
+#define  REG_PCI_ERR_STATUS_MASK       0x1004  /* PCI Error status mask */
+
+/* used to configure PCI related parameters that are not in PCI config space. 
+ * DEFAULT: 0bxx000, SIZE: 5 bits
+ */
+#define  REG_BIM_CFG                0x1008  /* BIM Configuration */
+#define    BIM_CFG_RESERVED0        0x001   /* reserved */
+#define    BIM_CFG_RESERVED1        0x002   /* reserved */
+#define    BIM_CFG_64BIT_DISABLE    0x004   /* disable 64-bit mode */
+#define    BIM_CFG_66MHZ            0x008   /* (ro) 1 = 66MHz, 0 = < 66MHz */
+#define    BIM_CFG_32BIT            0x010   /* (ro) 1 = 32-bit slot, 0 = 64-bit */
+#define    BIM_CFG_DPAR_INTR_ENABLE 0x020   /* detected parity err enable */
+#define    BIM_CFG_RMA_INTR_ENABLE  0x040   /* master abort intr enable */
+#define    BIM_CFG_RTA_INTR_ENABLE  0x080   /* target abort intr enable */
+#define    BIM_CFG_RESERVED2        0x100   /* reserved */
+#define    BIM_CFG_BIM_DISABLE      0x200   /* stop BIM DMA. use before global 
+                                              reset. reserved in Cassini. */
+#define    BIM_CFG_BIM_STATUS       0x400   /* (ro) 1 = BIM DMA suspended.
+                                                 reserved in Cassini. */
+#define    BIM_CFG_PERROR_BLOCK     0x800  /* block PERR# to pci bus. def: 0.
+                                                reserved in Cassini. */
+
+/* DEFAULT: 0x00000000, SIZE: 32 bits */
+#define  REG_BIM_DIAG                  0x100C  /* BIM Diagnostic */
+#define    BIM_DIAG_MSTR_SM_MASK       0x3FFFFF00 /* PCI master controller state
+                                                    machine bits [21:0] */
+#define    BIM_DIAG_BRST_SM_MASK       0x7F    /* PCI burst controller state 
+                                                 machine bits [6:0] */
+
+/* writing to SW_RESET_TX and SW_RESET_RX will issue a global
+ * reset. poll until TX and RX read back as 0's for completion.
+ */
+#define  REG_SW_RESET                  0x1010  /* Software reset */
+#define    SW_RESET_TX                 0x00000001  /* reset TX DMA engine. poll until
+                                                     cleared to 0.  */
+#define    SW_RESET_RX                 0x00000002  /* reset RX DMA engine. poll until
+                                                     cleared to 0. */
+#define    SW_RESET_RSTOUT             0x00000004  /* force RSTOUT# pin active (low).
+                                                     resets PHY and anything else 
+                                                     connected to RSTOUT#. RSTOUT#
+                                                     is also activated by local PCI
+                                                     reset when hot-swap is being 
+                                                     done. */
+#define    SW_RESET_BLOCK_PCS_SLINK    0x00000008  /* if a global reset is done with 
+                                                     this bit set, PCS and SLINK 
+                                                     modules won't be reset. 
+                                                     i.e., link won't drop. */
+#define    SW_RESET_BREQ_SM_MASK       0x00007F00  /* breq state machine [6:0] */
+#define    SW_RESET_PCIARB_SM_MASK     0x00070000  /* pci arbitration state bits:
+                                                     0b000: ARB_IDLE1
+                                                     0b001: ARB_IDLE2
+                                                     0b010: ARB_WB_ACK
+                                                     0b011: ARB_WB_WAT
+                                                     0b100: ARB_RB_ACK
+                                                     0b101: ARB_RB_WAT
+                                                     0b110: ARB_RB_END
+                                                     0b111: ARB_WB_END */
+#define    SW_RESET_RDPCI_SM_MASK      0x00300000  /* read pci state bits:
+                                                     0b00: RD_PCI_WAT
+                                                     0b01: RD_PCI_RDY
+                                                     0b11: RD_PCI_ACK */
+#define    SW_RESET_RDARB_SM_MASK      0x00C00000  /* read arbitration state bits:
+                                                     0b00: AD_IDL_RX
+                                                     0b01: AD_ACK_RX
+                                                     0b10: AD_ACK_TX
+                                                     0b11: AD_IDL_TX */
+#define    SW_RESET_WRPCI_SM_MASK      0x06000000  /* write pci state bits 
+                                                     0b00: WR_PCI_WAT
+                                                     0b01: WR_PCI_RDY
+                                                     0b11: WR_PCI_ACK */
+#define    SW_RESET_WRARB_SM_MASK      0x38000000  /* write arbitration state bits:
+                                                     0b000: ARB_IDLE1
+                                                     0b001: ARB_IDLE2
+                                                     0b010: ARB_TX_ACK
+                                                     0b011: ARB_TX_WAT
+                                                     0b100: ARB_RX_ACK
+                                                     0b110: ARB_RX_WAT */
+
+/* Cassini only. 64-bit register used to check PCI datapath. when read,
+ * value written has both lower and upper 32-bit halves rotated to the right
+ * one bit position. e.g., FFFFFFFF FFFFFFFF -> 7FFFFFFF 7FFFFFFF
+ */
+#define  REG_MINUS_BIM_DATAPATH_TEST   0x1018  /* Cassini: BIM datapath test 
+                                                 Cassini+: reserved */
+
+/* output enables are provided for each device's chip select and for the rest
+ * of the outputs from cassini to its local bus devices. two sw programmable
+ * bits are connected to general purpus control/status bits.
+ * DEFAULT: 0x7
+ */
+#define  REG_BIM_LOCAL_DEV_EN          0x1020  /* BIM local device 
+                                                 output EN. default: 0x7 */
+#define    BIM_LOCAL_DEV_PAD           0x01    /* address bus, RW signal, and
+                                                 OE signal output enable on the
+                                                 local bus interface. these
+                                                 are shared between both local 
+                                                 bus devices. tristate when 0. */
+#define    BIM_LOCAL_DEV_PROM          0x02    /* PROM chip select */
+#define    BIM_LOCAL_DEV_EXT           0x04    /* secondary local bus device chip
+                                                 select output enable */
+#define    BIM_LOCAL_DEV_SOFT_0        0x08    /* sw programmable ctrl bit 0 */
+#define    BIM_LOCAL_DEV_SOFT_1        0x10    /* sw programmable ctrl bit 1 */
+#define    BIM_LOCAL_DEV_HW_RESET      0x20    /* internal hw reset. Cassini+ only. */
+
+/* access 24 entry BIM read and write buffers. put address in REG_BIM_BUFFER_ADDR
+ * and read/write from/to it REG_BIM_BUFFER_DATA_LOW and _DATA_HI. 
+ * _DATA_HI should be the last access of the sequence. 
+ * DEFAULT: undefined
+ */
+#define  REG_BIM_BUFFER_ADDR           0x1024  /* BIM buffer address. for
+                                                 purposes. */
+#define    BIM_BUFFER_ADDR_MASK        0x3F    /* index (0 - 23) of buffer  */
+#define    BIM_BUFFER_WR_SELECT        0x40    /* write buffer access = 1
+                                                 read buffer access = 0 */
+/* DEFAULT: undefined */
+#define  REG_BIM_BUFFER_DATA_LOW       0x1028  /* BIM buffer data low */
+#define  REG_BIM_BUFFER_DATA_HI        0x102C  /* BIM buffer data high */
+
+/* set BIM_RAM_BIST_START to start built-in self test for BIM read buffer. 
+ * bit auto-clears when done with status read from _SUMMARY and _PASS bits.
+ */
+#define  REG_BIM_RAM_BIST              0x102C  /* BIM RAM (read buffer) BIST 
+                                                 control/status */
+#define    BIM_RAM_BIST_RD_START       0x01    /* start BIST for BIM read buffer */
+#define    BIM_RAM_BIST_WR_START       0x02    /* start BIST for BIM write buffer.
+                                                 Cassini only. reserved in
+                                                 Cassini+. */
+#define    BIM_RAM_BIST_RD_PASS        0x04    /* summary BIST pass status for read
+                                                 buffer. */
+#define    BIM_RAM_BIST_WR_PASS        0x08    /* summary BIST pass status for write
+                                                 buffer. Cassini only. reserved
+                                                 in Cassini+. */
+#define    BIM_RAM_BIST_RD_LOW_PASS    0x10    /* read low bank passes BIST */
+#define    BIM_RAM_BIST_RD_HI_PASS     0x20    /* read high bank passes BIST */
+#define    BIM_RAM_BIST_WR_LOW_PASS    0x40    /* write low bank passes BIST.
+                                                 Cassini only. reserved in 
+                                                 Cassini+. */
+#define    BIM_RAM_BIST_WR_HI_PASS     0x80    /* write high bank passes BIST.
+                                                 Cassini only. reserved in
+                                                 Cassini+. */
+
+/* ASUN: i'm not sure what this does as it's not in the spec.
+ * DEFAULT: 0xFC
+ */
+#define  REG_BIM_DIAG_MUX              0x1030  /* BIM diagnostic probe mux
+                                                 select register */
+
+/* enable probe monitoring mode and select data appearing on the P_A* bus. bit 
+ * values for _SEL_HI_MASK and _SEL_LOW_MASK:
+ * 0x0: internal probe[7:0] (pci arb state, wtc empty w, wtc full w, wtc empty w,
+ *                           wtc empty r, post pci)
+ * 0x1: internal probe[15:8] (pci wbuf comp, pci wpkt comp, pci rbuf comp,
+ *                            pci rpkt comp, txdma wr req, txdma wr ack,
+ *                           txdma wr rdy, txdma wr xfr done)
+ * 0x2: internal probe[23:16] (txdma rd req, txdma rd ack, txdma rd rdy, rxdma rd,
+ *                             rd arb state, rd pci state)
+ * 0x3: internal probe[31:24] (rxdma req, rxdma ack, rxdma rdy, wrarb state,
+ *                             wrpci state)
+ * 0x4: pci io probe[7:0]     0x5: pci io probe[15:8]
+ * 0x6: pci io probe[23:16]   0x7: pci io probe[31:24]
+ * 0x8: pci io probe[39:32]   0x9: pci io probe[47:40]
+ * 0xa: pci io probe[55:48]   0xb: pci io probe[63:56]
+ * the following are not available in Cassini:
+ * 0xc: rx probe[7:0]         0xd: tx probe[7:0]
+ * 0xe: hp probe[7:0]        0xf: mac probe[7:0]
+ */
+#define  REG_PLUS_PROBE_MUX_SELECT     0x1034 /* Cassini+: PROBE MUX SELECT */
+#define    PROBE_MUX_EN                0x80000000 /* allow probe signals to be 
+                                                    driven on local bus P_A[15:0]
+                                                    for debugging */
+#define    PROBE_MUX_SUB_MUX_MASK      0x0000FF00 /* select sub module probe signals:
+                                                    0x03 = mac[1:0]
+                                                    0x0C = rx[1:0]
+                                                    0x30 = tx[1:0]
+                                                    0xC0 = hp[1:0] */
+#define    PROBE_MUX_SEL_HI_MASK       0x000000F0 /* select which module to appear
+                                                    on P_A[15:8]. see above for 
+                                                    values. */
+#define    PROBE_MUX_SEL_LOW_MASK      0x0000000F /* select which module to appear
+                                                    on P_A[7:0]. see above for 
+                                                    values. */
+
+/* values mean the same thing as REG_INTR_MASK excep that it's for INTB. 
+ DEFAULT: 0x1F */
+#define  REG_PLUS_INTR_MASK_1          0x1038 /* Cassini+: interrupt mask
+                                                register 2 for INTB */
+#define  REG_PLUS_INTRN_MASK(x)       (REG_PLUS_INTR_MASK_1 + ((x) - 1)*16)
+/* bits correspond to both _MASK and _STATUS registers. _ALT corresponds to 
+ * all of the alternate (2-4) INTR registers while _1 corresponds to only 
+ * _MASK_1 and _STATUS_1 registers. 
+ * DEFAULT: 0x7 for MASK registers, 0x0 for ALIAS_CLEAR registers
+ */
+#define    INTR_RX_DONE_ALT              0x01  
+#define    INTR_RX_COMP_FULL_ALT         0x02
+#define    INTR_RX_COMP_AF_ALT           0x04
+#define    INTR_RX_BUF_UNAVAIL_1         0x08
+#define    INTR_RX_BUF_AE_1              0x10 /* almost empty */
+#define    INTRN_MASK_RX_EN              0x80     
+#define    INTRN_MASK_CLEAR_ALL          (INTR_RX_DONE_ALT | \
+                                          INTR_RX_COMP_FULL_ALT | \
+                                          INTR_RX_COMP_AF_ALT | \
+                                          INTR_RX_BUF_UNAVAIL_1 | \
+                                          INTR_RX_BUF_AE_1)
+#define  REG_PLUS_INTR_STATUS_1        0x103C /* Cassini+: interrupt status
+                                                register 2 for INTB. default: 0x1F */
+#define  REG_PLUS_INTRN_STATUS(x)       (REG_PLUS_INTR_STATUS_1 + ((x) - 1)*16)
+#define    INTR_STATUS_ALT_INTX_EN     0x80   /* generate INTX when one of the
+                                                flags are set. enables desc ring. */
+
+#define  REG_PLUS_ALIAS_CLEAR_1        0x1040 /* Cassini+: alias clear mask
+                                                register 2 for INTB */
+#define  REG_PLUS_ALIASN_CLEAR(x)      (REG_PLUS_ALIAS_CLEAR_1 + ((x) - 1)*16)
+
+#define  REG_PLUS_INTR_STATUS_ALIAS_1  0x1044 /* Cassini+: interrupt status 
+                                                register alias 2 for INTB */
+#define  REG_PLUS_INTRN_STATUS_ALIAS(x) (REG_PLUS_INTR_STATUS_ALIAS_1 + ((x) - 1)*16)
+
+#define REG_SATURN_PCFG               0x106c /* pin configuration register for
+                                               integrated macphy */
+
+#define   SATURN_PCFG_TLA             0x00000001 /* 1 = phy actled */
+#define   SATURN_PCFG_FLA             0x00000002 /* 1 = phy link10led */
+#define   SATURN_PCFG_CLA             0x00000004 /* 1 = phy link100led */
+#define   SATURN_PCFG_LLA             0x00000008 /* 1 = phy link1000led */
+#define   SATURN_PCFG_RLA             0x00000010 /* 1 = phy duplexled */
+#define   SATURN_PCFG_PDS             0x00000020 /* phy debug mode. 
+                                                   0 = normal */
+#define   SATURN_PCFG_MTP             0x00000080 /* test point select */ 
+#define   SATURN_PCFG_GMO             0x00000100 /* GMII observe. 1 = 
+                                                   GMII on SERDES pins for
+                                                   monitoring. */
+#define   SATURN_PCFG_FSI             0x00000200 /* 1 = freeze serdes/gmii. all
+                                                   pins configed as outputs.
+                                                   for power saving when using
+                                                   internal phy. */
+#define   SATURN_PCFG_LAD             0x00000800 /* 0 = mac core led ctrl 
+                                                   polarity from strapping 
+                                                   value.
+                                                   1 = mac core led ctrl
+                                                   polarity active low. */
+
+
+/** transmit dma registers **/
+#define MAX_TX_RINGS_SHIFT            2
+#define MAX_TX_RINGS                  (1 << MAX_TX_RINGS_SHIFT)
+#define MAX_TX_RINGS_MASK             (MAX_TX_RINGS - 1)
+
+/* TX configuration. 
+ * descr ring sizes size = 32 * (1 << n), n < 9. e.g., 0x8 = 8k. default: 0x8 
+ * DEFAULT: 0x3F000001
+ */
+#define  REG_TX_CFG                    0x2004  /* TX config */
+#define    TX_CFG_DMA_EN               0x00000001  /* enable TX DMA. if cleared, DMA
+                                                     will stop after xfer of current
+                                                     buffer has been completed. */
+#define    TX_CFG_FIFO_PIO_SEL         0x00000002  /* TX DMA FIFO can be 
+                                                     accessed w/ FIFO addr 
+                                                     and data registers. 
+                                                     TX DMA should be 
+                                                     disabled. */
+#define    TX_CFG_DESC_RING0_MASK      0x0000003C  /* # desc entries in
+                                                     ring 1. */
+#define    TX_CFG_DESC_RING0_SHIFT     2
+#define    TX_CFG_DESC_RINGN_MASK(a)   (TX_CFG_DESC_RING0_MASK << (a)*4)
+#define    TX_CFG_DESC_RINGN_SHIFT(a)  (TX_CFG_DESC_RING0_SHIFT + (a)*4)
+#define    TX_CFG_PACED_MODE           0x00100000  /* TX_ALL only set after 
+                                                     TX FIFO becomes empty. 
+                                                     if 0, TX_ALL set
+                                                     if descr queue empty. */
+#define    TX_CFG_DMA_RDPIPE_DIS       0x01000000  /* always set to 1 */
+#define    TX_CFG_COMPWB_Q1            0x02000000  /* completion writeback happens at
+                                                     the end of every packet kicked
+                                                     through Q1. */
+#define    TX_CFG_COMPWB_Q2            0x04000000  /* completion writeback happens at
+                                                     the end of every packet kicked
+                                                     through Q2. */
+#define    TX_CFG_COMPWB_Q3            0x08000000  /* completion writeback happens at
+                                                     the end of every packet kicked
+                                                     through Q3 */
+#define    TX_CFG_COMPWB_Q4            0x10000000  /* completion writeback happens at
+                                                     the end of every packet kicked
+                                                     through Q4 */
+#define    TX_CFG_INTR_COMPWB_DIS      0x20000000  /* disable pre-interrupt completion
+                                                     writeback */
+#define    TX_CFG_CTX_SEL_MASK         0xC0000000  /* selects tx test port 
+                                                     connection
+                                                     0b00: tx mac req, 
+                                                           tx mac retry req,
+                                                           tx ack and tx tag.
+                                                     0b01: txdma rd req, 
+                                                           txdma rd ack,
+                                                           txdma rd rdy,
+                                                           txdma rd type0
+                                                     0b11: txdma wr req, 
+                                                           txdma wr ack,
+                                                           txdma wr rdy,
+                                                           txdma wr xfr done. */
+#define    TX_CFG_CTX_SEL_SHIFT        30
+                                                     
+/* 11-bit counters that point to next location in FIFO to be loaded/retrieved.
+ * used for diagnostics only.
+ */
+#define  REG_TX_FIFO_WRITE_PTR         0x2014  /* TX FIFO write pointer */
+#define  REG_TX_FIFO_SHADOW_WRITE_PTR  0x2018  /* TX FIFO shadow write 
+                                                 pointer. temp hold reg.
+                                                 diagnostics only. */
+#define  REG_TX_FIFO_READ_PTR          0x201C  /* TX FIFO read pointer */
+#define  REG_TX_FIFO_SHADOW_READ_PTR   0x2020  /* TX FIFO shadow read
+                                                 pointer */
+
+/* (ro) 11-bit up/down counter w/ # of frames currently in TX FIFO */
+#define  REG_TX_FIFO_PKT_CNT           0x2024  /* TX FIFO packet counter */
+
+/* current state of all state machines in TX */
+#define  REG_TX_SM_1                   0x2028  /* TX state machine reg #1 */
+#define    TX_SM_1_CHAIN_MASK          0x000003FF   /* chaining state machine */
+#define    TX_SM_1_CSUM_MASK           0x00000C00   /* checksum state machine */
+#define    TX_SM_1_FIFO_LOAD_MASK      0x0003F000   /* FIFO load state machine.
+                                                      = 0x01 when TX disabled. */
+#define    TX_SM_1_FIFO_UNLOAD_MASK    0x003C0000   /* FIFO unload state machine */
+#define    TX_SM_1_CACHE_MASK          0x03C00000   /* desc. prefetch cache controller
+                                                      state machine */
+#define    TX_SM_1_CBQ_ARB_MASK        0xF8000000   /* CBQ arbiter state machine */
+                                                        
+#define  REG_TX_SM_2                   0x202C  /* TX state machine reg #2 */
+#define    TX_SM_2_COMP_WB_MASK        0x07    /* completion writeback sm */
+#define           TX_SM_2_SUB_LOAD_MASK       0x38    /* sub load state machine */
+#define           TX_SM_2_KICK_MASK           0xC0    /* kick state machine */
+
+/* 64-bit pointer to the transmit data buffer. only the 50 LSB are incremented
+ * while the upper 23 bits are taken from the TX descriptor
+ */
+#define  REG_TX_DATA_PTR_LOW           0x2030  /* TX data pointer low */
+#define  REG_TX_DATA_PTR_HI            0x2034  /* TX data pointer high */
+
+/* 13 bit registers written by driver w/ descriptor value that follows 
+ * last valid xmit descriptor. kick # and complete # values are used by
+ * the xmit dma engine to control tx descr fetching. if > 1 valid 
+ * tx descr is available within the cache line being read, cassini will
+ * internally cache up to 4 of them. 0 on reset. _KICK = rw, _COMP = ro.
+ */
+#define  REG_TX_KICK0                  0x2038  /* TX kick reg #1 */
+#define  REG_TX_KICKN(x)               (REG_TX_KICK0 + (x)*4)
+#define  REG_TX_COMP0                  0x2048  /* TX completion reg #1 */
+#define  REG_TX_COMPN(x)               (REG_TX_COMP0 + (x)*4)
+
+/* values of TX_COMPLETE_1-4 are written. each completion register 
+ * is 2bytes in size and contiguous. 8B allocation w/ 8B alignment. 
+ * NOTE: completion reg values are only written back prior to TX_INTME and
+ * TX_ALL interrupts. at all other times, the most up-to-date index values 
+ * should be obtained from the REG_TX_COMPLETE_# registers. 
+ * here's the layout: 
+ * offset from base addr      completion # byte
+ *           0                TX_COMPLETE_1_MSB
+ *          1                TX_COMPLETE_1_LSB
+ *           2                TX_COMPLETE_2_MSB
+ *          3                TX_COMPLETE_2_LSB
+ *           4                TX_COMPLETE_3_MSB
+ *          5                TX_COMPLETE_3_LSB
+ *           6                TX_COMPLETE_4_MSB
+ *          7                TX_COMPLETE_4_LSB
+ */
+#define  TX_COMPWB_SIZE             8
+#define  REG_TX_COMPWB_DB_LOW       0x2058  /* TX completion write back
+                                              base low */
+#define  REG_TX_COMPWB_DB_HI        0x205C  /* TX completion write back
+                                              base high */
+#define    TX_COMPWB_MSB_MASK       0x00000000000000FFULL
+#define    TX_COMPWB_MSB_SHIFT      0
+#define    TX_COMPWB_LSB_MASK       0x000000000000FF00ULL
+#define    TX_COMPWB_LSB_SHIFT      8
+#define    TX_COMPWB_NEXT(x)        ((x) >> 16)
+                                                     
+/* 53 MSB used as base address. 11 LSB assumed to be 0. TX desc pointer must
+ * be 2KB-aligned. */
+#define  REG_TX_DB0_LOW         0x2060  /* TX descriptor base low #1 */
+#define  REG_TX_DB0_HI          0x2064  /* TX descriptor base hi #1 */
+#define  REG_TX_DBN_LOW(x)      (REG_TX_DB0_LOW + (x)*8)
+#define  REG_TX_DBN_HI(x)       (REG_TX_DB0_HI + (x)*8)
+
+/* 16-bit registers hold weights for the weighted round-robin of the
+ * four CBQ TX descr rings. weights correspond to # bytes xferred from
+ * host to TXFIFO in a round of WRR arbitration. can be set
+ * dynamically with new weights set upon completion of the current
+ * packet transfer from host memory to TXFIFO. a dummy write to any of
+ * these registers causes a queue1 pre-emption with all historical bw
+ * deficit data reset to 0 (useful when congestion requires a
+ * pre-emption/re-allocation of network bandwidth
+ */
+#define  REG_TX_MAXBURST_0             0x2080  /* TX MaxBurst #1 */
+#define  REG_TX_MAXBURST_1             0x2084  /* TX MaxBurst #2 */
+#define  REG_TX_MAXBURST_2             0x2088  /* TX MaxBurst #3 */
+#define  REG_TX_MAXBURST_3             0x208C  /* TX MaxBurst #4 */
+
+/* diagnostics access to any TX FIFO location. every access is 65
+ * bits.  _DATA_LOW = 32 LSB, _DATA_HI_T1/T0 = 32 MSB. _TAG = tag bit.
+ * writing _DATA_HI_T0 sets tag bit low, writing _DATA_HI_T1 sets tag
+ * bit high.  TX_FIFO_PIO_SEL must be set for TX FIFO PIO access. if
+ * TX FIFO data integrity is desired, TX DMA should be
+ * disabled. _DATA_HI_Tx should be the last access of the sequence.
+ */
+#define  REG_TX_FIFO_ADDR              0x2104  /* TX FIFO address */
+#define  REG_TX_FIFO_TAG               0x2108  /* TX FIFO tag */
+#define  REG_TX_FIFO_DATA_LOW          0x210C  /* TX FIFO data low */
+#define  REG_TX_FIFO_DATA_HI_T1        0x2110  /* TX FIFO data high t1 */
+#define  REG_TX_FIFO_DATA_HI_T0        0x2114  /* TX FIFO data high t0 */
+#define  REG_TX_FIFO_SIZE              0x2118  /* (ro) TX FIFO size = 0x090 = 9KB */
+
+/* 9-bit register controls BIST of TX FIFO. bit set indicates that the BIST 
+ * passed for the specified memory
+ */
+#define  REG_TX_RAMBIST                0x211C /* TX RAMBIST control/status */
+#define    TX_RAMBIST_STATE            0x01C0 /* progress state of RAMBIST 
+                                                controller state machine */
+#define    TX_RAMBIST_RAM33A_PASS      0x0020 /* RAM33A passed */
+#define    TX_RAMBIST_RAM32A_PASS      0x0010 /* RAM32A passed */
+#define    TX_RAMBIST_RAM33B_PASS      0x0008 /* RAM33B passed */
+#define    TX_RAMBIST_RAM32B_PASS      0x0004 /* RAM32B passed */
+#define    TX_RAMBIST_SUMMARY          0x0002 /* all RAM passed */
+#define    TX_RAMBIST_START            0x0001 /* write 1 to start BIST. self
+                                                clears on completion. */
+
+/** receive dma registers **/
+#define MAX_RX_DESC_RINGS              2
+#define MAX_RX_COMP_RINGS              4
+
+/* receive DMA channel configuration. default: 0x80910 
+ * free ring size       = (1 << n)*32  -> [32 - 8k]
+ * completion ring size = (1 << n)*128 -> [128 - 32k], n < 9 
+ * DEFAULT: 0x80910
+ */
+#define  REG_RX_CFG                     0x4000  /* RX config */
+#define    RX_CFG_DMA_EN                0x00000001 /* enable RX DMA. 0 stops
+                                                        channel as soon as current
+                                                        frame xfer has completed.
+                                                        driver should disable MAC 
+                                                        for 200ms before disabling 
+                                                        RX */
+#define    RX_CFG_DESC_RING_MASK        0x0000001E /* # desc entries in RX 
+                                                        free desc ring. 
+                                                        def: 0x8 = 8k */
+#define    RX_CFG_DESC_RING_SHIFT       1
+#define    RX_CFG_COMP_RING_MASK        0x000001E0 /* # desc entries in RX complete
+                                                        ring. def: 0x8 = 32k */
+#define    RX_CFG_COMP_RING_SHIFT       5
+#define    RX_CFG_BATCH_DIS             0x00000200 /* disable receive desc 
+                                                     batching. def: 0x0 =
+                                                     enabled */
+#define    RX_CFG_SWIVEL_MASK           0x00001C00 /* byte offset of the 1st 
+                                                     data byte of the packet 
+                                                     w/in 8 byte boundares.
+                                                     this swivels the data 
+                                                     DMA'ed to header 
+                                                     buffers, jumbo buffers
+                                                     when header split is not
+                                                     requested and MTU sized
+                                                     buffers. def: 0x2 */
+#define    RX_CFG_SWIVEL_SHIFT          10
+
+/* cassini+ only */
+#define    RX_CFG_DESC_RING1_MASK       0x000F0000 /* # of desc entries in
+                                                        RX free desc ring 2. 
+                                                        def: 0x8 = 8k */
+#define    RX_CFG_DESC_RING1_SHIFT      16
+
+
+/* the page size register allows cassini chips to do the following with 
+ * received data:
+ * [--------------------------------------------------------------] page
+ * [off][buf1][pad][off][buf2][pad][off][buf3][pad][off][buf4][pad]
+ * |--------------| = PAGE_SIZE_BUFFER_STRIDE
+ * page = PAGE_SIZE 
+ * offset = PAGE_SIZE_MTU_OFF
+ * for the above example, MTU_BUFFER_COUNT = 4.
+ * NOTE: as is apparent, you need to ensure that the following holds:
+ * MTU_BUFFER_COUNT <= PAGE_SIZE/PAGE_SIZE_BUFFER_STRIDE
+ * DEFAULT: 0x48002002 (8k pages)
+ */
+#define  REG_RX_PAGE_SIZE               0x4004  /* RX page size */
+#define    RX_PAGE_SIZE_MASK            0x00000003 /* size of pages pointed to
+                                                     by receive descriptors.
+                                                     if jumbo buffers are 
+                                                     supported the page size 
+                                                     should not be < 8k.
+                                                     0b00 = 2k, 0b01 = 4k
+                                                     0b10 = 8k, 0b11 = 16k
+                                                     DEFAULT: 8k */
+#define    RX_PAGE_SIZE_SHIFT           0
+#define    RX_PAGE_SIZE_MTU_COUNT_MASK  0x00007800 /* # of MTU buffers the hw
+                                                     packs into a page. 
+                                                     DEFAULT: 4 */
+#define    RX_PAGE_SIZE_MTU_COUNT_SHIFT 11
+#define    RX_PAGE_SIZE_MTU_STRIDE_MASK 0x18000000 /* # of bytes that separate
+                                                        each MTU buffer + 
+                                                        offset from each 
+                                                        other.
+                                                        0b00 = 1k, 0b01 = 2k
+                                                        0b10 = 4k, 0b11 = 8k
+                                                        DEFAULT: 0x1 */
+#define    RX_PAGE_SIZE_MTU_STRIDE_SHIFT 27
+#define    RX_PAGE_SIZE_MTU_OFF_MASK    0xC0000000 /* offset in each page that
+                                                     hw writes the MTU buffer
+                                                     into. 
+                                                     0b00 = 0,  
+                                                     0b01 = 64 bytes
+                                                     0b10 = 96, 0b11 = 128
+                                                     DEFAULT: 0x1 */
+#define    RX_PAGE_SIZE_MTU_OFF_SHIFT   30
+                                                        
+/* 11-bit counter points to next location in RX FIFO to be loaded/read. 
+ * shadow write pointers enable retries in case of early receive aborts.
+ * DEFAULT: 0x0. generated on 64-bit boundaries.
+ */
+#define  REG_RX_FIFO_WRITE_PTR             0x4008  /* RX FIFO write pointer */
+#define  REG_RX_FIFO_READ_PTR              0x400C  /* RX FIFO read pointer */
+#define  REG_RX_IPP_FIFO_SHADOW_WRITE_PTR  0x4010  /* RX IPP FIFO shadow write 
+                                                     pointer */
+#define  REG_RX_IPP_FIFO_SHADOW_READ_PTR   0x4014  /* RX IPP FIFO shadow read
+                                                     pointer */
+#define  REG_RX_IPP_FIFO_READ_PTR          0x400C  /* RX IPP FIFO read 
+                                                     pointer. (8-bit counter) */
+
+/* current state of RX DMA state engines + other info
+ * DEFAULT: 0x0
+ */
+#define  REG_RX_DEBUG                      0x401C  /* RX debug */
+#define    RX_DEBUG_LOAD_STATE_MASK        0x0000000F /* load state machine w/ MAC:
+                                                        0x0 = idle,   0x1 = load_bop
+                                                        0x2 = load 1, 0x3 = load 2
+                                                        0x4 = load 3, 0x5 = load 4
+                                                        0x6 = last detect
+                                                        0x7 = wait req
+                                                        0x8 = wait req statuss 1st
+                                                        0x9 = load st
+                                                        0xa = bubble mac
+                                                        0xb = error */
+#define    RX_DEBUG_LM_STATE_MASK          0x00000070 /* load state machine w/ HP and
+                                                        RX FIFO:
+                                                        0x0 = idle,   0x1 = hp xfr
+                                                        0x2 = wait hp ready
+                                                        0x3 = wait flow code
+                                                        0x4 = fifo xfer
+                                                        0x5 = make status
+                                                        0x6 = csum ready
+                                                        0x7 = error */
+#define    RX_DEBUG_FC_STATE_MASK          0x000000180 /* flow control state machine
+                                                        w/ MAC:
+                                                        0x0 = idle
+                                                        0x1 = wait xoff ack
+                                                        0x2 = wait xon
+                                                        0x3 = wait xon ack */
+#define    RX_DEBUG_DATA_STATE_MASK        0x000001E00 /* unload data state machine
+                                                        states: 
+                                                        0x0 = idle data
+                                                        0x1 = header begin
+                                                        0x2 = xfer header
+                                                        0x3 = xfer header ld
+                                                        0x4 = mtu begin
+                                                        0x5 = xfer mtu
+                                                        0x6 = xfer mtu ld
+                                                        0x7 = jumbo begin
+                                                        0x8 = xfer jumbo 
+                                                        0x9 = xfer jumbo ld
+                                                        0xa = reas begin
+                                                        0xb = xfer reas
+                                                        0xc = flush tag
+                                                        0xd = xfer reas ld
+                                                        0xe = error
+                                                        0xf = bubble idle */
+#define    RX_DEBUG_DESC_STATE_MASK        0x0001E000 /* unload desc state machine
+                                                        states:
+                                                        0x0 = idle desc
+                                                        0x1 = wait ack
+                                                        0x9 = wait ack 2
+                                                        0x2 = fetch desc 1
+                                                        0xa = fetch desc 2
+                                                        0x3 = load ptrs
+                                                        0x4 = wait dma
+                                                        0x5 = wait ack batch
+                                                        0x6 = post batch
+                                                        0x7 = xfr done */
+#define    RX_DEBUG_INTR_READ_PTR_MASK     0x30000000 /* interrupt read ptr of the
+                                                        interrupt queue */
+#define    RX_DEBUG_INTR_WRITE_PTR_MASK    0xC0000000 /* interrupt write pointer
+                                                        of the interrupt queue */
+
+/* flow control frames are emmitted using two PAUSE thresholds:
+ * XOFF PAUSE uses pause time value pre-programmed in the Send PAUSE MAC reg
+ * XON PAUSE uses a pause time of 0. granularity of threshold is 64bytes.
+ * PAUSE thresholds defined in terms of FIFO occupancy and may be translated
+ * into FIFO vacancy using RX_FIFO_SIZE. setting ON will trigger XON frames 
+ * when FIFO reaches 0. OFF threshold should not be > size of RX FIFO. max
+ * value is is 0x6F. 
+ * DEFAULT: 0x00078
+ */
+#define  REG_RX_PAUSE_THRESH               0x4020  /* RX pause thresholds */
+#define    RX_PAUSE_THRESH_QUANTUM         64
+#define    RX_PAUSE_THRESH_OFF_MASK        0x000001FF /* XOFF PAUSE emitted when
+                                                        RX FIFO occupancy > 
+                                                        value*64B */
+#define    RX_PAUSE_THRESH_OFF_SHIFT       0
+#define    RX_PAUSE_THRESH_ON_MASK         0x001FF000 /* XON PAUSE emitted after
+                                                        emitting XOFF PAUSE when RX
+                                                        FIFO occupancy falls below
+                                                        this value*64B. must be
+                                                        < XOFF threshold. if =
+                                                        RX_FIFO_SIZE< XON frames are
+                                                        never emitted. */
+#define    RX_PAUSE_THRESH_ON_SHIFT        12
+
+/* 13-bit register used to control RX desc fetching and intr generation. if 4+
+ * valid RX descriptors are available, Cassini will read 4 at a time. 
+ * writing N means that all desc up to *but* excluding N are available. N must
+ * be a multiple of 4 (N % 4 = 0). first desc should be cache-line aligned. 
+ * DEFAULT: 0 on reset
+ */
+#define  REG_RX_KICK                    0x4024  /* RX kick reg */
+
+/* 8KB aligned 64-bit pointer to the base of the RX free/completion rings.
+ * lower 13 bits of the low register are hard-wired to 0.
+ */
+#define  REG_RX_DB_LOW                     0x4028  /* RX descriptor ring 
+                                                        base low */
+#define  REG_RX_DB_HI                      0x402C  /* RX descriptor ring
+                                                        base hi */
+#define  REG_RX_CB_LOW                     0x4030  /* RX completion ring
+                                                        base low */
+#define  REG_RX_CB_HI                      0x4034  /* RX completion ring 
+                                                        base hi */
+/* 13-bit register indicate desc used by cassini for receive frames. used
+ * for diagnostic purposes. 
+ * DEFAULT: 0 on reset
+ */
+#define  REG_RX_COMP                       0x4038  /* (ro) RX completion */
+
+/* HEAD and TAIL are used to control RX desc posting and interrupt
+ * generation.  hw moves the head register to pass ownership to sw. sw
+ * moves the tail register to pass ownership back to hw. to give all
+ * entries to hw, set TAIL = HEAD.  if HEAD and TAIL indicate that no
+ * more entries are available, DMA will pause and an interrupt will be
+ * generated to indicate no more entries are available.  sw can use
+ * this interrupt to reduce the # of times it must update the
+ * completion tail register.
+ * DEFAULT: 0 on reset
+ */
+#define  REG_RX_COMP_HEAD                  0x403C  /* RX completion head */
+#define  REG_RX_COMP_TAIL                  0x4040  /* RX completion tail */
+
+/* values used for receive interrupt blanking. loaded each time the ISR is read
+ * DEFAULT: 0x00000000
+ */
+#define  REG_RX_BLANK                      0x4044  /* RX blanking register 
+                                                        for ISR read */
+#define    RX_BLANK_INTR_PKT_MASK          0x000001FF /* RX_DONE intr asserted if 
+                                                        this many sets of completion
+                                                        writebacks (up to 2 packets)
+                                                        occur since the last time
+                                                        the ISR was read. 0 = no
+                                                        packet blanking */
+#define    RX_BLANK_INTR_PKT_SHIFT         0
+#define    RX_BLANK_INTR_TIME_MASK         0x3FFFF000 /* RX_DONE interrupt asserted
+                                                        if that many clocks were
+                                                        counted since last time the
+                                                        ISR was read. 
+                                                        each count is 512 core
+                                                        clocks (125MHz). 0 = no
+                                                        time blanking */
+#define    RX_BLANK_INTR_TIME_SHIFT        12
+
+/* values used for interrupt generation based on threshold values of how 
+ * many free desc and completion entries are available for hw use.
+ * DEFAULT: 0x00000000
+ */
+#define  REG_RX_AE_THRESH                  0x4048  /* RX almost empty 
+                                                        thresholds */
+#define    RX_AE_THRESH_FREE_MASK          0x00001FFF /* RX_BUF_AE will be 
+                                                        generated if # desc
+                                                        avail for hw use <= 
+                                                        # */
+#define    RX_AE_THRESH_FREE_SHIFT         0
+#define    RX_AE_THRESH_COMP_MASK          0x0FFFE000 /* RX_COMP_AE will be
+                                                        generated if # of 
+                                                        completion entries
+                                                        avail for hw use <= 
+                                                        # */
+#define    RX_AE_THRESH_COMP_SHIFT         13
+
+/* probabilities for random early drop (RED) thresholds on a FIFO threshold 
+ * basis. probability should increase when the FIFO level increases. control 
+ * packets are never dropped and not counted in stats. probability programmed 
+ * on a 12.5% granularity. e.g., 0x1 = 1/8 packets dropped.
+ * DEFAULT: 0x00000000
+ */
+#define  REG_RX_RED                      0x404C  /* RX random early detect enable */
+#define    RX_RED_4K_6K_FIFO_MASK        0x000000FF /*  4KB < FIFO thresh < 6KB */
+#define    RX_RED_6K_8K_FIFO_MASK        0x0000FF00 /*  6KB < FIFO thresh < 8KB */
+#define    RX_RED_8K_10K_FIFO_MASK       0x00FF0000 /*  8KB < FIFO thresh < 10KB */
+#define    RX_RED_10K_12K_FIFO_MASK      0xFF000000 /* 10KB < FIFO thresh < 12KB */
+
+/* FIFO fullness levels for RX FIFO, RX control FIFO, and RX IPP FIFO. 
+ * RX control FIFO = # of packets in RX FIFO. 
+ * DEFAULT: 0x0
+ */
+#define  REG_RX_FIFO_FULLNESS              0x4050  /* (ro) RX FIFO fullness */
+#define    RX_FIFO_FULLNESS_RX_FIFO_MASK   0x3FF80000 /* level w/ 8B granularity */
+#define    RX_FIFO_FULLNESS_IPP_FIFO_MASK  0x0007FF00 /* level w/ 8B granularity */
+#define    RX_FIFO_FULLNESS_RX_PKT_MASK    0x000000FF /* # packets in RX FIFO */
+#define  REG_RX_IPP_PACKET_COUNT           0x4054  /* RX IPP packet counter */
+#define  REG_RX_WORK_DMA_PTR_LOW           0x4058  /* RX working DMA ptr low */
+#define  REG_RX_WORK_DMA_PTR_HI            0x405C  /* RX working DMA ptr 
+                                                     high */
+
+/* BIST testing ro RX FIFO, RX control FIFO, and RX IPP FIFO. only RX BIST
+ * START/COMPLETE is writeable. START will clear when the BIST has completed
+ * checking all 17 RAMS. 
+ * DEFAULT: 0bxxxx xxxxx xxxx xxxx xxxx x000 0000 0000 00x0
+ */
+#define  REG_RX_BIST                       0x4060  /* (ro) RX BIST */
+#define    RX_BIST_32A_PASS                0x80000000 /* RX FIFO 32A passed */
+#define    RX_BIST_33A_PASS                0x40000000 /* RX FIFO 33A passed */
+#define    RX_BIST_32B_PASS                0x20000000 /* RX FIFO 32B passed */
+#define    RX_BIST_33B_PASS                0x10000000 /* RX FIFO 33B passed */
+#define    RX_BIST_32C_PASS                0x08000000 /* RX FIFO 32C passed */
+#define    RX_BIST_33C_PASS                0x04000000 /* RX FIFO 33C passed */
+#define    RX_BIST_IPP_32A_PASS            0x02000000 /* RX IPP FIFO 33B passed */
+#define    RX_BIST_IPP_33A_PASS            0x01000000 /* RX IPP FIFO 33A passed */
+#define    RX_BIST_IPP_32B_PASS            0x00800000 /* RX IPP FIFO 32B passed */
+#define    RX_BIST_IPP_33B_PASS            0x00400000 /* RX IPP FIFO 33B passed */
+#define    RX_BIST_IPP_32C_PASS            0x00200000 /* RX IPP FIFO 32C passed */
+#define    RX_BIST_IPP_33C_PASS            0x00100000 /* RX IPP FIFO 33C passed */
+#define    RX_BIST_CTRL_32_PASS            0x00800000 /* RX CTRL FIFO 32 passed */
+#define    RX_BIST_CTRL_33_PASS            0x00400000 /* RX CTRL FIFO 33 passed */
+#define    RX_BIST_REAS_26A_PASS           0x00200000 /* RX Reas 26A passed */
+#define    RX_BIST_REAS_26B_PASS           0x00100000 /* RX Reas 26B passed */
+#define    RX_BIST_REAS_27_PASS            0x00080000 /* RX Reas 27 passed */
+#define    RX_BIST_STATE_MASK              0x00078000 /* BIST state machine */
+#define    RX_BIST_SUMMARY                 0x00000002 /* when BIST complete,
+                                                        summary pass bit 
+                                                        contains AND of BIST
+                                                        results of all 16
+                                                        RAMS */
+#define    RX_BIST_START                   0x00000001 /* write 1 to start 
+                                                        BIST. self clears
+                                                        on completion. */
+
+/* next location in RX CTRL FIFO that will be loaded w/ data from RX IPP/read
+ * from to retrieve packet control info. 
+ * DEFAULT: 0
+ */
+#define  REG_RX_CTRL_FIFO_WRITE_PTR        0x4064  /* (ro) RX control FIFO 
+                                                     write ptr */
+#define  REG_RX_CTRL_FIFO_READ_PTR         0x4068  /* (ro) RX control FIFO read
+                                                     ptr */
+
+/* receive interrupt blanking. loaded each time interrupt alias register is
+ * read. 
+ * DEFAULT: 0x0
+ */
+#define  REG_RX_BLANK_ALIAS_READ           0x406C  /* RX blanking register for
+                                                     alias read */
+#define    RX_BAR_INTR_PACKET_MASK         0x000001FF /* assert RX_DONE if # 
+                                                        completion writebacks 
+                                                        > # since last ISR 
+                                                        read. 0 = no 
+                                                        blanking. up to 2 
+                                                        packets per 
+                                                        completion wb. */
+#define    RX_BAR_INTR_TIME_MASK           0x3FFFF000 /* assert RX_DONE if #
+                                                        clocks > # since last
+                                                        ISR read. each count
+                                                        is 512 core clocks
+                                                        (125MHz). 0 = no 
+                                                        blanking. */
+
+/* diagnostic access to RX FIFO. 32 LSB accessed via DATA_LOW. 32 MSB accessed
+ * via DATA_HI_T0 or DATA_HI_T1. TAG reads the tag bit. writing HI_T0
+ * will unset the tag bit while writing HI_T1 will set the tag bit. to reset
+ * to normal operation after diagnostics, write to address location 0x0.
+ * RX_DMA_EN bit must be set to 0x0 for RX FIFO PIO access. DATA_HI should
+ * be the last write access of a write sequence.
+ * DEFAULT: undefined
+ */
+#define  REG_RX_FIFO_ADDR                  0x4080  /* RX FIFO address */
+#define  REG_RX_FIFO_TAG                   0x4084  /* RX FIFO tag */
+#define  REG_RX_FIFO_DATA_LOW              0x4088  /* RX FIFO data low */
+#define  REG_RX_FIFO_DATA_HI_T0            0x408C  /* RX FIFO data high T0 */
+#define  REG_RX_FIFO_DATA_HI_T1            0x4090  /* RX FIFO data high T1 */
+
+/* diagnostic assess to RX CTRL FIFO. 8-bit FIFO_ADDR holds address of
+ * 81 bit control entry and 6 bit flow id. LOW and MID are both 32-bit
+ * accesses. HI is 7-bits with 6-bit flow id and 1 bit control
+ * word. RX_DMA_EN must be 0 for RX CTRL FIFO PIO access. DATA_HI
+ * should be last write access of the write sequence.
+ * DEFAULT: undefined
+ */
+#define  REG_RX_CTRL_FIFO_ADDR             0x4094  /* RX Control FIFO and 
+                                                     Batching FIFO addr */
+#define  REG_RX_CTRL_FIFO_DATA_LOW         0x4098  /* RX Control FIFO data 
+                                                     low */
+#define  REG_RX_CTRL_FIFO_DATA_MID         0x409C  /* RX Control FIFO data 
+                                                     mid */
+#define  REG_RX_CTRL_FIFO_DATA_HI          0x4100  /* RX Control FIFO data 
+                                                     hi and flow id */
+#define    RX_CTRL_FIFO_DATA_HI_CTRL       0x0001  /* upper bit of ctrl word */
+#define    RX_CTRL_FIFO_DATA_HI_FLOW_MASK  0x007E  /* flow id */
+
+/* diagnostic access to RX IPP FIFO. same semantics as RX_FIFO.
+ * DEFAULT: undefined
+ */
+#define  REG_RX_IPP_FIFO_ADDR              0x4104  /* RX IPP FIFO address */
+#define  REG_RX_IPP_FIFO_TAG               0x4108  /* RX IPP FIFO tag */
+#define  REG_RX_IPP_FIFO_DATA_LOW          0x410C  /* RX IPP FIFO data low */
+#define  REG_RX_IPP_FIFO_DATA_HI_T0        0x4110  /* RX IPP FIFO data high
+                                                     T0 */
+#define  REG_RX_IPP_FIFO_DATA_HI_T1        0x4114  /* RX IPP FIFO data high
+                                                     T1 */
+
+/* 64-bit pointer to receive data buffer in host memory used for headers and
+ * small packets. MSB in high register. loaded by DMA state machine and 
+ * increments as DMA writes receive data. only 50 LSB are incremented. top
+ * 13 bits taken from RX descriptor.
+ * DEFAULT: undefined
+ */
+#define  REG_RX_HEADER_PAGE_PTR_LOW        0x4118  /* (ro) RX header page ptr
+                                                     low */
+#define  REG_RX_HEADER_PAGE_PTR_HI         0x411C  /* (ro) RX header page ptr
+                                                     high */
+#define  REG_RX_MTU_PAGE_PTR_LOW           0x4120  /* (ro) RX MTU page pointer 
+                                                     low */
+#define  REG_RX_MTU_PAGE_PTR_HI            0x4124  /* (ro) RX MTU page pointer 
+                                                     high */
+
+/* PIO diagnostic access to RX reassembly DMA Table RAM. 6-bit register holds
+ * one of 64 79-bit locations in the RX Reassembly DMA table and the addr of
+ * one of the 64 byte locations in the Batching table. LOW holds 32 LSB. 
+ * MID holds the next 32 LSB. HIGH holds the 15 MSB. RX_DMA_EN must be set
+ * to 0 for PIO access. DATA_HIGH should be last write of write sequence.
+ * layout:  
+ * reassmbl ptr [78:15] | reassmbl index [14:1] | reassmbl entry valid [0]
+ * DEFAULT: undefined
+ */
+#define  REG_RX_TABLE_ADDR             0x4128  /* RX reassembly DMA table
+                                                 address */
+#define    RX_TABLE_ADDR_MASK          0x0000003F /* address mask */
+
+#define  REG_RX_TABLE_DATA_LOW         0x412C  /* RX reassembly DMA table
+                                                 data low */
+#define  REG_RX_TABLE_DATA_MID         0x4130  /* RX reassembly DMA table 
+                                                 data mid */
+#define  REG_RX_TABLE_DATA_HI          0x4134  /* RX reassembly DMA table
+                                                 data high */
+
+/* cassini+ only */
+/* 8KB aligned 64-bit pointer to base of RX rings. lower 13 bits hardwired to
+ * 0. same semantics as primary desc/complete rings.
+ */
+#define  REG_PLUS_RX_DB1_LOW            0x4200  /* RX descriptor ring
+                                                  2 base low */
+#define  REG_PLUS_RX_DB1_HI             0x4204  /* RX descriptor ring
+                                                  2 base high */
+#define  REG_PLUS_RX_CB1_LOW            0x4208  /* RX completion ring
+                                                  2 base low. 4 total */
+#define  REG_PLUS_RX_CB1_HI             0x420C  /* RX completion ring
+                                                  2 base high. 4 total */
+#define  REG_PLUS_RX_CBN_LOW(x)        (REG_PLUS_RX_CB1_LOW + 8*((x) - 1))
+#define  REG_PLUS_RX_CBN_HI(x)         (REG_PLUS_RX_CB1_HI + 8*((x) - 1))
+#define  REG_PLUS_RX_KICK1             0x4220  /* RX Kick 2 register */
+#define  REG_PLUS_RX_COMP1             0x4224  /* (ro) RX completion 2 
+                                                 reg */
+#define  REG_PLUS_RX_COMP1_HEAD        0x4228  /* (ro) RX completion 2 
+                                                 head reg. 4 total. */
+#define  REG_PLUS_RX_COMP1_TAIL        0x422C  /* RX completion 2 
+                                                 tail reg. 4 total. */
+#define  REG_PLUS_RX_COMPN_HEAD(x)    (REG_PLUS_RX_COMP1_HEAD + 8*((x) - 1))
+#define  REG_PLUS_RX_COMPN_TAIL(x)    (REG_PLUS_RX_COMP1_TAIL + 8*((x) - 1))
+#define  REG_PLUS_RX_AE1_THRESH        0x4240  /* RX almost empty 2
+                                                 thresholds */
+#define    RX_AE1_THRESH_FREE_MASK     RX_AE_THRESH_FREE_MASK
+#define    RX_AE1_THRESH_FREE_SHIFT    RX_AE_THRESH_FREE_SHIFT
+
+/** header parser registers **/
+
+/* RX parser configuration register. 
+ * DEFAULT: 0x1651004
+ */
+#define  REG_HP_CFG                       0x4140  /* header parser 
+                                                    configuration reg */
+#define    HP_CFG_PARSE_EN                0x00000001 /* enab header parsing */
+#define    HP_CFG_NUM_CPU_MASK            0x000000FC /* # processors 
+                                                     0 = 64. 0x3f = 63 */
+#define    HP_CFG_NUM_CPU_SHIFT           2
+#define    HP_CFG_SYN_INC_MASK            0x00000100 /* SYN bit won't increment
+                                                       TCP seq # by one when
+                                                       stored in FDBM */
+#define    HP_CFG_TCP_THRESH_MASK         0x000FFE00 /* # bytes of TCP data
+                                                       needed to be considered
+                                                       for reassembly */
+#define    HP_CFG_TCP_THRESH_SHIFT        9
+
+/* access to RX Instruction RAM. 5-bit register/counter holds addr
+ * of 39 bit entry to be read/written. 32 LSB in _DATA_LOW. 7 MSB in _DATA_HI.
+ * RX_DMA_EN must be 0 for RX instr PIO access. DATA_HI should be last access
+ * of sequence. 
+ * DEFAULT: undefined
+ */
+#define  REG_HP_INSTR_RAM_ADDR             0x4144  /* HP instruction RAM
+                                                     address */
+#define    HP_INSTR_RAM_ADDR_MASK          0x01F   /* 5-bit mask */
+#define  REG_HP_INSTR_RAM_DATA_LOW         0x4148  /* HP instruction RAM
+                                                     data low */
+#define    HP_INSTR_RAM_LOW_OUTMASK_MASK   0x0000FFFF
+#define    HP_INSTR_RAM_LOW_OUTMASK_SHIFT  0
+#define    HP_INSTR_RAM_LOW_OUTSHIFT_MASK  0x000F0000
+#define    HP_INSTR_RAM_LOW_OUTSHIFT_SHIFT 16
+#define    HP_INSTR_RAM_LOW_OUTEN_MASK     0x00300000
+#define    HP_INSTR_RAM_LOW_OUTEN_SHIFT    20
+#define    HP_INSTR_RAM_LOW_OUTARG_MASK    0xFFC00000
+#define    HP_INSTR_RAM_LOW_OUTARG_SHIFT   22
+#define  REG_HP_INSTR_RAM_DATA_MID         0x414C  /* HP instruction RAM 
+                                                     data mid */
+#define    HP_INSTR_RAM_MID_OUTARG_MASK    0x00000003
+#define    HP_INSTR_RAM_MID_OUTARG_SHIFT   0
+#define    HP_INSTR_RAM_MID_OUTOP_MASK     0x0000003C
+#define    HP_INSTR_RAM_MID_OUTOP_SHIFT    2
+#define    HP_INSTR_RAM_MID_FNEXT_MASK     0x000007C0
+#define    HP_INSTR_RAM_MID_FNEXT_SHIFT    6
+#define    HP_INSTR_RAM_MID_FOFF_MASK      0x0003F800
+#define    HP_INSTR_RAM_MID_FOFF_SHIFT     11
+#define    HP_INSTR_RAM_MID_SNEXT_MASK     0x007C0000
+#define    HP_INSTR_RAM_MID_SNEXT_SHIFT    18
+#define    HP_INSTR_RAM_MID_SOFF_MASK      0x3F800000
+#define    HP_INSTR_RAM_MID_SOFF_SHIFT     23
+#define    HP_INSTR_RAM_MID_OP_MASK        0xC0000000
+#define    HP_INSTR_RAM_MID_OP_SHIFT       30
+#define  REG_HP_INSTR_RAM_DATA_HI          0x4150  /* HP instruction RAM
+                                                     data high */
+#define    HP_INSTR_RAM_HI_VAL_MASK        0x0000FFFF
+#define    HP_INSTR_RAM_HI_VAL_SHIFT       0
+#define    HP_INSTR_RAM_HI_MASK_MASK       0xFFFF0000
+#define    HP_INSTR_RAM_HI_MASK_SHIFT      16
+
+/* PIO access into RX Header parser data RAM and flow database.
+ * 11-bit register. Data fills the LSB portion of bus if less than 32 bits.
+ * DATA_RAM: write RAM_FDB_DATA with index to access DATA_RAM.
+ * RAM bytes = 4*(x - 1) + [3:0]. e.g., 0 -> [3:0], 31 -> [123:120]
+ * FLOWDB: write DATA_RAM_FDB register and then read/write FDB1-12 to access 
+ * flow database.
+ * RX_DMA_EN must be 0 for RX parser RAM PIO access. RX Parser RAM data reg
+ * should be the last write access of the write sequence.
+ * DEFAULT: undefined
+ */
+#define  REG_HP_DATA_RAM_FDB_ADDR          0x4154  /* HP data and FDB
+                                                     RAM address */
+#define    HP_DATA_RAM_FDB_DATA_MASK       0x001F  /* select 1 of 86 byte 
+                                                     locations in header 
+                                                     parser data ram to 
+                                                     read/write */
+#define    HP_DATA_RAM_FDB_FDB_MASK        0x3F00  /* 1 of 64 353-bit locations
+                                                     in the flow database */
+#define  REG_HP_DATA_RAM_DATA              0x4158  /* HP data RAM data */
+
+/* HP flow database registers: 1 - 12, 0x415C - 0x4188, 4 8-bit bytes 
+ * FLOW_DB(1) = IP_SA[127:96], FLOW_DB(2) = IP_SA[95:64]
+ * FLOW_DB(3) = IP_SA[63:32],  FLOW_DB(4) = IP_SA[31:0] 
+ * FLOW_DB(5) = IP_DA[127:96], FLOW_DB(6) = IP_DA[95:64]
+ * FLOW_DB(7) = IP_DA[63:32],  FLOW_DB(8) = IP_DA[31:0]
+ * FLOW_DB(9) = {TCP_SP[15:0],TCP_DP[15:0]}
+ * FLOW_DB(10) = bit 0 has value for flow valid
+ * FLOW_DB(11) = TCP_SEQ[63:32], FLOW_DB(12) = TCP_SEQ[31:0]
+ */
+#define  REG_HP_FLOW_DB0                   0x415C  /* HP flow database 1 reg */
+#define  REG_HP_FLOW_DBN(x)                (REG_HP_FLOW_DB0 + (x)*4)
+
+/* diagnostics for RX Header Parser block. 
+ * ASUN: the header parser state machine register is used for diagnostics
+ * purposes. however, the spec doesn't have any details on it.
+ */
+#define  REG_HP_STATE_MACHINE              0x418C  /* (ro) HP state machine */
+#define  REG_HP_STATUS0                    0x4190  /* (ro) HP status 1 */
+#define    HP_STATUS0_SAP_MASK             0xFFFF0000 /* SAP */
+#define    HP_STATUS0_L3_OFF_MASK          0x0000FE00 /* L3 offset */
+#define    HP_STATUS0_LB_CPUNUM_MASK       0x000001F8 /* load balancing CPU 
+                                                        number */
+#define    HP_STATUS0_HRP_OPCODE_MASK      0x00000007 /* HRP opcode */
+
+#define  REG_HP_STATUS1                    0x4194  /* (ro) HP status 2 */
+#define    HP_STATUS1_ACCUR2_MASK          0xE0000000 /* accu R2[6:4] */
+#define    HP_STATUS1_FLOWID_MASK          0x1F800000 /* flow id */
+#define    HP_STATUS1_TCP_OFF_MASK         0x007F0000 /* tcp payload offset */
+#define    HP_STATUS1_TCP_SIZE_MASK        0x0000FFFF /* tcp payload size */
+
+#define  REG_HP_STATUS2                    0x4198  /* (ro) HP status 3 */
+#define    HP_STATUS2_ACCUR2_MASK          0xF0000000 /* accu R2[3:0] */
+#define    HP_STATUS2_CSUM_OFF_MASK        0x07F00000 /* checksum start 
+                                                        start offset */
+#define    HP_STATUS2_ACCUR1_MASK          0x000FE000 /* accu R1 */
+#define    HP_STATUS2_FORCE_DROP           0x00001000 /* force drop */
+#define    HP_STATUS2_BWO_REASSM           0x00000800 /* batching w/o 
+                                                        reassembly */
+#define    HP_STATUS2_JH_SPLIT_EN          0x00000400 /* jumbo header split
+                                                        enable */
+#define    HP_STATUS2_FORCE_TCP_NOCHECK    0x00000200 /* force tcp no payload
+                                                        check */
+#define    HP_STATUS2_DATA_MASK_ZERO       0x00000100 /* mask of data length
+                                                        equal to zero */
+#define    HP_STATUS2_FORCE_TCP_CHECK      0x00000080 /* force tcp payload 
+                                                        chk */
+#define    HP_STATUS2_MASK_TCP_THRESH      0x00000040 /* mask of payload 
+                                                        threshold */
+#define    HP_STATUS2_NO_ASSIST            0x00000020 /* no assist */
+#define    HP_STATUS2_CTRL_PACKET_FLAG     0x00000010 /* control packet flag */
+#define    HP_STATUS2_TCP_FLAG_CHECK       0x00000008 /* tcp flag check */
+#define    HP_STATUS2_SYN_FLAG             0x00000004 /* syn flag */
+#define    HP_STATUS2_TCP_CHECK            0x00000002 /* tcp payload chk */
+#define    HP_STATUS2_TCP_NOCHECK          0x00000001 /* tcp no payload chk */
+
+/* BIST for header parser(HP) and flow database memories (FDBM). set _START
+ * to start BIST. controller clears _START on completion. _START can also
+ * be cleared to force termination of BIST. a bit set indicates that that
+ * memory passed its BIST.
+ */
+#define  REG_HP_RAM_BIST                   0x419C  /* HP RAM BIST reg */
+#define    HP_RAM_BIST_HP_DATA_PASS        0x80000000 /* HP data ram */
+#define    HP_RAM_BIST_HP_INSTR0_PASS      0x40000000 /* HP instr ram 0 */
+#define    HP_RAM_BIST_HP_INSTR1_PASS      0x20000000 /* HP instr ram 1 */
+#define    HP_RAM_BIST_HP_INSTR2_PASS      0x10000000 /* HP instr ram 2 */
+#define    HP_RAM_BIST_FDBM_AGE0_PASS      0x08000000 /* FDBM aging RAM0 */
+#define    HP_RAM_BIST_FDBM_AGE1_PASS      0x04000000 /* FDBM aging RAM1 */
+#define    HP_RAM_BIST_FDBM_FLOWID00_PASS  0x02000000 /* FDBM flowid RAM0 
+                                                        bank 0 */
+#define    HP_RAM_BIST_FDBM_FLOWID10_PASS  0x01000000 /* FDBM flowid RAM1
+                                                        bank 0 */
+#define    HP_RAM_BIST_FDBM_FLOWID20_PASS  0x00800000 /* FDBM flowid RAM2
+                                                        bank 0 */
+#define    HP_RAM_BIST_FDBM_FLOWID30_PASS  0x00400000 /* FDBM flowid RAM3
+                                                        bank 0 */
+#define    HP_RAM_BIST_FDBM_FLOWID01_PASS  0x00200000 /* FDBM flowid RAM0
+                                                        bank 1 */
+#define    HP_RAM_BIST_FDBM_FLOWID11_PASS  0x00100000 /* FDBM flowid RAM1
+                                                        bank 2 */
+#define    HP_RAM_BIST_FDBM_FLOWID21_PASS  0x00080000 /* FDBM flowid RAM2
+                                                        bank 1 */
+#define    HP_RAM_BIST_FDBM_FLOWID31_PASS  0x00040000 /* FDBM flowid RAM3
+                                                        bank 1 */
+#define    HP_RAM_BIST_FDBM_TCPSEQ_PASS    0x00020000 /* FDBM tcp sequence
+                                                        RAM */
+#define    HP_RAM_BIST_SUMMARY             0x00000002 /* all BIST tests */
+#define    HP_RAM_BIST_START               0x00000001 /* start/stop BIST */
+
+
+/** MAC registers.  **/
+/* reset bits are set using a PIO write and self-cleared after the command
+ * execution has completed.
+ */
+#define  REG_MAC_TX_RESET                  0x6000  /* TX MAC software reset
+                                                     command (default: 0x0) */
+#define  REG_MAC_RX_RESET                  0x6004  /* RX MAC software reset
+                                                     command (default: 0x0) */
+/* execute a pause flow control frame transmission
+ DEFAULT: 0x0XXXX */
+#define  REG_MAC_SEND_PAUSE                0x6008  /* send pause command reg */
+#define    MAC_SEND_PAUSE_TIME_MASK        0x0000FFFF /* value of pause time 
+                                                        to be sent on network
+                                                        in units of slot 
+                                                        times */
+#define    MAC_SEND_PAUSE_SEND             0x00010000 /* send pause flow ctrl
+                                                        frame on network */
+
+/* bit set indicates that event occurred. auto-cleared when status register
+ * is read and have corresponding mask bits in mask register. events will 
+ * trigger an interrupt if the corresponding mask bit is 0. 
+ * status register default: 0x00000000
+ * mask register default = 0xFFFFFFFF on reset
+ */
+#define  REG_MAC_TX_STATUS                 0x6010  /* TX MAC status reg */
+#define    MAC_TX_FRAME_XMIT               0x0001  /* successful frame 
+                                                     transmision */
+#define    MAC_TX_UNDERRUN                 0x0002  /* terminated frame 
+                                                     transmission due to
+                                                     data starvation in the 
+                                                     xmit data path */
+#define    MAC_TX_MAX_PACKET_ERR           0x0004  /* frame exceeds max allowed
+                                                     length passed to TX MAC
+                                                     by the DMA engine */
+#define    MAC_TX_COLL_NORMAL              0x0008  /* rollover of the normal
+                                                     collision counter */
+#define    MAC_TX_COLL_EXCESS              0x0010  /* rollover of the excessive
+                                                     collision counter */
+#define    MAC_TX_COLL_LATE                0x0020  /* rollover of the late
+                                                     collision counter */
+#define    MAC_TX_COLL_FIRST               0x0040  /* rollover of the first
+                                                     collision counter */
+#define    MAC_TX_DEFER_TIMER              0x0080  /* rollover of the defer
+                                                     timer */
+#define    MAC_TX_PEAK_ATTEMPTS            0x0100  /* rollover of the peak
+                                                     attempts counter */
+
+#define  REG_MAC_RX_STATUS                 0x6014  /* RX MAC status reg */
+#define    MAC_RX_FRAME_RECV               0x0001  /* successful receipt of
+                                                     a frame */
+#define    MAC_RX_OVERFLOW                 0x0002  /* dropped frame due to 
+                                                     RX FIFO overflow */
+#define    MAC_RX_FRAME_COUNT              0x0004  /* rollover of receive frame
+                                                     counter */
+#define    MAC_RX_ALIGN_ERR                0x0008  /* rollover of alignment
+                                                     error counter */
+#define    MAC_RX_CRC_ERR                  0x0010  /* rollover of crc error
+                                                     counter */
+#define    MAC_RX_LEN_ERR                  0x0020  /* rollover of length 
+                                                     error counter */
+#define    MAC_RX_VIOL_ERR                 0x0040  /* rollover of code 
+                                                     violation error */
+
+/* DEFAULT: 0xXXXX0000 on reset */
+#define  REG_MAC_CTRL_STATUS               0x6018  /* MAC control status reg */
+#define    MAC_CTRL_PAUSE_RECEIVED         0x00000001  /* successful 
+                                                         reception of a 
+                                                         pause control 
+                                                         frame */
+#define    MAC_CTRL_PAUSE_STATE            0x00000002  /* MAC has made a 
+                                                         transition from 
+                                                         "not paused" to 
+                                                         "paused" */
+#define    MAC_CTRL_NOPAUSE_STATE          0x00000004  /* MAC has made a 
+                                                         transition from 
+                                                         "paused" to "not
+                                                         paused" */
+#define    MAC_CTRL_PAUSE_TIME_MASK        0xFFFF0000  /* value of pause time
+                                                         operand that was 
+                                                         received in the last
+                                                         pause flow control
+                                                         frame */
+
+/* layout identical to TX MAC[8:0] */
+#define  REG_MAC_TX_MASK                   0x6020  /* TX MAC mask reg */
+/* layout identical to RX MAC[6:0] */
+#define  REG_MAC_RX_MASK                   0x6024  /* RX MAC mask reg */
+/* layout identical to CTRL MAC[2:0] */
+#define  REG_MAC_CTRL_MASK                 0x6028  /* MAC control mask reg */
+
+/* to ensure proper operation, CFG_EN must be cleared to 0 and a delay 
+ * imposed before writes to other bits in the TX_MAC_CFG register or any of
+ * the MAC parameters is performed. delay dependent upon time required to
+ * transmit a maximum size frame (= MAC_FRAMESIZE_MAX*8/Mbps). e.g.,
+ * the delay for a 1518-byte frame on a 100Mbps network is 125us. 
+ * alternatively, just poll TX_CFG_EN until it reads back as 0. 
+ * NOTE: on half-duplex 1Gbps, TX_CFG_CARRIER_EXTEND and 
+ * RX_CFG_CARRIER_EXTEND should be set and the SLOT_TIME register should
+ * be 0x200 (slot time of 512 bytes)
+ */
+#define  REG_MAC_TX_CFG                 0x6030  /* TX MAC config reg */
+#define    MAC_TX_CFG_EN                0x0001  /* enable TX MAC. 0 will
+                                                     force TXMAC state
+                                                     machine to remain in
+                                                     idle state or to 
+                                                     transition to idle state
+                                                     on completion of an
+                                                     ongoing packet. */
+#define    MAC_TX_CFG_IGNORE_CARRIER    0x0002  /* disable CSMA/CD deferral
+                                                  process. set to 1 when 
+                                                  full duplex and 0 when
+                                                  half duplex */
+#define    MAC_TX_CFG_IGNORE_COLL       0x0004  /* disable CSMA/CD backoff
+                                                  algorithm. set to 1 when
+                                                  full duplex and 0 when
+                                                  half duplex */
+#define    MAC_TX_CFG_IPG_EN            0x0008  /* enable extension of the
+                                                  Rx-to-TX IPG. after 
+                                                  receiving a frame, TX 
+                                                  MAC will reset its 
+                                                  deferral process to 
+                                                  carrier sense for the
+                                                  amount of time = IPG0 +
+                                                  IPG1 and commit to 
+                                                  transmission for time
+                                                  specified in IPG2. when
+                                                  0 or when xmitting frames
+                                                  back-to-pack (Tx-to-Tx
+                                                  IPG), TX MAC ignores 
+                                                  IPG0 and will only use
+                                                  IPG1 for deferral time.
+                                                  IPG2 still used. */
+#define    MAC_TX_CFG_NEVER_GIVE_UP_EN  0x0010  /* TX MAC will not easily
+                                                  give up on frame 
+                                                  xmission. if backoff 
+                                                  algorithm reaches the
+                                                  ATTEMPT_LIMIT, it will
+                                                  clear attempts counter
+                                                  and continue trying to
+                                                  send the frame as 
+                                                  specified by 
+                                                  GIVE_UP_LIM. when 0,
+                                                  TX MAC will execute 
+                                                  standard CSMA/CD prot. */
+#define    MAC_TX_CFG_NEVER_GIVE_UP_LIM 0x0020  /* when set, TX MAC will
+                                                  continue to try to xmit
+                                                  until successful. when
+                                                  0, TX MAC will continue
+                                                  to try xmitting until
+                                                  successful or backoff
+                                                  algorithm reaches 
+                                                  ATTEMPT_LIMIT*16 */
+#define    MAC_TX_CFG_NO_BACKOFF        0x0040  /* modify CSMA/CD to disable
+                                                  backoff algorithm. TX
+                                                  MAC will not back off
+                                                  after a xmission attempt
+                                                  that resulted in a 
+                                                  collision. */
+#define    MAC_TX_CFG_SLOW_DOWN         0x0080  /* modify CSMA/CD so that
+                                                  deferral process is reset
+                                                  in response to carrier
+                                                  sense during the entire
+                                                  duration of IPG. TX MAC
+                                                  will only commit to frame
+                                                  xmission after frame
+                                                  xmission has actually
+                                                  begun. */
+#define    MAC_TX_CFG_NO_FCS            0x0100  /* TX MAC will not generate
+                                                  CRC for all xmitted
+                                                  packets. when clear, CRC
+                                                  generation is dependent
+                                                  upon NO_CRC bit in the
+                                                  xmit control word from 
+                                                  TX DMA */
+#define    MAC_TX_CFG_CARRIER_EXTEND    0x0200  /* enables xmit part of the
+                                                  carrier extension 
+                                                  feature. this allows for 
+                                                  longer collision domains
+                                                  by extending the carrier
+                                                  and collision window
+                                                  from the end of FCS until
+                                                  the end of the slot time
+                                                  if necessary. Required
+                                                  for half-duplex at 1Gbps,
+                                                  clear otherwise. */
+
+/* when CRC is not stripped, reassembly packets will not contain the CRC. 
+ * these will be stripped by HRP because it reassembles layer 4 data, and the
+ * CRC is layer 2. however, non-reassembly packets will still contain the CRC 
+ * when passed to the host. to ensure proper operation, need to wait 3.2ms
+ * after clearing RX_CFG_EN before writing to any other RX MAC registers
+ * or other MAC parameters. alternatively, poll RX_CFG_EN until it clears
+ * to 0. similary, HASH_FILTER_EN and ADDR_FILTER_EN have the same 
+ * restrictions as CFG_EN.
+ */
+#define  REG_MAC_RX_CFG                 0x6034  /* RX MAC config reg */
+#define    MAC_RX_CFG_EN                0x0001  /* enable RX MAC */
+#define    MAC_RX_CFG_STRIP_PAD         0x0002  /* always program to 0.
+                                                  feature not supported */
+#define    MAC_RX_CFG_STRIP_FCS         0x0004  /* RX MAC will strip the 
+                                                  last 4 bytes of a 
+                                                  received frame. */
+#define    MAC_RX_CFG_PROMISC_EN        0x0008  /* promiscuous mode */
+#define    MAC_RX_CFG_PROMISC_GROUP_EN  0x0010  /* accept all valid 
+                                                  multicast frames (group
+                                                  bit in DA field set) */
+#define    MAC_RX_CFG_HASH_FILTER_EN    0x0020  /* use hash table to filter
+                                                  multicast addresses */
+#define    MAC_RX_CFG_ADDR_FILTER_EN    0x0040  /* cause RX MAC to use 
+                                                  address filtering regs 
+                                                  to filter both unicast
+                                                  and multicast 
+                                                  addresses */
+#define    MAC_RX_CFG_DISABLE_DISCARD   0x0080  /* pass errored frames to
+                                                  RX DMA by setting BAD
+                                                  bit but not Abort bit
+                                                  in the status. CRC, 
+                                                  framing, and length errs
+                                                  will not increment 
+                                                  error counters. frames
+                                                  which don't match dest
+                                                  addr will be passed up
+                                                  w/ BAD bit set. */
+#define    MAC_RX_CFG_CARRIER_EXTEND    0x0100  /* enable reception of 
+                                                  packet bursts generated
+                                                  by carrier extension
+                                                  with packet bursting
+                                                  senders. only applies
+                                                  to half-duplex 1Gbps */
+
+/* DEFAULT: 0x0 */
+#define  REG_MAC_CTRL_CFG               0x6038  /* MAC control config reg */
+#define    MAC_CTRL_CFG_SEND_PAUSE_EN   0x0001  /* respond to requests for 
+                                                  sending pause flow ctrl 
+                                                  frames */
+#define    MAC_CTRL_CFG_RECV_PAUSE_EN   0x0002  /* respond to received 
+                                                  pause flow ctrl frames */
+#define    MAC_CTRL_CFG_PASS_CTRL       0x0004  /* pass valid MAC ctrl
+                                                  packets to RX DMA */
+
+/* to ensure proper operation, a global initialization sequence should be
+ * performed when a loopback config is entered or exited. if programmed after
+ * a hw or global sw reset, RX/TX MAC software reset and initialization 
+ * should be done to ensure stable clocking. 
+ * DEFAULT: 0x0
+ */
+#define  REG_MAC_XIF_CFG                0x603C  /* XIF config reg */
+#define    MAC_XIF_TX_MII_OUTPUT_EN        0x0001  /* enable output drivers
+                                                     on MII xmit bus */
+#define    MAC_XIF_MII_INT_LOOPBACK        0x0002  /* loopback GMII xmit data
+                                                     path to GMII recv data
+                                                     path. phy mode register
+                                                     clock selection must be
+                                                     set to GMII mode and 
+                                                     GMII_MODE should be set
+                                                     to 1. in loopback mode,
+                                                     REFCLK will drive the
+                                                     entire mac core. 0 for
+                                                     normal operation. */
+#define    MAC_XIF_DISABLE_ECHO            0x0004  /* disables receive data
+                                                     path during packet 
+                                                     xmission. clear to 0
+                                                     in any full duplex mode,
+                                                     in any loopback mode,
+                                                     or in half-duplex SERDES
+                                                     or SLINK modes. set when
+                                                     in half-duplex when 
+                                                     using external phy. */
+#define    MAC_XIF_GMII_MODE               0x0008  /* MAC operates with GMII
+                                                     clocks and datapath */
+#define    MAC_XIF_MII_BUFFER_OUTPUT_EN    0x0010  /* MII_BUF_EN pin. enable
+                                                     external tristate buffer
+                                                     on the MII receive 
+                                                     bus. */
+#define    MAC_XIF_LINK_LED                0x0020  /* LINKLED# active (low) */
+#define    MAC_XIF_FDPLX_LED               0x0040  /* FDPLXLED# active (low) */
+
+#define  REG_MAC_IPG0                      0x6040  /* inter-packet gap0 reg.
+                                                     recommended: 0x00 */
+#define  REG_MAC_IPG1                      0x6044  /* inter-packet gap1 reg
+                                                     recommended: 0x08 */
+#define  REG_MAC_IPG2                      0x6048  /* inter-packet gap2 reg
+                                                     recommended: 0x04 */
+#define  REG_MAC_SLOT_TIME                 0x604C  /* slot time reg
+                                                     recommended: 0x40 */
+#define  REG_MAC_FRAMESIZE_MIN             0x6050  /* min frame size reg 
+                                                     recommended: 0x40 */
+
+/* FRAMESIZE_MAX holds both the max frame size as well as the max burst size.
+ * recommended value:  0x2000.05EE
+ */
+#define  REG_MAC_FRAMESIZE_MAX             0x6054  /* max frame size reg */
+#define    MAC_FRAMESIZE_MAX_BURST_MASK    0x3FFF0000 /* max burst size */
+#define    MAC_FRAMESIZE_MAX_BURST_SHIFT   16
+#define    MAC_FRAMESIZE_MAX_FRAME_MASK    0x00007FFF /* max frame size */
+#define    MAC_FRAMESIZE_MAX_FRAME_SHIFT   0
+#define  REG_MAC_PA_SIZE                   0x6058  /* PA size reg. number of
+                                                     preamble bytes that the
+                                                     TX MAC will xmit at the
+                                                     beginning of each frame
+                                                     value should be 2 or 
+                                                     greater. recommended 
+                                                     value: 0x07 */
+#define  REG_MAC_JAM_SIZE                  0x605C  /* jam size reg. duration 
+                                                     of jam in units of media
+                                                     byte time. recommended
+                                                     value: 0x04 */
+#define  REG_MAC_ATTEMPT_LIMIT             0x6060  /* attempt limit reg. #
+                                                     of attempts TX MAC will
+                                                     make to xmit a frame 
+                                                     before it resets its
+                                                     attempts counter. after
+                                                     the limit has been 
+                                                     reached, TX MAC may or
+                                                     may not drop the frame
+                                                     dependent upon value
+                                                     in TX_MAC_CFG. 
+                                                     recommended 
+                                                     value: 0x10 */
+#define  REG_MAC_CTRL_TYPE                 0x6064  /* MAC control type reg.
+                                                     type field of a MAC 
+                                                     ctrl frame. recommended
+                                                     value: 0x8808 */
+
+/* mac address registers: 0 - 44, 0x6080 - 0x6130, 4 8-bit bytes.
+ * register           contains                   comparison  
+ *    0        16 MSB of primary MAC addr        [47:32] of DA field
+ *    1        16 middle bits ""                 [31:16] of DA field
+ *    2        16 LSB ""                         [15:0] of DA field
+ *    3*x      16MSB of alt MAC addr 1-15        [47:32] of DA field
+ *    4*x      16 middle bits ""                 [31:16]
+ *    5*x      16 LSB ""                         [15:0]
+ *    42       16 MSB of MAC CTRL addr           [47:32] of DA. 
+ *    43       16 middle bits ""                 [31:16]
+ *    44       16 LSB ""                         [15:0]
+ *    MAC CTRL addr must be the reserved multicast addr for MAC CTRL frames.
+ *    if there is a match, MAC will set the bit for alternative address
+ *    filter pass [15]
+
+ *    here is the map of registers given MAC address notation: a:b:c:d:e:f
+ *                     ab             cd             ef
+ *    primary addr     reg 2          reg 1          reg 0
+ *    alt addr 1       reg 5          reg 4          reg 3
+ *    alt addr x       reg 5*x        reg 4*x        reg 3*x
+ *    ctrl addr        reg 44         reg 43         reg 42
+ */
+#define  REG_MAC_ADDR0                     0x6080  /* MAC address 0 reg */
+#define  REG_MAC_ADDRN(x)                  (REG_MAC_ADDR0 + (x)*4)
+#define  REG_MAC_ADDR_FILTER0              0x614C  /* address filter 0 reg
+                                                     [47:32] */
+#define  REG_MAC_ADDR_FILTER1              0x6150  /* address filter 1 reg 
+                                                     [31:16] */
+#define  REG_MAC_ADDR_FILTER2              0x6154  /* address filter 2 reg 
+                                                     [15:0] */
+#define  REG_MAC_ADDR_FILTER2_1_MASK       0x6158  /* address filter 2 and 1
+                                                     mask reg. 8-bit reg
+                                                     contains nibble mask for
+                                                     reg 2 and 1. */
+#define  REG_MAC_ADDR_FILTER0_MASK         0x615C  /* address filter 0 mask 
+                                                     reg */
+
+/* hash table registers: 0 - 15, 0x6160 - 0x619C, 4 8-bit bytes 
+ * 16-bit registers contain bits of the hash table.
+ * reg x  -> [16*(15 - x) + 15 : 16*(15 - x)]. 
+ * e.g., 15 -> [15:0], 0 -> [255:240]
+ */
+#define  REG_MAC_HASH_TABLE0               0x6160  /* hash table 0 reg */
+#define  REG_MAC_HASH_TABLEN(x)            (REG_MAC_HASH_TABLE0 + (x)*4)
+
+/* statistics registers. these registers generate an interrupt on 
+ * overflow. recommended initialization: 0x0000. most are 16-bits except
+ * for PEAK_ATTEMPTS register which is 8 bits.
+ */
+#define  REG_MAC_COLL_NORMAL               0x61A0 /* normal collision 
+                                                    counter. */
+#define  REG_MAC_COLL_FIRST                0x61A4 /* first attempt
+                                                    successful collision 
+                                                    counter */
+#define  REG_MAC_COLL_EXCESS               0x61A8 /* excessive collision 
+                                                    counter */
+#define  REG_MAC_COLL_LATE                 0x61AC /* late collision counter */
+#define  REG_MAC_TIMER_DEFER               0x61B0 /* defer timer. time base 
+                                                    is the media byte 
+                                                    clock/256 */
+#define  REG_MAC_ATTEMPTS_PEAK             0x61B4 /* peak attempts reg */
+#define  REG_MAC_RECV_FRAME                0x61B8 /* receive frame counter */
+#define  REG_MAC_LEN_ERR                   0x61BC /* length error counter */
+#define  REG_MAC_ALIGN_ERR                 0x61C0 /* alignment error counter */
+#define  REG_MAC_FCS_ERR                   0x61C4 /* FCS error counter */
+#define  REG_MAC_RX_CODE_ERR               0x61C8 /* RX code violation
+                                                    error counter */
+
+/* misc registers */
+#define  REG_MAC_RANDOM_SEED               0x61CC /* random number seed reg.
+                                                  10-bit register used as a
+                                                  seed  for the random number
+                                                  generator for the CSMA/CD
+                                                  backoff algorithm. only 
+                                                  programmed after power-on
+                                                  reset and should be a 
+                                                  random value which has a 
+                                                  high likelihood of being 
+                                                  unique for each MAC 
+                                                  attached to a network 
+                                                  segment (e.g., 10 LSB of
+                                                  MAC address) */
+
+/* ASUN: there's a PAUSE_TIMER (ro) described, but it's not in the address
+ *       map
+ */
+
+/* 27-bit register has the current state for key state machines in the MAC */
+#define  REG_MAC_STATE_MACHINE             0x61D0 /* (ro) state machine reg */
+#define    MAC_SM_RLM_MASK                 0x07800000 
+#define    MAC_SM_RLM_SHIFT                23
+#define    MAC_SM_RX_FC_MASK               0x00700000
+#define    MAC_SM_RX_FC_SHIFT              20
+#define    MAC_SM_TLM_MASK                 0x000F0000
+#define    MAC_SM_TLM_SHIFT                16
+#define    MAC_SM_ENCAP_SM_MASK            0x0000F000
+#define    MAC_SM_ENCAP_SM_SHIFT           12
+#define    MAC_SM_TX_REQ_MASK              0x00000C00
+#define    MAC_SM_TX_REQ_SHIFT             10
+#define    MAC_SM_TX_FC_MASK               0x000003C0
+#define    MAC_SM_TX_FC_SHIFT              6
+#define    MAC_SM_FIFO_WRITE_SEL_MASK      0x00000038
+#define    MAC_SM_FIFO_WRITE_SEL_SHIFT     3
+#define    MAC_SM_TX_FIFO_EMPTY_MASK       0x00000007
+#define    MAC_SM_TX_FIFO_EMPTY_SHIFT      0
+
+/** MIF registers. the MIF can be programmed in either bit-bang or 
+ *  frame mode.
+ **/
+#define  REG_MIF_BIT_BANG_CLOCK            0x6200 /* MIF bit-bang clock.
+                                                  1 -> 0 will generate a 
+                                                  rising edge. 0 -> 1 will
+                                                  generate a falling edge. */
+#define  REG_MIF_BIT_BANG_DATA             0x6204 /* MIF bit-bang data. 1-bit
+                                                    register generates data */
+#define  REG_MIF_BIT_BANG_OUTPUT_EN        0x6208 /* MIF bit-bang output 
+                                                    enable. enable when 
+                                                    xmitting data from MIF to
+                                                    transceiver. */
+
+/* 32-bit register serves as an instruction register when the MIF is 
+ * programmed in frame mode. load this register w/ a valid instruction
+ * (as per IEEE 802.3u MII spec). poll this register to check for instruction
+ * execution completion. during a read operation, this register will also
+ * contain the 16-bit data returned by the tranceiver. unless specified 
+ * otherwise, fields are considered "don't care" when polling for 
+ * completion.
+ */
+#define  REG_MIF_FRAME                     0x620C /* MIF frame/output reg */
+#define    MIF_FRAME_START_MASK            0xC0000000 /* start of frame.
+                                                        load w/ 01 when
+                                                        issuing an instr */
+#define    MIF_FRAME_ST                    0x40000000 /* STart of frame */
+#define    MIF_FRAME_OPCODE_MASK           0x30000000 /* opcode. 01 for a 
+                                                        write. 10 for a 
+                                                        read */
+#define    MIF_FRAME_OP_READ               0x20000000 /* read OPcode */
+#define    MIF_FRAME_OP_WRITE              0x10000000 /* write OPcode */
+#define    MIF_FRAME_PHY_ADDR_MASK         0x0F800000 /* phy address. when
+                                                        issuing an instr,
+                                                        this field should be 
+                                                        loaded w/ the XCVR
+                                                        addr */
+#define    MIF_FRAME_PHY_ADDR_SHIFT        23
+#define    MIF_FRAME_REG_ADDR_MASK         0x007C0000 /* register address.
+                                                        when issuing an instr,
+                                                        addr of register
+                                                        to be read/written */
+#define    MIF_FRAME_REG_ADDR_SHIFT        18
+#define    MIF_FRAME_TURN_AROUND_MSB       0x00020000 /* turn around, MSB.
+                                                        when issuing an instr,
+                                                        set this bit to 1 */
+#define    MIF_FRAME_TURN_AROUND_LSB       0x00010000 /* turn around, LSB.
+                                                        when issuing an instr,
+                                                        set this bit to 0.
+                                                        when polling for
+                                                        completion, 1 means
+                                                        that instr execution
+                                                        has been completed */
+#define    MIF_FRAME_DATA_MASK             0x0000FFFF /* instruction payload
+                                                        load with 16-bit data
+                                                        to be written in
+                                                        transceiver reg for a
+                                                        write. doesn't matter
+                                                        in a read. when 
+                                                        polling for 
+                                                        completion, field is
+                                                        "don't care" for write
+                                                        and 16-bit data 
+                                                        returned by the 
+                                                        transceiver for a
+                                                        read (if valid bit
+                                                        is set) */
+#define  REG_MIF_CFG                    0x6210 /* MIF config reg */
+#define    MIF_CFG_PHY_SELECT           0x0001 /* 1 -> select MDIO_1
+                                                 0 -> select MDIO_0 */
+#define    MIF_CFG_POLL_EN              0x0002 /* enable polling
+                                                 mechanism. if set,
+                                                 BB_MODE should be 0 */
+#define    MIF_CFG_BB_MODE              0x0004 /* 1 -> bit-bang mode
+                                                 0 -> frame mode */
+#define    MIF_CFG_POLL_REG_MASK        0x00F8 /* register address to be
+                                                 used by polling mode.
+                                                 only meaningful if POLL_EN
+                                                 is set to 1 */
+#define    MIF_CFG_POLL_REG_SHIFT       3
+#define    MIF_CFG_MDIO_0               0x0100 /* (ro) dual purpose.
+                                                 when MDIO_0 is idle,
+                                                 1 -> tranceiver is 
+                                                 connected to MDIO_0.
+                                                 when MIF is communicating
+                                                 w/ MDIO_0 in bit-bang 
+                                                 mode, this bit indicates
+                                                 the incoming bit stream
+                                                 during a read op */
+#define    MIF_CFG_MDIO_1               0x0200 /* (ro) dual purpose.
+                                                 when MDIO_1 is idle, 
+                                                 1 -> transceiver is 
+                                                 connected to MDIO_1.
+                                                 when MIF is communicating
+                                                 w/ MDIO_1 in bit-bang
+                                                 mode, this bit indicates
+                                                 the incoming bit stream
+                                                 during a read op */
+#define    MIF_CFG_POLL_PHY_MASK        0x7C00 /* tranceiver address to
+                                                 be polled */
+#define    MIF_CFG_POLL_PHY_SHIFT       10
+
+/* 16-bit register used to determine which bits in the POLL_STATUS portion of
+ * the MIF_STATUS register will cause an interrupt. if a mask bit is 0,
+ * corresponding bit of the POLL_STATUS will generate a MIF interrupt when 
+ * set. DEFAULT: 0xFFFF
+ */
+#define  REG_MIF_MASK                      0x6214 /* MIF mask reg */
+
+/* 32-bit register used when in poll mode. auto-cleared after being read */
+#define  REG_MIF_STATUS                    0x6218 /* MIF status reg */
+#define    MIF_STATUS_POLL_DATA_MASK       0xFFFF0000 /* poll data contains
+                                                        the "latest image"
+                                                        update of the XCVR 
+                                                        reg being read */
+#define    MIF_STATUS_POLL_DATA_SHIFT      16
+#define    MIF_STATUS_POLL_STATUS_MASK     0x0000FFFF /* poll status indicates
+                                                        which bits in the
+                                                        POLL_DATA field have
+                                                        changed since the
+                                                        MIF_STATUS reg was
+                                                        last read */
+#define    MIF_STATUS_POLL_STATUS_SHIFT    0
+
+/* 7-bit register has current state for all state machines in the MIF */
+#define  REG_MIF_STATE_MACHINE             0x621C /* MIF state machine reg */
+#define    MIF_SM_CONTROL_MASK             0x07   /* control state machine 
+                                                    state */
+#define    MIF_SM_EXECUTION_MASK           0x60   /* execution state machine
+                                                    state */
+
+/** PCS/Serialink. the following registers are equivalent to the standard
+ *  MII management registers except that they're directly mapped in 
+ *  Cassini's register space.
+ **/
+
+/* the auto-negotiation enable bit should be programmed the same at
+ * the link partner as in the local device to enable auto-negotiation to
+ * complete. when that bit is reprogrammed, auto-neg/manual config is 
+ * restarted automatically.
+ * DEFAULT: 0x1040
+ */
+#define  REG_PCS_MII_CTRL                  0x9000 /* PCS MII control reg */
+#define    PCS_MII_CTRL_1000_SEL           0x0040 /* reads 1. ignored on
+                                                    writes */
+#define    PCS_MII_CTRL_COLLISION_TEST     0x0080 /* COL signal at the PCS
+                                                    to MAC interface is
+                                                    activated regardless
+                                                    of activity */
+#define    PCS_MII_CTRL_DUPLEX             0x0100 /* forced 0x0. PCS 
+                                                    behaviour same for
+                                                    half and full dplx */
+#define    PCS_MII_RESTART_AUTONEG         0x0200 /* self clearing. 
+                                                    restart auto-
+                                                    negotiation */
+#define    PCS_MII_ISOLATE                 0x0400 /* read as 0. ignored
+                                                    on writes */
+#define    PCS_MII_POWER_DOWN              0x0800 /* read as 0. ignored
+                                                    on writes */
+#define    PCS_MII_AUTONEG_EN              0x1000 /* default 1. PCS goes
+                                                    through automatic
+                                                    link config before it
+                                                    can be used. when 0,
+                                                    link can be used 
+                                                    w/out any link config
+                                                    phase */
+#define    PCS_MII_10_100_SEL              0x2000 /* read as 0. ignored on 
+                                                    writes */
+#define    PCS_MII_RESET                   0x8000 /* reset PCS. self-clears
+                                                    when done */
+
+/* DEFAULT: 0x0108 */
+#define  REG_PCS_MII_STATUS                0x9004 /* PCS MII status reg */
+#define    PCS_MII_STATUS_EXTEND_CAP       0x0001 /* reads 0 */
+#define    PCS_MII_STATUS_JABBER_DETECT    0x0002 /* reads 0 */
+#define    PCS_MII_STATUS_LINK_STATUS      0x0004 /* 1 -> link up. 
+                                                    0 -> link down. 0 is
+                                                    latched so that 0 is
+                                                    kept until read. read
+                                                    2x to determine if the
+                                                    link has gone up again */
+#define    PCS_MII_STATUS_AUTONEG_ABLE     0x0008 /* reads 1 (able to perform
+                                                    auto-neg) */
+#define    PCS_MII_STATUS_REMOTE_FAULT     0x0010 /* 1 -> remote fault detected
+                                                    from received link code
+                                                    word. only valid after
+                                                    auto-neg completed */
+#define    PCS_MII_STATUS_AUTONEG_COMP     0x0020 /* 1 -> auto-negotiation 
+                                                         completed
+                                                    0 -> auto-negotiation not
+                                                    completed */
+#define    PCS_MII_STATUS_EXTEND_STATUS    0x0100 /* reads as 1. used as an
+                                                    indication that this is
+                                                    a 1000 Base-X PHY. writes
+                                                    to it are ignored */
+
+/* used during auto-negotiation. 
+ * DEFAULT: 0x00E0
+ */
+#define  REG_PCS_MII_ADVERT                0x9008 /* PCS MII advertisement
+                                                    reg */
+#define    PCS_MII_ADVERT_FD               0x0020  /* advertise full duplex
+                                                     1000 Base-X */
+#define    PCS_MII_ADVERT_HD               0x0040  /* advertise half-duplex
+                                                     1000 Base-X */
+#define    PCS_MII_ADVERT_SYM_PAUSE        0x0080  /* advertise PAUSE
+                                                     symmetric capability */
+#define    PCS_MII_ADVERT_ASYM_PAUSE       0x0100  /* advertises PAUSE 
+                                                     asymmetric capability */
+#define    PCS_MII_ADVERT_RF_MASK          0x3000 /* remote fault. write bit13
+                                                    to optionally indicate to
+                                                    link partner that chip is
+                                                    going off-line. bit12 will
+                                                    get set when signal
+                                                    detect == FAIL and will
+                                                    remain set until 
+                                                    successful negotiation */
+#define    PCS_MII_ADVERT_ACK              0x4000 /* (ro) */
+#define    PCS_MII_ADVERT_NEXT_PAGE        0x8000 /* (ro) forced 0x0 */
+
+/* contents updated as a result of autonegotiation. layout and definitions
+ * identical to PCS_MII_ADVERT
+ */
+#define  REG_PCS_MII_LPA                   0x900C /* PCS MII link partner
+                                                    ability reg */
+#define    PCS_MII_LPA_FD             PCS_MII_ADVERT_FD
+#define    PCS_MII_LPA_HD             PCS_MII_ADVERT_HD
+#define    PCS_MII_LPA_SYM_PAUSE      PCS_MII_ADVERT_SYM_PAUSE
+#define    PCS_MII_LPA_ASYM_PAUSE     PCS_MII_ADVERT_ASYM_PAUSE
+#define    PCS_MII_LPA_RF_MASK        PCS_MII_ADVERT_RF_MASK
+#define    PCS_MII_LPA_ACK            PCS_MII_ADVERT_ACK
+#define    PCS_MII_LPA_NEXT_PAGE      PCS_MII_ADVERT_NEXT_PAGE
+
+/* DEFAULT: 0x0 */
+#define  REG_PCS_CFG                       0x9010 /* PCS config reg */
+#define    PCS_CFG_EN                      0x01   /* enable PCS. must be
+                                                    0 when modifying
+                                                    PCS_MII_ADVERT */
+#define    PCS_CFG_SD_OVERRIDE             0x02   /* sets signal detect to
+                                                    OK. bit is 
+                                                    non-resettable */
+#define    PCS_CFG_SD_ACTIVE_LOW           0x04   /* changes interpretation
+                                                    of optical signal to make
+                                                    signal detect okay when
+                                                    signal is low */
+#define    PCS_CFG_JITTER_STUDY_MASK       0x18   /* used to make jitter
+                                                    measurements. a single
+                                                    code group is xmitted
+                                                    regularly. 
+                                                    0x0 = normal operation
+                                                    0x1 = high freq test 
+                                                          pattern, D21.5
+                                                    0x2 = low freq test
+                                                          pattern, K28.7
+                                                    0x3 = reserved */
+#define    PCS_CFG_10MS_TIMER_OVERRIDE     0x20   /* shortens 10-20ms auto-
+                                                    negotiation timer to 
+                                                    a few cycles for test
+                                                    purposes */
+
+/* used for diagnostic purposes. bits 20-22 autoclear on read */
+#define  REG_PCS_STATE_MACHINE             0x9014 /* (ro) PCS state machine 
+                                                    and diagnostic reg */
+#define    PCS_SM_TX_STATE_MASK            0x0000000F /* 0 and 1 indicate 
+                                                        xmission of idle. 
+                                                        otherwise, xmission of
+                                                        a packet */
+#define    PCS_SM_RX_STATE_MASK            0x000000F0 /* 0 indicates reception
+                                                        of idle. otherwise,
+                                                        reception of packet */
+#define    PCS_SM_WORD_SYNC_STATE_MASK     0x00000700 /* 0 indicates loss of
+                                                        sync */
+#define    PCS_SM_SEQ_DETECT_STATE_MASK    0x00001800 /* cycling through 0-3
+                                                        indicates reception of
+                                                        Config codes. cycling
+                                                        through 0-1 indicates
+                                                        reception of idles */
+#define    PCS_SM_LINK_STATE_MASK          0x0001E000 
+#define        SM_LINK_STATE_UP            0x00016000 /* link state is up */
+
+#define    PCS_SM_LOSS_LINK_C              0x00100000 /* loss of link due to
+                                                        recept of Config 
+                                                        codes */
+#define    PCS_SM_LOSS_LINK_SYNC           0x00200000 /* loss of link due to
+                                                        loss of sync */
+#define    PCS_SM_LOSS_SIGNAL_DETECT       0x00400000 /* signal detect goes 
+                                                        from OK to FAIL. bit29
+                                                        will also be set if 
+                                                        this is set */
+#define    PCS_SM_NO_LINK_BREAKLINK        0x01000000 /* link not up due to
+                                                       receipt of breaklink
+                                                       C codes from partner.
+                                                       C codes w/ 0 content
+                                                       received triggering
+                                                       start/restart of 
+                                                       autonegotiation. 
+                                                       should be sent for
+                                                       no longer than 20ms */
+#define    PCS_SM_NO_LINK_SERDES           0x02000000 /* serdes being 
+                                                       initialized. see serdes
+                                                       state reg */
+#define    PCS_SM_NO_LINK_C                0x04000000 /* C codes not stable or
+                                                        not received */
+#define    PCS_SM_NO_LINK_SYNC             0x08000000 /* word sync not 
+                                                        achieved */
+#define    PCS_SM_NO_LINK_WAIT_C           0x10000000 /* waiting for C codes 
+                                                        w/ ack bit set */
+#define    PCS_SM_NO_LINK_NO_IDLE          0x20000000 /* link partner continues
+                                                        to send C codes 
+                                                        instead of idle 
+                                                        symbols or pkt data */
+
+/* this register indicates interrupt changes in specific PCS MII status bits.
+ * PCS_INT may be masked at the ISR level. only a single bit is implemented
+ * for link status change.
+ */
+#define  REG_PCS_INTR_STATUS               0x9018 /* PCS interrupt status */
+#define    PCS_INTR_STATUS_LINK_CHANGE     0x04   /* link status has changed
+                                                    since last read */
+
+/* control which network interface is used. no more than one bit should
+ * be set.
+ * DEFAULT: none
+ */
+#define  REG_PCS_DATAPATH_MODE             0x9050 /* datapath mode reg */
+#define    PCS_DATAPATH_MODE_MII           0x00 /* PCS is not used and 
+                                                  MII/GMII is selected. 
+                                                  selection between MII and
+                                                  GMII is controlled by 
+                                                  XIF_CFG */
+#define    PCS_DATAPATH_MODE_SERDES        0x02 /* PCS is used via the
+                                                  10-bit interface */
+
+/* input to serdes chip or serialink block */
+#define  REG_PCS_SERDES_CTRL              0x9054 /* serdes control reg */
+#define    PCS_SERDES_CTRL_LOOPBACK       0x01   /* enable loopback on 
+                                                   serdes interface */
+#define    PCS_SERDES_CTRL_SYNCD_EN       0x02   /* enable sync carrier
+                                                   detection. should be
+                                                   0x0 for normal 
+                                                   operation */
+#define    PCS_SERDES_CTRL_LOCKREF       0x04   /* frequency-lock RBC[0:1]
+                                                  to REFCLK when set.
+                                                  when clear, receiver
+                                                  clock locks to incoming
+                                                  serial data */
+
+/* multiplex test outputs into the PROM address (PA_3 through PA_0) pins.
+ * should be 0x0 for normal operations. 
+ * 0b000          normal operation, PROM address[3:0] selected
+ * 0b001          rxdma req, rxdma ack, rxdma ready, rxdma read 
+ * 0b010          rxmac req, rx ack, rx tag, rx clk shared 
+ * 0b011          txmac req, tx ack, tx tag, tx retry req 
+ * 0b100          tx tp3, tx tp2, tx tp1, tx tp0 
+ * 0b101          R period RX, R period TX, R period HP, R period BIM
+ * DEFAULT: 0x0
+ */
+#define  REG_PCS_SHARED_OUTPUT_SEL         0x9058 /* shared output select */
+#define    PCS_SOS_PROM_ADDR_MASK          0x0007
+
+/* used for diagnostics. this register indicates progress of the SERDES 
+ * boot up. 
+ * 0b00       undergoing reset
+ * 0b01       waiting 500us while lockrefn is asserted
+ * 0b10       waiting for comma detect
+ * 0b11       receive data is synchronized 
+ * DEFAULT: 0x0
+ */
+#define  REG_PCS_SERDES_STATE              0x905C /* (ro) serdes state */
+#define    PCS_SERDES_STATE_MASK           0x03   
+
+/* used for diagnostics. indicates number of packets transmitted or received.
+ * counters rollover w/out generating an interrupt.
+ * DEFAULT: 0x0
+ */
+#define  REG_PCS_PACKET_COUNT              0x9060 /* (ro) PCS packet counter */
+#define    PCS_PACKET_COUNT_TX             0x000007FF /* pkts xmitted by PCS */
+#define    PCS_PACKET_COUNT_RX             0x07FF0000 /* pkts recvd by PCS
+                                                        whether they 
+                                                        encountered an error
+                                                        or not */
+
+/** LocalBus Devices. the following provides run-time access to the 
+ *  Cassini's PROM
+ ***/
+#define  REG_EXPANSION_ROM_RUN_START       0x100000 /* expansion rom run time
+                                                      access */
+#define  REG_EXPANSION_ROM_RUN_END         0x17FFFF
+
+#define  REG_SECOND_LOCALBUS_START         0x180000 /* secondary local bus 
+                                                      device */
+#define  REG_SECOND_LOCALBUS_END           0x1FFFFF
+
+/* entropy device */
+#define  REG_ENTROPY_START                 REG_SECOND_LOCALBUS_START
+#define  REG_ENTROPY_DATA                  (REG_ENTROPY_START + 0x00)
+#define  REG_ENTROPY_STATUS                (REG_ENTROPY_START + 0x04)
+#define      ENTROPY_STATUS_DRDY           0x01
+#define      ENTROPY_STATUS_BUSY           0x02
+#define      ENTROPY_STATUS_CIPHER         0x04
+#define      ENTROPY_STATUS_BYPASS_MASK    0x18
+#define  REG_ENTROPY_MODE                  (REG_ENTROPY_START + 0x05)
+#define      ENTROPY_MODE_KEY_MASK         0x07
+#define      ENTROPY_MODE_ENCRYPT          0x40
+#define  REG_ENTROPY_RAND_REG              (REG_ENTROPY_START + 0x06)
+#define  REG_ENTROPY_RESET                 (REG_ENTROPY_START + 0x07)
+#define      ENTROPY_RESET_DES_IO          0x01
+#define      ENTROPY_RESET_STC_MODE        0x02
+#define      ENTROPY_RESET_KEY_CACHE       0x04
+#define      ENTROPY_RESET_IV              0x08
+#define  REG_ENTROPY_IV                    (REG_ENTROPY_START + 0x08)
+#define  REG_ENTROPY_KEY0                  (REG_ENTROPY_START + 0x10)
+#define  REG_ENTROPY_KEYN(x)               (REG_ENTROPY_KEY0 + 4*(x))
+
+/* phys of interest w/ their special mii registers */
+#define PHY_LUCENT_B0     0x00437421
+#define   LUCENT_MII_REG      0x1F
+
+#define PHY_NS_DP83065    0x20005c78
+#define   DP83065_MII_MEM     0x16
+#define   DP83065_MII_REGD    0x1D
+#define   DP83065_MII_REGE    0x1E
+
+#define PHY_BROADCOM_5411 0x00206071
+#define PHY_BROADCOM_B0   0x00206050
+#define   BROADCOM_MII_REG4   0x14
+#define   BROADCOM_MII_REG5   0x15
+#define   BROADCOM_MII_REG7   0x17
+#define   BROADCOM_MII_REG8   0x18
+
+#define   CAS_MII_ANNPTR          0x07
+#define   CAS_MII_ANNPRR          0x08
+#define   CAS_MII_1000_CTRL       0x09
+#define   CAS_MII_1000_STATUS     0x0A
+#define   CAS_MII_1000_EXTEND     0x0F
+
+#define   CAS_BMSR_1000_EXTEND    0x0100 /* supports 1000Base-T extended status */
+/* 
+ * if autoneg is disabled, here's the table:
+ * BMCR_SPEED100 = 100Mbps
+ * BMCR_SPEED1000 = 1000Mbps
+ * ~(BMCR_SPEED100 | BMCR_SPEED1000) = 10Mbps
+ */
+#define   CAS_BMCR_SPEED1000      0x0040  /* Select 1000Mbps */
+
+#define   CAS_ADVERTISE_1000HALF   0x0100
+#define   CAS_ADVERTISE_1000FULL   0x0200
+#define   CAS_ADVERTISE_PAUSE      0x0400
+#define   CAS_ADVERTISE_ASYM_PAUSE 0x0800
+
+/* regular lpa register */
+#define   CAS_LPA_PAUSE                   CAS_ADVERTISE_PAUSE
+#define   CAS_LPA_ASYM_PAUSE       CAS_ADVERTISE_ASYM_PAUSE
+
+/* 1000_STATUS register */
+#define   CAS_LPA_1000HALF        0x0400
+#define   CAS_LPA_1000FULL        0x0800
+
+#define   CAS_EXTEND_1000XFULL    0x8000
+#define   CAS_EXTEND_1000XHALF    0x4000
+#define   CAS_EXTEND_1000TFULL    0x2000
+#define   CAS_EXTEND_1000THALF    0x1000
+
+/* cassini header parser firmware */
+typedef struct cas_hp_inst {
+       const char *note;
+
+       u16 mask, val;
+
+       u8 op;
+       u8 soff, snext; /* if match succeeds, new offset and match */
+       u8 foff, fnext; /* if match fails, new offset and match */
+       /* output info */
+       u8 outop;    /* output opcode */
+
+       u16 outarg;  /* output argument */
+       u8 outenab;  /* output enable: 0 = not, 1 = if match
+                        2 = if !match, 3 = always */
+       u8 outshift; /* barrel shift right, 4 bits */
+       u16 outmask; 
+} cas_hp_inst_t;
+
+/* comparison */
+#define OP_EQ     0 /* packet == value */
+#define OP_LT     1 /* packet < value */
+#define OP_GT     2 /* packet > value */
+#define OP_NP     3 /* new packet */
+
+/* output opcodes */
+#define        CL_REG  0
+#define        LD_FID  1
+#define        LD_SEQ  2
+#define        LD_CTL  3
+#define        LD_SAP  4
+#define        LD_R1   5
+#define        LD_L3   6
+#define        LD_SUM  7
+#define        LD_HDR  8
+#define        IM_FID  9
+#define        IM_SEQ  10
+#define        IM_SAP  11
+#define        IM_R1   12
+#define        IM_CTL  13
+#define        LD_LEN  14
+#define        ST_FLG  15
+
+/* match setp #s for IP4TCP4 */
+#define S1_PCKT         0
+#define S1_VLAN         1
+#define S1_CFI          2
+#define S1_8023         3
+#define S1_LLC          4
+#define S1_LLCc         5
+#define S1_IPV4         6
+#define S1_IPV4c        7
+#define S1_IPV4F        8
+#define S1_TCP44        9
+#define S1_IPV6         10
+#define S1_IPV6L        11
+#define S1_IPV6c        12
+#define S1_TCP64        13
+#define S1_TCPSQ        14
+#define S1_TCPFG        15
+#define        S1_TCPHL        16
+#define        S1_TCPHc        17
+#define        S1_CLNP         18
+#define        S1_CLNP2        19
+#define        S1_DROP         20
+#define        S2_HTTP         21
+#define        S1_ESP4         22
+#define        S1_AH4          23
+#define        S1_ESP6         24
+#define        S1_AH6          25
+
+#define CAS_PROG_IP46TCP4_PREAMBLE \
+{ "packet arrival?", 0xffff, 0x0000, OP_NP,  6, S1_VLAN,  0, S1_PCKT,  \
+  CL_REG, 0x3ff, 1, 0x0, 0x0000}, \
+{ "VLAN?", 0xffff, 0x8100, OP_EQ,  1, S1_CFI,   0, S1_8023,  \
+  IM_CTL, 0x00a,  3, 0x0, 0xffff}, \
+{ "CFI?", 0x1000, 0x1000, OP_EQ,  0, S1_DROP,  1, S1_8023, \
+  CL_REG, 0x000,  0, 0x0, 0x0000}, \
+{ "8023?", 0xffff, 0x0600, OP_LT,  1, S1_LLC,   0, S1_IPV4, \
+  CL_REG, 0x000,  0, 0x0, 0x0000}, \
+{ "LLC?", 0xffff, 0xaaaa, OP_EQ,  1, S1_LLCc,  0, S1_CLNP, \
+  CL_REG, 0x000,  0, 0x0, 0x0000}, \
+{ "LLCc?", 0xff00, 0x0300, OP_EQ,  2, S1_IPV4,  0, S1_CLNP, \
+  CL_REG, 0x000,  0, 0x0, 0x0000}, \
+{ "IPV4?", 0xffff, 0x0800, OP_EQ,  1, S1_IPV4c, 0, S1_IPV6, \
+  LD_SAP, 0x100,  3, 0x0, 0xffff}, \
+{ "IPV4 cont?", 0xff00, 0x4500, OP_EQ,  3, S1_IPV4F, 0, S1_CLNP, \
+  LD_SUM, 0x00a,  1, 0x0, 0x0000}, \
+{ "IPV4 frag?", 0x3fff, 0x0000, OP_EQ,  1, S1_TCP44, 0, S1_CLNP, \
+  LD_LEN, 0x03e,  1, 0x0, 0xffff}, \
+{ "TCP44?", 0x00ff, 0x0006, OP_EQ,  7, S1_TCPSQ, 0, S1_CLNP, \
+  LD_FID, 0x182,  1, 0x0, 0xffff}, /* FID IP4&TCP src+dst */ \
+{ "IPV6?", 0xffff, 0x86dd, OP_EQ,  1, S1_IPV6L, 0, S1_CLNP,  \
+  LD_SUM, 0x015,  1, 0x0, 0x0000}, \
+{ "IPV6 len", 0xf000, 0x6000, OP_EQ,  0, S1_IPV6c, 0, S1_CLNP, \
+  IM_R1,  0x128,  1, 0x0, 0xffff}, \
+{ "IPV6 cont?", 0x0000, 0x0000, OP_EQ,  3, S1_TCP64, 0, S1_CLNP, \
+  LD_FID, 0x484,  1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */ \
+{ "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_CLNP, \
+  LD_LEN, 0x03f,  1, 0x0, 0xffff}
+
+#ifdef USE_HP_IP46TCP4
+static cas_hp_inst_t cas_prog_ip46tcp4tab[] = {
+       CAS_PROG_IP46TCP4_PREAMBLE, 
+       { "TCP seq", /* DADDR should point to dest port */ 
+         0x0000, 0x0000, OP_EQ, 0, S1_TCPFG, 4, S1_TCPFG, LD_SEQ, 
+         0x081,  3, 0x0, 0xffff}, /* Load TCP seq # */
+       { "TCP control flags", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHL, 0,
+         S1_TCPHL, ST_FLG, 0x045,  3, 0x0, 0x002f}, /* Load TCP flags */
+       { "TCP length", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHc, 0,
+         S1_TCPHc, LD_R1,  0x205,  3, 0xB, 0xf000},
+       { "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0,
+         S1_PCKT,  LD_HDR, 0x0ff,  3, 0x0, 0xffff},
+       { "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_CLNP2,  0, S1_CLNP2,
+         IM_CTL, 0x001,  3, 0x0, 0x0001},
+       { "Cleanup 2", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         IM_CTL, 0x000,  0, 0x0, 0x0000},
+       { "Drop packet", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         IM_CTL, 0x080,  3, 0x0, 0xffff},
+       { NULL },
+};
+#ifdef HP_IP46TCP4_DEFAULT
+#define CAS_HP_FIRMWARE               cas_prog_ip46tcp4tab
+#endif
+#endif
+
+/*
+ * Alternate table load which excludes HTTP server traffic from reassembly.
+ * It is substantially similar to the basic table, with one extra state
+ * and a few extra compares. */
+#ifdef USE_HP_IP46TCP4NOHTTP
+static cas_hp_inst_t cas_prog_ip46tcp4nohttptab[] = {
+       CAS_PROG_IP46TCP4_PREAMBLE,
+       { "TCP seq", /* DADDR should point to dest port */
+         0xFFFF, 0x0080, OP_EQ,  0, S2_HTTP,  0, S1_TCPFG, LD_SEQ, 
+         0x081,  3, 0x0, 0xffff} , /* Load TCP seq # */
+       { "TCP control flags", 0xFFFF, 0x8080, OP_EQ,  0, S2_HTTP,  0,
+         S1_TCPHL, ST_FLG, 0x145,  2, 0x0, 0x002f, }, /* Load TCP flags */
+       { "TCP length", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHc, 0, S1_TCPHc,
+         LD_R1,  0x205,  3, 0xB, 0xf000},
+       { "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         LD_HDR, 0x0ff,  3, 0x0, 0xffff},
+       { "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_CLNP2,  0, S1_CLNP2,
+         IM_CTL, 0x001,  3, 0x0, 0x0001},
+       { "Cleanup 2", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         CL_REG, 0x002,  3, 0x0, 0x0000},
+       { "Drop packet", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         IM_CTL, 0x080,  3, 0x0, 0xffff},
+       { "No HTTP", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         IM_CTL, 0x044,  3, 0x0, 0xffff},
+       { NULL },
+};
+#ifdef HP_IP46TCP4NOHTTP_DEFAULT
+#define CAS_HP_FIRMWARE               cas_prog_ip46tcp4nohttptab
+#endif
+#endif
+
+/* match step #s for IP4FRAG */
+#define        S3_IPV6c        11
+#define        S3_TCP64        12
+#define        S3_TCPSQ        13
+#define        S3_TCPFG        14
+#define        S3_TCPHL        15
+#define        S3_TCPHc        16
+#define        S3_FRAG         17
+#define        S3_FOFF         18
+#define        S3_CLNP         19
+
+#ifdef USE_HP_IP4FRAG
+static cas_hp_inst_t cas_prog_ip4fragtab[] = {
+       { "packet arrival?", 0xffff, 0x0000, OP_NP,  6, S1_VLAN,  0, S1_PCKT,
+         CL_REG, 0x3ff, 1, 0x0, 0x0000},
+       { "VLAN?", 0xffff, 0x8100, OP_EQ,  1, S1_CFI,   0, S1_8023,
+         IM_CTL, 0x00a,  3, 0x0, 0xffff},
+       { "CFI?", 0x1000, 0x1000, OP_EQ,  0, S3_CLNP,  1, S1_8023,
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "8023?", 0xffff, 0x0600, OP_LT,  1, S1_LLC,   0, S1_IPV4,
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "LLC?", 0xffff, 0xaaaa, OP_EQ,  1, S1_LLCc,  0, S3_CLNP,
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "LLCc?",0xff00, 0x0300, OP_EQ,  2, S1_IPV4,  0, S3_CLNP,
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "IPV4?", 0xffff, 0x0800, OP_EQ,  1, S1_IPV4c, 0, S1_IPV6,
+         LD_SAP, 0x100,  3, 0x0, 0xffff},
+       { "IPV4 cont?", 0xff00, 0x4500, OP_EQ,  3, S1_IPV4F, 0, S3_CLNP,
+         LD_SUM, 0x00a,  1, 0x0, 0x0000},
+       { "IPV4 frag?", 0x3fff, 0x0000, OP_EQ,  1, S1_TCP44, 0, S3_FRAG,
+         LD_LEN, 0x03e,  3, 0x0, 0xffff},
+       { "TCP44?", 0x00ff, 0x0006, OP_EQ,  7, S3_TCPSQ, 0, S3_CLNP,
+         LD_FID, 0x182,  3, 0x0, 0xffff}, /* FID IP4&TCP src+dst */
+       { "IPV6?", 0xffff, 0x86dd, OP_EQ,  1, S3_IPV6c, 0, S3_CLNP,
+         LD_SUM, 0x015,  1, 0x0, 0x0000},
+       { "IPV6 cont?", 0xf000, 0x6000, OP_EQ,  3, S3_TCP64, 0, S3_CLNP,
+         LD_FID, 0x484,  1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */
+       { "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S3_TCPSQ, 0, S3_CLNP,
+         LD_LEN, 0x03f,  1, 0x0, 0xffff},
+       { "TCP seq",    /* DADDR should point to dest port */
+         0x0000, 0x0000, OP_EQ,  0, S3_TCPFG, 4, S3_TCPFG, LD_SEQ,
+         0x081,  3, 0x0, 0xffff}, /* Load TCP seq # */
+       { "TCP control flags", 0x0000, 0x0000, OP_EQ,  0, S3_TCPHL, 0, 
+         S3_TCPHL, ST_FLG, 0x045,  3, 0x0, 0x002f}, /* Load TCP flags */
+       { "TCP length", 0x0000, 0x0000, OP_EQ,  0, S3_TCPHc, 0, S3_TCPHc,
+         LD_R1,  0x205,  3, 0xB, 0xf000},
+       { "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         LD_HDR, 0x0ff,  3, 0x0, 0xffff},
+       { "IP4 Fragment", 0x0000, 0x0000, OP_EQ,  0, S3_FOFF,  0, S3_FOFF,
+         LD_FID, 0x103,  3, 0x0, 0xffff}, /* FID IP4 src+dst */
+       { "IP4 frag offset", 0x0000, 0x0000, OP_EQ,  0, S3_FOFF,  0, S3_FOFF,
+         LD_SEQ, 0x040,  1, 0xD, 0xfff8},
+       { "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,  
+         IM_CTL, 0x001,  3, 0x0, 0x0001},
+       { NULL },
+};
+#ifdef HP_IP4FRAG_DEFAULT
+#define CAS_HP_FIRMWARE               cas_prog_ip4fragtab
+#endif
+#endif
+
+/*
+ * Alternate table which does batching without reassembly
+ */
+#ifdef USE_HP_IP46TCP4BATCH
+static cas_hp_inst_t cas_prog_ip46tcp4batchtab[] = {
+       CAS_PROG_IP46TCP4_PREAMBLE,
+       { "TCP seq",    /* DADDR should point to dest port */
+         0x0000, 0x0000, OP_EQ,  0, S1_TCPFG, 0, S1_TCPFG, LD_SEQ,
+         0x081,  3, 0x0, 0xffff}, /* Load TCP seq # */
+       { "TCP control flags", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHL, 0, 
+         S1_TCPHL, ST_FLG, 0x000,  3, 0x0, 0x0000}, /* Load TCP flags */
+       { "TCP length", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHc, 0, 
+         S1_TCPHc, LD_R1,  0x205,  3, 0xB, 0xf000},
+       { "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, 
+         S1_PCKT,  IM_CTL, 0x040,  3, 0x0, 0xffff}, /* set batch bit */
+       { "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         IM_CTL, 0x001,  3, 0x0, 0x0001},
+       { "Drop packet", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0,
+         S1_PCKT,  IM_CTL, 0x080,  3, 0x0, 0xffff},
+       { NULL },
+};
+#ifdef HP_IP46TCP4BATCH_DEFAULT
+#define CAS_HP_FIRMWARE               cas_prog_ip46tcp4batchtab
+#endif
+#endif
+
+/* Workaround for Cassini rev2 descriptor corruption problem.
+ * Does batching without reassembly, and sets the SAP to a known
+ * data pattern for all packets.
+ */
+#ifdef USE_HP_WORKAROUND
+static cas_hp_inst_t  cas_prog_workaroundtab[] = {
+       { "packet arrival?", 0xffff, 0x0000, OP_NP,  6, S1_VLAN,  0,
+         S1_PCKT,  CL_REG, 0x3ff,  1, 0x0, 0x0000} ,
+       { "VLAN?", 0xffff, 0x8100, OP_EQ,  1, S1_CFI, 0, S1_8023, 
+         IM_CTL, 0x04a,  3, 0x0, 0xffff},
+       { "CFI?", 0x1000, 0x1000, OP_EQ,  0, S1_CLNP,  1, S1_8023,
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "8023?", 0xffff, 0x0600, OP_LT,  1, S1_LLC,   0, S1_IPV4,
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "LLC?", 0xffff, 0xaaaa, OP_EQ,  1, S1_LLCc,  0, S1_CLNP,
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "LLCc?", 0xff00, 0x0300, OP_EQ,  2, S1_IPV4,  0, S1_CLNP,
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "IPV4?", 0xffff, 0x0800, OP_EQ,  1, S1_IPV4c, 0, S1_IPV6,
+         IM_SAP, 0x6AE,  3, 0x0, 0xffff},
+       { "IPV4 cont?", 0xff00, 0x4500, OP_EQ,  3, S1_IPV4F, 0, S1_CLNP,
+         LD_SUM, 0x00a,  1, 0x0, 0x0000},
+       { "IPV4 frag?", 0x3fff, 0x0000, OP_EQ,  1, S1_TCP44, 0, S1_CLNP,  
+         LD_LEN, 0x03e,  1, 0x0, 0xffff},
+       { "TCP44?", 0x00ff, 0x0006, OP_EQ,  7, S1_TCPSQ, 0, S1_CLNP,
+         LD_FID, 0x182,  3, 0x0, 0xffff}, /* FID IP4&TCP src+dst */
+       { "IPV6?", 0xffff, 0x86dd, OP_EQ,  1, S1_IPV6L, 0, S1_CLNP,
+         LD_SUM, 0x015,  1, 0x0, 0x0000},
+       { "IPV6 len", 0xf000, 0x6000, OP_EQ,  0, S1_IPV6c, 0, S1_CLNP,
+         IM_R1,  0x128,  1, 0x0, 0xffff},
+       { "IPV6 cont?", 0x0000, 0x0000, OP_EQ,  3, S1_TCP64, 0, S1_CLNP,
+         LD_FID, 0x484,  1, 0x0, 0xffff}, /* FID IP6&TCP src+dst */
+       { "TCP64?", 0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_CLNP,
+         LD_LEN, 0x03f,  1, 0x0, 0xffff},
+       { "TCP seq",      /* DADDR should point to dest port */
+         0x0000, 0x0000, OP_EQ,  0, S1_TCPFG, 4, S1_TCPFG, LD_SEQ, 
+         0x081,  3, 0x0, 0xffff}, /* Load TCP seq # */
+       { "TCP control flags", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHL, 0,
+         S1_TCPHL, ST_FLG, 0x045,  3, 0x0, 0x002f}, /* Load TCP flags */
+       { "TCP length", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHc, 0, S1_TCPHc,
+         LD_R1,  0x205,  3, 0xB, 0xf000},
+       { "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0,
+         S1_PCKT,  LD_HDR, 0x0ff,  3, 0x0, 0xffff},
+       { "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_CLNP2, 0, S1_CLNP2,
+         IM_SAP, 0x6AE,  3, 0x0, 0xffff} ,
+       { "Cleanup 2", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         IM_CTL, 0x001,  3, 0x0, 0x0001},
+       { NULL },
+};
+#ifdef HP_WORKAROUND_DEFAULT
+#define CAS_HP_FIRMWARE               cas_prog_workaroundtab
+#endif
+#endif
+
+#ifdef USE_HP_ENCRYPT
+static cas_hp_inst_t  cas_prog_encryptiontab[] = {
+       { "packet arrival?", 0xffff, 0x0000, OP_NP,  6, S1_VLAN,  0, 
+         S1_PCKT,  CL_REG, 0x3ff,  1, 0x0, 0x0000},
+       { "VLAN?", 0xffff, 0x8100, OP_EQ,  1, S1_CFI,   0, S1_8023,
+         IM_CTL, 0x00a,  3, 0x0, 0xffff},
+#if 0
+//"CFI?", /* 02 FIND CFI and If FIND go to S1_DROP */
+//0x1000, 0x1000, OP_EQ,  0, S1_DROP,  1, S1_8023,  CL_REG, 0x000,  0, 0x0, 0x00
+       00,
+#endif
+       { "CFI?", /* FIND CFI and If FIND go to CleanUP1 (ignore and send to host) */
+         0x1000, 0x1000, OP_EQ,  0, S1_CLNP,  1, S1_8023,  
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "8023?", 0xffff, 0x0600, OP_LT,  1, S1_LLC,   0, S1_IPV4, 
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "LLC?", 0xffff, 0xaaaa, OP_EQ,  1, S1_LLCc,  0, S1_CLNP, 
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "LLCc?", 0xff00, 0x0300, OP_EQ,  2, S1_IPV4,  0, S1_CLNP,
+         CL_REG, 0x000,  0, 0x0, 0x0000},
+       { "IPV4?", 0xffff, 0x0800, OP_EQ,  1, S1_IPV4c, 0, S1_IPV6,  
+         LD_SAP, 0x100,  3, 0x0, 0xffff},
+       { "IPV4 cont?", 0xff00, 0x4500, OP_EQ,  3, S1_IPV4F, 0, S1_CLNP,  
+         LD_SUM, 0x00a,  1, 0x0, 0x0000},
+       { "IPV4 frag?", 0x3fff, 0x0000, OP_EQ,  1, S1_TCP44, 0, S1_CLNP, 
+         LD_LEN, 0x03e,  1, 0x0, 0xffff},
+       { "TCP44?", 0x00ff, 0x0006, OP_EQ,  7, S1_TCPSQ, 0, S1_ESP4,
+         LD_FID, 0x182,  1, 0x0, 0xffff}, /* FID IP4&TCP src+dst */
+       { "IPV6?", 0xffff, 0x86dd, OP_EQ,  1, S1_IPV6L, 0, S1_CLNP,
+         LD_SUM, 0x015,  1, 0x0, 0x0000},
+       { "IPV6 len", 0xf000, 0x6000, OP_EQ,  0, S1_IPV6c, 0, S1_CLNP,
+         IM_R1,  0x128,  1, 0x0, 0xffff},
+       { "IPV6 cont?", 0x0000, 0x0000, OP_EQ,  3, S1_TCP64, 0, S1_CLNP, 
+         LD_FID, 0x484,  1, 0x0, 0xffff}, /*  FID IP6&TCP src+dst */
+       { "TCP64?", 
+#if 0
+//@@@0xff00, 0x0600, OP_EQ, 18, S1_TCPSQ, 0, S1_ESP6,  LD_LEN, 0x03f,  1, 0x0, 0xffff,
+#endif
+         0xff00, 0x0600, OP_EQ, 12, S1_TCPSQ, 0, S1_ESP6,  LD_LEN,
+         0x03f,  1, 0x0, 0xffff},
+       { "TCP seq", /* 14:DADDR should point to dest port */
+         0xFFFF, 0x0080, OP_EQ,  0, S2_HTTP,  0, S1_TCPFG, LD_SEQ,
+         0x081,  3, 0x0, 0xffff}, /* Load TCP seq # */
+       { "TCP control flags", 0xFFFF, 0x8080, OP_EQ,  0, S2_HTTP,  0,
+         S1_TCPHL, ST_FLG, 0x145,  2, 0x0, 0x002f}, /* Load TCP flags */
+       { "TCP length", 0x0000, 0x0000, OP_EQ,  0, S1_TCPHc, 0, S1_TCPHc, 
+         LD_R1,  0x205,  3, 0xB, 0xf000} ,
+       { "TCP length cont", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0,
+         S1_PCKT,  LD_HDR, 0x0ff,  3, 0x0, 0xffff}, 
+       { "Cleanup", 0x0000, 0x0000, OP_EQ,  0, S1_CLNP2,  0, S1_CLNP2,
+         IM_CTL, 0x001,  3, 0x0, 0x0001},
+       { "Cleanup 2", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         CL_REG, 0x002,  3, 0x0, 0x0000},
+       { "Drop packet", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         IM_CTL, 0x080,  3, 0x0, 0xffff},
+       { "No HTTP", 0x0000, 0x0000, OP_EQ,  0, S1_PCKT,  0, S1_PCKT,
+         IM_CTL, 0x044,  3, 0x0, 0xffff}, 
+       { "IPV4 ESP encrypted?",  /* S1_ESP4 */
+         0x00ff, 0x0032, OP_EQ,  0, S1_CLNP2, 0, S1_AH4, IM_CTL,
+         0x021, 1,  0x0, 0xffff},
+       { "IPV4 AH encrypted?",   /* S1_AH4 */
+         0x00ff, 0x0033, OP_EQ,  0, S1_CLNP2, 0, S1_CLNP, IM_CTL,
+         0x021, 1,  0x0, 0xffff},
+       { "IPV6 ESP encrypted?",  /* S1_ESP6 */
+#if 0
+//@@@0x00ff, 0x0032, OP_EQ,  0, S1_CLNP2, 0, S1_AH6, IM_CTL, 0x021, 1,  0x0, 0xffff,
+#endif
+         0xff00, 0x3200, OP_EQ,  0, S1_CLNP2, 0, S1_AH6, IM_CTL,
+         0x021, 1,  0x0, 0xffff},
+       { "IPV6 AH encrypted?",   /* S1_AH6 */
+#if 0
+//@@@0x00ff, 0x0033, OP_EQ,  0, S1_CLNP2, 0, S1_CLNP, IM_CTL, 0x021, 1,  0x0, 0xffff,
+#endif
+         0xff00, 0x3300, OP_EQ,  0, S1_CLNP2, 0, S1_CLNP, IM_CTL,
+         0x021, 1,  0x0, 0xffff},
+       { NULL },
+};
+#ifdef HP_ENCRYPT_DEFAULT
+#define CAS_HP_FIRMWARE               cas_prog_encryptiontab
+#endif
+#endif
+
+static cas_hp_inst_t cas_prog_null[] = { {NULL} };
+#ifdef HP_NULL_DEFAULT
+#define CAS_HP_FIRMWARE               cas_prog_null
+#endif
+
+/* firmware patch for NS_DP83065 */
+typedef struct cas_saturn_patch {
+       u16 addr;
+       u16 val;
+} cas_saturn_patch_t;
+
+#if 1
+cas_saturn_patch_t cas_saturn_patch[] = {
+{0x8200,    0x007e}, {0x8201,    0x0082}, {0x8202,    0x0009},
+{0x8203,    0x0000}, {0x8204,    0x0000}, {0x8205,    0x0000},
+{0x8206,    0x0000}, {0x8207,    0x0000}, {0x8208,    0x0000},
+{0x8209,    0x008e}, {0x820a,    0x008e}, {0x820b,    0x00ff},
+{0x820c,    0x00ce}, {0x820d,    0x0082}, {0x820e,    0x0025},
+{0x820f,    0x00ff}, {0x8210,    0x0001}, {0x8211,    0x000f},
+{0x8212,    0x00ce}, {0x8213,    0x0084}, {0x8214,    0x0026},
+{0x8215,    0x00ff}, {0x8216,    0x0001}, {0x8217,    0x0011},
+{0x8218,    0x00ce}, {0x8219,    0x0085}, {0x821a,    0x003d},
+{0x821b,    0x00df}, {0x821c,    0x00e5}, {0x821d,    0x0086},
+{0x821e,    0x0039}, {0x821f,    0x00b7}, {0x8220,    0x008f},
+{0x8221,    0x00f8}, {0x8222,    0x007e}, {0x8223,    0x00c3},
+{0x8224,    0x00c2}, {0x8225,    0x0096}, {0x8226,    0x0047},
+{0x8227,    0x0084}, {0x8228,    0x00f3}, {0x8229,    0x008a},
+{0x822a,    0x0000}, {0x822b,    0x0097}, {0x822c,    0x0047},
+{0x822d,    0x00ce}, {0x822e,    0x0082}, {0x822f,    0x0033},
+{0x8230,    0x00ff}, {0x8231,    0x0001}, {0x8232,    0x000f},
+{0x8233,    0x0096}, {0x8234,    0x0046}, {0x8235,    0x0084},
+{0x8236,    0x000c}, {0x8237,    0x0081}, {0x8238,    0x0004},
+{0x8239,    0x0027}, {0x823a,    0x000b}, {0x823b,    0x0096},
+{0x823c,    0x0046}, {0x823d,    0x0084}, {0x823e,    0x000c},
+{0x823f,    0x0081}, {0x8240,    0x0008}, {0x8241,    0x0027},
+{0x8242,    0x0057}, {0x8243,    0x007e}, {0x8244,    0x0084},
+{0x8245,    0x0025}, {0x8246,    0x0096}, {0x8247,    0x0047},
+{0x8248,    0x0084}, {0x8249,    0x00f3}, {0x824a,    0x008a},
+{0x824b,    0x0004}, {0x824c,    0x0097}, {0x824d,    0x0047},
+{0x824e,    0x00ce}, {0x824f,    0x0082}, {0x8250,    0x0054},
+{0x8251,    0x00ff}, {0x8252,    0x0001}, {0x8253,    0x000f},
+{0x8254,    0x0096}, {0x8255,    0x0046}, {0x8256,    0x0084},
+{0x8257,    0x000c}, {0x8258,    0x0081}, {0x8259,    0x0004},
+{0x825a,    0x0026}, {0x825b,    0x0038}, {0x825c,    0x00b6},
+{0x825d,    0x0012}, {0x825e,    0x0020}, {0x825f,    0x0084},
+{0x8260,    0x0020}, {0x8261,    0x0026}, {0x8262,    0x0003},
+{0x8263,    0x007e}, {0x8264,    0x0084}, {0x8265,    0x0025},
+{0x8266,    0x0096}, {0x8267,    0x007b}, {0x8268,    0x00d6},
+{0x8269,    0x007c}, {0x826a,    0x00fe}, {0x826b,    0x008f},
+{0x826c,    0x0056}, {0x826d,    0x00bd}, {0x826e,    0x00f7},
+{0x826f,    0x00b6}, {0x8270,    0x00fe}, {0x8271,    0x008f},
+{0x8272,    0x004e}, {0x8273,    0x00bd}, {0x8274,    0x00ec},
+{0x8275,    0x008e}, {0x8276,    0x00bd}, {0x8277,    0x00fa},
+{0x8278,    0x00f7}, {0x8279,    0x00bd}, {0x827a,    0x00f7},
+{0x827b,    0x0028}, {0x827c,    0x00ce}, {0x827d,    0x0082},
+{0x827e,    0x0082}, {0x827f,    0x00ff}, {0x8280,    0x0001},
+{0x8281,    0x000f}, {0x8282,    0x0096}, {0x8283,    0x0046},
+{0x8284,    0x0084}, {0x8285,    0x000c}, {0x8286,    0x0081},
+{0x8287,    0x0004}, {0x8288,    0x0026}, {0x8289,    0x000a},
+{0x828a,    0x00b6}, {0x828b,    0x0012}, {0x828c,    0x0020},
+{0x828d,    0x0084}, {0x828e,    0x0020}, {0x828f,    0x0027},
+{0x8290,    0x00b5}, {0x8291,    0x007e}, {0x8292,    0x0084},
+{0x8293,    0x0025}, {0x8294,    0x00bd}, {0x8295,    0x00f7},
+{0x8296,    0x001f}, {0x8297,    0x007e}, {0x8298,    0x0084},
+{0x8299,    0x001f}, {0x829a,    0x0096}, {0x829b,    0x0047},
+{0x829c,    0x0084}, {0x829d,    0x00f3}, {0x829e,    0x008a},
+{0x829f,    0x0008}, {0x82a0,    0x0097}, {0x82a1,    0x0047},
+{0x82a2,    0x00de}, {0x82a3,    0x00e1}, {0x82a4,    0x00ad},
+{0x82a5,    0x0000}, {0x82a6,    0x00ce}, {0x82a7,    0x0082},
+{0x82a8,    0x00af}, {0x82a9,    0x00ff}, {0x82aa,    0x0001},
+{0x82ab,    0x000f}, {0x82ac,    0x007e}, {0x82ad,    0x0084},
+{0x82ae,    0x0025}, {0x82af,    0x0096}, {0x82b0,    0x0041},
+{0x82b1,    0x0085}, {0x82b2,    0x0010}, {0x82b3,    0x0026},
+{0x82b4,    0x0006}, {0x82b5,    0x0096}, {0x82b6,    0x0023},
+{0x82b7,    0x0085}, {0x82b8,    0x0040}, {0x82b9,    0x0027},
+{0x82ba,    0x0006}, {0x82bb,    0x00bd}, {0x82bc,    0x00ed},
+{0x82bd,    0x0000}, {0x82be,    0x007e}, {0x82bf,    0x0083},
+{0x82c0,    0x00a2}, {0x82c1,    0x00de}, {0x82c2,    0x0042},
+{0x82c3,    0x00bd}, {0x82c4,    0x00eb}, {0x82c5,    0x008e},
+{0x82c6,    0x0096}, {0x82c7,    0x0024}, {0x82c8,    0x0084},
+{0x82c9,    0x0008}, {0x82ca,    0x0027}, {0x82cb,    0x0003},
+{0x82cc,    0x007e}, {0x82cd,    0x0083}, {0x82ce,    0x00df},
+{0x82cf,    0x0096}, {0x82d0,    0x007b}, {0x82d1,    0x00d6},
+{0x82d2,    0x007c}, {0x82d3,    0x00fe}, {0x82d4,    0x008f},
+{0x82d5,    0x0056}, {0x82d6,    0x00bd}, {0x82d7,    0x00f7},
+{0x82d8,    0x00b6}, {0x82d9,    0x00fe}, {0x82da,    0x008f},
+{0x82db,    0x0050}, {0x82dc,    0x00bd}, {0x82dd,    0x00ec},
+{0x82de,    0x008e}, {0x82df,    0x00bd}, {0x82e0,    0x00fa},
+{0x82e1,    0x00f7}, {0x82e2,    0x0086}, {0x82e3,    0x0011},
+{0x82e4,    0x00c6}, {0x82e5,    0x0049}, {0x82e6,    0x00bd},
+{0x82e7,    0x00e4}, {0x82e8,    0x0012}, {0x82e9,    0x00ce},
+{0x82ea,    0x0082}, {0x82eb,    0x00ef}, {0x82ec,    0x00ff},
+{0x82ed,    0x0001}, {0x82ee,    0x000f}, {0x82ef,    0x0096},
+{0x82f0,    0x0046}, {0x82f1,    0x0084}, {0x82f2,    0x000c},
+{0x82f3,    0x0081}, {0x82f4,    0x0000}, {0x82f5,    0x0027},
+{0x82f6,    0x0017}, {0x82f7,    0x00c6}, {0x82f8,    0x0049},
+{0x82f9,    0x00bd}, {0x82fa,    0x00e4}, {0x82fb,    0x0091},
+{0x82fc,    0x0024}, {0x82fd,    0x000d}, {0x82fe,    0x00b6},
+{0x82ff,    0x0012}, {0x8300,    0x0020}, {0x8301,    0x0085},
+{0x8302,    0x0020}, {0x8303,    0x0026}, {0x8304,    0x000c},
+{0x8305,    0x00ce}, {0x8306,    0x0082}, {0x8307,    0x00c1},
+{0x8308,    0x00ff}, {0x8309,    0x0001}, {0x830a,    0x000f},
+{0x830b,    0x007e}, {0x830c,    0x0084}, {0x830d,    0x0025},
+{0x830e,    0x007e}, {0x830f,    0x0084}, {0x8310,    0x0016},
+{0x8311,    0x00fe}, {0x8312,    0x008f}, {0x8313,    0x0052},
+{0x8314,    0x00bd}, {0x8315,    0x00ec}, {0x8316,    0x008e},
+{0x8317,    0x00bd}, {0x8318,    0x00fa}, {0x8319,    0x00f7},
+{0x831a,    0x0086}, {0x831b,    0x006a}, {0x831c,    0x00c6},
+{0x831d,    0x0049}, {0x831e,    0x00bd}, {0x831f,    0x00e4},
+{0x8320,    0x0012}, {0x8321,    0x00ce}, {0x8322,    0x0083},
+{0x8323,    0x0027}, {0x8324,    0x00ff}, {0x8325,    0x0001},
+{0x8326,    0x000f}, {0x8327,    0x0096}, {0x8328,    0x0046},
+{0x8329,    0x0084}, {0x832a,    0x000c}, {0x832b,    0x0081},
+{0x832c,    0x0000}, {0x832d,    0x0027}, {0x832e,    0x000a},
+{0x832f,    0x00c6}, {0x8330,    0x0049}, {0x8331,    0x00bd},
+{0x8332,    0x00e4}, {0x8333,    0x0091}, {0x8334,    0x0025},
+{0x8335,    0x0006}, {0x8336,    0x007e}, {0x8337,    0x0084},
+{0x8338,    0x0025}, {0x8339,    0x007e}, {0x833a,    0x0084},
+{0x833b,    0x0016}, {0x833c,    0x00b6}, {0x833d,    0x0018},
+{0x833e,    0x0070}, {0x833f,    0x00bb}, {0x8340,    0x0019},
+{0x8341,    0x0070}, {0x8342,    0x002a}, {0x8343,    0x0004},
+{0x8344,    0x0081}, {0x8345,    0x00af}, {0x8346,    0x002e},
+{0x8347,    0x0019}, {0x8348,    0x0096}, {0x8349,    0x007b},
+{0x834a,    0x00f6}, {0x834b,    0x0020}, {0x834c,    0x0007},
+{0x834d,    0x00fa}, {0x834e,    0x0020}, {0x834f,    0x0027},
+{0x8350,    0x00c4}, {0x8351,    0x0038}, {0x8352,    0x0081},
+{0x8353,    0x0038}, {0x8354,    0x0027}, {0x8355,    0x000b},
+{0x8356,    0x00f6}, {0x8357,    0x0020}, {0x8358,    0x0007},
+{0x8359,    0x00fa}, {0x835a,    0x0020}, {0x835b,    0x0027},
+{0x835c,    0x00cb}, {0x835d,    0x0008}, {0x835e,    0x007e},
+{0x835f,    0x0082}, {0x8360,    0x00d3}, {0x8361,    0x00bd},
+{0x8362,    0x00f7}, {0x8363,    0x0066}, {0x8364,    0x0086},
+{0x8365,    0x0074}, {0x8366,    0x00c6}, {0x8367,    0x0049},
+{0x8368,    0x00bd}, {0x8369,    0x00e4}, {0x836a,    0x0012},
+{0x836b,    0x00ce}, {0x836c,    0x0083}, {0x836d,    0x0071},
+{0x836e,    0x00ff}, {0x836f,    0x0001}, {0x8370,    0x000f},
+{0x8371,    0x0096}, {0x8372,    0x0046}, {0x8373,    0x0084},
+{0x8374,    0x000c}, {0x8375,    0x0081}, {0x8376,    0x0008},
+{0x8377,    0x0026}, {0x8378,    0x000a}, {0x8379,    0x00c6},
+{0x837a,    0x0049}, {0x837b,    0x00bd}, {0x837c,    0x00e4},
+{0x837d,    0x0091}, {0x837e,    0x0025}, {0x837f,    0x0006},
+{0x8380,    0x007e}, {0x8381,    0x0084}, {0x8382,    0x0025},
+{0x8383,    0x007e}, {0x8384,    0x0084}, {0x8385,    0x0016},
+{0x8386,    0x00bd}, {0x8387,    0x00f7}, {0x8388,    0x003e},
+{0x8389,    0x0026}, {0x838a,    0x000e}, {0x838b,    0x00bd},
+{0x838c,    0x00e5}, {0x838d,    0x0009}, {0x838e,    0x0026},
+{0x838f,    0x0006}, {0x8390,    0x00ce}, {0x8391,    0x0082},
+{0x8392,    0x00c1}, {0x8393,    0x00ff}, {0x8394,    0x0001},
+{0x8395,    0x000f}, {0x8396,    0x007e}, {0x8397,    0x0084},
+{0x8398,    0x0025}, {0x8399,    0x00fe}, {0x839a,    0x008f},
+{0x839b,    0x0054}, {0x839c,    0x00bd}, {0x839d,    0x00ec},
+{0x839e,    0x008e}, {0x839f,    0x00bd}, {0x83a0,    0x00fa},
+{0x83a1,    0x00f7}, {0x83a2,    0x00bd}, {0x83a3,    0x00f7},
+{0x83a4,    0x0033}, {0x83a5,    0x0086}, {0x83a6,    0x000f},
+{0x83a7,    0x00c6}, {0x83a8,    0x0051}, {0x83a9,    0x00bd},
+{0x83aa,    0x00e4}, {0x83ab,    0x0012}, {0x83ac,    0x00ce},
+{0x83ad,    0x0083}, {0x83ae,    0x00b2}, {0x83af,    0x00ff},
+{0x83b0,    0x0001}, {0x83b1,    0x000f}, {0x83b2,    0x0096},
+{0x83b3,    0x0046}, {0x83b4,    0x0084}, {0x83b5,    0x000c},
+{0x83b6,    0x0081}, {0x83b7,    0x0008}, {0x83b8,    0x0026},
+{0x83b9,    0x005c}, {0x83ba,    0x00b6}, {0x83bb,    0x0012},
+{0x83bc,    0x0020}, {0x83bd,    0x0084}, {0x83be,    0x003f},
+{0x83bf,    0x0081}, {0x83c0,    0x003a}, {0x83c1,    0x0027},
+{0x83c2,    0x001c}, {0x83c3,    0x0096}, {0x83c4,    0x0023},
+{0x83c5,    0x0085}, {0x83c6,    0x0040}, {0x83c7,    0x0027},
+{0x83c8,    0x0003}, {0x83c9,    0x007e}, {0x83ca,    0x0084},
+{0x83cb,    0x0025}, {0x83cc,    0x00c6}, {0x83cd,    0x0051},
+{0x83ce,    0x00bd}, {0x83cf,    0x00e4}, {0x83d0,    0x0091},
+{0x83d1,    0x0025}, {0x83d2,    0x0003}, {0x83d3,    0x007e},
+{0x83d4,    0x0084}, {0x83d5,    0x0025}, {0x83d6,    0x00ce},
+{0x83d7,    0x0082}, {0x83d8,    0x00c1}, {0x83d9,    0x00ff},
+{0x83da,    0x0001}, {0x83db,    0x000f}, {0x83dc,    0x007e},
+{0x83dd,    0x0084}, {0x83de,    0x0025}, {0x83df,    0x00bd},
+{0x83e0,    0x00f8}, {0x83e1,    0x0037}, {0x83e2,    0x007c},
+{0x83e3,    0x0000}, {0x83e4,    0x007a}, {0x83e5,    0x00ce},
+{0x83e6,    0x0083}, {0x83e7,    0x00ee}, {0x83e8,    0x00ff},
+{0x83e9,    0x0001}, {0x83ea,    0x000f}, {0x83eb,    0x007e},
+{0x83ec,    0x0084}, {0x83ed,    0x0025}, {0x83ee,    0x0096},
+{0x83ef,    0x0046}, {0x83f0,    0x0084}, {0x83f1,    0x000c},
+{0x83f2,    0x0081}, {0x83f3,    0x0008}, {0x83f4,    0x0026},
+{0x83f5,    0x0020}, {0x83f6,    0x0096}, {0x83f7,    0x0024},
+{0x83f8,    0x0084}, {0x83f9,    0x0008}, {0x83fa,    0x0026},
+{0x83fb,    0x0029}, {0x83fc,    0x00b6}, {0x83fd,    0x0018},
+{0x83fe,    0x0082}, {0x83ff,    0x00bb}, {0x8400,    0x0019},
+{0x8401,    0x0082}, {0x8402,    0x00b1}, {0x8403,    0x0001},
+{0x8404,    0x003b}, {0x8405,    0x0022}, {0x8406,    0x0009},
+{0x8407,    0x00b6}, {0x8408,    0x0012}, {0x8409,    0x0020},
+{0x840a,    0x0084}, {0x840b,    0x0037}, {0x840c,    0x0081},
+{0x840d,    0x0032}, {0x840e,    0x0027}, {0x840f,    0x0015},
+{0x8410,    0x00bd}, {0x8411,    0x00f8}, {0x8412,    0x0044},
+{0x8413,    0x007e}, {0x8414,    0x0082}, {0x8415,    0x00c1},
+{0x8416,    0x00bd}, {0x8417,    0x00f7}, {0x8418,    0x001f},
+{0x8419,    0x00bd}, {0x841a,    0x00f8}, {0x841b,    0x0044},
+{0x841c,    0x00bd}, {0x841d,    0x00fc}, {0x841e,    0x0029},
+{0x841f,    0x00ce}, {0x8420,    0x0082}, {0x8421,    0x0025},
+{0x8422,    0x00ff}, {0x8423,    0x0001}, {0x8424,    0x000f},
+{0x8425,    0x0039}, {0x8426,    0x0096}, {0x8427,    0x0047},
+{0x8428,    0x0084}, {0x8429,    0x00fc}, {0x842a,    0x008a},
+{0x842b,    0x0000}, {0x842c,    0x0097}, {0x842d,    0x0047},
+{0x842e,    0x00ce}, {0x842f,    0x0084}, {0x8430,    0x0034},
+{0x8431,    0x00ff}, {0x8432,    0x0001}, {0x8433,    0x0011},
+{0x8434,    0x0096}, {0x8435,    0x0046}, {0x8436,    0x0084},
+{0x8437,    0x0003}, {0x8438,    0x0081}, {0x8439,    0x0002},
+{0x843a,    0x0027}, {0x843b,    0x0003}, {0x843c,    0x007e},
+{0x843d,    0x0085}, {0x843e,    0x001e}, {0x843f,    0x0096},
+{0x8440,    0x0047}, {0x8441,    0x0084}, {0x8442,    0x00fc},
+{0x8443,    0x008a}, {0x8444,    0x0002}, {0x8445,    0x0097},
+{0x8446,    0x0047}, {0x8447,    0x00de}, {0x8448,    0x00e1},
+{0x8449,    0x00ad}, {0x844a,    0x0000}, {0x844b,    0x0086},
+{0x844c,    0x0001}, {0x844d,    0x00b7}, {0x844e,    0x0012},
+{0x844f,    0x0051}, {0x8450,    0x00bd}, {0x8451,    0x00f7},
+{0x8452,    0x0014}, {0x8453,    0x00b6}, {0x8454,    0x0010},
+{0x8455,    0x0031}, {0x8456,    0x0084}, {0x8457,    0x00fd},
+{0x8458,    0x00b7}, {0x8459,    0x0010}, {0x845a,    0x0031},
+{0x845b,    0x00bd}, {0x845c,    0x00f8}, {0x845d,    0x001e},
+{0x845e,    0x0096}, {0x845f,    0x0081}, {0x8460,    0x00d6},
+{0x8461,    0x0082}, {0x8462,    0x00fe}, {0x8463,    0x008f},
+{0x8464,    0x005a}, {0x8465,    0x00bd}, {0x8466,    0x00f7},
+{0x8467,    0x00b6}, {0x8468,    0x00fe}, {0x8469,    0x008f},
+{0x846a,    0x005c}, {0x846b,    0x00bd}, {0x846c,    0x00ec},
+{0x846d,    0x008e}, {0x846e,    0x00bd}, {0x846f,    0x00fa},
+{0x8470,    0x00f7}, {0x8471,    0x0086}, {0x8472,    0x0008},
+{0x8473,    0x00d6}, {0x8474,    0x0000}, {0x8475,    0x00c5},
+{0x8476,    0x0010}, {0x8477,    0x0026}, {0x8478,    0x0002},
+{0x8479,    0x008b}, {0x847a,    0x0020}, {0x847b,    0x00c6},
+{0x847c,    0x0051}, {0x847d,    0x00bd}, {0x847e,    0x00e4},
+{0x847f,    0x0012}, {0x8480,    0x00ce}, {0x8481,    0x0084},
+{0x8482,    0x0086}, {0x8483,    0x00ff}, {0x8484,    0x0001},
+{0x8485,    0x0011}, {0x8486,    0x0096}, {0x8487,    0x0046},
+{0x8488,    0x0084}, {0x8489,    0x0003}, {0x848a,    0x0081},
+{0x848b,    0x0002}, {0x848c,    0x0027}, {0x848d,    0x0003},
+{0x848e,    0x007e}, {0x848f,    0x0085}, {0x8490,    0x000f},
+{0x8491,    0x00c6}, {0x8492,    0x0051}, {0x8493,    0x00bd},
+{0x8494,    0x00e4}, {0x8495,    0x0091}, {0x8496,    0x0025},
+{0x8497,    0x0003}, {0x8498,    0x007e}, {0x8499,    0x0085},
+{0x849a,    0x001e}, {0x849b,    0x0096}, {0x849c,    0x0044},
+{0x849d,    0x0085}, {0x849e,    0x0010}, {0x849f,    0x0026},
+{0x84a0,    0x000a}, {0x84a1,    0x00b6}, {0x84a2,    0x0012},
+{0x84a3,    0x0050}, {0x84a4,    0x00ba}, {0x84a5,    0x0001},
+{0x84a6,    0x003c}, {0x84a7,    0x0085}, {0x84a8,    0x0010},
+{0x84a9,    0x0027}, {0x84aa,    0x00a8}, {0x84ab,    0x00bd},
+{0x84ac,    0x00f7}, {0x84ad,    0x0066}, {0x84ae,    0x00ce},
+{0x84af,    0x0084}, {0x84b0,    0x00b7}, {0x84b1,    0x00ff},
+{0x84b2,    0x0001}, {0x84b3,    0x0011}, {0x84b4,    0x007e},
+{0x84b5,    0x0085}, {0x84b6,    0x001e}, {0x84b7,    0x0096},
+{0x84b8,    0x0046}, {0x84b9,    0x0084}, {0x84ba,    0x0003},
+{0x84bb,    0x0081}, {0x84bc,    0x0002}, {0x84bd,    0x0026},
+{0x84be,    0x0050}, {0x84bf,    0x00b6}, {0x84c0,    0x0012},
+{0x84c1,    0x0030}, {0x84c2,    0x0084}, {0x84c3,    0x0003},
+{0x84c4,    0x0081}, {0x84c5,    0x0001}, {0x84c6,    0x0027},
+{0x84c7,    0x0003}, {0x84c8,    0x007e}, {0x84c9,    0x0085},
+{0x84ca,    0x001e}, {0x84cb,    0x0096}, {0x84cc,    0x0044},
+{0x84cd,    0x0085}, {0x84ce,    0x0010}, {0x84cf,    0x0026},
+{0x84d0,    0x0013}, {0x84d1,    0x00b6}, {0x84d2,    0x0012},
+{0x84d3,    0x0050}, {0x84d4,    0x00ba}, {0x84d5,    0x0001},
+{0x84d6,    0x003c}, {0x84d7,    0x0085}, {0x84d8,    0x0010},
+{0x84d9,    0x0026}, {0x84da,    0x0009}, {0x84db,    0x00ce},
+{0x84dc,    0x0084}, {0x84dd,    0x0053}, {0x84de,    0x00ff},
+{0x84df,    0x0001}, {0x84e0,    0x0011}, {0x84e1,    0x007e},
+{0x84e2,    0x0085}, {0x84e3,    0x001e}, {0x84e4,    0x00b6},
+{0x84e5,    0x0010}, {0x84e6,    0x0031}, {0x84e7,    0x008a},
+{0x84e8,    0x0002}, {0x84e9,    0x00b7}, {0x84ea,    0x0010},
+{0x84eb,    0x0031}, {0x84ec,    0x00bd}, {0x84ed,    0x0085},
+{0x84ee,    0x001f}, {0x84ef,    0x00bd}, {0x84f0,    0x00f8},
+{0x84f1,    0x0037}, {0x84f2,    0x007c}, {0x84f3,    0x0000},
+{0x84f4,    0x0080}, {0x84f5,    0x00ce}, {0x84f6,    0x0084},
+{0x84f7,    0x00fe}, {0x84f8,    0x00ff}, {0x84f9,    0x0001},
+{0x84fa,    0x0011}, {0x84fb,    0x007e}, {0x84fc,    0x0085},
+{0x84fd,    0x001e}, {0x84fe,    0x0096}, {0x84ff,    0x0046},
+{0x8500,    0x0084}, {0x8501,    0x0003}, {0x8502,    0x0081},
+{0x8503,    0x0002}, {0x8504,    0x0026}, {0x8505,    0x0009},
+{0x8506,    0x00b6}, {0x8507,    0x0012}, {0x8508,    0x0030},
+{0x8509,    0x0084}, {0x850a,    0x0003}, {0x850b,    0x0081},
+{0x850c,    0x0001}, {0x850d,    0x0027}, {0x850e,    0x000f},
+{0x850f,    0x00bd}, {0x8510,    0x00f8}, {0x8511,    0x0044},
+{0x8512,    0x00bd}, {0x8513,    0x00f7}, {0x8514,    0x000b},
+{0x8515,    0x00bd}, {0x8516,    0x00fc}, {0x8517,    0x0029},
+{0x8518,    0x00ce}, {0x8519,    0x0084}, {0x851a,    0x0026},
+{0x851b,    0x00ff}, {0x851c,    0x0001}, {0x851d,    0x0011},
+{0x851e,    0x0039}, {0x851f,    0x00d6}, {0x8520,    0x0022},
+{0x8521,    0x00c4}, {0x8522,    0x000f}, {0x8523,    0x00b6},
+{0x8524,    0x0012}, {0x8525,    0x0030}, {0x8526,    0x00ba},
+{0x8527,    0x0012}, {0x8528,    0x0032}, {0x8529,    0x0084},
+{0x852a,    0x0004}, {0x852b,    0x0027}, {0x852c,    0x000d},
+{0x852d,    0x0096}, {0x852e,    0x0022}, {0x852f,    0x0085},
+{0x8530,    0x0004}, {0x8531,    0x0027}, {0x8532,    0x0005},
+{0x8533,    0x00ca}, {0x8534,    0x0010}, {0x8535,    0x007e},
+{0x8536,    0x0085}, {0x8537,    0x003a}, {0x8538,    0x00ca},
+{0x8539,    0x0020}, {0x853a,    0x00d7}, {0x853b,    0x0022},
+{0x853c,    0x0039}, {0x853d,    0x0086}, {0x853e,    0x0000},
+{0x853f,    0x0097}, {0x8540,    0x0083}, {0x8541,    0x0018},
+{0x8542,    0x00ce}, {0x8543,    0x001c}, {0x8544,    0x0000},
+{0x8545,    0x00bd}, {0x8546,    0x00eb}, {0x8547,    0x0046},
+{0x8548,    0x0096}, {0x8549,    0x0057}, {0x854a,    0x0085},
+{0x854b,    0x0001}, {0x854c,    0x0027}, {0x854d,    0x0002},
+{0x854e,    0x004f}, {0x854f,    0x0039}, {0x8550,    0x0085},
+{0x8551,    0x0002}, {0x8552,    0x0027}, {0x8553,    0x0001},
+{0x8554,    0x0039}, {0x8555,    0x007f}, {0x8556,    0x008f},
+{0x8557,    0x007d}, {0x8558,    0x0086}, {0x8559,    0x0004},
+{0x855a,    0x00b7}, {0x855b,    0x0012}, {0x855c,    0x0004},
+{0x855d,    0x0086}, {0x855e,    0x0008}, {0x855f,    0x00b7},
+{0x8560,    0x0012}, {0x8561,    0x0007}, {0x8562,    0x0086},
+{0x8563,    0x0010}, {0x8564,    0x00b7}, {0x8565,    0x0012},
+{0x8566,    0x000c}, {0x8567,    0x0086}, {0x8568,    0x0007},
+{0x8569,    0x00b7}, {0x856a,    0x0012}, {0x856b,    0x0006},
+{0x856c,    0x00b6}, {0x856d,    0x008f}, {0x856e,    0x007d},
+{0x856f,    0x00b7}, {0x8570,    0x0012}, {0x8571,    0x0070},
+{0x8572,    0x0086}, {0x8573,    0x0001}, {0x8574,    0x00ba},
+{0x8575,    0x0012}, {0x8576,    0x0004}, {0x8577,    0x00b7},
+{0x8578,    0x0012}, {0x8579,    0x0004}, {0x857a,    0x0001},
+{0x857b,    0x0001}, {0x857c,    0x0001}, {0x857d,    0x0001},
+{0x857e,    0x0001}, {0x857f,    0x0001}, {0x8580,    0x00b6},
+{0x8581,    0x0012}, {0x8582,    0x0004}, {0x8583,    0x0084},
+{0x8584,    0x00fe}, {0x8585,    0x008a}, {0x8586,    0x0002},
+{0x8587,    0x00b7}, {0x8588,    0x0012}, {0x8589,    0x0004},
+{0x858a,    0x0001}, {0x858b,    0x0001}, {0x858c,    0x0001},
+{0x858d,    0x0001}, {0x858e,    0x0001}, {0x858f,    0x0001},
+{0x8590,    0x0086}, {0x8591,    0x00fd}, {0x8592,    0x00b4},
+{0x8593,    0x0012}, {0x8594,    0x0004}, {0x8595,    0x00b7},
+{0x8596,    0x0012}, {0x8597,    0x0004}, {0x8598,    0x00b6},
+{0x8599,    0x0012}, {0x859a,    0x0000}, {0x859b,    0x0084},
+{0x859c,    0x0008}, {0x859d,    0x0081}, {0x859e,    0x0008},
+{0x859f,    0x0027}, {0x85a0,    0x0016}, {0x85a1,    0x00b6},
+{0x85a2,    0x008f}, {0x85a3,    0x007d}, {0x85a4,    0x0081},
+{0x85a5,    0x000c}, {0x85a6,    0x0027}, {0x85a7,    0x0008},
+{0x85a8,    0x008b}, {0x85a9,    0x0004}, {0x85aa,    0x00b7},
+{0x85ab,    0x008f}, {0x85ac,    0x007d}, {0x85ad,    0x007e},
+{0x85ae,    0x0085}, {0x85af,    0x006c}, {0x85b0,    0x0086},
+{0x85b1,    0x0003}, {0x85b2,    0x0097}, {0x85b3,    0x0040},
+{0x85b4,    0x007e}, {0x85b5,    0x0089}, {0x85b6,    0x006e},
+{0x85b7,    0x0086}, {0x85b8,    0x0007}, {0x85b9,    0x00b7},
+{0x85ba,    0x0012}, {0x85bb,    0x0006}, {0x85bc,    0x005f},
+{0x85bd,    0x00f7}, {0x85be,    0x008f}, {0x85bf,    0x0082},
+{0x85c0,    0x005f}, {0x85c1,    0x00f7}, {0x85c2,    0x008f},
+{0x85c3,    0x007f}, {0x85c4,    0x00f7}, {0x85c5,    0x008f},
+{0x85c6,    0x0070}, {0x85c7,    0x00f7}, {0x85c8,    0x008f},
+{0x85c9,    0x0071}, {0x85ca,    0x00f7}, {0x85cb,    0x008f},
+{0x85cc,    0x0072}, {0x85cd,    0x00f7}, {0x85ce,    0x008f},
+{0x85cf,    0x0073}, {0x85d0,    0x00f7}, {0x85d1,    0x008f},
+{0x85d2,    0x0074}, {0x85d3,    0x00f7}, {0x85d4,    0x008f},
+{0x85d5,    0x0075}, {0x85d6,    0x00f7}, {0x85d7,    0x008f},
+{0x85d8,    0x0076}, {0x85d9,    0x00f7}, {0x85da,    0x008f},
+{0x85db,    0x0077}, {0x85dc,    0x00f7}, {0x85dd,    0x008f},
+{0x85de,    0x0078}, {0x85df,    0x00f7}, {0x85e0,    0x008f},
+{0x85e1,    0x0079}, {0x85e2,    0x00f7}, {0x85e3,    0x008f},
+{0x85e4,    0x007a}, {0x85e5,    0x00f7}, {0x85e6,    0x008f},
+{0x85e7,    0x007b}, {0x85e8,    0x00b6}, {0x85e9,    0x0012},
+{0x85ea,    0x0004}, {0x85eb,    0x008a}, {0x85ec,    0x0010},
+{0x85ed,    0x00b7}, {0x85ee,    0x0012}, {0x85ef,    0x0004},
+{0x85f0,    0x0086}, {0x85f1,    0x00e4}, {0x85f2,    0x00b7},
+{0x85f3,    0x0012}, {0x85f4,    0x0070}, {0x85f5,    0x00b7},
+{0x85f6,    0x0012}, {0x85f7,    0x0007}, {0x85f8,    0x00f7},
+{0x85f9,    0x0012}, {0x85fa,    0x0005}, {0x85fb,    0x00f7},
+{0x85fc,    0x0012}, {0x85fd,    0x0009}, {0x85fe,    0x0086},
+{0x85ff,    0x0008}, {0x8600,    0x00ba}, {0x8601,    0x0012},
+{0x8602,    0x0004}, {0x8603,    0x00b7}, {0x8604,    0x0012},
+{0x8605,    0x0004}, {0x8606,    0x0086}, {0x8607,    0x00f7},
+{0x8608,    0x00b4}, {0x8609,    0x0012}, {0x860a,    0x0004},
+{0x860b,    0x00b7}, {0x860c,    0x0012}, {0x860d,    0x0004},
+{0x860e,    0x0001}, {0x860f,    0x0001}, {0x8610,    0x0001},
+{0x8611,    0x0001}, {0x8612,    0x0001}, {0x8613,    0x0001},
+{0x8614,    0x00b6}, {0x8615,    0x0012}, {0x8616,    0x0008},
+{0x8617,    0x0027}, {0x8618,    0x007f}, {0x8619,    0x0081},
+{0x861a,    0x0080}, {0x861b,    0x0026}, {0x861c,    0x000b},
+{0x861d,    0x0086}, {0x861e,    0x0008}, {0x861f,    0x00ce},
+{0x8620,    0x008f}, {0x8621,    0x0079}, {0x8622,    0x00bd},
+{0x8623,    0x0089}, {0x8624,    0x007b}, {0x8625,    0x007e},
+{0x8626,    0x0086}, {0x8627,    0x008e}, {0x8628,    0x0081},
+{0x8629,    0x0040}, {0x862a,    0x0026}, {0x862b,    0x000b},
+{0x862c,    0x0086}, {0x862d,    0x0004}, {0x862e,    0x00ce},
+{0x862f,    0x008f}, {0x8630,    0x0076}, {0x8631,    0x00bd},
+{0x8632,    0x0089}, {0x8633,    0x007b}, {0x8634,    0x007e},
+{0x8635,    0x0086}, {0x8636,    0x008e}, {0x8637,    0x0081},
+{0x8638,    0x0020}, {0x8639,    0x0026}, {0x863a,    0x000b},
+{0x863b,    0x0086}, {0x863c,    0x0002}, {0x863d,    0x00ce},
+{0x863e,    0x008f}, {0x863f,    0x0073}, {0x8640,    0x00bd},
+{0x8641,    0x0089}, {0x8642,    0x007b}, {0x8643,    0x007e},
+{0x8644,    0x0086}, {0x8645,    0x008e}, {0x8646,    0x0081},
+{0x8647,    0x0010}, {0x8648,    0x0026}, {0x8649,    0x000b},
+{0x864a,    0x0086}, {0x864b,    0x0001}, {0x864c,    0x00ce},
+{0x864d,    0x008f}, {0x864e,    0x0070}, {0x864f,    0x00bd},
+{0x8650,    0x0089}, {0x8651,    0x007b}, {0x8652,    0x007e},
+{0x8653,    0x0086}, {0x8654,    0x008e}, {0x8655,    0x0081},
+{0x8656,    0x0008}, {0x8657,    0x0026}, {0x8658,    0x000b},
+{0x8659,    0x0086}, {0x865a,    0x0008}, {0x865b,    0x00ce},
+{0x865c,    0x008f}, {0x865d,    0x0079}, {0x865e,    0x00bd},
+{0x865f,    0x0089}, {0x8660,    0x007f}, {0x8661,    0x007e},
+{0x8662,    0x0086}, {0x8663,    0x008e}, {0x8664,    0x0081},
+{0x8665,    0x0004}, {0x8666,    0x0026}, {0x8667,    0x000b},
+{0x8668,    0x0086}, {0x8669,    0x0004}, {0x866a,    0x00ce},
+{0x866b,    0x008f}, {0x866c,    0x0076}, {0x866d,    0x00bd},
+{0x866e,    0x0089}, {0x866f,    0x007f}, {0x8670,    0x007e},
+{0x8671,    0x0086}, {0x8672,    0x008e}, {0x8673,    0x0081},
+{0x8674,    0x0002}, {0x8675,    0x0026}, {0x8676,    0x000b},
+{0x8677,    0x008a}, {0x8678,    0x0002}, {0x8679,    0x00ce},
+{0x867a,    0x008f}, {0x867b,    0x0073}, {0x867c,    0x00bd},
+{0x867d,    0x0089}, {0x867e,    0x007f}, {0x867f,    0x007e},
+{0x8680,    0x0086}, {0x8681,    0x008e}, {0x8682,    0x0081},
+{0x8683,    0x0001}, {0x8684,    0x0026}, {0x8685,    0x0008},
+{0x8686,    0x0086}, {0x8687,    0x0001}, {0x8688,    0x00ce},
+{0x8689,    0x008f}, {0x868a,    0x0070}, {0x868b,    0x00bd},
+{0x868c,    0x0089}, {0x868d,    0x007f}, {0x868e,    0x00b6},
+{0x868f,    0x008f}, {0x8690,    0x007f}, {0x8691,    0x0081},
+{0x8692,    0x000f}, {0x8693,    0x0026}, {0x8694,    0x0003},
+{0x8695,    0x007e}, {0x8696,    0x0087}, {0x8697,    0x0047},
+{0x8698,    0x00b6}, {0x8699,    0x0012}, {0x869a,    0x0009},
+{0x869b,    0x0084}, {0x869c,    0x0003}, {0x869d,    0x0081},
+{0x869e,    0x0003}, {0x869f,    0x0027}, {0x86a0,    0x0006},
+{0x86a1,    0x007c}, {0x86a2,    0x0012}, {0x86a3,    0x0009},
+{0x86a4,    0x007e}, {0x86a5,    0x0085}, {0x86a6,    0x00fe},
+{0x86a7,    0x00b6}, {0x86a8,    0x0012}, {0x86a9,    0x0006},
+{0x86aa,    0x0084}, {0x86ab,    0x0007}, {0x86ac,    0x0081},
+{0x86ad,    0x0007}, {0x86ae,    0x0027}, {0x86af,    0x0008},
+{0x86b0,    0x008b}, {0x86b1,    0x0001}, {0x86b2,    0x00b7},
+{0x86b3,    0x0012}, {0x86b4,    0x0006}, {0x86b5,    0x007e},
+{0x86b6,    0x0086}, {0x86b7,    0x00d5}, {0x86b8,    0x00b6},
+{0x86b9,    0x008f}, {0x86ba,    0x0082}, {0x86bb,    0x0026},
+{0x86bc,    0x000a}, {0x86bd,    0x007c}, {0x86be,    0x008f},
+{0x86bf,    0x0082}, {0x86c0,    0x004f}, {0x86c1,    0x00b7},
+{0x86c2,    0x0012}, {0x86c3,    0x0006}, {0x86c4,    0x007e},
+{0x86c5,    0x0085}, {0x86c6,    0x00c0}, {0x86c7,    0x00b6},
+{0x86c8,    0x0012}, {0x86c9,    0x0006}, {0x86ca,    0x0084},
+{0x86cb,    0x003f}, {0x86cc,    0x0081}, {0x86cd,    0x003f},
+{0x86ce,    0x0027}, {0x86cf,    0x0010}, {0x86d0,    0x008b},
+{0x86d1,    0x0008}, {0x86d2,    0x00b7}, {0x86d3,    0x0012},
+{0x86d4,    0x0006}, {0x86d5,    0x00b6}, {0x86d6,    0x0012},
+{0x86d7,    0x0009}, {0x86d8,    0x0084}, {0x86d9,    0x00fc},
+{0x86da,    0x00b7}, {0x86db,    0x0012}, {0x86dc,    0x0009},
+{0x86dd,    0x007e}, {0x86de,    0x0085}, {0x86df,    0x00fe},
+{0x86e0,    0x00ce}, {0x86e1,    0x008f}, {0x86e2,    0x0070},
+{0x86e3,    0x0018}, {0x86e4,    0x00ce}, {0x86e5,    0x008f},
+{0x86e6,    0x0084}, {0x86e7,    0x00c6}, {0x86e8,    0x000c},
+{0x86e9,    0x00bd}, {0x86ea,    0x0089}, {0x86eb,    0x006f},
+{0x86ec,    0x00ce}, {0x86ed,    0x008f}, {0x86ee,    0x0084},
+{0x86ef,    0x0018}, {0x86f0,    0x00ce}, {0x86f1,    0x008f},
+{0x86f2,    0x0070}, {0x86f3,    0x00c6}, {0x86f4,    0x000c},
+{0x86f5,    0x00bd}, {0x86f6,    0x0089}, {0x86f7,    0x006f},
+{0x86f8,    0x00d6}, {0x86f9,    0x0083}, {0x86fa,    0x00c1},
+{0x86fb,    0x004f}, {0x86fc,    0x002d}, {0x86fd,    0x0003},
+{0x86fe,    0x007e}, {0x86ff,    0x0087}, {0x8700,    0x0040},
+{0x8701,    0x00b6}, {0x8702,    0x008f}, {0x8703,    0x007f},
+{0x8704,    0x0081}, {0x8705,    0x0007}, {0x8706,    0x0027},
+{0x8707,    0x000f}, {0x8708,    0x0081}, {0x8709,    0x000b},
+{0x870a,    0x0027}, {0x870b,    0x0015}, {0x870c,    0x0081},
+{0x870d,    0x000d}, {0x870e,    0x0027}, {0x870f,    0x001b},
+{0x8710,    0x0081}, {0x8711,    0x000e}, {0x8712,    0x0027},
+{0x8713,    0x0021}, {0x8714,    0x007e}, {0x8715,    0x0087},
+{0x8716,    0x0040}, {0x8717,    0x00f7}, {0x8718,    0x008f},
+{0x8719,    0x007b}, {0x871a,    0x0086}, {0x871b,    0x0002},
+{0x871c,    0x00b7}, {0x871d,    0x008f}, {0x871e,    0x007a},
+{0x871f,    0x0020}, {0x8720,    0x001c}, {0x8721,    0x00f7},
+{0x8722,    0x008f}, {0x8723,    0x0078}, {0x8724,    0x0086},
+{0x8725,    0x0002}, {0x8726,    0x00b7}, {0x8727,    0x008f},
+{0x8728,    0x0077}, {0x8729,    0x0020}, {0x872a,    0x0012},
+{0x872b,    0x00f7}, {0x872c,    0x008f}, {0x872d,    0x0075},
+{0x872e,    0x0086}, {0x872f,    0x0002}, {0x8730,    0x00b7},
+{0x8731,    0x008f}, {0x8732,    0x0074}, {0x8733,    0x0020},
+{0x8734,    0x0008}, {0x8735,    0x00f7}, {0x8736,    0x008f},
+{0x8737,    0x0072}, {0x8738,    0x0086}, {0x8739,    0x0002},
+{0x873a,    0x00b7}, {0x873b,    0x008f}, {0x873c,    0x0071},
+{0x873d,    0x007e}, {0x873e,    0x0087}, {0x873f,    0x0047},
+{0x8740,    0x0086}, {0x8741,    0x0004}, {0x8742,    0x0097},
+{0x8743,    0x0040}, {0x8744,    0x007e}, {0x8745,    0x0089},
+{0x8746,    0x006e}, {0x8747,    0x00ce}, {0x8748,    0x008f},
+{0x8749,    0x0072}, {0x874a,    0x00bd}, {0x874b,    0x0089},
+{0x874c,    0x00f7}, {0x874d,    0x00ce}, {0x874e,    0x008f},
+{0x874f,    0x0075}, {0x8750,    0x00bd}, {0x8751,    0x0089},
+{0x8752,    0x00f7}, {0x8753,    0x00ce}, {0x8754,    0x008f},
+{0x8755,    0x0078}, {0x8756,    0x00bd}, {0x8757,    0x0089},
+{0x8758,    0x00f7}, {0x8759,    0x00ce}, {0x875a,    0x008f},
+{0x875b,    0x007b}, {0x875c,    0x00bd}, {0x875d,    0x0089},
+{0x875e,    0x00f7}, {0x875f,    0x004f}, {0x8760,    0x00b7},
+{0x8761,    0x008f}, {0x8762,    0x007d}, {0x8763,    0x00b7},
+{0x8764,    0x008f}, {0x8765,    0x0081}, {0x8766,    0x00b6},
+{0x8767,    0x008f}, {0x8768,    0x0072}, {0x8769,    0x0027},
+{0x876a,    0x0047}, {0x876b,    0x007c}, {0x876c,    0x008f},
+{0x876d,    0x007d}, {0x876e,    0x00b6}, {0x876f,    0x008f},
+{0x8770,    0x0075}, {0x8771,    0x0027}, {0x8772,    0x003f},
+{0x8773,    0x007c}, {0x8774,    0x008f}, {0x8775,    0x007d},
+{0x8776,    0x00b6}, {0x8777,    0x008f}, {0x8778,    0x0078},
+{0x8779,    0x0027}, {0x877a,    0x0037}, {0x877b,    0x007c},
+{0x877c,    0x008f}, {0x877d,    0x007d}, {0x877e,    0x00b6},
+{0x877f,    0x008f}, {0x8780,    0x007b}, {0x8781,    0x0027},
+{0x8782,    0x002f}, {0x8783,    0x007f}, {0x8784,    0x008f},
+{0x8785,    0x007d}, {0x8786,    0x007c}, {0x8787,    0x008f},
+{0x8788,    0x0081}, {0x8789,    0x007a}, {0x878a,    0x008f},
+{0x878b,    0x0072}, {0x878c,    0x0027}, {0x878d,    0x001b},
+{0x878e,    0x007c}, {0x878f,    0x008f}, {0x8790,    0x007d},
+{0x8791,    0x007a}, {0x8792,    0x008f}, {0x8793,    0x0075},
+{0x8794,    0x0027}, {0x8795,    0x0016}, {0x8796,    0x007c},
+{0x8797,    0x008f}, {0x8798,    0x007d}, {0x8799,    0x007a},
+{0x879a,    0x008f}, {0x879b,    0x0078}, {0x879c,    0x0027},
+{0x879d,    0x0011}, {0x879e,    0x007c}, {0x879f,    0x008f},
+{0x87a0,    0x007d}, {0x87a1,    0x007a}, {0x87a2,    0x008f},
+{0x87a3,    0x007b}, {0x87a4,    0x0027}, {0x87a5,    0x000c},
+{0x87a6,    0x007e}, {0x87a7,    0x0087}, {0x87a8,    0x0083},
+{0x87a9,    0x007a}, {0x87aa,    0x008f}, {0x87ab,    0x0075},
+{0x87ac,    0x007a}, {0x87ad,    0x008f}, {0x87ae,    0x0078},
+{0x87af,    0x007a}, {0x87b0,    0x008f}, {0x87b1,    0x007b},
+{0x87b2,    0x00ce}, {0x87b3,    0x00c1}, {0x87b4,    0x00fc},
+{0x87b5,    0x00f6}, {0x87b6,    0x008f}, {0x87b7,    0x007d},
+{0x87b8,    0x003a}, {0x87b9,    0x00a6}, {0x87ba,    0x0000},
+{0x87bb,    0x00b7}, {0x87bc,    0x0012}, {0x87bd,    0x0070},
+{0x87be,    0x00b6}, {0x87bf,    0x008f}, {0x87c0,    0x0072},
+{0x87c1,    0x0026}, {0x87c2,    0x0003}, {0x87c3,    0x007e},
+{0x87c4,    0x0087}, {0x87c5,    0x00fa}, {0x87c6,    0x00b6},
+{0x87c7,    0x008f}, {0x87c8,    0x0075}, {0x87c9,    0x0026},
+{0x87ca,    0x000a}, {0x87cb,    0x0018}, {0x87cc,    0x00ce},
+{0x87cd,    0x008f}, {0x87ce,    0x0073}, {0x87cf,    0x00bd},
+{0x87d0,    0x0089}, {0x87d1,    0x00d5}, {0x87d2,    0x007e},
+{0x87d3,    0x0087}, {0x87d4,    0x00fa}, {0x87d5,    0x00b6},
+{0x87d6,    0x008f}, {0x87d7,    0x0078}, {0x87d8,    0x0026},
+{0x87d9,    0x000a}, {0x87da,    0x0018}, {0x87db,    0x00ce},
+{0x87dc,    0x008f}, {0x87dd,    0x0076}, {0x87de,    0x00bd},
+{0x87df,    0x0089}, {0x87e0,    0x00d5}, {0x87e1,    0x007e},
+{0x87e2,    0x0087}, {0x87e3,    0x00fa}, {0x87e4,    0x00b6},
+{0x87e5,    0x008f}, {0x87e6,    0x007b}, {0x87e7,    0x0026},
+{0x87e8,    0x000a}, {0x87e9,    0x0018}, {0x87ea,    0x00ce},
+{0x87eb,    0x008f}, {0x87ec,    0x0079}, {0x87ed,    0x00bd},
+{0x87ee,    0x0089}, {0x87ef,    0x00d5}, {0x87f0,    0x007e},
+{0x87f1,    0x0087}, {0x87f2,    0x00fa}, {0x87f3,    0x0086},
+{0x87f4,    0x0005}, {0x87f5,    0x0097}, {0x87f6,    0x0040},
+{0x87f7,    0x007e}, {0x87f8,    0x0089}, {0x87f9,    0x0000},
+{0x87fa,    0x00b6}, {0x87fb,    0x008f}, {0x87fc,    0x0075},
+{0x87fd,    0x0081}, {0x87fe,    0x0007}, {0x87ff,    0x002e},
+{0x8800,    0x00f2}, {0x8801,    0x00f6}, {0x8802,    0x0012},
+{0x8803,    0x0006}, {0x8804,    0x00c4}, {0x8805,    0x00f8},
+{0x8806,    0x001b}, {0x8807,    0x00b7}, {0x8808,    0x0012},
+{0x8809,    0x0006}, {0x880a,    0x00b6}, {0x880b,    0x008f},
+{0x880c,    0x0078}, {0x880d,    0x0081}, {0x880e,    0x0007},
+{0x880f,    0x002e}, {0x8810,    0x00e2}, {0x8811,    0x0048},
+{0x8812,    0x0048}, {0x8813,    0x0048}, {0x8814,    0x00f6},
+{0x8815,    0x0012}, {0x8816,    0x0006}, {0x8817,    0x00c4},
+{0x8818,    0x00c7}, {0x8819,    0x001b}, {0x881a,    0x00b7},
+{0x881b,    0x0012}, {0x881c,    0x0006}, {0x881d,    0x00b6},
+{0x881e,    0x008f}, {0x881f,    0x007b}, {0x8820,    0x0081},
+{0x8821,    0x0007}, {0x8822,    0x002e}, {0x8823,    0x00cf},
+{0x8824,    0x00f6}, {0x8825,    0x0012}, {0x8826,    0x0005},
+{0x8827,    0x00c4}, {0x8828,    0x00f8}, {0x8829,    0x001b},
+{0x882a,    0x00b7}, {0x882b,    0x0012}, {0x882c,    0x0005},
+{0x882d,    0x0086}, {0x882e,    0x0000}, {0x882f,    0x00f6},
+{0x8830,    0x008f}, {0x8831,    0x0071}, {0x8832,    0x00bd},
+{0x8833,    0x0089}, {0x8834,    0x0094}, {0x8835,    0x0086},
+{0x8836,    0x0001}, {0x8837,    0x00f6}, {0x8838,    0x008f},
+{0x8839,    0x0074}, {0x883a,    0x00bd}, {0x883b,    0x0089},
+{0x883c,    0x0094}, {0x883d,    0x0086}, {0x883e,    0x0002},
+{0x883f,    0x00f6}, {0x8840,    0x008f}, {0x8841,    0x0077},
+{0x8842,    0x00bd}, {0x8843,    0x0089}, {0x8844,    0x0094},
+{0x8845,    0x0086}, {0x8846,    0x0003}, {0x8847,    0x00f6},
+{0x8848,    0x008f}, {0x8849,    0x007a}, {0x884a,    0x00bd},
+{0x884b,    0x0089}, {0x884c,    0x0094}, {0x884d,    0x00ce},
+{0x884e,    0x008f}, {0x884f,    0x0070}, {0x8850,    0x00a6},
+{0x8851,    0x0001}, {0x8852,    0x0081}, {0x8853,    0x0001},
+{0x8854,    0x0027}, {0x8855,    0x0007}, {0x8856,    0x0081},
+{0x8857,    0x0003}, {0x8858,    0x0027}, {0x8859,    0x0003},
+{0x885a,    0x007e}, {0x885b,    0x0088}, {0x885c,    0x0066},
+{0x885d,    0x00a6}, {0x885e,    0x0000}, {0x885f,    0x00b8},
+{0x8860,    0x008f}, {0x8861,    0x0081}, {0x8862,    0x0084},
+{0x8863,    0x0001}, {0x8864,    0x0026}, {0x8865,    0x000b},
+{0x8866,    0x008c}, {0x8867,    0x008f}, {0x8868,    0x0079},
+{0x8869,    0x002c}, {0x886a,    0x000e}, {0x886b,    0x0008},
+{0x886c,    0x0008}, {0x886d,    0x0008}, {0x886e,    0x007e},
+{0x886f,    0x0088}, {0x8870,    0x0050}, {0x8871,    0x00b6},
+{0x8872,    0x0012}, {0x8873,    0x0004}, {0x8874,    0x008a},
+{0x8875,    0x0040}, {0x8876,    0x00b7}, {0x8877,    0x0012},
+{0x8878,    0x0004}, {0x8879,    0x00b6}, {0x887a,    0x0012},
+{0x887b,    0x0004}, {0x887c,    0x0084}, {0x887d,    0x00fb},
+{0x887e,    0x0084}, {0x887f,    0x00ef}, {0x8880,    0x00b7},
+{0x8881,    0x0012}, {0x8882,    0x0004}, {0x8883,    0x00b6},
+{0x8884,    0x0012}, {0x8885,    0x0007}, {0x8886,    0x0036},
+{0x8887,    0x00b6}, {0x8888,    0x008f}, {0x8889,    0x007c},
+{0x888a,    0x0048}, {0x888b,    0x0048}, {0x888c,    0x00b7},
+{0x888d,    0x0012}, {0x888e,    0x0007}, {0x888f,    0x0086},
+{0x8890,    0x0001}, {0x8891,    0x00ba}, {0x8892,    0x0012},
+{0x8893,    0x0004}, {0x8894,    0x00b7}, {0x8895,    0x0012},
+{0x8896,    0x0004}, {0x8897,    0x0001}, {0x8898,    0x0001},
+{0x8899,    0x0001}, {0x889a,    0x0001}, {0x889b,    0x0001},
+{0x889c,    0x0001}, {0x889d,    0x0086}, {0x889e,    0x00fe},
+{0x889f,    0x00b4}, {0x88a0,    0x0012}, {0x88a1,    0x0004},
+{0x88a2,    0x00b7}, {0x88a3,    0x0012}, {0x88a4,    0x0004},
+{0x88a5,    0x0086}, {0x88a6,    0x0002}, {0x88a7,    0x00ba},
+{0x88a8,    0x0012}, {0x88a9,    0x0004}, {0x88aa,    0x00b7},
+{0x88ab,    0x0012}, {0x88ac,    0x0004}, {0x88ad,    0x0086},
+{0x88ae,    0x00fd}, {0x88af,    0x00b4}, {0x88b0,    0x0012},
+{0x88b1,    0x0004}, {0x88b2,    0x00b7}, {0x88b3,    0x0012},
+{0x88b4,    0x0004}, {0x88b5,    0x0032}, {0x88b6,    0x00b7},
+{0x88b7,    0x0012}, {0x88b8,    0x0007}, {0x88b9,    0x00b6},
+{0x88ba,    0x0012}, {0x88bb,    0x0000}, {0x88bc,    0x0084},
+{0x88bd,    0x0008}, {0x88be,    0x0081}, {0x88bf,    0x0008},
+{0x88c0,    0x0027}, {0x88c1,    0x000f}, {0x88c2,    0x007c},
+{0x88c3,    0x0082}, {0x88c4,    0x0008}, {0x88c5,    0x0026},
+{0x88c6,    0x0007}, {0x88c7,    0x0086}, {0x88c8,    0x0076},
+{0x88c9,    0x0097}, {0x88ca,    0x0040}, {0x88cb,    0x007e},
+{0x88cc,    0x0089}, {0x88cd,    0x006e}, {0x88ce,    0x007e},
+{0x88cf,    0x0086}, {0x88d0,    0x00ec}, {0x88d1,    0x00b6},
+{0x88d2,    0x008f}, {0x88d3,    0x007f}, {0x88d4,    0x0081},
+{0x88d5,    0x000f}, {0x88d6,    0x0027}, {0x88d7,    0x003c},
+{0x88d8,    0x00bd}, {0x88d9,    0x00e6}, {0x88da,    0x00c7},
+{0x88db,    0x00b7}, {0x88dc,    0x0012}, {0x88dd,    0x000d},
+{0x88de,    0x00bd}, {0x88df,    0x00e6}, {0x88e0,    0x00cb},
+{0x88e1,    0x00b6}, {0x88e2,    0x0012}, {0x88e3,    0x0004},
+{0x88e4,    0x008a}, {0x88e5,    0x0020}, {0x88e6,    0x00b7},
+{0x88e7,    0x0012}, {0x88e8,    0x0004}, {0x88e9,    0x00ce},
+{0x88ea,    0x00ff}, {0x88eb,    0x00ff}, {0x88ec,    0x00b6},
+{0x88ed,    0x0012}, {0x88ee,    0x0000}, {0x88ef,    0x0081},
+{0x88f0,    0x000c}, {0x88f1,    0x0026}, {0x88f2,    0x0005},
+{0x88f3,    0x0009}, {0x88f4,    0x0026}, {0x88f5,    0x00f6},
+{0x88f6,    0x0027}, {0x88f7,    0x001c}, {0x88f8,    0x00b6},
+{0x88f9,    0x0012}, {0x88fa,    0x0004}, {0x88fb,    0x0084},
+{0x88fc,    0x00df}, {0x88fd,    0x00b7}, {0x88fe,    0x0012},
+{0x88ff,    0x0004}, {0x8900,    0x0096}, {0x8901,    0x0083},
+{0x8902,    0x0081}, {0x8903,    0x0007}, {0x8904,    0x002c},
+{0x8905,    0x0005}, {0x8906,    0x007c}, {0x8907,    0x0000},
+{0x8908,    0x0083}, {0x8909,    0x0020}, {0x890a,    0x0006},
+{0x890b,    0x0096}, {0x890c,    0x0083}, {0x890d,    0x008b},
+{0x890e,    0x0008}, {0x890f,    0x0097}, {0x8910,    0x0083},
+{0x8911,    0x007e}, {0x8912,    0x0085}, {0x8913,    0x0041},
+{0x8914,    0x007f}, {0x8915,    0x008f}, {0x8916,    0x007e},
+{0x8917,    0x0086}, {0x8918,    0x0080}, {0x8919,    0x00b7},
+{0x891a,    0x0012}, {0x891b,    0x000c}, {0x891c,    0x0086},
+{0x891d,    0x0001}, {0x891e,    0x00b7}, {0x891f,    0x008f},
+{0x8920,    0x007d}, {0x8921,    0x00b6}, {0x8922,    0x0012},
+{0x8923,    0x000c}, {0x8924,    0x0084}, {0x8925,    0x007f},
+{0x8926,    0x00b7}, {0x8927,    0x0012}, {0x8928,    0x000c},
+{0x8929,    0x008a}, {0x892a,    0x0080}, {0x892b,    0x00b7},
+{0x892c,    0x0012}, {0x892d,    0x000c}, {0x892e,    0x0086},
+{0x892f,    0x000a}, {0x8930,    0x00bd}, {0x8931,    0x008a},
+{0x8932,    0x0006}, {0x8933,    0x00b6}, {0x8934,    0x0012},
+{0x8935,    0x000a}, {0x8936,    0x002a}, {0x8937,    0x0009},
+{0x8938,    0x00b6}, {0x8939,    0x0012}, {0x893a,    0x000c},
+{0x893b,    0x00ba}, {0x893c,    0x008f}, {0x893d,    0x007d},
+{0x893e,    0x00b7}, {0x893f,    0x0012}, {0x8940,    0x000c},
+{0x8941,    0x00b6}, {0x8942,    0x008f}, {0x8943,    0x007e},
+{0x8944,    0x0081}, {0x8945,    0x0060}, {0x8946,    0x0027},
+{0x8947,    0x001a}, {0x8948,    0x008b}, {0x8949,    0x0020},
+{0x894a,    0x00b7}, {0x894b,    0x008f}, {0x894c,    0x007e},
+{0x894d,    0x00b6}, {0x894e,    0x0012}, {0x894f,    0x000c},
+{0x8950,    0x0084}, {0x8951,    0x009f}, {0x8952,    0x00ba},
+{0x8953,    0x008f}, {0x8954,    0x007e}, {0x8955,    0x00b7},
+{0x8956,    0x0012}, {0x8957,    0x000c}, {0x8958,    0x00b6},
+{0x8959,    0x008f}, {0x895a,    0x007d}, {0x895b,    0x0048},
+{0x895c,    0x00b7}, {0x895d,    0x008f}, {0x895e,    0x007d},
+{0x895f,    0x007e}, {0x8960,    0x0089}, {0x8961,    0x0021},
+{0x8962,    0x00b6}, {0x8963,    0x0012}, {0x8964,    0x0004},
+{0x8965,    0x008a}, {0x8966,    0x0020}, {0x8967,    0x00b7},
+{0x8968,    0x0012}, {0x8969,    0x0004}, {0x896a,    0x00bd},
+{0x896b,    0x008a}, {0x896c,    0x000a}, {0x896d,    0x004f},
+{0x896e,    0x0039}, {0x896f,    0x00a6}, {0x8970,    0x0000},
+{0x8971,    0x0018}, {0x8972,    0x00a7}, {0x8973,    0x0000},
+{0x8974,    0x0008}, {0x8975,    0x0018}, {0x8976,    0x0008},
+{0x8977,    0x005a}, {0x8978,    0x0026}, {0x8979,    0x00f5},
+{0x897a,    0x0039}, {0x897b,    0x0036}, {0x897c,    0x006c},
+{0x897d,    0x0000}, {0x897e,    0x0032}, {0x897f,    0x00ba},
+{0x8980,    0x008f}, {0x8981,    0x007f}, {0x8982,    0x00b7},
+{0x8983,    0x008f}, {0x8984,    0x007f}, {0x8985,    0x00b6},
+{0x8986,    0x0012}, {0x8987,    0x0009}, {0x8988,    0x0084},
+{0x8989,    0x0003}, {0x898a,    0x00a7}, {0x898b,    0x0001},
+{0x898c,    0x00b6}, {0x898d,    0x0012}, {0x898e,    0x0006},
+{0x898f,    0x0084}, {0x8990,    0x003f}, {0x8991,    0x00a7},
+{0x8992,    0x0002}, {0x8993,    0x0039}, {0x8994,    0x0036},
+{0x8995,    0x0086}, {0x8996,    0x0003}, {0x8997,    0x00b7},
+{0x8998,    0x008f}, {0x8999,    0x0080}, {0x899a,    0x0032},
+{0x899b,    0x00c1}, {0x899c,    0x0000}, {0x899d,    0x0026},
+{0x899e,    0x0006}, {0x899f,    0x00b7}, {0x89a0,    0x008f},
+{0x89a1,    0x007c}, {0x89a2,    0x007e}, {0x89a3,    0x0089},
+{0x89a4,    0x00c9}, {0x89a5,    0x00c1}, {0x89a6,    0x0001},
+{0x89a7,    0x0027}, {0x89a8,    0x0018}, {0x89a9,    0x00c1},
+{0x89aa,    0x0002}, {0x89ab,    0x0027}, {0x89ac,    0x000c},
+{0x89ad,    0x00c1}, {0x89ae,    0x0003}, {0x89af,    0x0027},
+{0x89b0,    0x0000}, {0x89b1,    0x00f6}, {0x89b2,    0x008f},
+{0x89b3,    0x0080}, {0x89b4,    0x0005}, {0x89b5,    0x0005},
+{0x89b6,    0x00f7}, {0x89b7,    0x008f}, {0x89b8,    0x0080},
+{0x89b9,    0x00f6}, {0x89ba,    0x008f}, {0x89bb,    0x0080},
+{0x89bc,    0x0005}, {0x89bd,    0x0005}, {0x89be,    0x00f7},
+{0x89bf,    0x008f}, {0x89c0,    0x0080}, {0x89c1,    0x00f6},
+{0x89c2,    0x008f}, {0x89c3,    0x0080}, {0x89c4,    0x0005},
+{0x89c5,    0x0005}, {0x89c6,    0x00f7}, {0x89c7,    0x008f},
+{0x89c8,    0x0080}, {0x89c9,    0x00f6}, {0x89ca,    0x008f},
+{0x89cb,    0x0080}, {0x89cc,    0x0053}, {0x89cd,    0x00f4},
+{0x89ce,    0x0012}, {0x89cf,    0x0007}, {0x89d0,    0x001b},
+{0x89d1,    0x00b7}, {0x89d2,    0x0012}, {0x89d3,    0x0007},
+{0x89d4,    0x0039}, {0x89d5,    0x00ce}, {0x89d6,    0x008f},
+{0x89d7,    0x0070}, {0x89d8,    0x00a6}, {0x89d9,    0x0000},
+{0x89da,    0x0018}, {0x89db,    0x00e6}, {0x89dc,    0x0000},
+{0x89dd,    0x0018}, {0x89de,    0x00a7}, {0x89df,    0x0000},
+{0x89e0,    0x00e7}, {0x89e1,    0x0000}, {0x89e2,    0x00a6},
+{0x89e3,    0x0001}, {0x89e4,    0x0018}, {0x89e5,    0x00e6},
+{0x89e6,    0x0001}, {0x89e7,    0x0018}, {0x89e8,    0x00a7},
+{0x89e9,    0x0001}, {0x89ea,    0x00e7}, {0x89eb,    0x0001},
+{0x89ec,    0x00a6}, {0x89ed,    0x0002}, {0x89ee,    0x0018},
+{0x89ef,    0x00e6}, {0x89f0,    0x0002}, {0x89f1,    0x0018},
+{0x89f2,    0x00a7}, {0x89f3,    0x0002}, {0x89f4,    0x00e7},
+{0x89f5,    0x0002}, {0x89f6,    0x0039}, {0x89f7,    0x00a6},
+{0x89f8,    0x0000}, {0x89f9,    0x0084}, {0x89fa,    0x0007},
+{0x89fb,    0x00e6}, {0x89fc,    0x0000}, {0x89fd,    0x00c4},
+{0x89fe,    0x0038}, {0x89ff,    0x0054}, {0x8a00,    0x0054},
+{0x8a01,    0x0054}, {0x8a02,    0x001b}, {0x8a03,    0x00a7},
+{0x8a04,    0x0000}, {0x8a05,    0x0039}, {0x8a06,    0x004a},
+{0x8a07,    0x0026}, {0x8a08,    0x00fd}, {0x8a09,    0x0039},
+{0x8a0a,    0x0096}, {0x8a0b,    0x0022}, {0x8a0c,    0x0084},
+{0x8a0d,    0x000f}, {0x8a0e,    0x0097}, {0x8a0f,    0x0022},
+{0x8a10,    0x0086}, {0x8a11,    0x0001}, {0x8a12,    0x00b7},
+{0x8a13,    0x008f}, {0x8a14,    0x0070}, {0x8a15,    0x00b6},
+{0x8a16,    0x0012}, {0x8a17,    0x0007}, {0x8a18,    0x00b7},
+{0x8a19,    0x008f}, {0x8a1a,    0x0071}, {0x8a1b,    0x00f6},
+{0x8a1c,    0x0012}, {0x8a1d,    0x000c}, {0x8a1e,    0x00c4},
+{0x8a1f,    0x000f}, {0x8a20,    0x00c8}, {0x8a21,    0x000f},
+{0x8a22,    0x00f7}, {0x8a23,    0x008f}, {0x8a24,    0x0072},
+{0x8a25,    0x00f6}, {0x8a26,    0x008f}, {0x8a27,    0x0072},
+{0x8a28,    0x00b6}, {0x8a29,    0x008f}, {0x8a2a,    0x0071},
+{0x8a2b,    0x0084}, {0x8a2c,    0x0003}, {0x8a2d,    0x0027},
+{0x8a2e,    0x0014}, {0x8a2f,    0x0081}, {0x8a30,    0x0001},
+{0x8a31,    0x0027}, {0x8a32,    0x001c}, {0x8a33,    0x0081},
+{0x8a34,    0x0002}, {0x8a35,    0x0027}, {0x8a36,    0x0024},
+{0x8a37,    0x00f4}, {0x8a38,    0x008f}, {0x8a39,    0x0070},
+{0x8a3a,    0x0027}, {0x8a3b,    0x002a}, {0x8a3c,    0x0096},
+{0x8a3d,    0x0022}, {0x8a3e,    0x008a}, {0x8a3f,    0x0080},
+{0x8a40,    0x007e}, {0x8a41,    0x008a}, {0x8a42,    0x0064},
+{0x8a43,    0x00f4}, {0x8a44,    0x008f}, {0x8a45,    0x0070},
+{0x8a46,    0x0027}, {0x8a47,    0x001e}, {0x8a48,    0x0096},
+{0x8a49,    0x0022}, {0x8a4a,    0x008a}, {0x8a4b,    0x0010},
+{0x8a4c,    0x007e}, {0x8a4d,    0x008a}, {0x8a4e,    0x0064},
+{0x8a4f,    0x00f4}, {0x8a50,    0x008f}, {0x8a51,    0x0070},
+{0x8a52,    0x0027}, {0x8a53,    0x0012}, {0x8a54,    0x0096},
+{0x8a55,    0x0022}, {0x8a56,    0x008a}, {0x8a57,    0x0020},
+{0x8a58,    0x007e}, {0x8a59,    0x008a}, {0x8a5a,    0x0064},
+{0x8a5b,    0x00f4}, {0x8a5c,    0x008f}, {0x8a5d,    0x0070},
+{0x8a5e,    0x0027}, {0x8a5f,    0x0006}, {0x8a60,    0x0096},
+{0x8a61,    0x0022}, {0x8a62,    0x008a}, {0x8a63,    0x0040},
+{0x8a64,    0x0097}, {0x8a65,    0x0022}, {0x8a66,    0x0074},
+{0x8a67,    0x008f}, {0x8a68,    0x0071}, {0x8a69,    0x0074},
+{0x8a6a,    0x008f}, {0x8a6b,    0x0071}, {0x8a6c,    0x0078},
+{0x8a6d,    0x008f}, {0x8a6e,    0x0070}, {0x8a6f,    0x00b6},
+{0x8a70,    0x008f}, {0x8a71,    0x0070}, {0x8a72,    0x0085},
+{0x8a73,    0x0010}, {0x8a74,    0x0027}, {0x8a75,    0x00af},
+{0x8a76,    0x00d6}, {0x8a77,    0x0022}, {0x8a78,    0x00c4},
+{0x8a79,    0x0010}, {0x8a7a,    0x0058}, {0x8a7b,    0x00b6},
+{0x8a7c,    0x0012}, {0x8a7d,    0x0070}, {0x8a7e,    0x0081},
+{0x8a7f,    0x00e4}, {0x8a80,    0x0027}, {0x8a81,    0x0036},
+{0x8a82,    0x0081}, {0x8a83,    0x00e1}, {0x8a84,    0x0026},
+{0x8a85,    0x000c}, {0x8a86,    0x0096}, {0x8a87,    0x0022},
+{0x8a88,    0x0084}, {0x8a89,    0x0020}, {0x8a8a,    0x0044},
+{0x8a8b,    0x001b}, {0x8a8c,    0x00d6}, {0x8a8d,    0x0022},
+{0x8a8e,    0x00c4}, {0x8a8f,    0x00cf}, {0x8a90,    0x0020},
+{0x8a91,    0x0023}, {0x8a92,    0x0058}, {0x8a93,    0x0081},
+{0x8a94,    0x00c6}, {0x8a95,    0x0026}, {0x8a96,    0x000d},
+{0x8a97,    0x0096}, {0x8a98,    0x0022}, {0x8a99,    0x0084},
+{0x8a9a,    0x0040}, {0x8a9b,    0x0044}, {0x8a9c,    0x0044},
+{0x8a9d,    0x001b}, {0x8a9e,    0x00d6}, {0x8a9f,    0x0022},
+{0x8aa0,    0x00c4}, {0x8aa1,    0x00af}, {0x8aa2,    0x0020},
+{0x8aa3,    0x0011}, {0x8aa4,    0x0058}, {0x8aa5,    0x0081},
+{0x8aa6,    0x0027}, {0x8aa7,    0x0026}, {0x8aa8,    0x000f},
+{0x8aa9,    0x0096}, {0x8aaa,    0x0022}, {0x8aab,    0x0084},
+{0x8aac,    0x0080}, {0x8aad,    0x0044}, {0x8aae,    0x0044},
+{0x8aaf,    0x0044}, {0x8ab0,    0x001b}, {0x8ab1,    0x00d6},
+{0x8ab2,    0x0022}, {0x8ab3,    0x00c4}, {0x8ab4,    0x006f},
+{0x8ab5,    0x001b}, {0x8ab6,    0x0097}, {0x8ab7,    0x0022},
+{0x8ab8,    0x0039}, {0x8ab9,    0x0027}, {0x8aba,    0x000c},
+{0x8abb,    0x007c}, {0x8abc,    0x0082}, {0x8abd,    0x0006},
+{0x8abe,    0x00bd}, {0x8abf,    0x00d9}, {0x8ac0,    0x00ed},
+{0x8ac1,    0x00b6}, {0x8ac2,    0x0082}, {0x8ac3,    0x0007},
+{0x8ac4,    0x007e}, {0x8ac5,    0x008a}, {0x8ac6,    0x00b9},
+{0x8ac7,    0x007f}, {0x8ac8,    0x0082}, {0x8ac9,    0x0006},
+{0x8aca,    0x0039}, { 0x0, 0x0 }
+};
+#else
+cas_saturn_patch_t cas_saturn_patch[] = {
+{0x8200,    0x007e}, {0x8201,    0x0082}, {0x8202,    0x0009},
+{0x8203,    0x0000}, {0x8204,    0x0000}, {0x8205,    0x0000},
+{0x8206,    0x0000}, {0x8207,    0x0000}, {0x8208,    0x0000},
+{0x8209,    0x008e}, {0x820a,    0x008e}, {0x820b,    0x00ff},
+{0x820c,    0x00ce}, {0x820d,    0x0082}, {0x820e,    0x0025},
+{0x820f,    0x00ff}, {0x8210,    0x0001}, {0x8211,    0x000f},
+{0x8212,    0x00ce}, {0x8213,    0x0084}, {0x8214,    0x0026},
+{0x8215,    0x00ff}, {0x8216,    0x0001}, {0x8217,    0x0011},
+{0x8218,    0x00ce}, {0x8219,    0x0085}, {0x821a,    0x003d},
+{0x821b,    0x00df}, {0x821c,    0x00e5}, {0x821d,    0x0086},
+{0x821e,    0x0039}, {0x821f,    0x00b7}, {0x8220,    0x008f},
+{0x8221,    0x00f8}, {0x8222,    0x007e}, {0x8223,    0x00c3},
+{0x8224,    0x00c2}, {0x8225,    0x0096}, {0x8226,    0x0047},
+{0x8227,    0x0084}, {0x8228,    0x00f3}, {0x8229,    0x008a},
+{0x822a,    0x0000}, {0x822b,    0x0097}, {0x822c,    0x0047},
+{0x822d,    0x00ce}, {0x822e,    0x0082}, {0x822f,    0x0033},
+{0x8230,    0x00ff}, {0x8231,    0x0001}, {0x8232,    0x000f},
+{0x8233,    0x0096}, {0x8234,    0x0046}, {0x8235,    0x0084},
+{0x8236,    0x000c}, {0x8237,    0x0081}, {0x8238,    0x0004},
+{0x8239,    0x0027}, {0x823a,    0x000b}, {0x823b,    0x0096},
+{0x823c,    0x0046}, {0x823d,    0x0084}, {0x823e,    0x000c},
+{0x823f,    0x0081}, {0x8240,    0x0008}, {0x8241,    0x0027},
+{0x8242,    0x0057}, {0x8243,    0x007e}, {0x8244,    0x0084},
+{0x8245,    0x0025}, {0x8246,    0x0096}, {0x8247,    0x0047},
+{0x8248,    0x0084}, {0x8249,    0x00f3}, {0x824a,    0x008a},
+{0x824b,    0x0004}, {0x824c,    0x0097}, {0x824d,    0x0047},
+{0x824e,    0x00ce}, {0x824f,    0x0082}, {0x8250,    0x0054},
+{0x8251,    0x00ff}, {0x8252,    0x0001}, {0x8253,    0x000f},
+{0x8254,    0x0096}, {0x8255,    0x0046}, {0x8256,    0x0084},
+{0x8257,    0x000c}, {0x8258,    0x0081}, {0x8259,    0x0004},
+{0x825a,    0x0026}, {0x825b,    0x0038}, {0x825c,    0x00b6},
+{0x825d,    0x0012}, {0x825e,    0x0020}, {0x825f,    0x0084},
+{0x8260,    0x0020}, {0x8261,    0x0026}, {0x8262,    0x0003},
+{0x8263,    0x007e}, {0x8264,    0x0084}, {0x8265,    0x0025},
+{0x8266,    0x0096}, {0x8267,    0x007b}, {0x8268,    0x00d6},
+{0x8269,    0x007c}, {0x826a,    0x00fe}, {0x826b,    0x008f},
+{0x826c,    0x0056}, {0x826d,    0x00bd}, {0x826e,    0x00f7},
+{0x826f,    0x00b6}, {0x8270,    0x00fe}, {0x8271,    0x008f},
+{0x8272,    0x004e}, {0x8273,    0x00bd}, {0x8274,    0x00ec},
+{0x8275,    0x008e}, {0x8276,    0x00bd}, {0x8277,    0x00fa},
+{0x8278,    0x00f7}, {0x8279,    0x00bd}, {0x827a,    0x00f7},
+{0x827b,    0x0028}, {0x827c,    0x00ce}, {0x827d,    0x0082},
+{0x827e,    0x0082}, {0x827f,    0x00ff}, {0x8280,    0x0001},
+{0x8281,    0x000f}, {0x8282,    0x0096}, {0x8283,    0x0046},
+{0x8284,    0x0084}, {0x8285,    0x000c}, {0x8286,    0x0081},
+{0x8287,    0x0004}, {0x8288,    0x0026}, {0x8289,    0x000a},
+{0x828a,    0x00b6}, {0x828b,    0x0012}, {0x828c,    0x0020},
+{0x828d,    0x0084}, {0x828e,    0x0020}, {0x828f,    0x0027},
+{0x8290,    0x00b5}, {0x8291,    0x007e}, {0x8292,    0x0084},
+{0x8293,    0x0025}, {0x8294,    0x00bd}, {0x8295,    0x00f7},
+{0x8296,    0x001f}, {0x8297,    0x007e}, {0x8298,    0x0084},
+{0x8299,    0x001f}, {0x829a,    0x0096}, {0x829b,    0x0047},
+{0x829c,    0x0084}, {0x829d,    0x00f3}, {0x829e,    0x008a},
+{0x829f,    0x0008}, {0x82a0,    0x0097}, {0x82a1,    0x0047},
+{0x82a2,    0x00de}, {0x82a3,    0x00e1}, {0x82a4,    0x00ad},
+{0x82a5,    0x0000}, {0x82a6,    0x00ce}, {0x82a7,    0x0082},
+{0x82a8,    0x00af}, {0x82a9,    0x00ff}, {0x82aa,    0x0001},
+{0x82ab,    0x000f}, {0x82ac,    0x007e}, {0x82ad,    0x0084},
+{0x82ae,    0x0025}, {0x82af,    0x0096}, {0x82b0,    0x0041},
+{0x82b1,    0x0085}, {0x82b2,    0x0010}, {0x82b3,    0x0026},
+{0x82b4,    0x0006}, {0x82b5,    0x0096}, {0x82b6,    0x0023},
+{0x82b7,    0x0085}, {0x82b8,    0x0040}, {0x82b9,    0x0027},
+{0x82ba,    0x0006}, {0x82bb,    0x00bd}, {0x82bc,    0x00ed},
+{0x82bd,    0x0000}, {0x82be,    0x007e}, {0x82bf,    0x0083},
+{0x82c0,    0x00a2}, {0x82c1,    0x00de}, {0x82c2,    0x0042},
+{0x82c3,    0x00bd}, {0x82c4,    0x00eb}, {0x82c5,    0x008e},
+{0x82c6,    0x0096}, {0x82c7,    0x0024}, {0x82c8,    0x0084},
+{0x82c9,    0x0008}, {0x82ca,    0x0027}, {0x82cb,    0x0003},
+{0x82cc,    0x007e}, {0x82cd,    0x0083}, {0x82ce,    0x00df},
+{0x82cf,    0x0096}, {0x82d0,    0x007b}, {0x82d1,    0x00d6},
+{0x82d2,    0x007c}, {0x82d3,    0x00fe}, {0x82d4,    0x008f},
+{0x82d5,    0x0056}, {0x82d6,    0x00bd}, {0x82d7,    0x00f7},
+{0x82d8,    0x00b6}, {0x82d9,    0x00fe}, {0x82da,    0x008f},
+{0x82db,    0x0050}, {0x82dc,    0x00bd}, {0x82dd,    0x00ec},
+{0x82de,    0x008e}, {0x82df,    0x00bd}, {0x82e0,    0x00fa},
+{0x82e1,    0x00f7}, {0x82e2,    0x0086}, {0x82e3,    0x0011},
+{0x82e4,    0x00c6}, {0x82e5,    0x0049}, {0x82e6,    0x00bd},
+{0x82e7,    0x00e4}, {0x82e8,    0x0012}, {0x82e9,    0x00ce},
+{0x82ea,    0x0082}, {0x82eb,    0x00ef}, {0x82ec,    0x00ff},
+{0x82ed,    0x0001}, {0x82ee,    0x000f}, {0x82ef,    0x0096},
+{0x82f0,    0x0046}, {0x82f1,    0x0084}, {0x82f2,    0x000c},
+{0x82f3,    0x0081}, {0x82f4,    0x0000}, {0x82f5,    0x0027},
+{0x82f6,    0x0017}, {0x82f7,    0x00c6}, {0x82f8,    0x0049},
+{0x82f9,    0x00bd}, {0x82fa,    0x00e4}, {0x82fb,    0x0091},
+{0x82fc,    0x0024}, {0x82fd,    0x000d}, {0x82fe,    0x00b6},
+{0x82ff,    0x0012}, {0x8300,    0x0020}, {0x8301,    0x0085},
+{0x8302,    0x0020}, {0x8303,    0x0026}, {0x8304,    0x000c},
+{0x8305,    0x00ce}, {0x8306,    0x0082}, {0x8307,    0x00c1},
+{0x8308,    0x00ff}, {0x8309,    0x0001}, {0x830a,    0x000f},
+{0x830b,    0x007e}, {0x830c,    0x0084}, {0x830d,    0x0025},
+{0x830e,    0x007e}, {0x830f,    0x0084}, {0x8310,    0x0016},
+{0x8311,    0x00fe}, {0x8312,    0x008f}, {0x8313,    0x0052},
+{0x8314,    0x00bd}, {0x8315,    0x00ec}, {0x8316,    0x008e},
+{0x8317,    0x00bd}, {0x8318,    0x00fa}, {0x8319,    0x00f7},
+{0x831a,    0x0086}, {0x831b,    0x006a}, {0x831c,    0x00c6},
+{0x831d,    0x0049}, {0x831e,    0x00bd}, {0x831f,    0x00e4},
+{0x8320,    0x0012}, {0x8321,    0x00ce}, {0x8322,    0x0083},
+{0x8323,    0x0027}, {0x8324,    0x00ff}, {0x8325,    0x0001},
+{0x8326,    0x000f}, {0x8327,    0x0096}, {0x8328,    0x0046},
+{0x8329,    0x0084}, {0x832a,    0x000c}, {0x832b,    0x0081},
+{0x832c,    0x0000}, {0x832d,    0x0027}, {0x832e,    0x000a},
+{0x832f,    0x00c6}, {0x8330,    0x0049}, {0x8331,    0x00bd},
+{0x8332,    0x00e4}, {0x8333,    0x0091}, {0x8334,    0x0025},
+{0x8335,    0x0006}, {0x8336,    0x007e}, {0x8337,    0x0084},
+{0x8338,    0x0025}, {0x8339,    0x007e}, {0x833a,    0x0084},
+{0x833b,    0x0016}, {0x833c,    0x00b6}, {0x833d,    0x0018},
+{0x833e,    0x0070}, {0x833f,    0x00bb}, {0x8340,    0x0019},
+{0x8341,    0x0070}, {0x8342,    0x002a}, {0x8343,    0x0004},
+{0x8344,    0x0081}, {0x8345,    0x00af}, {0x8346,    0x002e},
+{0x8347,    0x0019}, {0x8348,    0x0096}, {0x8349,    0x007b},
+{0x834a,    0x00f6}, {0x834b,    0x0020}, {0x834c,    0x0007},
+{0x834d,    0x00fa}, {0x834e,    0x0020}, {0x834f,    0x0027},
+{0x8350,    0x00c4}, {0x8351,    0x0038}, {0x8352,    0x0081},
+{0x8353,    0x0038}, {0x8354,    0x0027}, {0x8355,    0x000b},
+{0x8356,    0x00f6}, {0x8357,    0x0020}, {0x8358,    0x0007},
+{0x8359,    0x00fa}, {0x835a,    0x0020}, {0x835b,    0x0027},
+{0x835c,    0x00cb}, {0x835d,    0x0008}, {0x835e,    0x007e},
+{0x835f,    0x0082}, {0x8360,    0x00d3}, {0x8361,    0x00bd},
+{0x8362,    0x00f7}, {0x8363,    0x0066}, {0x8364,    0x0086},
+{0x8365,    0x0074}, {0x8366,    0x00c6}, {0x8367,    0x0049},
+{0x8368,    0x00bd}, {0x8369,    0x00e4}, {0x836a,    0x0012},
+{0x836b,    0x00ce}, {0x836c,    0x0083}, {0x836d,    0x0071},
+{0x836e,    0x00ff}, {0x836f,    0x0001}, {0x8370,    0x000f},
+{0x8371,    0x0096}, {0x8372,    0x0046}, {0x8373,    0x0084},
+{0x8374,    0x000c}, {0x8375,    0x0081}, {0x8376,    0x0008},
+{0x8377,    0x0026}, {0x8378,    0x000a}, {0x8379,    0x00c6},
+{0x837a,    0x0049}, {0x837b,    0x00bd}, {0x837c,    0x00e4},
+{0x837d,    0x0091}, {0x837e,    0x0025}, {0x837f,    0x0006},
+{0x8380,    0x007e}, {0x8381,    0x0084}, {0x8382,    0x0025},
+{0x8383,    0x007e}, {0x8384,    0x0084}, {0x8385,    0x0016},
+{0x8386,    0x00bd}, {0x8387,    0x00f7}, {0x8388,    0x003e},
+{0x8389,    0x0026}, {0x838a,    0x000e}, {0x838b,    0x00bd},
+{0x838c,    0x00e5}, {0x838d,    0x0009}, {0x838e,    0x0026},
+{0x838f,    0x0006}, {0x8390,    0x00ce}, {0x8391,    0x0082},
+{0x8392,    0x00c1}, {0x8393,    0x00ff}, {0x8394,    0x0001},
+{0x8395,    0x000f}, {0x8396,    0x007e}, {0x8397,    0x0084},
+{0x8398,    0x0025}, {0x8399,    0x00fe}, {0x839a,    0x008f},
+{0x839b,    0x0054}, {0x839c,    0x00bd}, {0x839d,    0x00ec},
+{0x839e,    0x008e}, {0x839f,    0x00bd}, {0x83a0,    0x00fa},
+{0x83a1,    0x00f7}, {0x83a2,    0x00bd}, {0x83a3,    0x00f7},
+{0x83a4,    0x0033}, {0x83a5,    0x0086}, {0x83a6,    0x000f},
+{0x83a7,    0x00c6}, {0x83a8,    0x0051}, {0x83a9,    0x00bd},
+{0x83aa,    0x00e4}, {0x83ab,    0x0012}, {0x83ac,    0x00ce},
+{0x83ad,    0x0083}, {0x83ae,    0x00b2}, {0x83af,    0x00ff},
+{0x83b0,    0x0001}, {0x83b1,    0x000f}, {0x83b2,    0x0096},
+{0x83b3,    0x0046}, {0x83b4,    0x0084}, {0x83b5,    0x000c},
+{0x83b6,    0x0081}, {0x83b7,    0x0008}, {0x83b8,    0x0026},
+{0x83b9,    0x005c}, {0x83ba,    0x00b6}, {0x83bb,    0x0012},
+{0x83bc,    0x0020}, {0x83bd,    0x0084}, {0x83be,    0x003f},
+{0x83bf,    0x0081}, {0x83c0,    0x003a}, {0x83c1,    0x0027},
+{0x83c2,    0x001c}, {0x83c3,    0x0096}, {0x83c4,    0x0023},
+{0x83c5,    0x0085}, {0x83c6,    0x0040}, {0x83c7,    0x0027},
+{0x83c8,    0x0003}, {0x83c9,    0x007e}, {0x83ca,    0x0084},
+{0x83cb,    0x0025}, {0x83cc,    0x00c6}, {0x83cd,    0x0051},
+{0x83ce,    0x00bd}, {0x83cf,    0x00e4}, {0x83d0,    0x0091},
+{0x83d1,    0x0025}, {0x83d2,    0x0003}, {0x83d3,    0x007e},
+{0x83d4,    0x0084}, {0x83d5,    0x0025}, {0x83d6,    0x00ce},
+{0x83d7,    0x0082}, {0x83d8,    0x00c1}, {0x83d9,    0x00ff},
+{0x83da,    0x0001}, {0x83db,    0x000f}, {0x83dc,    0x007e},
+{0x83dd,    0x0084}, {0x83de,    0x0025}, {0x83df,    0x00bd},
+{0x83e0,    0x00f8}, {0x83e1,    0x0037}, {0x83e2,    0x007c},
+{0x83e3,    0x0000}, {0x83e4,    0x007a}, {0x83e5,    0x00ce},
+{0x83e6,    0x0083}, {0x83e7,    0x00ee}, {0x83e8,    0x00ff},
+{0x83e9,    0x0001}, {0x83ea,    0x000f}, {0x83eb,    0x007e},
+{0x83ec,    0x0084}, {0x83ed,    0x0025}, {0x83ee,    0x0096},
+{0x83ef,    0x0046}, {0x83f0,    0x0084}, {0x83f1,    0x000c},
+{0x83f2,    0x0081}, {0x83f3,    0x0008}, {0x83f4,    0x0026},
+{0x83f5,    0x0020}, {0x83f6,    0x0096}, {0x83f7,    0x0024},
+{0x83f8,    0x0084}, {0x83f9,    0x0008}, {0x83fa,    0x0026},
+{0x83fb,    0x0029}, {0x83fc,    0x00b6}, {0x83fd,    0x0018},
+{0x83fe,    0x0082}, {0x83ff,    0x00bb}, {0x8400,    0x0019},
+{0x8401,    0x0082}, {0x8402,    0x00b1}, {0x8403,    0x0001},
+{0x8404,    0x003b}, {0x8405,    0x0022}, {0x8406,    0x0009},
+{0x8407,    0x00b6}, {0x8408,    0x0012}, {0x8409,    0x0020},
+{0x840a,    0x0084}, {0x840b,    0x0037}, {0x840c,    0x0081},
+{0x840d,    0x0032}, {0x840e,    0x0027}, {0x840f,    0x0015},
+{0x8410,    0x00bd}, {0x8411,    0x00f8}, {0x8412,    0x0044},
+{0x8413,    0x007e}, {0x8414,    0x0082}, {0x8415,    0x00c1},
+{0x8416,    0x00bd}, {0x8417,    0x00f7}, {0x8418,    0x001f},
+{0x8419,    0x00bd}, {0x841a,    0x00f8}, {0x841b,    0x0044},
+{0x841c,    0x00bd}, {0x841d,    0x00fc}, {0x841e,    0x0029},
+{0x841f,    0x00ce}, {0x8420,    0x0082}, {0x8421,    0x0025},
+{0x8422,    0x00ff}, {0x8423,    0x0001}, {0x8424,    0x000f},
+{0x8425,    0x0039}, {0x8426,    0x0096}, {0x8427,    0x0047},
+{0x8428,    0x0084}, {0x8429,    0x00fc}, {0x842a,    0x008a},
+{0x842b,    0x0000}, {0x842c,    0x0097}, {0x842d,    0x0047},
+{0x842e,    0x00ce}, {0x842f,    0x0084}, {0x8430,    0x0034},
+{0x8431,    0x00ff}, {0x8432,    0x0001}, {0x8433,    0x0011},
+{0x8434,    0x0096}, {0x8435,    0x0046}, {0x8436,    0x0084},
+{0x8437,    0x0003}, {0x8438,    0x0081}, {0x8439,    0x0002},
+{0x843a,    0x0027}, {0x843b,    0x0003}, {0x843c,    0x007e},
+{0x843d,    0x0085}, {0x843e,    0x001e}, {0x843f,    0x0096},
+{0x8440,    0x0047}, {0x8441,    0x0084}, {0x8442,    0x00fc},
+{0x8443,    0x008a}, {0x8444,    0x0002}, {0x8445,    0x0097},
+{0x8446,    0x0047}, {0x8447,    0x00de}, {0x8448,    0x00e1},
+{0x8449,    0x00ad}, {0x844a,    0x0000}, {0x844b,    0x0086},
+{0x844c,    0x0001}, {0x844d,    0x00b7}, {0x844e,    0x0012},
+{0x844f,    0x0051}, {0x8450,    0x00bd}, {0x8451,    0x00f7},
+{0x8452,    0x0014}, {0x8453,    0x00b6}, {0x8454,    0x0010},
+{0x8455,    0x0031}, {0x8456,    0x0084}, {0x8457,    0x00fd},
+{0x8458,    0x00b7}, {0x8459,    0x0010}, {0x845a,    0x0031},
+{0x845b,    0x00bd}, {0x845c,    0x00f8}, {0x845d,    0x001e},
+{0x845e,    0x0096}, {0x845f,    0x0081}, {0x8460,    0x00d6},
+{0x8461,    0x0082}, {0x8462,    0x00fe}, {0x8463,    0x008f},
+{0x8464,    0x005a}, {0x8465,    0x00bd}, {0x8466,    0x00f7},
+{0x8467,    0x00b6}, {0x8468,    0x00fe}, {0x8469,    0x008f},
+{0x846a,    0x005c}, {0x846b,    0x00bd}, {0x846c,    0x00ec},
+{0x846d,    0x008e}, {0x846e,    0x00bd}, {0x846f,    0x00fa},
+{0x8470,    0x00f7}, {0x8471,    0x0086}, {0x8472,    0x0008},
+{0x8473,    0x00d6}, {0x8474,    0x0000}, {0x8475,    0x00c5},
+{0x8476,    0x0010}, {0x8477,    0x0026}, {0x8478,    0x0002},
+{0x8479,    0x008b}, {0x847a,    0x0020}, {0x847b,    0x00c6},
+{0x847c,    0x0051}, {0x847d,    0x00bd}, {0x847e,    0x00e4},
+{0x847f,    0x0012}, {0x8480,    0x00ce}, {0x8481,    0x0084},
+{0x8482,    0x0086}, {0x8483,    0x00ff}, {0x8484,    0x0001},
+{0x8485,    0x0011}, {0x8486,    0x0096}, {0x8487,    0x0046},
+{0x8488,    0x0084}, {0x8489,    0x0003}, {0x848a,    0x0081},
+{0x848b,    0x0002}, {0x848c,    0x0027}, {0x848d,    0x0003},
+{0x848e,    0x007e}, {0x848f,    0x0085}, {0x8490,    0x000f},
+{0x8491,    0x00c6}, {0x8492,    0x0051}, {0x8493,    0x00bd},
+{0x8494,    0x00e4}, {0x8495,    0x0091}, {0x8496,    0x0025},
+{0x8497,    0x0003}, {0x8498,    0x007e}, {0x8499,    0x0085},
+{0x849a,    0x001e}, {0x849b,    0x0096}, {0x849c,    0x0044},
+{0x849d,    0x0085}, {0x849e,    0x0010}, {0x849f,    0x0026},
+{0x84a0,    0x000a}, {0x84a1,    0x00b6}, {0x84a2,    0x0012},
+{0x84a3,    0x0050}, {0x84a4,    0x00ba}, {0x84a5,    0x0001},
+{0x84a6,    0x003c}, {0x84a7,    0x0085}, {0x84a8,    0x0010},
+{0x84a9,    0x0027}, {0x84aa,    0x00a8}, {0x84ab,    0x00bd},
+{0x84ac,    0x00f7}, {0x84ad,    0x0066}, {0x84ae,    0x00ce},
+{0x84af,    0x0084}, {0x84b0,    0x00b7}, {0x84b1,    0x00ff},
+{0x84b2,    0x0001}, {0x84b3,    0x0011}, {0x84b4,    0x007e},
+{0x84b5,    0x0085}, {0x84b6,    0x001e}, {0x84b7,    0x0096},
+{0x84b8,    0x0046}, {0x84b9,    0x0084}, {0x84ba,    0x0003},
+{0x84bb,    0x0081}, {0x84bc,    0x0002}, {0x84bd,    0x0026},
+{0x84be,    0x0050}, {0x84bf,    0x00b6}, {0x84c0,    0x0012},
+{0x84c1,    0x0030}, {0x84c2,    0x0084}, {0x84c3,    0x0003},
+{0x84c4,    0x0081}, {0x84c5,    0x0001}, {0x84c6,    0x0027},
+{0x84c7,    0x0003}, {0x84c8,    0x007e}, {0x84c9,    0x0085},
+{0x84ca,    0x001e}, {0x84cb,    0x0096}, {0x84cc,    0x0044},
+{0x84cd,    0x0085}, {0x84ce,    0x0010}, {0x84cf,    0x0026},
+{0x84d0,    0x0013}, {0x84d1,    0x00b6}, {0x84d2,    0x0012},
+{0x84d3,    0x0050}, {0x84d4,    0x00ba}, {0x84d5,    0x0001},
+{0x84d6,    0x003c}, {0x84d7,    0x0085}, {0x84d8,    0x0010},
+{0x84d9,    0x0026}, {0x84da,    0x0009}, {0x84db,    0x00ce},
+{0x84dc,    0x0084}, {0x84dd,    0x0053}, {0x84de,    0x00ff},
+{0x84df,    0x0001}, {0x84e0,    0x0011}, {0x84e1,    0x007e},
+{0x84e2,    0x0085}, {0x84e3,    0x001e}, {0x84e4,    0x00b6},
+{0x84e5,    0x0010}, {0x84e6,    0x0031}, {0x84e7,    0x008a},
+{0x84e8,    0x0002}, {0x84e9,    0x00b7}, {0x84ea,    0x0010},
+{0x84eb,    0x0031}, {0x84ec,    0x00bd}, {0x84ed,    0x0085},
+{0x84ee,    0x001f}, {0x84ef,    0x00bd}, {0x84f0,    0x00f8},
+{0x84f1,    0x0037}, {0x84f2,    0x007c}, {0x84f3,    0x0000},
+{0x84f4,    0x0080}, {0x84f5,    0x00ce}, {0x84f6,    0x0084},
+{0x84f7,    0x00fe}, {0x84f8,    0x00ff}, {0x84f9,    0x0001},
+{0x84fa,    0x0011}, {0x84fb,    0x007e}, {0x84fc,    0x0085},
+{0x84fd,    0x001e}, {0x84fe,    0x0096}, {0x84ff,    0x0046},
+{0x8500,    0x0084}, {0x8501,    0x0003}, {0x8502,    0x0081},
+{0x8503,    0x0002}, {0x8504,    0x0026}, {0x8505,    0x0009},
+{0x8506,    0x00b6}, {0x8507,    0x0012}, {0x8508,    0x0030},
+{0x8509,    0x0084}, {0x850a,    0x0003}, {0x850b,    0x0081},
+{0x850c,    0x0001}, {0x850d,    0x0027}, {0x850e,    0x000f},
+{0x850f,    0x00bd}, {0x8510,    0x00f8}, {0x8511,    0x0044},
+{0x8512,    0x00bd}, {0x8513,    0x00f7}, {0x8514,    0x000b},
+{0x8515,    0x00bd}, {0x8516,    0x00fc}, {0x8517,    0x0029},
+{0x8518,    0x00ce}, {0x8519,    0x0084}, {0x851a,    0x0026},
+{0x851b,    0x00ff}, {0x851c,    0x0001}, {0x851d,    0x0011},
+{0x851e,    0x0039}, {0x851f,    0x00d6}, {0x8520,    0x0022},
+{0x8521,    0x00c4}, {0x8522,    0x000f}, {0x8523,    0x00b6},
+{0x8524,    0x0012}, {0x8525,    0x0030}, {0x8526,    0x00ba},
+{0x8527,    0x0012}, {0x8528,    0x0032}, {0x8529,    0x0084},
+{0x852a,    0x0004}, {0x852b,    0x0027}, {0x852c,    0x000d},
+{0x852d,    0x0096}, {0x852e,    0x0022}, {0x852f,    0x0085},
+{0x8530,    0x0004}, {0x8531,    0x0027}, {0x8532,    0x0005},
+{0x8533,    0x00ca}, {0x8534,    0x0010}, {0x8535,    0x007e},
+{0x8536,    0x0085}, {0x8537,    0x003a}, {0x8538,    0x00ca},
+{0x8539,    0x0020}, {0x853a,    0x00d7}, {0x853b,    0x0022},
+{0x853c,    0x0039}, {0x853d,    0x0086}, {0x853e,    0x0000},
+{0x853f,    0x0097}, {0x8540,    0x0083}, {0x8541,    0x0018},
+{0x8542,    0x00ce}, {0x8543,    0x001c}, {0x8544,    0x0000},
+{0x8545,    0x00bd}, {0x8546,    0x00eb}, {0x8547,    0x0046},
+{0x8548,    0x0096}, {0x8549,    0x0057}, {0x854a,    0x0085},
+{0x854b,    0x0001}, {0x854c,    0x0027}, {0x854d,    0x0002},
+{0x854e,    0x004f}, {0x854f,    0x0039}, {0x8550,    0x0085},
+{0x8551,    0x0002}, {0x8552,    0x0027}, {0x8553,    0x0001},
+{0x8554,    0x0039}, {0x8555,    0x007f}, {0x8556,    0x008f},
+{0x8557,    0x007d}, {0x8558,    0x0086}, {0x8559,    0x0004},
+{0x855a,    0x00b7}, {0x855b,    0x0012}, {0x855c,    0x0004},
+{0x855d,    0x0086}, {0x855e,    0x0008}, {0x855f,    0x00b7},
+{0x8560,    0x0012}, {0x8561,    0x0007}, {0x8562,    0x0086},
+{0x8563,    0x0010}, {0x8564,    0x00b7}, {0x8565,    0x0012},
+{0x8566,    0x000c}, {0x8567,    0x0086}, {0x8568,    0x0007},
+{0x8569,    0x00b7}, {0x856a,    0x0012}, {0x856b,    0x0006},
+{0x856c,    0x00b6}, {0x856d,    0x008f}, {0x856e,    0x007d},
+{0x856f,    0x00b7}, {0x8570,    0x0012}, {0x8571,    0x0070},
+{0x8572,    0x0086}, {0x8573,    0x0001}, {0x8574,    0x00ba},
+{0x8575,    0x0012}, {0x8576,    0x0004}, {0x8577,    0x00b7},
+{0x8578,    0x0012}, {0x8579,    0x0004}, {0x857a,    0x0001},
+{0x857b,    0x0001}, {0x857c,    0x0001}, {0x857d,    0x0001},
+{0x857e,    0x0001}, {0x857f,    0x0001}, {0x8580,    0x00b6},
+{0x8581,    0x0012}, {0x8582,    0x0004}, {0x8583,    0x0084},
+{0x8584,    0x00fe}, {0x8585,    0x008a}, {0x8586,    0x0002},
+{0x8587,    0x00b7}, {0x8588,    0x0012}, {0x8589,    0x0004},
+{0x858a,    0x0001}, {0x858b,    0x0001}, {0x858c,    0x0001},
+{0x858d,    0x0001}, {0x858e,    0x0001}, {0x858f,    0x0001},
+{0x8590,    0x0086}, {0x8591,    0x00fd}, {0x8592,    0x00b4},
+{0x8593,    0x0012}, {0x8594,    0x0004}, {0x8595,    0x00b7},
+{0x8596,    0x0012}, {0x8597,    0x0004}, {0x8598,    0x00b6},
+{0x8599,    0x0012}, {0x859a,    0x0000}, {0x859b,    0x0084},
+{0x859c,    0x0008}, {0x859d,    0x0081}, {0x859e,    0x0008},
+{0x859f,    0x0027}, {0x85a0,    0x0016}, {0x85a1,    0x00b6},
+{0x85a2,    0x008f}, {0x85a3,    0x007d}, {0x85a4,    0x0081},
+{0x85a5,    0x000c}, {0x85a6,    0x0027}, {0x85a7,    0x0008},
+{0x85a8,    0x008b}, {0x85a9,    0x0004}, {0x85aa,    0x00b7},
+{0x85ab,    0x008f}, {0x85ac,    0x007d}, {0x85ad,    0x007e},
+{0x85ae,    0x0085}, {0x85af,    0x006c}, {0x85b0,    0x0086},
+{0x85b1,    0x0003}, {0x85b2,    0x0097}, {0x85b3,    0x0040},
+{0x85b4,    0x007e}, {0x85b5,    0x0089}, {0x85b6,    0x006e},
+{0x85b7,    0x0086}, {0x85b8,    0x0007}, {0x85b9,    0x00b7},
+{0x85ba,    0x0012}, {0x85bb,    0x0006}, {0x85bc,    0x005f},
+{0x85bd,    0x00f7}, {0x85be,    0x008f}, {0x85bf,    0x0082},
+{0x85c0,    0x005f}, {0x85c1,    0x00f7}, {0x85c2,    0x008f},
+{0x85c3,    0x007f}, {0x85c4,    0x00f7}, {0x85c5,    0x008f},
+{0x85c6,    0x0070}, {0x85c7,    0x00f7}, {0x85c8,    0x008f},
+{0x85c9,    0x0071}, {0x85ca,    0x00f7}, {0x85cb,    0x008f},
+{0x85cc,    0x0072}, {0x85cd,    0x00f7}, {0x85ce,    0x008f},
+{0x85cf,    0x0073}, {0x85d0,    0x00f7}, {0x85d1,    0x008f},
+{0x85d2,    0x0074}, {0x85d3,    0x00f7}, {0x85d4,    0x008f},
+{0x85d5,    0x0075}, {0x85d6,    0x00f7}, {0x85d7,    0x008f},
+{0x85d8,    0x0076}, {0x85d9,    0x00f7}, {0x85da,    0x008f},
+{0x85db,    0x0077}, {0x85dc,    0x00f7}, {0x85dd,    0x008f},
+{0x85de,    0x0078}, {0x85df,    0x00f7}, {0x85e0,    0x008f},
+{0x85e1,    0x0079}, {0x85e2,    0x00f7}, {0x85e3,    0x008f},
+{0x85e4,    0x007a}, {0x85e5,    0x00f7}, {0x85e6,    0x008f},
+{0x85e7,    0x007b}, {0x85e8,    0x00b6}, {0x85e9,    0x0012},
+{0x85ea,    0x0004}, {0x85eb,    0x008a}, {0x85ec,    0x0010},
+{0x85ed,    0x00b7}, {0x85ee,    0x0012}, {0x85ef,    0x0004},
+{0x85f0,    0x0086}, {0x85f1,    0x00e4}, {0x85f2,    0x00b7},
+{0x85f3,    0x0012}, {0x85f4,    0x0070}, {0x85f5,    0x00b7},
+{0x85f6,    0x0012}, {0x85f7,    0x0007}, {0x85f8,    0x00f7},
+{0x85f9,    0x0012}, {0x85fa,    0x0005}, {0x85fb,    0x00f7},
+{0x85fc,    0x0012}, {0x85fd,    0x0009}, {0x85fe,    0x0086},
+{0x85ff,    0x0008}, {0x8600,    0x00ba}, {0x8601,    0x0012},
+{0x8602,    0x0004}, {0x8603,    0x00b7}, {0x8604,    0x0012},
+{0x8605,    0x0004}, {0x8606,    0x0086}, {0x8607,    0x00f7},
+{0x8608,    0x00b4}, {0x8609,    0x0012}, {0x860a,    0x0004},
+{0x860b,    0x00b7}, {0x860c,    0x0012}, {0x860d,    0x0004},
+{0x860e,    0x0001}, {0x860f,    0x0001}, {0x8610,    0x0001},
+{0x8611,    0x0001}, {0x8612,    0x0001}, {0x8613,    0x0001},
+{0x8614,    0x00b6}, {0x8615,    0x0012}, {0x8616,    0x0008},
+{0x8617,    0x0027}, {0x8618,    0x007f}, {0x8619,    0x0081},
+{0x861a,    0x0080}, {0x861b,    0x0026}, {0x861c,    0x000b},
+{0x861d,    0x0086}, {0x861e,    0x0008}, {0x861f,    0x00ce},
+{0x8620,    0x008f}, {0x8621,    0x0079}, {0x8622,    0x00bd},
+{0x8623,    0x0089}, {0x8624,    0x007b}, {0x8625,    0x007e},
+{0x8626,    0x0086}, {0x8627,    0x008e}, {0x8628,    0x0081},
+{0x8629,    0x0040}, {0x862a,    0x0026}, {0x862b,    0x000b},
+{0x862c,    0x0086}, {0x862d,    0x0004}, {0x862e,    0x00ce},
+{0x862f,    0x008f}, {0x8630,    0x0076}, {0x8631,    0x00bd},
+{0x8632,    0x0089}, {0x8633,    0x007b}, {0x8634,    0x007e},
+{0x8635,    0x0086}, {0x8636,    0x008e}, {0x8637,    0x0081},
+{0x8638,    0x0020}, {0x8639,    0x0026}, {0x863a,    0x000b},
+{0x863b,    0x0086}, {0x863c,    0x0002}, {0x863d,    0x00ce},
+{0x863e,    0x008f}, {0x863f,    0x0073}, {0x8640,    0x00bd},
+{0x8641,    0x0089}, {0x8642,    0x007b}, {0x8643,    0x007e},
+{0x8644,    0x0086}, {0x8645,    0x008e}, {0x8646,    0x0081},
+{0x8647,    0x0010}, {0x8648,    0x0026}, {0x8649,    0x000b},
+{0x864a,    0x0086}, {0x864b,    0x0001}, {0x864c,    0x00ce},
+{0x864d,    0x008f}, {0x864e,    0x0070}, {0x864f,    0x00bd},
+{0x8650,    0x0089}, {0x8651,    0x007b}, {0x8652,    0x007e},
+{0x8653,    0x0086}, {0x8654,    0x008e}, {0x8655,    0x0081},
+{0x8656,    0x0008}, {0x8657,    0x0026}, {0x8658,    0x000b},
+{0x8659,    0x0086}, {0x865a,    0x0008}, {0x865b,    0x00ce},
+{0x865c,    0x008f}, {0x865d,    0x0079}, {0x865e,    0x00bd},
+{0x865f,    0x0089}, {0x8660,    0x007f}, {0x8661,    0x007e},
+{0x8662,    0x0086}, {0x8663,    0x008e}, {0x8664,    0x0081},
+{0x8665,    0x0004}, {0x8666,    0x0026}, {0x8667,    0x000b},
+{0x8668,    0x0086}, {0x8669,    0x0004}, {0x866a,    0x00ce},
+{0x866b,    0x008f}, {0x866c,    0x0076}, {0x866d,    0x00bd},
+{0x866e,    0x0089}, {0x866f,    0x007f}, {0x8670,    0x007e},
+{0x8671,    0x0086}, {0x8672,    0x008e}, {0x8673,    0x0081},
+{0x8674,    0x0002}, {0x8675,    0x0026}, {0x8676,    0x000b},
+{0x8677,    0x008a}, {0x8678,    0x0002}, {0x8679,    0x00ce},
+{0x867a,    0x008f}, {0x867b,    0x0073}, {0x867c,    0x00bd},
+{0x867d,    0x0089}, {0x867e,    0x007f}, {0x867f,    0x007e},
+{0x8680,    0x0086}, {0x8681,    0x008e}, {0x8682,    0x0081},
+{0x8683,    0x0001}, {0x8684,    0x0026}, {0x8685,    0x0008},
+{0x8686,    0x0086}, {0x8687,    0x0001}, {0x8688,    0x00ce},
+{0x8689,    0x008f}, {0x868a,    0x0070}, {0x868b,    0x00bd},
+{0x868c,    0x0089}, {0x868d,    0x007f}, {0x868e,    0x00b6},
+{0x868f,    0x008f}, {0x8690,    0x007f}, {0x8691,    0x0081},
+{0x8692,    0x000f}, {0x8693,    0x0026}, {0x8694,    0x0003},
+{0x8695,    0x007e}, {0x8696,    0x0087}, {0x8697,    0x0047},
+{0x8698,    0x00b6}, {0x8699,    0x0012}, {0x869a,    0x0009},
+{0x869b,    0x0084}, {0x869c,    0x0003}, {0x869d,    0x0081},
+{0x869e,    0x0003}, {0x869f,    0x0027}, {0x86a0,    0x0006},
+{0x86a1,    0x007c}, {0x86a2,    0x0012}, {0x86a3,    0x0009},
+{0x86a4,    0x007e}, {0x86a5,    0x0085}, {0x86a6,    0x00fe},
+{0x86a7,    0x00b6}, {0x86a8,    0x0012}, {0x86a9,    0x0006},
+{0x86aa,    0x0084}, {0x86ab,    0x0007}, {0x86ac,    0x0081},
+{0x86ad,    0x0007}, {0x86ae,    0x0027}, {0x86af,    0x0008},
+{0x86b0,    0x008b}, {0x86b1,    0x0001}, {0x86b2,    0x00b7},
+{0x86b3,    0x0012}, {0x86b4,    0x0006}, {0x86b5,    0x007e},
+{0x86b6,    0x0086}, {0x86b7,    0x00d5}, {0x86b8,    0x00b6},
+{0x86b9,    0x008f}, {0x86ba,    0x0082}, {0x86bb,    0x0026},
+{0x86bc,    0x000a}, {0x86bd,    0x007c}, {0x86be,    0x008f},
+{0x86bf,    0x0082}, {0x86c0,    0x004f}, {0x86c1,    0x00b7},
+{0x86c2,    0x0012}, {0x86c3,    0x0006}, {0x86c4,    0x007e},
+{0x86c5,    0x0085}, {0x86c6,    0x00c0}, {0x86c7,    0x00b6},
+{0x86c8,    0x0012}, {0x86c9,    0x0006}, {0x86ca,    0x0084},
+{0x86cb,    0x003f}, {0x86cc,    0x0081}, {0x86cd,    0x003f},
+{0x86ce,    0x0027}, {0x86cf,    0x0010}, {0x86d0,    0x008b},
+{0x86d1,    0x0008}, {0x86d2,    0x00b7}, {0x86d3,    0x0012},
+{0x86d4,    0x0006}, {0x86d5,    0x00b6}, {0x86d6,    0x0012},
+{0x86d7,    0x0009}, {0x86d8,    0x0084}, {0x86d9,    0x00fc},
+{0x86da,    0x00b7}, {0x86db,    0x0012}, {0x86dc,    0x0009},
+{0x86dd,    0x007e}, {0x86de,    0x0085}, {0x86df,    0x00fe},
+{0x86e0,    0x00ce}, {0x86e1,    0x008f}, {0x86e2,    0x0070},
+{0x86e3,    0x0018}, {0x86e4,    0x00ce}, {0x86e5,    0x008f},
+{0x86e6,    0x0084}, {0x86e7,    0x00c6}, {0x86e8,    0x000c},
+{0x86e9,    0x00bd}, {0x86ea,    0x0089}, {0x86eb,    0x006f},
+{0x86ec,    0x00ce}, {0x86ed,    0x008f}, {0x86ee,    0x0084},
+{0x86ef,    0x0018}, {0x86f0,    0x00ce}, {0x86f1,    0x008f},
+{0x86f2,    0x0070}, {0x86f3,    0x00c6}, {0x86f4,    0x000c},
+{0x86f5,    0x00bd}, {0x86f6,    0x0089}, {0x86f7,    0x006f},
+{0x86f8,    0x00d6}, {0x86f9,    0x0083}, {0x86fa,    0x00c1},
+{0x86fb,    0x004f}, {0x86fc,    0x002d}, {0x86fd,    0x0003},
+{0x86fe,    0x007e}, {0x86ff,    0x0087}, {0x8700,    0x0040},
+{0x8701,    0x00b6}, {0x8702,    0x008f}, {0x8703,    0x007f},
+{0x8704,    0x0081}, {0x8705,    0x0007}, {0x8706,    0x0027},
+{0x8707,    0x000f}, {0x8708,    0x0081}, {0x8709,    0x000b},
+{0x870a,    0x0027}, {0x870b,    0x0015}, {0x870c,    0x0081},
+{0x870d,    0x000d}, {0x870e,    0x0027}, {0x870f,    0x001b},
+{0x8710,    0x0081}, {0x8711,    0x000e}, {0x8712,    0x0027},
+{0x8713,    0x0021}, {0x8714,    0x007e}, {0x8715,    0x0087},
+{0x8716,    0x0040}, {0x8717,    0x00f7}, {0x8718,    0x008f},
+{0x8719,    0x007b}, {0x871a,    0x0086}, {0x871b,    0x0002},
+{0x871c,    0x00b7}, {0x871d,    0x008f}, {0x871e,    0x007a},
+{0x871f,    0x0020}, {0x8720,    0x001c}, {0x8721,    0x00f7},
+{0x8722,    0x008f}, {0x8723,    0x0078}, {0x8724,    0x0086},
+{0x8725,    0x0002}, {0x8726,    0x00b7}, {0x8727,    0x008f},
+{0x8728,    0x0077}, {0x8729,    0x0020}, {0x872a,    0x0012},
+{0x872b,    0x00f7}, {0x872c,    0x008f}, {0x872d,    0x0075},
+{0x872e,    0x0086}, {0x872f,    0x0002}, {0x8730,    0x00b7},
+{0x8731,    0x008f}, {0x8732,    0x0074}, {0x8733,    0x0020},
+{0x8734,    0x0008}, {0x8735,    0x00f7}, {0x8736,    0x008f},
+{0x8737,    0x0072}, {0x8738,    0x0086}, {0x8739,    0x0002},
+{0x873a,    0x00b7}, {0x873b,    0x008f}, {0x873c,    0x0071},
+{0x873d,    0x007e}, {0x873e,    0x0087}, {0x873f,    0x0047},
+{0x8740,    0x0086}, {0x8741,    0x0004}, {0x8742,    0x0097},
+{0x8743,    0x0040}, {0x8744,    0x007e}, {0x8745,    0x0089},
+{0x8746,    0x006e}, {0x8747,    0x00ce}, {0x8748,    0x008f},
+{0x8749,    0x0072}, {0x874a,    0x00bd}, {0x874b,    0x0089},
+{0x874c,    0x00f7}, {0x874d,    0x00ce}, {0x874e,    0x008f},
+{0x874f,    0x0075}, {0x8750,    0x00bd}, {0x8751,    0x0089},
+{0x8752,    0x00f7}, {0x8753,    0x00ce}, {0x8754,    0x008f},
+{0x8755,    0x0078}, {0x8756,    0x00bd}, {0x8757,    0x0089},
+{0x8758,    0x00f7}, {0x8759,    0x00ce}, {0x875a,    0x008f},
+{0x875b,    0x007b}, {0x875c,    0x00bd}, {0x875d,    0x0089},
+{0x875e,    0x00f7}, {0x875f,    0x004f}, {0x8760,    0x00b7},
+{0x8761,    0x008f}, {0x8762,    0x007d}, {0x8763,    0x00b7},
+{0x8764,    0x008f}, {0x8765,    0x0081}, {0x8766,    0x00b6},
+{0x8767,    0x008f}, {0x8768,    0x0072}, {0x8769,    0x0027},
+{0x876a,    0x0047}, {0x876b,    0x007c}, {0x876c,    0x008f},
+{0x876d,    0x007d}, {0x876e,    0x00b6}, {0x876f,    0x008f},
+{0x8770,    0x0075}, {0x8771,    0x0027}, {0x8772,    0x003f},
+{0x8773,    0x007c}, {0x8774,    0x008f}, {0x8775,    0x007d},
+{0x8776,    0x00b6}, {0x8777,    0x008f}, {0x8778,    0x0078},
+{0x8779,    0x0027}, {0x877a,    0x0037}, {0x877b,    0x007c},
+{0x877c,    0x008f}, {0x877d,    0x007d}, {0x877e,    0x00b6},
+{0x877f,    0x008f}, {0x8780,    0x007b}, {0x8781,    0x0027},
+{0x8782,    0x002f}, {0x8783,    0x007f}, {0x8784,    0x008f},
+{0x8785,    0x007d}, {0x8786,    0x007c}, {0x8787,    0x008f},
+{0x8788,    0x0081}, {0x8789,    0x007a}, {0x878a,    0x008f},
+{0x878b,    0x0072}, {0x878c,    0x0027}, {0x878d,    0x001b},
+{0x878e,    0x007c}, {0x878f,    0x008f}, {0x8790,    0x007d},
+{0x8791,    0x007a}, {0x8792,    0x008f}, {0x8793,    0x0075},
+{0x8794,    0x0027}, {0x8795,    0x0016}, {0x8796,    0x007c},
+{0x8797,    0x008f}, {0x8798,    0x007d}, {0x8799,    0x007a},
+{0x879a,    0x008f}, {0x879b,    0x0078}, {0x879c,    0x0027},
+{0x879d,    0x0011}, {0x879e,    0x007c}, {0x879f,    0x008f},
+{0x87a0,    0x007d}, {0x87a1,    0x007a}, {0x87a2,    0x008f},
+{0x87a3,    0x007b}, {0x87a4,    0x0027}, {0x87a5,    0x000c},
+{0x87a6,    0x007e}, {0x87a7,    0x0087}, {0x87a8,    0x0083},
+{0x87a9,    0x007a}, {0x87aa,    0x008f}, {0x87ab,    0x0075},
+{0x87ac,    0x007a}, {0x87ad,    0x008f}, {0x87ae,    0x0078},
+{0x87af,    0x007a}, {0x87b0,    0x008f}, {0x87b1,    0x007b},
+{0x87b2,    0x00ce}, {0x87b3,    0x00c1}, {0x87b4,    0x00fc},
+{0x87b5,    0x00f6}, {0x87b6,    0x008f}, {0x87b7,    0x007d},
+{0x87b8,    0x003a}, {0x87b9,    0x00a6}, {0x87ba,    0x0000},
+{0x87bb,    0x00b7}, {0x87bc,    0x0012}, {0x87bd,    0x0070},
+{0x87be,    0x00b6}, {0x87bf,    0x008f}, {0x87c0,    0x0072},
+{0x87c1,    0x0026}, {0x87c2,    0x0003}, {0x87c3,    0x007e},
+{0x87c4,    0x0087}, {0x87c5,    0x00fa}, {0x87c6,    0x00b6},
+{0x87c7,    0x008f}, {0x87c8,    0x0075}, {0x87c9,    0x0026},
+{0x87ca,    0x000a}, {0x87cb,    0x0018}, {0x87cc,    0x00ce},
+{0x87cd,    0x008f}, {0x87ce,    0x0073}, {0x87cf,    0x00bd},
+{0x87d0,    0x0089}, {0x87d1,    0x00d5}, {0x87d2,    0x007e},
+{0x87d3,    0x0087}, {0x87d4,    0x00fa}, {0x87d5,    0x00b6},
+{0x87d6,    0x008f}, {0x87d7,    0x0078}, {0x87d8,    0x0026},
+{0x87d9,    0x000a}, {0x87da,    0x0018}, {0x87db,    0x00ce},
+{0x87dc,    0x008f}, {0x87dd,    0x0076}, {0x87de,    0x00bd},
+{0x87df,    0x0089}, {0x87e0,    0x00d5}, {0x87e1,    0x007e},
+{0x87e2,    0x0087}, {0x87e3,    0x00fa}, {0x87e4,    0x00b6},
+{0x87e5,    0x008f}, {0x87e6,    0x007b}, {0x87e7,    0x0026},
+{0x87e8,    0x000a}, {0x87e9,    0x0018}, {0x87ea,    0x00ce},
+{0x87eb,    0x008f}, {0x87ec,    0x0079}, {0x87ed,    0x00bd},
+{0x87ee,    0x0089}, {0x87ef,    0x00d5}, {0x87f0,    0x007e},
+{0x87f1,    0x0087}, {0x87f2,    0x00fa}, {0x87f3,    0x0086},
+{0x87f4,    0x0005}, {0x87f5,    0x0097}, {0x87f6,    0x0040},
+{0x87f7,    0x007e}, {0x87f8,    0x0089}, {0x87f9,    0x006e},
+{0x87fa,    0x00b6}, {0x87fb,    0x008f}, {0x87fc,    0x0075},
+{0x87fd,    0x0081}, {0x87fe,    0x0007}, {0x87ff,    0x002e},
+{0x8800,    0x00f2}, {0x8801,    0x00f6}, {0x8802,    0x0012},
+{0x8803,    0x0006}, {0x8804,    0x00c4}, {0x8805,    0x00f8},
+{0x8806,    0x001b}, {0x8807,    0x00b7}, {0x8808,    0x0012},
+{0x8809,    0x0006}, {0x880a,    0x00b6}, {0x880b,    0x008f},
+{0x880c,    0x0078}, {0x880d,    0x0081}, {0x880e,    0x0007},
+{0x880f,    0x002e}, {0x8810,    0x00e2}, {0x8811,    0x0048},
+{0x8812,    0x0048}, {0x8813,    0x0048}, {0x8814,    0x00f6},
+{0x8815,    0x0012}, {0x8816,    0x0006}, {0x8817,    0x00c4},
+{0x8818,    0x00c7}, {0x8819,    0x001b}, {0x881a,    0x00b7},
+{0x881b,    0x0012}, {0x881c,    0x0006}, {0x881d,    0x00b6},
+{0x881e,    0x008f}, {0x881f,    0x007b}, {0x8820,    0x0081},
+{0x8821,    0x0007}, {0x8822,    0x002e}, {0x8823,    0x00cf},
+{0x8824,    0x00f6}, {0x8825,    0x0012}, {0x8826,    0x0005},
+{0x8827,    0x00c4}, {0x8828,    0x00f8}, {0x8829,    0x001b},
+{0x882a,    0x00b7}, {0x882b,    0x0012}, {0x882c,    0x0005},
+{0x882d,    0x0086}, {0x882e,    0x0000}, {0x882f,    0x00f6},
+{0x8830,    0x008f}, {0x8831,    0x0071}, {0x8832,    0x00bd},
+{0x8833,    0x0089}, {0x8834,    0x0094}, {0x8835,    0x0086},
+{0x8836,    0x0001}, {0x8837,    0x00f6}, {0x8838,    0x008f},
+{0x8839,    0x0074}, {0x883a,    0x00bd}, {0x883b,    0x0089},
+{0x883c,    0x0094}, {0x883d,    0x0086}, {0x883e,    0x0002},
+{0x883f,    0x00f6}, {0x8840,    0x008f}, {0x8841,    0x0077},
+{0x8842,    0x00bd}, {0x8843,    0x0089}, {0x8844,    0x0094},
+{0x8845,    0x0086}, {0x8846,    0x0003}, {0x8847,    0x00f6},
+{0x8848,    0x008f}, {0x8849,    0x007a}, {0x884a,    0x00bd},
+{0x884b,    0x0089}, {0x884c,    0x0094}, {0x884d,    0x00ce},
+{0x884e,    0x008f}, {0x884f,    0x0070}, {0x8850,    0x00a6},
+{0x8851,    0x0001}, {0x8852,    0x0081}, {0x8853,    0x0001},
+{0x8854,    0x0027}, {0x8855,    0x0007}, {0x8856,    0x0081},
+{0x8857,    0x0003}, {0x8858,    0x0027}, {0x8859,    0x0003},
+{0x885a,    0x007e}, {0x885b,    0x0088}, {0x885c,    0x0066},
+{0x885d,    0x00a6}, {0x885e,    0x0000}, {0x885f,    0x00b8},
+{0x8860,    0x008f}, {0x8861,    0x0081}, {0x8862,    0x0084},
+{0x8863,    0x0001}, {0x8864,    0x0026}, {0x8865,    0x000b},
+{0x8866,    0x008c}, {0x8867,    0x008f}, {0x8868,    0x0079},
+{0x8869,    0x002c}, {0x886a,    0x000e}, {0x886b,    0x0008},
+{0x886c,    0x0008}, {0x886d,    0x0008}, {0x886e,    0x007e},
+{0x886f,    0x0088}, {0x8870,    0x0050}, {0x8871,    0x00b6},
+{0x8872,    0x0012}, {0x8873,    0x0004}, {0x8874,    0x008a},
+{0x8875,    0x0040}, {0x8876,    0x00b7}, {0x8877,    0x0012},
+{0x8878,    0x0004}, {0x8879,    0x00b6}, {0x887a,    0x0012},
+{0x887b,    0x0004}, {0x887c,    0x0084}, {0x887d,    0x00fb},
+{0x887e,    0x0084}, {0x887f,    0x00ef}, {0x8880,    0x00b7},
+{0x8881,    0x0012}, {0x8882,    0x0004}, {0x8883,    0x00b6},
+{0x8884,    0x0012}, {0x8885,    0x0007}, {0x8886,    0x0036},
+{0x8887,    0x00b6}, {0x8888,    0x008f}, {0x8889,    0x007c},
+{0x888a,    0x0048}, {0x888b,    0x0048}, {0x888c,    0x00b7},
+{0x888d,    0x0012}, {0x888e,    0x0007}, {0x888f,    0x0086},
+{0x8890,    0x0001}, {0x8891,    0x00ba}, {0x8892,    0x0012},
+{0x8893,    0x0004}, {0x8894,    0x00b7}, {0x8895,    0x0012},
+{0x8896,    0x0004}, {0x8897,    0x0001}, {0x8898,    0x0001},
+{0x8899,    0x0001}, {0x889a,    0x0001}, {0x889b,    0x0001},
+{0x889c,    0x0001}, {0x889d,    0x0086}, {0x889e,    0x00fe},
+{0x889f,    0x00b4}, {0x88a0,    0x0012}, {0x88a1,    0x0004},
+{0x88a2,    0x00b7}, {0x88a3,    0x0012}, {0x88a4,    0x0004},
+{0x88a5,    0x0086}, {0x88a6,    0x0002}, {0x88a7,    0x00ba},
+{0x88a8,    0x0012}, {0x88a9,    0x0004}, {0x88aa,    0x00b7},
+{0x88ab,    0x0012}, {0x88ac,    0x0004}, {0x88ad,    0x0086},
+{0x88ae,    0x00fd}, {0x88af,    0x00b4}, {0x88b0,    0x0012},
+{0x88b1,    0x0004}, {0x88b2,    0x00b7}, {0x88b3,    0x0012},
+{0x88b4,    0x0004}, {0x88b5,    0x0032}, {0x88b6,    0x00b7},
+{0x88b7,    0x0012}, {0x88b8,    0x0007}, {0x88b9,    0x00b6},
+{0x88ba,    0x0012}, {0x88bb,    0x0000}, {0x88bc,    0x0084},
+{0x88bd,    0x0008}, {0x88be,    0x0081}, {0x88bf,    0x0008},
+{0x88c0,    0x0027}, {0x88c1,    0x000f}, {0x88c2,    0x007c},
+{0x88c3,    0x0082}, {0x88c4,    0x0008}, {0x88c5,    0x0026},
+{0x88c6,    0x0007}, {0x88c7,    0x0086}, {0x88c8,    0x0076},
+{0x88c9,    0x0097}, {0x88ca,    0x0040}, {0x88cb,    0x007e},
+{0x88cc,    0x0089}, {0x88cd,    0x006e}, {0x88ce,    0x007e},
+{0x88cf,    0x0086}, {0x88d0,    0x00ec}, {0x88d1,    0x00b6},
+{0x88d2,    0x008f}, {0x88d3,    0x007f}, {0x88d4,    0x0081},
+{0x88d5,    0x000f}, {0x88d6,    0x0027}, {0x88d7,    0x003c},
+{0x88d8,    0x00bd}, {0x88d9,    0x00e6}, {0x88da,    0x00c7},
+{0x88db,    0x00b7}, {0x88dc,    0x0012}, {0x88dd,    0x000d},
+{0x88de,    0x00bd}, {0x88df,    0x00e6}, {0x88e0,    0x00cb},
+{0x88e1,    0x00b6}, {0x88e2,    0x0012}, {0x88e3,    0x0004},
+{0x88e4,    0x008a}, {0x88e5,    0x0020}, {0x88e6,    0x00b7},
+{0x88e7,    0x0012}, {0x88e8,    0x0004}, {0x88e9,    0x00ce},
+{0x88ea,    0x00ff}, {0x88eb,    0x00ff}, {0x88ec,    0x00b6},
+{0x88ed,    0x0012}, {0x88ee,    0x0000}, {0x88ef,    0x0081},
+{0x88f0,    0x000c}, {0x88f1,    0x0026}, {0x88f2,    0x0005},
+{0x88f3,    0x0009}, {0x88f4,    0x0026}, {0x88f5,    0x00f6},
+{0x88f6,    0x0027}, {0x88f7,    0x001c}, {0x88f8,    0x00b6},
+{0x88f9,    0x0012}, {0x88fa,    0x0004}, {0x88fb,    0x0084},
+{0x88fc,    0x00df}, {0x88fd,    0x00b7}, {0x88fe,    0x0012},
+{0x88ff,    0x0004}, {0x8900,    0x0096}, {0x8901,    0x0083},
+{0x8902,    0x0081}, {0x8903,    0x0007}, {0x8904,    0x002c},
+{0x8905,    0x0005}, {0x8906,    0x007c}, {0x8907,    0x0000},
+{0x8908,    0x0083}, {0x8909,    0x0020}, {0x890a,    0x0006},
+{0x890b,    0x0096}, {0x890c,    0x0083}, {0x890d,    0x008b},
+{0x890e,    0x0008}, {0x890f,    0x0097}, {0x8910,    0x0083},
+{0x8911,    0x007e}, {0x8912,    0x0085}, {0x8913,    0x0041},
+{0x8914,    0x007f}, {0x8915,    0x008f}, {0x8916,    0x007e},
+{0x8917,    0x0086}, {0x8918,    0x0080}, {0x8919,    0x00b7},
+{0x891a,    0x0012}, {0x891b,    0x000c}, {0x891c,    0x0086},
+{0x891d,    0x0001}, {0x891e,    0x00b7}, {0x891f,    0x008f},
+{0x8920,    0x007d}, {0x8921,    0x00b6}, {0x8922,    0x0012},
+{0x8923,    0x000c}, {0x8924,    0x0084}, {0x8925,    0x007f},
+{0x8926,    0x00b7}, {0x8927,    0x0012}, {0x8928,    0x000c},
+{0x8929,    0x008a}, {0x892a,    0x0080}, {0x892b,    0x00b7},
+{0x892c,    0x0012}, {0x892d,    0x000c}, {0x892e,    0x0086},
+{0x892f,    0x000a}, {0x8930,    0x00bd}, {0x8931,    0x008a},
+{0x8932,    0x0006}, {0x8933,    0x00b6}, {0x8934,    0x0012},
+{0x8935,    0x000a}, {0x8936,    0x002a}, {0x8937,    0x0009},
+{0x8938,    0x00b6}, {0x8939,    0x0012}, {0x893a,    0x000c},
+{0x893b,    0x00ba}, {0x893c,    0x008f}, {0x893d,    0x007d},
+{0x893e,    0x00b7}, {0x893f,    0x0012}, {0x8940,    0x000c},
+{0x8941,    0x00b6}, {0x8942,    0x008f}, {0x8943,    0x007e},
+{0x8944,    0x0081}, {0x8945,    0x0060}, {0x8946,    0x0027},
+{0x8947,    0x001a}, {0x8948,    0x008b}, {0x8949,    0x0020},
+{0x894a,    0x00b7}, {0x894b,    0x008f}, {0x894c,    0x007e},
+{0x894d,    0x00b6}, {0x894e,    0x0012}, {0x894f,    0x000c},
+{0x8950,    0x0084}, {0x8951,    0x009f}, {0x8952,    0x00ba},
+{0x8953,    0x008f}, {0x8954,    0x007e}, {0x8955,    0x00b7},
+{0x8956,    0x0012}, {0x8957,    0x000c}, {0x8958,    0x00b6},
+{0x8959,    0x008f}, {0x895a,    0x007d}, {0x895b,    0x0048},
+{0x895c,    0x00b7}, {0x895d,    0x008f}, {0x895e,    0x007d},
+{0x895f,    0x007e}, {0x8960,    0x0089}, {0x8961,    0x0021},
+{0x8962,    0x00b6}, {0x8963,    0x0012}, {0x8964,    0x0004},
+{0x8965,    0x008a}, {0x8966,    0x0020}, {0x8967,    0x00b7},
+{0x8968,    0x0012}, {0x8969,    0x0004}, {0x896a,    0x00bd},
+{0x896b,    0x008a}, {0x896c,    0x000a}, {0x896d,    0x004f},
+{0x896e,    0x0039}, {0x896f,    0x00a6}, {0x8970,    0x0000},
+{0x8971,    0x0018}, {0x8972,    0x00a7}, {0x8973,    0x0000},
+{0x8974,    0x0008}, {0x8975,    0x0018}, {0x8976,    0x0008},
+{0x8977,    0x005a}, {0x8978,    0x0026}, {0x8979,    0x00f5},
+{0x897a,    0x0039}, {0x897b,    0x0036}, {0x897c,    0x006c},
+{0x897d,    0x0000}, {0x897e,    0x0032}, {0x897f,    0x00ba},
+{0x8980,    0x008f}, {0x8981,    0x007f}, {0x8982,    0x00b7},
+{0x8983,    0x008f}, {0x8984,    0x007f}, {0x8985,    0x00b6},
+{0x8986,    0x0012}, {0x8987,    0x0009}, {0x8988,    0x0084},
+{0x8989,    0x0003}, {0x898a,    0x00a7}, {0x898b,    0x0001},
+{0x898c,    0x00b6}, {0x898d,    0x0012}, {0x898e,    0x0006},
+{0x898f,    0x0084}, {0x8990,    0x003f}, {0x8991,    0x00a7},
+{0x8992,    0x0002}, {0x8993,    0x0039}, {0x8994,    0x0036},
+{0x8995,    0x0086}, {0x8996,    0x0003}, {0x8997,    0x00b7},
+{0x8998,    0x008f}, {0x8999,    0x0080}, {0x899a,    0x0032},
+{0x899b,    0x00c1}, {0x899c,    0x0000}, {0x899d,    0x0026},
+{0x899e,    0x0006}, {0x899f,    0x00b7}, {0x89a0,    0x008f},
+{0x89a1,    0x007c}, {0x89a2,    0x007e}, {0x89a3,    0x0089},
+{0x89a4,    0x00c9}, {0x89a5,    0x00c1}, {0x89a6,    0x0001},
+{0x89a7,    0x0027}, {0x89a8,    0x0018}, {0x89a9,    0x00c1},
+{0x89aa,    0x0002}, {0x89ab,    0x0027}, {0x89ac,    0x000c},
+{0x89ad,    0x00c1}, {0x89ae,    0x0003}, {0x89af,    0x0027},
+{0x89b0,    0x0000}, {0x89b1,    0x00f6}, {0x89b2,    0x008f},
+{0x89b3,    0x0080}, {0x89b4,    0x0005}, {0x89b5,    0x0005},
+{0x89b6,    0x00f7}, {0x89b7,    0x008f}, {0x89b8,    0x0080},
+{0x89b9,    0x00f6}, {0x89ba,    0x008f}, {0x89bb,    0x0080},
+{0x89bc,    0x0005}, {0x89bd,    0x0005}, {0x89be,    0x00f7},
+{0x89bf,    0x008f}, {0x89c0,    0x0080}, {0x89c1,    0x00f6},
+{0x89c2,    0x008f}, {0x89c3,    0x0080}, {0x89c4,    0x0005},
+{0x89c5,    0x0005}, {0x89c6,    0x00f7}, {0x89c7,    0x008f},
+{0x89c8,    0x0080}, {0x89c9,    0x00f6}, {0x89ca,    0x008f},
+{0x89cb,    0x0080}, {0x89cc,    0x0053}, {0x89cd,    0x00f4},
+{0x89ce,    0x0012}, {0x89cf,    0x0007}, {0x89d0,    0x001b},
+{0x89d1,    0x00b7}, {0x89d2,    0x0012}, {0x89d3,    0x0007},
+{0x89d4,    0x0039}, {0x89d5,    0x00ce}, {0x89d6,    0x008f},
+{0x89d7,    0x0070}, {0x89d8,    0x00a6}, {0x89d9,    0x0000},
+{0x89da,    0x0018}, {0x89db,    0x00e6}, {0x89dc,    0x0000},
+{0x89dd,    0x0018}, {0x89de,    0x00a7}, {0x89df,    0x0000},
+{0x89e0,    0x00e7}, {0x89e1,    0x0000}, {0x89e2,    0x00a6},
+{0x89e3,    0x0001}, {0x89e4,    0x0018}, {0x89e5,    0x00e6},
+{0x89e6,    0x0001}, {0x89e7,    0x0018}, {0x89e8,    0x00a7},
+{0x89e9,    0x0001}, {0x89ea,    0x00e7}, {0x89eb,    0x0001},
+{0x89ec,    0x00a6}, {0x89ed,    0x0002}, {0x89ee,    0x0018},
+{0x89ef,    0x00e6}, {0x89f0,    0x0002}, {0x89f1,    0x0018},
+{0x89f2,    0x00a7}, {0x89f3,    0x0002}, {0x89f4,    0x00e7},
+{0x89f5,    0x0002}, {0x89f6,    0x0039}, {0x89f7,    0x00a6},
+{0x89f8,    0x0000}, {0x89f9,    0x0084}, {0x89fa,    0x0007},
+{0x89fb,    0x00e6}, {0x89fc,    0x0000}, {0x89fd,    0x00c4},
+{0x89fe,    0x0038}, {0x89ff,    0x0054}, {0x8a00,    0x0054},
+{0x8a01,    0x0054}, {0x8a02,    0x001b}, {0x8a03,    0x00a7},
+{0x8a04,    0x0000}, {0x8a05,    0x0039}, {0x8a06,    0x004a},
+{0x8a07,    0x0026}, {0x8a08,    0x00fd}, {0x8a09,    0x0039},
+{0x8a0a,    0x0096}, {0x8a0b,    0x0022}, {0x8a0c,    0x0084},
+{0x8a0d,    0x000f}, {0x8a0e,    0x0097}, {0x8a0f,    0x0022},
+{0x8a10,    0x0086}, {0x8a11,    0x0001}, {0x8a12,    0x00b7},
+{0x8a13,    0x008f}, {0x8a14,    0x0070}, {0x8a15,    0x00b6},
+{0x8a16,    0x0012}, {0x8a17,    0x0007}, {0x8a18,    0x00b7},
+{0x8a19,    0x008f}, {0x8a1a,    0x0071}, {0x8a1b,    0x00f6},
+{0x8a1c,    0x0012}, {0x8a1d,    0x000c}, {0x8a1e,    0x00c4},
+{0x8a1f,    0x000f}, {0x8a20,    0x00c8}, {0x8a21,    0x000f},
+{0x8a22,    0x00f7}, {0x8a23,    0x008f}, {0x8a24,    0x0072},
+{0x8a25,    0x00f6}, {0x8a26,    0x008f}, {0x8a27,    0x0072},
+{0x8a28,    0x00b6}, {0x8a29,    0x008f}, {0x8a2a,    0x0071},
+{0x8a2b,    0x0084}, {0x8a2c,    0x0003}, {0x8a2d,    0x0027},
+{0x8a2e,    0x0014}, {0x8a2f,    0x0081}, {0x8a30,    0x0001},
+{0x8a31,    0x0027}, {0x8a32,    0x001c}, {0x8a33,    0x0081},
+{0x8a34,    0x0002}, {0x8a35,    0x0027}, {0x8a36,    0x0024},
+{0x8a37,    0x00f4}, {0x8a38,    0x008f}, {0x8a39,    0x0070},
+{0x8a3a,    0x0027}, {0x8a3b,    0x002a}, {0x8a3c,    0x0096},
+{0x8a3d,    0x0022}, {0x8a3e,    0x008a}, {0x8a3f,    0x0080},
+{0x8a40,    0x007e}, {0x8a41,    0x008a}, {0x8a42,    0x0064},
+{0x8a43,    0x00f4}, {0x8a44,    0x008f}, {0x8a45,    0x0070},
+{0x8a46,    0x0027}, {0x8a47,    0x001e}, {0x8a48,    0x0096},
+{0x8a49,    0x0022}, {0x8a4a,    0x008a}, {0x8a4b,    0x0010},
+{0x8a4c,    0x007e}, {0x8a4d,    0x008a}, {0x8a4e,    0x0064},
+{0x8a4f,    0x00f4}, {0x8a50,    0x008f}, {0x8a51,    0x0070},
+{0x8a52,    0x0027}, {0x8a53,    0x0012}, {0x8a54,    0x0096},
+{0x8a55,    0x0022}, {0x8a56,    0x008a}, {0x8a57,    0x0020},
+{0x8a58,    0x007e}, {0x8a59,    0x008a}, {0x8a5a,    0x0064},
+{0x8a5b,    0x00f4}, {0x8a5c,    0x008f}, {0x8a5d,    0x0070},
+{0x8a5e,    0x0027}, {0x8a5f,    0x0006}, {0x8a60,    0x0096},
+{0x8a61,    0x0022}, {0x8a62,    0x008a}, {0x8a63,    0x0040},
+{0x8a64,    0x0097}, {0x8a65,    0x0022}, {0x8a66,    0x0074},
+{0x8a67,    0x008f}, {0x8a68,    0x0071}, {0x8a69,    0x0074},
+{0x8a6a,    0x008f}, {0x8a6b,    0x0071}, {0x8a6c,    0x0078},
+{0x8a6d,    0x008f}, {0x8a6e,    0x0070}, {0x8a6f,    0x00b6},
+{0x8a70,    0x008f}, {0x8a71,    0x0070}, {0x8a72,    0x0085},
+{0x8a73,    0x0010}, {0x8a74,    0x0027}, {0x8a75,    0x00af},
+{0x8a76,    0x00d6}, {0x8a77,    0x0022}, {0x8a78,    0x00c4},
+{0x8a79,    0x0010}, {0x8a7a,    0x0058}, {0x8a7b,    0x00b6},
+{0x8a7c,    0x0012}, {0x8a7d,    0x0070}, {0x8a7e,    0x0081},
+{0x8a7f,    0x00e4}, {0x8a80,    0x0027}, {0x8a81,    0x0036},
+{0x8a82,    0x0081}, {0x8a83,    0x00e1}, {0x8a84,    0x0026},
+{0x8a85,    0x000c}, {0x8a86,    0x0096}, {0x8a87,    0x0022},
+{0x8a88,    0x0084}, {0x8a89,    0x0020}, {0x8a8a,    0x0044},
+{0x8a8b,    0x001b}, {0x8a8c,    0x00d6}, {0x8a8d,    0x0022},
+{0x8a8e,    0x00c4}, {0x8a8f,    0x00cf}, {0x8a90,    0x0020},
+{0x8a91,    0x0023}, {0x8a92,    0x0058}, {0x8a93,    0x0081},
+{0x8a94,    0x00c6}, {0x8a95,    0x0026}, {0x8a96,    0x000d},
+{0x8a97,    0x0096}, {0x8a98,    0x0022}, {0x8a99,    0x0084},
+{0x8a9a,    0x0040}, {0x8a9b,    0x0044}, {0x8a9c,    0x0044},
+{0x8a9d,    0x001b}, {0x8a9e,    0x00d6}, {0x8a9f,    0x0022},
+{0x8aa0,    0x00c4}, {0x8aa1,    0x00af}, {0x8aa2,    0x0020},
+{0x8aa3,    0x0011}, {0x8aa4,    0x0058}, {0x8aa5,    0x0081},
+{0x8aa6,    0x0027}, {0x8aa7,    0x0026}, {0x8aa8,    0x000f},
+{0x8aa9,    0x0096}, {0x8aaa,    0x0022}, {0x8aab,    0x0084},
+{0x8aac,    0x0080}, {0x8aad,    0x0044}, {0x8aae,    0x0044},
+{0x8aaf,    0x0044}, {0x8ab0,    0x001b}, {0x8ab1,    0x00d6},
+{0x8ab2,    0x0022}, {0x8ab3,    0x00c4}, {0x8ab4,    0x006f},
+{0x8ab5,    0x001b}, {0x8ab6,    0x0097}, {0x8ab7,    0x0022},
+{0x8ab8,    0x0039}, {0x8ab9,    0x0027}, {0x8aba,    0x000c},
+{0x8abb,    0x007c}, {0x8abc,    0x0082}, {0x8abd,    0x0006},
+{0x8abe,    0x00bd}, {0x8abf,    0x00d9}, {0x8ac0,    0x00ed},
+{0x8ac1,    0x00b6}, {0x8ac2,    0x0082}, {0x8ac3,    0x0007},
+{0x8ac4,    0x007e}, {0x8ac5,    0x008a}, {0x8ac6,    0x00b9},
+{0x8ac7,    0x007f}, {0x8ac8,    0x0082}, {0x8ac9,    0x0006},
+{0x8aca,    0x0039}, { 0x0, 0x0 }
+};
+#endif
+
+
+/* phy types */
+#define   CAS_PHY_UNKNOWN       0x00
+#define   CAS_PHY_SERDES        0x01
+#define   CAS_PHY_MII_MDIO0     0x02
+#define   CAS_PHY_MII_MDIO1     0x04
+#define   CAS_PHY_MII(x)        ((x) & (CAS_PHY_MII_MDIO0 | CAS_PHY_MII_MDIO1))
+
+/* _RING_INDEX is the index for the ring sizes to be used.  _RING_SIZE
+ * is the actual size. the default index for the various rings is
+ * 8. NOTE: there a bunch of alignment constraints for the rings. to
+ * deal with that, i just allocate rings to create the desired
+ * alignment. here are the constraints:
+ *   RX DESC and COMP rings must be 8KB aligned
+ *   TX DESC must be 2KB aligned. 
+ * if you change the numbers, be cognizant of how the alignment will change
+ * in INIT_BLOCK as well.
+ */
+
+#define DESC_RING_I_TO_S(x)  (32*(1 << (x)))
+#define COMP_RING_I_TO_S(x)  (128*(1 << (x)))
+#define TX_DESC_RING_INDEX 4  /* 512 = 8k */
+#define RX_DESC_RING_INDEX 4  /* 512 = 8k */
+#define RX_COMP_RING_INDEX 4  /* 2048 = 64k: should be 4x rx ring size */
+
+#if (TX_DESC_RING_INDEX > 8) || (TX_DESC_RING_INDEX < 0)
+#error TX_DESC_RING_INDEX must be between 0 and 8
+#endif
+
+#if (RX_DESC_RING_INDEX > 8) || (RX_DESC_RING_INDEX < 0)
+#error RX_DESC_RING_INDEX must be between 0 and 8
+#endif
+
+#if (RX_COMP_RING_INDEX > 8) || (RX_COMP_RING_INDEX < 0)
+#error RX_COMP_RING_INDEX must be between 0 and 8
+#endif
+
+#define N_TX_RINGS                    MAX_TX_RINGS      /* for QoS */
+#define N_TX_RINGS_MASK               MAX_TX_RINGS_MASK
+#define N_RX_DESC_RINGS               MAX_RX_DESC_RINGS /* 1 for ipsec */
+#define N_RX_COMP_RINGS               0x1 /* for mult. PCI interrupts */
+
+/* number of flows that can go through re-assembly */
+#define N_RX_FLOWS                    64
+
+#define TX_DESC_RING_SIZE  DESC_RING_I_TO_S(TX_DESC_RING_INDEX)
+#define RX_DESC_RING_SIZE  DESC_RING_I_TO_S(RX_DESC_RING_INDEX)
+#define RX_COMP_RING_SIZE  COMP_RING_I_TO_S(RX_COMP_RING_INDEX)
+#define TX_DESC_RINGN_INDEX(x) TX_DESC_RING_INDEX
+#define RX_DESC_RINGN_INDEX(x) RX_DESC_RING_INDEX
+#define RX_COMP_RINGN_INDEX(x) RX_COMP_RING_INDEX
+#define TX_DESC_RINGN_SIZE(x)  TX_DESC_RING_SIZE
+#define RX_DESC_RINGN_SIZE(x)  RX_DESC_RING_SIZE
+#define RX_COMP_RINGN_SIZE(x)  RX_COMP_RING_SIZE
+
+/* convert values */
+#define CAS_BASE(x, y)                (((y) << (x ## _SHIFT)) & (x ## _MASK))
+#define CAS_VAL(x, y)                 (((y) & (x ## _MASK)) >> (x ## _SHIFT))
+#define CAS_TX_RINGN_BASE(y)          ((TX_DESC_RINGN_INDEX(y) << \
+                                        TX_CFG_DESC_RINGN_SHIFT(y)) & \
+                                        TX_CFG_DESC_RINGN_MASK(y))
+
+/* min is 2k, but we can't do jumbo frames unless it's at least 8k */
+#define CAS_MIN_PAGE_SHIFT            11 /* 2048 */
+#define CAS_JUMBO_PAGE_SHIFT          13 /* 8192 */
+#define CAS_MAX_PAGE_SHIFT            14 /* 16384 */             
+
+#define TX_DESC_BUFLEN_MASK         0x0000000000003FFFULL /* buffer length in
+                                                            bytes. 0 - 9256 */
+#define TX_DESC_BUFLEN_SHIFT        0
+#define TX_DESC_CSUM_START_MASK     0x00000000001F8000ULL /* checksum start. #
+                                                            of bytes to be 
+                                                            skipped before
+                                                            csum calc begins.
+                                                            value must be
+                                                            even */
+#define TX_DESC_CSUM_START_SHIFT    15
+#define TX_DESC_CSUM_STUFF_MASK     0x000000001FE00000ULL /* checksum stuff.
+                                                            byte offset w/in 
+                                                            the pkt for the
+                                                            1st csum byte.
+                                                            must be > 8 */
+#define TX_DESC_CSUM_STUFF_SHIFT    21
+#define TX_DESC_CSUM_EN             0x0000000020000000ULL /* enable checksum */
+#define TX_DESC_EOF                 0x0000000040000000ULL /* end of frame */
+#define TX_DESC_SOF                 0x0000000080000000ULL /* start of frame */
+#define TX_DESC_INTME               0x0000000100000000ULL /* interrupt me */
+#define TX_DESC_NO_CRC              0x0000000200000000ULL /* debugging only.
+                                                            CRC will not be
+                                                            inserted into
+                                                            outgoing frame. */
+struct cas_tx_desc {
+       u64     control;
+       u64     buffer;
+};
+
+/* descriptor ring for free buffers contains page-sized buffers. the index
+ * value is not used by the hw in any way. it's just stored and returned in
+ * the completion ring.
+ */
+struct cas_rx_desc {
+       u64     index;
+       u64     buffer;
+};
+
+/* received packets are put on the completion ring. */
+/* word 1 */
+#define RX_COMP1_DATA_SIZE_MASK           0x0000000007FFE000ULL   
+#define RX_COMP1_DATA_SIZE_SHIFT          13
+#define RX_COMP1_DATA_OFF_MASK            0x000001FFF8000000ULL
+#define RX_COMP1_DATA_OFF_SHIFT           27
+#define RX_COMP1_DATA_INDEX_MASK          0x007FFE0000000000ULL
+#define RX_COMP1_DATA_INDEX_SHIFT         41
+#define RX_COMP1_SKIP_MASK                0x0180000000000000ULL
+#define RX_COMP1_SKIP_SHIFT               55
+#define RX_COMP1_RELEASE_NEXT             0x0200000000000000ULL
+#define RX_COMP1_SPLIT_PKT                0x0400000000000000ULL
+#define RX_COMP1_RELEASE_FLOW             0x0800000000000000ULL  
+#define RX_COMP1_RELEASE_DATA             0x1000000000000000ULL  
+#define RX_COMP1_RELEASE_HDR              0x2000000000000000ULL
+#define RX_COMP1_TYPE_MASK                0xC000000000000000ULL
+#define RX_COMP1_TYPE_SHIFT               62
+
+/* word 2 */
+#define RX_COMP2_NEXT_INDEX_MASK          0x00000007FFE00000ULL
+#define RX_COMP2_NEXT_INDEX_SHIFT         21
+#define RX_COMP2_HDR_SIZE_MASK            0x00000FF800000000ULL
+#define RX_COMP2_HDR_SIZE_SHIFT           35
+#define RX_COMP2_HDR_OFF_MASK             0x0003F00000000000ULL
+#define RX_COMP2_HDR_OFF_SHIFT            44
+#define RX_COMP2_HDR_INDEX_MASK           0xFFFC000000000000ULL
+#define RX_COMP2_HDR_INDEX_SHIFT          50
+
+/* word 3 */
+#define RX_COMP3_SMALL_PKT                0x0000000000000001ULL
+#define RX_COMP3_JUMBO_PKT                0x0000000000000002ULL
+#define RX_COMP3_JUMBO_HDR_SPLIT_EN       0x0000000000000004ULL
+#define RX_COMP3_CSUM_START_MASK          0x000000000007F000ULL
+#define RX_COMP3_CSUM_START_SHIFT         12
+#define RX_COMP3_FLOWID_MASK              0x0000000001F80000ULL
+#define RX_COMP3_FLOWID_SHIFT             19
+#define RX_COMP3_OPCODE_MASK              0x000000000E000000ULL
+#define RX_COMP3_OPCODE_SHIFT             25
+#define RX_COMP3_FORCE_FLAG               0x0000000010000000ULL
+#define RX_COMP3_NO_ASSIST                0x0000000020000000ULL
+#define RX_COMP3_LOAD_BAL_MASK            0x000001F800000000ULL
+#define RX_COMP3_LOAD_BAL_SHIFT           35
+#define RX_PLUS_COMP3_ENC_PKT             0x0000020000000000ULL /* cas+ */
+#define RX_COMP3_L3_HEAD_OFF_MASK         0x0000FE0000000000ULL /* cas */
+#define RX_COMP3_L3_HEAD_OFF_SHIFT        41
+#define RX_PLUS_COMP_L3_HEAD_OFF_MASK     0x0000FC0000000000ULL /* cas+ */
+#define RX_PLUS_COMP_L3_HEAD_OFF_SHIFT    42
+#define RX_COMP3_SAP_MASK                 0xFFFF000000000000ULL
+#define RX_COMP3_SAP_SHIFT                48
+
+/* word 4 */
+#define RX_COMP4_TCP_CSUM_MASK            0x000000000000FFFFULL
+#define RX_COMP4_TCP_CSUM_SHIFT           0
+#define RX_COMP4_PKT_LEN_MASK             0x000000003FFF0000ULL
+#define RX_COMP4_PKT_LEN_SHIFT            16
+#define RX_COMP4_PERFECT_MATCH_MASK       0x00000003C0000000ULL
+#define RX_COMP4_PERFECT_MATCH_SHIFT      30
+#define RX_COMP4_ZERO                     0x0000080000000000ULL
+#define RX_COMP4_HASH_VAL_MASK            0x0FFFF00000000000ULL
+#define RX_COMP4_HASH_VAL_SHIFT           44
+#define RX_COMP4_HASH_PASS                0x1000000000000000ULL
+#define RX_COMP4_BAD                      0x4000000000000000ULL
+#define RX_COMP4_LEN_MISMATCH             0x8000000000000000ULL
+
+/* we encode the following: ring/index/release. only 14 bits
+ * are usable.
+ * NOTE: the encoding is dependent upon RX_DESC_RING_SIZE and 
+ *       MAX_RX_DESC_RINGS. */
+#define RX_INDEX_NUM_MASK                 0x0000000000000FFFULL
+#define RX_INDEX_NUM_SHIFT                0
+#define RX_INDEX_RING_MASK                0x0000000000001000ULL
+#define RX_INDEX_RING_SHIFT               12
+#define RX_INDEX_RELEASE                  0x0000000000002000ULL
+
+struct cas_rx_comp {
+       u64     word1;
+       u64     word2;
+       u64     word3;
+       u64     word4;
+}; 
+
+enum link_state {
+       link_down = 0,  /* No link, will retry */
+       link_aneg,      /* Autoneg in progress */
+       link_force_try, /* Try Forced link speed */
+       link_force_ret, /* Forced mode worked, retrying autoneg */
+       link_force_ok,  /* Stay in forced mode */
+       link_up         /* Link is up */
+};
+
+typedef struct cas_page {
+       struct list_head list;
+       struct page *buffer;
+       dma_addr_t dma_addr;
+       int used;
+} cas_page_t;
+
+
+/* some alignment constraints:
+ * TX DESC, RX DESC, and RX COMP must each be 8K aligned.
+ * TX COMPWB must be 8-byte aligned. 
+ * to accomplish this, here's what we do:
+ * 
+ * INIT_BLOCK_RX_COMP  = 64k (already aligned)
+ * INIT_BLOCK_RX_DESC  = 8k
+ * INIT_BLOCK_TX       = 8k
+ * INIT_BLOCK_RX1_DESC = 8k
+ * TX COMPWB
+ */
+#define INIT_BLOCK_TX           (TX_DESC_RING_SIZE)
+#define INIT_BLOCK_RX_DESC      (RX_DESC_RING_SIZE)
+#define INIT_BLOCK_RX_COMP      (RX_COMP_RING_SIZE)
+
+struct cas_init_block {
+       struct cas_rx_comp rxcs[N_RX_COMP_RINGS][INIT_BLOCK_RX_COMP];
+       struct cas_rx_desc rxds[N_RX_DESC_RINGS][INIT_BLOCK_RX_DESC]; 
+       struct cas_tx_desc txds[N_TX_RINGS][INIT_BLOCK_TX];
+       u64 tx_compwb; 
+};
+
+/* tiny buffers to deal with target abort issue. we allocate a bit
+ * over so that we don't have target abort issues with these buffers
+ * as well.
+ */
+#define TX_TINY_BUF_LEN    0x100
+#define TX_TINY_BUF_BLOCK  ((INIT_BLOCK_TX + 1)*TX_TINY_BUF_LEN)
+
+struct cas_tiny_count {
+       int nbufs;
+       int used;
+};
+
+struct cas {
+       spinlock_t lock; /* for most bits */
+       spinlock_t tx_lock[N_TX_RINGS]; /* tx bits */
+       spinlock_t stat_lock[N_TX_RINGS + 1]; /* for stat gathering */
+       spinlock_t rx_inuse_lock; /* rx inuse list */
+       spinlock_t rx_spare_lock; /* rx spare list */
+
+       void __iomem *regs;
+       int tx_new[N_TX_RINGS], tx_old[N_TX_RINGS];
+       int rx_old[N_RX_DESC_RINGS];
+       int rx_cur[N_RX_COMP_RINGS], rx_new[N_RX_COMP_RINGS];
+       int rx_last[N_RX_DESC_RINGS]; 
+
+       /* Set when chip is actually in operational state
+        * (ie. not power managed) */
+       int hw_running;
+       int opened;
+       struct semaphore pm_sem; /* open/close/suspend/resume */
+
+       struct cas_init_block *init_block;
+       struct cas_tx_desc *init_txds[MAX_TX_RINGS];
+       struct cas_rx_desc *init_rxds[MAX_RX_DESC_RINGS];
+       struct cas_rx_comp *init_rxcs[MAX_RX_COMP_RINGS];
+
+       /* we use sk_buffs for tx and pages for rx. the rx skbuffs
+        * are there for flow re-assembly. */
+       struct sk_buff      *tx_skbs[N_TX_RINGS][TX_DESC_RING_SIZE];
+       struct sk_buff_head  rx_flows[N_RX_FLOWS];
+       cas_page_t          *rx_pages[N_RX_DESC_RINGS][RX_DESC_RING_SIZE];
+       struct list_head     rx_spare_list, rx_inuse_list;
+       int                  rx_spares_needed;
+
+       /* for small packets when copying would be quicker than
+          mapping */
+       struct cas_tiny_count tx_tiny_use[N_TX_RINGS][TX_DESC_RING_SIZE];
+       u8 *tx_tiny_bufs[N_TX_RINGS];
+
+       u32                     msg_enable;
+
+       /* N_TX_RINGS must be >= N_RX_DESC_RINGS */
+       struct net_device_stats net_stats[N_TX_RINGS + 1];
+
+       u32                     pci_cfg[64 >> 2];
+       u8                      pci_revision;
+
+       int                     phy_type;
+       int                     phy_addr;
+       u32                     phy_id;
+#define CAS_FLAG_1000MB_CAP     0x00000001
+#define CAS_FLAG_REG_PLUS       0x00000002
+#define CAS_FLAG_TARGET_ABORT   0x00000004
+#define CAS_FLAG_SATURN         0x00000008
+#define CAS_FLAG_RXD_POST_MASK  0x000000F0
+#define CAS_FLAG_RXD_POST_SHIFT 4
+#define CAS_FLAG_RXD_POST(x)    ((1 << (CAS_FLAG_RXD_POST_SHIFT + (x))) & \
+                                 CAS_FLAG_RXD_POST_MASK)
+#define CAS_FLAG_ENTROPY_DEV    0x00000100
+#define CAS_FLAG_NO_HW_CSUM     0x00000200
+       u32                     cas_flags;
+       int                     packet_min; /* minimum packet size */
+       int                     tx_fifo_size;
+       int                     rx_fifo_size;
+       int                     rx_pause_off;
+       int                     rx_pause_on;
+       int                     crc_size;      /* 4 if half-duplex */
+
+       int                     pci_irq_INTC;
+       int                     min_frame_size; /* for tx fifo workaround */
+
+       /* page size allocation */
+       int                     page_size; 
+       int                     page_order;
+       int                     mtu_stride;
+
+       u32                     mac_rx_cfg;
+
+       /* Autoneg & PHY control */
+       int                     link_cntl;
+       int                     link_fcntl;
+       enum link_state         lstate;
+       struct timer_list       link_timer;
+       int                     timer_ticks;
+       struct work_struct      reset_task;
+#if 0
+       atomic_t                reset_task_pending;
+#else
+       atomic_t                reset_task_pending;
+       atomic_t                reset_task_pending_mtu;
+       atomic_t                reset_task_pending_spare;
+       atomic_t                reset_task_pending_all;
+#endif
+
+#ifdef CONFIG_CASSINI_QGE_DEBUG
+       atomic_t interrupt_seen; /* 1 if any interrupts are getting through */
+#endif
+       
+       /* Link-down problem workaround */
+#define LINK_TRANSITION_UNKNOWN        0
+#define LINK_TRANSITION_ON_FAILURE     1
+#define LINK_TRANSITION_STILL_FAILED   2
+#define LINK_TRANSITION_LINK_UP        3
+#define LINK_TRANSITION_LINK_CONFIG    4
+#define LINK_TRANSITION_LINK_DOWN      5
+#define LINK_TRANSITION_REQUESTED_RESET        6
+       int                     link_transition;
+       int                     link_transition_jiffies_valid;
+       unsigned long           link_transition_jiffies;
+
+       /* Tuning */
+       u8 orig_cacheline_size; /* value when loaded */
+#define CAS_PREF_CACHELINE_SIZE         0x20   /* Minimum desired */
+
+       /* Diagnostic counters and state. */
+       int                     casreg_len; /* reg-space size for dumping */
+       u64                     pause_entered;
+       u16                     pause_last_time_recvd;
+  
+       dma_addr_t block_dvma, tx_tiny_dvma[N_TX_RINGS];
+       struct pci_dev *pdev;
+       struct net_device *dev;
+};
+
+#define TX_DESC_NEXT(r, x)  (((x) + 1) & (TX_DESC_RINGN_SIZE(r) - 1))
+#define RX_DESC_ENTRY(r, x) ((x) & (RX_DESC_RINGN_SIZE(r) - 1))
+#define RX_COMP_ENTRY(r, x) ((x) & (RX_COMP_RINGN_SIZE(r) - 1))
+
+#define TX_BUFF_COUNT(r, x, y)    ((x) <= (y) ? ((y) - (x)) : \
+        (TX_DESC_RINGN_SIZE(r) - (x) + (y)))    
+
+#define TX_BUFFS_AVAIL(cp, i)  ((cp)->tx_old[(i)] <= (cp)->tx_new[(i)] ? \
+        (cp)->tx_old[(i)] + (TX_DESC_RINGN_SIZE(i) - 1) - (cp)->tx_new[(i)] : \
+        (cp)->tx_old[(i)] - (cp)->tx_new[(i)] - 1)
+
+#define CAS_ALIGN(addr, align) \
+     (((unsigned long) (addr) + ((align) - 1UL)) & ~((align) - 1))
+
+#define RX_FIFO_SIZE                  16384
+#define EXPANSION_ROM_SIZE            65536
+
+#define CAS_MC_EXACT_MATCH_SIZE       15
+#define CAS_MC_HASH_SIZE              256
+#define CAS_MC_HASH_MAX              (CAS_MC_EXACT_MATCH_SIZE + \
+                                      CAS_MC_HASH_SIZE)
+
+#define TX_TARGET_ABORT_LEN           0x20
+#define RX_SWIVEL_OFF_VAL             0x2
+#define RX_AE_FREEN_VAL(x)            (RX_DESC_RINGN_SIZE(x) >> 1)
+#define RX_AE_COMP_VAL                (RX_COMP_RING_SIZE >> 1)
+#define RX_BLANK_INTR_PKT_VAL         0x05
+#define RX_BLANK_INTR_TIME_VAL        0x0F
+#define HP_TCP_THRESH_VAL             1530 /* reduce to enable reassembly */
+
+#define RX_SPARE_COUNT                (RX_DESC_RING_SIZE >> 1)
+#define RX_SPARE_RECOVER_VAL          (RX_SPARE_COUNT >> 2)
+
+#endif /* _CASSINI_H */
index cdc07ccd7332fb7b4b9e006bf0625331cce5729a..a6078ad9b654ff0295901a885a72c730a4188c8b 100644 (file)
 
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #if ALLOW_DMA
 #include <asm/dma.h>
 #endif
index 32d5fabd4b1019a2c26378f72dbd7d6d518fb2e4..a2c4dd4fb2218071fbffb8aa9f9438ddacff359a 100644 (file)
@@ -99,7 +99,7 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs
 static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter*);
 
 #ifdef CONFIG_PROC_FS
-#define IBMVETH_PROC_DIR "ibmveth"
+#define IBMVETH_PROC_DIR "net/ibmveth"
 static struct proc_dir_entry *ibmveth_proc_dir;
 #endif
 
@@ -1010,7 +1010,7 @@ static int __devexit ibmveth_remove(struct vio_dev *dev)
 #ifdef CONFIG_PROC_FS
 static void ibmveth_proc_register_driver(void)
 {
-       ibmveth_proc_dir = create_proc_entry(IBMVETH_PROC_DIR, S_IFDIR, proc_net);
+       ibmveth_proc_dir = proc_mkdir(IBMVETH_PROC_DIR, NULL);
        if (ibmveth_proc_dir) {
                SET_MODULE_OWNER(ibmveth_proc_dir);
        }
@@ -1018,7 +1018,7 @@ static void ibmveth_proc_register_driver(void)
 
 static void ibmveth_proc_unregister_driver(void)
 {
-       remove_proc_entry(IBMVETH_PROC_DIR, proc_net);
+       remove_proc_entry(IBMVETH_PROC_DIR, NULL);
 }
 
 static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) 
index 6d9de626c9670db8e0f4d436cfbfda6913fd6ceb..651c5a6578fd35cc8dd69a3e70ff3341c5366329 100644 (file)
@@ -1875,11 +1875,11 @@ static int __init vlsi_mod_init(void)
 
        sirpulse = !!sirpulse;
 
-       /* create_proc_entry returns NULL if !CONFIG_PROC_FS.
+       /* proc_mkdir returns NULL if !CONFIG_PROC_FS.
         * Failure to create the procfs entry is handled like running
         * without procfs - it's not required for the driver to work.
         */
-       vlsi_proc_root = create_proc_entry(PROC_DIR, S_IFDIR, NULL);
+       vlsi_proc_root = proc_mkdir(PROC_DIR, NULL);
        if (vlsi_proc_root) {
                /* protect registered procdir against module removal.
                 * Because we are in the module init path there's no race
index 82f236cc3b9b31e4aa9df662a639456d519ea103..a842ecc60a34000d746c7d96aff16ca1f661f3e2 100644 (file)
@@ -1070,7 +1070,7 @@ static int __init pppoe_proc_init(void)
 {
        struct proc_dir_entry *p;
 
-       p = create_proc_entry("pppoe", S_IRUGO, proc_net);
+       p = create_proc_entry("net/pppoe", S_IRUGO, NULL);
        if (!p)
                return -ENOMEM;
 
@@ -1142,7 +1142,7 @@ static void __exit pppoe_exit(void)
        dev_remove_pack(&pppoes_ptype);
        dev_remove_pack(&pppoed_ptype);
        unregister_netdevice_notifier(&pppoe_notifier);
-       remove_proc_entry("pppoe", proc_net);
+       remove_proc_entry("net/pppoe", NULL);
        proto_unregister(&pppoe_sk_proto);
 }
 
index f9223c1c5aa45f95cb501252a341073ff8e19483..afb3f186b8843b96b4ad0214c18e40515a11b091 100644 (file)
@@ -92,8 +92,7 @@ VERSION 2.2LK <2005/01/25>
 #endif /* RTL8169_DEBUG */
 
 #define R8169_MSG_DEFAULT \
-       (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFUP | \
-        NETIF_MSG_IFDOWN)
+       (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
 
 #define TX_BUFFS_AVAIL(tp) \
        (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
index 2e72d79a143c1ae4c57959eae8cfbcccd76f6968..b18c92cb629e8a34ee95888f0ecd8498eacddf6a 100644 (file)
@@ -235,7 +235,7 @@ static int      SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
  * Extern Function Prototypes
  *
  ******************************************************************************/
-static const char      SKRootName[] = "sk98lin";
+static const char      SKRootName[] = "net/sk98lin";
 static struct          proc_dir_entry *pSkRootDir;
 extern struct  file_operations sk_proc_fops;
 
@@ -5242,20 +5242,20 @@ static int __init skge_init(void)
 {
        int error;
 
-       pSkRootDir = proc_mkdir(SKRootName, proc_net);
+       pSkRootDir = proc_mkdir(SKRootName, NULL);
        if (pSkRootDir) 
                pSkRootDir->owner = THIS_MODULE;
        
        error = pci_register_driver(&skge_driver);
        if (error)
-               proc_net_remove(SKRootName);
+               remove_proc_entry(SKRootName, NULL);
        return error;
 }
 
 static void __exit skge_exit(void)
 {
        pci_unregister_driver(&skge_driver);
-       proc_net_remove(SKRootName);
+       remove_proc_entry(SKRootName, NULL);
 
 }
 
index 81f4aedf534c32bfe1faaabb8dd4cc301b00f3ab..25f85fb9df46d33b16fafa3f0be04b2dd757aef6 100644 (file)
@@ -67,8 +67,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.40"
-#define DRV_MODULE_RELDATE     "September 15, 2005"
+#define DRV_MODULE_VERSION     "3.41"
+#define DRV_MODULE_RELDATE     "September 27, 2005"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -3389,7 +3389,8 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
        struct tg3 *tp = netdev_priv(dev);
        struct tg3_hw_status *sblk = tp->hw_status;
 
-       if (sblk->status & SD_STATUS_UPDATED) {
+       if ((sblk->status & SD_STATUS_UPDATED) ||
+           !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
                tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
                             0x00000001);
                return IRQ_RETVAL(1);
@@ -5395,6 +5396,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
        struct tg3 *tp = netdev_priv(dev);
        struct sockaddr *addr = p;
 
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EINVAL;
+
        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
        spin_lock_bh(&tp->lock);
@@ -5806,6 +5810,13 @@ static int tg3_reset_hw(struct tg3 *tp)
        }
        memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
 
+       if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
+               tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
+               /* reset to prevent losing 1st rx packet intermittently */
+               tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+               udelay(10);
+       }
+
        tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
                MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
        tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
@@ -5937,7 +5948,7 @@ static int tg3_reset_hw(struct tg3 *tp)
        tw32(MAC_LED_CTRL, tp->led_ctrl);
 
        tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
-       if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) {
+       if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
                tw32_f(MAC_RX_MODE, RX_MODE_RESET);
                udelay(10);
        }
@@ -7360,12 +7371,17 @@ static int tg3_nway_reset(struct net_device *dev)
        if (!netif_running(dev))
                return -EAGAIN;
 
+       if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+               return -EINVAL;
+
        spin_lock_bh(&tp->lock);
        r = -EINVAL;
        tg3_readphy(tp, MII_BMCR, &bmcr);
        if (!tg3_readphy(tp, MII_BMCR, &bmcr) &&
-           (bmcr & BMCR_ANENABLE)) {
-               tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART);
+           ((bmcr & BMCR_ANENABLE) ||
+            (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) {
+               tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART |
+                                          BMCR_ANENABLE);
                r = 0;
        }
        spin_unlock_bh(&tp->lock);
@@ -7927,19 +7943,32 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
        struct tg3_rx_buffer_desc *desc;
 
        if (loopback_mode == TG3_MAC_LOOPBACK) {
+               /* HW errata - mac loopback fails in some cases on 5780.
+                * Normal traffic and PHY loopback are not affected by
+                * errata.
+                */
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+                       return 0;
+
                mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
                           MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
                           MAC_MODE_PORT_MODE_GMII;
                tw32(MAC_MODE, mac_mode);
        } else if (loopback_mode == TG3_PHY_LOOPBACK) {
+               tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
+                                          BMCR_SPEED1000);
+               udelay(40);
+               /* reset to prevent losing 1st rx packet intermittently */
+               if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
+                       tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+                       udelay(10);
+                       tw32_f(MAC_RX_MODE, tp->rx_mode);
+               }
                mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
                           MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
                if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
                        mac_mode &= ~MAC_MODE_LINK_POLARITY;
                tw32(MAC_MODE, mac_mode);
-
-               tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
-                                          BMCR_SPEED1000);
        }
        else
                return -EINVAL;
@@ -10324,6 +10353,44 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        };
 }
 
+static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
+{
+       if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+               strcpy(str, "PCI Express");
+               return str;
+       } else if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
+               u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL) & 0x1f;
+
+               strcpy(str, "PCIX:");
+
+               if ((clock_ctrl == 7) ||
+                   ((tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK) ==
+                    GRC_MISC_CFG_BOARD_ID_5704CIOBE))
+                       strcat(str, "133MHz");
+               else if (clock_ctrl == 0)
+                       strcat(str, "33MHz");
+               else if (clock_ctrl == 2)
+                       strcat(str, "50MHz");
+               else if (clock_ctrl == 4)
+                       strcat(str, "66MHz");
+               else if (clock_ctrl == 6)
+                       strcat(str, "100MHz");
+               else if (clock_ctrl == 7)
+                       strcat(str, "133MHz");
+       } else {
+               strcpy(str, "PCI:");
+               if (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED)
+                       strcat(str, "66MHz");
+               else
+                       strcat(str, "33MHz");
+       }
+       if (tp->tg3_flags & TG3_FLAG_PCI_32BIT)
+               strcat(str, ":32-bit");
+       else
+               strcat(str, ":64-bit");
+       return str;
+}
+
 static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp)
 {
        struct pci_dev *peer;
@@ -10386,6 +10453,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        struct net_device *dev;
        struct tg3 *tp;
        int i, err, pci_using_dac, pm_cap;
+       char str[40];
 
        if (tg3_version_printed++ == 0)
                printk(KERN_INFO "%s", version);
@@ -10631,16 +10699,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        pci_set_drvdata(pdev, dev);
 
-       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ",
+       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ",
               dev->name,
               tp->board_part_number,
               tp->pci_chip_rev_id,
               tg3_phy_string(tp),
-              ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""),
-              ((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ?
-               ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") :
-               ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")),
-              ((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"),
+              tg3_bus_string(tp, str),
               (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000");
 
        for (i = 0; i < 6; i++)
index c184b773e58543be34027d65810b7fdb2f4f1539..2e733c60bfa40f497a991c89038f586b9cd85d50 100644 (file)
@@ -2246,6 +2246,7 @@ struct tg3 {
         (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
         (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
         (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
+        (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5780 || \
         (X) == PHY_ID_BCM8002)
 
        struct tg3_hw_stats             *hw_stats;
index 8de49fe57233504ffdbf62cf310a9c34c22b286e..6deb7cc810cca9574356a0f84172e2057dce3869 100644 (file)
@@ -2458,7 +2458,6 @@ struct net_device *alloc_orinocodev(int sizeof_card,
        dev->watchdog_timeo = HZ; /* 1 second timeout */
        dev->get_stats = orinoco_get_stats;
        dev->ethtool_ops = &orinoco_ethtool_ops;
-       dev->get_wireless_stats = orinoco_get_wireless_stats;
        dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
        dev->change_mtu = orinoco_change_mtu;
        dev->set_multicast_list = orinoco_set_multicast_list;
@@ -4399,6 +4398,7 @@ static const struct iw_handler_def orinoco_handler_def = {
        .standard = orinoco_handler,
        .private = orinoco_private_handler,
        .private_args = orinoco_privtab,
+       .get_wireless_stats = orinoco_get_wireless_stats,
 };
 
 static void orinoco_get_drvinfo(struct net_device *dev,
index ddc741e6ecbff04b1272817df92e2683fc0f2b09..36cc9a96a3387c4d7619546cc36c1bd48bfcb675 100644 (file)
@@ -146,7 +146,7 @@ config I82365
 
 config TCIC
        tristate "Databook TCIC host bridge support"
-       depends on PCMCIA
+       depends on PCMCIA && ISA
        select PCCARD_NONSTATIC
        help
          Say Y here to include support for the Databook TCIC family of PCMCIA
index 1d755e20880cebff5015681c217dd4d672c16c97..3f6d51d11374063b0f3e0c86de1d75e23c1f3b34 100644 (file)
@@ -228,6 +228,11 @@ int cb_alloc(struct pcmcia_socket * s)
        pci_bus_size_bridges(bus);
        pci_bus_assign_resources(bus);
        cardbus_assign_irqs(bus, s->pci_irq);
+
+       /* socket specific tune function */
+       if (s->tune_bridge)
+               s->tune_bridge(s, bus);
+
        pci_enable_bridges(bus);
        pci_bus_add_devices(bus);
 
index 08d1c92882647a2e1801722236f3349973fdf55b..94be9e51654e39da4ac7ab5694eb7bc9b89723a3 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <asm/hardware.h>
 #include <asm/io.h>
-#include <asm/mach-types.h>
 #include <asm/sizes.h>
 
 #include <asm/arch/mux.h>
index c42455d20eb683c6d2c99de733966ad403c5941d..f9a5c70284b5a8901a7afbd86d07f39b1330978b 100644 (file)
@@ -691,7 +691,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
        unsigned long size = end - start + 1;
        int ret = 0;
 
-       if (end <= start)
+       if (end < start)
                return -EINVAL;
 
        down(&rsrc_sem);
@@ -724,7 +724,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
        unsigned long size = end - start + 1;
        int ret = 0;
 
-       if (end <= start)
+       if (end < start)
                return -EINVAL;
 
        if (end > IO_SPACE_LIMIT)
@@ -817,7 +817,7 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
 
        /* if we got at least one of IO, and one of MEM, we can be glad and
         * activate the PCMCIA subsystem */
-       if (done & (IORESOURCE_MEM | IORESOURCE_IO))
+       if (done == (IORESOURCE_MEM | IORESOURCE_IO))
                s->resource_setup_done = 1;
 
        return 0;
@@ -925,7 +925,7 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size
                                return -EINVAL;
                }
        }
-       if (end_addr <= start_addr)
+       if (end_addr < start_addr)
                return -EINVAL;
 
        ret = adjust_io(s, add, start_addr, end_addr);
@@ -977,7 +977,7 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz
                                return -EINVAL;
                }
        }
-       if (end_addr <= start_addr)
+       if (end_addr < start_addr)
                return -EINVAL;
 
        ret = adjust_memory(s, add, start_addr, end_addr);
index fbe233e19cebb285d620363c42d730b32c5a729b..da0b404561c92946cc4e7e9e6d632f6ec0655935 100644 (file)
@@ -59,6 +59,7 @@
 
 #define  TI122X_SCR_SER_STEP           0xc0000000
 #define  TI122X_SCR_INTRTIE            0x20000000
+#define  TIXX21_SCR_TIEALL             0x10000000
 #define  TI122X_SCR_CBRSVD             0x00400000
 #define  TI122X_SCR_MRBURSTDN          0x00008000
 #define  TI122X_SCR_MRBURSTUP          0x00004000
 /* EnE test register */
 #define ENE_TEST_C9                    0xc9    /* 8bit */
 #define ENE_TEST_C9_TLTENABLE          0x02
+#define ENE_TEST_C9_PFENABLE_F0                0x04
+#define ENE_TEST_C9_PFENABLE_F1                0x08
+#define ENE_TEST_C9_PFENABLE           (ENE_TEST_C9_PFENABLE_F0 | ENE_TEST_C9_PFENABLE_F0)
+#define ENE_TEST_C9_WPDISALBLE_F0      0x40
+#define ENE_TEST_C9_WPDISALBLE_F1      0x80
+#define ENE_TEST_C9_WPDISALBLE         (ENE_TEST_C9_WPDISALBLE_F0 | ENE_TEST_C9_WPDISALBLE_F1)
 
 /*
  * Texas Instruments CardBus controller overrides.
@@ -618,6 +625,7 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
        int devfn;
        unsigned int state;
        int ret = 1;
+       u32 sysctl;
 
        /* catch the two-slot controllers */
        switch (socket->dev->device) {
@@ -640,6 +648,24 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
                 */
                break;
 
+       case PCI_DEVICE_ID_TI_X515:
+       case PCI_DEVICE_ID_TI_X420:
+       case PCI_DEVICE_ID_TI_X620:
+       case PCI_DEVICE_ID_TI_XX21_XX11:
+       case PCI_DEVICE_ID_TI_7410:
+       case PCI_DEVICE_ID_TI_7610:
+               /*
+                * those are either single or dual slot CB with additional functions
+                * like 1394, smartcard reader, etc. check the TIEALL flag for them
+                * the TIEALL flag binds the IRQ of all functions toghether.
+                * we catch the single slot variants later.
+                */
+               sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
+               if (sysctl & TIXX21_SCR_TIEALL)
+                       return 0;
+
+               break;
+
        /* single-slot controllers have the 2nd slot empty always :) */
        default:
                return 1;
@@ -652,6 +678,15 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
        if (!func)
                return 1;
 
+       /*
+        * check that the device id of both slots match. this is needed for the
+        * XX21 and the XX11 controller that share the same device id for single
+        * and dual slot controllers. return '2nd slot empty'. we already checked
+        * if the interrupt is tied to another function.
+        */
+       if (socket->dev->device != func->device)
+               goto out;
+
        slot2 = pci_get_drvdata(func);
        if (!slot2)
                goto out;
@@ -790,16 +825,6 @@ static int ti12xx_override(struct yenta_socket *socket)
        if (val_orig != val)
                config_writel(socket, TI113X_SYSTEM_CONTROL, val);
 
-       /*
-        * for EnE bridges only: clear testbit TLTEnable. this makes the
-        * RME Hammerfall DSP sound card working.
-        */
-       if (socket->dev->vendor == PCI_VENDOR_ID_ENE) {
-               u8 test_c9 = config_readb(socket, ENE_TEST_C9);
-               test_c9 &= ~ENE_TEST_C9_TLTENABLE;
-               config_writeb(socket, ENE_TEST_C9, test_c9);
-       }
-
        /*
         * Yenta expects controllers to use CSCINT to route
         * CSC interrupts to PCI rather than INTVAL.
@@ -841,5 +866,75 @@ static int ti1250_override(struct yenta_socket *socket)
        return ti12xx_override(socket);
 }
 
+
+/**
+ * EnE specific part. EnE bridges are register compatible with TI bridges but
+ * have their own test registers and more important their own little problems.
+ * Some fixup code to make everybody happy (TM).
+ */
+
+/**
+ * set/clear various test bits:
+ * Defaults to clear the bit.
+ * - mask (u8) defines what bits to change
+ * - bits (u8) is the values to change them to
+ * -> it's
+ *     current = (current & ~mask) | bits
+ */
+/* pci ids of devices that wants to have the bit set */
+#define DEVID(_vend,_dev,_subvend,_subdev,mask,bits) {         \
+               .vendor         = _vend,                        \
+               .device         = _dev,                         \
+               .subvendor      = _subvend,                     \
+               .subdevice      = _subdev,                      \
+               .driver_data    = ((mask) << 8 | (bits)),       \
+       }
+static struct pci_device_id ene_tune_tbl[] = {
+       /* Echo Audio products based on motorola DSP56301 and DSP56361 */
+       DEVID(PCI_VENDOR_ID_MOTOROLA, 0x1801, 0xECC0, PCI_ANY_ID,
+               ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),
+       DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID,
+               ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),
+
+       {}
+};
+
+static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus)
+{
+       struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+       struct pci_dev *dev;
+       struct pci_device_id *id = NULL;
+       u8 test_c9, old_c9, mask, bits;
+
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               id = (struct pci_device_id *) pci_match_id(ene_tune_tbl, dev);
+               if (id)
+                       break;
+       }
+
+       test_c9 = old_c9 = config_readb(socket, ENE_TEST_C9);
+       if (id) {
+               mask = (id->driver_data >> 8) & 0xFF;
+               bits = id->driver_data & 0xFF;
+
+               test_c9 = (test_c9 & ~mask) | bits;
+       }
+       else
+               /* default to clear TLTEnable bit, old behaviour */
+               test_c9 &= ~ENE_TEST_C9_TLTENABLE;
+
+       printk(KERN_INFO "yenta EnE: chaning testregister 0xC9, %02x -> %02x\n", old_c9, test_c9);
+       config_writeb(socket, ENE_TEST_C9, test_c9);
+}
+
+
+static int ene_override(struct yenta_socket *socket)
+{
+       /* install tune_bridge() function */
+       socket->socket.tune_bridge = ene_tune_bridge;
+
+       return ti1250_override(socket);
+}
+
 #endif /* _LINUX_TI113X_H */
 
index ba4d78e5b121fdd126fd54d7651a4740da83490f..db9f952f9e3c2a575fba721ddb9018ed4c94cdb2 100644 (file)
@@ -559,12 +559,6 @@ static void yenta_interrogate(struct yenta_socket *socket)
 static int yenta_sock_init(struct pcmcia_socket *sock)
 {
        struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
-       u16 bridge;
-
-       bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR;
-       if (!socket->cb_irq)
-               bridge |= CB_BRIDGE_INTR;
-       config_writew(socket, CB_BRIDGE_CONTROL, bridge);
 
        exca_writeb(socket, I365_GBLCTL, 0x00);
        exca_writeb(socket, I365_GENCTL, 0x00);
@@ -819,6 +813,7 @@ enum {
        CARDBUS_TYPE_TOPIC95,
        CARDBUS_TYPE_TOPIC97,
        CARDBUS_TYPE_O2MICRO,
+       CARDBUS_TYPE_ENE,
 };
 
 /*
@@ -865,6 +860,12 @@ static struct cardbus_type cardbus_type[] = {
                .override       = o2micro_override,
                .restore_state  = o2micro_restore_state,
        },
+       [CARDBUS_TYPE_ENE]      = {
+               .override       = ene_override,
+               .save_state     = ti_save_state,
+               .restore_state  = ti_restore_state,
+               .sock_init      = ti_init,
+       },
 };
 
 
@@ -883,16 +884,8 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
 {
        int i;
        unsigned long val;
-       u16 bridge_ctrl;
        u32 mask;
 
-       /* Set up ISA irq routing to probe the ISA irqs.. */
-       bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
-       if (!(bridge_ctrl & CB_BRIDGE_INTR)) {
-               bridge_ctrl |= CB_BRIDGE_INTR;
-               config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-       }
-
        /*
         * Probe for usable interrupts using the force
         * register to generate bogus card status events.
@@ -914,9 +907,6 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
 
        mask = probe_irq_mask(val) & 0xffff;
 
-       bridge_ctrl &= ~CB_BRIDGE_INTR;
-       config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-
        return mask;
 }
 
@@ -944,18 +934,11 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *re
 /* probes the PCI interrupt, use only on override functions */
 static int yenta_probe_cb_irq(struct yenta_socket *socket)
 {
-       u16 bridge_ctrl;
-
        if (!socket->cb_irq)
                return -1;
 
        socket->probe_status = 0;
 
-       /* disable ISA interrupts */
-       bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
-       bridge_ctrl &= ~CB_BRIDGE_INTR;
-       config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-
        if (request_irq(socket->cb_irq, yenta_probe_handler, SA_SHIRQ, "yenta", socket)) {
                printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n");
                return -1;
@@ -966,7 +949,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
        cb_writel(socket, CB_SOCKET_EVENT, -1);
        cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
        cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS);
-       
+
        msleep(100);
 
        /* disable interrupts */
@@ -1004,11 +987,12 @@ static void yenta_config_init(struct yenta_socket *socket)
 {
        u16 bridge;
        struct pci_dev *dev = socket->dev;
+       struct pci_bus_region region;
 
-       pci_set_power_state(socket->dev, 0);
+       pcibios_resource_to_bus(socket->dev, &region, &dev->resource[0]);
 
        config_writel(socket, CB_LEGACY_MODE_BASE, 0);
-       config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start);
+       config_writel(socket, PCI_BASE_ADDRESS_0, region.start);
        config_writew(socket, PCI_COMMAND,
                        PCI_COMMAND_IO |
                        PCI_COMMAND_MEMORY |
@@ -1031,8 +1015,8 @@ static void yenta_config_init(struct yenta_socket *socket)
         *  - PCI interrupts enabled if a PCI interrupt exists..
         */
        bridge = config_readw(socket, CB_BRIDGE_CONTROL);
-       bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
-       bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN | CB_BRIDGE_INTR;
+       bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
+       bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
        config_writew(socket, CB_BRIDGE_CONTROL, bridge);
 }
 
@@ -1265,10 +1249,22 @@ static struct pci_device_id yenta_table [] = {
        CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250),
        CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250),
 
-       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, TI12XX),
-       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, TI12XX),
-       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, TI1250),
-       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX),
+       CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX),
+
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, TI12XX),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, TI12XX),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, TI12XX),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, TI12XX),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),
+       CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE),
 
        CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH),
        CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH),
index 902c76364af7fb01e6265318cc69b92a62def2ff..f0894bfa908b3953401e4ffb8456f33211d95dc1 100644 (file)
@@ -62,6 +62,7 @@
 static unsigned int ata_busy_sleep (struct ata_port *ap,
                                    unsigned long tmout_pat,
                                    unsigned long tmout);
+static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev);
 static void ata_set_mode(struct ata_port *ap);
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
 static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift);
@@ -1131,7 +1132,7 @@ static inline void ata_dump_id(struct ata_device *dev)
 static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 {
        struct ata_device *dev = &ap->device[device];
-       unsigned int i;
+       unsigned int major_version;
        u16 tmp;
        unsigned long xfer_modes;
        u8 status;
@@ -1229,9 +1230,9 @@ retry:
         * common ATA, ATAPI feature tests
         */
 
-       /* we require LBA and DMA support (bits 8 & 9 of word 49) */
-       if (!ata_id_has_dma(dev->id) || !ata_id_has_lba(dev->id)) {
-               printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id);
+       /* we require DMA support (bits 8 of word 49) */
+       if (!ata_id_has_dma(dev->id)) {
+               printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
                goto err_out_nosup;
        }
 
@@ -1251,32 +1252,69 @@ retry:
                if (!ata_id_is_ata(dev->id))    /* sanity check */
                        goto err_out_nosup;
 
+               /* get major version */
                tmp = dev->id[ATA_ID_MAJOR_VER];
-               for (i = 14; i >= 1; i--)
-                       if (tmp & (1 << i))
+               for (major_version = 14; major_version >= 1; major_version--)
+                       if (tmp & (1 << major_version))
                                break;
 
-               /* we require at least ATA-3 */
-               if (i < 3) {
-                       printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id);
-                       goto err_out_nosup;
-               }
+               /*
+                * The exact sequence expected by certain pre-ATA4 drives is:
+                * SRST RESET
+                * IDENTIFY
+                * INITIALIZE DEVICE PARAMETERS
+                * anything else..
+                * Some drives were very specific about that exact sequence.
+                */
+               if (major_version < 4 || (!ata_id_has_lba(dev->id)))
+                       ata_dev_init_params(ap, dev);
+
+               if (ata_id_has_lba(dev->id)) {
+                       dev->flags |= ATA_DFLAG_LBA;
+
+                       if (ata_id_has_lba48(dev->id)) {
+                               dev->flags |= ATA_DFLAG_LBA48;
+                               dev->n_sectors = ata_id_u64(dev->id, 100);
+                       } else {
+                               dev->n_sectors = ata_id_u32(dev->id, 60);
+                       }
+
+                       /* print device info to dmesg */
+                       printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
+                              ap->id, device,
+                              major_version,
+                              ata_mode_string(xfer_modes),
+                              (unsigned long long)dev->n_sectors,
+                              dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA");
+               } else { 
+                       /* CHS */
+
+                       /* Default translation */
+                       dev->cylinders  = dev->id[1];
+                       dev->heads      = dev->id[3];
+                       dev->sectors    = dev->id[6];
+                       dev->n_sectors  = dev->cylinders * dev->heads * dev->sectors;
+
+                       if (ata_id_current_chs_valid(dev->id)) {
+                               /* Current CHS translation is valid. */
+                               dev->cylinders = dev->id[54];
+                               dev->heads     = dev->id[55];
+                               dev->sectors   = dev->id[56];
+                               
+                               dev->n_sectors = ata_id_u32(dev->id, 57);
+                       }
+
+                       /* print device info to dmesg */
+                       printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n",
+                              ap->id, device,
+                              major_version,
+                              ata_mode_string(xfer_modes),
+                              (unsigned long long)dev->n_sectors,
+                              (int)dev->cylinders, (int)dev->heads, (int)dev->sectors);
 
-               if (ata_id_has_lba48(dev->id)) {
-                       dev->flags |= ATA_DFLAG_LBA48;
-                       dev->n_sectors = ata_id_u64(dev->id, 100);
-               } else {
-                       dev->n_sectors = ata_id_u32(dev->id, 60);
                }
 
                ap->host->max_cmd_len = 16;
-
-               /* print device info to dmesg */
-               printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
-                      ap->id, device,
-                      ata_mode_string(xfer_modes),
-                      (unsigned long long)dev->n_sectors,
-                      dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
        }
 
        /* ATAPI-specific feature tests */
@@ -2143,6 +2181,54 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
        DPRINTK("EXIT\n");
 }
 
+/**
+ *     ata_dev_init_params - Issue INIT DEV PARAMS command
+ *     @ap: Port associated with device @dev
+ *     @dev: Device to which command will be sent
+ *
+ *     LOCKING:
+ */
+
+static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
+{
+       DECLARE_COMPLETION(wait);
+       struct ata_queued_cmd *qc;
+       int rc;
+       unsigned long flags;
+       u16 sectors = dev->id[6];
+       u16 heads   = dev->id[3];
+
+       /* Number of sectors per track 1-255. Number of heads 1-16 */
+       if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16)
+               return;
+
+       /* set up init dev params taskfile */
+       DPRINTK("init dev params \n");
+
+       qc = ata_qc_new_init(ap, dev);
+       BUG_ON(qc == NULL);
+
+       qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
+       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       qc->tf.protocol = ATA_PROT_NODATA;
+       qc->tf.nsect = sectors;
+       qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
+
+       qc->waiting = &wait;
+       qc->complete_fn = ata_qc_complete_noop;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       rc = ata_qc_issue(qc);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       if (rc)
+               ata_port_disable(ap);
+       else
+               wait_for_completion(&wait);
+
+       DPRINTK("EXIT\n");
+}
+
 /**
  *     ata_sg_clean - Unmap DMA memory associated with command
  *     @qc: Command containing DMA memory to be released
@@ -2425,20 +2511,20 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 static unsigned long ata_pio_poll(struct ata_port *ap)
 {
        u8 status;
-       unsigned int poll_state = PIO_ST_UNKNOWN;
-       unsigned int reg_state = PIO_ST_UNKNOWN;
-       const unsigned int tmout_state = PIO_ST_TMOUT;
-
-       switch (ap->pio_task_state) {
-       case PIO_ST:
-       case PIO_ST_POLL:
-               poll_state = PIO_ST_POLL;
-               reg_state = PIO_ST;
+       unsigned int poll_state = HSM_ST_UNKNOWN;
+       unsigned int reg_state = HSM_ST_UNKNOWN;
+       const unsigned int tmout_state = HSM_ST_TMOUT;
+
+       switch (ap->hsm_task_state) {
+       case HSM_ST:
+       case HSM_ST_POLL:
+               poll_state = HSM_ST_POLL;
+               reg_state = HSM_ST;
                break;
-       case PIO_ST_LAST:
-       case PIO_ST_LAST_POLL:
-               poll_state = PIO_ST_LAST_POLL;
-               reg_state = PIO_ST_LAST;
+       case HSM_ST_LAST:
+       case HSM_ST_LAST_POLL:
+               poll_state = HSM_ST_LAST_POLL;
+               reg_state = HSM_ST_LAST;
                break;
        default:
                BUG();
@@ -2448,14 +2534,14 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
        status = ata_chk_status(ap);
        if (status & ATA_BUSY) {
                if (time_after(jiffies, ap->pio_task_timeout)) {
-                       ap->pio_task_state = tmout_state;
+                       ap->hsm_task_state = tmout_state;
                        return 0;
                }
-               ap->pio_task_state = poll_state;
+               ap->hsm_task_state = poll_state;
                return ATA_SHORT_PAUSE;
        }
 
-       ap->pio_task_state = reg_state;
+       ap->hsm_task_state = reg_state;
        return 0;
 }
 
@@ -2480,14 +2566,14 @@ static int ata_pio_complete (struct ata_port *ap)
         * we enter, BSY will be cleared in a chk-status or two.  If not,
         * the drive is probably seeking or something.  Snooze for a couple
         * msecs, then chk-status again.  If still busy, fall back to
-        * PIO_ST_POLL state.
+        * HSM_ST_POLL state.
         */
        drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
        if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
                msleep(2);
                drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
                if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
-                       ap->pio_task_state = PIO_ST_LAST_POLL;
+                       ap->hsm_task_state = HSM_ST_LAST_POLL;
                        ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
                        return 0;
                }
@@ -2495,14 +2581,14 @@ static int ata_pio_complete (struct ata_port *ap)
 
        drv_stat = ata_wait_idle(ap);
        if (!ata_ok(drv_stat)) {
-               ap->pio_task_state = PIO_ST_ERR;
+               ap->hsm_task_state = HSM_ST_ERR;
                return 0;
        }
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
        assert(qc != NULL);
 
-       ap->pio_task_state = PIO_ST_IDLE;
+       ap->hsm_task_state = HSM_ST_IDLE;
 
        ata_poll_qc_complete(qc, drv_stat);
 
@@ -2662,7 +2748,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
        unsigned char *buf;
 
        if (qc->cursect == (qc->nsect - 1))
-               ap->pio_task_state = PIO_ST_LAST;
+               ap->hsm_task_state = HSM_ST_LAST;
 
        page = sg[qc->cursg].page;
        offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE;
@@ -2712,7 +2798,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
        unsigned int offset, count;
 
        if (qc->curbytes + bytes >= qc->nbytes)
-               ap->pio_task_state = PIO_ST_LAST;
+               ap->hsm_task_state = HSM_ST_LAST;
 
 next_sg:
        if (unlikely(qc->cursg >= qc->n_elem)) {
@@ -2734,7 +2820,7 @@ next_sg:
                for (i = 0; i < words; i++)
                        ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
 
-               ap->pio_task_state = PIO_ST_LAST;
+               ap->hsm_task_state = HSM_ST_LAST;
                return;
        }
 
@@ -2815,7 +2901,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
 err_out:
        printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
              ap->id, dev->devno);
-       ap->pio_task_state = PIO_ST_ERR;
+       ap->hsm_task_state = HSM_ST_ERR;
 }
 
 /**
@@ -2837,14 +2923,14 @@ static void ata_pio_block(struct ata_port *ap)
         * a chk-status or two.  If not, the drive is probably seeking
         * or something.  Snooze for a couple msecs, then
         * chk-status again.  If still busy, fall back to
-        * PIO_ST_POLL state.
+        * HSM_ST_POLL state.
         */
        status = ata_busy_wait(ap, ATA_BUSY, 5);
        if (status & ATA_BUSY) {
                msleep(2);
                status = ata_busy_wait(ap, ATA_BUSY, 10);
                if (status & ATA_BUSY) {
-                       ap->pio_task_state = PIO_ST_POLL;
+                       ap->hsm_task_state = HSM_ST_POLL;
                        ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
                        return;
                }
@@ -2856,7 +2942,7 @@ static void ata_pio_block(struct ata_port *ap)
        if (is_atapi_taskfile(&qc->tf)) {
                /* no more data to transfer or unsupported ATAPI command */
                if ((status & ATA_DRQ) == 0) {
-                       ap->pio_task_state = PIO_ST_LAST;
+                       ap->hsm_task_state = HSM_ST_LAST;
                        return;
                }
 
@@ -2864,7 +2950,7 @@ static void ata_pio_block(struct ata_port *ap)
        } else {
                /* handle BSY=0, DRQ=0 as error */
                if ((status & ATA_DRQ) == 0) {
-                       ap->pio_task_state = PIO_ST_ERR;
+                       ap->hsm_task_state = HSM_ST_ERR;
                        return;
                }
 
@@ -2884,7 +2970,7 @@ static void ata_pio_error(struct ata_port *ap)
        printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n",
               ap->id, drv_stat);
 
-       ap->pio_task_state = PIO_ST_IDLE;
+       ap->hsm_task_state = HSM_ST_IDLE;
 
        ata_poll_qc_complete(qc, drv_stat | ATA_ERR);
 }
@@ -2899,25 +2985,25 @@ fsm_start:
        timeout = 0;
        qc_completed = 0;
 
-       switch (ap->pio_task_state) {
-       case PIO_ST_IDLE:
+       switch (ap->hsm_task_state) {
+       case HSM_ST_IDLE:
                return;
 
-       case PIO_ST:
+       case HSM_ST:
                ata_pio_block(ap);
                break;
 
-       case PIO_ST_LAST:
+       case HSM_ST_LAST:
                qc_completed = ata_pio_complete(ap);
                break;
 
-       case PIO_ST_POLL:
-       case PIO_ST_LAST_POLL:
+       case HSM_ST_POLL:
+       case HSM_ST_LAST_POLL:
                timeout = ata_pio_poll(ap);
                break;
 
-       case PIO_ST_TMOUT:
-       case PIO_ST_ERR:
+       case HSM_ST_TMOUT:
+       case HSM_ST_ERR:
                ata_pio_error(ap);
                return;
        }
@@ -3156,8 +3242,12 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 
                ata_tf_init(ap, &qc->tf, dev->devno);
 
-               if (dev->flags & ATA_DFLAG_LBA48)
-                       qc->tf.flags |= ATA_TFLAG_LBA48;
+               if (dev->flags & ATA_DFLAG_LBA) {
+                       qc->tf.flags |= ATA_TFLAG_LBA;
+
+                       if (dev->flags & ATA_DFLAG_LBA48)
+                               qc->tf.flags |= ATA_TFLAG_LBA48;
+               }
        }
 
        return qc;
@@ -3360,7 +3450,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
        case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
                ata_qc_set_polling(qc);
                ata_tf_to_host_nolock(ap, &qc->tf);
-               ap->pio_task_state = PIO_ST;
+               ap->hsm_task_state = HSM_ST;
                queue_work(ata_wq, &ap->pio_task);
                break;
 
@@ -3586,7 +3676,7 @@ u8 ata_bmdma_status(struct ata_port *ap)
                void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
                host_stat = readb(mmio + ATA_DMA_STATUS);
        } else
-       host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+               host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
        return host_stat;
 }
 
@@ -3806,7 +3896,7 @@ static void atapi_packet_task(void *_data)
                ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
 
                /* PIO commands are handled by polling */
-               ap->pio_task_state = PIO_ST;
+               ap->hsm_task_state = HSM_ST;
                queue_work(ata_wq, &ap->pio_task);
        }
 
@@ -4273,85 +4363,87 @@ void ata_pci_host_stop (struct ata_host_set *host_set)
  *     ata_pci_init_native_mode - Initialize native-mode driver
  *     @pdev:  pci device to be initialized
  *     @port:  array[2] of pointers to port info structures.
+ *     @ports: bitmap of ports present
  *
  *     Utility function which allocates and initializes an
  *     ata_probe_ent structure for a standard dual-port
  *     PIO-based IDE controller.  The returned ata_probe_ent
  *     structure can be passed to ata_device_add().  The returned
  *     ata_probe_ent structure should then be freed with kfree().
+ *
+ *     The caller need only pass the address of the primary port, the
+ *     secondary will be deduced automatically. If the device has non
+ *     standard secondary port mappings this function can be called twice,
+ *     once for each interface.
  */
 
 struct ata_probe_ent *
-ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int ports)
 {
        struct ata_probe_ent *probe_ent =
                ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+       int p = 0;
+
        if (!probe_ent)
                return NULL;
 
-       probe_ent->n_ports = 2;
        probe_ent->irq = pdev->irq;
        probe_ent->irq_flags = SA_SHIRQ;
 
-       probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-       probe_ent->port[0].altstatus_addr =
-       probe_ent->port[0].ctl_addr =
-               pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-       probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-
-       probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-       probe_ent->port[1].altstatus_addr =
-       probe_ent->port[1].ctl_addr =
-               pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-       probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+       if (ports & ATA_PORT_PRIMARY) {
+               probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
+               probe_ent->port[p].altstatus_addr =
+               probe_ent->port[p].ctl_addr =
+                       pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+               probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4);
+               ata_std_ports(&probe_ent->port[p]);
+               p++;
+       }
 
-       ata_std_ports(&probe_ent->port[0]);
-       ata_std_ports(&probe_ent->port[1]);
+       if (ports & ATA_PORT_SECONDARY) {
+               probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 2);
+               probe_ent->port[p].altstatus_addr =
+               probe_ent->port[p].ctl_addr =
+                       pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+               probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+               ata_std_ports(&probe_ent->port[p]);
+               p++;
+       }
 
+       probe_ent->n_ports = p;
        return probe_ent;
 }
 
-static struct ata_probe_ent *
-ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
-    struct ata_probe_ent **ppe2)
+static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info **port, int port_num)
 {
-       struct ata_probe_ent *probe_ent, *probe_ent2;
+       struct ata_probe_ent *probe_ent;
 
        probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
        if (!probe_ent)
                return NULL;
-       probe_ent2 = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[1]);
-       if (!probe_ent2) {
-               kfree(probe_ent);
-               return NULL;
-       }
-
-       probe_ent->n_ports = 1;
-       probe_ent->irq = 14;
 
-       probe_ent->hard_port_no = 0;
+       
        probe_ent->legacy_mode = 1;
-
-       probe_ent2->n_ports = 1;
-       probe_ent2->irq = 15;
-
-       probe_ent2->hard_port_no = 1;
-       probe_ent2->legacy_mode = 1;
-
-       probe_ent->port[0].cmd_addr = 0x1f0;
-       probe_ent->port[0].altstatus_addr =
-       probe_ent->port[0].ctl_addr = 0x3f6;
-       probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-
-       probe_ent2->port[0].cmd_addr = 0x170;
-       probe_ent2->port[0].altstatus_addr =
-       probe_ent2->port[0].ctl_addr = 0x376;
-       probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
-
+       probe_ent->n_ports = 1;
+       probe_ent->hard_port_no = port_num;
+
+       switch(port_num)
+       {
+               case 0:
+                       probe_ent->irq = 14;
+                       probe_ent->port[0].cmd_addr = 0x1f0;
+                       probe_ent->port[0].altstatus_addr =
+                       probe_ent->port[0].ctl_addr = 0x3f6;
+                       break;
+               case 1:
+                       probe_ent->irq = 15;
+                       probe_ent->port[0].cmd_addr = 0x170;
+                       probe_ent->port[0].altstatus_addr =
+                       probe_ent->port[0].ctl_addr = 0x376;
+                       break;
+       }
+       probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4) + 8 * port_num;
        ata_std_ports(&probe_ent->port[0]);
-       ata_std_ports(&probe_ent2->port[0]);
-
-       *ppe2 = probe_ent2;
        return probe_ent;
 }
 
@@ -4380,7 +4472,7 @@ ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
 int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
                      unsigned int n_ports)
 {
-       struct ata_probe_ent *probe_ent, *probe_ent2 = NULL;
+       struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL;
        struct ata_port_info *port[2];
        u8 tmp8, mask;
        unsigned int legacy_mode = 0;
@@ -4397,7 +4489,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
 
        if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0
            && (pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
-               /* TODO: support transitioning to native mode? */
+               /* TODO: What if one channel is in native mode ... */
                pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
                mask = (1 << 2) | (1 << 0);
                if ((tmp8 & mask) != mask)
@@ -4405,11 +4497,20 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
        }
 
        /* FIXME... */
-       if ((!legacy_mode) && (n_ports > 1)) {
-               printk(KERN_ERR "ata: BUG: native mode, n_ports > 1\n");
-               return -EINVAL;
+       if ((!legacy_mode) && (n_ports > 2)) {
+               printk(KERN_ERR "ata: BUG: native mode, n_ports > 2\n");
+               n_ports = 2;
+               /* For now */
        }
 
+       /* FIXME: Really for ATA it isn't safe because the device may be
+          multi-purpose and we want to leave it alone if it was already
+          enabled. Secondly for shared use as Arjan says we want refcounting
+          
+          Checking dev->is_enabled is insufficient as this is not set at
+          boot for the primary video which is BIOS enabled
+         */
+         
        rc = pci_enable_device(pdev);
        if (rc)
                return rc;
@@ -4420,6 +4521,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
                goto err_out;
        }
 
+       /* FIXME: Should use platform specific mappers for legacy port ranges */
        if (legacy_mode) {
                if (!request_region(0x1f0, 8, "libata")) {
                        struct resource *conflict, res;
@@ -4464,10 +4566,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
                goto err_out_regions;
 
        if (legacy_mode) {
-               probe_ent = ata_pci_init_legacy_mode(pdev, port, &probe_ent2);
-       } else
-               probe_ent = ata_pci_init_native_mode(pdev, port);
-       if (!probe_ent) {
+               if (legacy_mode & (1 << 0))
+                       probe_ent = ata_pci_init_legacy_port(pdev, port, 0);
+               if (legacy_mode & (1 << 1))
+                       probe_ent2 = ata_pci_init_legacy_port(pdev, port, 1);
+       } else {
+               if (n_ports == 2)
+                       probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
+               else
+                       probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY);
+       }
+       if (!probe_ent && !probe_ent2) {
                rc = -ENOMEM;
                goto err_out_regions;
        }
index 8295a656e521f65af1a6058097866e85167dfcdd..45ebe9fd52eaaccf38d9b96a0b90b39879a58d60 100644 (file)
@@ -435,10 +435,21 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
                return 1;       /* power conditions not supported */
        if (scsicmd[4] & 0x1) {
                tf->nsect = 1;  /* 1 sector, lba=0 */
-               tf->lbah = 0x0;
-               tf->lbam = 0x0;
-               tf->lbal = 0x0;
-               tf->device |= ATA_LBA;
+
+               if (qc->dev->flags & ATA_DFLAG_LBA) {
+                       qc->tf.flags |= ATA_TFLAG_LBA;
+
+                       tf->lbah = 0x0;
+                       tf->lbam = 0x0;
+                       tf->lbal = 0x0;
+                       tf->device |= ATA_LBA;
+               } else {
+                       /* CHS */
+                       tf->lbal = 0x1; /* sect */
+                       tf->lbam = 0x0; /* cyl low */
+                       tf->lbah = 0x0; /* cyl high */
+               }
+
                tf->command = ATA_CMD_VERIFY;   /* READ VERIFY */
        } else {
                tf->nsect = 0;  /* time period value (0 implies now) */
@@ -487,6 +498,99 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
        return 0;
 }
 
+/**
+ *     scsi_6_lba_len - Get LBA and transfer length
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Calculate LBA and transfer length for 6-byte commands.
+ *
+ *     RETURNS:
+ *     @plba: the LBA
+ *     @plen: the transfer length
+ */
+
+static void scsi_6_lba_len(u8 *scsicmd, u64 *plba, u32 *plen)
+{
+       u64 lba = 0;
+       u32 len = 0;
+
+       VPRINTK("six-byte command\n");
+
+       lba |= ((u64)scsicmd[2]) << 8;
+       lba |= ((u64)scsicmd[3]);
+
+       len |= ((u32)scsicmd[4]);
+
+       *plba = lba;
+       *plen = len;
+}
+
+/**
+ *     scsi_10_lba_len - Get LBA and transfer length
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Calculate LBA and transfer length for 10-byte commands.
+ *
+ *     RETURNS:
+ *     @plba: the LBA
+ *     @plen: the transfer length
+ */
+
+static void scsi_10_lba_len(u8 *scsicmd, u64 *plba, u32 *plen)
+{
+       u64 lba = 0;
+       u32 len = 0;
+
+       VPRINTK("ten-byte command\n");
+
+       lba |= ((u64)scsicmd[2]) << 24;
+       lba |= ((u64)scsicmd[3]) << 16;
+       lba |= ((u64)scsicmd[4]) << 8;
+       lba |= ((u64)scsicmd[5]);
+
+       len |= ((u32)scsicmd[7]) << 8;
+       len |= ((u32)scsicmd[8]);
+
+       *plba = lba;
+       *plen = len;
+}
+
+/**
+ *     scsi_16_lba_len - Get LBA and transfer length
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Calculate LBA and transfer length for 16-byte commands.
+ *
+ *     RETURNS:
+ *     @plba: the LBA
+ *     @plen: the transfer length
+ */
+
+static void scsi_16_lba_len(u8 *scsicmd, u64 *plba, u32 *plen)
+{
+       u64 lba = 0;
+       u32 len = 0;
+
+       VPRINTK("sixteen-byte command\n");
+
+       lba |= ((u64)scsicmd[2]) << 56;
+       lba |= ((u64)scsicmd[3]) << 48;
+       lba |= ((u64)scsicmd[4]) << 40;
+       lba |= ((u64)scsicmd[5]) << 32;
+       lba |= ((u64)scsicmd[6]) << 24;
+       lba |= ((u64)scsicmd[7]) << 16;
+       lba |= ((u64)scsicmd[8]) << 8;
+       lba |= ((u64)scsicmd[9]);
+
+       len |= ((u32)scsicmd[10]) << 24;
+       len |= ((u32)scsicmd[11]) << 16;
+       len |= ((u32)scsicmd[12]) << 8;
+       len |= ((u32)scsicmd[13]);
+
+       *plba = lba;
+       *plen = len;
+}
+
 /**
  *     ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
  *     @qc: Storage for translated ATA taskfile
@@ -504,77 +608,86 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 {
        struct ata_taskfile *tf = &qc->tf;
+       struct ata_device *dev = qc->dev;
+       unsigned int lba   = tf->flags & ATA_TFLAG_LBA;
        unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
        u64 dev_sectors = qc->dev->n_sectors;
-       u64 sect = 0;
-       u32 n_sect = 0;
+       u64 block;
+       u32 n_block;
 
        tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf->protocol = ATA_PROT_NODATA;
-       tf->device |= ATA_LBA;
-
-       if (scsicmd[0] == VERIFY) {
-               sect |= ((u64)scsicmd[2]) << 24;
-               sect |= ((u64)scsicmd[3]) << 16;
-               sect |= ((u64)scsicmd[4]) << 8;
-               sect |= ((u64)scsicmd[5]);
-
-               n_sect |= ((u32)scsicmd[7]) << 8;
-               n_sect |= ((u32)scsicmd[8]);
-       }
-
-       else if (scsicmd[0] == VERIFY_16) {
-               sect |= ((u64)scsicmd[2]) << 56;
-               sect |= ((u64)scsicmd[3]) << 48;
-               sect |= ((u64)scsicmd[4]) << 40;
-               sect |= ((u64)scsicmd[5]) << 32;
-               sect |= ((u64)scsicmd[6]) << 24;
-               sect |= ((u64)scsicmd[7]) << 16;
-               sect |= ((u64)scsicmd[8]) << 8;
-               sect |= ((u64)scsicmd[9]);
-
-               n_sect |= ((u32)scsicmd[10]) << 24;
-               n_sect |= ((u32)scsicmd[11]) << 16;
-               n_sect |= ((u32)scsicmd[12]) << 8;
-               n_sect |= ((u32)scsicmd[13]);
-       }
 
+       if (scsicmd[0] == VERIFY)
+               scsi_10_lba_len(scsicmd, &block, &n_block);
+       else if (scsicmd[0] == VERIFY_16)
+               scsi_16_lba_len(scsicmd, &block, &n_block);
        else
                return 1;
 
-       if (!n_sect)
+       if (!n_block)
                return 1;
-       if (sect >= dev_sectors)
+       if (block >= dev_sectors)
                return 1;
-       if ((sect + n_sect) > dev_sectors)
+       if ((block + n_block) > dev_sectors)
                return 1;
        if (lba48) {
-               if (n_sect > (64 * 1024))
+               if (n_block > (64 * 1024))
                        return 1;
        } else {
-               if (n_sect > 256)
+               if (n_block > 256)
                        return 1;
        }
 
-       if (lba48) {
-               tf->command = ATA_CMD_VERIFY_EXT;
+       if (lba) {
+               if (lba48) {
+                       tf->command = ATA_CMD_VERIFY_EXT;
 
-               tf->hob_nsect = (n_sect >> 8) & 0xff;
+                       tf->hob_nsect = (n_block >> 8) & 0xff;
 
-               tf->hob_lbah = (sect >> 40) & 0xff;
-               tf->hob_lbam = (sect >> 32) & 0xff;
-               tf->hob_lbal = (sect >> 24) & 0xff;
-       } else {
-               tf->command = ATA_CMD_VERIFY;
+                       tf->hob_lbah = (block >> 40) & 0xff;
+                       tf->hob_lbam = (block >> 32) & 0xff;
+                       tf->hob_lbal = (block >> 24) & 0xff;
+               } else {
+                       tf->command = ATA_CMD_VERIFY;
 
-               tf->device |= (sect >> 24) & 0xf;
-       }
+                       tf->device |= (block >> 24) & 0xf;
+               }
 
-       tf->nsect = n_sect & 0xff;
+               tf->nsect = n_block & 0xff;
 
-       tf->lbah = (sect >> 16) & 0xff;
-       tf->lbam = (sect >> 8) & 0xff;
-       tf->lbal = sect & 0xff;
+               tf->lbah = (block >> 16) & 0xff;
+               tf->lbam = (block >> 8) & 0xff;
+               tf->lbal = block & 0xff;
+
+               tf->device |= ATA_LBA;
+       } else {
+               /* CHS */
+               u32 sect, head, cyl, track;
+
+               /* Convert LBA to CHS */
+               track = (u32)block / dev->sectors;
+               cyl   = track / dev->heads;
+               head  = track % dev->heads;
+               sect  = (u32)block % dev->sectors + 1;
+
+               DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+                       (u32)block, track, cyl, head, sect);
+               
+               /* Check whether the converted CHS can fit. 
+                  Cylinder: 0-65535 
+                  Head: 0-15
+                  Sector: 1-255*/
+               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) 
+                       return 1;
+               
+               tf->command = ATA_CMD_VERIFY;
+               tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+               tf->lbal = sect;
+               tf->lbam = cyl;
+               tf->lbah = cyl >> 8;
+               tf->device |= head;
+       }
 
        return 0;
 }
@@ -602,11 +715,14 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 {
        struct ata_taskfile *tf = &qc->tf;
+       struct ata_device *dev = qc->dev;
+       unsigned int lba   = tf->flags & ATA_TFLAG_LBA;
        unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+       u64 block;
+       u32 n_block;
 
        tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf->protocol = qc->dev->xfer_protocol;
-       tf->device |= ATA_LBA;
 
        if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
            scsicmd[0] == READ_16) {
@@ -616,90 +732,102 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
                tf->flags |= ATA_TFLAG_WRITE;
        }
 
-       if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
-               if (lba48) {
-                       tf->hob_nsect = scsicmd[7];
-                       tf->hob_lbal = scsicmd[2];
-
-                       qc->nsect = ((unsigned int)scsicmd[7] << 8) |
-                                       scsicmd[8];
-               } else {
-                       /* if we don't support LBA48 addressing, the request
-                        * -may- be too large. */
-                       if ((scsicmd[2] & 0xf0) || scsicmd[7])
-                               return 1;
+       /* Calculate the SCSI LBA and transfer length. */
+       switch (scsicmd[0]) {
+       case READ_10:
+       case WRITE_10:
+               scsi_10_lba_len(scsicmd, &block, &n_block);
+               break;
+       case READ_6:
+       case WRITE_6:
+               scsi_6_lba_len(scsicmd, &block, &n_block);
 
-                       /* stores LBA27:24 in lower 4 bits of device reg */
-                       tf->device |= scsicmd[2];
+               /* for 6-byte r/w commands, transfer length 0
+                * means 256 blocks of data, not 0 block.
+                */
+               if (!n_block)
+                       n_block = 256;
+               break;
+       case READ_16:
+       case WRITE_16:
+               scsi_16_lba_len(scsicmd, &block, &n_block);
+               break;
+       default:
+               DPRINTK("no-byte command\n");
+               return 1;
+       }
 
-                       qc->nsect = scsicmd[8];
-               }
+       /* Check and compose ATA command */
+       if (!n_block)
+               /* For 10-byte and 16-byte SCSI R/W commands, transfer
+                * length 0 means transfer 0 block of data.
+                * However, for ATA R/W commands, sector count 0 means
+                * 256 or 65536 sectors, not 0 sectors as in SCSI.
+                */
+               return 1;
 
-               tf->nsect = scsicmd[8];
-               tf->lbal = scsicmd[5];
-               tf->lbam = scsicmd[4];
-               tf->lbah = scsicmd[3];
+       if (lba) {
+               if (lba48) {
+                       /* The request -may- be too large for LBA48. */
+                       if ((block >> 48) || (n_block > 65536))
+                               return 1;
 
-               VPRINTK("ten-byte command\n");
-               if (qc->nsect == 0) /* we don't support length==0 cmds */
-                       return 1;
-               return 0;
-       }
+                       tf->hob_nsect = (n_block >> 8) & 0xff;
 
-       if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
-               qc->nsect = tf->nsect = scsicmd[4];
-               if (!qc->nsect) {
-                       qc->nsect = 256;
-                       if (lba48)
-                               tf->hob_nsect = 1;
-               }
+                       tf->hob_lbah = (block >> 40) & 0xff;
+                       tf->hob_lbam = (block >> 32) & 0xff;
+                       tf->hob_lbal = (block >> 24) & 0xff;
+               } else { 
+                       /* LBA28 */
 
-               tf->lbal = scsicmd[3];
-               tf->lbam = scsicmd[2];
-               tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
+                       /* The request -may- be too large for LBA28. */
+                       if ((block >> 28) || (n_block > 256))
+                               return 1;
 
-               VPRINTK("six-byte command\n");
-               return 0;
-       }
+                       tf->device |= (block >> 24) & 0xf;
+               }
 
-       if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
-               /* rule out impossible LBAs and sector counts */
-               if (scsicmd[2] || scsicmd[3] || scsicmd[10] || scsicmd[11])
-                       return 1;
+               qc->nsect = n_block;
+               tf->nsect = n_block & 0xff;
 
-               if (lba48) {
-                       tf->hob_nsect = scsicmd[12];
-                       tf->hob_lbal = scsicmd[6];
-                       tf->hob_lbam = scsicmd[5];
-                       tf->hob_lbah = scsicmd[4];
+               tf->lbah = (block >> 16) & 0xff;
+               tf->lbam = (block >> 8) & 0xff;
+               tf->lbal = block & 0xff;
 
-                       qc->nsect = ((unsigned int)scsicmd[12] << 8) |
-                                       scsicmd[13];
-               } else {
-                       /* once again, filter out impossible non-zero values */
-                       if (scsicmd[4] || scsicmd[5] || scsicmd[12] ||
-                           (scsicmd[6] & 0xf0))
-                               return 1;
+               tf->device |= ATA_LBA;
+       } else { 
+               /* CHS */
+               u32 sect, head, cyl, track;
 
-                       /* stores LBA27:24 in lower 4 bits of device reg */
-                       tf->device |= scsicmd[6];
+               /* The request -may- be too large for CHS addressing. */
+               if ((block >> 28) || (n_block > 256))
+                       return 1;
 
-                       qc->nsect = scsicmd[13];
-               }
+               /* Convert LBA to CHS */
+               track = (u32)block / dev->sectors;
+               cyl   = track / dev->heads;
+               head  = track % dev->heads;
+               sect  = (u32)block % dev->sectors + 1;
 
-               tf->nsect = scsicmd[13];
-               tf->lbal = scsicmd[9];
-               tf->lbam = scsicmd[8];
-               tf->lbah = scsicmd[7];
+               DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+                       (u32)block, track, cyl, head, sect);
 
-               VPRINTK("sixteen-byte command\n");
-               if (qc->nsect == 0) /* we don't support length==0 cmds */
+               /* Check whether the converted CHS can fit. 
+                  Cylinder: 0-65535 
+                  Head: 0-15
+                  Sector: 1-255*/
+               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
                        return 1;
-               return 0;
+
+               qc->nsect = n_block;
+               tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
+               tf->lbal = sect;
+               tf->lbam = cyl;
+               tf->lbah = cyl >> 8;
+               tf->device |= head;
        }
 
-       DPRINTK("no-byte command\n");
-       return 1;
+       return 0;
 }
 
 static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
@@ -1246,10 +1374,20 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
 
        VPRINTK("ENTER\n");
 
-       if (ata_id_has_lba48(args->id))
-               n_sectors = ata_id_u64(args->id, 100);
-       else
-               n_sectors = ata_id_u32(args->id, 60);
+       if (ata_id_has_lba(args->id)) {
+               if (ata_id_has_lba48(args->id))
+                       n_sectors = ata_id_u64(args->id, 100);
+               else
+                       n_sectors = ata_id_u32(args->id, 60);
+       } else {
+               /* CHS default translation */
+               n_sectors = args->id[1] * args->id[3] * args->id[6];
+
+               if (ata_id_current_chs_valid(args->id))
+                       /* CHS current translation */
+                       n_sectors = ata_id_u32(args->id, 57);
+       }
+
        n_sectors--;            /* ATA TotalUserSectors - 1 */
 
        if (args->cmd->cmnd[0] == READ_CAPACITY) {
index ea76fe44585e8f6b96e6f8ffd6dc6ce6dd558db1..ecda7df2114243bc4cd16e46f85bf228289d711f 100644 (file)
@@ -35,7 +35,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "sata_mv"
-#define DRV_VERSION    "0.12"
+#define DRV_VERSION    "0.22"
 
 enum {
        /* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -55,31 +55,61 @@ enum {
        MV_SATAHC_ARBTR_REG_SZ  = MV_MINOR_REG_AREA_SZ,         /* arbiter */
        MV_PORT_REG_SZ          = MV_MINOR_REG_AREA_SZ,
 
-       MV_Q_CT                 = 32,
-       MV_CRQB_SZ              = 32,
-       MV_CRPB_SZ              = 8,
+       MV_USE_Q_DEPTH          = ATA_DEF_QUEUE,
 
-       MV_DMA_BOUNDARY         = 0xffffffffU,
-       SATAHC_MASK             = (~(MV_SATAHC_REG_SZ - 1)),
+       MV_MAX_Q_DEPTH          = 32,
+       MV_MAX_Q_DEPTH_MASK     = MV_MAX_Q_DEPTH - 1,
+
+       /* CRQB needs alignment on a 1KB boundary. Size == 1KB
+        * CRPB needs alignment on a 256B boundary. Size == 256B
+        * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
+        * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
+        */
+       MV_CRQB_Q_SZ            = (32 * MV_MAX_Q_DEPTH),
+       MV_CRPB_Q_SZ            = (8 * MV_MAX_Q_DEPTH),
+       MV_MAX_SG_CT            = 176,
+       MV_SG_TBL_SZ            = (16 * MV_MAX_SG_CT),
+       MV_PORT_PRIV_DMA_SZ     = (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
+
+       /* Our DMA boundary is determined by an ePRD being unable to handle
+        * anything larger than 64KB
+        */
+       MV_DMA_BOUNDARY         = 0xffffU,
 
        MV_PORTS_PER_HC         = 4,
        /* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
        MV_PORT_HC_SHIFT        = 2,
-       /* == (port % MV_PORTS_PER_HC) to determine port from 0-7 port */
+       /* == (port % MV_PORTS_PER_HC) to determine hard port from 0-7 port */
        MV_PORT_MASK            = 3,
 
        /* Host Flags */
        MV_FLAG_DUAL_HC         = (1 << 30),  /* two SATA Host Controllers */
        MV_FLAG_IRQ_COALESCE    = (1 << 29),  /* IRQ coalescing capability */
-       MV_FLAG_BDMA            = (1 << 28),  /* Basic DMA */
+       MV_FLAG_GLBL_SFT_RST    = (1 << 28),  /* Global Soft Reset support */
+       MV_COMMON_FLAGS         = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO),
+       MV_6XXX_FLAGS           = (MV_FLAG_IRQ_COALESCE | 
+                                  MV_FLAG_GLBL_SFT_RST),
 
        chip_504x               = 0,
        chip_508x               = 1,
        chip_604x               = 2,
        chip_608x               = 3,
 
+       CRQB_FLAG_READ          = (1 << 0),
+       CRQB_TAG_SHIFT          = 1,
+       CRQB_CMD_ADDR_SHIFT     = 8,
+       CRQB_CMD_CS             = (0x2 << 11),
+       CRQB_CMD_LAST           = (1 << 15),
+
+       CRPB_FLAG_STATUS_SHIFT  = 8,
+
+       EPRD_FLAG_END_OF_TBL    = (1 << 31),
+
        /* PCI interface registers */
 
+       PCI_COMMAND_OFS         = 0xc00,
+
        PCI_MAIN_CMD_STS_OFS    = 0xd30,
        STOP_PCI_MASTER         = (1 << 2),
        PCI_MASTER_EMPTY        = (1 << 3),
@@ -111,20 +141,13 @@ enum {
        HC_CFG_OFS              = 0,
 
        HC_IRQ_CAUSE_OFS        = 0x14,
-       CRBP_DMA_DONE           = (1 << 0),     /* shift by port # */
+       CRPB_DMA_DONE           = (1 << 0),     /* shift by port # */
        HC_IRQ_COAL             = (1 << 4),     /* IRQ coalescing */
        DEV_IRQ                 = (1 << 8),     /* shift by port # */
 
        /* Shadow block registers */
-       SHD_PIO_DATA_OFS        = 0x100,
-       SHD_FEA_ERR_OFS         = 0x104,
-       SHD_SECT_CNT_OFS        = 0x108,
-       SHD_LBA_L_OFS           = 0x10C,
-       SHD_LBA_M_OFS           = 0x110,
-       SHD_LBA_H_OFS           = 0x114,
-       SHD_DEV_HD_OFS          = 0x118,
-       SHD_CMD_STA_OFS         = 0x11C,
-       SHD_CTL_AST_OFS         = 0x120,
+       SHD_BLK_OFS             = 0x100,
+       SHD_CTL_AST_OFS         = 0x20,         /* ofs from SHD_BLK_OFS */
 
        /* SATA registers */
        SATA_STATUS_OFS         = 0x300,  /* ctrl, err regs follow status */
@@ -132,6 +155,11 @@ enum {
 
        /* Port registers */
        EDMA_CFG_OFS            = 0,
+       EDMA_CFG_Q_DEPTH        = 0,                    /* queueing disabled */
+       EDMA_CFG_NCQ            = (1 << 5),
+       EDMA_CFG_NCQ_GO_ON_ERR  = (1 << 14),            /* continue on error */
+       EDMA_CFG_RD_BRST_EXT    = (1 << 11),            /* read burst 512B */
+       EDMA_CFG_WR_BUFF_LEN    = (1 << 13),            /* write buffer 512B */
 
        EDMA_ERR_IRQ_CAUSE_OFS  = 0x8,
        EDMA_ERR_IRQ_MASK_OFS   = 0xc,
@@ -161,33 +189,85 @@ enum {
                                   EDMA_ERR_LNK_DATA_TX | 
                                   EDMA_ERR_TRANS_PROTO),
 
+       EDMA_REQ_Q_BASE_HI_OFS  = 0x10,
+       EDMA_REQ_Q_IN_PTR_OFS   = 0x14,         /* also contains BASE_LO */
+       EDMA_REQ_Q_BASE_LO_MASK = 0xfffffc00U,
+
+       EDMA_REQ_Q_OUT_PTR_OFS  = 0x18,
+       EDMA_REQ_Q_PTR_SHIFT    = 5,
+
+       EDMA_RSP_Q_BASE_HI_OFS  = 0x1c,
+       EDMA_RSP_Q_IN_PTR_OFS   = 0x20,
+       EDMA_RSP_Q_OUT_PTR_OFS  = 0x24,         /* also contains BASE_LO */
+       EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U,
+       EDMA_RSP_Q_PTR_SHIFT    = 3,
+
        EDMA_CMD_OFS            = 0x28,
        EDMA_EN                 = (1 << 0),
        EDMA_DS                 = (1 << 1),
        ATA_RST                 = (1 << 2),
 
-       /* BDMA is 6xxx part only */
-       BDMA_CMD_OFS            = 0x224,
-       BDMA_START              = (1 << 0),
+       /* Host private flags (hp_flags) */
+       MV_HP_FLAG_MSI          = (1 << 0),
 
-       MV_UNDEF                = 0,
+       /* Port private flags (pp_flags) */
+       MV_PP_FLAG_EDMA_EN      = (1 << 0),
+       MV_PP_FLAG_EDMA_DS_ACT  = (1 << 1),
 };
 
-struct mv_port_priv {
+/* Command ReQuest Block: 32B */
+struct mv_crqb {
+       u32                     sg_addr;
+       u32                     sg_addr_hi;
+       u16                     ctrl_flags;
+       u16                     ata_cmd[11];
+};
 
+/* Command ResPonse Block: 8B */
+struct mv_crpb {
+       u16                     id;
+       u16                     flags;
+       u32                     tmstmp;
 };
 
-struct mv_host_priv {
+/* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
+struct mv_sg {
+       u32                     addr;
+       u32                     flags_size;
+       u32                     addr_hi;
+       u32                     reserved;
+};
 
+struct mv_port_priv {
+       struct mv_crqb          *crqb;
+       dma_addr_t              crqb_dma;
+       struct mv_crpb          *crpb;
+       dma_addr_t              crpb_dma;
+       struct mv_sg            *sg_tbl;
+       dma_addr_t              sg_tbl_dma;
+
+       unsigned                req_producer;           /* cp of req_in_ptr */
+       unsigned                rsp_consumer;           /* cp of rsp_out_ptr */
+       u32                     pp_flags;
+};
+
+struct mv_host_priv {
+       u32                     hp_flags;
 };
 
 static void mv_irq_clear(struct ata_port *ap);
 static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
 static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
+static u8 mv_check_err(struct ata_port *ap);
 static void mv_phy_reset(struct ata_port *ap);
-static int mv_master_reset(void __iomem *mmio_base);
+static void mv_host_stop(struct ata_host_set *host_set);
+static int mv_port_start(struct ata_port *ap);
+static void mv_port_stop(struct ata_port *ap);
+static void mv_qc_prep(struct ata_queued_cmd *qc);
+static int mv_qc_issue(struct ata_queued_cmd *qc);
 static irqreturn_t mv_interrupt(int irq, void *dev_instance,
                                struct pt_regs *regs);
+static void mv_eng_timeout(struct ata_port *ap);
 static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 
 static Scsi_Host_Template mv_sht = {
@@ -196,13 +276,13 @@ static Scsi_Host_Template mv_sht = {
        .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
        .eh_strategy_handler    = ata_scsi_error,
-       .can_queue              = ATA_DEF_QUEUE,
+       .can_queue              = MV_USE_Q_DEPTH,
        .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = MV_UNDEF,
+       .sg_tablesize           = MV_MAX_SG_CT,
        .max_sectors            = ATA_MAX_SECTORS,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
        .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = MV_UNDEF,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
        .proc_name              = DRV_NAME,
        .dma_boundary           = MV_DMA_BOUNDARY,
        .slave_configure        = ata_scsi_slave_config,
@@ -216,15 +296,16 @@ static struct ata_port_operations mv_ops = {
        .tf_load                = ata_tf_load,
        .tf_read                = ata_tf_read,
        .check_status           = ata_check_status,
+       .check_err              = mv_check_err,
        .exec_command           = ata_exec_command,
        .dev_select             = ata_std_dev_select,
 
        .phy_reset              = mv_phy_reset,
 
-       .qc_prep                = ata_qc_prep,
-       .qc_issue               = ata_qc_issue_prot,
+       .qc_prep                = mv_qc_prep,
+       .qc_issue               = mv_qc_issue,
 
-       .eng_timeout            = ata_eng_timeout,
+       .eng_timeout            = mv_eng_timeout,
 
        .irq_handler            = mv_interrupt,
        .irq_clear              = mv_irq_clear,
@@ -232,46 +313,39 @@ static struct ata_port_operations mv_ops = {
        .scr_read               = mv_scr_read,
        .scr_write              = mv_scr_write,
 
-       .port_start             = ata_port_start,
-       .port_stop              = ata_port_stop,
-       .host_stop              = ata_host_stop,
+       .port_start             = mv_port_start,
+       .port_stop              = mv_port_stop,
+       .host_stop              = mv_host_stop,
 };
 
 static struct ata_port_info mv_port_info[] = {
        {  /* chip_504x */
                .sht            = &mv_sht,
-               .host_flags     = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO),
-               .pio_mask       = 0x1f, /* pio4-0 */
-               .udma_mask      = 0,    /* 0x7f (udma6-0 disabled for now) */
+               .host_flags     = MV_COMMON_FLAGS,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0,    /* 0x7f (udma0-6 disabled for now) */
                .port_ops       = &mv_ops,
        },
        {  /* chip_508x */
                .sht            = &mv_sht,
-               .host_flags     = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | 
-                                  MV_FLAG_DUAL_HC),
-               .pio_mask       = 0x1f, /* pio4-0 */
-               .udma_mask      = 0,    /* 0x7f (udma6-0 disabled for now) */
+               .host_flags     = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0,    /* 0x7f (udma0-6 disabled for now) */
                .port_ops       = &mv_ops,
        },
        {  /* chip_604x */
                .sht            = &mv_sht,
-               .host_flags     = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | 
-                                  MV_FLAG_IRQ_COALESCE | MV_FLAG_BDMA),
-               .pio_mask       = 0x1f, /* pio4-0 */
-               .udma_mask      = 0,    /* 0x7f (udma6-0 disabled for now) */
+               .host_flags     = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 */
                .port_ops       = &mv_ops,
        },
        {  /* chip_608x */
                .sht            = &mv_sht,
-               .host_flags     = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                  ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
-                                  MV_FLAG_IRQ_COALESCE | MV_FLAG_DUAL_HC |
-                                  MV_FLAG_BDMA),
-               .pio_mask       = 0x1f, /* pio4-0 */
-               .udma_mask      = 0,    /* 0x7f (udma6-0 disabled for now) */
+               .host_flags     = (MV_COMMON_FLAGS | MV_6XXX_FLAGS | 
+                                  MV_FLAG_DUAL_HC),
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 */
                .port_ops       = &mv_ops,
        },
 };
@@ -306,12 +380,6 @@ static inline void writelfl(unsigned long data, void __iomem *addr)
        (void) readl(addr);     /* flush to avoid PCI posted write */
 }
 
-static inline void __iomem *mv_port_addr_to_hc_base(void __iomem *port_mmio)
-{
-       return ((void __iomem *)((unsigned long)port_mmio & 
-                                (unsigned long)SATAHC_MASK));
-}
-
 static inline void __iomem *mv_hc_base(void __iomem *base, unsigned int hc)
 {
        return (base + MV_SATAHC0_REG_BASE + (hc * MV_SATAHC_REG_SZ));
@@ -329,24 +397,141 @@ static inline void __iomem *mv_ap_base(struct ata_port *ap)
        return mv_port_base(ap->host_set->mmio_base, ap->port_no);
 }
 
-static inline int mv_get_hc_count(unsigned long flags)
+static inline int mv_get_hc_count(unsigned long hp_flags)
+{
+       return ((hp_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
+}
+
+static void mv_irq_clear(struct ata_port *ap)
 {
-       return ((flags & MV_FLAG_DUAL_HC) ? 2 : 1);
 }
 
-static inline int mv_is_edma_active(struct ata_port *ap)
+static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp,
+                        struct ata_port *ap)
 {
-       void __iomem *port_mmio = mv_ap_base(ap);
-       return (EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
+       unsigned long flags;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       
+       writelfl(EDMA_EN, base + EDMA_CMD_OFS);
+       pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
+
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
 }
 
-static inline int mv_port_bdma_capable(struct ata_port *ap)
+static void mv_stop_dma(struct ata_port *ap)
 {
-       return (ap->flags & MV_FLAG_BDMA);
+       void __iomem *port_mmio = mv_ap_base(ap);
+       struct mv_port_priv *pp = ap->private_data;
+       unsigned long flags;
+       u32 reg;
+       int i;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       
+       if (!(MV_PP_FLAG_EDMA_DS_ACT & pp->pp_flags) &&
+           ((MV_PP_FLAG_EDMA_EN & pp->pp_flags) ||
+            (EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)))) {
+               /* Disable EDMA if we're not already trying to disable it
+                * and it is currently active.   The disable bit auto clears.
+                */
+               pp->pp_flags |= MV_PP_FLAG_EDMA_DS_ACT;
+               writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+               pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+       }
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       
+       /* now properly wait for the eDMA to stop */
+       for (i = 1000; i > 0; i--) {
+               reg = readl(port_mmio + EDMA_CMD_OFS);
+               if (!(EDMA_EN & reg)) {
+                       break;
+               }
+               udelay(100);
+       }
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       pp->pp_flags &= ~MV_PP_FLAG_EDMA_DS_ACT;
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       if (EDMA_EN & reg) {
+               printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id);
+       }
 }
 
-static void mv_irq_clear(struct ata_port *ap)
+static void mv_dump_mem(void __iomem *start, unsigned bytes)
 {
+#ifdef ATA_DEBUG
+       int b, w;
+       for (b = 0; b < bytes; ) {
+               DPRINTK("%p: ", start + b);
+               for (w = 0; b < bytes && w < 4; w++) {
+                       printk("%08x ",readl(start + b));
+                       b += sizeof(u32);
+               }
+               printk("\n");
+       }
+#endif
+}
+static void mv_dump_pci_cfg(struct pci_dev *pdev, unsigned bytes)
+{
+#ifdef ATA_DEBUG
+       int b, w;
+       u32 dw;
+       for (b = 0; b < bytes; ) {
+               DPRINTK("%02x: ", b);
+               for (w = 0; b < bytes && w < 4; w++) {
+                       (void) pci_read_config_dword(pdev,b,&dw);
+                       printk("%08x ",dw);
+                       b += sizeof(u32);
+               }
+               printk("\n");
+       }
+#endif
+}
+static void mv_dump_all_regs(void __iomem *mmio_base, int port,
+                            struct pci_dev *pdev)
+{
+#ifdef ATA_DEBUG
+       void __iomem *hc_base = mv_hc_base(mmio_base, 
+                                          port >> MV_PORT_HC_SHIFT);
+       void __iomem *port_base;
+       int start_port, num_ports, p, start_hc, num_hcs, hc;
+
+       if (0 > port) {
+               start_hc = start_port = 0;
+               num_ports = 8;          /* shld be benign for 4 port devs */
+               num_hcs = 2;
+       } else {
+               start_hc = port >> MV_PORT_HC_SHIFT;
+               start_port = port;
+               num_ports = num_hcs = 1;
+       }
+       DPRINTK("All registers for port(s) %u-%u:\n", start_port, 
+               num_ports > 1 ? num_ports - 1 : start_port);
+
+       if (NULL != pdev) {
+               DPRINTK("PCI config space regs:\n");
+               mv_dump_pci_cfg(pdev, 0x68);
+       }
+       DPRINTK("PCI regs:\n");
+       mv_dump_mem(mmio_base+0xc00, 0x3c);
+       mv_dump_mem(mmio_base+0xd00, 0x34);
+       mv_dump_mem(mmio_base+0xf00, 0x4);
+       mv_dump_mem(mmio_base+0x1d00, 0x6c);
+       for (hc = start_hc; hc < start_hc + num_hcs; hc++) {
+               hc_base = mv_hc_base(mmio_base, port >> MV_PORT_HC_SHIFT);
+               DPRINTK("HC regs (HC %i):\n", hc);
+               mv_dump_mem(hc_base, 0x1c);
+       }
+       for (p = start_port; p < start_port + num_ports; p++) {
+               port_base = mv_port_base(mmio_base, p);
+               DPRINTK("EDMA regs (port %i):\n",p);
+               mv_dump_mem(port_base, 0x54);
+               DPRINTK("SATA regs (port %i):\n",p);
+               mv_dump_mem(port_base+0x300, 0x60);
+       }
+#endif
 }
 
 static unsigned int mv_scr_offset(unsigned int sc_reg_in)
@@ -389,30 +574,29 @@ static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
        }
 }
 
-static int mv_master_reset(void __iomem *mmio_base)
+/* This routine only applies to 6xxx parts */
+static int mv_global_soft_reset(void __iomem *mmio_base)
 {
        void __iomem *reg = mmio_base + PCI_MAIN_CMD_STS_OFS;
        int i, rc = 0;
        u32 t;
 
-       VPRINTK("ENTER\n");
-
        /* Following procedure defined in PCI "main command and status
         * register" table.
         */
        t = readl(reg);
        writel(t | STOP_PCI_MASTER, reg);
 
-       for (i = 0; i < 100; i++) {
-               msleep(10);
+       for (i = 0; i < 1000; i++) {
+               udelay(1);
                t = readl(reg);
                if (PCI_MASTER_EMPTY & t) {
                        break;
                }
        }
        if (!(PCI_MASTER_EMPTY & t)) {
-               printk(KERN_ERR DRV_NAME "PCI master won't flush\n");
-               rc = 1;         /* broken HW? */
+               printk(KERN_ERR DRV_NAME "PCI master won't flush\n");
+               rc = 1;
                goto done;
        }
 
@@ -425,39 +609,311 @@ static int mv_master_reset(void __iomem *mmio_base)
        } while (!(GLOB_SFT_RST & t) && (i-- > 0));
 
        if (!(GLOB_SFT_RST & t)) {
-               printk(KERN_ERR DRV_NAME "can't set global reset\n");
-               rc = 1;         /* broken HW? */
+               printk(KERN_ERR DRV_NAME "can't set global reset\n");
+               rc = 1;
                goto done;
        }
 
-       /* clear reset */
+       /* clear reset and *reenable the PCI master* (not mentioned in spec) */
        i = 5;
        do {
-               writel(t & ~GLOB_SFT_RST, reg);
+               writel(t & ~(GLOB_SFT_RST | STOP_PCI_MASTER), reg);
                t = readl(reg);
                udelay(1);
        } while ((GLOB_SFT_RST & t) && (i-- > 0));
 
        if (GLOB_SFT_RST & t) {
-               printk(KERN_ERR DRV_NAME "can't clear global reset\n");
-               rc = 1;         /* broken HW? */
+               printk(KERN_ERR DRV_NAME "can't clear global reset\n");
+               rc = 1;
        }
-
- done:
-       VPRINTK("EXIT, rc = %i\n", rc);
+done:
        return rc;
 }
 
-static void mv_err_intr(struct ata_port *ap)
+static void mv_host_stop(struct ata_host_set *host_set)
 {
-       void __iomem *port_mmio;
-       u32 edma_err_cause, serr = 0;
+       struct mv_host_priv *hpriv = host_set->private_data;
+       struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+       if (hpriv->hp_flags & MV_HP_FLAG_MSI) {
+               pci_disable_msi(pdev);
+       } else {
+               pci_intx(pdev, 0);
+       }
+       kfree(hpriv);
+       ata_host_stop(host_set);
+}
+
+static int mv_port_start(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct mv_port_priv *pp;
+       void __iomem *port_mmio = mv_ap_base(ap);
+       void *mem;
+       dma_addr_t mem_dma;
+
+       pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+       if (!pp) {
+               return -ENOMEM;
+       }
+       memset(pp, 0, sizeof(*pp));
+
+       mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, 
+                                GFP_KERNEL);
+       if (!mem) {
+               kfree(pp);
+               return -ENOMEM;
+       }
+       memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
+
+       /* First item in chunk of DMA memory: 
+        * 32-slot command request table (CRQB), 32 bytes each in size
+        */
+       pp->crqb = mem;
+       pp->crqb_dma = mem_dma;
+       mem += MV_CRQB_Q_SZ;
+       mem_dma += MV_CRQB_Q_SZ;
+
+       /* Second item: 
+        * 32-slot command response table (CRPB), 8 bytes each in size
+        */
+       pp->crpb = mem;
+       pp->crpb_dma = mem_dma;
+       mem += MV_CRPB_Q_SZ;
+       mem_dma += MV_CRPB_Q_SZ;
+
+       /* Third item:
+        * Table of scatter-gather descriptors (ePRD), 16 bytes each
+        */
+       pp->sg_tbl = mem;
+       pp->sg_tbl_dma = mem_dma;
+
+       writelfl(EDMA_CFG_Q_DEPTH | EDMA_CFG_RD_BRST_EXT | 
+                EDMA_CFG_WR_BUFF_LEN, port_mmio + EDMA_CFG_OFS);
+
+       writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
+       writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK, 
+                port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+       writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+       writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+
+       writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
+       writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, 
+                port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+       pp->req_producer = pp->rsp_consumer = 0;
+
+       /* Don't turn on EDMA here...do it before DMA commands only.  Else
+        * we'll be unable to send non-data, PIO, etc due to restricted access
+        * to shadow regs.
+        */
+       ap->private_data = pp;
+       return 0;
+}
+
+static void mv_port_stop(struct ata_port *ap)
+{
+       struct device *dev = ap->host_set->dev;
+       struct mv_port_priv *pp = ap->private_data;
+
+       mv_stop_dma(ap);
+
+       ap->private_data = NULL;
+       dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma);
+       kfree(pp);
+}
+
+static void mv_fill_sg(struct ata_queued_cmd *qc)
+{
+       struct mv_port_priv *pp = qc->ap->private_data;
+       unsigned int i;
+
+       for (i = 0; i < qc->n_elem; i++) {
+               u32 sg_len;
+               dma_addr_t addr;
+
+               addr = sg_dma_address(&qc->sg[i]);
+               sg_len = sg_dma_len(&qc->sg[i]);
+
+               pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff);
+               pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
+               assert(0 == (sg_len & ~MV_DMA_BOUNDARY));
+               pp->sg_tbl[i].flags_size = cpu_to_le32(sg_len);
+       }
+       if (0 < qc->n_elem) {
+               pp->sg_tbl[qc->n_elem - 1].flags_size |= EPRD_FLAG_END_OF_TBL;
+       }
+}
+
+static inline unsigned mv_inc_q_index(unsigned *index)
+{
+       *index = (*index + 1) & MV_MAX_Q_DEPTH_MASK;
+       return *index;
+}
+
+static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last)
+{
+       *cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
+               (last ? CRQB_CMD_LAST : 0);
+}
+
+static void mv_qc_prep(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct mv_port_priv *pp = ap->private_data;
+       u16 *cw;
+       struct ata_taskfile *tf;
+       u16 flags = 0;
+
+       if (ATA_PROT_DMA != qc->tf.protocol) {
+               return;
+       }
 
-       /* bug here b/c we got an err int on a port we don't know about,
-        * so there's no way to clear it
+       /* the req producer index should be the same as we remember it */
+       assert(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> 
+                EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+              pp->req_producer);
+
+       /* Fill in command request block
+        */
+       if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+               flags |= CRQB_FLAG_READ;
+       }
+       assert(MV_MAX_Q_DEPTH > qc->tag);
+       flags |= qc->tag << CRQB_TAG_SHIFT;
+
+       pp->crqb[pp->req_producer].sg_addr = 
+               cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
+       pp->crqb[pp->req_producer].sg_addr_hi = 
+               cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
+       pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags);
+
+       cw = &pp->crqb[pp->req_producer].ata_cmd[0];
+       tf = &qc->tf;
+
+       /* Sadly, the CRQB cannot accomodate all registers--there are
+        * only 11 bytes...so we must pick and choose required
+        * registers based on the command.  So, we drop feature and
+        * hob_feature for [RW] DMA commands, but they are needed for
+        * NCQ.  NCQ will drop hob_nsect.
         */
-       BUG_ON(NULL == ap);
-       port_mmio = mv_ap_base(ap);
+       switch (tf->command) {
+       case ATA_CMD_READ:
+       case ATA_CMD_READ_EXT:
+       case ATA_CMD_WRITE:
+       case ATA_CMD_WRITE_EXT:
+               mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
+               break;
+#ifdef LIBATA_NCQ              /* FIXME: remove this line when NCQ added */
+       case ATA_CMD_FPDMA_READ:
+       case ATA_CMD_FPDMA_WRITE:
+               mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0); 
+               mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
+               break;
+#endif                         /* FIXME: remove this line when NCQ added */
+       default:
+               /* The only other commands EDMA supports in non-queued and
+                * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
+                * of which are defined/used by Linux.  If we get here, this
+                * driver needs work.
+                *
+                * FIXME: modify libata to give qc_prep a return value and
+                * return error here.
+                */
+               BUG_ON(tf->command);
+               break;
+       }
+       mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
+       mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
+       mv_crqb_pack_cmd(cw++, tf->lbal, ATA_REG_LBAL, 0);
+       mv_crqb_pack_cmd(cw++, tf->hob_lbam, ATA_REG_LBAM, 0);
+       mv_crqb_pack_cmd(cw++, tf->lbam, ATA_REG_LBAM, 0);
+       mv_crqb_pack_cmd(cw++, tf->hob_lbah, ATA_REG_LBAH, 0);
+       mv_crqb_pack_cmd(cw++, tf->lbah, ATA_REG_LBAH, 0);
+       mv_crqb_pack_cmd(cw++, tf->device, ATA_REG_DEVICE, 0);
+       mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);    /* last */
+
+       if (!(qc->flags & ATA_QCFLAG_DMAMAP)) {
+               return;
+       }
+       mv_fill_sg(qc);
+}
+
+static int mv_qc_issue(struct ata_queued_cmd *qc)
+{
+       void __iomem *port_mmio = mv_ap_base(qc->ap);
+       struct mv_port_priv *pp = qc->ap->private_data;
+       u32 in_ptr;
+
+       if (ATA_PROT_DMA != qc->tf.protocol) {
+               /* We're about to send a non-EDMA capable command to the
+                * port.  Turn off EDMA so there won't be problems accessing
+                * shadow block, etc registers.
+                */
+               mv_stop_dma(qc->ap);
+               return ata_qc_issue_prot(qc);
+       }
+
+       in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+       /* the req producer index should be the same as we remember it */
+       assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+              pp->req_producer);
+       /* until we do queuing, the queue should be empty at this point */
+       assert(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) ==
+              ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >> 
+                EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
+
+       mv_inc_q_index(&pp->req_producer);      /* now incr producer index */
+
+       if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
+               /* turn on EDMA if not already on */
+               mv_start_dma(port_mmio, pp, qc->ap);
+       }
+       assert(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS));
+
+       /* and write the request in pointer to kick the EDMA to life */
+       in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
+       in_ptr |= pp->req_producer << EDMA_REQ_Q_PTR_SHIFT;
+       writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+       return 0;
+}
+
+static u8 mv_get_crpb_status(struct ata_port *ap)
+{
+       void __iomem *port_mmio = mv_ap_base(ap);
+       struct mv_port_priv *pp = ap->private_data;
+       u32 out_ptr;
+
+       out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+       /* the response consumer index should be the same as we remember it */
+       assert(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == 
+              pp->rsp_consumer);
+
+       /* increment our consumer index... */
+       pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer);
+       
+       /* and, until we do NCQ, there should only be 1 CRPB waiting */
+       assert(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >> 
+                EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) == 
+              pp->rsp_consumer);
+
+       /* write out our inc'd consumer index so EDMA knows we're caught up */
+       out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
+       out_ptr |= pp->rsp_consumer << EDMA_RSP_Q_PTR_SHIFT;
+       writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+
+       /* Return ATA status register for completed CRPB */
+       return (pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT);
+}
+
+static void mv_err_intr(struct ata_port *ap)
+{
+       void __iomem *port_mmio = mv_ap_base(ap);
+       u32 edma_err_cause, serr = 0;
 
        edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
@@ -477,8 +933,7 @@ static void mv_err_intr(struct ata_port *ap)
        }
 }
 
-/* Handle any outstanding interrupts in a single SATAHC 
- */
+/* Handle any outstanding interrupts in a single SATAHC */
 static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
                         unsigned int hc)
 {
@@ -487,8 +942,8 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
        struct ata_port *ap;
        struct ata_queued_cmd *qc;
        u32 hc_irq_cause;
-       int shift, port, port0, hard_port;
-       u8 ata_status;
+       int shift, port, port0, hard_port, handled;
+       u8 ata_status = 0;
 
        if (hc == 0) {
                port0 = 0;
@@ -499,7 +954,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
        /* we'll need the HC success int register in most cases */
        hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
        if (hc_irq_cause) {
-               writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
+               writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
        }
 
        VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
@@ -508,35 +963,38 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
        for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
                ap = host_set->ports[port];
                hard_port = port & MV_PORT_MASK;        /* range 0-3 */
-               ata_status = 0xffU;
+               handled = 0;    /* ensure ata_status is set if handled++ */
 
-               if (((CRBP_DMA_DONE | DEV_IRQ) << hard_port) & hc_irq_cause) {
-                       BUG_ON(NULL == ap);
-                       /* rcv'd new resp, basic DMA complete, or ATA IRQ */
-                       /* This is needed to clear the ATA INTRQ.
-                        * FIXME: don't read the status reg in EDMA mode!
+               if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
+                       /* new CRPB on the queue; just one at a time until NCQ
+                        */
+                       ata_status = mv_get_crpb_status(ap);
+                       handled++;
+               } else if ((DEV_IRQ << hard_port) & hc_irq_cause) {
+                       /* received ATA IRQ; read the status reg to clear INTRQ
                         */
                        ata_status = readb((void __iomem *)
                                           ap->ioaddr.status_addr);
+                       handled++;
                }
 
-               shift = port * 2;
+               shift = port << 1;              /* (port * 2) */
                if (port >= MV_PORTS_PER_HC) {
                        shift++;        /* skip bit 8 in the HC Main IRQ reg */
                }
                if ((PORT0_ERR << shift) & relevant) {
                        mv_err_intr(ap);
-                       /* FIXME: smart to OR in ATA_ERR? */
+                       /* OR in ATA_ERR to ensure libata knows we took one */
                        ata_status = readb((void __iomem *)
                                           ap->ioaddr.status_addr) | ATA_ERR;
+                       handled++;
                }
                
-               if (ap) {
+               if (handled && ap) {
                        qc = ata_qc_from_tag(ap, ap->active_tag);
                        if (NULL != qc) {
                                VPRINTK("port %u IRQ found for qc, "
                                        "ata_status 0x%x\n", port,ata_status);
-                               BUG_ON(0xffU == ata_status);
                                /* mark qc status appropriately */
                                ata_qc_complete(qc, ata_status);
                        }
@@ -550,12 +1008,10 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
 {
        struct ata_host_set *host_set = dev_instance;
        unsigned int hc, handled = 0, n_hcs;
-       void __iomem *mmio;
+       void __iomem *mmio = host_set->mmio_base;
        u32 irq_stat;
 
-       mmio = host_set->mmio_base;
        irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
-       n_hcs = mv_get_hc_count(host_set->ports[0]->flags);
 
        /* check the cases where we either have nothing pending or have read
         * a bogus register value which can indicate HW removal or PCI fault
@@ -564,64 +1020,87 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
                return IRQ_NONE;
        }
 
+       n_hcs = mv_get_hc_count(host_set->ports[0]->flags);
        spin_lock(&host_set->lock);
 
        for (hc = 0; hc < n_hcs; hc++) {
                u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
                if (relevant) {
                        mv_host_intr(host_set, relevant, hc);
-                       handled = 1;
+                       handled++;
                }
        }
        if (PCI_ERR & irq_stat) {
-               /* FIXME: these are all masked by default, but still need
-                * to recover from them properly.
-                */
-       }
+               printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
+                      readl(mmio + PCI_IRQ_CAUSE_OFS));
+
+               VPRINTK("All regs @ PCI error\n");
+               mv_dump_all_regs(mmio, -1, to_pci_dev(host_set->dev));
 
+               writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+               handled++;
+       }
        spin_unlock(&host_set->lock);
 
        return IRQ_RETVAL(handled);
 }
 
+static u8 mv_check_err(struct ata_port *ap)
+{
+       mv_stop_dma(ap);                /* can't read shadow regs if DMA on */
+       return readb((void __iomem *) ap->ioaddr.error_addr);
+}
+
+/* Part of this is taken from __sata_phy_reset and modified to not sleep
+ * since this routine gets called from interrupt level.
+ */
 static void mv_phy_reset(struct ata_port *ap)
 {
        void __iomem *port_mmio = mv_ap_base(ap);
        struct ata_taskfile tf;
        struct ata_device *dev = &ap->device[0];
-       u32 edma = 0, bdma;
+       unsigned long timeout;
 
        VPRINTK("ENTER, port %u, mmio 0x%p\n", ap->port_no, port_mmio);
 
-       edma = readl(port_mmio + EDMA_CMD_OFS);
-       if (EDMA_EN & edma) {
-               /* disable EDMA if active */
-               edma &= ~EDMA_EN;
-               writelfl(edma | EDMA_DS, port_mmio + EDMA_CMD_OFS);
-               udelay(1);
-       } else if (mv_port_bdma_capable(ap) &&
-                  (bdma = readl(port_mmio + BDMA_CMD_OFS)) & BDMA_START) {
-               /* disable BDMA if active */
-               writelfl(bdma & ~BDMA_START, port_mmio + BDMA_CMD_OFS);
-       }
+       mv_stop_dma(ap);
 
-       writelfl(edma | ATA_RST, port_mmio + EDMA_CMD_OFS);
+       writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
        udelay(25);             /* allow reset propagation */
 
        /* Spec never mentions clearing the bit.  Marvell's driver does
         * clear the bit, however.
         */
-       writelfl(edma & ~ATA_RST, port_mmio + EDMA_CMD_OFS);
+       writelfl(0, port_mmio + EDMA_CMD_OFS);
 
-       VPRINTK("Done.  Now calling __sata_phy_reset()\n");
+       VPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
+               "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
+               mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
 
        /* proceed to init communications via the scr_control reg */
-       __sata_phy_reset(ap);
+       scr_write_flush(ap, SCR_CONTROL, 0x301);
+       mdelay(1);
+       scr_write_flush(ap, SCR_CONTROL, 0x300);
+       timeout = jiffies + (HZ * 1);
+       do {
+               mdelay(10);
+               if ((scr_read(ap, SCR_STATUS) & 0xf) != 1)
+                       break;
+       } while (time_before(jiffies, timeout));
 
-       if (ap->flags & ATA_FLAG_PORT_DISABLED) {
-               VPRINTK("Port disabled pre-sig.  Exiting.\n");
+       VPRINTK("S-regs after PHY wake: SStat 0x%08x SErr 0x%08x "
+               "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
+               mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
+
+       if (sata_dev_present(ap)) {
+               ata_port_probe(ap);
+       } else {
+               printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
+                      ap->id, scr_read(ap, SCR_STATUS));
+               ata_port_disable(ap);
                return;
        }
+       ap->cbl = ATA_CBL_SATA;
 
        tf.lbah = readb((void __iomem *) ap->ioaddr.lbah_addr);
        tf.lbam = readb((void __iomem *) ap->ioaddr.lbam_addr);
@@ -636,28 +1115,76 @@ static void mv_phy_reset(struct ata_port *ap)
        VPRINTK("EXIT\n");
 }
 
-static void mv_port_init(struct ata_ioports *port, unsigned long base)
+static void mv_eng_timeout(struct ata_port *ap)
+{
+       struct ata_queued_cmd *qc;
+       unsigned long flags;
+
+       printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
+       DPRINTK("All regs @ start of eng_timeout\n");
+       mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no, 
+                        to_pci_dev(ap->host_set->dev));
+
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+        printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
+              ap->host_set->mmio_base, ap, qc, qc->scsicmd, 
+              &qc->scsicmd->cmnd);
+
+       mv_err_intr(ap);
+       mv_phy_reset(ap);
+
+       if (!qc) {
+               printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+                      ap->id);
+       } else {
+               /* hack alert!  We cannot use the supplied completion
+                * function from inside the ->eh_strategy_handler() thread.
+                * libata is the only user of ->eh_strategy_handler() in
+                * any kernel, so the default scsi_done() assumes it is
+                * not being called from the SCSI EH.
+                */
+               spin_lock_irqsave(&ap->host_set->lock, flags);
+               qc->scsidone = scsi_finish_command;
+               ata_qc_complete(qc, ATA_ERR);
+               spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       }
+}
+
+static void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
 {
-       /* PIO related setup */
-       port->data_addr = base + SHD_PIO_DATA_OFS;
-       port->error_addr = port->feature_addr = base + SHD_FEA_ERR_OFS;
-       port->nsect_addr = base + SHD_SECT_CNT_OFS;
-       port->lbal_addr = base + SHD_LBA_L_OFS;
-       port->lbam_addr = base + SHD_LBA_M_OFS;
-       port->lbah_addr = base + SHD_LBA_H_OFS;
-       port->device_addr = base + SHD_DEV_HD_OFS;
-       port->status_addr = port->command_addr = base + SHD_CMD_STA_OFS;
-       port->altstatus_addr = port->ctl_addr = base + SHD_CTL_AST_OFS;
-       /* unused */
+       unsigned long shd_base = (unsigned long) port_mmio + SHD_BLK_OFS;
+       unsigned serr_ofs;
+
+       /* PIO related setup 
+        */
+       port->data_addr = shd_base + (sizeof(u32) * ATA_REG_DATA);
+       port->error_addr = 
+               port->feature_addr = shd_base + (sizeof(u32) * ATA_REG_ERR);
+       port->nsect_addr = shd_base + (sizeof(u32) * ATA_REG_NSECT);
+       port->lbal_addr = shd_base + (sizeof(u32) * ATA_REG_LBAL);
+       port->lbam_addr = shd_base + (sizeof(u32) * ATA_REG_LBAM);
+       port->lbah_addr = shd_base + (sizeof(u32) * ATA_REG_LBAH);
+       port->device_addr = shd_base + (sizeof(u32) * ATA_REG_DEVICE);
+       port->status_addr = 
+               port->command_addr = shd_base + (sizeof(u32) * ATA_REG_STATUS);
+       /* special case: control/altstatus doesn't have ATA_REG_ address */
+       port->altstatus_addr = port->ctl_addr = shd_base + SHD_CTL_AST_OFS;
+
+       /* unused: */
        port->cmd_addr = port->bmdma_addr = port->scr_addr = 0;
 
+       /* Clear any currently outstanding port interrupt conditions */
+       serr_ofs = mv_scr_offset(SCR_ERROR);
+       writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
+       writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
        /* unmask all EDMA error interrupts */
-       writel(~0, (void __iomem *)base + EDMA_ERR_IRQ_MASK_OFS);
+       writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
 
        VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n", 
-               readl((void __iomem *)base + EDMA_CFG_OFS),
-               readl((void __iomem *)base + EDMA_ERR_IRQ_CAUSE_OFS),
-               readl((void __iomem *)base + EDMA_ERR_IRQ_MASK_OFS));
+               readl(port_mmio + EDMA_CFG_OFS),
+               readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS),
+               readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
 }
 
 static int mv_host_init(struct ata_probe_ent *probe_ent)
@@ -666,7 +1193,8 @@ static int mv_host_init(struct ata_probe_ent *probe_ent)
        void __iomem *mmio = probe_ent->mmio_base;
        void __iomem *port_mmio;
 
-       if (mv_master_reset(probe_ent->mmio_base)) {
+       if ((MV_FLAG_GLBL_SFT_RST & probe_ent->host_flags) && 
+           mv_global_soft_reset(probe_ent->mmio_base)) {
                rc = 1;
                goto done;
        }
@@ -676,17 +1204,27 @@ static int mv_host_init(struct ata_probe_ent *probe_ent)
 
        for (port = 0; port < probe_ent->n_ports; port++) {
                port_mmio = mv_port_base(mmio, port);
-               mv_port_init(&probe_ent->port[port], (unsigned long)port_mmio);
+               mv_port_init(&probe_ent->port[port], port_mmio);
        }
 
        for (hc = 0; hc < n_hc; hc++) {
-               VPRINTK("HC%i: HC config=0x%08x HC IRQ cause=0x%08x\n", hc,
-                       readl(mv_hc_base(mmio, hc) + HC_CFG_OFS),
-                       readl(mv_hc_base(mmio, hc) + HC_IRQ_CAUSE_OFS));
+               void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+
+               VPRINTK("HC%i: HC config=0x%08x HC IRQ cause "
+                       "(before clear)=0x%08x\n", hc,
+                       readl(hc_mmio + HC_CFG_OFS),
+                       readl(hc_mmio + HC_IRQ_CAUSE_OFS));
+
+               /* Clear any currently outstanding hc interrupt conditions */
+               writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
        }
 
-       writel(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
-       writel(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+       /* Clear any currently outstanding host interrupt conditions */
+       writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+
+       /* and unmask interrupt generation for host regs */
+       writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+       writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
 
        VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
                "PCI int cause/mask=0x%08x/0x%08x\n", 
@@ -694,11 +1232,37 @@ static int mv_host_init(struct ata_probe_ent *probe_ent)
                readl(mmio + HC_MAIN_IRQ_MASK_OFS),
                readl(mmio + PCI_IRQ_CAUSE_OFS),
                readl(mmio + PCI_IRQ_MASK_OFS));
-
- done:
+done:
        return rc;
 }
 
+/* FIXME: complete this */
+static void mv_print_info(struct ata_probe_ent *probe_ent)
+{
+       struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
+       struct mv_host_priv *hpriv = probe_ent->private_data;
+       u8 rev_id, scc;
+       const char *scc_s;
+
+       /* Use this to determine the HW stepping of the chip so we know
+        * what errata to workaround
+        */
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
+
+       pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
+       if (scc == 0)
+               scc_s = "SCSI";
+       else if (scc == 0x01)
+               scc_s = "RAID";
+       else
+               scc_s = "unknown";
+
+       printk(KERN_INFO DRV_NAME 
+              "(%s) %u slots %u ports %s mode IRQ via %s\n",
+              pci_name(pdev), (unsigned)MV_MAX_Q_DEPTH, probe_ent->n_ports, 
+              scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
+}
+
 static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version = 0;
@@ -706,16 +1270,12 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct mv_host_priv *hpriv;
        unsigned int board_idx = (unsigned int)ent->driver_data;
        void __iomem *mmio_base;
-       int pci_dev_busy = 0;
-       int rc;
+       int pci_dev_busy = 0, rc;
 
        if (!printed_version++) {
-               printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+               printk(KERN_INFO DRV_NAME " version " DRV_VERSION "\n");
        }
 
-       VPRINTK("ENTER for PCI Bus:Slot.Func=%u:%u.%u\n", pdev->bus->number,
-               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
-
        rc = pci_enable_device(pdev);
        if (rc) {
                return rc;
@@ -727,8 +1287,6 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_out;
        }
 
-       pci_intx(pdev, 1);
-
        probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
        if (probe_ent == NULL) {
                rc = -ENOMEM;
@@ -739,8 +1297,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        probe_ent->dev = pci_dev_to_dev(pdev);
        INIT_LIST_HEAD(&probe_ent->node);
 
-       mmio_base = ioremap_nocache(pci_resource_start(pdev, MV_PRIMARY_BAR),
-                                   pci_resource_len(pdev, MV_PRIMARY_BAR));
+       mmio_base = pci_iomap(pdev, MV_PRIMARY_BAR, 0);
        if (mmio_base == NULL) {
                rc = -ENOMEM;
                goto err_out_free_ent;
@@ -769,37 +1326,40 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc) {
                goto err_out_hpriv;
        }
-/*     mv_print_info(probe_ent); */
 
-       {
-               int b, w;
-               u32 dw[4];      /* hold a line of 16b */
-               VPRINTK("PCI config space:\n");
-               for (b = 0; b < 0x40; ) {
-                       for (w = 0; w < 4; w++) {
-                               (void) pci_read_config_dword(pdev,b,&dw[w]);
-                               b += sizeof(*dw);
-                       }
-                       VPRINTK("%08x %08x %08x %08x\n",
-                               dw[0],dw[1],dw[2],dw[3]);
-               }
+       /* Enable interrupts */
+       if (pci_enable_msi(pdev) == 0) {
+               hpriv->hp_flags |= MV_HP_FLAG_MSI;
+       } else {
+               pci_intx(pdev, 1);
        }
 
-       /* FIXME: check ata_device_add return value */
-       ata_device_add(probe_ent);
-       kfree(probe_ent);
+       mv_dump_pci_cfg(pdev, 0x68);
+       mv_print_info(probe_ent);
+
+       if (ata_device_add(probe_ent) == 0) {
+               rc = -ENODEV;           /* No devices discovered */
+               goto err_out_dev_add;
+       }
 
+       kfree(probe_ent);
        return 0;
 
- err_out_hpriv:
+err_out_dev_add:
+       if (MV_HP_FLAG_MSI & hpriv->hp_flags) {
+               pci_disable_msi(pdev);
+       } else {
+               pci_intx(pdev, 0);
+       }
+err_out_hpriv:
        kfree(hpriv);
- err_out_iounmap:
-       iounmap(mmio_base);
- err_out_free_ent:
+err_out_iounmap:
+       pci_iounmap(pdev, mmio_base);
+err_out_free_ent:
        kfree(probe_ent);
- err_out_regions:
+err_out_regions:
        pci_release_regions(pdev);
- err_out:
+err_out:
        if (!pci_dev_busy) {
                pci_disable_device(pdev);
        }
index c05653c7779dd792855a138a8e4479911d08c592..749ff92d8c63feda1ceb0978876af4c7ea1f6962 100644 (file)
@@ -405,7 +405,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        rc = -ENOMEM;
 
        ppi = &nv_port_info;
-       probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
        if (!probe_ent)
                goto err_out_regions;
 
index 538ad727bd2eb897c32cad017dcad8e11701d6bf..def7e0d9dacb591a88d26a69574c706bd6092c66 100644 (file)
@@ -438,11 +438,11 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
                break;
 
         default:
-                ap->stats.idle_irq++;
-                break;
+               ap->stats.idle_irq++;
+               break;
         }
 
-        return handled;
+       return handled;
 }
 
 static void pdc_irq_clear(struct ata_port *ap)
index b227e51d12f4c3b0f8a591e72967cbe0ebda1bc4..0761a3234fcf092be55ac1f2c837c5c713b61253 100644 (file)
@@ -263,7 +263,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_out_regions;
 
        ppi = &sis_port_info;
-       probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
        if (!probe_ent) {
                rc = -ENOMEM;
                goto err_out_regions;
index 4c9fb8b71be1cb5cb64a047e71d64fd433776882..9c06f2abe7f7950f8bd0a945cb694cc2dca399a5 100644 (file)
@@ -202,7 +202,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_out_regions;
 
        ppi = &uli_port_info;
-       probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
        if (!probe_ent) {
                rc = -ENOMEM;
                goto err_out_regions;
index 128b996b07b70167e3c928a62c035249cbc2e34f..565872479b9a03258a0dc3351c24d83fb4665c6c 100644 (file)
@@ -212,7 +212,7 @@ static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
        struct ata_probe_ent *probe_ent;
        struct ata_port_info *ppi = &svia_port_info;
 
-       probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+       probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
        if (!probe_ent)
                return NULL;
 
index 4d09a6e4dd2ea7143cbeece3813cbc869a211a7d..ad94367df430a8d8df9d9b62109fc2bf545b7af9 100644 (file)
@@ -2849,8 +2849,7 @@ sg_proc_init(void)
        struct proc_dir_entry *pdep;
        struct sg_proc_leaf * leaf;
 
-       sg_proc_sgp = create_proc_entry(sg_proc_sg_dirname,
-                                       S_IFDIR | S_IRUGO | S_IXUGO, NULL);
+       sg_proc_sgp = proc_mkdir(sg_proc_sg_dirname, NULL);
        if (!sg_proc_sgp)
                return 1;
        for (k = 0; k < num_leaves; ++k) {
index 78c1f36ad9b72c3987e8ae64f31f0a7b95f8e419..87ef368384fb31d9d055f169e1c1986e43db8659 100644 (file)
@@ -98,7 +98,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
 {
        struct uart_port *port = dev_id;
        struct tty_struct *tty = port->info->tty;
-       unsigned int status, ch, flg, ignored = 0;
+       unsigned int status, ch, flg;
 
        status = clps_readl(SYSFLG(port));
        while (!(status & SYSFLG_URXFE)) {
index 4c985e6b3784b0b611413c74deba61a98c086997..4e1e80adaf11f4baae5d24e42dcfaaf1be2e26b7 100644 (file)
@@ -860,7 +860,7 @@ imx_console_setup(struct console *co, char *options)
        return uart_set_options(&sport->port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver imx_reg;
+static struct uart_driver imx_reg;
 static struct console imx_console = {
        .name           = "ttySMX",
        .write          = imx_console_write,
index 0c5c96a582b340cec9ea60f12c71262e2ddea2cc..f88fdd48068584bae364d291d6eb0f399ce47948 100644 (file)
@@ -973,18 +973,6 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
                                this_ir &= ~this_mir;
                        }
                }
-               if (this_ir) {
-                       printk(KERN_ERR
-                              "unknown IOC4 %s interrupt 0x%x, sio_ir = 0x%x,"
-                               " sio_ies = 0x%x, other_ir = 0x%x :"
-                               "other_ies = 0x%x\n",
-                              (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" :
-                              "other", this_ir,
-                              readl(&soft->is_ioc4_misc_addr->sio_ir.raw),
-                              readl(&soft->is_ioc4_misc_addr->sio_ies.raw),
-                              readl(&soft->is_ioc4_misc_addr->other_ir.raw),
-                              readl(&soft->is_ioc4_misc_addr->other_ies.raw));
-               }
        }
 #ifdef DEBUG_INTERRUPTS
        {
index c361c6fb08092135171a7165876bb52c27313f19..50d7870d92bb469dd2d13ee00a38d0e874d53dcc 100644 (file)
@@ -82,8 +82,6 @@
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
 
-#include <asm/mach-types.h>
-
 /* structures */
 
 struct s3c24xx_uart_info {
@@ -753,8 +751,8 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
 {
        struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
        struct s3c24xx_uart_port *ourport = to_ourport(port);
-       struct s3c24xx_uart_clksrc *clksrc;
-       struct clk *clk;
+       struct s3c24xx_uart_clksrc *clksrc = NULL;
+       struct clk *clk = NULL;
        unsigned long flags;
        unsigned int baud, quot;
        unsigned int ulcon;
index 1ae0b381c1628c02f268806ccfe9489cbd0676a9..2c7d3ef76e8e8d627eca5c77f2c561b5d7bedc8c 100644 (file)
@@ -859,6 +859,7 @@ static struct pcmcia_device_id serial_ids[] = {
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"),
        PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"),
+       PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"),  /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
        PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
        PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
index cbb451d227d215a372110204ab89950f93f66aed..6385d1a99b60588e97d8d6fd80fc837e0267d02c 100644 (file)
@@ -242,7 +242,6 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
        case HC_STATE_SUSPENDED:
                /* no DMA or IRQs except when HC is active */
                if (dev->current_state == PCI_D0) {
-                       free_irq (hcd->irq, hcd);
                        pci_save_state (dev);
                        pci_disable_device (dev);
                }
@@ -374,14 +373,6 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
 
        hcd->state = HC_STATE_RESUMING;
        hcd->saw_irq = 0;
-       retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
-                               hcd->irq_descr, hcd);
-       if (retval < 0) {
-               dev_err (hcd->self.controller,
-                       "can't restore IRQ after resume!\n");
-               usb_hc_died (hcd);
-               return retval;
-       }
 
        retval = hcd->driver->resume (hcd);
        if (!HC_IS_RUNNING (hcd->state)) {
index 817620d738414cdafd5caaa1bb6d5dd582754eee..859aca7be753bf6dfbc209e0bf19497834262e7a 100644 (file)
@@ -17,8 +17,6 @@
  */
 
 #include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/arch/hardware.h>
 
 
 extern int usb_disabled(void);
index 5cde76faab935bb4376815e6652a423170539245..d8f3ba7ad52e2d9309da74ff0fb8badcdf0f239d 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/io.h>
 #include <asm/mach-types.h>
 
-#include <asm/arch/hardware.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/irqs.h>
 #include <asm/arch/gpio.h>
index 3d9bcf78a9a4f6ed0b9084ac220779342f009c40..da7d5478f74d716a43fce47553a602d747b0afce 100644 (file)
@@ -20,7 +20,6 @@
 */
 
 #include <asm/hardware.h>
-#include <asm/mach-types.h>
 #include <asm/hardware/clock.h>
 #include <asm/arch/usb-control.h>
 
index 4a5857c53f112dc53eed4e0794f8f2fd8a62994d..0bc0b1247a6bc69f4a6ce2fdf5c86a04b0509014 100644 (file)
@@ -1148,7 +1148,7 @@ vicam_write_proc_gain(struct file *file, const char *buffer,
 static void
 vicam_create_proc_root(void)
 {
-       vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0);
+       vicam_proc_root = proc_mkdir("video/vicam", NULL);
 
        if (vicam_proc_root)
                vicam_proc_root->owner = THIS_MODULE;
@@ -1181,7 +1181,7 @@ vicam_create_proc_entry(struct vicam_camera *cam)
 
        sprintf(name, "video%d", cam->vdev.minor);
 
-       cam->proc_dir = create_proc_entry(name, S_IFDIR, vicam_proc_root);
+       cam->proc_dir = proc_mkdir(name, vicam_proc_root);
 
        if ( !cam->proc_dir )
                return; // FIXME: We should probably return an error here
index 773ae11b4a19edfddf92b0333462d6ef19c000d3..1cd942abb58078c94080d093ead2d771e760b02a 100644 (file)
@@ -768,6 +768,7 @@ config FB_INTEL
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select FB_SOFT_CURSOR
        help
          This driver supports the on-board graphics built in to the Intel
           830M/845G/852GM/855GM/865G chipsets.
index 046b47860266daa0ec4c45124d124e90c77a941a..8a24a66d9ba8f6e7033ce0a4667c613ba8e7a183 100644 (file)
@@ -475,7 +475,7 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
         */
 
        /* Flush PCI buffers ? */
-       tmp = INREG(DEVICE_ID);
+       tmp = INREG16(DEVICE_ID);
 
        local_irq_disable();
 
index 59a1b6f85067863a87749913911b2386827ff898..097d668c4fe5932df13b40b2fcf08d8939321b8b 100644 (file)
@@ -62,9 +62,9 @@ static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
                 OUTPLL(pllSCLK_CNTL, tmp);
                return;
        }
-       /* RV350 (M10) */
+       /* RV350 (M10/M11) */
        if (rinfo->family == CHIP_FAMILY_RV350) {
-                /* for RV350/M10, no delays are required. */
+                /* for RV350/M10/M11, no delays are required. */
                 tmp = INPLL(pllSCLK_CNTL2);
                 tmp |= (SCLK_CNTL2__R300_FORCE_TCL |
                         SCLK_CNTL2__R300_FORCE_GA  |
@@ -248,7 +248,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
                return;
        }
 
-       /* M10 */
+       /* M10/M11 */
        if (rinfo->family == CHIP_FAMILY_RV350) {
                tmp = INPLL(pllSCLK_CNTL2);
                tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL |
@@ -1155,7 +1155,7 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
        OUTREG( CRTC_GEN_CNTL,  (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) );
        OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) );
   
-       /* This is the code for the Aluminium PowerBooks M10 */
+       /* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */
        if (rinfo->family == CHIP_FAMILY_RV350) {
                u32 sdram_mode_reg = rinfo->save_regs[35];
                static u32 default_mrtable[] =
@@ -2741,9 +2741,11 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
                        rinfo->pm_mode |= radeon_pm_d2;
 
                /* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip
-                * in some desktop G4s), and Via (M9+ chip on iBook G4)
+                * in some desktop G4s), Via (M9+ chip on iBook G4) and
+                * Snowy (M11 chip on iBook G4 manufactured after July 2005)
                 */
-               if (!strcmp(rinfo->of_node->name, "ATY,JasperParent")) {
+               if (!strcmp(rinfo->of_node->name, "ATY,JasperParent") ||
+                   !strcmp(rinfo->of_node->name, "ATY,SnowyParent")) {
                        rinfo->reinit_func = radeon_reinitialize_M10;
                        rinfo->pm_mode |= radeon_pm_off;
                }
index 659bc9f62244aa316190dddcfa8a0aa22c78ea71..01b8b2f785140677d249fb2d72e12cf6a4396472 100644 (file)
@@ -395,6 +395,8 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
 
 #define INREG8(addr)           readb((rinfo->mmio_base)+addr)
 #define OUTREG8(addr,val)      writeb(val, (rinfo->mmio_base)+addr)
+#define INREG16(addr)          readw((rinfo->mmio_base)+addr)
+#define OUTREG16(addr,val)     writew(val, (rinfo->mmio_base)+addr)
 #define INREG(addr)            readl((rinfo->mmio_base)+addr)
 #define OUTREG(addr,val)       writel(val, (rinfo->mmio_base)+addr)
 
index 630f2dfa9699efe8c3c6685d6956d5ba809c8098..3c72c627e65e99249ceadfbbcc5c8c4d02c8cca4 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/fb.h>
 #include <linux/backlight.h>
 
-#include <asm/mach-types.h>
 #include <asm/arch/sharpsl.h>
 
 #define CORGI_DEFAULT_INTENSITY                0x1f
index ae2762cb560828ab4f6ad8b654fa663c8ffb4fc8..6992100a508c09175cd527bcb9d10d977f3a769e 100644 (file)
@@ -410,20 +410,21 @@ static void cyblafb_imageblit(struct fb_info *info,
        out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1));
 
        while(index < index_end) {
+               const char *p = image->data + index;
                for(i=0;i<width_dds;i++) {
-                       out32(GE9C,*((u32*) ((u32)image->data + index)));
+                       out32(GE9C,*(u32*)p);
+                       p+=4;
                        index+=4;
                }
                switch(width_dbs) {
                case 0: break;
-               case 8: out32(GE9C,*((u8*)((u32)image->data+index)));
+               case 8: out32(GE9C,*(u8*)p);
                        index+=1;
                        break;
-               case 16: out32(GE9C,*((u16*)((u32)image->data+index)));
+               case 16: out32(GE9C,*(u16*)p);
                        index+=2;
                        break;
-               case 24: out32(GE9C,(u32)(*((u16*)((u32)image->data+index))) |
-                              (u32)(*((u8*)((u32)image->data+index+2)))<<16);
+               case 24: out32(GE9C,*(u16*)p | *(u8*)(p+2)<<16);
                        index+=3;
                        break;
                }
index fda53aac1fc100c07b4d1e69d7a0c1a9388090fc..689d2586366d7ffafbdb7c55741580f6f858f277 100644 (file)
@@ -44,7 +44,7 @@ static void i810i2c_setscl(void *data, int state)
 {
         struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
         struct i810fb_par         *par = chan->par;
-       u8                        *mmio = par->mmio_start_virtual;
+       u8                        __iomem *mmio = par->mmio_start_virtual;
 
        i810_writel(mmio, GPIOB, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
                    SCL_DIR_MASK | SCL_VAL_MASK);
@@ -55,7 +55,7 @@ static void i810i2c_setsda(void *data, int state)
 {
         struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
         struct i810fb_par         *par = chan->par;
-       u8                        *mmio = par->mmio_start_virtual;
+       u8                        __iomem *mmio = par->mmio_start_virtual;
 
        i810_writel(mmio, GPIOB, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
                    SDA_DIR_MASK | SDA_VAL_MASK);
@@ -66,7 +66,7 @@ static int i810i2c_getscl(void *data)
 {
         struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
         struct i810fb_par         *par = chan->par;
-       u8                        *mmio = par->mmio_start_virtual;
+       u8                        __iomem *mmio = par->mmio_start_virtual;
 
        i810_writel(mmio, GPIOB, SCL_DIR_MASK);
        i810_writel(mmio, GPIOB, 0);
@@ -77,7 +77,7 @@ static int i810i2c_getsda(void *data)
 {
         struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
         struct i810fb_par         *par = chan->par;
-       u8                        *mmio = par->mmio_start_virtual;
+       u8                        __iomem *mmio = par->mmio_start_virtual;
 
        i810_writel(mmio, GPIOB, SDA_DIR_MASK);
        i810_writel(mmio, GPIOB, 0);
@@ -88,7 +88,7 @@ static void i810ddc_setscl(void *data, int state)
 {
         struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
         struct i810fb_par       *par = chan->par;
-       u8                      *mmio = par->mmio_start_virtual;
+       u8                      __iomem *mmio = par->mmio_start_virtual;
 
        i810_writel(mmio, GPIOA, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
                    SCL_DIR_MASK | SCL_VAL_MASK);
@@ -99,7 +99,7 @@ static void i810ddc_setsda(void *data, int state)
 {
         struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
         struct i810fb_par         *par = chan->par;
-       u8                      *mmio = par->mmio_start_virtual;
+       u8                      __iomem *mmio = par->mmio_start_virtual;
 
        i810_writel(mmio, GPIOA, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
                    SDA_DIR_MASK | SDA_VAL_MASK);
@@ -110,7 +110,7 @@ static int i810ddc_getscl(void *data)
 {
         struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
         struct i810fb_par         *par = chan->par;
-       u8                      *mmio = par->mmio_start_virtual;
+       u8                      __iomem *mmio = par->mmio_start_virtual;
 
        i810_writel(mmio, GPIOA, SCL_DIR_MASK);
        i810_writel(mmio, GPIOA, 0);
@@ -121,7 +121,7 @@ static int i810ddc_getsda(void *data)
 {
         struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
         struct i810fb_par         *par = chan->par;
-       u8                      *mmio = par->mmio_start_virtual;
+       u8                      __iomem *mmio = par->mmio_start_virtual;
 
        i810_writel(mmio, GPIOA, SDA_DIR_MASK);
        i810_writel(mmio, GPIOA, 0);
index 6c2244cf0e746156df2d4b574ef26703de16808e..1d54d3d6960b6f09be29a340794050a520d7f772 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <asm/hardware.h>
 #include <asm/io.h>
-#include <asm/mach-types.h>
 #include <asm/uaccess.h>
 #include <asm/arch/imxfb.h>
 
index bf62e6ed0382c9a0cabe0ba632288ff85d26f44a..80a09344f1aaedffd1e6e665dd26186fe70e84b4 100644 (file)
@@ -226,7 +226,7 @@ MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
 
 static int accel        = 1;
 static int vram         = 4;
-static int hwcursor     = 1;
+static int hwcursor     = 0;
 static int mtrr         = 1;
 static int fixed        = 0;
 static int noinit       = 0;
@@ -609,15 +609,9 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                dinfo->accel = 0;
        }
 
-       if (MB(voffset) < stolen_size)
-               offset = (stolen_size >> 12);
-       else
-               offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
-
        /* Framebuffer parameters - Use all the stolen memory if >= vram */
-       if (ROUND_UP_TO_PAGE(stolen_size) >= ((offset << 12) +  MB(vram))) {
+       if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) {
                dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);
-               dinfo->fb.offset = 0;
                dinfo->fbmem_gart = 0;
        } else {
                dinfo->fb.size =  MB(vram);
@@ -648,6 +642,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
+       if (MB(voffset) < stolen_size)
+               offset = (stolen_size >> 12);
+       else
+               offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
+
        /* set the mem offsets - set them after the already used pages */
        if (dinfo->accel) {
                dinfo->ring.offset = offset + gtt_info.current_memory;
@@ -662,10 +661,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                        + (dinfo->cursor.size >> 12);
        }
 
+       /* Allocate memories (which aren't stolen) */
        /* Map the fb and MMIO regions */
        /* ioremap only up to the end of used aperture */
        dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
-               (dinfo->aperture.physical, (dinfo->fb.offset << 12)
+               (dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12)
                 + dinfo->fb.size);
        if (!dinfo->aperture.virtual) {
                ERR_MSG("Cannot remap FB region.\n");
@@ -682,7 +682,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
-       /* Allocate memories (which aren't stolen) */
        if (dinfo->accel) {
                if (!(dinfo->gtt_ring_mem =
                      agp_allocate_memory(bridge, dinfo->ring.size >> 12,
@@ -1484,7 +1483,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 #endif
 
        if (!dinfo->hwcursor)
-               return -ENXIO;
+               return soft_cursor(info, cursor);
 
        intelfbhw_cursor_hide(dinfo);
 
index 34d4dcc0320ac9774e2c480e0d9c43e140ead5fe..194eed0a238c9a355dd030d1051de9cf37d7a2bc 100644 (file)
@@ -260,9 +260,9 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        }
 
 #ifdef CONFIG_CPU_FREQ
-       DPRINTK("dma period = %d ps, clock = %d kHz\n",
-               pxafb_display_dma_period(var),
-               get_clk_frequency_khz(0));
+       pr_debug("pxafb: dma period = %d ps, clock = %d kHz\n",
+                pxafb_display_dma_period(var),
+                get_clk_frequency_khz(0));
 #endif
 
        return 0;
@@ -270,7 +270,7 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 
 static inline void pxafb_set_truecolor(u_int is_true_color)
 {
-       DPRINTK("true_color = %d\n", is_true_color);
+       pr_debug("pxafb: true_color = %d\n", is_true_color);
        // do your machine-specific setup if needed
 }
 
@@ -284,7 +284,7 @@ static int pxafb_set_par(struct fb_info *info)
        struct fb_var_screeninfo *var = &info->var;
        unsigned long palette_mem_size;
 
-       DPRINTK("set_par\n");
+       pr_debug("pxafb: set_par\n");
 
        if (var->bits_per_pixel == 16)
                fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
@@ -308,7 +308,7 @@ static int pxafb_set_par(struct fb_info *info)
 
        palette_mem_size = fbi->palette_size * sizeof(u16);
 
-       DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
+       pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
 
        fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
        fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
@@ -369,7 +369,7 @@ static int pxafb_blank(int blank, struct fb_info *info)
        struct pxafb_info *fbi = (struct pxafb_info *)info;
        int i;
 
-       DPRINTK("pxafb_blank: blank=%d\n", blank);
+       pr_debug("pxafb: blank=%d\n", blank);
 
        switch (blank) {
        case FB_BLANK_POWERDOWN:
@@ -508,15 +508,15 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
        u_long flags;
        u_int lines_per_panel, pcd = get_pcd(var->pixclock);
 
-       DPRINTK("Configuring PXA LCD\n");
+       pr_debug("pxafb: Configuring PXA LCD\n");
 
-       DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n",
-               var->xres, var->hsync_len,
-               var->left_margin, var->right_margin);
-       DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n",
-               var->yres, var->vsync_len,
-               var->upper_margin, var->lower_margin);
-       DPRINTK("var: pixclock=%d pcd=%d\n", var->pixclock, pcd);
+       pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
+                var->xres, var->hsync_len,
+                var->left_margin, var->right_margin);
+       pr_debug("var: yres=%d vslen=%d um=%d bm=%d\n",
+                var->yres, var->vsync_len,
+                var->upper_margin, var->lower_margin);
+       pr_debug("var: pixclock=%d pcd=%d\n", var->pixclock, pcd);
 
 #if DEBUG_VAR
        if (var->xres < 16        || var->xres > 1024)
@@ -589,10 +589,10 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
        if (pcd)
                new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
 
-       DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
-       DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
-       DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
-       DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3);
+       pr_debug("nlccr0 = 0x%08x\n", new_regs.lccr0);
+       pr_debug("nlccr1 = 0x%08x\n", new_regs.lccr1);
+       pr_debug("nlccr2 = 0x%08x\n", new_regs.lccr2);
+       pr_debug("nlccr3 = 0x%08x\n", new_regs.lccr3);
 
        /* Update shadow copy atomically */
        local_irq_save(flags);
@@ -637,24 +637,24 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
        }
 
 #if 0
-       DPRINTK("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu);
-       DPRINTK("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu);
-       DPRINTK("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu);
-       DPRINTK("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma);
-       DPRINTK("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma);
-       DPRINTK("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma);
-
-       DPRINTK("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr);
-       DPRINTK("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr);
-       DPRINTK("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr);
-
-       DPRINTK("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr);
-       DPRINTK("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr);
-       DPRINTK("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr);
-
-       DPRINTK("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd);
-       DPRINTK("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd);
-       DPRINTK("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd);
+       pr_debug("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu);
+       pr_debug("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu);
+       pr_debug("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu);
+       pr_debug("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma);
+       pr_debug("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma);
+       pr_debug("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma);
+
+       pr_debug("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr);
+       pr_debug("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr);
+       pr_debug("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr);
+
+       pr_debug("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr);
+       pr_debug("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr);
+       pr_debug("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr);
+
+       pr_debug("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd);
+       pr_debug("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd);
+       pr_debug("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd);
 #endif
 
        fbi->reg_lccr0 = new_regs.lccr0;
@@ -684,7 +684,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
  */
 static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on)
 {
-       DPRINTK("backlight o%s\n", on ? "n" : "ff");
+       pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff");
 
        if (pxafb_backlight_power)
                pxafb_backlight_power(on);
@@ -692,7 +692,7 @@ static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on)
 
 static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
 {
-       DPRINTK("LCD power o%s\n", on ? "n" : "ff");
+       pr_debug("pxafb: LCD power o%s\n", on ? "n" : "ff");
 
        if (pxafb_lcd_power)
                pxafb_lcd_power(on);
@@ -740,13 +740,13 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
 
 static void pxafb_enable_controller(struct pxafb_info *fbi)
 {
-       DPRINTK("Enabling LCD controller\n");
-       DPRINTK("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0);
-       DPRINTK("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1);
-       DPRINTK("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0);
-       DPRINTK("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1);
-       DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
-       DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
+       pr_debug("pxafb: Enabling LCD controller\n");
+       pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0);
+       pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1);
+       pr_debug("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0);
+       pr_debug("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1);
+       pr_debug("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
+       pr_debug("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
 
        /* enable LCD controller clock */
        pxa_set_cken(CKEN16_LCD, 1);
@@ -761,19 +761,19 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
        FDADR1 = fbi->fdadr1;
        LCCR0 |= LCCR0_ENB;
 
-       DPRINTK("FDADR0 0x%08x\n", (unsigned int) FDADR0);
-       DPRINTK("FDADR1 0x%08x\n", (unsigned int) FDADR1);
-       DPRINTK("LCCR0 0x%08x\n", (unsigned int) LCCR0);
-       DPRINTK("LCCR1 0x%08x\n", (unsigned int) LCCR1);
-       DPRINTK("LCCR2 0x%08x\n", (unsigned int) LCCR2);
-       DPRINTK("LCCR3 0x%08x\n", (unsigned int) LCCR3);
+       pr_debug("FDADR0 0x%08x\n", (unsigned int) FDADR0);
+       pr_debug("FDADR1 0x%08x\n", (unsigned int) FDADR1);
+       pr_debug("LCCR0 0x%08x\n", (unsigned int) LCCR0);
+       pr_debug("LCCR1 0x%08x\n", (unsigned int) LCCR1);
+       pr_debug("LCCR2 0x%08x\n", (unsigned int) LCCR2);
+       pr_debug("LCCR3 0x%08x\n", (unsigned int) LCCR3);
 }
 
 static void pxafb_disable_controller(struct pxafb_info *fbi)
 {
        DECLARE_WAITQUEUE(wait, current);
 
-       DPRINTK("Disabling LCD controller\n");
+       pr_debug("pxafb: disabling LCD controller\n");
 
        set_current_state(TASK_UNINTERRUPTIBLE);
        add_wait_queue(&fbi->ctrlr_wait, &wait);
@@ -1039,7 +1039,7 @@ static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
                fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;
 
                palette_mem_size = fbi->palette_size * sizeof(u16);
-               DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
+               pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
 
                fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
                fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
index 22c00be786a8e28e12327051ae6473bb81eb4c47..47f41f70db7a042c821ddc65832529487364f26b 100644 (file)
@@ -113,15 +113,6 @@ struct pxafb_info {
 
 #define PXA_NAME       "PXA"
 
-/*
- *  Debug macros
- */
-#if DEBUG
-#  define DPRINTK(fmt, args...)        printk("%s: " fmt, __FUNCTION__ , ## args)
-#else
-#  define DPRINTK(fmt, args...)
-#endif
-
 /*
  * Minimum X and Y resolutions
  */
index 00c0223a352ea861b7318d9a81af2f3a0c09f406..5ab79afb53b78bdce439488c1fa53ce457290471 100644 (file)
@@ -228,8 +228,8 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
  * information
 */
 
-static int s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
-                                 struct fb_var_screeninfo *var)
+static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
+                                  struct fb_var_screeninfo *var)
 {
        fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
 
index 821c9c4d76aa064698025e4c5444894b7dc8e39f..d95f8626d1702e918e4d8b415e0de3afbed6afb9 100644 (file)
@@ -71,21 +71,28 @@ static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
  *
  */
 
-struct v9fs_fid *v9fs_fid_create(struct dentry *dentry)
+struct v9fs_fid *v9fs_fid_create(struct dentry *dentry,
+       struct v9fs_session_info *v9ses, int fid, int create)
 {
        struct v9fs_fid *new;
 
+       dprintk(DEBUG_9P, "fid create dentry %p, fid %d, create %d\n",
+               dentry, fid, create);
+
        new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
        if (new == NULL) {
                dprintk(DEBUG_ERROR, "Out of Memory\n");
                return ERR_PTR(-ENOMEM);
        }
 
-       new->fid = -1;
+       new->fid = fid;
+       new->v9ses = v9ses;
        new->fidopen = 0;
-       new->fidcreate = 0;
+       new->fidcreate = create;
        new->fidclunked = 0;
        new->iounit = 0;
+       new->rdir_pos = 0;
+       new->rdir_fcall = NULL;
 
        if (v9fs_fid_insert(new, dentry) == 0)
                return new;
@@ -108,6 +115,59 @@ void v9fs_fid_destroy(struct v9fs_fid *fid)
        kfree(fid);
 }
 
+/**
+ * v9fs_fid_walk_up - walks from the process current directory
+ *     up to the specified dentry.
+ */
+static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry)
+{
+       int fidnum, cfidnum, err;
+       struct v9fs_fid *cfid;
+       struct dentry *cde;
+       struct v9fs_session_info *v9ses;
+
+       v9ses = v9fs_inode2v9ses(current->fs->pwd->d_inode);
+       cfid = v9fs_fid_lookup(current->fs->pwd);
+       if (cfid == NULL) {
+               dprintk(DEBUG_ERROR, "process cwd doesn't have a fid\n");
+               return ERR_PTR(-ENOENT);
+       }
+
+       cfidnum = cfid->fid;
+       cde = current->fs->pwd;
+       /* TODO: take advantage of multiwalk */
+
+       fidnum = v9fs_get_idpool(&v9ses->fidpool);
+       if (fidnum < 0) {
+               dprintk(DEBUG_ERROR, "could not get a new fid num\n");
+               err = -ENOENT;
+               goto clunk_fid;
+       }
+
+       while (cde != dentry) {
+               if (cde == cde->d_parent) {
+                       dprintk(DEBUG_ERROR, "can't find dentry\n");
+                       err = -ENOENT;
+                       goto clunk_fid;
+               }
+
+               err = v9fs_t_walk(v9ses, cfidnum, fidnum, "..", NULL);
+               if (err < 0) {
+                       dprintk(DEBUG_ERROR, "problem walking to parent\n");
+                       goto clunk_fid;
+               }
+
+               cfidnum = fidnum;
+               cde = cde->d_parent;
+       }
+
+       return v9fs_fid_create(dentry, v9ses, fidnum, 0);
+
+clunk_fid:
+       v9fs_t_clunk(v9ses, fidnum, NULL);
+       return ERR_PTR(err);
+}
+
 /**
  * v9fs_fid_lookup - retrieve the right fid from a  particular dentry
  * @dentry: dentry to look for fid in
@@ -119,49 +179,25 @@ void v9fs_fid_destroy(struct v9fs_fid *fid)
  *
  */
 
-struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type)
+struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
 {
        struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
        struct v9fs_fid *current_fid = NULL;
        struct v9fs_fid *temp = NULL;
        struct v9fs_fid *return_fid = NULL;
-       int found_parent = 0;
-       int found_user = 0;
 
-       dprintk(DEBUG_9P, " dentry: %s (%p) type %d\n", dentry->d_iname, dentry,
-               type);
+       dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry);
 
-       if (fid_list && !list_empty(fid_list)) {
+       if (fid_list) {
                list_for_each_entry_safe(current_fid, temp, fid_list, list) {
-                       if (current_fid->uid == current->uid) {
-                               if (return_fid == NULL) {
-                                       if ((type == FID_OP)
-                                           || (!current_fid->fidopen)) {
-                                               return_fid = current_fid;
-                                               found_user = 1;
-                                       }
-                               }
-                       }
-                       if (current_fid->pid == current->real_parent->pid) {
-                               if ((return_fid == NULL) || (found_parent)
-                                   || (found_user)) {
-                                       if ((type == FID_OP)
-                                           || (!current_fid->fidopen)) {
-                                               return_fid = current_fid;
-                                               found_parent = 1;
-                                               found_user = 0;
-                                       }
-                               }
-                       }
-                       if (current_fid->pid == current->pid) {
-                               if ((type == FID_OP) ||
-                                   (!current_fid->fidopen)) {
-                                       return_fid = current_fid;
-                                       found_parent = 0;
-                                       found_user = 0;
-                               }
+                       if (!current_fid->fidcreate) {
+                               return_fid = current_fid;
+                               break;
                        }
                }
+
+               if (!return_fid)
+                       return_fid = current_fid;
        }
 
        /* we are at the root but didn't match */
@@ -187,55 +223,33 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type)
 
 /* XXX - there may be some duplication we can get rid of */
                if (par == dentry) {
-                       /* we need to fid_lookup the starting point */
-                       int fidnum = -1;
-                       int oldfid = -1;
-                       int result = -1;
-                       struct v9fs_session_info *v9ses =
-                           v9fs_inode2v9ses(current->fs->pwd->d_inode);
-
-                       current_fid =
-                           v9fs_fid_lookup(current->fs->pwd, FID_WALK);
-                       if (current_fid == NULL) {
-                               dprintk(DEBUG_ERROR,
-                                       "process cwd doesn't have a fid\n");
-                               return return_fid;
-                       }
-                       oldfid = current_fid->fid;
-                       par = current->fs->pwd;
-                       /* TODO: take advantage of multiwalk */
+                       return_fid = v9fs_fid_walk_up(dentry);
+                       if (IS_ERR(return_fid))
+                               return_fid = NULL;
+               }
+       }
 
-                       fidnum = v9fs_get_idpool(&v9ses->fidpool);
-                       if (fidnum < 0) {
-                               dprintk(DEBUG_ERROR,
-                                       "could not get a new fid num\n");
-                               return return_fid;
-                       }
+       return return_fid;
+}
 
-                       while (par != dentry) {
-                               result =
-                                   v9fs_t_walk(v9ses, oldfid, fidnum, "..",
-                                               NULL);
-                               if (result < 0) {
-                                       dprintk(DEBUG_ERROR,
-                                               "problem walking to parent\n");
-
-                                       break;
-                               }
-                               oldfid = fidnum;
-                               if (par == par->d_parent) {
-                                       dprintk(DEBUG_ERROR,
-                                               "can't find dentry\n");
-                                       break;
-                               }
-                               par = par->d_parent;
-                       }
-                       if (par == dentry) {
-                               return_fid = v9fs_fid_create(dentry);
-                               return_fid->fid = fidnum;
+struct v9fs_fid *v9fs_fid_get_created(struct dentry *dentry)
+{
+       struct list_head *fid_list;
+       struct v9fs_fid *fid, *ftmp, *ret;
+
+       dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+       fid_list = (struct list_head *)dentry->d_fsdata;
+       ret = NULL;
+       if (fid_list) {
+               list_for_each_entry_safe(fid, ftmp, fid_list, list) {
+                       if (fid->fidcreate && fid->pid == current->pid) {
+                               list_del(&fid->list);
+                               ret = fid;
+                               break;
                        }
                }
        }
 
-       return return_fid;
+       dprintk(DEBUG_9P, "return %p\n", ret);
+       return ret;
 }
index 7db478ccca365911e3e3fc4b354613313e99eb7f..84c673a44c831a3a1ec977e26b1a65d2aed82506 100644 (file)
@@ -25,6 +25,7 @@
 
 #define FID_OP   0
 #define FID_WALK 1
+#define FID_CREATE 2
 
 struct v9fs_fid {
        struct list_head list;   /* list of fids associated with a dentry */
@@ -52,6 +53,8 @@ struct v9fs_fid {
        struct v9fs_session_info *v9ses;        /* session info for this FID */
 };
 
-struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type);
+struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry);
+struct v9fs_fid *v9fs_fid_get_created(struct dentry *);
 void v9fs_fid_destroy(struct v9fs_fid *fid);
-struct v9fs_fid *v9fs_fid_create(struct dentry *);
+struct v9fs_fid *v9fs_fid_create(struct dentry *,
+       struct v9fs_session_info *v9ses, int fid, int create);
index 306c96741f8193ad153d8dd864c54ceff6b2297a..a6aa947de0f9b7e0c44b4eda3f6df531b2e112bb 100644 (file)
@@ -67,7 +67,7 @@ static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd)
        struct dentry *dc = current->fs->pwd;
 
        dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry);
-       if (v9fs_fid_lookup(dentry, FID_OP)) {
+       if (v9fs_fid_lookup(dentry)) {
                dprintk(DEBUG_VFS, "VALID\n");
                return 1;
        }
index c478a73841863c5f0e6fec75e86359f1aa7c08ea..57a43b8feef56e9f257434129edcb9b72a07016b 100644 (file)
@@ -197,21 +197,18 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
        filemap_fdatawait(inode->i_mapping);
 
        if (fidnum >= 0) {
-               fid->fidopen--;
                dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen,
                        fid->fid);
 
-               if (fid->fidopen == 0) {
-                       if (v9fs_t_clunk(v9ses, fidnum, NULL))
-                               dprintk(DEBUG_ERROR, "clunk failed\n");
+               if (v9fs_t_clunk(v9ses, fidnum, NULL))
+                       dprintk(DEBUG_ERROR, "clunk failed\n");
 
-                       v9fs_put_idpool(fid->fid, &v9ses->fidpool);
-               }
+               v9fs_put_idpool(fid->fid, &v9ses->fidpool);
 
                kfree(fid->rdir_fcall);
+               kfree(fid);
 
                filp->private_data = NULL;
-               v9fs_fid_destroy(fid);
        }
 
        d_drop(filp->f_dentry);
index 1f8ae7d580abea733ecffd334403d400ed8f640d..a4799e971d1c0cfc37c5464601aaff7e56fcb218 100644 (file)
 int v9fs_file_open(struct inode *inode, struct file *file)
 {
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
-       struct v9fs_fid *v9fid = v9fs_fid_lookup(file->f_dentry, FID_WALK);
-       struct v9fs_fid *v9newfid = NULL;
+       struct v9fs_fid *v9fid, *fid;
        struct v9fs_fcall *fcall = NULL;
        int open_mode = 0;
        unsigned int iounit = 0;
        int newfid = -1;
        long result = -1;
 
-       dprintk(DEBUG_VFS, "inode: %p file: %p v9fid= %p\n", inode, file,
-               v9fid);
+       dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file);
+
+       v9fid = v9fs_fid_get_created(file->f_dentry);
+       if (!v9fid)
+               v9fid = v9fs_fid_lookup(file->f_dentry);
 
        if (!v9fid) {
-               struct dentry *dentry = file->f_dentry;
                dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n");
+               return -EBADF;
+       }
 
-               /* XXX - some duplication from lookup, generalize later */
-               /* basically vfs_lookup is too heavy weight */
-               v9fid = v9fs_fid_lookup(file->f_dentry, FID_OP);
-               if (!v9fid)
-                       return -EBADF;
+       if (!v9fid->fidcreate) {
+               fid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
+               if (fid == NULL) {
+                       dprintk(DEBUG_ERROR, "Out of Memory\n");
+                       return -ENOMEM;
+               }
 
-               v9fid = v9fs_fid_lookup(dentry->d_parent, FID_WALK);
-               if (!v9fid)
-                       return -EBADF;
+               fid->fidopen = 0;
+               fid->fidcreate = 0;
+               fid->fidclunked = 0;
+               fid->iounit = 0;
+               fid->v9ses = v9ses;
 
                newfid = v9fs_get_idpool(&v9ses->fidpool);
                if (newfid < 0) {
@@ -85,58 +91,16 @@ int v9fs_file_open(struct inode *inode, struct file *file)
                }
 
                result =
-                   v9fs_t_walk(v9ses, v9fid->fid, newfid,
-                               (char *)file->f_dentry->d_name.name, NULL);
+                   v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, NULL);
+
                if (result < 0) {
                        v9fs_put_idpool(newfid, &v9ses->fidpool);
                        dprintk(DEBUG_ERROR, "rewalk didn't work\n");
                        return -EBADF;
                }
 
-               v9fid = v9fs_fid_create(dentry);
-               if (v9fid == NULL) {
-                       dprintk(DEBUG_ERROR, "couldn't insert\n");
-                       return -ENOMEM;
-               }
-               v9fid->fid = newfid;
-       }
-
-       if (v9fid->fidcreate) {
-               /* create case */
-               newfid = v9fid->fid;
-               iounit = v9fid->iounit;
-               v9fid->fidcreate = 0;
-       } else {
-               if (!S_ISDIR(inode->i_mode))
-                       newfid = v9fid->fid;
-               else {
-                       newfid = v9fs_get_idpool(&v9ses->fidpool);
-                       if (newfid < 0) {
-                               eprintk(KERN_WARNING, "allocation failed\n");
-                               return -ENOSPC;
-                       }
-                       /* This would be a somewhat critical clone */
-                       result =
-                           v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL,
-                                       &fcall);
-                       if (result < 0) {
-                               dprintk(DEBUG_ERROR, "clone error: %s\n",
-                                       FCALL_ERROR(fcall));
-                               kfree(fcall);
-                               return result;
-                       }
-
-                       v9newfid = v9fs_fid_create(file->f_dentry);
-                       v9newfid->fid = newfid;
-                       v9newfid->qid = v9fid->qid;
-                       v9newfid->iounit = v9fid->iounit;
-                       v9newfid->fidopen = 0;
-                       v9newfid->fidclunked = 0;
-                       v9newfid->v9ses = v9ses;
-                       v9fid = v9newfid;
-                       kfree(fcall);
-               }
-
+               fid->fid = newfid;
+               v9fid = fid;
                /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
                /* translate open mode appropriately */
                open_mode = file->f_flags & 0x3;
@@ -163,9 +127,13 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 
                iounit = fcall->params.ropen.iounit;
                kfree(fcall);
+       } else {
+               /* create case */
+               newfid = v9fid->fid;
+               iounit = v9fid->iounit;
+               v9fid->fidcreate = 0;
        }
 
-
        file->private_data = v9fid;
 
        v9fid->rdir_pos = 0;
index b16322db5ce6bace424d5a2fa6242636fbe4f221..2b696ae6655a10306f5111c90f14a5af645c9220 100644 (file)
@@ -307,7 +307,7 @@ v9fs_create(struct inode *dir,
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
        struct super_block *sb = dir->i_sb;
        struct v9fs_fid *dirfid =
-           v9fs_fid_lookup(file_dentry->d_parent, FID_WALK);
+           v9fs_fid_lookup(file_dentry->d_parent);
        struct v9fs_fid *fid = NULL;
        struct inode *file_inode = NULL;
        struct v9fs_fcall *fcall = NULL;
@@ -317,6 +317,7 @@ v9fs_create(struct inode *dir,
        long newfid = -1;
        int result = 0;
        unsigned int iounit = 0;
+       int wfidno = -1;
 
        perm = unixmode2p9mode(v9ses, perm);
 
@@ -350,7 +351,7 @@ v9fs_create(struct inode *dir,
        if (result < 0) {
                dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall));
                v9fs_put_idpool(newfid, &v9ses->fidpool);
-               newfid = 0;
+               newfid = -1;
                goto CleanUpFid;
        }
 
@@ -369,20 +370,39 @@ v9fs_create(struct inode *dir,
        qid = fcall->params.rcreate.qid;
        kfree(fcall);
 
-       fid = v9fs_fid_create(file_dentry);
+       fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1);
+       dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate);
        if (!fid) {
                result = -ENOMEM;
                goto CleanUpFid;
        }
 
-       fid->fid = newfid;
-       fid->fidopen = 0;
-       fid->fidcreate = 1;
        fid->qid = qid;
        fid->iounit = iounit;
-       fid->rdir_pos = 0;
-       fid->rdir_fcall = NULL;
-       fid->v9ses = v9ses;
+
+       /* walk to the newly created file and put the fid in the dentry */
+       wfidno = v9fs_get_idpool(&v9ses->fidpool);
+       if (newfid < 0) {
+               eprintk(KERN_WARNING, "no free fids available\n");
+               return -ENOSPC;
+       }
+
+       result = v9fs_t_walk(v9ses, dirfidnum, wfidno,
+               (char *) file_dentry->d_name.name, NULL);
+       if (result < 0) {
+               dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall));
+               v9fs_put_idpool(wfidno, &v9ses->fidpool);
+               wfidno = -1;
+               goto CleanUpFid;
+       }
+
+       if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) {
+               if (!v9fs_t_clunk(v9ses, newfid, &fcall)) {
+                       v9fs_put_idpool(wfidno, &v9ses->fidpool);
+               }
+
+               goto CleanUpFid;
+       }
 
        if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) ||
            (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) ||
@@ -410,11 +430,11 @@ v9fs_create(struct inode *dir,
        d_instantiate(file_dentry, file_inode);
 
        if (perm & V9FS_DMDIR) {
-               if (v9fs_t_clunk(v9ses, newfid, &fcall))
+               if (!v9fs_t_clunk(v9ses, newfid, &fcall))
+                       v9fs_put_idpool(newfid, &v9ses->fidpool);
+               else
                        dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n",
                                FCALL_ERROR(fcall));
-
-               v9fs_put_idpool(newfid, &v9ses->fidpool);
                kfree(fcall);
                fid->fidopen = 0;
                fid->fidcreate = 0;
@@ -426,12 +446,22 @@ v9fs_create(struct inode *dir,
       CleanUpFid:
        kfree(fcall);
 
-       if (newfid) {
-               if (v9fs_t_clunk(v9ses, newfid, &fcall))
+       if (newfid >= 0) {
+               if (!v9fs_t_clunk(v9ses, newfid, &fcall))
+                       v9fs_put_idpool(newfid, &v9ses->fidpool);
+               else
+                       dprintk(DEBUG_ERROR, "clunk failed: %s\n",
+                               FCALL_ERROR(fcall));
+
+               kfree(fcall);
+       }
+       if (wfidno >= 0) {
+               if (!v9fs_t_clunk(v9ses, wfidno, &fcall))
+                       v9fs_put_idpool(wfidno, &v9ses->fidpool);
+               else
                        dprintk(DEBUG_ERROR, "clunk failed: %s\n",
                                FCALL_ERROR(fcall));
 
-               v9fs_put_idpool(newfid, &v9ses->fidpool);
                kfree(fcall);
        }
        return result;
@@ -461,7 +491,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
        file_inode = file->d_inode;
        sb = file_inode->i_sb;
        v9ses = v9fs_inode2v9ses(file_inode);
-       v9fid = v9fs_fid_lookup(file, FID_OP);
+       v9fid = v9fs_fid_lookup(file);
 
        if (!v9fid) {
                dprintk(DEBUG_ERROR,
@@ -545,7 +575,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 
        sb = dir->i_sb;
        v9ses = v9fs_inode2v9ses(dir);
-       dirfid = v9fs_fid_lookup(dentry->d_parent, FID_WALK);
+       dirfid = v9fs_fid_lookup(dentry->d_parent);
 
        if (!dirfid) {
                dprintk(DEBUG_ERROR, "no dirfid\n");
@@ -573,7 +603,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
                v9fs_put_idpool(newfid, &v9ses->fidpool);
                if (result == -ENOENT) {
                        d_add(dentry, NULL);
-                       dprintk(DEBUG_ERROR,
+                       dprintk(DEBUG_VFS,
                                "Return negative dentry %p count %d\n",
                                dentry, atomic_read(&dentry->d_count));
                        return NULL;
@@ -601,16 +631,13 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 
        inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid);
 
-       fid = v9fs_fid_create(dentry);
+       fid = v9fs_fid_create(dentry, v9ses, newfid, 0);
        if (fid == NULL) {
                dprintk(DEBUG_ERROR, "couldn't insert\n");
                result = -ENOMEM;
                goto FreeFcall;
        }
 
-       fid->fid = newfid;
-       fid->fidopen = 0;
-       fid->v9ses = v9ses;
        fid->qid = fcall->params.rstat.stat->qid;
 
        dentry->d_op = &v9fs_dentry_operations;
@@ -665,11 +692,11 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 {
        struct inode *old_inode = old_dentry->d_inode;
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode);
-       struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_WALK);
+       struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry);
        struct v9fs_fid *olddirfid =
-           v9fs_fid_lookup(old_dentry->d_parent, FID_WALK);
+           v9fs_fid_lookup(old_dentry->d_parent);
        struct v9fs_fid *newdirfid =
-           v9fs_fid_lookup(new_dentry->d_parent, FID_WALK);
+           v9fs_fid_lookup(new_dentry->d_parent);
        struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
        struct v9fs_fcall *fcall = NULL;
        int fid = -1;
@@ -744,7 +771,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 {
        struct v9fs_fcall *fcall = NULL;
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
-       struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP);
+       struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
        int err = -EPERM;
 
        dprintk(DEBUG_VFS, "dentry: %p\n", dentry);
@@ -778,7 +805,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
 {
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
-       struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP);
+       struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
        struct v9fs_fcall *fcall = NULL;
        struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
        int res = -EPERM;
@@ -960,7 +987,7 @@ v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        if (retval != 0)
                goto FreeFcall;
 
-       newfid = v9fs_fid_lookup(dentry, FID_OP);
+       newfid = v9fs_fid_lookup(dentry);
 
        /* issue a twstat */
        v9fs_blank_mistat(v9ses, mistat);
@@ -1004,7 +1031,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
 
        struct v9fs_fcall *fcall = NULL;
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
-       struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP);
+       struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
 
        if (!fid) {
                dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n");
@@ -1148,7 +1175,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
        struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
        struct v9fs_fcall *fcall = NULL;
        struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
-       struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_OP);
+       struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry);
        struct v9fs_fid *newfid = NULL;
        char *symname = __getname();
 
@@ -1168,7 +1195,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
        if (retval != 0)
                goto FreeMem;
 
-       newfid = v9fs_fid_lookup(dentry, FID_OP);
+       newfid = v9fs_fid_lookup(dentry);
        if (!newfid) {
                dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n");
                goto FreeMem;
@@ -1246,7 +1273,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
        if (retval != 0)
                goto FreeMem;
 
-       newfid = v9fs_fid_lookup(dentry, FID_OP);
+       newfid = v9fs_fid_lookup(dentry);
        if (!newfid) {
                dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n");
                retval = -EINVAL;
index 1e2b2b54d300645e3f1a85fed6df339b4eb09089..82c5b00840796d5f82bd6810a92f783b11e953d1 100644 (file)
@@ -129,7 +129,6 @@ static struct super_block *v9fs_get_sb(struct file_system_type
 
        if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
                dprintk(DEBUG_ERROR, "problem initiating session\n");
-               kfree(v9ses);
                return ERR_PTR(newfid);
        }
 
@@ -155,23 +154,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type
 
        sb->s_root = root;
 
-       /* Setup the Root Inode */
-       root_fid = v9fs_fid_create(root);
-       if (root_fid == NULL) {
-               retval = -ENOMEM;
-               goto put_back_sb;
-       }
-
-       root_fid->fidopen = 0;
-       root_fid->v9ses = v9ses;
-
        stat_result = v9fs_t_stat(v9ses, newfid, &fcall);
        if (stat_result < 0) {
                dprintk(DEBUG_ERROR, "stat error\n");
                v9fs_t_clunk(v9ses, newfid, NULL);
                v9fs_put_idpool(newfid, &v9ses->fidpool);
        } else {
-               root_fid->fid = newfid;
+               /* Setup the Root Inode */
+               root_fid = v9fs_fid_create(root, v9ses, newfid, 0);
+               if (root_fid == NULL) {
+                       retval = -ENOMEM;
+                       goto put_back_sb;
+               }
+
                root_fid->qid = fcall->params.rstat.stat->qid;
                root->d_inode->i_ino =
                    v9fs_qid2ino(&fcall->params.rstat.stat->qid);
index 068ccea2f184b5beadb2add2a59a86305e0487d3..48f5422cb19a942e017aad4e334195d53ab83595 100644 (file)
@@ -472,6 +472,9 @@ config FUSE_FS
          utilities is available from the FUSE homepage:
          <http://fuse.sourceforge.net/>
 
+         See <file:Documentation/filesystems/fuse.txt> for more information.
+         See <file:Documentation/Changes> for needed library/utility version.
+
          If you want to develop a userspace FS, or if you want to use
          a filesystem based on FUSE, answer Y or M.
 
index 0e11e31dbb77147078b79eaad3fc97c70b79321d..d6b1551342b7206bff66323d60c6a8126bcaf813 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -741,19 +741,9 @@ static ssize_t aio_run_iocb(struct kiocb *iocb)
        ret = retry(iocb);
        current->io_wait = NULL;
 
-       if (-EIOCBRETRY != ret) {
-               if (-EIOCBQUEUED != ret) {
-                       BUG_ON(!list_empty(&iocb->ki_wait.task_list));
-                       aio_complete(iocb, ret, 0);
-                       /* must not access the iocb after this */
-               }
-       } else {
-               /*
-                * Issue an additional retry to avoid waiting forever if
-                * no waits were queued (e.g. in case of a short read).
-                */
-               if (list_empty(&iocb->ki_wait.task_list))
-                       kiocbSetKicked(iocb);
+       if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) {
+               BUG_ON(!list_empty(&iocb->ki_wait.task_list));
+               aio_complete(iocb, ret, 0);
        }
 out:
        spin_lock_irq(&ctx->ctx_lock);
@@ -899,16 +889,24 @@ static void aio_kick_handler(void *data)
  * and if required activate the aio work queue to process
  * it
  */
-static void queue_kicked_iocb(struct kiocb *iocb)
+static void try_queue_kicked_iocb(struct kiocb *iocb)
 {
        struct kioctx   *ctx = iocb->ki_ctx;
        unsigned long flags;
        int run = 0;
 
-       WARN_ON((!list_empty(&iocb->ki_wait.task_list)));
+       /* We're supposed to be the only path putting the iocb back on the run
+        * list.  If we find that the iocb is *back* on a wait queue already
+        * than retry has happened before we could queue the iocb.  This also
+        * means that the retry could have completed and freed our iocb, no
+        * good. */
+       BUG_ON((!list_empty(&iocb->ki_wait.task_list)));
 
        spin_lock_irqsave(&ctx->ctx_lock, flags);
-       run = __queue_kicked_iocb(iocb);
+       /* set this inside the lock so that we can't race with aio_run_iocb()
+        * testing it and putting the iocb on the run list under the lock */
+       if (!kiocbTryKick(iocb))
+               run = __queue_kicked_iocb(iocb);
        spin_unlock_irqrestore(&ctx->ctx_lock, flags);
        if (run)
                aio_queue_work(ctx);
@@ -931,10 +929,7 @@ void fastcall kick_iocb(struct kiocb *iocb)
                return;
        }
 
-       /* If its already kicked we shouldn't queue it again */
-       if (!kiocbTryKick(iocb)) {
-               queue_kicked_iocb(iocb);
-       }
+       try_queue_kicked_iocb(iocb);
 }
 EXPORT_SYMBOL(kick_iocb);
 
@@ -1322,8 +1317,11 @@ asmlinkage long sys_io_destroy(aio_context_t ctx)
 }
 
 /*
- * Default retry method for aio_read (also used for first time submit)
- * Responsible for updating iocb state as retries progress
+ * aio_p{read,write} are the default  ki_retry methods for
+ * IO_CMD_P{READ,WRITE}.  They maintains kiocb retry state around potentially
+ * multiple calls to f_op->aio_read().  They loop around partial progress
+ * instead of returning -EIOCBRETRY because they don't have the means to call
+ * kick_iocb().
  */
 static ssize_t aio_pread(struct kiocb *iocb)
 {
@@ -1332,25 +1330,25 @@ static ssize_t aio_pread(struct kiocb *iocb)
        struct inode *inode = mapping->host;
        ssize_t ret = 0;
 
-       ret = file->f_op->aio_read(iocb, iocb->ki_buf,
-               iocb->ki_left, iocb->ki_pos);
+       do {
+               ret = file->f_op->aio_read(iocb, iocb->ki_buf,
+                       iocb->ki_left, iocb->ki_pos);
+               /*
+                * Can't just depend on iocb->ki_left to determine
+                * whether we are done. This may have been a short read.
+                */
+               if (ret > 0) {
+                       iocb->ki_buf += ret;
+                       iocb->ki_left -= ret;
+               }
 
-       /*
-        * Can't just depend on iocb->ki_left to determine
-        * whether we are done. This may have been a short read.
-        */
-       if (ret > 0) {
-               iocb->ki_buf += ret;
-               iocb->ki_left -= ret;
                /*
-                * For pipes and sockets we return once we have
-                * some data; for regular files we retry till we
-                * complete the entire read or find that we can't
-                * read any more data (e.g short reads).
+                * For pipes and sockets we return once we have some data; for
+                * regular files we retry till we complete the entire read or
+                * find that we can't read any more data (e.g short reads).
                 */
-               if (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode))
-                       ret = -EIOCBRETRY;
-       }
+       } while (ret > 0 && iocb->ki_left > 0 &&
+                !S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode));
 
        /* This means we must have transferred all that we could */
        /* No need to retry anymore */
@@ -1360,27 +1358,21 @@ static ssize_t aio_pread(struct kiocb *iocb)
        return ret;
 }
 
-/*
- * Default retry method for aio_write (also used for first time submit)
- * Responsible for updating iocb state as retries progress
- */
+/* see aio_pread() */
 static ssize_t aio_pwrite(struct kiocb *iocb)
 {
        struct file *file = iocb->ki_filp;
        ssize_t ret = 0;
 
-       ret = file->f_op->aio_write(iocb, iocb->ki_buf,
-               iocb->ki_left, iocb->ki_pos);
-
-       if (ret > 0) {
-               iocb->ki_buf += ret;
-               iocb->ki_left -= ret;
-
-               ret = -EIOCBRETRY;
-       }
+       do {
+               ret = file->f_op->aio_write(iocb, iocb->ki_buf,
+                       iocb->ki_left, iocb->ki_pos);
+               if (ret > 0) {
+                       iocb->ki_buf += ret;
+                       iocb->ki_left -= ret;
+               }
+       } while (ret > 0 && iocb->ki_left > 0);
 
-       /* This means we must have transferred all that we could */
-       /* No need to retry anymore */
        if ((ret == 0) || (iocb->ki_left == 0))
                ret = iocb->ki_nbytes - iocb->ki_left;
 
index 403b90a1213dc54757882c26434520147c2024ae..4284cd31eba6dcb6f125f1fd574aa2213439b45f 100644 (file)
 /* Maximum number of poll wake up nests we are allowing */
 #define EP_MAX_POLLWAKE_NESTS 4
 
+/* Maximum msec timeout value storeable in a long int */
+#define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ)
+
+
 struct epoll_filefd {
        struct file *file;
        int fd;
@@ -1506,8 +1510,8 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
         * and the overflow condition. The passed timeout is in milliseconds,
         * that why (t * HZ) / 1000.
         */
-       jtimeout = timeout == -1 || timeout > (MAX_SCHEDULE_TIMEOUT - 1000) / HZ ?
-               MAX_SCHEDULE_TIMEOUT: (timeout * HZ + 999) / 1000;
+       jtimeout = (timeout < 0 || timeout >= EP_MAX_MSTIMEO) ?
+               MAX_SCHEDULE_TIMEOUT : (timeout * HZ + 999) / 1000;
 
 retry:
        write_lock_irqsave(&ep->lock, flags);
index c8d07030c89725c8b4451287b867a4ba637065a3..e2d6208633a737eea56ea50083c8f1e4c3559695 100644 (file)
@@ -605,27 +605,28 @@ got:
        insert_inode_hash(inode);
 
        if (DQUOT_ALLOC_INODE(inode)) {
-               DQUOT_DROP(inode);
                err = -ENOSPC;
-               goto fail2;
+               goto fail_drop;
        }
+
        err = ext2_init_acl(inode, dir);
-       if (err) {
-               DQUOT_FREE_INODE(inode);
-               DQUOT_DROP(inode);
-               goto fail2;
-       }
+       if (err)
+               goto fail_free_drop;
+
        err = ext2_init_security(inode,dir);
-       if (err) {
-               DQUOT_FREE_INODE(inode);
-               goto fail2;
-       }
+       if (err)
+               goto fail_free_drop;
+
        mark_inode_dirty(inode);
        ext2_debug("allocating inode %lu\n", inode->i_ino);
        ext2_preread_inode(inode);
        return inode;
 
-fail2:
+fail_free_drop:
+       DQUOT_FREE_INODE(inode);
+
+fail_drop:
+       DQUOT_DROP(inode);
        inode->i_flags |= S_NOQUOTA;
        inode->i_nlink = 0;
        iput(inode);
index 96552769d039e64d13d2ecc80e4c356eefc4398c..6549945f9ac156ae0523108ffc3b8bfc0cd88448 100644 (file)
@@ -597,27 +597,22 @@ got:
 
        ret = inode;
        if(DQUOT_ALLOC_INODE(inode)) {
-               DQUOT_DROP(inode);
                err = -EDQUOT;
-               goto fail2;
+               goto fail_drop;
        }
+
        err = ext3_init_acl(handle, inode, dir);
-       if (err) {
-               DQUOT_FREE_INODE(inode);
-               DQUOT_DROP(inode);
-               goto fail2;
-       }
+       if (err)
+               goto fail_free_drop;
+
        err = ext3_init_security(handle,inode, dir);
-       if (err) {
-               DQUOT_FREE_INODE(inode);
-               goto fail2;
-       }
+       if (err)
+               goto fail_free_drop;
+
        err = ext3_mark_inode_dirty(handle, inode);
        if (err) {
                ext3_std_error(sb, err);
-               DQUOT_FREE_INODE(inode);
-               DQUOT_DROP(inode);
-               goto fail2;
+               goto fail_free_drop;
        }
 
        ext3_debug("allocating inode %lu\n", inode->i_ino);
@@ -631,7 +626,11 @@ really_out:
        brelse(bitmap_bh);
        return ret;
 
-fail2:
+fail_free_drop:
+       DQUOT_FREE_INODE(inode);
+
+fail_drop:
+       DQUOT_DROP(inode);
        inode->i_flags |= S_NOQUOTA;
        inode->i_nlink = 0;
        iput(inode);
index e79e49b3eec7e0304a2a8763c54f0c31d48536f6..29f1e9f6e85c3648c8a3deeb7847d078625e9844 100644 (file)
@@ -96,6 +96,8 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
        fuse_lookup_init(req, dir, entry, &outarg);
        request_send(fc, req);
        err = req->out.h.error;
+       if (!err && (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID))
+               err = -EIO;
        if (!err) {
                inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
                                  &outarg.attr);
@@ -152,6 +154,10 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
                fuse_put_request(fc, req);
                return err;
        }
+       if (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID) {
+               fuse_put_request(fc, req);
+               return -EIO;
+       }
        inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
                          &outarg.attr);
        if (!inode) {
index 6454022b05367c3818fa24e3d7dab7dd5a45bfae..657ab11c173b38a05678f49c05accc7313b02ede 100644 (file)
@@ -23,6 +23,10 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
        struct fuse_file *ff;
        int err;
 
+       /* VFS checks this, but only _after_ ->open() */
+       if (file->f_flags & O_DIRECT)
+               return -EINVAL;
+
        err = generic_file_open(inode, file);
        if (err)
                return err;
index 59c5062cd63f3bcc8af85edbdabda742a0c88325..dd7113106269992822e97e4bbf07ad2bc5ab5eca 100644 (file)
@@ -793,11 +793,6 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from,
        return(err);
 }
 
-void hostfs_truncate(struct inode *ino)
-{
-       not_implemented();
-}
-
 int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
 {
        char *name;
@@ -894,7 +889,6 @@ static struct inode_operations hostfs_iops = {
        .rmdir          = hostfs_rmdir,
        .mknod          = hostfs_mknod,
        .rename         = hostfs_rename,
-       .truncate       = hostfs_truncate,
        .permission     = hostfs_permission,
        .setattr        = hostfs_setattr,
        .getattr        = hostfs_getattr,
@@ -910,7 +904,6 @@ static struct inode_operations hostfs_dir_iops = {
        .rmdir          = hostfs_rmdir,
        .mknod          = hostfs_mknod,
        .rename         = hostfs_rename,
-       .truncate       = hostfs_truncate,
        .permission     = hostfs_permission,
        .setattr        = hostfs_setattr,
        .getattr        = hostfs_getattr,
index c7e9237379c233bae7d99490ec6f637a7233221b..83f3322765cd1d47f08398f797550d26b0db5835 100644 (file)
@@ -29,7 +29,8 @@ ToDo/Notes:
          The Windows boot will run chkdsk and then reboot.  The user can then
          immediately boot into Linux rather than having to do a full Windows
          boot first before rebooting into Linux and we will recognize such a
-         journal and empty it as it is clean by definition.
+         journal and empty it as it is clean by definition.  Note, this only
+         works if chkdsk left the journal in an obviously clean state.
        - Support journals ($LogFile) with only one restart page as well as
          journals with two different restart pages.  We sanity check both and
          either use the only sane one or the more recent one of the two in the
@@ -94,6 +95,13 @@ ToDo/Notes:
          my ways.
        - Fix various bugs in the runlist merging code.  (Based on libntfs
          changes by Richard Russon.)
+       - Fix sparse warnings that have crept in over time.
+       - Change ntfs_cluster_free() to require a write locked runlist on entry
+         since we otherwise get into a lock reversal deadlock if a read locked
+         runlist is passed in. In the process also change it to take an ntfs
+         inode instead of a vfs inode as parameter.
+       - Fix the definition of the CHKD ntfs record magic.  It had an off by
+         two error causing it to be CHKB instead of CHKD.
 
 2.1.23 - Implement extension of resident files and make writing safe as well as
         many bug fixes, cleanups, and enhancements...
index 609ad1728ce4c74cb14531ad77438b06aefef4f0..01f2dfa39cecaf29f3af0964247c1abd9a008670 100644 (file)
@@ -123,7 +123,7 @@ enum {
        magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */
 
        /* Found in $LogFile/$DATA.  (May be found in $MFT/$DATA, also?) */
-       magic_CHKD = const_cpu_to_le32(0x424b4843), /* Modified by chkdsk. */
+       magic_CHKD = const_cpu_to_le32(0x444b4843), /* Modified by chkdsk. */
 
        /* Found in all ntfs record containing records. */
        magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector
@@ -308,10 +308,8 @@ typedef le16 MFT_RECORD_FLAGS;
  * The _LE versions are to be applied on little endian MFT_REFs.
  * Note: The _LE versions will return a CPU endian formatted value!
  */
-typedef enum {
-       MFT_REF_MASK_CPU        = 0x0000ffffffffffffULL,
-       MFT_REF_MASK_LE         = const_cpu_to_le64(0x0000ffffffffffffULL),
-} MFT_REF_CONSTS;
+#define MFT_REF_MASK_CPU 0x0000ffffffffffffULL
+#define MFT_REF_MASK_LE const_cpu_to_le64(0x0000ffffffffffffULL)
 
 typedef u64 MFT_REF;
 typedef le64 leMFT_REF;
index 7b5934290685ddd814a81bce2be415f0d71659a3..5af3bf0b7eee15220a26841ad0812c6766720f38 100644 (file)
@@ -779,14 +779,13 @@ out:
 
 /**
  * __ntfs_cluster_free - free clusters on an ntfs volume
- * @vi:                vfs inode whose runlist describes the clusters to free
- * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
+ * @ni:                ntfs inode whose runlist describes the clusters to free
+ * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters
  * @count:     number of clusters to free or -1 for all clusters
- * @write_locked:      true if the runlist is locked for writing
  * @is_rollback:       true if this is a rollback operation
  *
  * Free @count clusters starting at the cluster @start_vcn in the runlist
- * described by the vfs inode @vi.
+ * described by the vfs inode @ni.
  *
  * If @count is -1, all clusters from @start_vcn to the end of the runlist are
  * deallocated.  Thus, to completely free all clusters in a runlist, use
@@ -801,31 +800,28 @@ out:
  * Return the number of deallocated clusters (not counting sparse ones) on
  * success and -errno on error.
  *
- * Locking: - The runlist described by @vi must be locked on entry and is
- *           locked on return.  Note if the runlist is locked for reading the
- *           lock may be dropped and reacquired.  Note the runlist may be
- *           modified when needed runlist fragments need to be mapped.
+ * Locking: - The runlist described by @ni must be locked for writing on entry
+ *           and is locked on return.  Note the runlist may be modified when
+ *           needed runlist fragments need to be mapped.
  *         - The volume lcn bitmap must be unlocked on entry and is unlocked
  *           on return.
  *         - This function takes the volume lcn bitmap lock for writing and
  *           modifies the bitmap contents.
  */
-s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
-               const BOOL write_locked, const BOOL is_rollback)
+s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
+               const BOOL is_rollback)
 {
        s64 delta, to_free, total_freed, real_freed;
-       ntfs_inode *ni;
        ntfs_volume *vol;
        struct inode *lcnbmp_vi;
        runlist_element *rl;
        int err;
 
-       BUG_ON(!vi);
+       BUG_ON(!ni);
        ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count "
-                       "0x%llx.%s", vi->i_ino, (unsigned long long)start_vcn,
+                       "0x%llx.%s", ni->mft_no, (unsigned long long)start_vcn,
                        (unsigned long long)count,
                        is_rollback ? " (rollback)" : "");
-       ni = NTFS_I(vi);
        vol = ni->vol;
        lcnbmp_vi = vol->lcnbmp_ino;
        BUG_ON(!lcnbmp_vi);
@@ -843,7 +839,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
 
        total_freed = real_freed = 0;
 
-       rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, write_locked);
+       rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, TRUE);
        if (IS_ERR(rl)) {
                if (!is_rollback)
                        ntfs_error(vol->sb, "Failed to find first runlist "
@@ -897,7 +893,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
 
                        /* Attempt to map runlist. */
                        vcn = rl->vcn;
-                       rl = ntfs_attr_find_vcn_nolock(ni, vcn, write_locked);
+                       rl = ntfs_attr_find_vcn_nolock(ni, vcn, TRUE);
                        if (IS_ERR(rl)) {
                                err = PTR_ERR(rl);
                                if (!is_rollback)
@@ -965,8 +961,7 @@ err_out:
         * If rollback fails, set the volume errors flag, emit an error
         * message, and return the error code.
         */
-       delta = __ntfs_cluster_free(vi, start_vcn, total_freed, write_locked,
-                       TRUE);
+       delta = __ntfs_cluster_free(ni, start_vcn, total_freed, TRUE);
        if (delta < 0) {
                ntfs_error(vol->sb, "Failed to rollback (error %i).  Leaving "
                                "inconsistent metadata!  Unmount and run "
index e4d7fb98d6856a86953b5d91d395633d67ee4ff2..a6a8827882e73c71705ebf9ec174805e0a75dc8e 100644 (file)
@@ -2,7 +2,7 @@
  * lcnalloc.h - Exports for NTFS kernel cluster (de)allocation.  Part of the
  *             Linux-NTFS project.
  *
- * Copyright (c) 2004 Anton Altaparmakov
+ * Copyright (c) 2004-2005 Anton Altaparmakov
  *
  * This program/include file is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as published
@@ -28,6 +28,7 @@
 #include <linux/fs.h>
 
 #include "types.h"
+#include "inode.h"
 #include "runlist.h"
 #include "volume.h"
 
@@ -42,18 +43,17 @@ extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
                const VCN start_vcn, const s64 count, const LCN start_lcn,
                const NTFS_CLUSTER_ALLOCATION_ZONES zone);
 
-extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
-               s64 count, const BOOL write_locked, const BOOL is_rollback);
+extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
+               s64 count, const BOOL is_rollback);
 
 /**
  * ntfs_cluster_free - free clusters on an ntfs volume
- * @vi:                vfs inode whose runlist describes the clusters to free
- * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
+ * @ni:                ntfs inode whose runlist describes the clusters to free
+ * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters
  * @count:     number of clusters to free or -1 for all clusters
- * @write_locked:      true if the runlist is locked for writing
  *
  * Free @count clusters starting at the cluster @start_vcn in the runlist
- * described by the vfs inode @vi.
+ * described by the ntfs inode @ni.
  *
  * If @count is -1, all clusters from @start_vcn to the end of the runlist are
  * deallocated.  Thus, to completely free all clusters in a runlist, use
@@ -65,19 +65,18 @@ extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
  * Return the number of deallocated clusters (not counting sparse ones) on
  * success and -errno on error.
  *
- * Locking: - The runlist described by @vi must be locked on entry and is
- *           locked on return.  Note if the runlist is locked for reading the
- *           lock may be dropped and reacquired.  Note the runlist may be
- *           modified when needed runlist fragments need to be mapped.
+ * Locking: - The runlist described by @ni must be locked for writing on entry
+ *           and is locked on return.  Note the runlist may be modified when
+ *           needed runlist fragments need to be mapped.
  *         - The volume lcn bitmap must be unlocked on entry and is unlocked
  *           on return.
  *         - This function takes the volume lcn bitmap lock for writing and
  *           modifies the bitmap contents.
  */
-static inline s64 ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
-               s64 count, const BOOL write_locked)
+static inline s64 ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn,
+               s64 count)
 {
-       return __ntfs_cluster_free(vi, start_vcn, count, write_locked, FALSE);
+       return __ntfs_cluster_free(ni, start_vcn, count, FALSE);
 }
 
 extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
index 0173e95500d94448712f18086d045a3c1d292d41..0fd70295cca67347694d815e85e335c25efb2b68 100644 (file)
@@ -51,7 +51,8 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
                RESTART_PAGE_HEADER *rp, s64 pos)
 {
        u32 logfile_system_page_size, logfile_log_page_size;
-       u16 usa_count, usa_ofs, usa_end, ra_ofs;
+       u16 ra_ofs, usa_count, usa_ofs, usa_end = 0;
+       BOOL have_usa = TRUE;
 
        ntfs_debug("Entering.");
        /*
@@ -86,6 +87,14 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
                                (int)sle16_to_cpu(rp->minor_ver));
                return FALSE;
        }
+       /*
+        * If chkdsk has been run the restart page may not be protected by an
+        * update sequence array.
+        */
+       if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) {
+               have_usa = FALSE;
+               goto skip_usa_checks;
+       }
        /* Verify the size of the update sequence array. */
        usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS);
        if (usa_count != le16_to_cpu(rp->usa_count)) {
@@ -102,6 +111,7 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
                                "inconsistent update sequence array offset.");
                return FALSE;
        }
+skip_usa_checks:
        /*
         * Verify the position of the restart area.  It must be:
         *      - aligned to 8-byte boundary,
@@ -109,7 +119,8 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi,
         *      - within the system page size.
         */
        ra_ofs = le16_to_cpu(rp->restart_area_offset);
-       if (ra_ofs & 7 || ra_ofs < usa_end ||
+       if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end :
+                       ra_ofs < sizeof(RESTART_PAGE_HEADER)) ||
                        ra_ofs > logfile_system_page_size) {
                ntfs_error(vi->i_sb, "$LogFile restart page specifies "
                                "inconsistent restart area offset.");
@@ -402,8 +413,12 @@ static int ntfs_check_and_load_restart_page(struct inode *vi,
                        idx++;
                } while (to_read > 0);
        }
-       /* Perform the multi sector transfer deprotection on the buffer. */
-       if (post_read_mst_fixup((NTFS_RECORD*)trp,
+       /*
+        * Perform the multi sector transfer deprotection on the buffer if the
+        * restart page is protected.
+        */
+       if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count))
+                       && post_read_mst_fixup((NTFS_RECORD*)trp,
                        le32_to_cpu(rp->system_page_size))) {
                /*
                 * A multi sector tranfer error was detected.  We only need to
@@ -615,11 +630,16 @@ is_empty:
                 * Otherwise just throw it away.
                 */
                if (rstr2_lsn > rstr1_lsn) {
+                       ntfs_debug("Using second restart page as it is more "
+                                       "recent.");
                        ntfs_free(rstr1_ph);
                        rstr1_ph = rstr2_ph;
                        /* rstr1_lsn = rstr2_lsn; */
-               } else
+               } else {
+                       ntfs_debug("Using first restart page as it is more "
+                                       "recent.");
                        ntfs_free(rstr2_ph);
+               }
                rstr2_ph = NULL;
        }
        /* All consistency checks passed. */
index 42388f95ea6da5b008a092ea04f8eff0d49b3cc7..a51f3dd0e9eb56c106f3935b14c4d2d7ed76cbc7 100644 (file)
@@ -113,7 +113,7 @@ typedef struct {
  */
 enum {
        RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002),
-       RESTART_SPACE_FILLER    = 0xffff, /* gcc: Force enum bit width to 16. */
+       RESTART_SPACE_FILLER    = const_cpu_to_le16(0xffff), /* gcc: Force enum bit width to 16. */
 } __attribute__ ((__packed__));
 
 typedef le16 RESTART_AREA_FLAGS;
index 2c32b84385a8f693bef3130b9fd5ee32b224c966..247586d1d5dc52787c36233c60f10f32105f0bc3 100644 (file)
@@ -1953,7 +1953,7 @@ restore_undo_alloc:
        a = ctx->attr;
        a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1);
 undo_alloc:
-       if (ntfs_cluster_free(vol->mft_ino, old_last_vcn, -1, TRUE) < 0) {
+       if (ntfs_cluster_free(mft_ni, old_last_vcn, -1) < 0) {
                ntfs_error(vol->sb, "Failed to free clusters from mft data "
                                "attribute.%s", es);
                NVolSetErrors(vol);
index b60324aaa2b6731d9ddedd67badaa7b5c9790a60..a091ee4f430df6cc83317b59c4a2fc363c005080 100644 (file)
@@ -497,6 +497,9 @@ static ssize_t do_readv_writev(int type, struct file *file,
        }
 
        ret = rw_verify_area(type, file, pos, tot_len);
+       if (ret)
+               goto out;
+       ret = security_file_permission(file, type == READ ? MAY_READ : MAY_WRITE);
        if (ret)
                goto out;
 
index be9754a05c19faa9b8fa1833d00cae4eb2fe11df..9d7f87375aa774b477485aa79eb422d00c9536ac 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/arch/memory.h>
 
 #ifndef __ASSEMBLY__
-#define IOMEM(x) ((void __iomem *)(x))
+#define IOMEM(x) ((void __iomem *)(unsigned long)(x))
 #else
 #define IOMEM(x) x
 #endif /* __ASSEMBLY__ */
@@ -52,7 +52,7 @@
 /*
  * IO Addresses
  */
-#define VIDC_BASE              (void __iomem *)0xe0400000
+#define VIDC_BASE              IOMEM(0xe0400000)
 #define EXPMASK_BASE           0xe0360000
 #define IOMD_BASE              IOMEM(0xe0200000)
 #define IOC_BASE               IOMEM(0xe0200000)
index 97741d6e506ae37aeac40032278f8e84cbf83cad..d529ffda8599638c64a6df9409bce444674bcec7 100644 (file)
 
 /* start peripherals off after the S3C2410 */
 
-#define ANUBIS_IOADDR(x)       (S3C2410_ADDR((x) + 0x02000000))
+#define ANUBIS_IOADDR(x)       (S3C2410_ADDR((x) + 0x01800000))
 
 #define ANUBIS_PA_CPLD         (S3C2410_CS1 | (1<<26))
 
 /* we put the CPLD registers next, to get them out of the way */
 
-#define ANUBIS_VA_CTRL1            ANUBIS_IOADDR(0x00000000)    /* 0x01300000 */
+#define ANUBIS_VA_CTRL1            ANUBIS_IOADDR(0x00000000)    /* 0x01800000 */
 #define ANUBIS_PA_CTRL1            (ANUBIS_PA_CPLD)
 
-#define ANUBIS_VA_CTRL2            ANUBIS_IOADDR(0x00100000)    /* 0x01400000 */
+#define ANUBIS_VA_CTRL2            ANUBIS_IOADDR(0x00100000)    /* 0x01900000 */
 #define ANUBIS_PA_CTRL2            (ANUBIS_PA_CPLD)
 
-#define ANUBIS_VA_CTRL3            ANUBIS_IOADDR(0x00200000)    /* 0x01500000 */
+#define ANUBIS_VA_CTRL3            ANUBIS_IOADDR(0x00200000)    /* 0x01A00000 */
 #define ANUBIS_PA_CTRL3            (ANUBIS_PA_CPLD)
 
-#define ANUBIS_VA_CTRL4            ANUBIS_IOADDR(0x00300000)    /* 0x01600000 */
+#define ANUBIS_VA_CTRL4            ANUBIS_IOADDR(0x00300000)    /* 0x01B00000 */
 #define ANUBIS_PA_CTRL4            (ANUBIS_PA_CPLD)
 
 #define ANUBIS_IDEPRI      ANUBIS_IOADDR(0x01000000)
index 9f895bf61494308a2c2add721009c3699125781d..47e904cf25c748b6f19fca6e7b9ab70c9aa3ded3 100644 (file)
 
 #define IO_SPACE_LIMIT 0xffffffff
 
-#define __io(a)                        ((void __iomem *)(a))
+static inline void __iomem *__io(unsigned long addr)
+{
+       return (void __iomem *)addr;
+}
+#define __io(a)        __io(a)
 #define __mem_pci(a)           (a)
 #define __mem_isa(a)           (a)
 
index a1696ba238d3aad1c891f194ac93d8c0b73c1362..7da97a937548afd05a977ceb0d2148821dc05cfb 100644 (file)
@@ -124,6 +124,8 @@ do { \
        if (((ex).e_flags & EF_ARM_EABI_MASK) || \
            ((ex).e_flags & EF_ARM_SOFT_FLOAT)) \
                set_thread_flag(TIF_USING_IWMMXT); \
+       else \
+               clear_thread_flag(TIF_USING_IWMMXT); \
 } while (0)
 
 #endif
index cfa71a0dffb655764153153f6ee7a5ddc338f016..5c4ae8f5dbb076ad2e46ea8be9c48acb1bc56879 100644 (file)
@@ -136,9 +136,9 @@ extern void __readwrite_bug(const char *fn);
 /*
  * String version of IO memory access ops:
  */
-extern void _memcpy_fromio(void *, void __iomem *, size_t);
-extern void _memcpy_toio(void __iomem *, const void *, size_t);
-extern void _memset_io(void __iomem *, int, size_t);
+extern void _memcpy_fromio(void *, const volatile void __iomem *, size_t);
+extern void _memcpy_toio(volatile void __iomem *, const void *, size_t);
+extern void _memset_io(volatile void __iomem *, int, size_t);
 
 #define mmiowb()
 
index 760f6e65af05583c2faea5b1997989d8435c5c3b..ced69161917b802cd3184017cdd1614f0477f86b 100644 (file)
@@ -115,7 +115,6 @@ typedef unsigned long sigset_t;
 
 #ifdef __KERNEL__
 #define SA_TIMER               0x40000000
-#define SA_IRQNOMASK           0x08000000
 #endif
 
 #include <asm-generic/signal.h>
index f86c1e549466a0809c02fecc750cb5627ed08027..ff28c8b31f5844694de47bf5a8775c55b37d569c 100644 (file)
@@ -158,6 +158,19 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
 #define lazy_mmu_prot_update(pte)      do { } while (0)
 #endif
 
+#ifndef __HAVE_ARCH_MULTIPLE_ZERO_PAGE
+#define move_pte(pte, prot, old_addr, new_addr)        (pte)
+#else
+#define move_pte(pte, prot, old_addr, new_addr)                                \
+({                                                                     \
+       pte_t newpte = (pte);                                           \
+       if (pte_present(pte) && pfn_valid(pte_pfn(pte)) &&              \
+                       pte_page(pte) == ZERO_PAGE(old_addr))           \
+               newpte = mk_pte(ZERO_PAGE(new_addr), (prot));           \
+       newpte;                                                         \
+})
+#endif
+
 /*
  * When walking page tables, get the address of the next boundary,
  * or the end address of the range if that comes earlier.  Although no
index 4ac84cc6f01ac8c81fd16c9734a216a5cb4543f2..622815bf3243e00306774bbea1ab01e2bc2a2f3e 100644 (file)
@@ -18,6 +18,8 @@
 #include <asm/irq.h>
 #include <asm/sections.h>
 
+struct hw_interrupt_type;
+
 /*
  * Various low-level irq details needed by irq.c, process.c,
  * time.c, io_apic.c and smp.c
index 3a7829bb5954030cfb3a2eee73620de5a3f37403..9adb51211c2270d7500dfb00d8ed3a59264651e6 100644 (file)
@@ -187,8 +187,8 @@ extern void __get_user_unknown (void);
 ({                                                                                     \
        const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);                              \
        __typeof__ (size) __gu_size = (size);                                           \
-       long __gu_err = -EFAULT, __gu_val = 0;                                          \
-                                                                                       \
+       long __gu_err = -EFAULT;                                                        \
+       unsigned long __gu_val = 0;                                                     \
        if (!check || __access_ok(__gu_ptr, size, segment))                             \
                switch (__gu_size) {                                                    \
                      case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break;  \
@@ -240,13 +240,13 @@ extern unsigned long __must_check __copy_user (void __user *to, const void __use
 static inline unsigned long
 __copy_to_user (void __user *to, const void *from, unsigned long count)
 {
-       return __copy_user(to, (void __user *) from, count);
+       return __copy_user(to, (__force void __user *) from, count);
 }
 
 static inline unsigned long
 __copy_from_user (void *to, const void __user *from, unsigned long count)
 {
-       return __copy_user((void __user *) to, from, count);
+       return __copy_user((__force void __user *) to, from, count);
 }
 
 #define __copy_to_user_inatomic                __copy_to_user
@@ -258,7 +258,7 @@ __copy_from_user (void *to, const void __user *from, unsigned long count)
        long __cu_len = (n);                                                            \
                                                                                        \
        if (__access_ok(__cu_to, __cu_len, get_fs()))                                   \
-               __cu_len = __copy_user(__cu_to, (void __user *) __cu_from, __cu_len);   \
+               __cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len);   \
        __cu_len;                                                                       \
 })
 
@@ -270,7 +270,7 @@ __copy_from_user (void *to, const void __user *from, unsigned long count)
                                                                                        \
        __chk_user_ptr(__cu_from);                                                      \
        if (__access_ok(__cu_from, __cu_len, get_fs()))                                 \
-               __cu_len = __copy_user((void __user *) __cu_to, __cu_from, __cu_len);   \
+               __cu_len = __copy_user((__force void __user *) __cu_to, __cu_from, __cu_len);   \
        __cu_len;                                                                       \
 })
 
index 8e9e481e6996a2b584dc5add75e9f29755163ddf..70ad1c949c2b498cf691cdfc6326877ecb284681 100644 (file)
@@ -60,7 +60,7 @@ __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
  *     address.
  */
 
-static inline void ioremap(unsigned long offset, unsigned long size)
+static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
 {
        return __ioremap(offset, size, 0);
 }
index 93d863c455a19ff302af1e231a578616bc1d9270..0da7c47d2f01ce5fe0b0af464d3145b9653db18a 100644 (file)
@@ -208,7 +208,8 @@ extern void __get_user_4(void);
  * On error, the variable @x is set to zero.
  */
 #define get_user(x,ptr)                                                        \
-({     int __ret_gu,__val_gu;                                          \
+({     int __ret_gu;                                                   \
+       unsigned long __val_gu;                                         \
        __chk_user_ptr(ptr);                                            \
        switch(sizeof (*(ptr))) {                                       \
        case 1:  __get_user_x(1,__ret_gu,__val_gu,ptr); break;          \
@@ -403,7 +404,8 @@ struct __large_struct { unsigned long buf[100]; };
 
 #define __get_user_nocheck(x,ptr,size)                                 \
 ({                                                                     \
-       long __gu_err, __gu_val;                                        \
+       long __gu_err;                                                  \
+       unsigned long __gu_val;                                         \
        __get_user_size(__gu_val,(ptr),(size),__gu_err);                \
        (x) = (__typeof__(*(ptr)))__gu_val;                             \
        __gu_err;                                                       \
@@ -594,8 +596,8 @@ static inline unsigned long __generic_copy_to_user_nocheck(void __user *to,
        return n;
 }
 
-unsigned long __generic_copy_to_user(void *, const void *, unsigned long);
-unsigned long __generic_copy_from_user(void *, const void *, unsigned long);
+unsigned long __generic_copy_to_user(void __user *, const void *, unsigned long);
+unsigned long __generic_copy_from_user(void *, const void __user *, unsigned long);
 
 /**
  * __copy_to_user: - Copy a block of data into user space, with less checking.
index cbd1672c94cb366db294898d470704c2707ac49d..eaf5d9b3a0e18d45d495d706a0dd5ad56bb3a3c6 100644 (file)
@@ -68,6 +68,8 @@ extern unsigned long zero_page_mask;
 #define ZERO_PAGE(vaddr) \
        (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
 
+#define __HAVE_ARCH_MULTIPLE_ZERO_PAGE
+
 extern void paging_init(void);
 
 /*
index 7eb7cf6360bd1e76d5909faf11959b6cea49f6b5..94d83998a75912851f4a3ff4095d2b09f4408f67 100644 (file)
@@ -56,7 +56,7 @@ extern unsigned long pci_dram_offset;
  * is actually performed (i.e. the data has come back) before we start
  * executing any following instructions.
  */
-extern inline int in_8(volatile unsigned char __iomem *addr)
+extern inline int in_8(const volatile unsigned char __iomem *addr)
 {
        int ret;
 
@@ -72,7 +72,7 @@ extern inline void out_8(volatile unsigned char __iomem *addr, int val)
        __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
 }
 
-extern inline int in_le16(volatile unsigned short __iomem *addr)
+extern inline int in_le16(const volatile unsigned short __iomem *addr)
 {
        int ret;
 
@@ -83,7 +83,7 @@ extern inline int in_le16(volatile unsigned short __iomem *addr)
        return ret;
 }
 
-extern inline int in_be16(volatile unsigned short __iomem *addr)
+extern inline int in_be16(const volatile unsigned short __iomem *addr)
 {
        int ret;
 
@@ -104,7 +104,7 @@ extern inline void out_be16(volatile unsigned short __iomem *addr, int val)
        __asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
 }
 
-extern inline unsigned in_le32(volatile unsigned __iomem *addr)
+extern inline unsigned in_le32(const volatile unsigned __iomem *addr)
 {
        unsigned ret;
 
@@ -115,7 +115,7 @@ extern inline unsigned in_le32(volatile unsigned __iomem *addr)
        return ret;
 }
 
-extern inline unsigned in_be32(volatile unsigned __iomem *addr)
+extern inline unsigned in_be32(const volatile unsigned __iomem *addr)
 {
        unsigned ret;
 
@@ -139,7 +139,7 @@ extern inline void out_be32(volatile unsigned __iomem *addr, int val)
 #define readb(addr) in_8((volatile u8 *)(addr))
 #define writeb(b,addr) out_8((volatile u8 *)(addr), (b))
 #else
-static inline __u8 readb(volatile void __iomem *addr)
+static inline __u8 readb(const volatile void __iomem *addr)
 {
        return in_8(addr);
 }
@@ -150,11 +150,11 @@ static inline void writeb(__u8 b, volatile void __iomem *addr)
 #endif
 
 #if defined(CONFIG_APUS)
-static inline __u16 readw(volatile void __iomem *addr)
+static inline __u16 readw(const volatile void __iomem *addr)
 {
        return *(__force volatile __u16 *)(addr);
 }
-static inline __u32 readl(volatile void __iomem *addr)
+static inline __u32 readl(const volatile void __iomem *addr)
 {
        return *(__force volatile __u32 *)(addr);
 }
@@ -173,11 +173,11 @@ static inline void writel(__u32 b, volatile void __iomem *addr)
 #define writew(b,addr) out_le16((volatile u16 *)(addr),(b))
 #define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
 #else
-static inline __u16 readw(volatile void __iomem *addr)
+static inline __u16 readw(const volatile void __iomem *addr)
 {
        return in_le16(addr);
 }
-static inline __u32 readl(volatile void __iomem *addr)
+static inline __u32 readl(const volatile void __iomem *addr)
 {
        return in_le32(addr);
 }
index 75c2ffa26b26d5b22a1dffcc78a1731361001b7a..ee2f9188cc64c0af24aea5d053d96952f1f6659b 100644 (file)
@@ -233,7 +233,7 @@ struct mv64x60_chip_info {
 struct mv64x60_handle {
        u32             type;           /* type of bridge */
        u32             rev;            /* revision of bridge */
-       void            *v_base;        /* virtual base addr of bridge regs */
+       void            __iomem *v_base;/* virtual base addr of bridge regs */
        phys_addr_t     p_base;         /* physical base addr of bridge regs */
 
        u32             pci_mode_a;     /* pci 0 mode: conventional pci, pci-x*/
@@ -303,7 +303,7 @@ void mv64x60_alloc_hose(struct mv64x60_handle *bh, u32 cfg_addr,
        u32 cfg_data, struct pci_controller **hose);
 int mv64x60_get_type(struct mv64x60_handle *bh);
 int mv64x60_setup_for_chip(struct mv64x60_handle *bh);
-void *mv64x60_get_bridge_vbase(void);
+void __iomem *mv64x60_get_bridge_vbase(void);
 u32 mv64x60_get_bridge_type(void);
 u32 mv64x60_get_bridge_rev(void);
 void mv64x60_get_mem_windows(struct mv64x60_handle *bh,
index 45411a67e0825f3e4685bfeebd5d6724a0ab6ab3..74271d7c1d161f9577f9ddb6d3be88ebc351a7bc 100644 (file)
@@ -25,6 +25,7 @@ struct ppc64_tlb_batch {
        pte_t pte[PPC64_TLB_BATCH_NR];
        unsigned long addr[PPC64_TLB_BATCH_NR];
        unsigned long vaddr[PPC64_TLB_BATCH_NR];
+       unsigned int large;
 };
 DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
 
index c181a60d868c7ee82e79db9ce1d57f9817a8d8d4..132c1276547b9300475560b00a889867dab7fd12 100644 (file)
@@ -164,7 +164,8 @@ do {                                                                        \
 
 #define __get_user_nocheck(x,ptr,size)                         \
 ({                                                             \
-       long __gu_err, __gu_val;                                \
+       long __gu_err;                                          \
+       unsigned long __gu_val;                                 \
        might_sleep();                                          \
        __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\
        (x) = (__typeof__(*(ptr)))__gu_val;                     \
@@ -173,7 +174,8 @@ do {                                                                        \
 
 #define __get_user_check(x,ptr,size)                                   \
 ({                                                                     \
-       long __gu_err = -EFAULT, __gu_val = 0;                          \
+       long __gu_err = -EFAULT;                                        \
+       unsigned long __gu_val = 0;                                     \
        const __typeof__(*(ptr)) __user *__gu_addr = (ptr);             \
        might_sleep();                                                  \
        if (access_ok(VERIFY_READ,__gu_addr,size))                      \
index d57bc0cebdcec86509ac09b57dc9e322cbccaf6c..803545351dd8d399c41469b32ed82298da36adf7 100644 (file)
@@ -61,7 +61,7 @@ typedef struct
 struct sigcontext
 {
        unsigned long   oldmask[_SIGCONTEXT_NSIG_WORDS];
-       _sigregs        *sregs;
+       _sigregs        __user *sregs;
 };
 
 
index 3d6e11c6c1fdd94a4568e1bd230bbdfb25733f3b..7084626de215750590bf4dfac15f88257ce187bb 100644 (file)
@@ -165,7 +165,7 @@ struct sigaction {
 #endif /* __KERNEL__ */
 
 typedef struct sigaltstack {
-        void *ss_sp;
+        void __user *ss_sp;
         int ss_flags;
         size_t ss_size;
 } stack_t;
index 8f4f6a95965130820e03f46e22cfe795721bbfcb..8395ad2f1c093037f9ff0e87201c77f75f45cb8f 100644 (file)
@@ -82,6 +82,8 @@ extern unsigned long page_kernel;
 /* Top-level page directory */
 extern pgd_t swapper_pg_dir[1024];
 
+extern void paging_init(void);
+
 /* Page table for 0-4MB for everybody, on the Sparc this
  * holds the same as on the i386.
  */
index ededd2659eab7b0a3dc99e4e36bae5e7e70750c7..b3f61659ba81531a4acc77e9f21acbd918fc660c 100644 (file)
@@ -66,6 +66,11 @@ extern void flush_ptrace_access(struct vm_area_struct *, struct page *,
 #define flush_cache_vmap(start, end)           do { } while (0)
 #define flush_cache_vunmap(start, end)         do { } while (0)
 
+#ifdef CONFIG_DEBUG_PAGEALLOC
+/* internal debugging function */
+void kernel_map_pages(struct page *page, int numpages, int enable);
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _SPARC64_CACHEFLUSH_H */
index 9a3a81f1cc58ab7ba06c7e4290fc851a44ed570c..74de79dca9152ca44ce0f4ef006e459834d28278 100644 (file)
@@ -22,6 +22,16 @@ typedef struct {
        unsigned int    __pad1;
        unsigned long   *pte_cache[2];
        unsigned long   *pgd_cache;
+
+       /* Dcache line 3, rarely used */
+       unsigned int    dcache_size;
+       unsigned int    dcache_line_size;
+       unsigned int    icache_size;
+       unsigned int    icache_line_size;
+       unsigned int    ecache_size;
+       unsigned int    ecache_line_size;
+       unsigned int    __pad2;
+       unsigned int    __pad3;
 } cpuinfo_sparc;
 
 DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
index b63a33cf497181342351eeb629559a807bf5b161..0abd3a674e8f1abcd178f5f3fe9260efcc2a04ce 100644 (file)
 #define __JALAPENO_ID  0x003e0016
 
 #define CHEETAH_MANUF          0x003e
-#define CHEETAH_IMPL           0x0014
-#define CHEETAH_PLUS_IMPL      0x0015
-#define JALAPENO_IMPL          0x0016
+#define CHEETAH_IMPL           0x0014 /* Ultra-III   */
+#define CHEETAH_PLUS_IMPL      0x0015 /* Ultra-III+  */
+#define JALAPENO_IMPL          0x0016 /* Ultra-IIIi  */
+#define JAGUAR_IMPL            0x0018 /* Ultra-IV    */
+#define PANTHER_IMPL           0x0019 /* Ultra-IV+   */
+#define SERRANO_IMPL           0x0022 /* Ultra-IIIi+ */
 
 #define BRANCH_IF_CHEETAH_BASE(tmp1,tmp2,label)        \
        rdpr    %ver, %tmp1;                    \
index 0a336901d58576eb30a921df2b429b458447c2e6..b4959d2b0d991712cc4114644804d17a9152061f 100644 (file)
@@ -186,8 +186,8 @@ struct linux_prom_registers {
 };
 
 struct linux_prom64_registers {
-       long phys_addr;
-       long reg_size;
+       unsigned long phys_addr;
+       unsigned long reg_size;
 };
 
 struct linux_prom_irqs {
index a432d9e7daaa31dbe9730be407051da85cc6b68d..d02f1e8ae1a6cd9bbbe8c46a47be25ae9aa2ccaa 100644 (file)
@@ -38,6 +38,20 @@ extern int prom_stdin, prom_stdout;
  */
 extern int prom_chosen_node;
 
+/* Helper values and strings in arch/sparc64/kernel/head.S */
+extern const char prom_finddev_name[];
+extern const char prom_chosen_path[];
+extern const char prom_getprop_name[];
+extern const char prom_mmu_name[];
+extern const char prom_callmethod_name[];
+extern const char prom_translate_name[];
+extern const char prom_map_name[];
+extern const char prom_unmap_name[];
+extern int prom_mmu_ihandle_cache;
+extern unsigned int prom_boot_mapped_pc;
+extern unsigned int prom_boot_mapping_mode;
+extern unsigned long prom_boot_mapping_phys_high, prom_boot_mapping_phys_low;
+
 struct linux_mlist_p1275 {
        struct linux_mlist_p1275 *theres_more;
        unsigned long start_adr;
@@ -68,7 +82,7 @@ extern char *prom_getbootargs(void);
  * of the string is different on V0 vs. V2->higher proms.  The caller must
  * know what he/she is doing!  Returns the device descriptor, an int.
  */
-extern int prom_devopen(char *device_string);
+extern int prom_devopen(const char *device_string);
 
 /* Close a previously opened device described by the passed integer
  * descriptor.
@@ -81,27 +95,13 @@ extern int prom_devclose(int device_handle);
 extern void prom_seek(int device_handle, unsigned int seek_hival,
                      unsigned int seek_lowval);
 
-/* Machine memory configuration routine. */
-
-/* This function returns a V0 format memory descriptor table, it has three
- * entries.  One for the total amount of physical ram on the machine, one
- * for the amount of physical ram available, and one describing the virtual
- * areas which are allocated by the prom.  So, in a sense the physical
- * available is a calculation of the total physical minus the physical mapped
- * by the prom with virtual mappings.
- *
- * These lists are returned pre-sorted, this should make your life easier
- * since the prom itself is way too lazy to do such nice things.
- */
-extern struct linux_mem_p1275 *prom_meminfo(void);
-
 /* Miscellaneous routines, don't really fit in any category per se. */
 
 /* Reboot the machine with the command line passed. */
-extern void prom_reboot(char *boot_command);
+extern void prom_reboot(const char *boot_command);
 
 /* Evaluate the forth string passed. */
-extern void prom_feval(char *forth_string);
+extern void prom_feval(const char *forth_string);
 
 /* Enter the prom, with possibility of continuation with the 'go'
  * command in newer proms.
@@ -154,7 +154,7 @@ extern char prom_getchar(void);
 extern void prom_putchar(char character);
 
 /* Prom's internal routines, don't use in kernel/boot code. */
-extern void prom_printf(char *fmt, ...);
+extern void prom_printf(const char *fmt, ...);
 extern void prom_write(const char *buf, unsigned int len);
 
 /* Query for input device type */
@@ -215,7 +215,7 @@ extern int prom_getunumber(int syndrome_code,
                           char *buf, int buflen);
 
 /* Retain physical memory to the caller across soft resets. */
-extern unsigned long prom_retain(char *name,
+extern unsigned long prom_retain(const char *name,
                                 unsigned long pa_low, unsigned long pa_high,
                                 long size, long align);
 
@@ -269,28 +269,28 @@ extern int prom_getsibling(int node);
 /* Get the length, at the passed node, of the given property type.
  * Returns -1 on error (ie. no such property at this node).
  */
-extern int prom_getproplen(int thisnode, char *property);
+extern int prom_getproplen(int thisnode, const char *property);
 
 /* Fetch the requested property using the given buffer.  Returns
  * the number of bytes the prom put into your buffer or -1 on error.
  */
-extern int prom_getproperty(int thisnode, char *property,
+extern int prom_getproperty(int thisnode, const char *property,
                            char *prop_buffer, int propbuf_size);
 
 /* Acquire an integer property. */
-extern int prom_getint(int node, char *property);
+extern int prom_getint(int node, const char *property);
 
 /* Acquire an integer property, with a default value. */
-extern int prom_getintdefault(int node, char *property, int defval);
+extern int prom_getintdefault(int node, const char *property, int defval);
 
 /* Acquire a boolean property, 0=FALSE 1=TRUE. */
-extern int prom_getbool(int node, char *prop);
+extern int prom_getbool(int node, const char *prop);
 
 /* Acquire a string property, null string on error. */
-extern void prom_getstring(int node, char *prop, char *buf, int bufsize);
+extern void prom_getstring(int node, const char *prop, char *buf, int bufsize);
 
 /* Does the passed node have the given "name"? YES=1 NO=0 */
-extern int prom_nodematch(int thisnode, char *name);
+extern int prom_nodematch(int thisnode, const char *name);
 
 /* Puts in buffer a prom name in the form name@x,y or name (x for which_io 
  * and y for first regs phys address
@@ -300,7 +300,7 @@ extern int prom_getname(int node, char *buf, int buflen);
 /* Search all siblings starting at the passed node for "name" matching
  * the given string.  Returns the node on success, zero on failure.
  */
-extern int prom_searchsiblings(int node_start, char *name);
+extern int prom_searchsiblings(int node_start, const char *name);
 
 /* Return the first property type, as a string, for the given node.
  * Returns a null string on error. Buffer should be at least 32B long.
@@ -310,21 +310,21 @@ extern char *prom_firstprop(int node, char *buffer);
 /* Returns the next property after the passed property for the given
  * node.  Returns null string on failure. Buffer should be at least 32B long.
  */
-extern char *prom_nextprop(int node, char *prev_property, char *buffer);
+extern char *prom_nextprop(int node, const char *prev_property, char *buffer);
 
 /* Returns 1 if the specified node has given property. */
-extern int prom_node_has_property(int node, char *property);
+extern int prom_node_has_property(int node, const char *property);
 
 /* Returns phandle of the path specified */
-extern int prom_finddevice(char *name);
+extern int prom_finddevice(const char *name);
 
 /* Set the indicated property at the given node with the passed value.
  * Returns the number of bytes of your value that the prom took.
  */
-extern int prom_setprop(int node, char *prop_name, char *prop_value,
+extern int prom_setprop(int node, const char *prop_name, char *prop_value,
                        int value_size);
                        
-extern int prom_pathtoinode(char *path);
+extern int prom_pathtoinode(const char *path);
 extern int prom_inst2pkg(int);
 
 /* CPU probing helpers.  */
@@ -334,7 +334,7 @@ int cpu_find_by_mid(int mid, int *prom_node);
 /* Client interface level routines. */
 extern void prom_set_trap_table(unsigned long tba);
 
-extern long p1275_cmd (char *, long, ...);
+extern long p1275_cmd(const char *, long, ...);
                                   
 
 #if 0
index 7f8d764abc47df424b469c8809855fb67fb2deb6..5426bb28a9931956a46585268a4b86e2703a50f2 100644 (file)
@@ -140,23 +140,6 @@ extern unsigned long page_to_pfn(struct page *);
 #define virt_to_phys __pa
 #define phys_to_virt __va
 
-/* The following structure is used to hold the physical
- * memory configuration of the machine.  This is filled in
- * probe_memory() and is later used by mem_init() to set up
- * mem_map[].  We statically allocate SPARC_PHYS_BANKS of
- * these structs, this is arbitrary.  The entry after the
- * last valid one has num_bytes==0.
- */
-
-struct sparc_phys_banks {
-       unsigned long base_addr;
-       unsigned long num_bytes;
-};
-
-#define SPARC_PHYS_BANKS 32
-
-extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
-
 #endif /* !(__ASSEMBLY__) */
 
 #define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
index a297f6144f0fa940d36bd674c0a3b181261213e7..8c6dfc6c7af6e6d67ab3e1893cd66421208adbd8 100644 (file)
  * table can map
  */
 #define PMD_SHIFT      (PAGE_SHIFT + (PAGE_SHIFT-3))
-#define PMD_SIZE       (1UL << PMD_SHIFT)
+#define PMD_SIZE       (_AC(1,UL) << PMD_SHIFT)
 #define PMD_MASK       (~(PMD_SIZE-1))
 #define PMD_BITS       (PAGE_SHIFT - 2)
 
 /* PGDIR_SHIFT determines what a third-level page table entry can map */
 #define PGDIR_SHIFT    (PAGE_SHIFT + (PAGE_SHIFT-3) + PMD_BITS)
-#define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
+#define PGDIR_SIZE     (_AC(1,UL) << PGDIR_SHIFT)
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))
 #define PGDIR_BITS     (PAGE_SHIFT - 2)
 
@@ -98,7 +98,9 @@
 #define _PAGE_NFO      _AC(0x1000000000000000,UL) /* No Fault Only          */
 #define _PAGE_IE       _AC(0x0800000000000000,UL) /* Invert Endianness      */
 #define _PAGE_SOFT2    _AC(0x07FC000000000000,UL) /* Software bits, set 2   */
-#define _PAGE_RES1     _AC(0x0003000000000000,UL) /* Reserved               */
+#define _PAGE_RES1     _AC(0x0002000000000000,UL) /* Reserved               */
+#define _PAGE_SZ32MB   _AC(0x0001000000000000,UL) /* (Panther) 32MB page    */
+#define _PAGE_SZ256MB  _AC(0x2001000000000000,UL) /* (Panther) 256MB page   */
 #define _PAGE_SN       _AC(0x0000800000000000,UL) /* (Cheetah) Snoop        */
 #define _PAGE_RES2     _AC(0x0000780000000000,UL) /* Reserved               */
 #define _PAGE_PADDR_SF _AC(0x000001FFFFFFE000,UL) /* (Spitfire) paddr[40:13]*/
@@ -336,7 +338,11 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *p
 #define pte_clear(mm,addr,ptep)                \
        set_pte_at((mm), (addr), (ptep), __pte(0UL))
 
-extern pgd_t swapper_pg_dir[1];
+extern pgd_t swapper_pg_dir[2048];
+extern pmd_t swapper_low_pmd_dir[2048];
+
+extern void paging_init(void);
+extern unsigned long find_ecache_flush_span(unsigned long size);
 
 /* These do nothing with the way I have things setup. */
 #define mmu_lockarea(vaddr, len)               (vaddr)
index 80a65d7e3dbff92308d2b4e1bf5e394e45c97551..203e8eee63515db1fa9a7dd5ed998aacfe99b460 100644 (file)
@@ -70,26 +70,14 @@ static inline int access_ok(int type, const void __user * addr, unsigned long si
  * with the main instruction path.  This means when everything is well,
  * we don't even have to jump over them.  Further, they do not intrude
  * on our cache or tlb entries.
- *
- * There is a special way how to put a range of potentially faulting
- * insns (like twenty ldd/std's with now intervening other instructions)
- * You specify address of first in insn and 0 in fixup and in the next
- * exception_table_entry you specify last potentially faulting insn + 1
- * and in fixup the routine which should handle the fault.
- * That fixup code will get
- * (faulting_insn_address - first_insn_in_the_range_address)/4
- * in %g2 (ie. index of the faulting instruction in the range).
  */
 
-struct exception_table_entry
-{
-        unsigned insn, fixup;
+struct exception_table_entry {
+        unsigned int insn, fixup;
 };
 
-/* Special exable search, which handles ranges.  Returns fixup */
-unsigned long search_extables_range(unsigned long addr, unsigned long *g2);
-
 extern void __ret_efault(void);
+extern void __retl_efault(void);
 
 /* Uh, these should become the main single-value transfer routines..
  * They automatically use the right size if we just have the right
@@ -263,7 +251,7 @@ copy_from_user(void *to, const void __user *from, unsigned long size)
 {
        unsigned long ret = ___copy_from_user(to, from, size);
 
-       if (ret)
+       if (unlikely(ret))
                ret = copy_from_user_fixup(to, from, size);
        return ret;
 }
@@ -279,7 +267,7 @@ copy_to_user(void __user *to, const void *from, unsigned long size)
 {
        unsigned long ret = ___copy_to_user(to, from, size);
 
-       if (ret)
+       if (unlikely(ret))
                ret = copy_to_user_fixup(to, from, size);
        return ret;
 }
@@ -295,7 +283,7 @@ copy_in_user(void __user *to, void __user *from, unsigned long size)
 {
        unsigned long ret = ___copy_in_user(to, from, size);
 
-       if (ret)
+       if (unlikely(ret))
                ret = copy_in_user_fixup(to, from, size);
        return ret;
 }
index 801710d00a404ec6dd175714a9e074789ffe158e..2ee028b8de9df8f74edeb1c67b1f4375c3ae82b1 100644 (file)
@@ -44,7 +44,7 @@
         const __typeof__(ptr) __private_ptr = ptr; \
         __typeof__(*(__private_ptr)) __private_val; \
         int __private_ret = -EFAULT; \
-        (x) = 0; \
+        (x) = (__typeof__(*(__private_ptr)))0; \
        if (__copy_from_user(&__private_val, (__private_ptr), \
            sizeof(*(__private_ptr))) == 0) {\
                (x) = (__typeof__(*(__private_ptr))) __private_val; \
index 4d727f3f5550bb2eadba0a20829bbf96ff970050..5a7fe3c6c3d8427c51e3bbf8daf54c81a4ec05dc 100644 (file)
@@ -234,6 +234,7 @@ static inline unsigned int cpuid_edx(unsigned int op)
 #define MSR_K8_TOP_MEM1                   0xC001001A
 #define MSR_K8_TOP_MEM2                   0xC001001D
 #define MSR_K8_SYSCFG             0xC0010010
+#define MSR_K8_HWCR               0xC0010015
 
 /* K6 MSRs */
 #define MSR_K6_EFER                    0xC0000080
index 2cb483516459dd3efb48fa48269b66c3beb8d072..dd8711ecaf2ff71cf1bf0c6fd14d3ba690849465 100644 (file)
@@ -384,7 +384,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 }
 
 #define pte_index(address) \
-               ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+               (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \
                        pte_index(address))
 
index a4d5af907f900da1183e40fa0d9c452c1dbf85d6..60def658b2462f3282c9802a6241b67c3b441b65 100644 (file)
@@ -43,6 +43,40 @@ struct kioctx;
 #define kiocbIsKicked(iocb)    test_bit(KIF_KICKED, &(iocb)->ki_flags)
 #define kiocbIsCancelled(iocb) test_bit(KIF_CANCELLED, &(iocb)->ki_flags)
 
+/* is there a better place to document function pointer methods? */
+/**
+ * ki_retry    -       iocb forward progress callback
+ * @kiocb:     The kiocb struct to advance by performing an operation.
+ *
+ * This callback is called when the AIO core wants a given AIO operation
+ * to make forward progress.  The kiocb argument describes the operation
+ * that is to be performed.  As the operation proceeds, perhaps partially,
+ * ki_retry is expected to update the kiocb with progress made.  Typically
+ * ki_retry is set in the AIO core and it itself calls file_operations
+ * helpers.
+ *
+ * ki_retry's return value determines when the AIO operation is completed
+ * and an event is generated in the AIO event ring.  Except the special
+ * return values described below, the value that is returned from ki_retry
+ * is transferred directly into the completion ring as the operation's
+ * resulting status.  Once this has happened ki_retry *MUST NOT* reference
+ * the kiocb pointer again.
+ *
+ * If ki_retry returns -EIOCBQUEUED it has made a promise that aio_complete()
+ * will be called on the kiocb pointer in the future.  The AIO core will
+ * not ask the method again -- ki_retry must ensure forward progress.
+ * aio_complete() must be called once and only once in the future, multiple
+ * calls may result in undefined behaviour.
+ *
+ * If ki_retry returns -EIOCBRETRY it has made a promise that kick_iocb()
+ * will be called on the kiocb pointer in the future.  This may happen
+ * through generic helpers that associate kiocb->ki_wait with a wait
+ * queue head that ki_retry uses via current->io_wait.  It can also happen
+ * with custom tracking and manual calls to kick_iocb(), though that is
+ * discouraged.  In either case, kick_iocb() must be called once and only
+ * once.  ki_retry must ensure forward progress, the AIO core will wait
+ * indefinitely for kick_iocb() to be called.
+ */
 struct kiocb {
        struct list_head        ki_run_list;
        long                    ki_flags;
index a5b74efab0679ae2a1f17dd6329596bf89c531ea..ecb7346d0c166cb9185664886925d9bf4150e239 100644 (file)
@@ -132,6 +132,7 @@ enum {
        ATA_CMD_PACKET          = 0xA0,
        ATA_CMD_VERIFY          = 0x40,
        ATA_CMD_VERIFY_EXT      = 0x42,
+       ATA_CMD_INIT_DEV_PARAMS = 0x91,
 
        /* SETFEATURES stuff */
        SETFEATURES_XFER        = 0x03,
@@ -146,14 +147,14 @@ enum {
        XFER_MW_DMA_2           = 0x22,
        XFER_MW_DMA_1           = 0x21,
        XFER_MW_DMA_0           = 0x20,
+       XFER_SW_DMA_2           = 0x12,
+       XFER_SW_DMA_1           = 0x11,
+       XFER_SW_DMA_0           = 0x10,
        XFER_PIO_4              = 0x0C,
        XFER_PIO_3              = 0x0B,
        XFER_PIO_2              = 0x0A,
        XFER_PIO_1              = 0x09,
        XFER_PIO_0              = 0x08,
-       XFER_SW_DMA_2           = 0x12,
-       XFER_SW_DMA_1           = 0x11,
-       XFER_SW_DMA_0           = 0x10,
        XFER_PIO_SLOW           = 0x00,
 
        /* ATAPI stuff */
@@ -181,6 +182,7 @@ enum {
        ATA_TFLAG_ISADDR        = (1 << 1), /* enable r/w to nsect/lba regs */
        ATA_TFLAG_DEVICE        = (1 << 2), /* enable r/w to device reg */
        ATA_TFLAG_WRITE         = (1 << 3), /* data dir: host->dev==1 (write) */
+       ATA_TFLAG_LBA           = (1 << 4), /* enable LBA */
 };
 
 enum ata_tf_protocols {
@@ -250,6 +252,18 @@ struct ata_taskfile {
          ((u64) (id)[(n) + 1] << 16) | \
          ((u64) (id)[(n) + 0]) )
 
+static inline int ata_id_current_chs_valid(u16 *id)
+{
+       /* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command 
+          has not been issued to the device then the values of 
+          id[54] to id[56] are vendor specific. */
+       return (id[53] & 0x01) && /* Current translation valid */
+               id[54] &&  /* cylinders in current translation */
+               id[55] &&  /* heads in current translation */
+               id[55] <= 16 &&
+               id[56];    /* sectors in current translation */
+}
+
 static inline int atapi_cdb_len(u16 *dev_id)
 {
        u16 tmp = dev_id[0] & 0x3;
index 96de26301f84babb622cce291e9d56b19a49db1e..86d4b0a81713733bb1cbb137d6dd2861ddd58623 100644 (file)
@@ -104,12 +104,19 @@ struct cn_queue_dev {
        struct sock *nls;
 };
 
-struct cn_callback {
+struct cn_callback_id {
        unsigned char name[CN_CBQ_NAMELEN];
-
        struct cb_id id;
+};
+
+struct cn_callback_data {
+       void (*destruct_data) (void *);
+       void *ddata;
+       
+       void *callback_priv;
        void (*callback) (void *);
-       void *priv;
+
+       void *free;
 };
 
 struct cn_callback_entry {
@@ -118,8 +125,8 @@ struct cn_callback_entry {
        struct work_struct work;
        struct cn_queue_dev *pdev;
 
-       void (*destruct_data) (void *);
-       void *ddata;
+       struct cn_callback_id id;
+       struct cn_callback_data data;
 
        int seq, group;
        struct sock *nls;
@@ -144,7 +151,7 @@ int cn_add_callback(struct cb_id *, char *, void (*callback) (void *));
 void cn_del_callback(struct cb_id *);
 int cn_netlink_send(struct cn_msg *, u32, int);
 
-int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb);
+int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *));
 void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id);
 
 struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *);
@@ -152,6 +159,8 @@ void cn_queue_free_dev(struct cn_queue_dev *dev);
 
 int cn_cb_equal(struct cb_id *, struct cb_id *);
 
+void cn_queue_wrapper(void *data);
+
 extern int cn_already_initialized;
 
 #endif                         /* __KERNEL__ */
index fc2d4c8225aa80d0429572594d26c87a8a5f9425..d21c305c6c64cec22a264fd6cb8f6ae6fb22e784 100644 (file)
@@ -111,7 +111,9 @@ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
        return (struct ethhdr *)skb->mac.raw;
 }
 
+#ifdef CONFIG_SYSCTL
 extern struct ctl_table ether_table[];
 #endif
+#endif
 
 #endif /* _LINUX_IF_ETHER_H */
index cc326174a80886d8c6aba40e11055455de84a60f..918c34a8347e6eb2b33624026f28d0a36bf77476 100644 (file)
@@ -42,11 +42,14 @@ struct keyring_list {
 /*
  * check to see whether permission is granted to use a key in the desired way
  */
-static inline int key_permission(const struct key *key, key_perm_t perm)
+static inline int key_permission(const key_ref_t key_ref, key_perm_t perm)
 {
+       struct key *key = key_ref_to_ptr(key_ref);
        key_perm_t kperm;
 
-       if (key->uid == current->fsuid)
+       if (is_key_possessed(key_ref))
+               kperm = key->perm >> 24;
+       else if (key->uid == current->fsuid)
                kperm = key->perm >> 16;
        else if (key->gid != -1 &&
                 key->perm & KEY_GRP_ALL &&
@@ -65,11 +68,14 @@ static inline int key_permission(const struct key *key, key_perm_t perm)
  * check to see whether permission is granted to use a key in at least one of
  * the desired ways
  */
-static inline int key_any_permission(const struct key *key, key_perm_t perm)
+static inline int key_any_permission(const key_ref_t key_ref, key_perm_t perm)
 {
+       struct key *key = key_ref_to_ptr(key_ref);
        key_perm_t kperm;
 
-       if (key->uid == current->fsuid)
+       if (is_key_possessed(key_ref))
+               kperm = key->perm >> 24;
+       else if (key->uid == current->fsuid)
                kperm = key->perm >> 16;
        else if (key->gid != -1 &&
                 key->perm & KEY_GRP_ALL &&
@@ -94,13 +100,17 @@ static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid)
        return ret;
 }
 
-static inline int key_task_permission(const struct key *key,
+static inline int key_task_permission(const key_ref_t key_ref,
                                      struct task_struct *context,
                                      key_perm_t perm)
 {
+       struct key *key = key_ref_to_ptr(key_ref);
        key_perm_t kperm;
 
-       if (key->uid == context->fsuid) {
+       if (is_key_possessed(key_ref)) {
+               kperm = key->perm >> 24;
+       }
+       else if (key->uid == context->fsuid) {
                kperm = key->perm >> 16;
        }
        else if (key->gid != -1 &&
@@ -121,9 +131,9 @@ static inline int key_task_permission(const struct key *key,
 
 }
 
-extern struct key *lookup_user_key(struct task_struct *context,
-                                  key_serial_t id, int create, int partial,
-                                  key_perm_t perm);
+extern key_ref_t lookup_user_key(struct task_struct *context,
+                                key_serial_t id, int create, int partial,
+                                key_perm_t perm);
 
 extern long join_session_keyring(const char *name);
 
index 970bbd916cf44a4b32bf5b1ea0005483b1f52c32..f1efa016dbf3c61aa37f8d97cf42ea1185155890 100644 (file)
@@ -35,11 +35,18 @@ struct key;
 
 #undef KEY_DEBUGGING
 
-#define KEY_USR_VIEW   0x00010000      /* user can view a key's attributes */
-#define KEY_USR_READ   0x00020000      /* user can read key payload / view keyring */
-#define KEY_USR_WRITE  0x00040000      /* user can update key payload / add link to keyring */
-#define KEY_USR_SEARCH 0x00080000      /* user can find a key in search / search a keyring */
-#define KEY_USR_LINK   0x00100000      /* user can create a link to a key/keyring */
+#define KEY_POS_VIEW   0x01000000      /* possessor can view a key's attributes */
+#define KEY_POS_READ   0x02000000      /* possessor can read key payload / view keyring */
+#define KEY_POS_WRITE  0x04000000      /* possessor can update key payload / add link to keyring */
+#define KEY_POS_SEARCH 0x08000000      /* possessor can find a key in search / search a keyring */
+#define KEY_POS_LINK   0x10000000      /* possessor can create a link to a key/keyring */
+#define KEY_POS_ALL    0x1f000000
+
+#define KEY_USR_VIEW   0x00010000      /* user permissions... */
+#define KEY_USR_READ   0x00020000
+#define KEY_USR_WRITE  0x00040000
+#define KEY_USR_SEARCH 0x00080000
+#define KEY_USR_LINK   0x00100000
 #define KEY_USR_ALL    0x001f0000
 
 #define KEY_GRP_VIEW   0x00000100      /* group permissions... */
@@ -65,6 +72,38 @@ struct key_owner;
 struct keyring_list;
 struct keyring_name;
 
+/*****************************************************************************/
+/*
+ * key reference with possession attribute handling
+ *
+ * NOTE! key_ref_t is a typedef'd pointer to a type that is not actually
+ * defined. This is because we abuse the bottom bit of the reference to carry a
+ * flag to indicate whether the calling process possesses that key in one of
+ * its keyrings.
+ *
+ * the key_ref_t has been made a separate type so that the compiler can reject
+ * attempts to dereference it without proper conversion.
+ *
+ * the three functions are used to assemble and disassemble references
+ */
+typedef struct __key_reference_with_attributes *key_ref_t;
+
+static inline key_ref_t make_key_ref(const struct key *key,
+                                    unsigned long possession)
+{
+       return (key_ref_t) ((unsigned long) key | possession);
+}
+
+static inline struct key *key_ref_to_ptr(const key_ref_t key_ref)
+{
+       return (struct key *) ((unsigned long) key_ref & ~1UL);
+}
+
+static inline unsigned long is_key_possessed(const key_ref_t key_ref)
+{
+       return (unsigned long) key_ref & 1UL;
+}
+
 /*****************************************************************************/
 /*
  * authentication token / access credential / keyring
@@ -215,20 +254,25 @@ static inline struct key *key_get(struct key *key)
        return key;
 }
 
+static inline void key_ref_put(key_ref_t key_ref)
+{
+       key_put(key_ref_to_ptr(key_ref));
+}
+
 extern struct key *request_key(struct key_type *type,
                               const char *description,
                               const char *callout_info);
 
 extern int key_validate(struct key *key);
 
-extern struct key *key_create_or_update(struct key *keyring,
-                                       const char *type,
-                                       const char *description,
-                                       const void *payload,
-                                       size_t plen,
-                                       int not_in_quota);
+extern key_ref_t key_create_or_update(key_ref_t keyring,
+                                     const char *type,
+                                     const char *description,
+                                     const void *payload,
+                                     size_t plen,
+                                     int not_in_quota);
 
-extern int key_update(struct key *key,
+extern int key_update(key_ref_t key,
                      const void *payload,
                      size_t plen);
 
@@ -243,9 +287,9 @@ extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
 
 extern int keyring_clear(struct key *keyring);
 
-extern struct key *keyring_search(struct key *keyring,
-                                 struct key_type *type,
-                                 const char *description);
+extern key_ref_t keyring_search(key_ref_t keyring,
+                               struct key_type *type,
+                               const char *description);
 
 extern int keyring_add_key(struct key *keyring,
                           struct key *key);
@@ -285,6 +329,10 @@ extern void key_init(void);
 #define key_serial(k)                  0
 #define key_get(k)                     ({ NULL; })
 #define key_put(k)                     do { } while(0)
+#define key_ref_put(k)                 do { } while(0)
+#define make_key_ref(k)                        ({ NULL; })
+#define key_ref_to_ptr(k)              ({ NULL; })
+#define is_key_possessed(k)            0
 #define alloc_uid_keyring(u)           0
 #define switch_uid_keyring(u)          do { } while(0)
 #define __install_session_keyring(t, k)        ({ NULL; })
index ceee1fc42c600d0aa0d045edb37db8c253fec457..4d45179872cccc591e18bbe40c469e67480bef8f 100644 (file)
@@ -97,6 +97,7 @@ enum {
        ATA_DFLAG_LBA48         = (1 << 0), /* device supports LBA48 */
        ATA_DFLAG_PIO           = (1 << 1), /* device currently in PIO mode */
        ATA_DFLAG_LOCK_SECTORS  = (1 << 2), /* don't adjust max_sectors */
+       ATA_DFLAG_LBA           = (1 << 3), /* device supports LBA */
 
        ATA_DEV_UNKNOWN         = 0,    /* unknown device */
        ATA_DEV_ATA             = 1,    /* ATA device */
@@ -154,17 +155,21 @@ enum {
        ATA_SHIFT_UDMA          = 0,
        ATA_SHIFT_MWDMA         = 8,
        ATA_SHIFT_PIO           = 11,
+       
+       /* Masks for port functions */
+       ATA_PORT_PRIMARY        = (1 << 0),
+       ATA_PORT_SECONDARY      = (1 << 1),
 };
 
-enum pio_task_states {
-       PIO_ST_UNKNOWN,
-       PIO_ST_IDLE,
-       PIO_ST_POLL,
-       PIO_ST_TMOUT,
-       PIO_ST,
-       PIO_ST_LAST,
-       PIO_ST_LAST_POLL,
-       PIO_ST_ERR,
+enum hsm_task_states {
+       HSM_ST_UNKNOWN,
+       HSM_ST_IDLE,
+       HSM_ST_POLL,
+       HSM_ST_TMOUT,
+       HSM_ST,
+       HSM_ST_LAST,
+       HSM_ST_LAST_POLL,
+       HSM_ST_ERR,
 };
 
 /* forward declarations */
@@ -282,6 +287,11 @@ struct ata_device {
        u8                      xfer_protocol;  /* taskfile xfer protocol */
        u8                      read_cmd;       /* opcode to use on read */
        u8                      write_cmd;      /* opcode to use on write */
+
+       /* for CHS addressing */
+       u16                     cylinders;      /* Number of cylinders */
+       u16                     heads;          /* Number of heads */
+       u16                     sectors;        /* Number of sectors per track */
 };
 
 struct ata_port {
@@ -319,7 +329,7 @@ struct ata_port {
        struct work_struct      packet_task;
 
        struct work_struct      pio_task;
-       unsigned int            pio_task_state;
+       unsigned int            hsm_task_state;
        unsigned long           pio_task_timeout;
 
        void                    *private_data;
@@ -452,7 +462,7 @@ struct pci_bits {
 
 extern void ata_pci_host_stop (struct ata_host_set *host_set);
 extern struct ata_probe_ent *
-ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int portmask);
 extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
 
 #endif /* CONFIG_PCI */
index 47da39ba3f0377f378556150daed3d5530a49849..2f0299a448f68687e0bf430c3f531f07fbe029d2 100644 (file)
@@ -183,7 +183,7 @@ struct of_device_id
        char    name[32];
        char    type[32];
        char    compatible[128];
-#if __KERNEL__
+#ifdef __KERNEL__
        void    *data;
 #else
        kernel_ulong_t data;
@@ -209,10 +209,11 @@ struct pcmcia_device_id {
        /* for real multi-function devices */
        __u8            function;
 
-       /* for pseude multi-function devices */
+       /* for pseudo multi-function devices */
        __u8            device_no;
 
-       __u32           prod_id_hash[4];
+       __u32           prod_id_hash[4]
+               __attribute__((aligned(sizeof(__u32))));
 
        /* not matched against in kernelspace*/
 #ifdef __KERNEL__
index 7c717907896d1d5de04ac4028f70a0ff83b8bb13..368e4c825ff1b5006adfe8a962083500a6776e0c 100644 (file)
@@ -265,6 +265,8 @@ struct net_device
         * the interface.
         */
        char                    name[IFNAMSIZ];
+       /* device name hash chain */
+       struct hlist_node       name_hlist;
 
        /*
         *      I/O specific fields
@@ -292,6 +294,21 @@ struct net_device
 
        /* ------- Fields preinitialized in Space.c finish here ------- */
 
+       /* Net device features */
+       unsigned long           features;
+#define NETIF_F_SG             1       /* Scatter/gather IO. */
+#define NETIF_F_IP_CSUM                2       /* Can checksum only TCP/UDP over IPv4. */
+#define NETIF_F_NO_CSUM                4       /* Does not require checksum. F.e. loopack. */
+#define NETIF_F_HW_CSUM                8       /* Can checksum all the packets. */
+#define NETIF_F_HIGHDMA                32      /* Can DMA to high memory. */
+#define NETIF_F_FRAGLIST       64      /* Scatter/gather IO. */
+#define NETIF_F_HW_VLAN_TX     128     /* Transmit VLAN hw acceleration */
+#define NETIF_F_HW_VLAN_RX     256     /* Receive VLAN hw acceleration */
+#define NETIF_F_HW_VLAN_FILTER 512     /* Receive filtering on VLAN */
+#define NETIF_F_VLAN_CHALLENGED        1024    /* Device cannot handle VLAN packets */
+#define NETIF_F_TSO            2048    /* Can offload TCP/IP segmentation */
+#define NETIF_F_LLTX           4096    /* LockLess TX */
+
        struct net_device       *next_sched;
 
        /* Interface index. Unique device identifier    */
@@ -316,9 +333,6 @@ struct net_device
         * will (read: may be cleaned up at will).
         */
 
-       /* These may be needed for future network-power-down code. */
-       unsigned long           trans_start;    /* Time (in jiffies) of last Tx */
-       unsigned long           last_rx;        /* Time of last Rx      */
 
        unsigned short          flags;  /* interface flags (a la BSD)   */
        unsigned short          gflags;
@@ -328,15 +342,12 @@ struct net_device
        unsigned                mtu;    /* interface MTU value          */
        unsigned short          type;   /* interface hardware type      */
        unsigned short          hard_header_len;        /* hardware hdr length  */
-       void                    *priv;  /* pointer to private data      */
 
        struct net_device       *master; /* Pointer to master device of a group,
                                          * which this device is member of.
                                          */
 
        /* Interface address info. */
-       unsigned char           broadcast[MAX_ADDR_LEN];        /* hw bcast add */
-       unsigned char           dev_addr[MAX_ADDR_LEN]; /* hw address   */
        unsigned char           perm_addr[MAX_ADDR_LEN]; /* permanent hw address */
        unsigned char           addr_len;       /* hardware address length      */
        unsigned short          dev_id;         /* for shared network cards */
@@ -346,8 +357,6 @@ struct net_device
        int                     promiscuity;
        int                     allmulti;
 
-       int                     watchdog_timeo;
-       struct timer_list       watchdog_timer;
 
        /* Protocol specific pointers */
        
@@ -358,32 +367,62 @@ struct net_device
        void                    *ec_ptr;        /* Econet specific data */
        void                    *ax25_ptr;      /* AX.25 specific data */
 
-       struct list_head        poll_list;      /* Link to poll list    */
+/*
+ * Cache line mostly used on receive path (including eth_type_trans())
+ */
+       struct list_head        poll_list ____cacheline_aligned_in_smp;
+                                       /* Link to poll list    */
+
+       int                     (*poll) (struct net_device *dev, int *quota);
        int                     quota;
        int                     weight;
+       unsigned long           last_rx;        /* Time of last Rx      */
+       /* Interface address info used in eth_type_trans() */
+       unsigned char           dev_addr[MAX_ADDR_LEN]; /* hw address, (before bcast 
+                                                       because most packets are unicast) */
+
+       unsigned char           broadcast[MAX_ADDR_LEN];        /* hw bcast add */
 
+/*
+ * Cache line mostly used on queue transmit path (qdisc)
+ */
+       /* device queue lock */
+       spinlock_t              queue_lock ____cacheline_aligned_in_smp;
        struct Qdisc            *qdisc;
        struct Qdisc            *qdisc_sleeping;
-       struct Qdisc            *qdisc_ingress;
        struct list_head        qdisc_list;
        unsigned long           tx_queue_len;   /* Max frames per queue allowed */
 
        /* ingress path synchronizer */
        spinlock_t              ingress_lock;
+       struct Qdisc            *qdisc_ingress;
+
+/*
+ * One part is mostly used on xmit path (device)
+ */
        /* hard_start_xmit synchronizer */
-       spinlock_t              xmit_lock;
+       spinlock_t              xmit_lock ____cacheline_aligned_in_smp;
        /* cpu id of processor entered to hard_start_xmit or -1,
           if nobody entered there.
         */
        int                     xmit_lock_owner;
-       /* device queue lock */
-       spinlock_t              queue_lock;
+       void                    *priv;  /* pointer to private data      */
+       int                     (*hard_start_xmit) (struct sk_buff *skb,
+                                                   struct net_device *dev);
+       /* These may be needed for future network-power-down code. */
+       unsigned long           trans_start;    /* Time (in jiffies) of last Tx */
+
+       int                     watchdog_timeo; /* used by dev_watchdog() */
+       struct timer_list       watchdog_timer;
+
+/*
+ * refcnt is a very hot point, so align it on SMP
+ */
        /* Number of references to this device */
-       atomic_t                refcnt;
+       atomic_t                refcnt ____cacheline_aligned_in_smp;
+
        /* delayed register/unregister */
        struct list_head        todo_list;
-       /* device name hash chain */
-       struct hlist_node       name_hlist;
        /* device index hash chain */
        struct hlist_node       index_hlist;
 
@@ -396,21 +435,6 @@ struct net_device
               NETREG_RELEASED,         /* called free_netdev */
        } reg_state;
 
-       /* Net device features */
-       unsigned long           features;
-#define NETIF_F_SG             1       /* Scatter/gather IO. */
-#define NETIF_F_IP_CSUM                2       /* Can checksum only TCP/UDP over IPv4. */
-#define NETIF_F_NO_CSUM                4       /* Does not require checksum. F.e. loopack. */
-#define NETIF_F_HW_CSUM                8       /* Can checksum all the packets. */
-#define NETIF_F_HIGHDMA                32      /* Can DMA to high memory. */
-#define NETIF_F_FRAGLIST       64      /* Scatter/gather IO. */
-#define NETIF_F_HW_VLAN_TX     128     /* Transmit VLAN hw acceleration */
-#define NETIF_F_HW_VLAN_RX     256     /* Receive VLAN hw acceleration */
-#define NETIF_F_HW_VLAN_FILTER 512     /* Receive filtering on VLAN */
-#define NETIF_F_VLAN_CHALLENGED        1024    /* Device cannot handle VLAN packets */
-#define NETIF_F_TSO            2048    /* Can offload TCP/IP segmentation */
-#define NETIF_F_LLTX           4096    /* LockLess TX */
-
        /* Called after device is detached from network. */
        void                    (*uninit)(struct net_device *dev);
        /* Called after last user reference disappears. */
@@ -419,10 +443,7 @@ struct net_device
        /* Pointers to interface service routines.      */
        int                     (*open)(struct net_device *dev);
        int                     (*stop)(struct net_device *dev);
-       int                     (*hard_start_xmit) (struct sk_buff *skb,
-                                                   struct net_device *dev);
 #define HAVE_NETDEV_POLL
-       int                     (*poll) (struct net_device *dev, int *quota);
        int                     (*hard_header) (struct sk_buff *skb,
                                                struct net_device *dev,
                                                unsigned short type,
index 3b50eb91f007c8157036df8e5fdaf8782e7be037..30db23f06b0371784a338928be973aaf6b1aba1c 100644 (file)
@@ -5,16 +5,14 @@
 
 /* This header used to share core functionality between the standalone
    NAT module, and the compatibility layer's use of NAT for masquerading. */
-extern int ip_nat_init(void);
-extern void ip_nat_cleanup(void);
 
-extern unsigned int nat_packet(struct ip_conntrack *ct,
+extern unsigned int ip_nat_packet(struct ip_conntrack *ct,
                               enum ip_conntrack_info conntrackinfo,
                               unsigned int hooknum,
                               struct sk_buff **pskb);
 
-extern int icmp_reply_translation(struct sk_buff **pskb,
-                                 struct ip_conntrack *ct,
-                                 enum ip_nat_manip_type manip,
-                                 enum ip_conntrack_dir dir);
+extern int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
+                                        struct ip_conntrack *ct,
+                                        enum ip_nat_manip_type manip,
+                                        enum ip_conntrack_dir dir);
 #endif /* _IP_NAT_CORE_H */
index b86a4b77007ef05108637f959695cd52eaa304e0..eb36fd293b4191e200138c106f5c12c64b9c19f2 100644 (file)
 #define PCI_DEVICE_ID_NS_87560_USB     0x0012
 #define PCI_DEVICE_ID_NS_83815         0x0020
 #define PCI_DEVICE_ID_NS_83820         0x0022
+#define PCI_DEVICE_ID_NS_SATURN                0x0035
 #define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500
 #define PCI_DEVICE_ID_NS_SCx200_SMI    0x0501
 #define PCI_DEVICE_ID_NS_SCx200_IDE    0x0502
 #define PCI_DEVICE_ID_TI_TVP4010       0x3d04
 #define PCI_DEVICE_ID_TI_TVP4020       0x3d07
 #define PCI_DEVICE_ID_TI_4450          0x8011
+#define PCI_DEVICE_ID_TI_XX21_XX11     0x8031
+#define PCI_DEVICE_ID_TI_X515          0x8036
 #define PCI_DEVICE_ID_TI_1130          0xac12
 #define PCI_DEVICE_ID_TI_1031          0xac13
 #define PCI_DEVICE_ID_TI_1131          0xac15
 #define PCI_DEVICE_ID_TI_4451          0xac42
 #define PCI_DEVICE_ID_TI_4510          0xac44
 #define PCI_DEVICE_ID_TI_4520          0xac46
+#define PCI_DEVICE_ID_TI_7510          0xac47
+#define PCI_DEVICE_ID_TI_7610          0xac48
+#define PCI_DEVICE_ID_TI_7410          0xac49
 #define PCI_DEVICE_ID_TI_1410          0xac50
 #define PCI_DEVICE_ID_TI_1420          0xac51
 #define PCI_DEVICE_ID_TI_1451A         0xac52
 #define PCI_DEVICE_ID_TI_1620          0xac54
 #define PCI_DEVICE_ID_TI_1520          0xac55
 #define PCI_DEVICE_ID_TI_1510          0xac56
+#define PCI_DEVICE_ID_TI_X620          0xac8d
+#define PCI_DEVICE_ID_TI_X420          0xac8e
 
 #define PCI_VENDOR_ID_SONY             0x104d
 #define PCI_DEVICE_ID_SONY_CXD3222     0x8039
 #define PCI_DEVICE_ID_SUN_SABRE                0xa000
 #define PCI_DEVICE_ID_SUN_HUMMINGBIRD  0xa001
 #define PCI_DEVICE_ID_SUN_TOMATILLO    0xa801
+#define PCI_DEVICE_ID_SUN_CASSINI      0xabba
 
 #define PCI_VENDOR_ID_CMD              0x1095
 #define PCI_DEVICE_ID_CMD_640          0x0640
 #define PCI_DEVICE_ID_ENE_1211         0x1211
 #define PCI_DEVICE_ID_ENE_1225         0x1225
 #define PCI_DEVICE_ID_ENE_1410         0x1410
+#define PCI_DEVICE_ID_ENE_710          0x1411
+#define PCI_DEVICE_ID_ENE_712          0x1412
 #define PCI_DEVICE_ID_ENE_1420         0x1420
+#define PCI_DEVICE_ID_ENE_720          0x1421
+#define PCI_DEVICE_ID_ENE_722          0x1422
+
 #define PCI_VENDOR_ID_CHELSIO          0x1425
 
 #define PCI_VENDOR_ID_MIPS             0x153f
index 49e617fa0f662a10a04980ed0f2b3997a1adc0d0..c3ba31f210a963a466d22d50d3fd5a42b03e15d4 100644 (file)
@@ -107,13 +107,25 @@ extern unsigned long nr_iowait(void);
 
 #include <asm/processor.h>
 
+/*
+ * Task state bitmask. NOTE! These bits are also
+ * encoded in fs/proc/array.c: get_task_state().
+ *
+ * We have two separate sets of flags: task->state
+ * is about runnability, while task->exit_state are
+ * about the task exiting. Confusing, but this way
+ * modifying one set can't modify the other one by
+ * mistake.
+ */
 #define TASK_RUNNING           0
 #define TASK_INTERRUPTIBLE     1
 #define TASK_UNINTERRUPTIBLE   2
 #define TASK_STOPPED           4
 #define TASK_TRACED            8
+/* in tsk->exit_state */
 #define EXIT_ZOMBIE            16
 #define EXIT_DEAD              32
+/* in tsk->state again */
 #define TASK_NONINTERACTIVE    64
 
 #define __set_task_state(tsk, state_value)             \
index 3a29a9f9b451d7f3b0e6135ff7d4fcc0fa886027..fc8e367f671e11bccc88faccb6247ce0017e5009 100644 (file)
@@ -202,7 +202,8 @@ enum
        NET_TR=14,
        NET_DECNET=15,
        NET_ECONET=16,
-       NET_SCTP=17, 
+       NET_SCTP=17,
+       NET_LLC=18,
 };
 
 /* /proc/sys/kernel/random */
@@ -522,6 +523,29 @@ enum {
        NET_IPX_FORWARDING=2
 };
 
+/* /proc/sys/net/llc */
+enum {
+       NET_LLC2=1,
+       NET_LLC_STATION=2,
+};
+
+/* /proc/sys/net/llc/llc2 */
+enum {
+       NET_LLC2_TIMEOUT=1,
+};
+
+/* /proc/sys/net/llc/station */
+enum {
+       NET_LLC_STATION_ACK_TIMEOUT=1,
+};
+
+/* /proc/sys/net/llc/llc2/timeout */
+enum {
+       NET_LLC2_ACK_TIMEOUT=1,
+       NET_LLC2_P_TIMEOUT=2,
+       NET_LLC2_REJ_TIMEOUT=3,
+       NET_LLC2_BUSY_TIMEOUT=4,
+};
 
 /* /proc/sys/net/appletalk */
 enum {
index 71769a5aeef3b929afd6b8dd0aa9fdab6f3c7f13..1adb2ef3f6f7b975cb1c59de626b70a17fa79f07 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 
+#include <asm/atomic.h>
+
 struct net_device;
 struct packet_type;
 struct sk_buff;
@@ -44,6 +46,7 @@ struct llc_sap {
        unsigned char    state;
        unsigned char    p_bit;
        unsigned char    f_bit;
+       atomic_t         refcnt;
        int              (*rcv_func)(struct sk_buff *skb,
                                     struct net_device *dev,
                                     struct packet_type *pt,
@@ -81,13 +84,27 @@ extern struct llc_sap *llc_sap_open(unsigned char lsap,
                                               struct net_device *dev,
                                               struct packet_type *pt,
                                               struct net_device *orig_dev));
+static inline void llc_sap_hold(struct llc_sap *sap)
+{
+       atomic_inc(&sap->refcnt);
+}
+
 extern void llc_sap_close(struct llc_sap *sap);
 
+static inline void llc_sap_put(struct llc_sap *sap)
+{
+       if (atomic_dec_and_test(&sap->refcnt))
+               llc_sap_close(sap);
+}
+
 extern struct llc_sap *llc_sap_find(unsigned char sap_value);
 
 extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
                                     unsigned char *dmac, unsigned char dsap);
 
+extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
+extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
+
 extern int llc_station_init(void);
 extern void llc_station_exit(void);
 
@@ -98,4 +115,17 @@ extern void llc_proc_exit(void);
 #define llc_proc_init()        (0)
 #define llc_proc_exit()        do { } while(0)
 #endif /* CONFIG_PROC_FS */
+#ifdef CONFIG_SYSCTL
+extern int llc_sysctl_init(void);
+extern void llc_sysctl_exit(void);
+
+extern int sysctl_llc2_ack_timeout;
+extern int sysctl_llc2_busy_timeout;
+extern int sysctl_llc2_p_timeout;
+extern int sysctl_llc2_rej_timeout;
+extern int sysctl_llc_station_ack_timeout;
+#else
+#define llc_sysctl_init() (0)
+#define llc_sysctl_exit() do { } while(0)
+#endif /* CONFIG_SYSCTL */
 #endif /* LLC_H */
index 8ad3bc2c23d78d16880623cb74cdc43f722f1263..54852ff6033bdf0c57cea25c0dc91ff3df468ed0 100644 (file)
 #define LLC_EVENT                1
 #define LLC_PACKET               2
 
-#define LLC_P_TIME               2
-#define LLC_ACK_TIME             1
-#define LLC_REJ_TIME             3
-#define LLC_BUSY_TIME            3
+#define LLC2_P_TIME               2
+#define LLC2_ACK_TIME             1
+#define LLC2_REJ_TIME             3
+#define LLC2_BUSY_TIME            3
 
 struct llc_timer {
        struct timer_list timer;
-       u16               expire;       /* timer expire time */
+       unsigned long     expire;       /* timer expire time */
 };
 
 struct llc_sock {
@@ -38,6 +38,7 @@ struct llc_sock {
        struct llc_addr     laddr;              /* lsap/mac pair */
        struct llc_addr     daddr;              /* dsap/mac pair */
        struct net_device   *dev;               /* device to send to remote */
+       u32                 copied_seq;         /* head of yet unread data */
        u8                  retry_count;        /* number of retries */
        u8                  ack_must_be_send;
        u8                  first_pdu_Ns;
@@ -92,7 +93,8 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb)
        return skb->cb[sizeof(skb->cb) - 1];
 }
 
-extern struct sock *llc_sk_alloc(int family, int priority, struct proto *prot);
+extern struct sock *llc_sk_alloc(int family, unsigned int __nocast priority,
+                                struct proto *prot);
 extern void llc_sk_free(struct sock *sk);
 
 extern void llc_sk_reset(struct sock *sk);
@@ -115,5 +117,4 @@ extern void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk);
 
 extern u8 llc_data_accept_state(u8 state);
 extern void llc_build_offset_table(void);
-extern int llc_release_sockets(struct llc_sap *sap);
 #endif /* LLC_CONN_H */
index 353baaa627f3b74f61c244c6a8d41102a7480b1c..2c56dbece7291ba1398dc5c5ce02ec3504e8f075 100644 (file)
  * See the GNU General Public License for more details.
  */
 struct llc_sap;
+struct net_device;
 struct sk_buff;
+struct sock;
 
 extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
-extern void llc_save_primitive(struct sk_buff* skb, unsigned char prim);
-extern struct sk_buff *llc_alloc_frame(void);
+extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb,
+                              unsigned char prim);
+extern struct sk_buff *llc_alloc_frame(struct sock *sk,
+                                      struct net_device *dev);
 
 extern void llc_build_and_send_test_pkt(struct llc_sap *sap,
                                        struct sk_buff *skb,
index 0f7aacc33fe95d68b24efefe69886e03679e9e34..c8592c7e8eaa5bc2bb90411d8f7fa5e8134bb854 100644 (file)
@@ -21,6 +21,9 @@
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/bulkmem.h>
+#ifdef CONFIG_CARDBUS
+#include <linux/pci.h>
+#endif
 
 /* Definitions for card status flags for GetStatus */
 #define SS_WRPROT      0x0001
@@ -233,7 +236,11 @@ struct pcmcia_socket {
 
        /* so is power hook */
        int (*power_hook)(struct pcmcia_socket *sock, int operation);
-                           
+#ifdef CONFIG_CARDBUS
+       /* allows tuning the CB bridge before loading driver for the CB card */
+       void (*tune_bridge)(struct pcmcia_socket *sock, struct pci_bus *bus);
+#endif
+
        /* state thread */
        struct semaphore                skt_sem;        /* protects socket h/w state */
 
index e16cf94870f263936fdcbef502739791a709f11d..e6f4c9e55df7b21d7ff0ccc6408b346594d314eb 100644 (file)
@@ -665,7 +665,6 @@ struct ib_ucontext {
        struct list_head        qp_list;
        struct list_head        srq_list;
        struct list_head        ah_list;
-       spinlock_t              lock;
 };
 
 struct ib_uobject {
index 3a926011507b8768ff9991b55837a3f7ee9f579e..a0f18c9cc89df5983b16afc41c610e66391f5a0b 100644 (file)
@@ -611,6 +611,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
                dentry->d_fsdata = &attr;
        }
 
+       mode &= ~current->fs->umask;
        ret = vfs_create(dir->d_inode, dentry, mode, NULL);
        dentry->d_fsdata = NULL;
        if (ret)
index 79866bc6b3a154d06c4b42daa3daec60aa96ebd9..45a5719a01047b2355a6eaffe4f1b75c3e22d915 100644 (file)
@@ -968,8 +968,6 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
        char *page;
        ssize_t retval = 0;
        char *s;
-       char *start;
-       size_t n;
 
        if (!(page = (char *)__get_free_page(GFP_KERNEL)))
                return -ENOMEM;
@@ -999,14 +997,7 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
        *s++ = '\n';
        *s = '\0';
 
-       /* Do nothing if *ppos is at the eof or beyond the eof. */
-       if (s - page <= *ppos)
-               return 0;
-
-       start = page + *ppos;
-       n = s - start;
-       retval = n - copy_to_user(buf, start, min(n, nbytes));
-       *ppos += retval;
+       retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page);
 out:
        free_page((unsigned long)page);
        return retval;
index ee6d8b8abef5454fc2e224fdfbdf12a332591c6e..43077732619beef843fd6170361b1f4d04691179 100644 (file)
@@ -1203,7 +1203,7 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap,
 
                exit_code = p->exit_code;
                if (unlikely(!exit_code) ||
-                   unlikely(p->state > TASK_STOPPED))
+                   unlikely(p->state & TASK_TRACED))
                        goto bail_ref;
                return wait_noreap_copyout(p, pid, uid,
                                           why, (exit_code << 8) | 0x7f,
index fbf173215fd217bed3db643ba0676916f7085daf..1a8614bac5d5c819110ae67bd21efca75845b600 100644 (file)
@@ -80,8 +80,6 @@ static char *next_arg(char *args, char **param, char **val)
        int in_quote = 0, quoted = 0;
        char *next;
 
-       /* Chew any extra spaces */
-       while (*args == ' ') args++;
        if (*args == '"') {
                args++;
                in_quote = 1;
@@ -121,6 +119,10 @@ static char *next_arg(char *args, char **param, char **val)
                next = args + i + 1;
        } else
                next = args + i;
+
+       /* Chew up trailing spaces. */
+       while (*next == ' ')
+               next++;
        return next;
 }
 
@@ -135,6 +137,10 @@ int parse_args(const char *name,
 
        DEBUGP("Parsing ARGS: %s\n", args);
 
+       /* Chew leading spaces */
+       while (*args == ' ')
+               args++;
+
        while (*args) {
                int ret;
 
index 9c9167d910ddb361b59857e3a318b94049d3031a..6748de23e83ce95f011061507e441ebb38a45498 100644 (file)
@@ -9,6 +9,9 @@
 #define SUSPEND_CONSOLE        (MAX_NR_CONSOLES-1)
 #endif
 
+#define MAX_PBES       ((PAGE_SIZE - sizeof(struct new_utsname) \
+                       - 4 - 3*sizeof(unsigned long) - sizeof(int) \
+                       - sizeof(void *)) / sizeof(swp_entry_t))
 
 struct swsusp_info {
        struct new_utsname      uts;
@@ -18,7 +21,7 @@ struct swsusp_info {
        unsigned long           image_pages;
        unsigned long           pagedir_pages;
        suspend_pagedir_t       * suspend_pagedir;
-       swp_entry_t             pagedir[768];
+       swp_entry_t             pagedir[MAX_PBES];
 } __attribute__((aligned(PAGE_SIZE)));
 
 
index 1cc9ff25e479a4b3cba533c8caedd9f8cf729d4e..acf79ac1cb6d5f13667916aac50fd81ddd3af04e 100644 (file)
@@ -402,15 +402,14 @@ static int write_page(unsigned long addr, swp_entry_t * loc)
 static void data_free(void)
 {
        swp_entry_t entry;
-       int i;
+       struct pbe * p;
 
-       for (i = 0; i < nr_copy_pages; i++) {
-               entry = (pagedir_nosave + i)->swap_address;
+       for_each_pbe(p, pagedir_nosave) {
+               entry = p->swap_address;
                if (entry.val)
                        swap_free(entry);
                else
                        break;
-               (pagedir_nosave + i)->swap_address = (swp_entry_t){0};
        }
 }
 
@@ -932,6 +931,10 @@ static int swsusp_alloc(void)
        if (!enough_swap())
                return -ENOSPC;
 
+       if (MAX_PBES < nr_copy_pages / PBES_PER_PAGE +
+           !!(nr_copy_pages % PBES_PER_PAGE))
+               return -ENOSPC;
+
        if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) {
                printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
                return -ENOMEM;
@@ -1438,9 +1441,9 @@ static int read_pagedir(struct pbe *pblist)
        }
 
        if (error)
-               free_page((unsigned long)pblist);
-
-       BUG_ON(i != swsusp_info.pagedir_pages);
+               free_pagedir(pblist);
+       else
+               BUG_ON(i != swsusp_info.pagedir_pages);
 
        return error;
 }
index 5a274705ba1945b8ec81100a139daec057fc696d..619b027e92b53ce02706a04f6e4524a6cc1135a8 100644 (file)
@@ -1763,7 +1763,8 @@ do_signal_stop(int signr)
                                 * stop is always done with the siglock held,
                                 * so this check has no races.
                                 */
-                               if (t->state < TASK_STOPPED) {
+                               if (!t->exit_state &&
+                                   !(t->state & (TASK_STOPPED|TASK_TRACED))) {
                                        stop_count++;
                                        signal_wake_up(t, 0);
                                }
index 8ec4e4c2a179f5fc1a8d7ddb648dad0d9f69cdbb..c1330cc197835ae66bffaa2baacc032ace0020b4 100644 (file)
@@ -61,17 +61,9 @@ static unsigned long __init init_bootmem_core (pg_data_t *pgdat,
 {
        bootmem_data_t *bdata = pgdat->bdata;
        unsigned long mapsize = ((end - start)+7)/8;
-       static struct pglist_data *pgdat_last;
-
-       pgdat->pgdat_next = NULL;
-       /* Add new nodes last so that bootmem always starts
-          searching in the first nodes, not the last ones */
-       if (pgdat_last)
-               pgdat_last->pgdat_next = pgdat;
-       else {
-               pgdat_list = pgdat;     
-               pgdat_last = pgdat;
-       }
+
+       pgdat->pgdat_next = pgdat_list;
+       pgdat_list = pgdat;
 
        mapsize = ALIGN(mapsize, sizeof(long));
        bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
index a32fed454bd7c60e15da0c720b1631b55a3f8835..f343fc73a8bdd7f0ecd68fb1674438033c85cc49 100644 (file)
@@ -141,10 +141,10 @@ move_one_page(struct vm_area_struct *vma, unsigned long old_addr,
                        if (dst) {
                                pte_t pte;
                                pte = ptep_clear_flush(vma, old_addr, src);
+
                                /* ZERO_PAGE can be dependant on virtual addr */
-                               if (pfn_valid(pte_pfn(pte)) &&
-                                       pte_page(pte) == ZERO_PAGE(old_addr))
-                                       pte = pte_wrprotect(mk_pte(ZERO_PAGE(new_addr), new_vma->vm_page_prot));
+                               pte = move_pte(pte, new_vma->vm_page_prot,
+                                                       old_addr, new_addr);
                                set_pte_at(mm, new_addr, dst, pte);
                        } else
                                error = -ENOMEM;
index c9adfce004056d2539ffa04a9ab09c1a2773d89d..5cbbdfa6dd0e75b0dbcffd490d1f6a75eb76f745 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2510,16 +2510,12 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep,
 #define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
 #endif
 
-
-static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags)
+static inline void *____cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags)
 {
-       unsigned long save_flags;
        void* objp;
        struct array_cache *ac;
 
-       cache_alloc_debugcheck_before(cachep, flags);
-
-       local_irq_save(save_flags);
+       check_irq_off();
        ac = ac_data(cachep);
        if (likely(ac->avail)) {
                STATS_INC_ALLOCHIT(cachep);
@@ -2529,6 +2525,18 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast fl
                STATS_INC_ALLOCMISS(cachep);
                objp = cache_alloc_refill(cachep, flags);
        }
+       return objp;
+}
+
+static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags)
+{
+       unsigned long save_flags;
+       void* objp;
+
+       cache_alloc_debugcheck_before(cachep, flags);
+
+       local_irq_save(save_flags);
+       objp = ____cache_alloc(cachep, flags);
        local_irq_restore(save_flags);
        objp = cache_alloc_debugcheck_after(cachep, flags, objp,
                                        __builtin_return_address(0));
@@ -2856,7 +2864,10 @@ void *kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int __nocast flags, i
 
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
-       ptr = __cache_alloc_node(cachep, flags, nodeid);
+       if (nodeid == numa_node_id())
+               ptr = ____cache_alloc(cachep, flags);
+       else
+               ptr = __cache_alloc_node(cachep, flags, nodeid);
        local_irq_restore(save_flags);
        ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, __builtin_return_address(0));
 
index b24817c63ca8e31459a7b2c87b43bb2b05726ec8..2530f35241cde096a08a748790d74b75f8b22884 100644 (file)
@@ -56,7 +56,7 @@ struct datalink_proto *register_8022_client(unsigned char type,
 
 void unregister_8022_client(struct datalink_proto *proto)
 {
-       llc_sap_close(proto->sap);
+       llc_sap_put(proto->sap);
        kfree(proto);
 }
 
index ab80b1fab53c877eb312e35bea9b98f7bc3b233b..4d638944d933bf971c7750425474dfd3079360eb 100644 (file)
@@ -106,7 +106,7 @@ module_init(snap_init);
 
 static void __exit snap_exit(void)
 {
-       llc_sap_close(snap_sap);
+       llc_sap_put(snap_sap);
 }
 
 module_exit(snap_exit);
index 1bb7dc1b85cd448d4de0b47485dd54b9212b535d..1eaa3d19d8bf760b19b57d2a6b5556de677dd0cb 100644 (file)
@@ -238,7 +238,7 @@ unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev)
                return trllc->ethertype;
        }
 
-       return ntohs(ETH_P_802_2);
+       return ntohs(ETH_P_TR_802_2);
 }
 
 /*
index 1d31b3a3f1e598c2da003d9dd4e5c50551719e39..7982656b9c830d7ea1c819d427240ca5a797a210 100644 (file)
@@ -100,8 +100,7 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to,
                        continue;
 
                if (to->sat_addr.s_net == ATADDR_ANYNET &&
-                   to->sat_addr.s_node == ATADDR_BCAST &&
-                   at->src_net == atif->address.s_net)
+                   to->sat_addr.s_node == ATADDR_BCAST)
                        goto found;
 
                if (to->sat_addr.s_net == at->src_net &&
@@ -1443,8 +1442,10 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
        else
                atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode);
 
-       /* Not ours, so we route the packet via the correct AppleTalk iface */
        if (!atif) {
+               /* Not ours, so we route the packet via the correct
+                * AppleTalk iface
+                */
                atalk_route_packet(skb, dev, ddp, &ddphv, origlen);
                goto out;
        }
@@ -1592,9 +1593,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 
        if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) {
                rt = atrtr_find(&usat->sat_addr);
-               if (!rt)
-                       return -ENETUNREACH;
-
                dev = rt->dev;
        } else {
                struct atalk_addr at_hint;
@@ -1603,11 +1601,12 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
                at_hint.s_net  = at->src_net;
 
                rt = atrtr_find(&at_hint);
-               if (!rt)
-                       return -ENETUNREACH;
-
                dev = rt->dev;
        }
+       if (!rt)
+               return -ENETUNREACH;
+
+       dev = rt->dev;
 
        SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n",
                        sk, size, dev->name);
@@ -1677,6 +1676,20 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
                SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk);
                /* loop back */
                skb_orphan(skb);
+               if (ddp->deh_dnode == ATADDR_BCAST) {
+                       struct atalk_addr at_lo;
+
+                       at_lo.s_node = 0;
+                       at_lo.s_net  = 0;
+
+                       rt = atrtr_find(&at_lo);
+                       if (!rt) {
+                               kfree_skb(skb);
+                               return -ENETUNREACH;
+                       }
+                       dev = rt->dev;
+                       skb->dev = dev;
+               }
                ddp_dl->request(ddp_dl, skb, dev->dev_addr);
        } else {
                SOCK_DEBUG(sk, "SK %p: send out.\n", sk);
index 1c8867f7f54a920cdc996b14ba1eebdd8b42dfac..a30d0bf480638de8a44c18b221b007d65085047a 100644 (file)
@@ -50,8 +50,10 @@ void atm_reset_addr(struct atm_dev *dev)
        struct atm_dev_addr *this, *p;
 
        spin_lock_irqsave(&dev->lock, flags);
-       list_for_each_entry_safe(this, p, &dev->local, entry)
-           kfree(this);
+       list_for_each_entry_safe(this, p, &dev->local, entry) {
+               list_del(&this->entry);
+               kfree(this);
+       }
        spin_unlock_irqrestore(&dev->lock, flags);
        notify_sigd(dev);
 }
index e93e838069e8794980c90dc80ef99bca31a2a4db..801a5813ec60ab54f7dbbecb313e80a53c57c03a 100644 (file)
@@ -178,8 +178,6 @@ static void vcc_destroy_socket(struct sock *sk)
                if (vcc->push)
                        vcc->push(vcc, NULL); /* atmarpd has no push */
 
-               vcc_remove_socket(sk);  /* no more receive */
-
                while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
                        atm_return(vcc,skb->truesize);
                        kfree_skb(skb);
@@ -188,6 +186,8 @@ static void vcc_destroy_socket(struct sock *sk)
                module_put(vcc->dev->ops->owner);
                atm_dev_put(vcc->dev);
        }
+
+       vcc_remove_socket(sk);
 }
 
 
index d89056ec44d4ff11a842b045a8403253151cdae4..a150198b05a3984751c13aced3cbe226314a56b4 100644 (file)
@@ -105,17 +105,35 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        if (!error)
                                sock->state = SS_CONNECTED;
                        goto done;
-               default:
+               case ATM_SETBACKEND:
+               case ATM_NEWBACKENDIF:
+                       {
+                               atm_backend_t backend;
+                               error = get_user(backend, (atm_backend_t __user *) argp);
+                               if (error)
+                                       goto done;
+                               switch (backend) {
+                                       case ATM_BACKEND_PPP:
+                                               request_module("pppoatm");
+                                               break;
+                                       case ATM_BACKEND_BR2684:
+                                               request_module("br2684");
+                                               break;
+                               }
+                       }
+                       break;
+               case ATMMPC_CTRL:
+               case ATMMPC_DATA:
+                       request_module("mpoa");
+                       break;
+               case ATMARPD_CTRL:
+                       request_module("clip");
+                       break;
+               case ATMLEC_CTRL:
+                       request_module("lec");
                        break;
        }
 
-       if (cmd == ATMMPC_CTRL || cmd == ATMMPC_DATA)
-               request_module("mpoa");
-       if (cmd == ATMARPD_CTRL)
-               request_module("clip");
-       if (cmd == ATMLEC_CTRL)
-               request_module("lec");
-
        error = -ENOIOCTLCMD;
 
        down(&ioctl_mutex);
index a0752487026d5f299ab9044592a4652fbaab3508..ad840b9afba8a3a68e644a682f9bf6499e38d765 100644 (file)
@@ -686,9 +686,19 @@ static unsigned char lec_ctrl_magic[] = {
         0x01,
         0x01 };
 
+#define LEC_DATA_DIRECT_8023  2
+#define LEC_DATA_DIRECT_8025  3
+
+static int lec_is_data_direct(struct atm_vcc *vcc)
+{ 
+       return ((vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8023) ||
+               (vcc->sap.blli[0].l3.tr9577.snap[4] == LEC_DATA_DIRECT_8025));
+} 
+
 static void 
 lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
 {
+       unsigned long flags;
         struct net_device *dev = (struct net_device *)vcc->proto_data;
         struct lec_priv *priv = (struct lec_priv *)dev->priv; 
 
@@ -728,7 +738,8 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
                 skb_queue_tail(&sk->sk_receive_queue, skb);
                 sk->sk_data_ready(sk, skb->len);
         } else { /* Data frame, queue to protocol handlers */
-                unsigned char *dst;
+               struct lec_arp_table *entry;
+                unsigned char *src, *dst;
 
                 atm_return(vcc,skb->truesize);
                 if (*(uint16_t *)skb->data == htons(priv->lecid) ||
@@ -741,10 +752,30 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
                         return;
                 }
 #ifdef CONFIG_TR
-                if (priv->is_trdev) dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest;
+                if (priv->is_trdev)
+                       dst = ((struct lecdatahdr_8025 *) skb->data)->h_dest;
                 else
 #endif
-                dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest;
+               dst = ((struct lecdatahdr_8023 *) skb->data)->h_dest;
+
+               /* If this is a Data Direct VCC, and the VCC does not match
+                * the LE_ARP cache entry, delete the LE_ARP cache entry.
+                */
+               spin_lock_irqsave(&priv->lec_arp_lock, flags);
+               if (lec_is_data_direct(vcc)) {
+#ifdef CONFIG_TR
+                       if (priv->is_trdev)
+                               src = ((struct lecdatahdr_8025 *) skb->data)->h_source;
+                       else
+#endif
+                       src = ((struct lecdatahdr_8023 *) skb->data)->h_source;
+                       entry = lec_arp_find(priv, src);
+                       if (entry && entry->vcc != vcc) {
+                               lec_arp_remove(priv, entry);
+                               kfree(entry);
+                       }
+               }
+               spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 
                 if (!(dst[0]&0x01) &&   /* Never filter Multi/Broadcast */
                     !priv->is_proxy &&  /* Proxy wants all the packets */
@@ -1990,6 +2021,12 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find,
                         found = entry->vcc;
                        goto out;
                 }
+               /* If the LE_ARP cache entry is still pending, reset count to 0
+                * so another LE_ARP request can be made for this frame.
+                */
+               if (entry->status == ESI_ARP_PENDING) {
+                       entry->no_tries = 0;
+               }
                 /* Data direct VC not yet set up, check to see if the unknown
                    frame count is greater than the limit. If the limit has
                    not been reached, allow the caller to send packet to
index f7c449ac1800cffe9cb355806886f7d1d19e8950..e7211a7f382c5b35ea059bd36feabfa5f8a32cfd 100644 (file)
@@ -217,8 +217,9 @@ void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
 static void purge_vcc(struct atm_vcc *vcc)
 {
        if (sk_atm(vcc)->sk_family == PF_ATMSVC &&
-           !test_bit(ATM_VF_META,&vcc->flags)) {
-               set_bit(ATM_VF_RELEASED,&vcc->flags);
+           !test_bit(ATM_VF_META, &vcc->flags)) {
+               set_bit(ATM_VF_RELEASED, &vcc->flags);
+               clear_bit(ATM_VF_REGIS, &vcc->flags);
                vcc_release_async(vcc, -EUNATCH);
        }
 }
@@ -243,8 +244,7 @@ static void sigd_close(struct atm_vcc *vcc)
                sk_for_each(s, node, head) {
                        struct atm_vcc *vcc = atm_sk(s);
 
-                       if (vcc->dev)
-                               purge_vcc(vcc);
+                       purge_vcc(vcc);
                }
        }
        read_unlock(&vcc_sklist_lock);
index 08e46052a3e4a896714254fce4a6c46702152d7c..d7b266136bf64168d0ce7ac8cc5796801fc11f13 100644 (file)
@@ -302,6 +302,7 @@ static int svc_listen(struct socket *sock,int backlog)
                error = -EINVAL;
                goto out;
        }
+       vcc_insert_socket(sk);
        set_bit(ATM_VF_WAITING, &vcc->flags);
        prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
        sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local);
index da9bf71421a7ef98e6ade66ea8902d7cfaadb37f..81987df536eb83f04d28da673806693589582993 100644 (file)
@@ -211,74 +211,45 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
 int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
                            struct iovec *to, int len)
 {
-       int start = skb_headlen(skb);
-       int i, copy = start - offset;
-
-       /* Copy header. */
-       if (copy > 0) {
-               if (copy > len)
-                       copy = len;
-               if (memcpy_toiovec(to, skb->data + offset, copy))
-                       goto fault;
-               if ((len -= copy) == 0)
-                       return 0;
-               offset += copy;
-       }
+       int i, err, fraglen, end = 0;
+       struct sk_buff *next = skb_shinfo(skb)->frag_list;
+next_skb:
+       fraglen = skb_headlen(skb);
+       i = -1;
 
-       /* Copy paged appendix. Hmm... why does this look so complicated? */
-       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-               int end;
-
-               BUG_TRAP(start <= offset + len);
+       while (1) {
+               int start = end;
 
-               end = start + skb_shinfo(skb)->frags[i].size;
-               if ((copy = end - offset) > 0) {
-                       int err;
-                       u8  *vaddr;
-                       skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-                       struct page *page = frag->page;
+               if ((end += fraglen) > offset) {
+                       int copy = end - offset, o = offset - start;
 
                        if (copy > len)
                                copy = len;
-                       vaddr = kmap(page);
-                       err = memcpy_toiovec(to, vaddr + frag->page_offset +
-                                            offset - start, copy);
-                       kunmap(page);
+                       if (i == -1)
+                               err = memcpy_toiovec(to, skb->data + o, copy);
+                       else {
+                               skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+                               struct page *page = frag->page;
+                               void *p = kmap(page) + frag->page_offset + o;
+                               err = memcpy_toiovec(to, p, copy);
+                               kunmap(page);
+                       }
                        if (err)
                                goto fault;
                        if (!(len -= copy))
                                return 0;
                        offset += copy;
                }
-               start = end;
+               if (++i >= skb_shinfo(skb)->nr_frags)
+                       break;
+               fraglen = skb_shinfo(skb)->frags[i].size;
        }
-
-       if (skb_shinfo(skb)->frag_list) {
-               struct sk_buff *list = skb_shinfo(skb)->frag_list;
-
-               for (; list; list = list->next) {
-                       int end;
-
-                       BUG_TRAP(start <= offset + len);
-
-                       end = start + list->len;
-                       if ((copy = end - offset) > 0) {
-                               if (copy > len)
-                                       copy = len;
-                               if (skb_copy_datagram_iovec(list,
-                                                           offset - start,
-                                                           to, copy))
-                                       goto fault;
-                               if ((len -= copy) == 0)
-                                       return 0;
-                               offset += copy;
-                       }
-                       start = end;
-               }
+       if (next) {
+               skb = next;
+               BUG_ON(skb_shinfo(skb)->frag_list);
+               next = skb->next;
+               goto next_skb;
        }
-       if (!len)
-               return 0;
-
 fault:
        return -EFAULT;
 }
index c01511e3d0c14a417f4ac025749405c061446e19..9066c874e273b6f3bced25f16b876cd5b85e23f3 100644 (file)
@@ -574,6 +574,8 @@ struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
        return dev;
 }
 
+EXPORT_SYMBOL(dev_getbyhwaddr);
+
 struct net_device *dev_getfirstbyhwtype(unsigned short type)
 {
        struct net_device *dev;
@@ -1257,6 +1259,8 @@ int dev_queue_xmit(struct sk_buff *skb)
                if (skb_checksum_help(skb, 0))
                        goto out_kfree_skb;
 
+       spin_lock_prefetch(&dev->queue_lock);
+
        /* Disable soft irqs for various locks below. Also 
         * stops preemption for RCU. 
         */
index 39fc55edf691aab986eb1cb53f134f65839c33a4..4128fc76ac3a2906bc586c1f5b05ae670cdca686 100644 (file)
@@ -61,7 +61,9 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
 void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
 
 static struct neigh_table *neigh_tables;
+#ifdef CONFIG_PROC_FS
 static struct file_operations neigh_stat_seq_fops;
+#endif
 
 /*
    Neighbour hash table buckets are protected with rwlock tbl->lock.
@@ -725,6 +727,13 @@ static __inline__ int neigh_max_probes(struct neighbour *n)
                p->ucast_probes + p->app_probes + p->mcast_probes);
 }
 
+static inline void neigh_add_timer(struct neighbour *n, unsigned long when)
+{
+       if (unlikely(mod_timer(&n->timer, when))) {
+               printk("NEIGH: BUG, double timer add, state is %x\n",
+                      n->nud_state);
+       }
+}
 
 /* Called when a timer expires for a neighbour entry. */
 
@@ -809,8 +818,7 @@ static void neigh_timer_handler(unsigned long arg)
                neigh_hold(neigh);
                if (time_before(next, jiffies + HZ/2))
                        next = jiffies + HZ/2;
-               neigh->timer.expires = next;
-               add_timer(&neigh->timer);
+               neigh_add_timer(neigh, next);
        }
        if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
                struct sk_buff *skb = skb_peek(&neigh->arp_queue);
@@ -852,8 +860,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
                        atomic_set(&neigh->probes, neigh->parms->ucast_probes);
                        neigh->nud_state     = NUD_INCOMPLETE;
                        neigh_hold(neigh);
-                       neigh->timer.expires = now + 1;
-                       add_timer(&neigh->timer);
+                       neigh_add_timer(neigh, now + 1);
                } else {
                        neigh->nud_state = NUD_FAILED;
                        write_unlock_bh(&neigh->lock);
@@ -866,8 +873,8 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
                NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
                neigh_hold(neigh);
                neigh->nud_state = NUD_DELAY;
-               neigh->timer.expires = jiffies + neigh->parms->delay_probe_time;
-               add_timer(&neigh->timer);
+               neigh_add_timer(neigh,
+                               jiffies + neigh->parms->delay_probe_time);
        }
 
        if (neigh->nud_state == NUD_INCOMPLETE) {
@@ -1013,10 +1020,10 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                neigh_del_timer(neigh);
                if (new & NUD_IN_TIMER) {
                        neigh_hold(neigh);
-                       neigh->timer.expires = jiffies + 
+                       neigh_add_timer(neigh, (jiffies + 
                                                ((new & NUD_REACHABLE) ? 
-                                                neigh->parms->reachable_time : 0);
-                       add_timer(&neigh->timer);
+                                                neigh->parms->reachable_time :
+                                                0)));
                }
                neigh->nud_state = new;
        }
index ef430b1e8e42acc87af3d12fb4c95544c8996570..b7f2d65a614f3e573154ff3f07d4b7e34ab184fe 100644 (file)
 
 /* Used to help with determining the pkts on receive */
 #define PKTGEN_MAGIC 0xbe9be955
-#define PG_PROC_DIR "pktgen"
+#define PG_PROC_DIR "net/pktgen"
 
 #define MAX_CFLOWS  65536
 
@@ -1476,18 +1476,7 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer,
 
 static int create_proc_dir(void)
 {
-        int     len;
-        /*  does proc_dir already exists */
-        len = strlen(PG_PROC_DIR);
-
-        for (pg_proc_dir = proc_net->subdir; pg_proc_dir; pg_proc_dir=pg_proc_dir->next) {
-                if ((pg_proc_dir->namelen == len) &&
-                   (! memcmp(pg_proc_dir->name, PG_PROC_DIR, len))) 
-                        break;
-        }
-        
-        if (!pg_proc_dir) 
-                pg_proc_dir = create_proc_entry(PG_PROC_DIR, S_IFDIR, proc_net);
+       pg_proc_dir = proc_mkdir(PG_PROC_DIR, NULL);
         
         if (!pg_proc_dir) 
                 return -ENODEV;
@@ -1497,7 +1486,7 @@ static int create_proc_dir(void)
 
 static int remove_proc_dir(void)
 {
-        remove_proc_entry(PG_PROC_DIR, proc_net);
+        remove_proc_entry(PG_PROC_DIR, NULL);
         return 0;
 }
 
@@ -2908,7 +2897,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char* ifname)
                 pkt_dev->udp_dst_max = 9;
 
                 strncpy(pkt_dev->ifname, ifname, 31);
-                sprintf(pkt_dev->fname, "net/%s/%s", PG_PROC_DIR, ifname);
+                sprintf(pkt_dev->fname, "%s/%s", PG_PROC_DIR, ifname);
 
                 if (! pktgen_setup_dev(pkt_dev)) {
                         printk("pktgen: ERROR: pktgen_setup_dev failed.\n");
@@ -2981,7 +2970,7 @@ static int pktgen_create_thread(const char* name, int cpu)
         spin_lock_init(&t->if_lock);
        t->cpu = cpu;
         
-        sprintf(t->fname, "net/%s/%s", PG_PROC_DIR, t->name);
+        sprintf(t->fname, "%s/%s", PG_PROC_DIR, t->name);
         t->proc_ent = create_proc_entry(t->fname, 0600, NULL);
         if (!t->proc_ent) {
                 printk("pktgen: cannot create %s procfs entry.\n", t->fname);
@@ -3064,7 +3053,7 @@ static int __init pg_init(void)
 
        create_proc_dir();
 
-        sprintf(module_fname, "net/%s/pgctrl", PG_PROC_DIR);
+        sprintf(module_fname, "%s/pgctrl", PG_PROC_DIR);
         module_proc_ent = create_proc_entry(module_fname, 0600, NULL);
         if (!module_proc_ent) {
                 printk("pktgen: ERROR: cannot create %s procfs entry.\n", module_fname);
index ac63b56e23b29c45113df81fa226bc2c9568d758..928d2a1d6d8e7bbc42dcb01f56d598244b12e575 100644 (file)
@@ -660,16 +660,20 @@ struct sock *sk_alloc(int family, unsigned int __nocast priority,
                        sock_lock_init(sk);
                }
                
-               if (security_sk_alloc(sk, family, priority)) {
-                       if (slab != NULL)
-                               kmem_cache_free(slab, sk);
-                       else
-                               kfree(sk);
-                       sk = NULL;
-               } else
-                       __module_get(prot->owner);
+               if (security_sk_alloc(sk, family, priority))
+                       goto out_free;
+
+               if (!try_module_get(prot->owner))
+                       goto out_free;
        }
        return sk;
+
+out_free:
+       if (slab != NULL)
+               kmem_cache_free(slab, sk);
+       else
+               kfree(sk);
+       return NULL;
 }
 
 void sk_free(struct sock *sk)
index 87a052a9a84f9b4025ebf430f0c6197afd3a759c..68a5ca866442c059c4d21359f5f7632fa971f8bd 100644 (file)
@@ -146,6 +146,19 @@ int eth_rebuild_header(struct sk_buff *skb)
        return 0;
 }
 
+static inline unsigned int compare_eth_addr(const unsigned char *__a, const unsigned char *__b)
+{
+       const unsigned short *dest = (unsigned short *) __a;
+       const unsigned short *devaddr = (unsigned short *) __b;
+       unsigned int res;
+
+       BUILD_BUG_ON(ETH_ALEN != 6);
+       res = ((dest[0] ^ devaddr[0]) |
+              (dest[1] ^ devaddr[1]) |
+              (dest[2] ^ devaddr[2])) != 0;
+
+       return res;
+}
 
 /*
  *     Determine the packet's protocol ID. The rule here is that we 
@@ -158,16 +171,15 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
        struct ethhdr *eth;
        unsigned char *rawp;
        
-       skb->mac.raw=skb->data;
+       skb->mac.raw = skb->data;
        skb_pull(skb,ETH_HLEN);
        eth = eth_hdr(skb);
        
-       if(*eth->h_dest&1)
-       {
-               if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
-                       skb->pkt_type=PACKET_BROADCAST;
+       if (*eth->h_dest&1) {
+               if (!compare_eth_addr(eth->h_dest, dev->broadcast))
+                       skb->pkt_type = PACKET_BROADCAST;
                else
-                       skb->pkt_type=PACKET_MULTICAST;
+                       skb->pkt_type = PACKET_MULTICAST;
        }
        
        /*
@@ -178,10 +190,9 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
         *      seems to set IFF_PROMISC.
         */
         
-       else if(1 /*dev->flags&IFF_PROMISC*/)
-       {
-               if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
-                       skb->pkt_type=PACKET_OTHERHOST;
+       else if(1 /*dev->flags&IFF_PROMISC*/) {
+               if (unlikely(compare_eth_addr(eth->h_dest, dev->dev_addr)))
+                       skb->pkt_type = PACKET_OTHERHOST;
        }
        
        if (ntohs(eth->h_proto) >= 1536)
index 03a47343ddc75a386370e9e07861299faf9e71ae..6059e9e37123b711554c6e50a18daf8a5872c793 100644 (file)
@@ -230,7 +230,7 @@ static int __init ieee80211_init(void)
        struct proc_dir_entry *e;
 
        ieee80211_debug_level = debug;
-       ieee80211_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net);
+       ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
        if (ieee80211_proc == NULL) {
                IEEE80211_ERROR("Unable to create " DRV_NAME
                                " proc directory\n");
index 3cf9b451675ce13123a37c005dc269fff067fc87..2cd7e7d1ac9097d96d263b6c352ecc1ca068f5ba 100644 (file)
@@ -537,6 +537,17 @@ config IP_NF_TARGET_TCPMSS
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_TARGET_NFQUEUE
+       tristate "NFQUEUE Target Support"
+       depends on IP_NF_IPTABLES
+       help
+         This Target replaced the old obsolete QUEUE target.
+
+         As opposed to QUEUE, it supports 65535 different queues,
+         not just one.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
 # NAT + specific targets
 config IP_NF_NAT
        tristate "Full NAT"
index 3d45d3c0283c99ddf20ccedde1c98b093e743827..dab4b58dd31ee6b69e99e5bef48d7c3de9f77224 100644 (file)
@@ -4,7 +4,8 @@
 
 # objects for the standalone - connection tracking / NAT
 ip_conntrack-objs      := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
-iptable_nat-objs       := ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
+ip_nat-objs    := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
+iptable_nat-objs       := ip_nat_rule.o ip_nat_standalone.o
 
 ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
 ip_nat_pptp-objs       := ip_nat_helper_pptp.o ip_nat_proto_gre.o
@@ -40,7 +41,7 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
 # the three instances of ip_tables
 obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
 obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
-obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
+obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o ip_nat.o
 obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
 
 # matches
@@ -92,6 +93,7 @@ obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
 obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
+obj-$(CONFIG_IP_NF_TARGET_NFQUEUE) += ipt_NFQUEUE.o
 
 # generic ARP tables
 obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
@@ -101,4 +103,3 @@ obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o
 obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o
 
 obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
-obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += ipt_NFQUEUE.o
index de3cb9db6f857ffd8064f12cae2c2dd719453c8a..744abb9d377a4399463261d759f5f7e83acae2dd 100644 (file)
@@ -247,6 +247,7 @@ static int gre_packet(struct ip_conntrack *ct,
                                   ct->proto.gre.stream_timeout);
                /* Also, more likely to be important, and not a probe. */
                set_bit(IPS_ASSURED_BIT, &ct->status);
+               ip_conntrack_event_cache(IPCT_STATUS, skb);
        } else
                ip_ct_refresh_acct(ct, conntrackinfo, skb,
                                   ct->proto.gre.timeout);
index a875f35e576ddfd117a2ac4224f1a5e9feff3016..59a4a0111dd3fa9d91b2863a25069dbbfee56d8f 100644 (file)
@@ -416,6 +416,7 @@ static int sctp_packet(struct ip_conntrack *conntrack,
                && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
                DEBUGP("Setting assured bit\n");
                set_bit(IPS_ASSURED_BIT, &conntrack->status);
+               ip_conntrack_event_cache(IPCT_STATUS, skb);
        }
 
        return NF_ACCEPT;
index 1985abc59d2497f13c453750277d71da0bf73946..121760d6cc50cd2ccd4568591168988606ab15d3 100644 (file)
@@ -1014,7 +1014,8 @@ static int tcp_packet(struct ip_conntrack *conntrack,
                /* Set ASSURED if we see see valid ack in ESTABLISHED 
                   after SYN_RECV or a valid answer for a picked up 
                   connection. */
-                       set_bit(IPS_ASSURED_BIT, &conntrack->status);
+               set_bit(IPS_ASSURED_BIT, &conntrack->status);
+               ip_conntrack_event_cache(IPCT_STATUS, skb);
        }
        ip_ct_refresh_acct(conntrack, ctinfo, skb, timeout);
 
index c3ea891d38e7113a53f1a80227314fb4e35dba0f..c5e3abd24672beb3bf04ccef61a2d8b3582b79fd 100644 (file)
@@ -74,12 +74,14 @@ ip_nat_proto_find_get(u_int8_t protonum)
 
        return p;
 }
+EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);
 
 void
 ip_nat_proto_put(struct ip_nat_protocol *p)
 {
        module_put(p->me);
 }
+EXPORT_SYMBOL_GPL(ip_nat_proto_put);
 
 /* We keep an extra hash for each conntrack, for fast searching. */
 static inline unsigned int
@@ -111,6 +113,7 @@ ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
        return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
                                      oldcheck^0xFFFF));
 }
+EXPORT_SYMBOL(ip_nat_cheat_check);
 
 /* Is this tuple already taken? (not by us) */
 int
@@ -127,6 +130,7 @@ ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
        invert_tuplepr(&reply, tuple);
        return ip_conntrack_tuple_taken(&reply, ignored_conntrack);
 }
+EXPORT_SYMBOL(ip_nat_used_tuple);
 
 /* If we source map this tuple so reply looks like reply_tuple, will
  * that meet the constraints of range. */
@@ -347,6 +351,7 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,
 
        return NF_ACCEPT;
 }
+EXPORT_SYMBOL(ip_nat_setup_info);
 
 /* Returns true if succeeded. */
 static int
@@ -387,10 +392,10 @@ manip_pkt(u_int16_t proto,
 }
 
 /* Do packet manipulations according to ip_nat_setup_info. */
-unsigned int nat_packet(struct ip_conntrack *ct,
-                       enum ip_conntrack_info ctinfo,
-                       unsigned int hooknum,
-                       struct sk_buff **pskb)
+unsigned int ip_nat_packet(struct ip_conntrack *ct,
+                          enum ip_conntrack_info ctinfo,
+                          unsigned int hooknum,
+                          struct sk_buff **pskb)
 {
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
        unsigned long statusbit;
@@ -417,12 +422,13 @@ unsigned int nat_packet(struct ip_conntrack *ct,
        }
        return NF_ACCEPT;
 }
+EXPORT_SYMBOL_GPL(ip_nat_packet);
 
 /* Dir is direction ICMP is coming from (opposite to packet it contains) */
-int icmp_reply_translation(struct sk_buff **pskb,
-                          struct ip_conntrack *ct,
-                          enum ip_nat_manip_type manip,
-                          enum ip_conntrack_dir dir)
+int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
+                                 struct ip_conntrack *ct,
+                                 enum ip_nat_manip_type manip,
+                                 enum ip_conntrack_dir dir)
 {
        struct {
                struct icmphdr icmp;
@@ -509,6 +515,7 @@ int icmp_reply_translation(struct sk_buff **pskb,
 
        return 1;
 }
+EXPORT_SYMBOL_GPL(ip_nat_icmp_reply_translation);
 
 /* Protocol registration. */
 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
@@ -525,6 +532,7 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto)
        write_unlock_bh(&ip_nat_lock);
        return ret;
 }
+EXPORT_SYMBOL(ip_nat_protocol_register);
 
 /* Noone stores the protocol anywhere; simply delete it. */
 void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
@@ -536,6 +544,7 @@ void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
        /* Someone could be still looking at the proto in a bh. */
        synchronize_net();
 }
+EXPORT_SYMBOL(ip_nat_protocol_unregister);
 
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
     defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
@@ -582,7 +591,7 @@ EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range);
 EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);
 #endif
 
-int __init ip_nat_init(void)
+static int __init ip_nat_init(void)
 {
        size_t i;
 
@@ -624,10 +633,14 @@ static int clean_nat(struct ip_conntrack *i, void *data)
        return 0;
 }
 
-/* Not __exit: called from ip_nat_standalone.c:init_or_cleanup() --RR */
-void ip_nat_cleanup(void)
+static void __exit ip_nat_cleanup(void)
 {
        ip_ct_iterate_cleanup(&clean_nat, NULL);
        ip_conntrack_destroyed = NULL;
        vfree(bysource);
 }
+
+MODULE_LICENSE("GPL");
+
+module_init(ip_nat_init);
+module_exit(ip_nat_cleanup);
index d2dd5d3135563f9e17631f6ab72e8bd42bcad387..5d506e0564d5f507b7209ddfea993e68366d52ec 100644 (file)
@@ -199,6 +199,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
        }
        return 1;
 }
+EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
                        
 /* Generic function for mangling variable-length address changes inside
  * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
@@ -256,6 +257,7 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb,
 
        return 1;
 }
+EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
 
 /* Adjust one found SACK option including checksum correction */
 static void
@@ -399,6 +401,7 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
 
        return 1;
 }
+EXPORT_SYMBOL(ip_nat_seq_adjust);
 
 /* Setup NAT on this expected conntrack so it follows master. */
 /* If we fail to get a free NAT slot, we'll get dropped on confirm */
@@ -425,3 +428,4 @@ void ip_nat_follow_master(struct ip_conntrack *ct,
        /* hook doesn't matter, but it has to do destination manip */
        ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
 }
+EXPORT_SYMBOL(ip_nat_follow_master);
index 0ff368b131f6bac3bfd27e8201b519ce700b64bd..30cd4e18c129e8904acbcedd8b1233762e0196c0 100644 (file)
@@ -108,8 +108,8 @@ ip_nat_fn(unsigned int hooknum,
        case IP_CT_RELATED:
        case IP_CT_RELATED+IP_CT_IS_REPLY:
                if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
-                       if (!icmp_reply_translation(pskb, ct, maniptype,
-                                                   CTINFO2DIR(ctinfo)))
+                       if (!ip_nat_icmp_reply_translation(pskb, ct, maniptype,
+                                                          CTINFO2DIR(ctinfo)))
                                return NF_DROP;
                        else
                                return NF_ACCEPT;
@@ -152,7 +152,7 @@ ip_nat_fn(unsigned int hooknum,
        }
 
        IP_NF_ASSERT(info);
-       return nat_packet(ct, ctinfo, hooknum, pskb);
+       return ip_nat_packet(ct, ctinfo, hooknum, pskb);
 }
 
 static unsigned int
@@ -325,15 +325,10 @@ static int init_or_cleanup(int init)
                printk("ip_nat_init: can't setup rules.\n");
                goto cleanup_nothing;
        }
-       ret = ip_nat_init();
-       if (ret < 0) {
-               printk("ip_nat_init: can't setup rules.\n");
-               goto cleanup_rule_init;
-       }
        ret = nf_register_hook(&ip_nat_in_ops);
        if (ret < 0) {
                printk("ip_nat_init: can't register in hook.\n");
-               goto cleanup_nat;
+               goto cleanup_rule_init;
        }
        ret = nf_register_hook(&ip_nat_out_ops);
        if (ret < 0) {
@@ -374,8 +369,6 @@ static int init_or_cleanup(int init)
        nf_unregister_hook(&ip_nat_out_ops);
  cleanup_inops:
        nf_unregister_hook(&ip_nat_in_ops);
- cleanup_nat:
-       ip_nat_cleanup();
  cleanup_rule_init:
        ip_nat_rule_cleanup();
  cleanup_nothing:
@@ -395,14 +388,4 @@ static void __exit fini(void)
 module_init(init);
 module_exit(fini);
 
-EXPORT_SYMBOL(ip_nat_setup_info);
-EXPORT_SYMBOL(ip_nat_protocol_register);
-EXPORT_SYMBOL(ip_nat_protocol_unregister);
-EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);
-EXPORT_SYMBOL_GPL(ip_nat_proto_put);
-EXPORT_SYMBOL(ip_nat_cheat_check);
-EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
-EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
-EXPORT_SYMBOL(ip_nat_used_tuple);
-EXPORT_SYMBOL(ip_nat_follow_master);
 MODULE_LICENSE("GPL");
index a7537c7bbd06f0040c4d44f255c081cea93a215b..677419d0c9ade7da761d5c558b9421b6e3e32f04 100644 (file)
@@ -355,8 +355,6 @@ static void tcp_clamp_window(struct sock *sk, struct tcp_sock *tp)
                        app_win -= icsk->icsk_ack.rcv_mss;
                app_win = max(app_win, 2U*tp->advmss);
 
-               if (!ofo_win)
-                       tp->window_clamp = min(tp->window_clamp, app_win);
                tp->rcv_ssthresh = min(tp->window_clamp, 2U*tp->advmss);
        }
 }
index d6e3d269e90611250fabaea9005d0dc3abc3dea3..c5b911f9b662cb33b959755cebd3f2fb8d8c7fe0 100644 (file)
@@ -190,7 +190,7 @@ void tcp_select_initial_window(int __space, __u32 mss,
        }
 
        /* Set initial window to value enough for senders,
-        * following RFC1414. Senders, not following this RFC,
+        * following RFC2414. Senders, not following this RFC,
         * will be satisfied with 2.
         */
        if (mss > (1<<*rcv_wscale)) {
index 2fea3f4402a0e5b0b3c7d2d8703aa6432f1e8dec..4e509e52fbc129d84762b2a36a7a5fc7f6a7a6da 100644 (file)
@@ -3520,6 +3520,8 @@ int __init addrconf_init(void)
        if (err)
                return err;
 
+       ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+
        register_netdevice_notifier(&ipv6_dev_notf);
 
 #ifdef CONFIG_IPV6_PRIVACY
index 216fbe1ac65c71c86c4d7545ee2c3025049670c2..bb7ccfe33f2384e9bbfeadcd8d48dabba4f417b1 100644 (file)
@@ -209,6 +209,17 @@ config IP6_NF_TARGET_REJECT
 
          To compile it as a module, choose M here.  If unsure, say N.
 
+config IP6_NF_TARGET_NFQUEUE
+       tristate "NFQUEUE Target Support"
+       depends on IP_NF_IPTABLES
+       help
+         This Target replaced the old obsolete QUEUE target.
+
+         As opposed to QUEUE, it supports 65535 different queues,
+         not just one.
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
 #  if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
 #    dep_tristate '    REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER
 #    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
index bd9a16a5cbba3b48e9d9199eb68a16cbb60c1246..2b2c370e8b1ccf72d3864a19d0e5a93ab0135e6a 100644 (file)
@@ -21,9 +21,9 @@ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
 obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
+obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o
 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
-obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += ip6t_NFQUEUE.o
index 6602d901f8b111ba51e2947f51b4ebaf452d5dbb..8aff254cb41851e7e53e0f96f13bd83d1a6346b2 100644 (file)
@@ -38,7 +38,7 @@
 #include <net/irda/parameters.h>
 #include <net/irda/irttp.h>
 
-static struct irttp_cb *irttp = NULL;
+static struct irttp_cb *irttp;
 
 static void __irttp_close_tsap(struct tsap_cb *self);
 
@@ -86,12 +86,9 @@ static pi_param_info_t param_info = { pi_major_call_table, 1, 0x0f, 4 };
  */
 int __init irttp_init(void)
 {
-       /* Initialize the irttp structure. */
-       if (irttp == NULL) {
-               irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL);
-               if (irttp == NULL)
-                       return -ENOMEM;
-       }
+       irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL);
+       if (irttp == NULL)
+               return -ENOMEM;
        memset(irttp, 0, sizeof(struct irttp_cb));
 
        irttp->magic = TTP_MAGIC;
@@ -100,6 +97,7 @@ int __init irttp_init(void)
        if (!irttp->tsaps) {
                IRDA_ERROR("%s: can't allocate IrTTP hashbin!\n",
                           __FUNCTION__);
+               kfree(irttp);
                return -ENOMEM;
        }
 
@@ -115,7 +113,6 @@ int __init irttp_init(void)
 void __exit irttp_cleanup(void) 
 {
        /* Check for main structure */
-       IRDA_ASSERT(irttp != NULL, return;);
        IRDA_ASSERT(irttp->magic == TTP_MAGIC, return;);
 
        /*
@@ -382,7 +379,6 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
        struct lsap_cb *lsap;
        notify_t ttp_notify;
 
-       IRDA_ASSERT(irttp != NULL, return NULL;);
        IRDA_ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
 
        /* The IrLMP spec (IrLMP 1.1 p10) says that we have the right to
@@ -1880,8 +1876,6 @@ static int irttp_seq_open(struct inode *inode, struct file *file)
        struct seq_file *seq;
        int rc = -ENOMEM;
        struct irttp_iter_state *s;
-       
-       IRDA_ASSERT(irttp != NULL, return -EINVAL;);
 
        s = kmalloc(sizeof(*s), GFP_KERNEL);
        if (!s)
index 5ebd4ed2bd4295ef2e25d7425852887f4e972c4f..4e260cff3c5d89d3064120f4f3718e6feff1e44a 100644 (file)
@@ -22,3 +22,4 @@ llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \
          llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_station.o
 
 llc2-$(CONFIG_PROC_FS) += llc_proc.o
+llc2-$(CONFIG_SYSCTL)  += sysctl_net_llc.o
index 66f55e514b568d2682f0c859e0db1e90cd252cf2..59d02cbbeb9effd53158859aa522a7c73b581f5c 100644 (file)
@@ -21,6 +21,7 @@
  * See the GNU General Public License for more details.
  */
 #include <linux/config.h>
+#include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/rtnetlink.h>
@@ -37,10 +38,9 @@ static u16 llc_ui_sap_link_no_max[256];
 static struct sockaddr_llc llc_ui_addrnull;
 static struct proto_ops llc_ui_ops;
 
-static int llc_ui_wait_for_conn(struct sock *sk, int timeout);
-static int llc_ui_wait_for_disc(struct sock *sk, int timeout);
-static int llc_ui_wait_for_data(struct sock *sk, int timeout);
-static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout);
+static int llc_ui_wait_for_conn(struct sock *sk, long timeout);
+static int llc_ui_wait_for_disc(struct sock *sk, long timeout);
+static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout);
 
 #if 0
 #define dprintk(args...) printk(KERN_DEBUG args)
@@ -116,12 +116,12 @@ static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
        struct llc_sock* llc = llc_sk(sk);
        int rc = 0;
 
-       if (llc_data_accept_state(llc->state) || llc->p_flag) {
-               int timeout = sock_sndtimeo(sk, noblock);
+       if (unlikely(llc_data_accept_state(llc->state) || llc->p_flag)) {
+               long timeout = sock_sndtimeo(sk, noblock);
 
                rc = llc_ui_wait_for_busy_core(sk, timeout);
        }
-       if (!rc)
+       if (unlikely(!rc))
                rc = llc_build_and_send_pkt(sk, skb);
        return rc;
 }
@@ -155,7 +155,7 @@ static int llc_ui_create(struct socket *sock, int protocol)
        struct sock *sk;
        int rc = -ESOCKTNOSUPPORT;
 
-       if (sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM) {
+       if (likely(sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM)) {
                rc = -ENOMEM;
                sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto);
                if (sk) {
@@ -177,7 +177,7 @@ static int llc_ui_release(struct socket *sock)
        struct sock *sk = sock->sk;
        struct llc_sock *llc;
 
-       if (!sk)
+       if (unlikely(sk == NULL))
                goto out;
        sock_hold(sk);
        lock_sock(sk);
@@ -189,10 +189,6 @@ static int llc_ui_release(struct socket *sock)
        if (!sock_flag(sk, SOCK_ZAPPED))
                llc_sap_remove_socket(llc->sap, sk);
        release_sock(sk);
-       if (llc->sap && hlist_empty(&llc->sap->sk_list.list)) {
-               llc_release_sockets(llc->sap);
-               llc_sap_close(llc->sap);
-       }
        if (llc->dev)
                dev_put(llc->dev);
        sock_put(sk);
@@ -221,6 +217,7 @@ static int llc_ui_autoport(void)
                                llc_ui_sap_last_autoport = i + 2;
                                goto out;
                        }
+                       llc_sap_put(sap);
                }
                llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
                tries++;
@@ -231,20 +228,13 @@ out:
 }
 
 /**
- *     llc_ui_autobind - Bind a socket to a specific address.
- *     @sk: Socket to bind an address to.
- *     @addr: Address the user wants the socket bound to.
+ *     llc_ui_autobind - automatically bind a socket to a sap
+ *     @sock: socket to bind
+ *     @addr: address to connect to
+ *
+ *     Used by llc_ui_connect and llc_ui_sendmsg when the user hasn't
+ *     specifically used llc_ui_bind to bind to an specific address/sap
  *
- *     Bind a socket to a specific address. For llc a user is able to bind to
- *     a specific sap only or mac + sap. If the user only specifies a sap and
- *     a null dmac (all zeros) the user is attempting to bind to an entire
- *     sap. This will stop anyone else on the local system from using that
- *     sap.  If someone else has a mac + sap open the bind to null + sap will
- *     fail.
- *     If the user desires to bind to a specific mac + sap, it is possible to
- *     have multiple sap connections via multiple macs.
- *     Bind and autobind for that matter must enforce the correct sap usage
- *     otherwise all hell will break loose.
  *     Returns: 0 upon success, negative otherwise.
  */
 static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
@@ -285,11 +275,7 @@ out:
  *     @addrlen: Length of the uaddr structure.
  *
  *     Bind a socket to a specific address. For llc a user is able to bind to
- *     a specific sap only or mac + sap. If the user only specifies a sap and
- *     a null dmac (all zeros) the user is attempting to bind to an entire
- *     sap. This will stop anyone else on the local system from using that
- *     sap. If someone else has a mac + sap open the bind to null + sap will
- *     fail.
+ *     a specific sap only or mac + sap.
  *     If the user desires to bind to a specific mac + sap, it is possible to
  *     have multiple sap connections via multiple macs.
  *     Bind and autobind for that matter must enforce the correct sap usage
@@ -305,10 +291,16 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
        int rc = -EINVAL;
 
        dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);
-       if (!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr))
+       if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))
                goto out;
        rc = -EAFNOSUPPORT;
-       if (addr->sllc_family != AF_LLC)
+       if (unlikely(addr->sllc_family != AF_LLC))
+               goto out;
+       rc = -ENODEV;
+       rtnl_lock();
+       llc->dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_mac);
+       rtnl_unlock();
+       if (!llc->dev)
                goto out;
        if (!addr->sllc_sap) {
                rc = -EUSERS;
@@ -322,6 +314,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                rc = -EBUSY; /* some other network layer is using the sap */
                if (!sap)
                        goto out;
+               llc_sap_hold(sap);
        } else {
                struct llc_addr laddr, daddr;
                struct sock *ask;
@@ -338,7 +331,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                ask = llc_lookup_established(sap, &daddr, &laddr);
                if (ask) {
                        sock_put(ask);
-                       goto out;
+                       goto out_put;
                }
        }
        llc->laddr.lsap = addr->sllc_sap;
@@ -348,6 +341,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
        llc_sap_add_socket(sap, sk);
        sock_reset_flag(sk, SOCK_ZAPPED);
        rc = 0;
+out_put:
+       llc_sap_put(sap);
 out:
        return rc;
 }
@@ -369,7 +364,7 @@ static int llc_ui_shutdown(struct socket *sock, int how)
        int rc = -ENOTCONN;
 
        lock_sock(sk);
-       if (sk->sk_state != TCP_ESTABLISHED)
+       if (unlikely(sk->sk_state != TCP_ESTABLISHED))
                goto out;
        rc = -EINVAL;
        if (how != 2)
@@ -404,14 +399,18 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
        struct sock *sk = sock->sk;
        struct llc_sock *llc = llc_sk(sk);
        struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
-       struct net_device *dev;
        int rc = -EINVAL;
 
        lock_sock(sk);
-       if (addrlen != sizeof(*addr))
+       if (unlikely(addrlen != sizeof(*addr)))
                goto out;
        rc = -EAFNOSUPPORT;
-       if (addr->sllc_family != AF_LLC)
+       if (unlikely(addr->sllc_family != AF_LLC))
+               goto out;
+       if (unlikely(sk->sk_type != SOCK_STREAM))
+               goto out;
+       rc = -EALREADY;
+       if (unlikely(sock->state == SS_CONNECTING))
                goto out;
        /* bind connection to sap if user hasn't done it. */
        if (sock_flag(sk, SOCK_ZAPPED)) {
@@ -419,19 +418,13 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
                rc = llc_ui_autobind(sock, addr);
                if (rc)
                        goto out;
-               llc->daddr.lsap = addr->sllc_sap;
-               memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);
        }
-       dev = llc->dev;
-       if (sk->sk_type != SOCK_STREAM)
-               goto out;
-       rc = -EALREADY;
-       if (sock->state == SS_CONNECTING)
-               goto out;
+       llc->daddr.lsap = addr->sllc_sap;
+       memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);
        sock->state = SS_CONNECTING;
        sk->sk_state   = TCP_SYN_SENT;
        llc->link   = llc_ui_next_link_no(llc->sap->laddr.lsap);
-       rc = llc_establish_connection(sk, dev->dev_addr,
+       rc = llc_establish_connection(sk, llc->dev->dev_addr,
                                      addr->sllc_mac, addr->sllc_sap);
        if (rc) {
                dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__);
@@ -439,12 +432,30 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
                sk->sk_state = TCP_CLOSE;
                goto out;
        }
-       rc = llc_ui_wait_for_conn(sk, sk->sk_rcvtimeo);
-       if (rc)
-               dprintk("%s: llc_ui_wait_for_conn failed=%d\n", __FUNCTION__, rc);
+
+       if (sk->sk_state == TCP_SYN_SENT) {
+               const long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
+
+               if (!timeo || !llc_ui_wait_for_conn(sk, timeo))
+                       goto out;
+
+               rc = sock_intr_errno(timeo);
+               if (signal_pending(current))
+                       goto out;
+       }
+
+       if (sk->sk_state == TCP_CLOSE)
+               goto sock_error;
+
+       sock->state = SS_CONNECTED;
+       rc = 0;
 out:
        release_sock(sk);
        return rc;
+sock_error:
+       rc = sock_error(sk) ? : -ECONNABORTED;
+       sock->state = SS_UNCONNECTED;
+       goto out;
 }
 
 /**
@@ -461,10 +472,10 @@ static int llc_ui_listen(struct socket *sock, int backlog)
        int rc = -EINVAL;
 
        lock_sock(sk);
-       if (sock->state != SS_UNCONNECTED)
+       if (unlikely(sock->state != SS_UNCONNECTED))
                goto out;
        rc = -EOPNOTSUPP;
-       if (sk->sk_type != SOCK_STREAM)
+       if (unlikely(sk->sk_type != SOCK_STREAM))
                goto out;
        rc = -EAGAIN;
        if (sock_flag(sk, SOCK_ZAPPED))
@@ -483,20 +494,14 @@ out:
        return rc;
 }
 
-static int llc_ui_wait_for_disc(struct sock *sk, int timeout)
+static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
 {
-       DECLARE_WAITQUEUE(wait, current);
-       int rc;
+       DEFINE_WAIT(wait);
+       int rc = 0;
 
-       add_wait_queue_exclusive(sk->sk_sleep, &wait);
-       for (;;) {
-               __set_current_state(TASK_INTERRUPTIBLE);
-               rc = 0;
-               if (sk->sk_state != TCP_CLOSE) {
-                       release_sock(sk);
-                       timeout = schedule_timeout(timeout);
-                       lock_sock(sk);
-               } else
+       while (1) {
+               prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+               if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE))
                        break;
                rc = -ERESTARTSYS;
                if (signal_pending(current))
@@ -504,65 +509,40 @@ static int llc_ui_wait_for_disc(struct sock *sk, int timeout)
                rc = -EAGAIN;
                if (!timeout)
                        break;
+               rc = 0;
        }
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(sk->sk_sleep, &wait);
+       finish_wait(sk->sk_sleep, &wait);
        return rc;
 }
 
-static int llc_ui_wait_for_conn(struct sock *sk, int timeout)
+static int llc_ui_wait_for_conn(struct sock *sk, long timeout)
 {
-       DECLARE_WAITQUEUE(wait, current);
-       int rc;
+       DEFINE_WAIT(wait);
 
-       add_wait_queue_exclusive(sk->sk_sleep, &wait);
-       for (;;) {
-               __set_current_state(TASK_INTERRUPTIBLE);
-               rc = -EAGAIN;
-               if (sk->sk_state == TCP_CLOSE)
-                       break;
-               rc = 0;
-               if (sk->sk_state != TCP_ESTABLISHED) {
-                       release_sock(sk);
-                       timeout = schedule_timeout(timeout);
-                       lock_sock(sk);
-               } else
+       while (1) {
+               prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+               if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT))
                        break;
-               rc = -ERESTARTSYS;
-               if (signal_pending(current))
-                       break;
-               rc = -EAGAIN;
-               if (!timeout)
+               if (signal_pending(current) || !timeout)
                        break;
        }
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(sk->sk_sleep, &wait);
-       return rc;
+       finish_wait(sk->sk_sleep, &wait);
+       return timeout;
 }
 
-static int llc_ui_wait_for_data(struct sock *sk, int timeout)
+static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
 {
-       DECLARE_WAITQUEUE(wait, current);
-       int rc = 0;
+       DEFINE_WAIT(wait);
+       struct llc_sock *llc = llc_sk(sk);
+       int rc;
 
-       add_wait_queue_exclusive(sk->sk_sleep, &wait);
-       for (;;) {
-               __set_current_state(TASK_INTERRUPTIBLE);
-               if (sk->sk_shutdown & RCV_SHUTDOWN)
-                       break;
-               /*
-                * Well, if we have backlog, try to process it now.
-                */
-                if (sk->sk_backlog.tail) {
-                       release_sock(sk);
-                       lock_sock(sk);
-               }
+       while (1) {
+               prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
                rc = 0;
-               if (skb_queue_empty(&sk->sk_receive_queue)) {
-                       release_sock(sk);
-                       timeout = schedule_timeout(timeout);
-                       lock_sock(sk);
-               } else
+               if (sk_wait_event(sk, &timeout,
+                                 (sk->sk_shutdown & RCV_SHUTDOWN) ||
+                                 (!llc_data_accept_state(llc->state) &&
+                                  !llc->p_flag)))
                        break;
                rc = -ERESTARTSYS;
                if (signal_pending(current))
@@ -571,40 +551,35 @@ static int llc_ui_wait_for_data(struct sock *sk, int timeout)
                if (!timeout)
                        break;
        }
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(sk->sk_sleep, &wait);
+       finish_wait(sk->sk_sleep, &wait);
        return rc;
 }
 
-static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout)
+static int llc_wait_data(struct sock *sk, long timeo)
 {
-       DECLARE_WAITQUEUE(wait, current);
-       struct llc_sock *llc = llc_sk(sk);
        int rc;
 
-       add_wait_queue_exclusive(sk->sk_sleep, &wait);
-       for (;;) {
-               dprintk("%s: looping...\n", __FUNCTION__);
-               __set_current_state(TASK_INTERRUPTIBLE);
-               rc = -ENOTCONN;
-               if (sk->sk_shutdown & RCV_SHUTDOWN)
+       while (1) {
+               /*
+                * POSIX 1003.1g mandates this order.
+                */
+               if (sk->sk_err) {
+                       rc = sock_error(sk);
                        break;
+               }
                rc = 0;
-               if (llc_data_accept_state(llc->state) || llc->p_flag) {
-                       release_sock(sk);
-                       timeout = schedule_timeout(timeout);
-                       lock_sock(sk);
-               } else
+               if (sk->sk_shutdown & RCV_SHUTDOWN)
                        break;
-               rc = -ERESTARTSYS;
+               rc = -EAGAIN;
+               if (!timeo)
+                       break;
+               rc = sock_intr_errno(timeo);
                if (signal_pending(current))
                        break;
-               rc = -EAGAIN;
-               if (!timeout)
+               rc = 0;
+               if (sk_wait_data(sk, &timeo))
                        break;
        }
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(sk->sk_sleep, &wait);
        return rc;
 }
 
@@ -627,15 +602,18 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
        dprintk("%s: accepting on %02X\n", __FUNCTION__,
                llc_sk(sk)->laddr.lsap);
        lock_sock(sk);
-       if (sk->sk_type != SOCK_STREAM)
+       if (unlikely(sk->sk_type != SOCK_STREAM))
                goto out;
        rc = -EINVAL;
-       if (sock->state != SS_UNCONNECTED || sk->sk_state != TCP_LISTEN)
+       if (unlikely(sock->state != SS_UNCONNECTED ||
+                    sk->sk_state != TCP_LISTEN))
                goto out;
        /* wait for a connection to arrive. */
-       rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo);
-       if (rc)
-               goto out;
+       if (skb_queue_empty(&sk->sk_receive_queue)) {
+               rc = llc_wait_data(sk, sk->sk_rcvtimeo);
+               if (rc)
+                       goto out;
+       }
        dprintk("%s: got a new connection on %02X\n", __FUNCTION__,
                llc_sk(sk)->laddr.lsap);
        skb = skb_dequeue(&sk->sk_receive_queue);
@@ -657,7 +635,6 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
        /* put original socket back into a clean listen state. */
        sk->sk_state = TCP_LISTEN;
        sk->sk_ack_backlog--;
-       skb->sk = NULL;
        dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,
                llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);
 frees:
@@ -671,56 +648,167 @@ out:
  *     llc_ui_recvmsg - copy received data to the socket user.
  *     @sock: Socket to copy data from.
  *     @msg: Various user space related information.
- *     @size: Size of user buffer.
+ *     @len: Size of user buffer.
  *     @flags: User specified flags.
  *
  *     Copy received data to the socket user.
  *     Returns non-negative upon success, negative otherwise.
  */
 static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
-                         struct msghdr *msg, size_t size, int flags)
+                         struct msghdr *msg, size_t len, int flags)
 {
-       struct sock *sk = sock->sk;
        struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;
-       struct sk_buff *skb;
+       const int nonblock = flags & MSG_DONTWAIT;
+       struct sk_buff *skb = NULL;
+       struct sock *sk = sock->sk;
+       struct llc_sock *llc = llc_sk(sk);
        size_t copied = 0;
-       int rc = -ENOMEM, timeout;
-       int noblock = flags & MSG_DONTWAIT;
+       u32 peek_seq = 0;
+       u32 *seq;
+       unsigned long used;
+       int target;     /* Read at least this many bytes */
+       long timeo;
 
-       dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__,
-               llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);
        lock_sock(sk);
-       timeout = sock_rcvtimeo(sk, noblock);
-       rc = llc_ui_wait_for_data(sk, timeout);
-       if (rc) {
-               dprintk("%s: llc_ui_wait_for_data failed recv "
-                       "in %02X from %02X\n", __FUNCTION__,
-                       llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);
+       copied = -ENOTCONN;
+       if (sk->sk_state == TCP_LISTEN)
                goto out;
-       }
-       skb = skb_dequeue(&sk->sk_receive_queue);
-       if (!skb) /* shutdown */
-               goto out;
-       copied = skb->len;
-       if (copied > size)
-               copied = size;
-       rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-       if (rc)
-               goto dgram_free;
-       if (skb->len > copied) {
-               skb_pull(skb, copied);
-               skb_queue_head(&sk->sk_receive_queue, skb);
-       }
-       if (uaddr)
-               memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
-       msg->msg_namelen = sizeof(*uaddr);
-       if (!skb->next) {
-dgram_free:
-               kfree_skb(skb);
-       }
+
+       timeo = sock_rcvtimeo(sk, nonblock);
+
+       seq = &llc->copied_seq;
+       if (flags & MSG_PEEK) {
+               peek_seq = llc->copied_seq;
+               seq = &peek_seq;
+       }
+
+       target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
+       copied = 0;
+
+       do {
+               u32 offset;
+
+               /*
+                * We need to check signals first, to get correct SIGURG
+                * handling. FIXME: Need to check this doesn't impact 1003.1g
+                * and move it down to the bottom of the loop
+                */
+               if (signal_pending(current)) {
+                       if (copied)
+                               break;
+                       copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
+                       break;
+               }
+
+               /* Next get a buffer. */
+
+               skb = skb_peek(&sk->sk_receive_queue);
+               if (skb) {
+                       offset = *seq;
+                       goto found_ok_skb;
+               }
+               /* Well, if we have backlog, try to process it now yet. */
+
+               if (copied >= target && !sk->sk_backlog.tail)
+                       break;
+
+               if (copied) {
+                       if (sk->sk_err ||
+                           sk->sk_state == TCP_CLOSE ||
+                           (sk->sk_shutdown & RCV_SHUTDOWN) ||
+                           !timeo ||
+                           (flags & MSG_PEEK))
+                               break;
+               } else {
+                       if (sock_flag(sk, SOCK_DONE))
+                               break;
+
+                       if (sk->sk_err) {
+                               copied = sock_error(sk);
+                               break;
+                       }
+                       if (sk->sk_shutdown & RCV_SHUTDOWN)
+                               break;
+
+                       if (sk->sk_state == TCP_CLOSE) {
+                               if (!sock_flag(sk, SOCK_DONE)) {
+                                       /*
+                                        * This occurs when user tries to read
+                                        * from never connected socket.
+                                        */
+                                       copied = -ENOTCONN;
+                                       break;
+                               }
+                               break;
+                       }
+                       if (!timeo) {
+                               copied = -EAGAIN;
+                               break;
+                       }
+               }
+
+               if (copied >= target) { /* Do not sleep, just process backlog. */
+                       release_sock(sk);
+                       lock_sock(sk);
+               } else
+                       sk_wait_data(sk, &timeo);
+
+               if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) {
+                       if (net_ratelimit())
+                               printk(KERN_DEBUG "LLC(%s:%d): Application "
+                                                 "bug, race in MSG_PEEK.\n",
+                                      current->comm, current->pid);
+                       peek_seq = llc->copied_seq;
+               }
+               continue;
+       found_ok_skb:
+               /* Ok so how much can we use? */
+               used = skb->len - offset;
+               if (len < used)
+                       used = len;
+
+               if (!(flags & MSG_TRUNC)) {
+                       int rc = skb_copy_datagram_iovec(skb, offset,
+                                                        msg->msg_iov, used);
+                       if (rc) {
+                               /* Exception. Bailout! */
+                               if (!copied)
+                                       copied = -EFAULT;
+                               break;
+                       }
+               }
+
+               *seq += used;
+               copied += used;
+               len -= used;
+
+               if (used + offset < skb->len)
+                       continue;
+
+               if (!(flags & MSG_PEEK)) {
+                       sk_eat_skb(sk, skb);
+                       *seq = 0;
+               }
+       } while (len > 0);
+
+       /* 
+        * According to UNIX98, msg_name/msg_namelen are ignored
+        * on connected socket. -ANK
+        * But... af_llc still doesn't have separate sets of methods for
+        * SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will
+        * eventually fix this tho :-) -acme
+        */
+       if (sk->sk_type == SOCK_DGRAM)
+               goto copy_uaddr;
 out:
        release_sock(sk);
-       return rc ? : copied;
+       return copied;
+copy_uaddr:
+       if (uaddr != NULL && skb != NULL) {
+               memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
+               msg->msg_namelen = sizeof(*uaddr);
+       }
+       goto out;
 }
 
 /**
@@ -740,7 +828,6 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
        struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name;
        int flags = msg->msg_flags;
        int noblock = flags & MSG_DONTWAIT;
-       struct net_device *dev;
        struct sk_buff *skb;
        size_t size = 0;
        int rc = -EINVAL, copied = 0, hdrlen;
@@ -763,19 +850,17 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
                if (rc)
                        goto release;
        }
-       dev = llc->dev;
-       hdrlen = dev->hard_header_len + llc_ui_header_len(sk, addr);
+       hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr);
        size = hdrlen + len;
-       if (size > dev->mtu)
-               size = dev->mtu;
+       if (size > llc->dev->mtu)
+               size = llc->dev->mtu;
        copied = size - hdrlen;
        release_sock(sk);
        skb = sock_alloc_send_skb(sk, size, noblock, &rc);
        lock_sock(sk);
        if (!skb)
                goto release;
-       skb->sk       = sk;
-       skb->dev      = dev;
+       skb->dev      = llc->dev;
        skb->protocol = llc_proto_type(addr->sllc_arphrd);
        skb_reserve(skb, hdrlen); 
        rc = memcpy_fromiovec(skb_put(skb, copied), msg->msg_iov, copied);
@@ -800,15 +885,13 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
        if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua))
                goto out;
        rc = llc_ui_send_data(sk, skb, noblock);
-       if (rc)
-               dprintk("%s: llc_ui_send_data failed: %d\n", __FUNCTION__, rc);
 out:
-       if (rc)
+       if (rc) {
                kfree_skb(skb);
 release:
-       if (rc)
                dprintk("%s: failed sending from %02X to %02X: %d\n",
                        __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc);
+       }
        release_sock(sk);
        return rc ? : copied;
 }
@@ -895,7 +978,7 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
        int rc = -EINVAL, opt;
 
        lock_sock(sk);
-       if (level != SOL_LLC || optlen != sizeof(int))
+       if (unlikely(level != SOL_LLC || optlen != sizeof(int)))
                goto out;
        rc = get_user(opt, (int __user *)optval);
        if (rc)
@@ -915,22 +998,22 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
        case LLC_OPT_ACK_TMR_EXP:
                if (opt > LLC_OPT_MAX_ACK_TMR_EXP)
                        goto out;
-               llc->ack_timer.expire = opt;
+               llc->ack_timer.expire = opt * HZ;
                break;
        case LLC_OPT_P_TMR_EXP:
                if (opt > LLC_OPT_MAX_P_TMR_EXP)
                        goto out;
-               llc->pf_cycle_timer.expire = opt;
+               llc->pf_cycle_timer.expire = opt * HZ;
                break;
        case LLC_OPT_REJ_TMR_EXP:
                if (opt > LLC_OPT_MAX_REJ_TMR_EXP)
                        goto out;
-               llc->rej_sent_timer.expire = opt;
+               llc->rej_sent_timer.expire = opt * HZ;
                break;
        case LLC_OPT_BUSY_TMR_EXP:
                if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)
                        goto out;
-               llc->busy_state_timer.expire = opt;
+               llc->busy_state_timer.expire = opt * HZ;
                break;
        case LLC_OPT_TX_WIN:
                if (opt > LLC_OPT_MAX_WIN)
@@ -970,7 +1053,7 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
        int val = 0, len = 0, rc = -EINVAL;
 
        lock_sock(sk);
-       if (level != SOL_LLC)
+       if (unlikely(level != SOL_LLC))
                goto out;
        rc = get_user(len, optlen);
        if (rc)
@@ -980,17 +1063,17 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
                goto out;
        switch (optname) {
        case LLC_OPT_RETRY:
-               val = llc->n2;                          break;
+               val = llc->n2;                                  break;
        case LLC_OPT_SIZE:
-               val = llc->n1;                          break;
+               val = llc->n1;                                  break;
        case LLC_OPT_ACK_TMR_EXP:
-               val = llc->ack_timer.expire;            break;
+               val = llc->ack_timer.expire / HZ;               break;
        case LLC_OPT_P_TMR_EXP:
-               val = llc->pf_cycle_timer.expire;       break;
+               val = llc->pf_cycle_timer.expire / HZ;          break;
        case LLC_OPT_REJ_TMR_EXP:
-               val = llc->rej_sent_timer.expire;       break;
+               val = llc->rej_sent_timer.expire / HZ;          break;
        case LLC_OPT_BUSY_TMR_EXP:
-               val = llc->busy_state_timer.expire;     break;
+               val = llc->busy_state_timer.expire / HZ;        break;
        case LLC_OPT_TX_WIN:
                val = llc->k;                           break;
        case LLC_OPT_RX_WIN:
@@ -1034,8 +1117,12 @@ static struct proto_ops llc_ui_ops = {
        .sendpage    = sock_no_sendpage,
 };
 
-extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
-extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
+static char llc_proc_err_msg[] __initdata =
+        KERN_CRIT "LLC: Unable to register the proc_fs entries\n";
+static char llc_sysctl_err_msg[] __initdata =
+        KERN_CRIT "LLC: Unable to register the sysctl entries\n";
+static char llc_sock_err_msg[] __initdata =
+        KERN_CRIT "LLC: Unable to register the network family\n";
 
 static int __init llc2_init(void)
 {
@@ -1048,13 +1135,28 @@ static int __init llc2_init(void)
        llc_station_init();
        llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
        rc = llc_proc_init();
-       if (rc != 0)
+       if (rc != 0) {
+               printk(llc_proc_err_msg);
                goto out_unregister_llc_proto;
-       sock_register(&llc_ui_family_ops);
+       }
+       rc = llc_sysctl_init();
+       if (rc) {
+               printk(llc_sysctl_err_msg);
+               goto out_proc;
+       }
+       rc = sock_register(&llc_ui_family_ops);
+       if (rc) {
+               printk(llc_sock_err_msg);
+               goto out_sysctl;
+       }
        llc_add_pack(LLC_DEST_SAP, llc_sap_handler);
        llc_add_pack(LLC_DEST_CONN, llc_conn_handler);
 out:
        return rc;
+out_sysctl:
+       llc_sysctl_exit();
+out_proc:
+       llc_proc_exit();
 out_unregister_llc_proto:
        proto_unregister(&llc_proto);
        goto out;
@@ -1067,6 +1169,7 @@ static void __exit llc2_exit(void)
        llc_remove_pack(LLC_DEST_CONN);
        sock_unregister(PF_LLC);
        llc_proc_exit();
+       llc_sysctl_exit();
        proto_unregister(&llc_proto);
 }
 
index b218be4c10ec44092e59deb2fdc149e027d7da79..b0bcfb1f12dd49b90a69ab7967c050f3652e3472 100644 (file)
@@ -60,23 +60,10 @@ int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb)
 {
-       int rc = -ENOTCONN;
-       u8 dsap;
-       struct llc_sap *sap;
-
-       llc_pdu_decode_dsap(skb, &dsap);
-       sap = llc_sap_find(dsap);
-       if (sap) {
-               struct llc_conn_state_ev *ev = llc_conn_ev(skb);
-               struct llc_sock *llc = llc_sk(sk);
+       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
-               llc_pdu_decode_sa(skb, llc->daddr.mac);
-               llc_pdu_decode_da(skb, llc->laddr.mac);
-               llc->dev = skb->dev;
-               ev->ind_prim = LLC_CONN_PRIM;
-               rc = 0;
-       }
-       return rc;
+       ev->ind_prim = LLC_CONN_PRIM;
+       return 0;
 }
 
 int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb)
@@ -120,10 +107,8 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb)
                        reason = LLC_DISC_REASON_RX_DISC_CMD_PDU;
        } else if (ev->type == LLC_CONN_EV_TYPE_ACK_TMR)
                reason = LLC_DISC_REASON_ACK_TMR_EXP;
-       else {
-               reason = 0;
+       else
                rc = -EINVAL;
-       }
        if (!rc) {
                ev->reason   = reason;
                ev->ind_prim = LLC_DISC_PRIM;
@@ -160,9 +145,6 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb)
                           LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME) {
                        reason = LLC_RESET_REASON_REMOTE;
                        rc = 0;
-               } else {
-                       reason = 0;
-                       rc  = 1;
                }
                break;
        case LLC_CONN_EV_TYPE_ACK_TMR:
@@ -172,8 +154,7 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb)
                if (llc->retry_count > llc->n2) {
                        reason = LLC_RESET_REASON_LOCAL;
                        rc = 0;
-               } else
-                       rc = 1;
+               }
                break;
        }
        if (!rc) {
@@ -217,18 +198,17 @@ int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk,
 int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_CMD);
                llc_pdu_init_as_disc_cmd(nskb, 1);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
                llc_conn_ac_set_p_flag_1(sk, skb);
@@ -243,20 +223,19 @@ free:
 int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
                u8 f_bit;
 
-               nskb->dev = llc->dev;
                llc_pdu_decode_pf_bit(skb, &f_bit);
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
                llc_pdu_init_as_dm_rsp(nskb, f_bit);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -270,19 +249,17 @@ free:
 int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
-               u8 f_bit = 1;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
-               llc_pdu_init_as_dm_rsp(nskb, f_bit);
+               llc_pdu_init_as_dm_rsp(nskb, 1);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -306,17 +283,16 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb)
                llc_pdu_decode_pf_bit(skb, &f_bit);
        else
                f_bit = 0;
-       nskb = llc_alloc_frame();
+       nskb = llc_alloc_frame(sk, llc->dev);
        if (nskb) {
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
                llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS,
                                         llc->vR, INCORRECT);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -330,21 +306,19 @@ free:
 int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               u8 f_bit = 0;
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
                struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)&llc->rx_pdu_hdr;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
-               llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS,
+               llc_pdu_init_as_frmr_rsp(nskb, pdu, 0, llc->vS,
                                         llc->vR, INCORRECT);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -360,21 +334,20 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
        u8 f_bit;
        int rc = -ENOBUFS;
        struct sk_buff *nskb;
+       struct llc_sock *llc = llc_sk(sk);
 
        llc_pdu_decode_pf_bit(skb, &f_bit);
-       nskb = llc_alloc_frame();
+       nskb = llc_alloc_frame(sk, llc->dev);
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
                struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
                llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS,
                                         llc->vR, INCORRECT);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -395,7 +368,7 @@ int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
                            llc->daddr.lsap, LLC_PDU_CMD);
        llc_pdu_init_as_i_cmd(skb, 1, llc->vS, llc->vR);
        rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
-       if (!rc) {
+       if (likely(!rc)) {
                llc_conn_send_pdu(sk, skb);
                llc_conn_ac_inc_vs_by_1(sk, skb);
        }
@@ -412,7 +385,7 @@ static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb)
                            llc->daddr.lsap, LLC_PDU_CMD);
        llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR);
        rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
-       if (!rc) {
+       if (likely(!rc)) {
                llc_conn_send_pdu(sk, skb);
                llc_conn_ac_inc_vs_by_1(sk, skb);
        }
@@ -429,7 +402,7 @@ int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
                            llc->daddr.lsap, LLC_PDU_CMD);
        llc_pdu_init_as_i_cmd(skb, 0, llc->vS, llc->vR);
        rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
-       if (!rc) {
+       if (likely(!rc)) {
                llc_conn_send_pdu(sk, skb);
                llc_conn_ac_inc_vs_by_1(sk, skb);
        }
@@ -451,18 +424,17 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk,
        u8 nr;
        struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
                llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (!rc)
+               if (likely(!rc))
                        llc_conn_send_pdu(sk, nskb);
                else
                        kfree_skb(skb);
@@ -487,18 +459,17 @@ int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
 int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_CMD);
                llc_pdu_init_as_rej_cmd(nskb, 1, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -512,19 +483,17 @@ free:
 int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               u8 f_bit = 1;
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
-               llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR);
+               llc_pdu_init_as_rej_rsp(nskb, 1, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -538,19 +507,17 @@ free:
 int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
-               u8 f_bit = 0;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
-               llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR);
+               llc_pdu_init_as_rej_rsp(nskb, 0, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -564,18 +531,17 @@ free:
 int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_CMD);
                llc_pdu_init_as_rnr_cmd(nskb, 1, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -589,19 +555,17 @@ free:
 int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
-               u8 f_bit = 1;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
-               llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR);
+               llc_pdu_init_as_rnr_rsp(nskb, 1, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -615,19 +579,17 @@ free:
 int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               u8 f_bit = 0;
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
-               llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR);
+               llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -645,7 +607,7 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb)
        if (!llc->remote_busy_flag) {
                llc->remote_busy_flag = 1;
                mod_timer(&llc->busy_state_timer.timer,
-                        jiffies + llc->busy_state_timer.expire * HZ);
+                        jiffies + llc->busy_state_timer.expire);
        }
        return 0;
 }
@@ -653,18 +615,17 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb)
 int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
                llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -678,18 +639,17 @@ free:
 int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_CMD);
                llc_pdu_init_as_rr_cmd(nskb, 1, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -703,19 +663,18 @@ free:
 int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
                u8 f_bit = 1;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
                llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -729,19 +688,17 @@ free:
 int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
-               u8 f_bit = 1;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
-               llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR);
+               llc_pdu_init_as_rr_rsp(nskb, 1, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -755,18 +712,17 @@ free:
 int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
                llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -780,18 +736,17 @@ free:
 int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
                llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -815,8 +770,8 @@ void llc_conn_set_p_flag(struct sock *sk, u8 value)
 int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
        struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
                struct llc_sap *sap = llc->sap;
@@ -824,12 +779,11 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
 
                if (llc->dev->flags & IFF_LOOPBACK)
                        dmac = llc->dev->dev_addr;
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_CMD);
                llc_pdu_init_as_sabme_cmd(nskb, 1);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, dmac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
                llc_conn_set_p_flag(sk, 1);
@@ -845,11 +799,11 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
 {
        u8 f_bit;
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        llc_pdu_decode_pf_bit(skb, &f_bit);
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
                nskb->dev = llc->dev;
@@ -857,7 +811,7 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
                                    llc->daddr.lsap, LLC_PDU_RSP);
                llc_pdu_init_as_ua_rsp(nskb, f_bit);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -886,7 +840,7 @@ int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb)
 
        llc_conn_set_p_flag(sk, 1);
        mod_timer(&llc->pf_cycle_timer.timer,
-                 jiffies + llc->pf_cycle_timer.expire * HZ);
+                 jiffies + llc->pf_cycle_timer.expire);
        return 0;
 }
 
@@ -957,7 +911,7 @@ static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk,
                            llc->daddr.lsap, LLC_PDU_RSP);
        llc_pdu_init_as_i_cmd(skb, llc->ack_pf, llc->vS, llc->vR);
        rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
-       if (!rc) {
+       if (likely(!rc)) {
                llc_conn_send_pdu(sk, skb);
                llc_conn_ac_inc_vs_by_1(sk, skb);
        }
@@ -1001,18 +955,17 @@ static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk,
                                               struct sk_buff *skb)
 {
        int rc = -ENOBUFS;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct llc_sock *llc = llc_sk(sk);
+       struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev);
 
        if (nskb) {
-               struct llc_sock *llc = llc_sk(sk);
                struct llc_sap *sap = llc->sap;
 
-               nskb->dev = llc->dev;
                llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
                                    llc->daddr.lsap, LLC_PDU_RSP);
                llc_pdu_init_as_rr_rsp(nskb, llc->ack_pf, llc->vR);
                rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
-               if (rc)
+               if (unlikely(rc))
                        goto free;
                llc_conn_send_pdu(sk, nskb);
        }
@@ -1165,7 +1118,7 @@ int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb)
 {
        struct llc_sock *llc = llc_sk(sk);
 
-       mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire * HZ);
+       mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire);
        return 0;
 }
 
@@ -1174,7 +1127,7 @@ int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb)
        struct llc_sock *llc = llc_sk(sk);
 
        mod_timer(&llc->rej_sent_timer.timer,
-                 jiffies + llc->rej_sent_timer.expire * HZ);
+                 jiffies + llc->rej_sent_timer.expire);
        return 0;
 }
 
@@ -1185,7 +1138,7 @@ int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
 
        if (!timer_pending(&llc->ack_timer.timer))
                mod_timer(&llc->ack_timer.timer,
-                         jiffies + llc->ack_timer.expire * HZ);
+                         jiffies + llc->ack_timer.expire);
        return 0;
 }
 
@@ -1233,7 +1186,7 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb)
                }
                if (unacked)
                        mod_timer(&llc->ack_timer.timer,
-                                 jiffies + llc->ack_timer.expire * HZ);
+                                 jiffies + llc->ack_timer.expire);
        } else if (llc->failed_data_req) {
                u8 f_bit;
 
@@ -1354,13 +1307,13 @@ int llc_conn_ac_set_vs_nr(struct sock *sk, struct sk_buff *skb)
        return 0;
 }
 
-int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb)
+static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb)
 {
        llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % 128;
        return 0;
 }
 
-void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data)
+static void llc_conn_tmr_common_cb(unsigned long timeout_data, u8 type)
 {
        struct sock *sk = (struct sock *)timeout_data;
        struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
@@ -1369,59 +1322,31 @@ void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data)
        if (skb) {
                struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
-               skb->sk  = sk;
-               ev->type = LLC_CONN_EV_TYPE_P_TMR;
+               skb_set_owner_r(skb, sk);
+               ev->type = type;
                llc_process_tmr_ev(sk, skb);
        }
        bh_unlock_sock(sk);
 }
 
-void llc_conn_busy_tmr_cb(unsigned long timeout_data)
+void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data)
 {
-       struct sock *sk = (struct sock *)timeout_data;
-       struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
-
-       bh_lock_sock(sk);
-       if (skb) {
-               struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_P_TMR);
+}
 
-               skb->sk  = sk;
-               ev->type = LLC_CONN_EV_TYPE_BUSY_TMR;
-               llc_process_tmr_ev(sk, skb);
-       }
-       bh_unlock_sock(sk);
+void llc_conn_busy_tmr_cb(unsigned long timeout_data)
+{
+       llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_BUSY_TMR);
 }
 
 void llc_conn_ack_tmr_cb(unsigned long timeout_data)
 {
-       struct sock* sk = (struct sock *)timeout_data;
-       struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
-
-       bh_lock_sock(sk);
-       if (skb) {
-               struct llc_conn_state_ev *ev = llc_conn_ev(skb);
-
-               skb->sk  = sk;
-               ev->type = LLC_CONN_EV_TYPE_ACK_TMR;
-               llc_process_tmr_ev(sk, skb);
-       }
-       bh_unlock_sock(sk);
+       llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_ACK_TMR);
 }
 
 void llc_conn_rej_tmr_cb(unsigned long timeout_data)
 {
-       struct sock *sk = (struct sock *)timeout_data;
-       struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
-
-       bh_lock_sock(sk);
-       if (skb) {
-               struct llc_conn_state_ev *ev = llc_conn_ev(skb);
-
-               skb->sk  = sk;
-               ev->type = LLC_CONN_EV_TYPE_REJ_TMR;
-               llc_process_tmr_ev(sk, skb);
-       }
-       bh_unlock_sock(sk);
+       llc_conn_tmr_common_cb(timeout_data, LLC_CONN_EV_TYPE_REJ_TMR);
 }
 
 int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb)
index d5bdb53a348f3002c184f3f0059ebbf183ba3309..c5deda24661486abeb62dc6a22b37e7ba366527e 100644 (file)
@@ -37,6 +37,7 @@
 #include <net/llc_conn.h>
 #include <net/llc_sap.h>
 #include <net/sock.h>
+#include <net/llc_c_ac.h>
 #include <net/llc_c_ev.h>
 #include <net/llc_pdu.h>
 
@@ -46,8 +47,6 @@
 #define dprintk(args...)
 #endif
 
-extern u16 llc_circular_between(u8 a, u8 b, u8 c);
-
 /**
  *     llc_util_ns_inside_rx_window - check if sequence number is in rx window
  *     @ns: sequence number of received pdu.
@@ -99,7 +98,7 @@ out:
 
 int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->prim == LLC_CONN_PRIM &&
               ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
@@ -107,7 +106,7 @@ int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->prim == LLC_DATA_PRIM &&
               ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
@@ -115,7 +114,7 @@ int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->prim == LLC_DISC_PRIM &&
               ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
@@ -123,7 +122,7 @@ int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->prim == LLC_RESET_PRIM &&
               ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
@@ -131,7 +130,7 @@ int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
               ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1;
@@ -139,7 +138,7 @@ int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
               ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1;
@@ -152,7 +151,7 @@ int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+       const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 
        return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
               LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC ? 0 : 1;
@@ -160,7 +159,7 @@ int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+       const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
               LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM ? 0 : 1;
@@ -168,7 +167,7 @@ int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+       const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
               LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR ? 0 : 1;
@@ -176,7 +175,7 @@ int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return llc_conn_space(sk, skb) &&
               LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
@@ -186,7 +185,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return llc_conn_space(sk, skb) &&
               LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
@@ -197,9 +196,9 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
 int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
                                              struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-       u8 vr = llc_sk(sk)->vR;
-       u8 ns = LLC_I_GET_NS(pdu);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const u8 vr = llc_sk(sk)->vR;
+       const u8 ns = LLC_I_GET_NS(pdu);
 
        return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
               LLC_I_PF_IS_0(pdu) && ns != vr &&
@@ -209,9 +208,9 @@ int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
 int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
                                              struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-       u8 vr = llc_sk(sk)->vR;
-       u8 ns = LLC_I_GET_NS(pdu);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const u8 vr = llc_sk(sk)->vR;
+       const u8 ns = LLC_I_GET_NS(pdu);
 
        return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
               LLC_I_PF_IS_1(pdu) && ns != vr &&
@@ -221,10 +220,11 @@ int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
 int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
                                             struct sk_buff *skb)
 {
-       struct llc_pdu_sn * pdu = llc_pdu_sn_hdr(skb);
-       u8 vr = llc_sk(sk)->vR;
-       u8 ns = LLC_I_GET_NS(pdu);
-       u16 rc = LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
+       const struct llc_pdu_sn * pdu = llc_pdu_sn_hdr(skb);
+       const u8 vr = llc_sk(sk)->vR;
+       const u8 ns = LLC_I_GET_NS(pdu);
+       const u16 rc = LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
+               ns != vr &&
                 llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
        if (!rc)
                dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
@@ -234,7 +234,7 @@ int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
 
 int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return llc_conn_space(sk, skb) &&
               LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
@@ -244,7 +244,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
               LLC_I_PF_IS_1(pdu) &&
@@ -253,7 +253,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return llc_conn_space(sk, skb) &&
               LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
@@ -263,9 +263,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
 int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
                                              struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-       u8 vr = llc_sk(sk)->vR;
-       u8 ns = LLC_I_GET_NS(pdu);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const u8 vr = llc_sk(sk)->vR;
+       const u8 ns = LLC_I_GET_NS(pdu);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
               LLC_I_PF_IS_0(pdu) && ns != vr &&
@@ -275,9 +275,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
 int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
                                              struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-       u8 vr = llc_sk(sk)->vR;
-       u8 ns = LLC_I_GET_NS(pdu);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const u8 vr = llc_sk(sk)->vR;
+       const u8 ns = LLC_I_GET_NS(pdu);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
               LLC_I_PF_IS_1(pdu) && ns != vr &&
@@ -287,9 +287,9 @@ int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
 int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
                                              struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-       u8 vr = llc_sk(sk)->vR;
-       u8 ns = LLC_I_GET_NS(pdu);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const u8 vr = llc_sk(sk)->vR;
+       const u8 ns = LLC_I_GET_NS(pdu);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
               !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
@@ -298,10 +298,11 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
 int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
                                             struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-       u8 vr = llc_sk(sk)->vR;
-       u8 ns = LLC_I_GET_NS(pdu);
-       u16 rc = LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const u8 vr = llc_sk(sk)->vR;
+       const u8 ns = LLC_I_GET_NS(pdu);
+       const u16 rc = LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_I(pdu) &&
+               ns != vr &&
                 llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
        if (!rc)
                dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
@@ -311,7 +312,7 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
 
 int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PF_IS_0(pdu) &&
@@ -320,7 +321,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PF_IS_1(pdu) &&
@@ -329,7 +330,7 @@ int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PF_IS_0(pdu) &&
@@ -338,7 +339,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PF_IS_1(pdu) &&
@@ -347,7 +348,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+       const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
@@ -355,7 +356,7 @@ int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PF_IS_0(pdu) &&
@@ -364,7 +365,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PF_IS_1(pdu) &&
@@ -373,7 +374,7 @@ int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PF_IS_0(pdu) &&
@@ -382,7 +383,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PF_IS_1(pdu) &&
@@ -391,7 +392,7 @@ int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PF_IS_0(pdu) &&
@@ -400,7 +401,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
               LLC_S_PF_IS_1(pdu) &&
@@ -409,7 +410,7 @@ int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return llc_conn_space(sk, skb) &&
               LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
@@ -419,7 +420,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        return llc_conn_space(sk, skb) &&
               LLC_PDU_IS_RSP(pdu) && LLC_PDU_TYPE_IS_S(pdu) &&
@@ -429,7 +430,7 @@ int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+       const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 
        return LLC_PDU_IS_CMD(pdu) && LLC_PDU_TYPE_IS_U(pdu) &&
               LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME ? 0 : 1;
@@ -446,7 +447,7 @@ int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
 int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
 {
        u16 rc = 1;
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
        if (LLC_PDU_IS_CMD(pdu)) {
                if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) {
@@ -461,7 +462,7 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb)
 int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
 {
        u16 rc = 1;
-       struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+       const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 
        if (LLC_PDU_IS_CMD(pdu)) {
                if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu))
@@ -477,32 +478,10 @@ int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
        return rc;
 }
 
-int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb)
-{
-       u16 rc = 1;
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-
-       if (LLC_PDU_IS_RSP(pdu)) {
-               if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) {
-                       if (LLC_I_PF_IS_1(pdu))
-                               rc = 0;
-               } else if (LLC_PDU_TYPE_IS_U(pdu))
-                       switch (LLC_U_PDU_RSP(pdu)) {
-                       case LLC_2_PDU_RSP_UA:
-                       case LLC_2_PDU_RSP_DM:
-                       case LLC_2_PDU_RSP_FRMR:
-                               if (LLC_U_PF_IS_1(pdu))
-                                       rc = 0;
-                               break;
-                       }
-       }
-       return rc;
-}
-
 int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb)
 {
        u16 rc = 1;
-       struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+       const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 
        if (LLC_PDU_IS_RSP(pdu)) {
                if (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu))
@@ -524,9 +503,9 @@ int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
                                               struct sk_buff *skb)
 {
        u16 rc = 1;
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-       u8 vs = llc_sk(sk)->vS;
-       u8 nr = LLC_I_GET_NR(pdu);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const u8 vs = llc_sk(sk)->vS;
+       const u8 nr = LLC_I_GET_NR(pdu);
 
        if (LLC_PDU_IS_CMD(pdu) &&
            (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
@@ -542,9 +521,9 @@ int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
                                               struct sk_buff *skb)
 {
        u16 rc = 1;
-       struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-       u8 vs = llc_sk(sk)->vS;
-       u8 nr = LLC_I_GET_NR(pdu);
+       const struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+       const u8 vs = llc_sk(sk)->vS;
+       const u8 nr = LLC_I_GET_NR(pdu);
 
        if (LLC_PDU_IS_RSP(pdu) &&
            (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
@@ -563,28 +542,28 @@ int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->type != LLC_CONN_EV_TYPE_P_TMR;
 }
 
 int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->type != LLC_CONN_EV_TYPE_ACK_TMR;
 }
 
 int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->type != LLC_CONN_EV_TYPE_REJ_TMR;
 }
 
 int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->type != LLC_CONN_EV_TYPE_BUSY_TMR;
 }
@@ -596,7 +575,7 @@ int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb)
 
 int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb)
 {
-       struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+       const struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
               ev->prim_type == LLC_CONN_EV_TX_BUFF_FULL ? 0 : 1;
index 4c644bc70eaec7b4a9f3f11d55f603afd72922b0..042b24a8ca4c2119904c34c90ce6020951c9525a 100644 (file)
@@ -40,6 +40,11 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
 /* Offset table on connection states transition diagram */
 static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
 
+int sysctl_llc2_ack_timeout = LLC2_ACK_TIME * HZ;
+int sysctl_llc2_p_timeout = LLC2_P_TIME * HZ;
+int sysctl_llc2_rej_timeout = LLC2_REJ_TIME * HZ;
+int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ;
+
 /**
  *     llc_conn_state_process - sends event to connection state machine
  *     @sk: connection
@@ -53,7 +58,7 @@ static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
 int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
 {
        int rc;
-       struct llc_sock *llc = llc_sk(sk);
+       struct llc_sock *llc = llc_sk(skb->sk);
        struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
        /*
@@ -63,13 +68,16 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
         */
        skb_get(skb);
        ev->ind_prim = ev->cfm_prim = 0;
-       rc = llc_conn_service(sk, skb); /* sending event to state machine */
-       if (rc) {
+       /*
+        * Send event to state machine
+        */
+       rc = llc_conn_service(skb->sk, skb);
+       if (unlikely(rc != 0)) {
                printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__);
                goto out_kfree_skb;
        }
 
-       if (!ev->ind_prim && !ev->cfm_prim) {
+       if (unlikely(!ev->ind_prim && !ev->cfm_prim)) {
                /* indicate or confirm not required */
                /* XXX this is not very pretty, perhaps we should store
                 * XXX indicate/confirm-needed state in the llc_conn_state_ev
@@ -80,13 +88,13 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
                goto out_skb_put;
        }
 
-       if (ev->ind_prim && ev->cfm_prim) /* Paranoia */
+       if (unlikely(ev->ind_prim && ev->cfm_prim)) /* Paranoia */
                skb_get(skb);
 
        switch (ev->ind_prim) {
        case LLC_DATA_PRIM:
-               llc_save_primitive(skb, LLC_DATA_PRIM);
-               if (sock_queue_rcv_skb(sk, skb)) {
+               llc_save_primitive(sk, skb, LLC_DATA_PRIM);
+               if (unlikely(sock_queue_rcv_skb(sk, skb))) {
                        /*
                         * shouldn't happen
                         */
@@ -95,13 +103,14 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
                        kfree_skb(skb);
                }
                break;
-       case LLC_CONN_PRIM: {
-               struct sock *parent = skb->sk;
-
-               skb->sk = sk;
-               skb_queue_tail(&parent->sk_receive_queue, skb);
-               sk->sk_state_change(parent);
-       }
+       case LLC_CONN_PRIM:
+               /*
+                * Can't be sock_queue_rcv_skb, because we have to leave the
+                * skb->sk pointing to the newly created struct sock in
+                * llc_conn_handler. -acme
+                */
+               skb_queue_tail(&sk->sk_receive_queue, skb);
+               sk->sk_state_change(sk);
                break;
        case LLC_DISC_PRIM:
                sock_hold(sk);
@@ -111,8 +120,8 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
                        sk->sk_socket->state  = SS_UNCONNECTED;
                        sk->sk_state          = TCP_CLOSE;
                        if (!sock_flag(sk, SOCK_DEAD)) {
-                               sk->sk_state_change(sk);
                                sock_set_flag(sk, SOCK_DEAD);
+                               sk->sk_state_change(sk);
                        }
                }
                kfree_skb(skb);
@@ -465,7 +474,7 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
 }
 
 /**
- *     llc_lookup_established - Finds connection for the remote/local sap/mac
+ *     __llc_lookup_established - Finds connection for the remote/local sap/mac
  *     @sap: SAP
  *     @daddr: address of remote LLC (MAC + SAP)
  *     @laddr: address of local LLC (MAC + SAP)
@@ -473,14 +482,16 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
  *     Search connection list of the SAP and finds connection using the remote
  *     mac, remote sap, local mac, and local sap. Returns pointer for
  *     connection found, %NULL otherwise.
+ *     Caller has to make sure local_bh is disabled.
  */
-struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
-                                   struct llc_addr *laddr)
+static struct sock *__llc_lookup_established(struct llc_sap *sap,
+                                            struct llc_addr *daddr,
+                                            struct llc_addr *laddr)
 {
        struct sock *rc;
        struct hlist_node *node;
 
-       read_lock_bh(&sap->sk_list.lock);
+       read_lock(&sap->sk_list.lock);
        sk_for_each(rc, node, &sap->sk_list.list) {
                struct llc_sock *llc = llc_sk(rc);
 
@@ -494,10 +505,22 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
        }
        rc = NULL;
 found:
-       read_unlock_bh(&sap->sk_list.lock);
+       read_unlock(&sap->sk_list.lock);
        return rc;
 }
 
+struct sock *llc_lookup_established(struct llc_sap *sap,
+                                   struct llc_addr *daddr,
+                                   struct llc_addr *laddr)
+{
+       struct sock *sk;
+
+       local_bh_disable();
+       sk = __llc_lookup_established(sap, daddr, laddr);
+       local_bh_enable();
+       return sk;
+}
+
 /**
  *     llc_lookup_listener - Finds listener for local MAC + SAP
  *     @sap: SAP
@@ -506,6 +529,7 @@ found:
  *     Search connection list of the SAP and finds connection listening on
  *     local mac, and local sap. Returns pointer for parent socket found,
  *     %NULL otherwise.
+ *     Caller has to make sure local_bh is disabled.
  */
 static struct sock *llc_lookup_listener(struct llc_sap *sap,
                                        struct llc_addr *laddr)
@@ -513,7 +537,7 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap,
        struct sock *rc;
        struct hlist_node *node;
 
-       read_lock_bh(&sap->sk_list.lock);
+       read_lock(&sap->sk_list.lock);
        sk_for_each(rc, node, &sap->sk_list.list) {
                struct llc_sock *llc = llc_sk(rc);
 
@@ -527,10 +551,19 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap,
        }
        rc = NULL;
 found:
-       read_unlock_bh(&sap->sk_list.lock);
+       read_unlock(&sap->sk_list.lock);
        return rc;
 }
 
+static struct sock *__llc_lookup(struct llc_sap *sap,
+                                struct llc_addr *daddr,
+                                struct llc_addr *laddr)
+{
+       struct sock *sk = __llc_lookup_established(sap, daddr, laddr);
+
+       return sk ? : llc_lookup_listener(sap, laddr);
+}
+
 /**
  *     llc_data_accept_state - designates if in this state data can be sent.
  *     @state: state of connection.
@@ -544,14 +577,14 @@ u8 llc_data_accept_state(u8 state)
 }
 
 /**
- *     find_next_offset - finds offset for next category of transitions
+ *     llc_find_next_offset - finds offset for next category of transitions
  *     @state: state table.
  *     @offset: start offset.
  *
  *     Finds offset of next category of transitions in transition table.
  *     Returns the start index of next category.
  */
-static u16 find_next_offset(struct llc_conn_state *state, u16 offset)
+static u16 __init llc_find_next_offset(struct llc_conn_state *state, u16 offset)
 {
        u16 cnt = 0;
        struct llc_conn_state_trans **next_trans;
@@ -578,8 +611,8 @@ void __init llc_build_offset_table(void)
                next_offset = 0;
                for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) {
                        llc_offset_table[state][ev_type] = next_offset;
-                       next_offset += find_next_offset(curr_state,
-                                                       next_offset) + 1;
+                       next_offset += llc_find_next_offset(curr_state,
+                                                           next_offset) + 1;
                }
        }
 }
@@ -623,6 +656,7 @@ static int llc_find_offset(int state, int ev_type)
  */
 void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk)
 {
+       llc_sap_hold(sap);
        write_lock_bh(&sap->sk_list.lock);
        llc_sk(sk)->sap = sap;
        sk_add_node(sk, &sap->sk_list.list);
@@ -642,6 +676,7 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
        write_lock_bh(&sap->sk_list.lock);
        sk_del_node_init(sk);
        write_unlock_bh(&sap->sk_list.lock);
+       llc_sap_put(sap);
 }
 
 /**
@@ -654,15 +689,34 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
 static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
 {
        struct llc_conn_state_ev *ev = llc_conn_ev(skb);
-       struct llc_sock *llc = llc_sk(sk);
 
-       if (!llc->dev)
-               llc->dev = skb->dev;
        ev->type   = LLC_CONN_EV_TYPE_PDU;
        ev->reason = 0;
        return llc_conn_state_process(sk, skb);
 }
 
+static struct sock *llc_create_incoming_sock(struct sock *sk,
+                                            struct net_device *dev,
+                                            struct llc_addr *saddr,
+                                            struct llc_addr *daddr)
+{
+       struct sock *newsk = llc_sk_alloc(sk->sk_family, GFP_ATOMIC,
+                                         sk->sk_prot);
+       struct llc_sock *newllc, *llc = llc_sk(sk);
+
+       if (!newsk)
+               goto out;
+       newllc = llc_sk(newsk);
+       memcpy(&newllc->laddr, daddr, sizeof(newllc->laddr));
+       memcpy(&newllc->daddr, saddr, sizeof(newllc->daddr));
+       newllc->dev = dev;
+       dev_hold(dev);
+       llc_sap_add_socket(llc->sap, newsk);
+       llc_sap_hold(llc->sap);
+out:
+       return newsk;
+}
+
 void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
 {
        struct llc_addr saddr, daddr;
@@ -673,35 +727,35 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
        llc_pdu_decode_da(skb, daddr.mac);
        llc_pdu_decode_dsap(skb, &daddr.lsap);
 
-       sk = llc_lookup_established(sap, &saddr, &daddr);
-       if (!sk) {
+       sk = __llc_lookup(sap, &saddr, &daddr);
+       if (!sk)
+               goto drop;
+
+       bh_lock_sock(sk);
+       /*
+        * This has to be done here and not at the upper layer ->accept
+        * method because of the way the PROCOM state machine works:
+        * it needs to set several state variables (see, for instance,
+        * llc_adm_actions_2 in net/llc/llc_c_st.c) and send a packet to
+        * the originator of the new connection, and this state has to be
+        * in the newly created struct sock private area. -acme
+        */
+       if (unlikely(sk->sk_state == TCP_LISTEN)) {
+               struct sock *newsk = llc_create_incoming_sock(sk, skb->dev,
+                                                             &saddr, &daddr);
+               if (!newsk)
+                       goto drop_unlock;
+               skb_set_owner_r(skb, newsk);
+       } else {
                /*
-                * Didn't find an active connection; verify if there
-                * is a listening socket for this llc addr
+                * Can't be skb_set_owner_r, this will be done at the
+                * llc_conn_state_process function, later on, when we will use
+                * skb_queue_rcv_skb to send it to upper layers, this is
+                * another trick required to cope with how the PROCOM state
+                * machine works. -acme
                 */
-               struct llc_sock *llc;
-               struct sock *parent = llc_lookup_listener(sap, &daddr);
-
-               if (!parent) {
-                       dprintk("llc_lookup_listener failed!\n");
-                       goto drop;
-               }
-
-               sk = llc_sk_alloc(parent->sk_family, GFP_ATOMIC, parent->sk_prot);
-               if (!sk) {
-                       sock_put(parent);
-                       goto drop;
-               }
-               llc = llc_sk(sk);
-               memcpy(&llc->laddr, &daddr, sizeof(llc->laddr));
-               memcpy(&llc->daddr, &saddr, sizeof(llc->daddr));
-               llc_sap_add_socket(sap, sk);
-               sock_hold(sk);
-               sock_put(parent);
-               skb->sk = parent;
-       } else
                skb->sk = sk;
-       bh_lock_sock(sk);
+       }
        if (!sock_owned_by_user(sk))
                llc_conn_rcv(sk, skb);
        else {
@@ -709,11 +763,16 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
                llc_set_backlog_type(skb, LLC_PACKET);
                sk_add_backlog(sk, skb);
        }
+out:
        bh_unlock_sock(sk);
        sock_put(sk);
        return;
 drop:
        kfree_skb(skb);
+       return;
+drop_unlock:
+       kfree_skb(skb);
+       goto out;
 }
 
 #undef LLC_REFCNT_DEBUG
@@ -721,32 +780,6 @@ drop:
 static atomic_t llc_sock_nr;
 #endif
 
-/**
- *     llc_release_sockets - releases all sockets in a sap
- *     @sap: sap to release its sockets
- *
- *     Releases all connections of a sap. Returns 0 if all actions complete
- *     successfully, nonzero otherwise
- */
-int llc_release_sockets(struct llc_sap *sap)
-{
-       int rc = 0;
-       struct sock *sk;
-       struct hlist_node *node;
-
-       write_lock_bh(&sap->sk_list.lock);
-
-       sk_for_each(sk, node, &sap->sk_list.list) {
-               llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
-
-               if (llc_send_disc(sk))
-                       rc = 1;
-       }
-
-       write_unlock_bh(&sap->sk_list.lock);
-       return rc;
-}
-
 /**
  *     llc_backlog_rcv - Processes rx frames and expired timers.
  *     @sk: LLC sock (p8022 connection)
@@ -762,14 +795,14 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
        int rc = 0;
        struct llc_sock *llc = llc_sk(sk);
 
-       if (llc_backlog_type(skb) == LLC_PACKET) {
-               if (llc->state > 1) /* not closed */
+       if (likely(llc_backlog_type(skb) == LLC_PACKET)) {
+               if (likely(llc->state > 1)) /* not closed */
                        rc = llc_conn_rcv(sk, skb);
                else
                        goto out_kfree_skb;
        } else if (llc_backlog_type(skb) == LLC_EVENT) {
                /* timer expiration event */
-               if (llc->state > 1)  /* not closed */
+               if (likely(llc->state > 1))  /* not closed */
                        rc = llc_conn_state_process(sk, skb);
                else
                        goto out_kfree_skb;
@@ -799,22 +832,22 @@ static void llc_sk_init(struct sock* sk)
        llc->dec_step = llc->connect_step = 1;
 
        init_timer(&llc->ack_timer.timer);
-       llc->ack_timer.expire         = LLC_ACK_TIME;
+       llc->ack_timer.expire         = sysctl_llc2_ack_timeout;
        llc->ack_timer.timer.data     = (unsigned long)sk;
        llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
 
        init_timer(&llc->pf_cycle_timer.timer);
-       llc->pf_cycle_timer.expire         = LLC_P_TIME;
+       llc->pf_cycle_timer.expire         = sysctl_llc2_p_timeout;
        llc->pf_cycle_timer.timer.data     = (unsigned long)sk;
        llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
 
        init_timer(&llc->rej_sent_timer.timer);
-       llc->rej_sent_timer.expire         = LLC_REJ_TIME;
+       llc->rej_sent_timer.expire         = sysctl_llc2_rej_timeout;
        llc->rej_sent_timer.timer.data     = (unsigned long)sk;
        llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
 
        init_timer(&llc->busy_state_timer.timer);
-       llc->busy_state_timer.expire         = LLC_BUSY_TIME;
+       llc->busy_state_timer.expire         = sysctl_llc2_busy_timeout;
        llc->busy_state_timer.timer.data     = (unsigned long)sk;
        llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
 
@@ -834,7 +867,8 @@ static void llc_sk_init(struct sock* sk)
  *     Allocates a LLC sock and initializes it. Returns the new LLC sock
  *     or %NULL if there's no memory available for one
  */
-struct sock *llc_sk_alloc(int family, int priority, struct proto *prot)
+struct sock *llc_sk_alloc(int family, unsigned int __nocast priority,
+                        struct proto *prot)
 {
        struct sock *sk = sk_alloc(family, priority, prot, 1);
 
index 9727455bf0e7907d4285c42e2744bb1e4d52aed9..ab0fcd32fd8447bf69b5ee10848dc0afa88c53df 100644 (file)
@@ -40,6 +40,7 @@ static struct llc_sap *llc_sap_alloc(void)
                sap->state = LLC_SAP_STATE_ACTIVE;
                memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);
                rwlock_init(&sap->sk_list.lock);
+               atomic_set(&sap->refcnt, 1);
        }
        return sap;
 }
@@ -52,9 +53,7 @@ static struct llc_sap *llc_sap_alloc(void)
  */
 static void llc_add_sap(struct llc_sap *sap)
 {
-       write_lock_bh(&llc_sap_list_lock);
        list_add_tail(&sap->node, &llc_sap_list);
-       write_unlock_bh(&llc_sap_list_lock);
 }
 
 /**
@@ -70,11 +69,25 @@ static void llc_del_sap(struct llc_sap *sap)
        write_unlock_bh(&llc_sap_list_lock);
 }
 
+static struct llc_sap *__llc_sap_find(unsigned char sap_value)
+{
+       struct llc_sap* sap;
+
+       list_for_each_entry(sap, &llc_sap_list, node)
+               if (sap->laddr.lsap == sap_value)
+                       goto out;
+       sap = NULL;
+out:
+       return sap;
+}
+
 /**
  *     llc_sap_find - searchs a SAP in station
  *     @sap_value: sap to be found
  *
  *     Searchs for a sap in the sap list of the LLC's station upon the sap ID.
+ *     If the sap is found it will be refcounted and the user will have to do
+ *     a llc_sap_put after use.
  *     Returns the sap or %NULL if not found.
  */
 struct llc_sap *llc_sap_find(unsigned char sap_value)
@@ -82,11 +95,9 @@ struct llc_sap *llc_sap_find(unsigned char sap_value)
        struct llc_sap* sap;
 
        read_lock_bh(&llc_sap_list_lock);
-       list_for_each_entry(sap, &llc_sap_list, node)
-               if (sap->laddr.lsap == sap_value)
-                       goto out;
-       sap = NULL;
-out:
+       sap = __llc_sap_find(sap_value);
+       if (sap)
+               llc_sap_hold(sap);
        read_unlock_bh(&llc_sap_list_lock);
        return sap;
 }
@@ -106,19 +117,20 @@ struct llc_sap *llc_sap_open(unsigned char lsap,
                                         struct packet_type *pt,
                                         struct net_device *orig_dev))
 {
-       struct llc_sap *sap = llc_sap_find(lsap);
+       struct llc_sap *sap = NULL;
 
-       if (sap) { /* SAP already exists */
-               sap = NULL;
+       write_lock_bh(&llc_sap_list_lock);
+       if (__llc_sap_find(lsap)) /* SAP already exists */
                goto out;
-       }
        sap = llc_sap_alloc();
        if (!sap)
                goto out;
        sap->laddr.lsap = lsap;
        sap->rcv_func   = func;
+       llc_sap_hold(sap);
        llc_add_sap(sap);
 out:
+       write_unlock_bh(&llc_sap_list_lock);
        return sap;
 }
 
index 0f84f66018e4ca2f63c09ee7b0a8ecdbfb429c19..ba90f7f0801ad5fbe9006a3da96234a71b6b7042 100644 (file)
@@ -47,14 +47,11 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
        int rc = -ECONNABORTED;
        struct llc_sock *llc = llc_sk(sk);
 
-       if (llc->state == LLC_CONN_STATE_ADM)
+       if (unlikely(llc->state == LLC_CONN_STATE_ADM))
                goto out;
        rc = -EBUSY;
-       if (llc_data_accept_state(llc->state)) { /* data_conn_refuse */
-               llc->failed_data_req = 1;
-               goto out;
-       }
-       if (llc->p_flag) {
+       if (unlikely(llc_data_accept_state(llc->state) || /* data_conn_refuse */
+                    llc->p_flag)) {
                llc->failed_data_req = 1;
                goto out;
        }
@@ -110,6 +107,7 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
                ev->type      = LLC_CONN_EV_TYPE_PRIM;
                ev->prim      = LLC_CONN_PRIM;
                ev->prim_type = LLC_PRIM_TYPE_REQ;
+               skb_set_owner_w(skb, sk);
                rc = llc_conn_state_process(sk, skb);
        }
 out_put:
@@ -144,6 +142,7 @@ int llc_send_disc(struct sock *sk)
        skb = alloc_skb(0, GFP_ATOMIC);
        if (!skb)
                goto out;
+       skb_set_owner_w(skb, sk);
        sk->sk_state  = TCP_CLOSING;
        ev            = llc_conn_ev(skb);
        ev->type      = LLC_CONN_EV_TYPE_PRIM;
index 13b46240b7a108148657aa736a03a52b7e540b41..8f3addf0724c01658c8c46b96677f701c52197f8 100644 (file)
@@ -99,15 +99,19 @@ out:
 static inline int llc_fixup_skb(struct sk_buff *skb)
 {
        u8 llc_len = 2;
-       struct llc_pdu_sn *pdu;
+       struct llc_pdu_un *pdu;
 
-       if (!pskb_may_pull(skb, sizeof(*pdu)))
+       if (unlikely(!pskb_may_pull(skb, sizeof(*pdu))))
                return 0;
 
-       pdu = (struct llc_pdu_sn *)skb->data;
+       pdu = (struct llc_pdu_un *)skb->data;
        if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
                llc_len = 1;
        llc_len += 2;
+
+       if (unlikely(!pskb_may_pull(skb, llc_len)))
+               return 0;
+
        skb->h.raw += llc_len;
        skb_pull(skb, llc_len);
        if (skb->protocol == htons(ETH_P_802_2)) {
@@ -166,17 +170,22 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
         */
        if (sap->rcv_func) {
                sap->rcv_func(skb, dev, pt, orig_dev);
-               goto out;
+               goto out_put;
        }
        dest = llc_pdu_type(skb);
        if (unlikely(!dest || !llc_type_handlers[dest - 1]))
-               goto drop;
+               goto drop_put;
        llc_type_handlers[dest - 1](sap, skb);
+out_put:
+       llc_sap_put(sap);
 out:
        return 0;
 drop:
        kfree_skb(skb);
        goto out;
+drop_put:
+       kfree_skb(skb);
+       goto out_put;
 handle_station:
        if (!llc_station_handler)
                goto drop;
index ab5784cf163e738754e161f54ac8c5fb85a3477a..b4d55b6abb679f33c39fa54c0d3f370a3909c448 100644 (file)
@@ -98,7 +98,7 @@ int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
                            dsap, LLC_PDU_CMD);
        llc_pdu_init_as_ui_cmd(skb);
        rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac);
-       if (!rc)
+       if (likely(!rc))
                rc = dev_queue_xmit(skb);
        return rc;
 }
index 36e8db3fa1a2af6bc95cae50b2e2948fea178aed..bd531cb235a70c6ea22de33b935307ca04aeea24 100644 (file)
@@ -134,7 +134,7 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v)
        llc_ui_format_mac(seq, llc->daddr.mac);
        seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap,
                   atomic_read(&sk->sk_wmem_alloc),
-                  atomic_read(&sk->sk_rmem_alloc),
+                  atomic_read(&sk->sk_rmem_alloc) - llc->copied_seq,
                   sk->sk_state,
                   sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1,
                   llc->link);
index ed8ba7de6122301e78800c6c4524815c16a5b782..bb3580fb8cfe9410e21cd432996cc06fbcc413de 100644 (file)
@@ -58,7 +58,7 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
                            ev->daddr.lsap, LLC_PDU_CMD);
        llc_pdu_init_as_ui_cmd(skb);
        rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
-       if (!rc)
+       if (likely(!rc))
                rc = dev_queue_xmit(skb);
        return rc;
 }
@@ -81,7 +81,7 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
                            ev->daddr.lsap, LLC_PDU_CMD);
        llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
        rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
-       if (!rc)
+       if (likely(!rc))
                rc = dev_queue_xmit(skb);
        return rc;
 }
@@ -103,15 +103,14 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb)
        llc_pdu_decode_sa(skb, mac_da);
        llc_pdu_decode_da(skb, mac_sa);
        llc_pdu_decode_ssap(skb, &dsap);
-       nskb = llc_alloc_frame();
+       nskb = llc_alloc_frame(NULL, skb->dev);
        if (!nskb)
                goto out;
-       nskb->dev = skb->dev;
        llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
                            LLC_PDU_RSP);
        llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0);
        rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
-       if (!rc)
+       if (likely(!rc))
                rc = dev_queue_xmit(nskb);
 out:
        return rc;
@@ -135,7 +134,7 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
                            ev->daddr.lsap, LLC_PDU_CMD);
        llc_pdu_init_as_test_cmd(skb);
        rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
-       if (!rc)
+       if (likely(!rc))
                rc = dev_queue_xmit(skb);
        return rc;
 }
@@ -149,15 +148,14 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb)
        llc_pdu_decode_sa(skb, mac_da);
        llc_pdu_decode_da(skb, mac_sa);
        llc_pdu_decode_ssap(skb, &dsap);
-       nskb = llc_alloc_frame();
+       nskb = llc_alloc_frame(NULL, skb->dev);
        if (!nskb)
                goto out;
-       nskb->dev = skb->dev;
        llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
                            LLC_PDU_RSP);
        llc_pdu_init_as_test_rsp(nskb, skb);
        rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
-       if (!rc)
+       if (likely(!rc))
                rc = dev_queue_xmit(nskb);
 out:
        return rc;
index 34228ef149854175c7ecc65a6bc7d008c05421b5..4029ceee9b9168d2f7b09e1eb1d64316f8544234 100644 (file)
 
 /**
  *     llc_alloc_frame - allocates sk_buff for frame
+ *     @dev: network device this skb will be sent over
  *
  *     Allocates an sk_buff for frame and initializes sk_buff fields.
  *     Returns allocated skb or %NULL when out of memory.
  */
-struct sk_buff *llc_alloc_frame(void)
+struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev)
 {
        struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
 
@@ -38,18 +39,23 @@ struct sk_buff *llc_alloc_frame(void)
                skb_reserve(skb, 50);
                skb->nh.raw   = skb->h.raw = skb->data;
                skb->protocol = htons(ETH_P_802_2);
-               skb->dev      = dev_base->next;
+               skb->dev      = dev;
                skb->mac.raw  = skb->head;
+               if (sk != NULL)
+                       skb_set_owner_w(skb, sk);
        }
        return skb;
 }
 
-void llc_save_primitive(struct sk_buff* skb, u8 prim)
+void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim)
 {
-       struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
+       struct sockaddr_llc *addr;
 
+       if (skb->sk->sk_type == SOCK_STREAM) /* See UNIX98 */
+               return;
        /* save primitive for use by the user. */
-       addr->sllc_family = skb->sk->sk_family;
+       addr              = llc_ui_skb_cb(skb);
+       addr->sllc_family = sk->sk_family;
        addr->sllc_arphrd = skb->dev->type;
        addr->sllc_test   = prim == LLC_TEST_PRIM;
        addr->sllc_xid    = prim == LLC_XID_PRIM;
@@ -189,7 +195,7 @@ static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
                if (skb->sk->sk_state == TCP_LISTEN)
                        kfree_skb(skb);
                else {
-                       llc_save_primitive(skb, ev->prim);
+                       llc_save_primitive(skb->sk, skb, ev->prim);
 
                        /* queue skb to the user. */
                        if (sock_queue_rcv_skb(skb->sk, skb))
@@ -308,7 +314,7 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
 
        sk = llc_lookup_dgram(sap, &laddr);
        if (sk) {
-               skb->sk = sk;
+               skb_set_owner_r(skb, sk);
                llc_sap_rcv(sap, skb);
                sock_put(sk);
        } else
index 8fe48a24bad5f1606826f57e5e018432fa00881a..f37dbf8ef126a1cdc8464d98f1320660f664a9f6 100644 (file)
@@ -50,6 +50,10 @@ struct llc_station {
        struct sk_buff_head         mac_pdu_q;
 };
 
+#define LLC_STATION_ACK_TIME (3 * HZ)
+
+int sysctl_llc_station_ack_timeout = LLC_STATION_ACK_TIME;
+
 /* Types of events (possible values in 'ev->type') */
 #define LLC_STATION_EV_TYPE_SIMPLE     1
 #define LLC_STATION_EV_TYPE_CONDITION  2
@@ -218,7 +222,8 @@ static void llc_station_send_pdu(struct sk_buff *skb)
 
 static int llc_station_ac_start_ack_timer(struct sk_buff *skb)
 {
-       mod_timer(&llc_main_station.ack_timer, jiffies + LLC_ACK_TIME * HZ);
+       mod_timer(&llc_main_station.ack_timer,
+                 jiffies + sysctl_llc_station_ack_timeout);
        return 0;
 }
 
@@ -249,14 +254,14 @@ static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb)
 static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb)
 {
        int rc = 1;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev);
 
        if (!nskb)
                goto out;
        llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD);
        llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127);
        rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, llc_station_mac_sa);
-       if (rc)
+       if (unlikely(rc))
                goto free;
        llc_station_send_pdu(nskb);
 out:
@@ -270,18 +275,17 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb)
 {
        u8 mac_da[ETH_ALEN], dsap;
        int rc = 1;
-       struct sk_buff* nskb = llc_alloc_frame();
+       struct sk_buff* nskb = llc_alloc_frame(NULL, skb->dev);
 
        if (!nskb)
                goto out;
        rc = 0;
-       nskb->dev = skb->dev;
        llc_pdu_decode_sa(skb, mac_da);
        llc_pdu_decode_ssap(skb, &dsap);
        llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
        llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127);
        rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da);
-       if (rc)
+       if (unlikely(rc))
                goto free;
        llc_station_send_pdu(nskb);
 out:
@@ -295,18 +299,17 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb)
 {
        u8 mac_da[ETH_ALEN], dsap;
        int rc = 1;
-       struct sk_buff *nskb = llc_alloc_frame();
+       struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev);
 
        if (!nskb)
                goto out;
        rc = 0;
-       nskb->dev = skb->dev;
        llc_pdu_decode_sa(skb, mac_da);
        llc_pdu_decode_ssap(skb, &dsap);
        llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
                llc_pdu_init_as_test_rsp(nskb, skb);
        rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da);
-       if (rc)
+       if (unlikely(rc))
                goto free;
        llc_station_send_pdu(nskb);
 out:
@@ -689,7 +692,8 @@ int __init llc_station_init(void)
        init_timer(&llc_main_station.ack_timer);
        llc_main_station.ack_timer.data     = (unsigned long)&llc_main_station;
        llc_main_station.ack_timer.function = llc_station_ack_tmr_cb;
-
+       llc_main_station.ack_timer.expires  = jiffies +
+                                               sysctl_llc_station_ack_timeout;
        skb = alloc_skb(0, GFP_ATOMIC);
        if (!skb)
                goto out;
@@ -697,7 +701,6 @@ int __init llc_station_init(void)
        llc_set_station_handler(llc_station_rcv);
        ev = llc_station_ev(skb);
        memset(ev, 0, sizeof(*ev));
-       llc_main_station.ack_timer.expires = jiffies + 3 * HZ;
        llc_main_station.maximum_retry  = 1;
        llc_main_station.state          = LLC_STATION_STATE_DOWN;
        ev->type        = LLC_STATION_EV_TYPE_SIMPLE;
diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c
new file mode 100644 (file)
index 0000000..d1eaddb
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * sysctl_net_llc.c: sysctl interface to LLC net subsystem.
+ * 
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <net/llc.h>
+
+#ifndef CONFIG_SYSCTL
+#error This file should not be compiled without CONFIG_SYSCTL defined
+#endif
+
+static struct ctl_table llc2_timeout_table[] = {
+       {
+               .ctl_name       = NET_LLC2_ACK_TIMEOUT,
+               .procname       = "ack",
+               .data           = &sysctl_llc2_ack_timeout,
+               .maxlen         = sizeof(long),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+       {
+               .ctl_name       = NET_LLC2_BUSY_TIMEOUT,
+               .procname       = "busy",
+               .data           = &sysctl_llc2_busy_timeout,
+               .maxlen         = sizeof(long),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+       {
+               .ctl_name       = NET_LLC2_P_TIMEOUT,
+               .procname       = "p",
+               .data           = &sysctl_llc2_p_timeout,
+               .maxlen         = sizeof(long),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+       {
+               .ctl_name       = NET_LLC2_REJ_TIMEOUT,
+               .procname       = "rej",
+               .data           = &sysctl_llc2_rej_timeout,
+               .maxlen         = sizeof(long),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+       { 0 },
+};
+
+static struct ctl_table llc_station_table[] = {
+       {
+               .ctl_name       = NET_LLC_STATION_ACK_TIMEOUT,
+               .procname       = "ack_timeout",
+               .data           = &sysctl_llc_station_ack_timeout,
+               .maxlen         = sizeof(long),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
+       },
+       { 0 },
+};
+
+static struct ctl_table llc2_dir_timeout_table[] = {
+       {
+               .ctl_name       = NET_LLC2,
+               .procname       = "timeout",
+               .mode           = 0555,
+               .child          = llc2_timeout_table,
+               },
+       { 0 },
+};
+
+static struct ctl_table llc_table[] = {
+       {
+               .ctl_name       = NET_LLC2,
+               .procname       = "llc2",
+               .mode           = 0555,
+               .child          = llc2_dir_timeout_table,
+               },
+       {
+               .ctl_name       = NET_LLC_STATION,
+               .procname       = "station",
+               .mode           = 0555,
+               .child          = llc_station_table,
+       },
+       { 0 },
+};
+
+static struct ctl_table llc_dir_table[] = {
+       {
+               .ctl_name       = NET_LLC,
+               .procname       = "llc",
+               .mode           = 0555,
+               .child          = llc_table,
+               },
+       { 0 },
+};
+
+static struct ctl_table llc_root_table[] = {
+       {
+               .ctl_name       = CTL_NET,
+               .procname       = "net",
+               .mode           = 0555,
+               .child          = llc_dir_table,
+       },
+       { 0 },
+};
+
+static struct ctl_table_header *llc_table_header;
+
+int __init llc_sysctl_init(void)
+{
+       llc_table_header = register_sysctl_table(llc_root_table, 1);
+
+       return llc_table_header ? 0 : -ENOMEM;
+}
+
+void llc_sysctl_exit(void)
+{
+       if (llc_table_header) {
+               unregister_sysctl_table(llc_table_header);
+               llc_table_header = NULL;
+       }
+}
index ee865d88183bb930d4d05faf01e584263a80f51f..6a67a87384cc2d3c95270d425e868bfcf53fdb1f 100644 (file)
@@ -761,12 +761,6 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
        if (dev->hard_header) {
                int res;
                err = -EINVAL;
-               if (saddr) {
-                       if (saddr->sll_halen != dev->addr_len)
-                               goto out_free;
-                       if (saddr->sll_hatype != dev->type)
-                               goto out_free;
-               }
                res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len);
                if (sock->type != SOCK_DGRAM) {
                        skb->tail = skb->data;
index 5acb1680524ab5a3ae381b2a741fabd0219f8bc1..829fdbc4400be21af83e3846fd913cd746fdca3b 100644 (file)
@@ -1472,22 +1472,25 @@ static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62
 static int __init rose_proto_init(void)
 {
        int i;
-       int rc = proto_register(&rose_proto, 0);
+       int rc;
 
+       if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) {
+               printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       rc = proto_register(&rose_proto, 0);
        if (rc != 0)
                goto out;
 
        rose_callsign = null_ax25_address;
 
-       if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) {
-               printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n");
-               return -1;
-       }
-
        dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL);
        if (dev_rose == NULL) {
                printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n");
-               return -1;
+               rc = -ENOMEM;
+               goto out_proto_unregister;
        }
 
        memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device*));
@@ -1500,10 +1503,12 @@ static int __init rose_proto_init(void)
                                   name, rose_setup);
                if (!dev) {
                        printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n");
+                       rc = -ENOMEM;
                        goto fail;
                }
-               if (register_netdev(dev)) {
-                       printk(KERN_ERR "ROSE: netdevice regeistration failed\n");
+               rc = register_netdev(dev);
+               if (rc) {
+                       printk(KERN_ERR "ROSE: netdevice registration failed\n");
                        free_netdev(dev);
                        goto fail;
                }
@@ -1536,8 +1541,9 @@ fail:
                free_netdev(dev_rose[i]);
        }
        kfree(dev_rose);
+out_proto_unregister:
        proto_unregister(&rose_proto);
-       return -ENOMEM;
+       goto out;
 }
 module_init(rose_proto_init);
 
index f9264472377f563976060325a76cab8ec96da7ce..3145103cdf5471b1d688b0593e04237cadc5dd2e 100644 (file)
@@ -1145,8 +1145,11 @@ static int __sock_create(int family, int type, int protocol, struct socket **res
        if (!try_module_get(net_families[family]->owner))
                goto out_release;
 
-       if ((err = net_families[family]->create(sock, protocol)) < 0)
+       if ((err = net_families[family]->create(sock, protocol)) < 0) {
+               sock->ops = NULL;
                goto out_module_put;
+       }
+
        /*
         * Now to bump the refcnt of the [loadable] module that owns this
         * socket at sock_release time we decrement its refcnt.
@@ -1360,16 +1363,16 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
        newsock->type = sock->type;
        newsock->ops = sock->ops;
 
-       err = security_socket_accept(sock, newsock);
-       if (err)
-               goto out_release;
-
        /*
         * We don't need try_module_get here, as the listening socket (sock)
         * has the protocol module (sock->ops->owner) held.
         */
        __module_get(newsock->ops->owner);
 
+       err = security_socket_accept(sock, newsock);
+       if (err)
+               goto out_release;
+
        err = sock->ops->accept(sock, newsock, sock->file->f_flags);
        if (err < 0)
                goto out_release;
@@ -1700,7 +1703,9 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
        struct socket *sock;
        char address[MAX_SOCK_ADDR];
        struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
-       unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */
+       unsigned char ctl[sizeof(struct cmsghdr) + 20]
+                       __attribute__ ((aligned (sizeof(__kernel_size_t))));
+                       /* 20 is size of ipv6_pktinfo */
        unsigned char *ctl_buf = ctl;
        struct msghdr msg_sys;
        int err, ctl_len, iov_size, total_len;
index d8ee38aede26fee4cb8b78d8bd99467267c80da6..f2ee673329a7d509e945825820a8f2e75bcfefef 100644 (file)
@@ -295,11 +295,13 @@ static int do_pcmcia_entry(const char *filename,
 {
        unsigned int i;
 
+       id->match_flags = TO_NATIVE(id->match_flags);
        id->manf_id = TO_NATIVE(id->manf_id);
        id->card_id = TO_NATIVE(id->card_id);
        id->func_id = TO_NATIVE(id->func_id);
        id->function = TO_NATIVE(id->function);
        id->device_no = TO_NATIVE(id->device_no);
+
        for (i=0; i<4; i++) {
                id->prod_id_hash[i] = TO_NATIVE(id->prod_id_hash[i]);
        }
index 46c8602661c999de31787f8eadd662759418a2e2..db99ed434f3a7afd65624a689f94a2d59686f92e 100644 (file)
@@ -71,26 +71,26 @@ extern void keyring_publish_name(struct key *keyring);
 
 extern int __key_link(struct key *keyring, struct key *key);
 
-extern struct key *__keyring_search_one(struct key *keyring,
-                                       const struct key_type *type,
-                                       const char *description,
-                                       key_perm_t perm);
+extern key_ref_t __keyring_search_one(key_ref_t keyring_ref,
+                                     const struct key_type *type,
+                                     const char *description,
+                                     key_perm_t perm);
 
 extern struct key *keyring_search_instkey(struct key *keyring,
                                          key_serial_t target_id);
 
 typedef int (*key_match_func_t)(const struct key *, const void *);
 
-extern struct key *keyring_search_aux(struct key *keyring,
-                                     struct task_struct *tsk,
-                                     struct key_type *type,
-                                     const void *description,
-                                     key_match_func_t match);
+extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
+                                   struct task_struct *tsk,
+                                   struct key_type *type,
+                                   const void *description,
+                                   key_match_func_t match);
 
-extern struct key *search_process_keyrings(struct key_type *type,
-                                          const void *description,
-                                          key_match_func_t match,
-                                          struct task_struct *tsk);
+extern key_ref_t search_process_keyrings(struct key_type *type,
+                                        const void *description,
+                                        key_match_func_t match,
+                                        struct task_struct *tsk);
 
 extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
 
index fb89f9844465587caa5f3333eabf1a877e0e0848..2182be9e93093d87596ea965c301812de88484ba 100644 (file)
@@ -693,14 +693,15 @@ void key_type_put(struct key_type *ktype)
  * - the key has an incremented refcount
  * - we need to put the key if we get an error
  */
-static inline struct key *__key_update(struct key *key, const void *payload,
-                                      size_t plen)
+static inline key_ref_t __key_update(key_ref_t key_ref,
+                                    const void *payload, size_t plen)
 {
+       struct key *key = key_ref_to_ptr(key_ref);
        int ret;
 
        /* need write permission on the key to update it */
        ret = -EACCES;
-       if (!key_permission(key, KEY_WRITE))
+       if (!key_permission(key_ref, KEY_WRITE))
                goto error;
 
        ret = -EEXIST;
@@ -719,12 +720,12 @@ static inline struct key *__key_update(struct key *key, const void *payload,
 
        if (ret < 0)
                goto error;
- out:
-       return key;
+out:
+       return key_ref;
 
- error:
+error:
        key_put(key);
-       key = ERR_PTR(ret);
+       key_ref = ERR_PTR(ret);
        goto out;
 
 } /* end __key_update() */
@@ -734,52 +735,56 @@ static inline struct key *__key_update(struct key *key, const void *payload,
  * search the specified keyring for a key of the same description; if one is
  * found, update it, otherwise add a new one
  */
-struct key *key_create_or_update(struct key *keyring,
-                                const char *type,
-                                const char *description,
-                                const void *payload,
-                                size_t plen,
-                                int not_in_quota)
+key_ref_t key_create_or_update(key_ref_t keyring_ref,
+                              const char *type,
+                              const char *description,
+                              const void *payload,
+                              size_t plen,
+                              int not_in_quota)
 {
        struct key_type *ktype;
-       struct key *key = NULL;
+       struct key *keyring, *key = NULL;
        key_perm_t perm;
+       key_ref_t key_ref;
        int ret;
 
-       key_check(keyring);
-
        /* look up the key type to see if it's one of the registered kernel
         * types */
        ktype = key_type_lookup(type);
        if (IS_ERR(ktype)) {
-               key = ERR_PTR(-ENODEV);
+               key_ref = ERR_PTR(-ENODEV);
                goto error;
        }
 
-       ret = -EINVAL;
+       key_ref = ERR_PTR(-EINVAL);
        if (!ktype->match || !ktype->instantiate)
                goto error_2;
 
+       keyring = key_ref_to_ptr(keyring_ref);
+
+       key_check(keyring);
+
+       down_write(&keyring->sem);
+
+       /* if we're going to allocate a new key, we're going to have
+        * to modify the keyring */
+       key_ref = ERR_PTR(-EACCES);
+       if (!key_permission(keyring_ref, KEY_WRITE))
+               goto error_3;
+
        /* search for an existing key of the same type and description in the
         * destination keyring
         */
-       down_write(&keyring->sem);
-
-       key = __keyring_search_one(keyring, ktype, description, 0);
-       if (!IS_ERR(key))
+       key_ref = __keyring_search_one(keyring_ref, ktype, description, 0);
+       if (!IS_ERR(key_ref))
                goto found_matching_key;
 
-       /* if we're going to allocate a new key, we're going to have to modify
-        * the keyring */
-       ret = -EACCES;
-       if (!key_permission(keyring, KEY_WRITE))
-               goto error_3;
-
        /* decide on the permissions we want */
-       perm = KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK;
+       perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK;
+       perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK;
 
        if (ktype->read)
-               perm |= KEY_USR_READ;
+               perm |= KEY_POS_READ | KEY_USR_READ;
 
        if (ktype == &key_type_keyring || ktype->update)
                perm |= KEY_USR_WRITE;
@@ -788,7 +793,7 @@ struct key *key_create_or_update(struct key *keyring,
        key = key_alloc(ktype, description, current->fsuid, current->fsgid,
                        perm, not_in_quota);
        if (IS_ERR(key)) {
-               ret = PTR_ERR(key);
+               key_ref = ERR_PTR(PTR_ERR(key));
                goto error_3;
        }
 
@@ -796,15 +801,18 @@ struct key *key_create_or_update(struct key *keyring,
        ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL);
        if (ret < 0) {
                key_put(key);
-               key = ERR_PTR(ret);
+               key_ref = ERR_PTR(ret);
+               goto error_3;
        }
 
+       key_ref = make_key_ref(key, is_key_possessed(keyring_ref));
+
  error_3:
        up_write(&keyring->sem);
  error_2:
        key_type_put(ktype);
  error:
-       return key;
+       return key_ref;
 
  found_matching_key:
        /* we found a matching key, so we're going to try to update it
@@ -813,7 +821,7 @@ struct key *key_create_or_update(struct key *keyring,
        up_write(&keyring->sem);
        key_type_put(ktype);
 
-       key = __key_update(key, payload, plen);
+       key_ref = __key_update(key_ref, payload, plen);
        goto error;
 
 } /* end key_create_or_update() */
@@ -824,15 +832,16 @@ EXPORT_SYMBOL(key_create_or_update);
 /*
  * update a key
  */
-int key_update(struct key *key, const void *payload, size_t plen)
+int key_update(key_ref_t key_ref, const void *payload, size_t plen)
 {
+       struct key *key = key_ref_to_ptr(key_ref);
        int ret;
 
        key_check(key);
 
        /* the key must be writable */
        ret = -EACCES;
-       if (!key_permission(key, KEY_WRITE))
+       if (!key_permission(key_ref, KEY_WRITE))
                goto error;
 
        /* attempt to update it if supported */
index a6516a64b297898923ca760e2e3b779880021c30..4c670ee6acf94ac0d936e6051346b27ff646d499 100644 (file)
@@ -34,7 +34,7 @@ asmlinkage long sys_add_key(const char __user *_type,
                            size_t plen,
                            key_serial_t ringid)
 {
-       struct key *keyring, *key;
+       key_ref_t keyring_ref, key_ref;
        char type[32], *description;
        void *payload;
        long dlen, ret;
@@ -86,25 +86,25 @@ asmlinkage long sys_add_key(const char __user *_type,
        }
 
        /* find the target keyring (which must be writable) */
-       keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
-       if (IS_ERR(keyring)) {
-               ret = PTR_ERR(keyring);
+       keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
+       if (IS_ERR(keyring_ref)) {
+               ret = PTR_ERR(keyring_ref);
                goto error3;
        }
 
        /* create or update the requested key and add it to the target
         * keyring */
-       key = key_create_or_update(keyring, type, description,
-                                  payload, plen, 0);
-       if (!IS_ERR(key)) {
-               ret = key->serial;
-               key_put(key);
+       key_ref = key_create_or_update(keyring_ref, type, description,
+                                      payload, plen, 0);
+       if (!IS_ERR(key_ref)) {
+               ret = key_ref_to_ptr(key_ref)->serial;
+               key_ref_put(key_ref);
        }
        else {
-               ret = PTR_ERR(key);
+               ret = PTR_ERR(key_ref);
        }
 
-       key_put(keyring);
+       key_ref_put(keyring_ref);
  error3:
        kfree(payload);
  error2:
@@ -131,7 +131,8 @@ asmlinkage long sys_request_key(const char __user *_type,
                                key_serial_t destringid)
 {
        struct key_type *ktype;
-       struct key *key, *dest;
+       struct key *key;
+       key_ref_t dest_ref;
        char type[32], *description, *callout_info;
        long dlen, ret;
 
@@ -187,11 +188,11 @@ asmlinkage long sys_request_key(const char __user *_type,
        }
 
        /* get the destination keyring if specified */
-       dest = NULL;
+       dest_ref = NULL;
        if (destringid) {
-               dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
-               if (IS_ERR(dest)) {
-                       ret = PTR_ERR(dest);
+               dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
+               if (IS_ERR(dest_ref)) {
+                       ret = PTR_ERR(dest_ref);
                        goto error3;
                }
        }
@@ -204,7 +205,8 @@ asmlinkage long sys_request_key(const char __user *_type,
        }
 
        /* do the search */
-       key = request_key_and_link(ktype, description, callout_info, dest);
+       key = request_key_and_link(ktype, description, callout_info,
+                                  key_ref_to_ptr(dest_ref));
        if (IS_ERR(key)) {
                ret = PTR_ERR(key);
                goto error5;
@@ -216,7 +218,7 @@ asmlinkage long sys_request_key(const char __user *_type,
  error5:
        key_type_put(ktype);
  error4:
-       key_put(dest);
+       key_ref_put(dest_ref);
  error3:
        kfree(callout_info);
  error2:
@@ -234,17 +236,17 @@ asmlinkage long sys_request_key(const char __user *_type,
  */
 long keyctl_get_keyring_ID(key_serial_t id, int create)
 {
-       struct key *key;
+       key_ref_t key_ref;
        long ret;
 
-       key = lookup_user_key(NULL, id, create, 0, KEY_SEARCH);
-       if (IS_ERR(key)) {
-               ret = PTR_ERR(key);
+       key_ref = lookup_user_key(NULL, id, create, 0, KEY_SEARCH);
+       if (IS_ERR(key_ref)) {
+               ret = PTR_ERR(key_ref);
                goto error;
        }
 
-       ret = key->serial;
-       key_put(key);
+       ret = key_ref_to_ptr(key_ref)->serial;
+       key_ref_put(key_ref);
  error:
        return ret;
 
@@ -302,7 +304,7 @@ long keyctl_update_key(key_serial_t id,
                       const void __user *_payload,
                       size_t plen)
 {
-       struct key *key;
+       key_ref_t key_ref;
        void *payload;
        long ret;
 
@@ -324,16 +326,16 @@ long keyctl_update_key(key_serial_t id,
        }
 
        /* find the target key (which must be writable) */
-       key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
-       if (IS_ERR(key)) {
-               ret = PTR_ERR(key);
+       key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
+       if (IS_ERR(key_ref)) {
+               ret = PTR_ERR(key_ref);
                goto error2;
        }
 
        /* update the key */
-       ret = key_update(key, payload, plen);
+       ret = key_update(key_ref, payload, plen);
 
-       key_put(key);
+       key_ref_put(key_ref);
  error2:
        kfree(payload);
  error:
@@ -349,19 +351,19 @@ long keyctl_update_key(key_serial_t id,
  */
 long keyctl_revoke_key(key_serial_t id)
 {
-       struct key *key;
+       key_ref_t key_ref;
        long ret;
 
-       key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
-       if (IS_ERR(key)) {
-               ret = PTR_ERR(key);
+       key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
+       if (IS_ERR(key_ref)) {
+               ret = PTR_ERR(key_ref);
                goto error;
        }
 
-       key_revoke(key);
+       key_revoke(key_ref_to_ptr(key_ref));
        ret = 0;
 
-       key_put(key);
+       key_ref_put(key_ref);
  error:
        return ret;
 
@@ -375,18 +377,18 @@ long keyctl_revoke_key(key_serial_t id)
  */
 long keyctl_keyring_clear(key_serial_t ringid)
 {
-       struct key *keyring;
+       key_ref_t keyring_ref;
        long ret;
 
-       keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
-       if (IS_ERR(keyring)) {
-               ret = PTR_ERR(keyring);
+       keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
+       if (IS_ERR(keyring_ref)) {
+               ret = PTR_ERR(keyring_ref);
                goto error;
        }
 
-       ret = keyring_clear(keyring);
+       ret = keyring_clear(key_ref_to_ptr(keyring_ref));
 
-       key_put(keyring);
+       key_ref_put(keyring_ref);
  error:
        return ret;
 
@@ -401,26 +403,26 @@ long keyctl_keyring_clear(key_serial_t ringid)
  */
 long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
 {
-       struct key *keyring, *key;
+       key_ref_t keyring_ref, key_ref;
        long ret;
 
-       keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
-       if (IS_ERR(keyring)) {
-               ret = PTR_ERR(keyring);
+       keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
+       if (IS_ERR(keyring_ref)) {
+               ret = PTR_ERR(keyring_ref);
                goto error;
        }
 
-       key = lookup_user_key(NULL, id, 1, 0, KEY_LINK);
-       if (IS_ERR(key)) {
-               ret = PTR_ERR(key);
+       key_ref = lookup_user_key(NULL, id, 1, 0, KEY_LINK);
+       if (IS_ERR(key_ref)) {
+               ret = PTR_ERR(key_ref);
                goto error2;
        }
 
-       ret = key_link(keyring, key);
+       ret = key_link(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref));
 
-       key_put(key);
+       key_ref_put(key_ref);
  error2:
-       key_put(keyring);
+       key_ref_put(keyring_ref);
  error:
        return ret;
 
@@ -435,26 +437,26 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
  */
 long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
 {
-       struct key *keyring, *key;
+       key_ref_t keyring_ref, key_ref;
        long ret;
 
-       keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE);
-       if (IS_ERR(keyring)) {
-               ret = PTR_ERR(keyring);
+       keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE);
+       if (IS_ERR(keyring_ref)) {
+               ret = PTR_ERR(keyring_ref);
                goto error;
        }
 
-       key = lookup_user_key(NULL, id, 0, 0, 0);
-       if (IS_ERR(key)) {
-               ret = PTR_ERR(key);
+       key_ref = lookup_user_key(NULL, id, 0, 0, 0);
+       if (IS_ERR(key_ref)) {
+               ret = PTR_ERR(key_ref);
                goto error2;
        }
 
-       ret = key_unlink(keyring, key);
+       ret = key_unlink(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref));
 
-       key_put(key);
+       key_ref_put(key_ref);
  error2:
-       key_put(keyring);
+       key_ref_put(keyring_ref);
  error:
        return ret;
 
@@ -476,24 +478,26 @@ long keyctl_describe_key(key_serial_t keyid,
                         size_t buflen)
 {
        struct key *key, *instkey;
+       key_ref_t key_ref;
        char *tmpbuf;
        long ret;
 
-       key = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
-       if (IS_ERR(key)) {
+       key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
+       if (IS_ERR(key_ref)) {
                /* viewing a key under construction is permitted if we have the
                 * authorisation token handy */
-               if (PTR_ERR(key) == -EACCES) {
+               if (PTR_ERR(key_ref) == -EACCES) {
                        instkey = key_get_instantiation_authkey(keyid);
                        if (!IS_ERR(instkey)) {
                                key_put(instkey);
-                               key = lookup_user_key(NULL, keyid, 0, 1, 0);
-                               if (!IS_ERR(key))
+                               key_ref = lookup_user_key(NULL, keyid,
+                                                         0, 1, 0);
+                               if (!IS_ERR(key_ref))
                                        goto okay;
                        }
                }
 
-               ret = PTR_ERR(key);
+               ret = PTR_ERR(key_ref);
                goto error;
        }
 
@@ -504,13 +508,16 @@ okay:
        if (!tmpbuf)
                goto error2;
 
+       key = key_ref_to_ptr(key_ref);
+
        ret = snprintf(tmpbuf, PAGE_SIZE - 1,
-                      "%s;%d;%d;%06x;%s",
-                      key->type->name,
-                      key->uid,
-                      key->gid,
-                      key->perm,
-                      key->description ? key->description :""
+                      "%s;%d;%d;%08x;%s",
+                      key_ref_to_ptr(key_ref)->type->name,
+                      key_ref_to_ptr(key_ref)->uid,
+                      key_ref_to_ptr(key_ref)->gid,
+                      key_ref_to_ptr(key_ref)->perm,
+                      key_ref_to_ptr(key_ref)->description ?
+                      key_ref_to_ptr(key_ref)->description : ""
                       );
 
        /* include a NUL char at the end of the data */
@@ -530,7 +537,7 @@ okay:
 
        kfree(tmpbuf);
  error2:
-       key_put(key);
+       key_ref_put(key_ref);
  error:
        return ret;
 
@@ -552,7 +559,7 @@ long keyctl_keyring_search(key_serial_t ringid,
                           key_serial_t destringid)
 {
        struct key_type *ktype;
-       struct key *keyring, *key, *dest;
+       key_ref_t keyring_ref, key_ref, dest_ref;
        char type[32], *description;
        long dlen, ret;
 
@@ -581,18 +588,18 @@ long keyctl_keyring_search(key_serial_t ringid,
                goto error2;
 
        /* get the keyring at which to begin the search */
-       keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
-       if (IS_ERR(keyring)) {
-               ret = PTR_ERR(keyring);
+       keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
+       if (IS_ERR(keyring_ref)) {
+               ret = PTR_ERR(keyring_ref);
                goto error2;
        }
 
        /* get the destination keyring if specified */
-       dest = NULL;
+       dest_ref = NULL;
        if (destringid) {
-               dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
-               if (IS_ERR(dest)) {
-                       ret = PTR_ERR(dest);
+               dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
+               if (IS_ERR(dest_ref)) {
+                       ret = PTR_ERR(dest_ref);
                        goto error3;
                }
        }
@@ -605,9 +612,9 @@ long keyctl_keyring_search(key_serial_t ringid,
        }
 
        /* do the search */
-       key = keyring_search(keyring, ktype, description);
-       if (IS_ERR(key)) {
-               ret = PTR_ERR(key);
+       key_ref = keyring_search(keyring_ref, ktype, description);
+       if (IS_ERR(key_ref)) {
+               ret = PTR_ERR(key_ref);
 
                /* treat lack or presence of a negative key the same */
                if (ret == -EAGAIN)
@@ -616,26 +623,26 @@ long keyctl_keyring_search(key_serial_t ringid,
        }
 
        /* link the resulting key to the destination keyring if we can */
-       if (dest) {
+       if (dest_ref) {
                ret = -EACCES;
-               if (!key_permission(key, KEY_LINK))
+               if (!key_permission(key_ref, KEY_LINK))
                        goto error6;
 
-               ret = key_link(dest, key);
+               ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref));
                if (ret < 0)
                        goto error6;
        }
 
-       ret = key->serial;
+       ret = key_ref_to_ptr(key_ref)->serial;
 
  error6:
-       key_put(key);
+       key_ref_put(key_ref);
  error5:
        key_type_put(ktype);
  error4:
-       key_put(dest);
+       key_ref_put(dest_ref);
  error3:
-       key_put(keyring);
+       key_ref_put(keyring_ref);
  error2:
        kfree(description);
  error:
@@ -643,16 +650,6 @@ long keyctl_keyring_search(key_serial_t ringid,
 
 } /* end keyctl_keyring_search() */
 
-/*****************************************************************************/
-/*
- * see if the key we're looking at is the target key
- */
-static int keyctl_read_key_same(const struct key *key, const void *target)
-{
-       return key == target;
-
-} /* end keyctl_read_key_same() */
-
 /*****************************************************************************/
 /*
  * read a user key's payload
@@ -665,38 +662,33 @@ static int keyctl_read_key_same(const struct key *key, const void *target)
  */
 long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
 {
-       struct key *key, *skey;
+       struct key *key;
+       key_ref_t key_ref;
        long ret;
 
        /* find the key first */
-       key = lookup_user_key(NULL, keyid, 0, 0, 0);
-       if (!IS_ERR(key)) {
-               /* see if we can read it directly */
-               if (key_permission(key, KEY_READ))
-                       goto can_read_key;
-
-               /* we can't; see if it's searchable from this process's
-                * keyrings
-                * - we automatically take account of the fact that it may be
-                *   dangling off an instantiation key
-                */
-               skey = search_process_keyrings(key->type, key,
-                                              keyctl_read_key_same, current);
-               if (!IS_ERR(skey))
-                       goto can_read_key2;
-
-               ret = PTR_ERR(skey);
-               if (ret == -EAGAIN)
-                       ret = -EACCES;
-               goto error2;
+       key_ref = lookup_user_key(NULL, keyid, 0, 0, 0);
+       if (IS_ERR(key_ref)) {
+               ret = -ENOKEY;
+               goto error;
        }
 
-       ret = -ENOKEY;
-       goto error;
+       key = key_ref_to_ptr(key_ref);
+
+       /* see if we can read it directly */
+       if (key_permission(key_ref, KEY_READ))
+               goto can_read_key;
+
+       /* we can't; see if it's searchable from this process's keyrings
+        * - we automatically take account of the fact that it may be
+        *   dangling off an instantiation key
+        */
+       if (!is_key_possessed(key_ref)) {
+               ret = -EACCES;
+               goto error2;
+       }
 
        /* the key is probably readable - now try to read it */
- can_read_key2:
-       key_put(skey);
  can_read_key:
        ret = key_validate(key);
        if (ret == 0) {
@@ -727,18 +719,21 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
 long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
 {
        struct key *key;
+       key_ref_t key_ref;
        long ret;
 
        ret = 0;
        if (uid == (uid_t) -1 && gid == (gid_t) -1)
                goto error;
 
-       key = lookup_user_key(NULL, id, 1, 1, 0);
-       if (IS_ERR(key)) {
-               ret = PTR_ERR(key);
+       key_ref = lookup_user_key(NULL, id, 1, 1, 0);
+       if (IS_ERR(key_ref)) {
+               ret = PTR_ERR(key_ref);
                goto error;
        }
 
+       key = key_ref_to_ptr(key_ref);
+
        /* make the changes with the locks held to prevent chown/chown races */
        ret = -EACCES;
        down_write(&key->sem);
@@ -784,18 +779,21 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
 long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
 {
        struct key *key;
+       key_ref_t key_ref;
        long ret;
 
        ret = -EINVAL;
-       if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
+       if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
                goto error;
 
-       key = lookup_user_key(NULL, id, 1, 1, 0);
-       if (IS_ERR(key)) {
-               ret = PTR_ERR(key);
+       key_ref = lookup_user_key(NULL, id, 1, 1, 0);
+       if (IS_ERR(key_ref)) {
+               ret = PTR_ERR(key_ref);
                goto error;
        }
 
+       key = key_ref_to_ptr(key_ref);
+
        /* make the changes with the locks held to prevent chown/chmod races */
        ret = -EACCES;
        down_write(&key->sem);
@@ -824,7 +822,8 @@ long keyctl_instantiate_key(key_serial_t id,
                            key_serial_t ringid)
 {
        struct request_key_auth *rka;
-       struct key *instkey, *keyring;
+       struct key *instkey;
+       key_ref_t keyring_ref;
        void *payload;
        long ret;
 
@@ -857,21 +856,21 @@ long keyctl_instantiate_key(key_serial_t id,
 
        /* find the destination keyring amongst those belonging to the
         * requesting task */
-       keyring = NULL;
+       keyring_ref = NULL;
        if (ringid) {
-               keyring = lookup_user_key(rka->context, ringid, 1, 0,
-                                         KEY_WRITE);
-               if (IS_ERR(keyring)) {
-                       ret = PTR_ERR(keyring);
+               keyring_ref = lookup_user_key(rka->context, ringid, 1, 0,
+                                             KEY_WRITE);
+               if (IS_ERR(keyring_ref)) {
+                       ret = PTR_ERR(keyring_ref);
                        goto error3;
                }
        }
 
        /* instantiate the key and link it into a keyring */
        ret = key_instantiate_and_link(rka->target_key, payload, plen,
-                                      keyring, instkey);
+                                      key_ref_to_ptr(keyring_ref), instkey);
 
-       key_put(keyring);
+       key_ref_put(keyring_ref);
  error3:
        key_put(instkey);
  error2:
@@ -889,7 +888,8 @@ long keyctl_instantiate_key(key_serial_t id,
 long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
 {
        struct request_key_auth *rka;
-       struct key *instkey, *keyring;
+       struct key *instkey;
+       key_ref_t keyring_ref;
        long ret;
 
        /* find the instantiation authorisation key */
@@ -903,19 +903,20 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
 
        /* find the destination keyring if present (which must also be
         * writable) */
-       keyring = NULL;
+       keyring_ref = NULL;
        if (ringid) {
-               keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
-               if (IS_ERR(keyring)) {
-                       ret = PTR_ERR(keyring);
+               keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
+               if (IS_ERR(keyring_ref)) {
+                       ret = PTR_ERR(keyring_ref);
                        goto error2;
                }
        }
 
        /* instantiate the key and link it into a keyring */
-       ret = key_negate_and_link(rka->target_key, timeout, keyring, instkey);
+       ret = key_negate_and_link(rka->target_key, timeout,
+                                 key_ref_to_ptr(keyring_ref), instkey);
 
-       key_put(keyring);
+       key_ref_put(keyring_ref);
  error2:
        key_put(instkey);
  error:
index 9c208c756df8136cbaa0a06f5442af60c712ae6d..0639396dd441eabdc27418b66df7673a749419e8 100644 (file)
@@ -309,7 +309,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
        int ret;
 
        keyring = key_alloc(&key_type_keyring, description,
-                           uid, gid, KEY_USR_ALL, not_in_quota);
+                           uid, gid, KEY_POS_ALL | KEY_USR_ALL, not_in_quota);
 
        if (!IS_ERR(keyring)) {
                ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
@@ -333,12 +333,13 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
  * - we rely on RCU to prevent the keyring lists from disappearing on us
  * - we return -EAGAIN if we didn't find any matching key
  * - we return -ENOKEY if we only found negative matching keys
+ * - we propagate the possession attribute from the keyring ref to the key ref
  */
-struct key *keyring_search_aux(struct key *keyring,
-                              struct task_struct *context,
-                              struct key_type *type,
-                              const void *description,
-                              key_match_func_t match)
+key_ref_t keyring_search_aux(key_ref_t keyring_ref,
+                            struct task_struct *context,
+                            struct key_type *type,
+                            const void *description,
+                            key_match_func_t match)
 {
        struct {
                struct keyring_list *keylist;
@@ -347,29 +348,33 @@ struct key *keyring_search_aux(struct key *keyring,
 
        struct keyring_list *keylist;
        struct timespec now;
-       struct key *key;
+       unsigned long possessed;
+       struct key *keyring, *key;
+       key_ref_t key_ref;
        long err;
        int sp, kix;
 
+       keyring = key_ref_to_ptr(keyring_ref);
+       possessed = is_key_possessed(keyring_ref);
        key_check(keyring);
 
-       rcu_read_lock();
-
        /* top keyring must have search permission to begin the search */
-       key = ERR_PTR(-EACCES);
-       if (!key_task_permission(keyring, context, KEY_SEARCH))
+       key_ref = ERR_PTR(-EACCES);
+       if (!key_task_permission(keyring_ref, context, KEY_SEARCH))
                goto error;
 
-       key = ERR_PTR(-ENOTDIR);
+       key_ref = ERR_PTR(-ENOTDIR);
        if (keyring->type != &key_type_keyring)
                goto error;
 
+       rcu_read_lock();
+
        now = current_kernel_time();
        err = -EAGAIN;
        sp = 0;
 
        /* start processing a new keyring */
- descend:
+descend:
        if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
                goto not_this_keyring;
 
@@ -397,7 +402,8 @@ struct key *keyring_search_aux(struct key *keyring,
                        continue;
 
                /* key must have search permissions */
-               if (!key_task_permission(key, context, KEY_SEARCH))
+               if (!key_task_permission(make_key_ref(key, possessed),
+                                        context, KEY_SEARCH))
                        continue;
 
                /* we set a different error code if we find a negative key */
@@ -411,7 +417,7 @@ struct key *keyring_search_aux(struct key *keyring,
 
        /* search through the keyrings nested in this one */
        kix = 0;
- ascend:
+ascend:
        for (; kix < keylist->nkeys; kix++) {
                key = keylist->keys[kix];
                if (key->type != &key_type_keyring)
@@ -423,7 +429,8 @@ struct key *keyring_search_aux(struct key *keyring,
                if (sp >= KEYRING_SEARCH_MAX_DEPTH)
                        continue;
 
-               if (!key_task_permission(key, context, KEY_SEARCH))
+               if (!key_task_permission(make_key_ref(key, possessed),
+                                        context, KEY_SEARCH))
                        continue;
 
                /* stack the current position */
@@ -438,7 +445,7 @@ struct key *keyring_search_aux(struct key *keyring,
 
        /* the keyring we're looking at was disqualified or didn't contain a
         * matching key */
- not_this_keyring:
+not_this_keyring:
        if (sp > 0) {
                /* resume the processing of a keyring higher up in the tree */
                sp--;
@@ -447,16 +454,18 @@ struct key *keyring_search_aux(struct key *keyring,
                goto ascend;
        }
 
-       key = ERR_PTR(err);
-       goto error;
+       key_ref = ERR_PTR(err);
+       goto error_2;
 
        /* we found a viable match */
- found:
+found:
        atomic_inc(&key->usage);
        key_check(key);
- error:
+       key_ref = make_key_ref(key, possessed);
+error_2:
        rcu_read_unlock();
-       return key;
+error:
+       return key_ref;
 
 } /* end keyring_search_aux() */
 
@@ -469,9 +478,9 @@ struct key *keyring_search_aux(struct key *keyring,
  * - we return -EAGAIN if we didn't find any matching key
  * - we return -ENOKEY if we only found negative matching keys
  */
-struct key *keyring_search(struct key *keyring,
-                          struct key_type *type,
-                          const char *description)
+key_ref_t keyring_search(key_ref_t keyring,
+                        struct key_type *type,
+                        const char *description)
 {
        if (!type->match)
                return ERR_PTR(-ENOKEY);
@@ -488,15 +497,19 @@ EXPORT_SYMBOL(keyring_search);
  * search the given keyring only (no recursion)
  * - keyring must be locked by caller
  */
-struct key *__keyring_search_one(struct key *keyring,
-                                const struct key_type *ktype,
-                                const char *description,
-                                key_perm_t perm)
+key_ref_t __keyring_search_one(key_ref_t keyring_ref,
+                              const struct key_type *ktype,
+                              const char *description,
+                              key_perm_t perm)
 {
        struct keyring_list *klist;
-       struct key *key;
+       unsigned long possessed;
+       struct key *keyring, *key;
        int loop;
 
+       keyring = key_ref_to_ptr(keyring_ref);
+       possessed = is_key_possessed(keyring_ref);
+
        rcu_read_lock();
 
        klist = rcu_dereference(keyring->payload.subscriptions);
@@ -507,21 +520,21 @@ struct key *__keyring_search_one(struct key *keyring,
                        if (key->type == ktype &&
                            (!key->type->match ||
                             key->type->match(key, description)) &&
-                           key_permission(key, perm) &&
+                           key_permission(make_key_ref(key, possessed),
+                                          perm) &&
                            !test_bit(KEY_FLAG_REVOKED, &key->flags)
                            )
                                goto found;
                }
        }
 
-       key = ERR_PTR(-ENOKEY);
-       goto error;
+       rcu_read_unlock();
+       return ERR_PTR(-ENOKEY);
 
  found:
        atomic_inc(&key->usage);
- error:
        rcu_read_unlock();
-       return key;
+       return make_key_ref(key, possessed);
 
 } /* end __keyring_search_one() */
 
@@ -603,7 +616,8 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound)
                        if (strcmp(keyring->description, name) != 0)
                                continue;
 
-                       if (!key_permission(keyring, KEY_SEARCH))
+                       if (!key_permission(make_key_ref(keyring, 0),
+                                           KEY_SEARCH))
                                continue;
 
                        /* found a potential candidate, but we still need to
index c55cf1fd08264769b162248f8107c41575578633..12b750e51fbf5c133ca4877b13a184081b73e652 100644 (file)
@@ -167,7 +167,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
 #define showflag(KEY, LETTER, FLAG) \
        (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-')
 
-       seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ",
+       seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ",
                   key->serial,
                   showflag(key, 'I', KEY_FLAG_INSTANTIATED),
                   showflag(key, 'R', KEY_FLAG_REVOKED),
index c089f78fb94ec170dbd042f08a4a61b9915c526e..d42d2158ce13beba31fb2753356e244a18e3a2a1 100644 (file)
@@ -39,7 +39,7 @@ struct key root_user_keyring = {
        .type           = &key_type_keyring,
        .user           = &root_key_user,
        .sem            = __RWSEM_INITIALIZER(root_user_keyring.sem),
-       .perm           = KEY_USR_ALL,
+       .perm           = KEY_POS_ALL | KEY_USR_ALL,
        .flags          = 1 << KEY_FLAG_INSTANTIATED,
        .description    = "_uid.0",
 #ifdef KEY_DEBUGGING
@@ -54,7 +54,7 @@ struct key root_session_keyring = {
        .type           = &key_type_keyring,
        .user           = &root_key_user,
        .sem            = __RWSEM_INITIALIZER(root_session_keyring.sem),
-       .perm           = KEY_USR_ALL,
+       .perm           = KEY_POS_ALL | KEY_USR_ALL,
        .flags          = 1 << KEY_FLAG_INSTANTIATED,
        .description    = "_uid_ses.0",
 #ifdef KEY_DEBUGGING
@@ -98,7 +98,7 @@ int alloc_uid_keyring(struct user_struct *user)
        user->session_keyring = session_keyring;
        ret = 0;
 
- error:
+error:
        return ret;
 
 } /* end alloc_uid_keyring() */
@@ -156,7 +156,7 @@ int install_thread_keyring(struct task_struct *tsk)
        ret = 0;
 
        key_put(old);
- error:
+error:
        return ret;
 
 } /* end install_thread_keyring() */
@@ -193,7 +193,7 @@ int install_process_keyring(struct task_struct *tsk)
        }
 
        ret = 0;
- error:
+error:
        return ret;
 
 } /* end install_process_keyring() */
@@ -236,7 +236,7 @@ static int install_session_keyring(struct task_struct *tsk,
        /* we're using RCU on the pointer */
        synchronize_rcu();
        key_put(old);
- error:
+error:
        return ret;
 
 } /* end install_session_keyring() */
@@ -376,13 +376,13 @@ void key_fsgid_changed(struct task_struct *tsk)
  * - we return -EAGAIN if we didn't find any matching key
  * - we return -ENOKEY if we found only negative matching keys
  */
-struct key *search_process_keyrings(struct key_type *type,
-                                   const void *description,
-                                   key_match_func_t match,
-                                   struct task_struct *context)
+key_ref_t search_process_keyrings(struct key_type *type,
+                                 const void *description,
+                                 key_match_func_t match,
+                                 struct task_struct *context)
 {
        struct request_key_auth *rka;
-       struct key *key, *ret, *err, *instkey;
+       key_ref_t key_ref, ret, err, instkey_ref;
 
        /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
         * searchable, but we failed to find a key or we found a negative key;
@@ -391,46 +391,48 @@ struct key *search_process_keyrings(struct key_type *type,
         *
         * in terms of priority: success > -ENOKEY > -EAGAIN > other error
         */
-       key = NULL;
+       key_ref = NULL;
        ret = NULL;
        err = ERR_PTR(-EAGAIN);
 
        /* search the thread keyring first */
        if (context->thread_keyring) {
-               key = keyring_search_aux(context->thread_keyring,
-                                        context, type, description, match);
-               if (!IS_ERR(key))
+               key_ref = keyring_search_aux(
+                       make_key_ref(context->thread_keyring, 1),
+                       context, type, description, match);
+               if (!IS_ERR(key_ref))
                        goto found;
 
-               switch (PTR_ERR(key)) {
+               switch (PTR_ERR(key_ref)) {
                case -EAGAIN: /* no key */
                        if (ret)
                                break;
                case -ENOKEY: /* negative key */
-                       ret = key;
+                       ret = key_ref;
                        break;
                default:
-                       err = key;
+                       err = key_ref;
                        break;
                }
        }
 
        /* search the process keyring second */
        if (context->signal->process_keyring) {
-               key = keyring_search_aux(context->signal->process_keyring,
-                                        context, type, description, match);
-               if (!IS_ERR(key))
+               key_ref = keyring_search_aux(
+                       make_key_ref(context->signal->process_keyring, 1),
+                       context, type, description, match);
+               if (!IS_ERR(key_ref))
                        goto found;
 
-               switch (PTR_ERR(key)) {
+               switch (PTR_ERR(key_ref)) {
                case -EAGAIN: /* no key */
                        if (ret)
                                break;
                case -ENOKEY: /* negative key */
-                       ret = key;
+                       ret = key_ref;
                        break;
                default:
-                       err = key;
+                       err = key_ref;
                        break;
                }
        }
@@ -438,23 +440,25 @@ struct key *search_process_keyrings(struct key_type *type,
        /* search the session keyring */
        if (context->signal->session_keyring) {
                rcu_read_lock();
-               key = keyring_search_aux(
-                       rcu_dereference(context->signal->session_keyring),
+               key_ref = keyring_search_aux(
+                       make_key_ref(rcu_dereference(
+                                            context->signal->session_keyring),
+                                    1),
                        context, type, description, match);
                rcu_read_unlock();
 
-               if (!IS_ERR(key))
+               if (!IS_ERR(key_ref))
                        goto found;
 
-               switch (PTR_ERR(key)) {
+               switch (PTR_ERR(key_ref)) {
                case -EAGAIN: /* no key */
                        if (ret)
                                break;
                case -ENOKEY: /* negative key */
-                       ret = key;
+                       ret = key_ref;
                        break;
                default:
-                       err = key;
+                       err = key_ref;
                        break;
                }
 
@@ -465,51 +469,54 @@ struct key *search_process_keyrings(struct key_type *type,
                        goto no_key;
 
                rcu_read_lock();
-               instkey = __keyring_search_one(
-                       rcu_dereference(context->signal->session_keyring),
+               instkey_ref = __keyring_search_one(
+                       make_key_ref(rcu_dereference(
+                                            context->signal->session_keyring),
+                                    1),
                        &key_type_request_key_auth, NULL, 0);
                rcu_read_unlock();
 
-               if (IS_ERR(instkey))
+               if (IS_ERR(instkey_ref))
                        goto no_key;
 
-               rka = instkey->payload.data;
+               rka = key_ref_to_ptr(instkey_ref)->payload.data;
 
-               key = search_process_keyrings(type, description, match,
-                                             rka->context);
-               key_put(instkey);
+               key_ref = search_process_keyrings(type, description, match,
+                                                 rka->context);
+               key_ref_put(instkey_ref);
 
-               if (!IS_ERR(key))
+               if (!IS_ERR(key_ref))
                        goto found;
 
-               switch (PTR_ERR(key)) {
+               switch (PTR_ERR(key_ref)) {
                case -EAGAIN: /* no key */
                        if (ret)
                                break;
                case -ENOKEY: /* negative key */
-                       ret = key;
+                       ret = key_ref;
                        break;
                default:
-                       err = key;
+                       err = key_ref;
                        break;
                }
        }
        /* or search the user-session keyring */
        else {
-               key = keyring_search_aux(context->user->session_keyring,
-                                        context, type, description, match);
-               if (!IS_ERR(key))
+               key_ref = keyring_search_aux(
+                       make_key_ref(context->user->session_keyring, 1),
+                       context, type, description, match);
+               if (!IS_ERR(key_ref))
                        goto found;
 
-               switch (PTR_ERR(key)) {
+               switch (PTR_ERR(key_ref)) {
                case -EAGAIN: /* no key */
                        if (ret)
                                break;
                case -ENOKEY: /* negative key */
-                       ret = key;
+                       ret = key_ref;
                        break;
                default:
-                       err = key;
+                       err = key_ref;
                        break;
                }
        }
@@ -517,29 +524,40 @@ struct key *search_process_keyrings(struct key_type *type,
 
 no_key:
        /* no key - decide on the error we're going to go for */
-       key = ret ? ret : err;
+       key_ref = ret ? ret : err;
 
 found:
-       return key;
+       return key_ref;
 
 } /* end search_process_keyrings() */
 
+/*****************************************************************************/
+/*
+ * see if the key we're looking at is the target key
+ */
+static int lookup_user_key_possessed(const struct key *key, const void *target)
+{
+       return key == target;
+
+} /* end lookup_user_key_possessed() */
+
 /*****************************************************************************/
 /*
  * lookup a key given a key ID from userspace with a given permissions mask
  * - don't create special keyrings unless so requested
  * - partially constructed keys aren't found unless requested
  */
-struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
-                           int create, int partial, key_perm_t perm)
+key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
+                         int create, int partial, key_perm_t perm)
 {
+       key_ref_t key_ref, skey_ref;
        struct key *key;
        int ret;
 
        if (!context)
                context = current;
 
-       key = ERR_PTR(-ENOKEY);
+       key_ref = ERR_PTR(-ENOKEY);
 
        switch (id) {
        case KEY_SPEC_THREAD_KEYRING:
@@ -556,6 +574,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
 
                key = context->thread_keyring;
                atomic_inc(&key->usage);
+               key_ref = make_key_ref(key, 1);
                break;
 
        case KEY_SPEC_PROCESS_KEYRING:
@@ -572,6 +591,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
 
                key = context->signal->process_keyring;
                atomic_inc(&key->usage);
+               key_ref = make_key_ref(key, 1);
                break;
 
        case KEY_SPEC_SESSION_KEYRING:
@@ -579,7 +599,7 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
                        /* always install a session keyring upon access if one
                         * doesn't exist yet */
                        ret = install_session_keyring(
-                              context, context->user->session_keyring);
+                               context, context->user->session_keyring);
                        if (ret < 0)
                                goto error;
                }
@@ -588,16 +608,19 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
                key = rcu_dereference(context->signal->session_keyring);
                atomic_inc(&key->usage);
                rcu_read_unlock();
+               key_ref = make_key_ref(key, 1);
                break;
 
        case KEY_SPEC_USER_KEYRING:
                key = context->user->uid_keyring;
                atomic_inc(&key->usage);
+               key_ref = make_key_ref(key, 1);
                break;
 
        case KEY_SPEC_USER_SESSION_KEYRING:
                key = context->user->session_keyring;
                atomic_inc(&key->usage);
+               key_ref = make_key_ref(key, 1);
                break;
 
        case KEY_SPEC_GROUP_KEYRING:
@@ -606,13 +629,28 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
                goto error;
 
        default:
-               key = ERR_PTR(-EINVAL);
+               key_ref = ERR_PTR(-EINVAL);
                if (id < 1)
                        goto error;
 
                key = key_lookup(id);
-               if (IS_ERR(key))
+               if (IS_ERR(key)) {
+                       key_ref = ERR_PTR(PTR_ERR(key));
                        goto error;
+               }
+
+               key_ref = make_key_ref(key, 0);
+
+               /* check to see if we possess the key */
+               skey_ref = search_process_keyrings(key->type, key,
+                                                  lookup_user_key_possessed,
+                                                  current);
+
+               if (!IS_ERR(skey_ref)) {
+                       key_put(key);
+                       key_ref = skey_ref;
+               }
+
                break;
        }
 
@@ -630,15 +668,15 @@ struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
        /* check the permissions */
        ret = -EACCES;
 
-       if (!key_task_permission(key, context, perm))
+       if (!key_task_permission(key_ref, context, perm))
                goto invalid_key;
 
- error:
-       return key;
+error:
+       return key_ref;
 
- invalid_key:
-       key_put(key);
-       key = ERR_PTR(ret);
+invalid_key:
+       key_ref_put(key_ref);
+       key_ref = ERR_PTR(ret);
        goto error;
 
 } /* end lookup_user_key() */
@@ -694,9 +732,9 @@ long join_session_keyring(const char *name)
        ret = keyring->serial;
        key_put(keyring);
 
- error2:
+error2:
        up(&key_session_sem);
- error:
+error:
        return ret;
 
 } /* end join_session_keyring() */
index 90c1506d007cc219c17ebd9c571d94b9c6a58ed9..e6dd366d43a35b0b70e6d1a40edec79a706a72d8 100644 (file)
@@ -129,7 +129,7 @@ static struct key *__request_key_construction(struct key_type *type,
 
        /* create a key and add it to the queue */
        key = key_alloc(type, description,
-                       current->fsuid, current->fsgid, KEY_USR_ALL, 0);
+                       current->fsuid, current->fsgid, KEY_POS_ALL, 0);
        if (IS_ERR(key))
                goto alloc_failed;
 
@@ -365,14 +365,24 @@ struct key *request_key_and_link(struct key_type *type,
 {
        struct key_user *user;
        struct key *key;
+       key_ref_t key_ref;
 
        kenter("%s,%s,%s,%p",
               type->name, description, callout_info, dest_keyring);
 
        /* search all the process keyrings for a key */
-       key = search_process_keyrings(type, description, type->match, current);
+       key_ref = search_process_keyrings(type, description, type->match,
+                                         current);
 
-       if (PTR_ERR(key) == -EAGAIN) {
+       kdebug("search 1: %p", key_ref);
+
+       if (!IS_ERR(key_ref)) {
+               key = key_ref_to_ptr(key_ref);
+       }
+       else if (PTR_ERR(key_ref) != -EAGAIN) {
+               key = ERR_PTR(PTR_ERR(key_ref));
+       }
+       else  {
                /* the search failed, but the keyrings were searchable, so we
                 * should consult userspace if we can */
                key = ERR_PTR(-ENOKEY);
@@ -384,7 +394,7 @@ struct key *request_key_and_link(struct key_type *type,
                if (!user)
                        goto nomem;
 
-               do {
+               for (;;) {
                        if (signal_pending(current))
                                goto interrupted;
 
@@ -397,10 +407,22 @@ struct key *request_key_and_link(struct key_type *type,
 
                        /* someone else made the key we want, so we need to
                         * search again as it might now be available to us */
-                       key = search_process_keyrings(type, description,
-                                                     type->match, current);
+                       key_ref = search_process_keyrings(type, description,
+                                                         type->match,
+                                                         current);
+
+                       kdebug("search 2: %p", key_ref);
 
-               } while (PTR_ERR(key) == -EAGAIN);
+                       if (!IS_ERR(key_ref)) {
+                               key = key_ref_to_ptr(key_ref);
+                               break;
+                       }
+
+                       if (PTR_ERR(key_ref) != -EAGAIN) {
+                               key = ERR_PTR(PTR_ERR(key_ref));
+                               break;
+                       }
+               }
 
                key_user_put(user);
 
index f22264632229ca79108a1e232461ecda378cc1e8..1ecd3d3fa9f895850a66e35c446b5ab506e85aab 100644 (file)
@@ -126,7 +126,7 @@ struct key *request_key_auth_new(struct key *target, struct key **_rkakey)
 
        rkakey = key_alloc(&key_type_request_key_auth, desc,
                           current->fsuid, current->fsgid,
-                          KEY_USR_VIEW, 1);
+                          KEY_POS_VIEW | KEY_USR_VIEW, 1);
        if (IS_ERR(rkakey)) {
                key_put(keyring);
                kleave("= %ld", PTR_ERR(rkakey));
index 6e4937fe062b40f2c4b3c05baaa9cc96f85c4cd8..b13be15165f57d527ea6e334bf1ca8fe9606b6b8 100644 (file)
@@ -630,6 +630,16 @@ static inline u16 inode_mode_to_security_class(umode_t mode)
        return SECCLASS_FILE;
 }
 
+static inline int default_protocol_stream(int protocol)
+{
+       return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
+}
+
+static inline int default_protocol_dgram(int protocol)
+{
+       return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
+}
+
 static inline u16 socket_type_to_security_class(int family, int type, int protocol)
 {
        switch (family) {
@@ -646,10 +656,16 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
        case PF_INET6:
                switch (type) {
                case SOCK_STREAM:
-                       return SECCLASS_TCP_SOCKET;
+                       if (default_protocol_stream(protocol))
+                               return SECCLASS_TCP_SOCKET;
+                       else
+                               return SECCLASS_RAWIP_SOCKET;
                case SOCK_DGRAM:
-                       return SECCLASS_UDP_SOCKET;
-               case SOCK_RAW:
+                       if (default_protocol_dgram(protocol))
+                               return SECCLASS_UDP_SOCKET;
+                       else
+                               return SECCLASS_RAWIP_SOCKET;
+               default:
                        return SECCLASS_RAWIP_SOCKET;
                }
                break;
@@ -2970,6 +2986,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 
        /*
         * If PF_INET or PF_INET6, check name_bind permission for the port.
+        * Multiple address binding for SCTP is not supported yet: we just
+        * check the first address now.
         */
        family = sock->sk->sk_family;
        if (family == PF_INET || family == PF_INET6) {
@@ -3014,12 +3032,12 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                                goto out;
                }
                
-               switch(sk->sk_protocol) {
-               case IPPROTO_TCP:
+               switch(isec->sclass) {
+               case SECCLASS_TCP_SOCKET:
                        node_perm = TCP_SOCKET__NODE_BIND;
                        break;
                        
-               case IPPROTO_UDP:
+               case SECCLASS_UDP_SOCKET:
                        node_perm = UDP_SOCKET__NODE_BIND;
                        break;